Documentation Home
MySQL NDB Cluster API Developer Guide
Download this Manual

MySQL NDB Cluster API Developer Guide  /  ...  /  Timestamp2 Example

2.5.13 Timestamp2 Example

The file timestamp2.cpp reproduced in this section provides an example of working in NDB API applications with the new MySQL temporal data types supporting fractional seconds that were implemented in MySQL 5.6, and in NDB 7.3 and NDB 7.4.

For more information working with MySQL temporal and other data types in the NDB API, see Section 2.1.3.2, “NDB API Handling of MySQL Data Types”.

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <NdbApi.hpp>
#include <string>
#include <unistd.h>

//no binlog value
#define NDB_ANYVALUE_FOR_NOLOGGING 0x8000007f

using namespace std;

int setTimestamp(NdbOperation* op,
                 const NdbDictionary::Column* col,
                 unsigned int value)
{
  if (col->getType() == NDB_TYPE_TIMESTAMP)
  {
    /* Set as 32-bit int in host layout */
    return op->setValue(col->getName(), value);
  }
  else if (col->getType() == NDB_TYPE_TIMESTAMP2)
  {
    /* Set as 64 bit big-endian value */
    //assert(col->getPrecision() == 0);
    Uint64 ts = 0;
    unsigned char* bytes = (unsigned char*) &ts;
    bytes[0] = value >> 24 & 0xff;
    bytes[1] = value >> 16 & 0xff;
    bytes[2] = value >>  8 & 0xff;
    bytes[3] = value       & 0xff;
    return op->setValue(col->getName(), ts);
  }
  else
  {
    cout << "Bad type for column " << col->getType()
         << std::endl;
    exit(1);
  }
}

unsigned int readTimestamp(NdbRecAttr* recAttr)
{
  if (recAttr->getType() == NDB_TYPE_TIMESTAMP)
  {
    /* Timestamp is in native 32 bit layout */
    return recAttr->u_32_value();
  }
  else if (recAttr->getType() == NDB_TYPE_TIMESTAMP2)
  {
    /* Timestamp is in big-endian layout */
    //assert(recAttr->getColumn()->getPrecision() == 0);
    Uint64 ts2 = recAttr->u_64_value();
    const unsigned char* bytes = (const unsigned char*) &ts2;
    const unsigned int ts = 
      (Uint64(bytes[0]) << 24) + 
      (Uint64(bytes[1]) << 16) +
      (Uint64(bytes[2]) <<  8) +
      (Uint64(bytes[3]));

    return ts;
  }
  else
  {
    cout << "Error with timestamp column type : "
         << recAttr->getType()
         << endl;
    exit(1);
  }
}

void insert(string connectString)
{
    Ndb_cluster_connection *cluster_connection = new Ndb_cluster_connection(connectString.c_str());
    if(cluster_connection->connect(5,5,1)) {
        cout << "Cannot connect to Cluster using connectstring: "<< connectString << endl;
        exit(1);
    }

    if(cluster_connection->wait_until_ready(30,0) < 0) {
        cout << "Cluster was not ready within 30 seconds" << endl;
    }

    Ndb *myNdb = new Ndb(cluster_connection, "myndb_user_data");

    if(myNdb->init(1024) == -1){
        cout << "Error: Cannot initialize NDB object" << endl;
        exit(-1);
    }

    const NdbDictionary::Dictionary *dict = myNdb->getDictionary();
    if (dict == NULL) {
        cout << "Error: Cannot fetch NndDictionary" << endl;
        exit(0);
    }

    const NdbDictionary::Table *timestampTable = dict->getTable("TIMESTAMP_TEST");
    if (timestampTable == NULL) {
        cout << "Error: Cannot fetch MYNDB table" << endl;
        exit(0);
    }

    NdbTransaction *trans = myNdb->startTransaction();
    if (trans == NULL) {
      cout << "Error: Cannot start new transaction" << endl;
      exit(1);
    }

    NdbOperation *myOperation = trans->getNdbOperation(timestampTable);
    if ( myOperation == NULL) {
      cout << "Error: Cannot get new operation" << endl;
      exit(1);
    }

    myOperation->insertTuple();

    Uint64 value;
    myNdb->getAutoIncrementValue(timestampTable, value, (Uint32)32);
    myOperation->setValue("KEY_COL", value);


    time_t timestamp= time(NULL);
    setTimestamp(myOperation,
                 timestampTable->getColumn("createTimestamp"),
                 timestamp);
    setTimestamp(myOperation,
                 timestampTable->getColumn("modifyTimestamp"),
                 timestamp);  
    //disable binlogging
    myOperation->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING);

    if(trans->execute(NdbTransaction::Commit) != 0) {
      cout << "Error: " << trans->getNdbError().message << endl;
      exit(1);
    }

    myNdb->closeTransaction(trans);
 
    delete myNdb;

    delete cluster_connection;
}


void fetch_from_database(string connectString)
{
    Ndb_cluster_connection *cluster_connection = new Ndb_cluster_connection(connectString.c_str());
    if(cluster_connection->connect(5,5,1)) {
        cout << "Cannot connect to Cluster using connectstring: "<< connectString << endl;
        exit(1);
    }

    if(cluster_connection->wait_until_ready(30,0) < 0) {
        cout << "Cluster was not ready within 30 seconds" << endl;
    }

    Ndb *myNdb = new Ndb(cluster_connection, "myndb_user_data");

    if(myNdb->init(1024) == -1){
        cout << "Error: Cannot initialize NDB object" << endl;
        exit(-1);
    }

    const NdbDictionary::Dictionary *dict = myNdb->getDictionary();
    if (dict == NULL) {
        cout << "Error: Cannot fetch NndDictionary" << endl;
        exit(0);
    }

    const NdbDictionary::Table *timestampTable = dict->getTable("TIMESTAMP_TEST");
    if (timestampTable == NULL) {
        cout << "Error: Cannot fetch MYNDB table" << endl;
        exit(0);
    }

    NdbTransaction *trans = myNdb->startTransaction();
    if (trans == NULL) {
      cout << "Error: Cannot start new transaction" << endl;
      exit(1);
    }

    NdbScanOperation *myOperation = trans->getNdbScanOperation(timestampTable);
    if ( myOperation == NULL) {
      cout << "Error: Cannot get new operation" << endl;
      exit(1);
    }

    if (myOperation->readTuples(NdbOperation::LM_Exclusive) == -1){
      cout << "Error: " << trans->getNdbError().message << endl;
      exit(0);
    }

    NdbRecAttr *recAttrs[3];
    recAttrs[0] = myOperation->getValue("KEY_COL");
    recAttrs[1] = myOperation->getValue("createTimestamp");
    recAttrs[2] = myOperation->getValue("modifyTimestamp");

    if (recAttrs[0] == NULL || recAttrs[1] == NULL || recAttrs[2] == NULL) {
        cout << "Error: " << trans->getNdbError().message << endl;
        exit(0);
    }

    if(trans->execute(NdbTransaction::NoCommit) != 0) {
      cout << "Error: " << trans->getNdbError().message << endl;
      exit(1);
    }

    int check;

    while((check = myOperation->nextResult(true)) == 0){
      do {
	    cout << recAttrs[0]->u_32_value() << "\t";
            cout << readTimestamp(recAttrs[1]) << "\t";
	    cout << readTimestamp(recAttrs[2]) << std::endl;
      }   while((check = myOperation->nextResult(false)) == 0);
    }

    myNdb->closeTransaction(trans);

    delete myNdb;

    delete cluster_connection;

}

int main(int argc, char **argv) {
	cout << "Timestamp test application!!!!" << endl;

	//fetch parameters
    string connectString;

    if (argc < 2) {
        cout<<"Please provide connect string for PLDB"<<endl;
        exit(1);
    }
    connectString = argv[1];

	ndb_init();

    insert(connectString);

    fetch_from_database(connectString);

	ndb_end(0);

	return EXIT_SUCCESS;
}