2.5.1.3 NDB API 基础阅读示例

此示例说明了NDB使用 NdbRecord接口和 NdbScanOperation. 我们假设您已经创建并填充了 basic表,可能使用前面显示的行插入示例(请参阅 第 2.5.1.2 节,“NDB API 基本插入示例”)。

您还可以在文件中找到此示例的源代码 storage/ndb/ndbapi-examples/ndbapi_basic/ndbapi_basic_read.cpp

#include <iostream>
#include <cstdlib>
#include <string>
#include <iterator>

#include <NdbApi.hpp>

class BasicRead
{
  public:
    BasicRead(const char *connectstring)
      : m_connection(connectstring), m_ndb(&m_connection, "ndbapi_examples") {}

    bool init();
    bool do_read();

  private:
    Ndb_cluster_connection m_connection;
    Ndb m_ndb;

    struct BasicRow
    {
      int attr1, attr2;
    };

    inline bool on_error(const struct NdbError &error,
                         const std::string &explanation)
    {
      // prints error in format:
      // ERROR <NdbErrorCode>: <NdbError message>
      //    explanation what went wrong on higher level (in the example code)
      std::cout << "ERROR "<< error.code << ": " << error.message << std::endl;
      std::cout << explanation << std::endl;
      return false;
    }
};

int main(int argc, char **argv)
{
  if (argc != 2)
  {
    std::cout << "Usage: ndb_ndbapi_basic_read <connectstring>" << std::endl;
    return EXIT_FAILURE;
  }
  const char *connectstring = argv[1];

  ndb_init();
  {
    BasicRead example(connectstring);
    if (!example.init())
      return EXIT_FAILURE;

    // Let's verify reads
    if (!example.do_read()) return EXIT_FAILURE;
  }
  ndb_end(0);
  return EXIT_SUCCESS;
}

bool BasicRead::do_read()
{
  NdbDictionary::Dictionary *dict = m_ndb.getDictionary();
  const NdbDictionary::Table *table = dict->getTable("basic");
  if (table == nullptr)
    return on_error(dict->getNdbError(),
                    "Cannot access table 'ndbapi_examples.basic'");

  // Prepare record specification,
  // this will allow us later to access rows in the table
  // using our structure BasicRow
  NdbRecord* record;
  NdbDictionary::RecordSpecification record_spec[] = {
    { table->getColumn("ATTR1"), offsetof(BasicRow, attr1), 0, 0, 0 },
    { table->getColumn("ATTR2"), offsetof(BasicRow, attr2), 0, 0, 0 }
  };

  record = dict->createRecord(table,
                              record_spec,
                              std::size(record_spec),
                              sizeof(record_spec[0]));
  if (record == nullptr)
    return on_error(dict->getNdbError(), "Failed to create record");

  // All reads will be performed within single transaction
  NdbTransaction *transaction = m_ndb.startTransaction(table);
  if(transaction == nullptr)
    return on_error(m_ndb.getNdbError(), "Failed to start transaction");

  // Note the usage of NdbScanOperation instead of regular NdbOperation
  NdbScanOperation *operation = transaction->scanTable(record);
  if(operation == nullptr)
    return on_error(transaction->getNdbError(),
                    "Failed to start scanTable operation");

  // Note the usage of NoCommit flag, as we are only reading the tuples
  if (transaction->execute(NdbTransaction::NoCommit) != 0)
    return on_error(transaction->getNdbError(),
                    "Failed to execute transaction");

  const BasicRow *row_ptr;
  int rc;
  std::cout << "ATTR1" << "\t" << "ATTR2" << std::endl;
  // Loop over all read results to print them
  while ((rc = operation->nextResult(reinterpret_cast<const char **>(&row_ptr),
                                     true, false)) == 0)
    std::cout << row_ptr->attr1 << "\t" << row_ptr->attr2
              << std::endl;
  if (rc == -1)
    return on_error(transaction->getNdbError(), "Failed to read tuple");

  operation->close();
  m_ndb.closeTransaction(transaction);
  dict->releaseRecord(record);

  return true;
}

bool BasicRead::init()
{
  if (m_connection.connect() != 0)
  {
    std::cout << "Cannot connect to cluster management server" << std::endl;
    return false;
  }

  if (m_connection.wait_until_ready(30, 0) != 0)
  {
    std::cout << "Cluster was not ready within 30 secs" << std::endl;
    return false;
  }

  if (m_ndb.init() != 0)
    return on_error(m_ndb.getNdbError(), "Failed to initialize ndb object");

  return true;
}