2.5.14 时间戳2示例

本节中复制的文件timestamp2.cpp提供了一个在 NDB API 应用程序中使用支持小数秒的 MySQL 时间数据类型的示例,这些数据类型在 MySQL 5.6、NDB 7.3 和 NDB 7.4 中实现。

有关在 NDB API 中使用 MySQL 时间和其他数据类型的更多信息,请参阅 第 2.1.3.2 节,“NDB API 处理 MySQL 数据类型”

#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;
}