MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndbapi_simple.cpp
1 /*
2  Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /*
19  * ndbapi_simple.cpp: Using synchronous transactions in NDB API
20  *
21  * Correct output from this program is:
22  *
23  * ATTR1 ATTR2
24  * 0 10
25  * 1 1
26  * 2 12
27  * Detected that deleted tuple doesn't exist!
28  * 4 14
29  * 5 5
30  * 6 16
31  * 7 7
32  * 8 18
33  * 9 9
34  *
35  */
36 
37 #include <mysql.h>
38 #include <mysqld_error.h>
39 #include <NdbApi.hpp>
40 // Used for cout
41 #include <stdio.h>
42 #include <iostream>
43 
44 static void run_application(MYSQL &, Ndb_cluster_connection &);
45 
46 #define PRINT_ERROR(code,msg) \
47  std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
48  << ", code: " << code \
49  << ", msg: " << msg << "." << std::endl
50 #define MYSQLERROR(mysql) { \
51  PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
52  exit(-1); }
53 #define APIERROR(error) { \
54  PRINT_ERROR(error.code,error.message); \
55  exit(-1); }
56 
57 int main(int argc, char** argv)
58 {
59  if (argc != 3)
60  {
61  std::cout << "Arguments are <socket mysqld> <connect_string cluster>.\n";
62  exit(-1);
63  }
64  // ndb_init must be called first
65  ndb_init();
66 
67  // connect to mysql server and cluster and run application
68  {
69  char * mysqld_sock = argv[1];
70  const char *connectstring = argv[2];
71  // Object representing the cluster
72  Ndb_cluster_connection cluster_connection(connectstring);
73 
74  // Connect to cluster management server (ndb_mgmd)
75  if (cluster_connection.connect(4 /* retries */,
76  5 /* delay between retries */,
77  1 /* verbose */))
78  {
79  std::cout << "Cluster management server was not ready within 30 secs.\n";
80  exit(-1);
81  }
82 
83  // Optionally connect and wait for the storage nodes (ndbd's)
84  if (cluster_connection.wait_until_ready(30,0) < 0)
85  {
86  std::cout << "Cluster was not ready within 30 secs.\n";
87  exit(-1);
88  }
89 
90  // connect to mysql server
91  MYSQL mysql;
92  if ( !mysql_init(&mysql) ) {
93  std::cout << "mysql_init failed\n";
94  exit(-1);
95  }
96  if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
97  0, mysqld_sock, 0) )
98  MYSQLERROR(mysql);
99 
100  // run the application code
101  run_application(mysql, cluster_connection);
102  }
103 
104  ndb_end(0);
105 
106  return 0;
107 }
108 
109 static void create_table(MYSQL &);
110 static void do_insert(Ndb &);
111 static void do_update(Ndb &);
112 static void do_delete(Ndb &);
113 static void do_read(Ndb &);
114 
115 static void run_application(MYSQL &mysql,
116  Ndb_cluster_connection &cluster_connection)
117 {
118  /********************************************
119  * Connect to database via mysql-c *ndb_examples
120  ********************************************/
121  mysql_query(&mysql, "CREATE DATABASE ndb_examples");
122  if (mysql_query(&mysql, "USE ndb_examples") != 0) MYSQLERROR(mysql);
123  create_table(mysql);
124 
125  /********************************************
126  * Connect to database via NdbApi *
127  ********************************************/
128  // Object representing the database
129  Ndb myNdb( &cluster_connection, "ndb_examples" );
130  if (myNdb.init()) APIERROR(myNdb.getNdbError());
131 
132  /*
133  * Do different operations on database
134  */
135  do_insert(myNdb);
136  do_update(myNdb);
137  do_delete(myNdb);
138  do_read(myNdb);
139 }
140 
141 /*********************************************************
142  * Create a table named api_simple if it does not exist *
143  *********************************************************/
144 static void create_table(MYSQL &mysql)
145 {
146  while (mysql_query(&mysql,
147  "CREATE TABLE"
148  " api_simple"
149  " (ATTR1 INT UNSIGNED NOT NULL PRIMARY KEY,"
150  " ATTR2 INT UNSIGNED NOT NULL)"
151  " ENGINE=NDB"))
152  {
153  if (mysql_errno(&mysql) == ER_TABLE_EXISTS_ERROR)
154  {
155  std::cout << "MySQL Cluster already has example table: api_simple. "
156  << "Dropping it..." << std::endl;
157  mysql_query(&mysql, "DROP TABLE api_simple");
158  }
159  else MYSQLERROR(mysql);
160  }
161 }
162 
163 /**************************************************************************
164  * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
165  **************************************************************************/
166 static void do_insert(Ndb &myNdb)
167 {
168  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
169  const NdbDictionary::Table *myTable= myDict->getTable("api_simple");
170 
171  if (myTable == NULL)
172  APIERROR(myDict->getNdbError());
173 
174  for (int i = 0; i < 5; i++) {
175  NdbTransaction *myTransaction= myNdb.startTransaction();
176  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
177 
178  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
179  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
180 
181  myOperation->insertTuple();
182  myOperation->equal("ATTR1", i);
183  myOperation->setValue("ATTR2", i);
184 
185  myOperation= myTransaction->getNdbOperation(myTable);
186  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
187 
188  myOperation->insertTuple();
189  myOperation->equal("ATTR1", i+5);
190  myOperation->setValue("ATTR2", i+5);
191 
192  if (myTransaction->execute( NdbTransaction::Commit ) == -1)
193  APIERROR(myTransaction->getNdbError());
194 
195  myNdb.closeTransaction(myTransaction);
196  }
197 }
198 
199 /*****************************************************************
200  * Update the second attribute in half of the tuples (adding 10) *
201  *****************************************************************/
202 static void do_update(Ndb &myNdb)
203 {
204  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
205  const NdbDictionary::Table *myTable= myDict->getTable("api_simple");
206 
207  if (myTable == NULL)
208  APIERROR(myDict->getNdbError());
209 
210  for (int i = 0; i < 10; i+=2) {
211  NdbTransaction *myTransaction= myNdb.startTransaction();
212  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
213 
214  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
215  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
216 
217  myOperation->updateTuple();
218  myOperation->equal( "ATTR1", i );
219  myOperation->setValue( "ATTR2", i+10);
220 
221  if( myTransaction->execute( NdbTransaction::Commit ) == -1 )
222  APIERROR(myTransaction->getNdbError());
223 
224  myNdb.closeTransaction(myTransaction);
225  }
226 }
227 
228 /*************************************************
229  * Delete one tuple (the one with primary key 3) *
230  *************************************************/
231 static void do_delete(Ndb &myNdb)
232 {
233  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
234  const NdbDictionary::Table *myTable= myDict->getTable("api_simple");
235 
236  if (myTable == NULL)
237  APIERROR(myDict->getNdbError());
238 
239  NdbTransaction *myTransaction= myNdb.startTransaction();
240  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
241 
242  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
243  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
244 
245  myOperation->deleteTuple();
246  myOperation->equal( "ATTR1", 3 );
247 
248  if (myTransaction->execute(NdbTransaction::Commit) == -1)
249  APIERROR(myTransaction->getNdbError());
250 
251  myNdb.closeTransaction(myTransaction);
252 }
253 
254 /*****************************
255  * Read and print all tuples *
256  *****************************/
257 static void do_read(Ndb &myNdb)
258 {
259  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
260  const NdbDictionary::Table *myTable= myDict->getTable("api_simple");
261 
262  if (myTable == NULL)
263  APIERROR(myDict->getNdbError());
264 
265  std::cout << "ATTR1 ATTR2" << std::endl;
266 
267  for (int i = 0; i < 10; i++) {
268  NdbTransaction *myTransaction= myNdb.startTransaction();
269  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
270 
271  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
272  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
273 
274  myOperation->readTuple(NdbOperation::LM_Read);
275  myOperation->equal("ATTR1", i);
276 
277  NdbRecAttr *myRecAttr= myOperation->getValue("ATTR2", NULL);
278  if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
279 
280  if(myTransaction->execute( NdbTransaction::Commit ) == -1)
281  APIERROR(myTransaction->getNdbError());
282 
283  if (myTransaction->getNdbError().classification == NdbError::NoDataFound)
284  if (i == 3)
285  std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
286  else
287  APIERROR(myTransaction->getNdbError());
288 
289  if (i != 3) {
290  printf(" %2d %2d\n", i, myRecAttr->u_32_value());
291  }
292  myNdb.closeTransaction(myTransaction);
293  }
294 }