MySQL NDB Cluster API 开发人员指南 / 第 2 章 NDB API / 2.5 NDB API 示例 / 2.5.1 基本 NDB API 示例 /
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;
}