List:Commits« Previous MessageNext Message »
From:Monty Taylor Date:June 19 2008 7:54pm
Subject:bzr commit into NDB/Bindings:trunk branch (monty:412)
View as plain text  
#At https://bazaar.launchpad.net/~ndb-bindings/ndb-bindings/trunk

  412 Monty Taylor	2008-06-19
      Added ndbapi_scan example program.
added:
  cpp/ndbapi_scan.cpp
modified:
  .bzrignore
  cpp/Makefile.am

=== modified file '.bzrignore'
--- a/.bzrignore	2008-05-08 19:23:13 +0000
+++ b/.bzrignore	2008-06-19 17:54:46 +0000
@@ -301,3 +301,4 @@ mgmpp/.libs
 mgmpp/.deps
 perl/lib
 java/.settings
+cpp/ndbapi_scan

=== modified file 'cpp/Makefile.am'
--- a/cpp/Makefile.am	2008-04-29 02:06:37 +0000
+++ b/cpp/Makefile.am	2008-06-19 17:54:46 +0000
@@ -1,4 +1,5 @@
 bin_PROGRAMS =  ndbapi_simple_index \
+		ndbapi_scan \
                 testchars \
                 teststrins \
                 testdateins \
@@ -10,6 +11,7 @@ bin_PROGRAMS =  ndbapi_simple_index \
 LDADD = -lmysqlclient_r
 
 ndbapi_simple_index_SOURCES = ndbapi_simple_index.cpp
+ndbapi_scan_SOURCES = ndbapi_scan.cpp
 testchars_SOURCES = testchars.cpp
 teststrins_SOURCES = teststrins.cpp
 testdateins_SOURCES = testdateins.cpp

=== added file 'cpp/ndbapi_scan.cpp'
--- a/cpp/ndbapi_scan.cpp	1970-01-01 00:00:00 +0000
+++ b/cpp/ndbapi_scan.cpp	2008-06-19 17:54:46 +0000
@@ -0,0 +1,847 @@
+
+/* Copyright (C) 2003 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+
+/*
+ * ndbapi_scan.cpp: 
+ * Illustrates how to use the scan api in the NDBAPI.
+ * The example shows how to do scan, scan for update and scan for delete
+ * using NdbScanFilter and NdbScanOperation
+ *
+ * Classes and methods used in this example:
+ *
+ *  Ndb_cluster_connection
+ *       connect()
+ *       wait_until_ready()
+ *
+ *  Ndb
+ *       init()
+ *       getDictionary()
+ *       startTransaction()
+ *       closeTransaction()
+ *
+ *  NdbTransaction
+ *       getNdbScanOperation()
+ *       execute()
+ *
+ *  NdbScanOperation
+ *       getValue() 
+ *       readTuples()
+ *       nextResult()
+ *       deleteCurrentTuple()
+ *       updateCurrentTuple()
+ *
+ *  const NdbDictionary::Dictionary
+ *       getTable()
+ *
+ *  const NdbDictionary::Table
+ *       getColumn()
+ *
+ *  const NdbDictionary::Column
+ *       getLength()
+ *
+ *  NdbOperation
+ *       insertTuple()
+ *       equal()
+ *       setValue()
+ *
+ *  NdbScanFilter
+ *       begin()
+ *	 eq()
+ *	 end()
+ *
+ */
+
+
+#include <mysql.h>
+#include <mysqld_error.h>
+#include <NdbApi.hpp>
+// Used for cout
+#include <iostream>
+#include <stdio.h>
+
+/**
+ * Helper sleep function
+ */
+static void
+milliSleep(int milliseconds){
+  struct timeval sleeptime;
+  sleeptime.tv_sec = milliseconds / 1000;
+  sleeptime.tv_usec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
+  select(0, 0, 0, 0, &sleeptime);
+}
+
+
+/**
+ * Helper debugging macros
+ */
+#define PRINT_ERROR(code,msg) \
+  std::cout << "Error in " << __FILE__ << ", line: " << __LINE__
\
+            << ", code: " << code \
+            << ", msg: " << msg << "." << std::endl
+#define MYSQLERROR(mysql) { \
+  PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
+  exit(-1); }
+#define APIERROR(error) { \
+  PRINT_ERROR(error.code,error.message); \
+  exit(-1); }
+
+struct Car 
+{
+  /**
+   * Note memset, so that entire char-fields are cleared
+   *   as all 20 bytes are significant (as type is char)
+   */
+  Car() { memset(this, 0, sizeof(* this)); }
+  
+  unsigned int reg_no;
+  char brand[20];
+  char color[20];
+};
+
+/**
+ * Function to drop table
+ */
+void drop_table(MYSQL &mysql)
+{
+  if (mysql_query(&mysql, "DROP TABLE GARAGE"))
+    MYSQLERROR(mysql);
+}
+
+
+/**
+ * Function to create table
+ */
+void create_table(MYSQL &mysql) 
+{
+  while (mysql_query(&mysql, 
+		  "CREATE TABLE"
+		  "  GARAGE"
+		  "    (REG_NO INT UNSIGNED NOT NULL,"
+		  "     BRAND CHAR(20) NOT NULL,"
+		  "     COLOR CHAR(20) NOT NULL,"
+		  "     PRIMARY KEY USING HASH (REG_NO))"
+		  "  ENGINE=NDB"))
+  {
+    if (mysql_errno(&mysql) != ER_TABLE_EXISTS_ERROR)
+      MYSQLERROR(mysql);
+    std::cout << "MySQL Cluster already has example table: GARAGE. "
+	      << "Dropping it..." << std::endl; 
+    /******************
+     * Drop table *
+     ******************/
+    drop_table(mysql);
+  }
+}
+
+int populate(Ndb * myNdb)
+{
+  int i;
+  Car cars[15];
+
+  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+  const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+  if (myTable == NULL) 
+    APIERROR(myDict->getNdbError());
+
+  /**
+   * Five blue mercedes
+   */
+  for (i = 0; i < 5; i++)
+  {
+    cars[i].reg_no = i;
+    sprintf(cars[i].brand, "Mercedes");
+    sprintf(cars[i].color, "Blue");
+  }
+
+  /**
+   * Five black bmw
+   */
+  for (i = 5; i < 10; i++)
+  {
+    cars[i].reg_no = i;
+    sprintf(cars[i].brand, "BMW");
+    sprintf(cars[i].color, "Black");
+  }
+
+  /**
+   * Five pink toyotas
+   */
+  for (i = 10; i < 15; i++)
+  {
+    cars[i].reg_no = i;
+    sprintf(cars[i].brand, "Toyota");
+    sprintf(cars[i].color, "Pink");
+  }
+  
+  NdbTransaction* myTrans = myNdb->startTransaction();
+  if (myTrans == NULL)
+    APIERROR(myNdb->getNdbError());
+
+  for (i = 0; i < 15; i++) 
+  {
+    NdbOperation* myNdbOperation = myTrans->getNdbOperation(myTable);
+    if (myNdbOperation == NULL) 
+      APIERROR(myTrans->getNdbError());
+    myNdbOperation->insertTuple();
+    myNdbOperation->equal("REG_NO", cars[i].reg_no);
+    myNdbOperation->setValue("BRAND", cars[i].brand);
+    myNdbOperation->setValue("COLOR", cars[i].color);
+  }
+
+  int check = myTrans->execute(NdbTransaction::Commit);
+
+  myTrans->close();
+
+  return check != -1;
+}
+
+int scan_delete(Ndb* myNdb, 
+		const NdbDictionary::Column * column,
+		const char * color)
+  
+{
+  
+  // Scan all records exclusive and delete 
+  // them one by one
+  int                  retryAttempt = 0;
+  const int            retryMax = 10;
+  int deletedRows = 0;
+  int check;
+  NdbError              err;
+  NdbTransaction	*myTrans;
+  NdbScanOperation	*myScanOp;
+
+  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+  const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+  if (myTable == NULL) 
+    APIERROR(myDict->getNdbError());
+
+  /**
+   * Loop as long as :
+   *  retryMax not reached
+   *  failed operations due to TEMPORARY erros
+   *
+   * Exit loop;
+   *  retyrMax reached
+   *  Permanent error (return -1)
+   */
+  while (true)
+  {
+    if (retryAttempt >= retryMax)
+    {
+      std::cout << "ERROR: has retried this operation " << retryAttempt 
+		<< " times, failing!" << std::endl;
+      return -1;
+    }
+
+    myTrans = myNdb->startTransaction();
+    if (myTrans == NULL) 
+    {
+      const NdbError err = myNdb->getNdbError();
+
+      if (err.status == NdbError::TemporaryError)
+      {
+	milliSleep(50);
+	retryAttempt++;
+	continue;
+      }
+      std::cout <<  err.message << std::endl;
+      return -1;
+    }
+
+   /**
+    * Get a scan operation.
+    */
+    myScanOp = myTrans->getNdbScanOperation(myTable);	
+    if (myScanOp == NULL) 
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+
+    /**
+     * Define a result set for the scan.
+     */ 
+    if(myScanOp->readTuples(NdbOperation::LM_Exclusive) != 0)
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    } 
+    
+    /**
+     * Use NdbScanFilter to define a search critera
+     */ 
+    NdbScanFilter filter(myScanOp) ;   
+    if(filter.begin(NdbScanFilter::AND) < 0  || 
+       filter.cmp(NdbScanFilter::COND_EQ, column->getColumnNo(), 
+                  color, column->getLength()) < 0 ||
+       filter.end() < 0)
+    {
+      std::cout <<  myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }    
+    
+    /**
+     * Start scan    (NoCommit since we are only reading at this stage);
+     */     
+    if(myTrans->execute(NdbTransaction::NoCommit) != 0){      
+      err = myTrans->getNdbError();    
+      if(err.status == NdbError::TemporaryError){
+	std::cout << myTrans->getNdbError().message << std::endl;
+	myNdb->closeTransaction(myTrans);
+	milliSleep(50);
+	continue;
+      }
+      std::cout << err.code << std::endl;
+      std::cout << myTrans->getNdbError().code << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+
+
+   /**
+    * start of loop: nextResult(true) means that "parallelism" number of
+    * rows are fetched from NDB and cached in NDBAPI
+    */    
+    while((check = myScanOp->nextResult(true)) == 0){
+      do 
+      {
+	if (myScanOp->deleteCurrentTuple() != 0)
+	{
+	  std::cout << myTrans->getNdbError().message << std::endl;
+	  myNdb->closeTransaction(myTrans);
+	  return -1;
+	}
+	deletedRows++;
+	
+	/**
+	 * nextResult(false) means that the records 
+	 * cached in the NDBAPI are modified before
+	 * fetching more rows from NDB.
+	 */    
+      } while((check = myScanOp->nextResult(false)) == 0);
+      
+      /**
+       * Commit when all cached tuple have been marked for deletion
+       */    
+      if(check != -1)
+      {
+	check = myTrans->execute(NdbTransaction::Commit);   
+      }
+
+      if(check == -1)
+      {
+	/**
+	 * Create a new transaction, while keeping scan open
+	 */
+	check = myTrans->restart();
+      }
+
+      /**
+       * Check for errors
+       */
+      err = myTrans->getNdbError();    
+      if(check == -1)
+      {
+	if(err.status == NdbError::TemporaryError)
+	{
+	  std::cout << myTrans->getNdbError().message << std::endl;
+	  myNdb->closeTransaction(myTrans);
+	  milliSleep(50);
+	  continue;
+	}	
+      }
+      /**
+       * End of loop 
+       */
+    }
+    std::cout << myTrans->getNdbError().message << std::endl;
+    myNdb->closeTransaction(myTrans);
+    return 0;
+  }
+  
+  if(myTrans!=0) 
+  {
+    std::cout << myTrans->getNdbError().message << std::endl;
+    myNdb->closeTransaction(myTrans);
+  }
+  return -1;
+}
+
+
+int scan_update(Ndb* myNdb, 
+		const NdbDictionary::Column * update_column,
+		const char * before_color,
+		const char * after_color)
+		
+{
+  
+  // Scan all records exclusive and update
+  // them one by one
+  int                  retryAttempt = 0;
+  const int            retryMax = 10;
+  int updatedRows = 0;
+  int check;
+  NdbError              err;
+  NdbTransaction	*myTrans;
+  NdbScanOperation	*myScanOp;
+
+  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+  const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+  Uint32 update_column_id = update_column->getColumnNo();
+
+  if (myTable == NULL) 
+    APIERROR(myDict->getNdbError());
+
+  /**
+   * Loop as long as :
+   *  retryMax not reached
+   *  failed operations due to TEMPORARY erros
+   *
+   * Exit loop;
+   *  retyrMax reached
+   *  Permanent error (return -1)
+   */
+  while (true)
+  {
+
+    if (retryAttempt >= retryMax)
+    {
+      std::cout << "ERROR: has retried this operation " << retryAttempt 
+		<< " times, failing!" << std::endl;
+      return -1;
+    }
+
+    myTrans = myNdb->startTransaction();
+    if (myTrans == NULL) 
+    {
+      const NdbError err = myNdb->getNdbError();
+
+      if (err.status == NdbError::TemporaryError)
+      {
+	milliSleep(50);
+	retryAttempt++;
+	continue;
+      }
+      std::cout <<  err.message << std::endl;
+      return -1;
+    }
+
+   /**
+    * Get a scan operation.
+    */
+    myScanOp = myTrans->getNdbScanOperation(myTable);	
+    if (myScanOp == NULL) 
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+
+    /**
+     * Define a result set for the scan.
+     */ 
+    if( myScanOp->readTuples(NdbOperation::LM_Exclusive) ) 
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    } 
+
+    /**
+     * Use NdbScanFilter to define a search critera
+     */ 
+    NdbScanFilter filter(myScanOp) ;   
+    if(filter.begin(NdbScanFilter::AND) < 0  || 
+       filter.cmp(NdbScanFilter::COND_EQ, update_column_id, 
+                  before_color, update_column->getLength()) <0||
+       filter.end() <0)
+    {
+      std::cout <<  myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }    
+    
+    /**
+     * Start scan    (NoCommit since we are only reading at this stage);
+     */     
+    if(myTrans->execute(NdbTransaction::NoCommit) != 0)
+    {      
+      err = myTrans->getNdbError();    
+      if(err.status == NdbError::TemporaryError){
+	std::cout << myTrans->getNdbError().message << std::endl;
+	myNdb->closeTransaction(myTrans);
+	milliSleep(50);
+	continue;
+      }
+      std::cout << myTrans->getNdbError().code << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+
+    /**
+     * start of loop: nextResult(true) means that "parallelism" number of
+     * rows are fetched from NDB and cached in NDBAPI
+     */    
+    while((check = myScanOp->nextResult(true)) == 0){
+      do {
+	/**
+	 * Get update operation
+	 */    
+	NdbOperation * myUpdateOp = myScanOp->updateCurrentTuple();
+	if (myUpdateOp == 0)
+	{
+	  std::cout << myTrans->getNdbError().message << std::endl;
+	  myNdb->closeTransaction(myTrans);
+	  return -1;
+	}
+	updatedRows++;
+
+	/**
+	 * do the update
+	 */    
+	myUpdateOp->setValue(update_column_id, after_color);
+	/**
+	 * nextResult(false) means that the records 
+	 * cached in the NDBAPI are modified before
+	 * fetching more rows from NDB.
+	 */    
+      } while((check = myScanOp->nextResult(false)) == 0);
+      
+      /**
+       * NoCommit when all cached tuple have been updated
+       */    
+      if(check != -1)
+      {
+	check = myTrans->execute(NdbTransaction::NoCommit);   
+      }
+
+      /**
+       * Check for errors
+       */
+      err = myTrans->getNdbError();    
+      if(check == -1)
+      {
+	if(err.status == NdbError::TemporaryError){
+	  std::cout << myTrans->getNdbError().message << std::endl;
+	  myNdb->closeTransaction(myTrans);
+	  milliSleep(50);
+	  continue;
+	}	
+      }
+      /**
+       * End of loop 
+       */
+    }
+
+    /**
+     * Commit all prepared operations
+     */
+    if(myTrans->execute(NdbTransaction::Commit) == -1)
+    {
+      if(err.status == NdbError::TemporaryError){
+	std::cout << myTrans->getNdbError().message << std::endl;
+	myNdb->closeTransaction(myTrans);
+	milliSleep(50);
+	continue;
+      }	
+    }
+
+    std::cout << myTrans->getNdbError().message << std::endl;
+    myNdb->closeTransaction(myTrans);
+    return 0;    
+  }
+
+
+  if(myTrans!=0) 
+  {
+    std::cout << myTrans->getNdbError().message << std::endl;
+    myNdb->closeTransaction(myTrans);
+  }
+  return -1;
+}
+
+
+
+int scan_print(Ndb * myNdb)
+{
+// Scan all records exclusive and update
+  // them one by one
+  int                  retryAttempt = 0;
+  const int            retryMax = 10;
+  int fetchedRows = 0;
+  int check;
+  NdbError              err;
+  NdbTransaction	*myTrans;
+  NdbScanOperation	*myScanOp;
+  /* Result of reading attribute value, three columns:
+     REG_NO, BRAND, and COLOR
+   */
+  NdbRecAttr *    	myRecAttr[3];   
+
+  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+  const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+  if (myTable == NULL) 
+    APIERROR(myDict->getNdbError());
+
+  /**
+   * Loop as long as :
+   *  retryMax not reached
+   *  failed operations due to TEMPORARY erros
+   *
+   * Exit loop;
+   *  retyrMax reached
+   *  Permanent error (return -1)
+   */
+  while (true)
+  {
+
+    if (retryAttempt >= retryMax)
+    {
+      std::cout << "ERROR: has retried this operation " << retryAttempt 
+		<< " times, failing!" << std::endl;
+      return -1;
+    }
+
+    myTrans = myNdb->startTransaction();
+    if (myTrans == NULL) 
+    {
+      const NdbError err = myNdb->getNdbError();
+
+      if (err.status == NdbError::TemporaryError)
+      {
+	milliSleep(50);
+	retryAttempt++;
+	continue;
+      }
+     std::cout << err.message << std::endl;
+      return -1;
+    }
+    /*
+     * Define a scan operation. 
+     * NDBAPI.
+     */
+    myScanOp = myTrans->getNdbScanOperation(myTable);	
+    if (myScanOp == NULL) 
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+
+    /**
+     * Read without locks, without being placed in lock queue
+     */
+    if( myScanOp->readTuples(NdbOperation::LM_CommittedRead) == -1)
+    {
+      std::cout << myTrans->getNdbError().message << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    } 
+
+    /**
+     * Define storage for fetched attributes.
+     * E.g., the resulting attributes of executing
+     * myOp->getValue("REG_NO") is placed in myRecAttr[0].
+     * No data exists in myRecAttr until transaction has commited!
+     */
+    myRecAttr[0] = myScanOp->getValue("REG_NO");
+    myRecAttr[1] = myScanOp->getValue("BRAND");
+    myRecAttr[2] = myScanOp->getValue("COLOR");
+    if(myRecAttr[0] ==NULL || myRecAttr[1] == NULL || myRecAttr[2]==NULL) 
+    {
+	std::cout << myTrans->getNdbError().message << std::endl;
+	myNdb->closeTransaction(myTrans);
+	return -1;
+    }
+    /**
+     * Start scan   (NoCommit since we are only reading at this stage);
+     */     
+    if(myTrans->execute(NdbTransaction::NoCommit) != 0){      
+      err = myTrans->getNdbError();    
+      if(err.status == NdbError::TemporaryError){
+	std::cout << myTrans->getNdbError().message << std::endl;
+	myNdb->closeTransaction(myTrans);
+	milliSleep(50);
+	continue;
+      }
+      std::cout << err.code << std::endl;
+      std::cout << myTrans->getNdbError().code << std::endl;
+      myNdb->closeTransaction(myTrans);
+      return -1;
+    }
+    
+    /**
+     * start of loop: nextResult(true) means that "parallelism" number of
+     * rows are fetched from NDB and cached in NDBAPI
+     */    
+    while((check = myScanOp->nextResult(true)) == 0){
+      do {
+	
+	fetchedRows++;
+	/**
+	 * print  REG_NO unsigned int
+	 */
+	std::cout << myRecAttr[0]->u_32_value() << "\t";
+
+	/**
+	 * print  BRAND character string
+	 */
+	std::cout << myRecAttr[1]->aRef() << "\t";
+
+	/**
+	 * print  COLOR character string
+	 */
+	std::cout << myRecAttr[2]->aRef() << std::endl;
+
+	/**
+	 * nextResult(false) means that the records 
+	 * cached in the NDBAPI are modified before
+	 * fetching more rows from NDB.
+	 */    
+      } while((check = myScanOp->nextResult(false)) == 0);
+
+    }    
+    myNdb->closeTransaction(myTrans);
+    return 1;
+  }
+  return -1;
+
+}
+
+
+int main(int argc, char** argv)
+{
+  if (argc != 3)
+  {
+    std::cout << "Arguments are <socket mysqld> <connect_string
cluster>.\n";
+    exit(-1);
+  }
+  char * mysqld_sock  = argv[1];
+  const char *connectstring = argv[2];
+  ndb_init();
+  MYSQL mysql;
+
+  /**************************************************************
+   * Connect to mysql server and create table                   *
+   **************************************************************/
+  {
+    if ( !mysql_init(&mysql) ) {
+      std::cout << "mysql_init failed\n";
+      exit(-1);
+    }
+    if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
+			     0, mysqld_sock, 0) )
+      MYSQLERROR(mysql);
+
+    mysql_query(&mysql, "CREATE DATABASE TEST_DB");
+    if (mysql_query(&mysql, "USE TEST_DB") != 0) MYSQLERROR(mysql);
+
+    create_table(mysql);
+  }
+
+  /**************************************************************
+   * Connect to ndb cluster                                     *
+   **************************************************************/
+
+  Ndb_cluster_connection cluster_connection(connectstring);
+  if (cluster_connection.connect(4, 5, 1))
+  {
+    std::cout << "Unable to connect to cluster within 30 secs." << std::endl;
+    exit(-1);
+  }
+  // Optionally connect and wait for the storage nodes (ndbd's)
+  if (cluster_connection.wait_until_ready(30,0) < 0)
+  {
+    std::cout << "Cluster was not ready within 30 secs.\n";
+    exit(-1);
+  }
+
+  Ndb myNdb(&cluster_connection,"TEST_DB");
+  if (myNdb.init(1024) == -1) {      // Set max 1024  parallel transactions
+    APIERROR(myNdb.getNdbError());
+    exit(-1);
+  }
+
+  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+  const NdbDictionary::Table *t= myDict->getTable("GARAGE");
+  const NdbDictionary::Column * column_color = t->getColumn("COLOR");
+  const NdbDictionary::Column * column_brand = t->getColumn("BRAND");
+
+  /*******************************************
+   * Check table definition                  *
+   *******************************************/
+  {
+    Car car;
+    if (column_color->getLength() != sizeof(car.color) ||
+	column_brand->getLength() != sizeof(car.brand))
+    {
+      std::cout << "Wrong table definition" << std::endl;
+      exit(-1);
+    }
+  }
+
+  if(populate(&myNdb) > 0)
+    std::cout << "populate: Success!" << std::endl;
+  
+  if(scan_print(&myNdb) > 0)
+    std::cout << "scan_print: Success!" << std::endl  << std::endl;
+  
+  std::cout << "Going to delete all pink cars!" << std::endl;
+  
+  {
+    /**
+     * Note! color needs to be of exact the same size as column defined
+     */
+    Car tmp;
+    sprintf(tmp.color, "Pink");
+    if(scan_delete(&myNdb, column_color, tmp.color) > 0)
+      std::cout << "scan_delete: Success!" << std::endl  << std::endl;
+  }
+
+  if(scan_print(&myNdb) > 0)
+    std::cout << "scan_print: Success!" << std::endl  << std::endl;
+  
+  {
+    /**
+     * Note! color1 & 2 need to be of exact the same size as column defined
+     */
+    Car tmp1, tmp2;
+    sprintf(tmp1.color, "Blue");
+    sprintf(tmp2.color, "Black");
+    std::cout << "Going to update all " << tmp1.color 
+	      << " cars to " << tmp2.color << " cars!" << std::endl;
+    if(scan_update(&myNdb, column_color, tmp1.color, tmp2.color) > 0) 
+      std::cout << "scan_update: Success!" << std::endl  << std::endl;
+  }
+  if(scan_print(&myNdb) > 0)
+    std::cout << "scan_print: Success!" << std::endl  << std::endl;
+
+  /**
+   * Drop table
+   */
+  drop_table(mysql);
+
+  return 0;
+}

Thread
bzr commit into NDB/Bindings:trunk branch (monty:412) Monty Taylor20 Jun