summaryrefslogtreecommitdiff
path: root/storage/ndb/include/ndbapi
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/include/ndbapi')
-rw-r--r--storage/ndb/include/ndbapi/Ndb.hpp1762
-rw-r--r--storage/ndb/include/ndbapi/NdbApi.hpp35
-rw-r--r--storage/ndb/include/ndbapi/NdbBlob.hpp410
-rw-r--r--storage/ndb/include/ndbapi/NdbDictionary.hpp1918
-rw-r--r--storage/ndb/include/ndbapi/NdbError.hpp250
-rw-r--r--storage/ndb/include/ndbapi/NdbEventOperation.hpp261
-rw-r--r--storage/ndb/include/ndbapi/NdbIndexOperation.hpp192
-rw-r--r--storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp204
-rw-r--r--storage/ndb/include/ndbapi/NdbIndexStat.hpp147
-rw-r--r--storage/ndb/include/ndbapi/NdbOperation.hpp1311
-rw-r--r--storage/ndb/include/ndbapi/NdbPool.hpp35
-rw-r--r--storage/ndb/include/ndbapi/NdbRecAttr.hpp416
-rw-r--r--storage/ndb/include/ndbapi/NdbReceiver.hpp150
-rw-r--r--storage/ndb/include/ndbapi/NdbScanFilter.hpp178
-rw-r--r--storage/ndb/include/ndbapi/NdbScanOperation.hpp313
-rw-r--r--storage/ndb/include/ndbapi/NdbTransaction.hpp1060
-rw-r--r--storage/ndb/include/ndbapi/ndb_cluster_connection.hpp130
-rw-r--r--storage/ndb/include/ndbapi/ndb_opt_defaults.h23
-rw-r--r--storage/ndb/include/ndbapi/ndbapi_limits.h30
-rw-r--r--storage/ndb/include/ndbapi/ndberror.h110
20 files changed, 8935 insertions, 0 deletions
diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp
new file mode 100644
index 00000000000..726a58c591d
--- /dev/null
+++ b/storage/ndb/include/ndbapi/Ndb.hpp
@@ -0,0 +1,1762 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+/**
+ @mainpage NDB API Programmers' Guide
+
+ This guide assumes a basic familiarity with MySQL Cluster concepts found
+ on http://dev.mysql.com/doc/mysql/en/NDBCluster.html .
+ Some of the fundamental ones are also described in section @ref secConcepts.
+
+ The NDB API is a MySQL Cluster application interface
+ that implements transactions.
+ The NDB API consists of the following fundamental classes:
+ - Ndb_cluster_connection, representing a connection to a cluster,
+ - Ndb is the main class, representing a connection to a database,
+ - NdbTransaction represents a transaction,
+ - NdbOperation represents an operation using a primary key,
+ - NdbScanOperation represents an operation performing a full table scan.
+ - NdbIndexOperation represents an operation using a unique hash index,
+ - NdbIndexScanOperation represents an operation performing a scan using
+ an ordered index,
+ - NdbRecAttr represents an attribute value
+ - NdbDictionary represents meta information about tables and attributes.
+
+ In addition, the NDB API defines a structure NdbError, which contains the
+ specification for an error.
+
+ It is also possible to receive "events" triggered when data in the database in changed.
+ This is done through the NdbEventOperation class.
+
+ There are also some auxiliary classes, which are listed in the class hierarchy.
+
+ The main structure of an application program is as follows:
+ -# Connect to a cluster using the Ndb_cluster_connection
+ object.
+ -# Initiate a database connection by constructing and initialising one or more Ndb objects.
+ -# Define and execute transactions using the NdbTransaction class.
+ -# Delete Ndb objects.
+ -# Terminate the connection to the cluster (terminate instance of Ndb_cluster_connection).
+
+ The procedure for using transactions is as follows:
+ -# Start transaction (instantiate an NdbTransaction object)
+ -# Add and define operations associated with the transaction using instances of one or more of the
+ NdbOperation, NdbScanOperation, NdbIndexOperation, and NdbIndexScanOperation classes
+ -# Execute transaction (call NdbTransaction::execute())
+
+ The operation can be of two different types,
+ <var>Commit</var> or <var>NoCommit</var>.
+ If the operation is of type <var>NoCommit</var>,
+ then the application program executes the operation part of a transaction,
+ but without actually committing the transaction.
+ After executing a <var>NoCommit</var> operation, the program can continue
+ to add and define more operations to the transaction
+ for later execution.
+
+ If the operation is of type <var>Commit</var>, then the transaction is
+ immediately committed. The transaction <em>must</em> be closed after it has been
+ commited (event if commit fails), and no further addition or definition of
+ operations for this transaction is allowed.
+
+ @section secSync Synchronous Transactions
+
+ Synchronous transactions are defined and executed as follows:
+
+ -# Start (create) the transaction, which is
+ referenced by an NdbTransaction object
+ (typically created using Ndb::startTransaction()).
+ At this point, the transaction is only being defined,
+ and is not yet sent to the NDB kernel.
+ -# Define operations and add them to the transaction, using one or more of
+ - NdbTransaction::getNdbOperation()
+ - NdbTransaction::getNdbScanOperation()
+ - NdbTransaction::getNdbIndexOperation()
+ - NdbTransaction::getNdbIndexScanOperation()
+ along with the appropriate methods of the respective NdbOperation class
+ (or one possiblt one or more of its subclasses).
+ Note that the transaction has still not yet been sent to the NDB kernel.
+ -# Execute the transaction, using the NdbTransaction::execute() method.
+ -# Close the transaction (call Ndb::closeTransaction()).
+
+ For an example of this process, see the program listing in
+ @ref ndbapi_simple.cpp.
+
+ To execute several parallel synchronous transactions, one can either
+ use multiple Ndb objects in several threads, or start multiple
+ application programs.
+
+ @section secNdbOperations Operations
+
+ A NdbTransaction consists of a list of operations, each of which is represented
+ by an instance of NdbOperation, NdbScanOperation, NdbIndexOperation, or
+ NdbIndexScanOperation.
+
+ <h3>Single row operations</h3>
+ After the operation is created using NdbTransaction::getNdbOperation()
+ (or NdbTransaction::getNdbIndexOperation()), it is defined in the following
+ three steps:
+ -# Define the standard operation type, using NdbOperation::readTuple()
+ -# Specify search conditions, using NdbOperation::equal()
+ -# Specify attribute actions, using NdbOperation::getValue()
+
+ Here are two brief examples illustrating this process. For the sake of
+ brevity, we omit error handling.
+
+ This first example uses an NdbOperation:
+ @code
+ // 1. Retrieve table object
+ myTable= myDict->getTable("MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbOperation(myTable);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuple(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ myOperation->equal("ATTR1", i);
+
+ // 5. Attribute Actions
+ myRecAttr= myOperation->getValue("ATTR2", NULL);
+ @endcode
+ For additional examples of this sort, see @ref ndbapi_simple.cpp.
+
+ The second example uses an NdbIndexOperation:
+ @code
+ // 1. Retrieve index object
+ myIndex= myDict->getIndex("MYINDEX", "MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbIndexOperation(myIndex);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuple(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ myOperation->equal("ATTR1", i);
+
+ // 5. Attribute Actions
+ myRecAttr = myOperation->getValue("ATTR2", NULL);
+ @endcode
+ Another example of this second type can be found in
+ @ref ndbapi_simple_index.cpp.
+
+ We will now discuss in somewhat greater detail each step involved in the
+ creation and use of synchronous transactions.
+
+ <h4>Step 1: Define single row operation type</h4>
+ The following operation types are supported:
+ -# NdbOperation::insertTuple() :
+ inserts a non-existing tuple
+ -# NdbOperation::writeTuple() :
+ updates an existing tuple if is exists,
+ otherwise inserts a new tuple
+ -# NdbOperation::updateTuple() :
+ updates an existing tuple
+ -# NdbOperation::deleteTuple() :
+ deletes an existing tuple
+ -# NdbOperation::readTuple() :
+ reads an existing tuple with specified lock mode
+
+ All of these operations operate on the unique tuple key.
+ (When NdbIndexOperation is used then all of these operations
+ operate on a defined unique hash index.)
+
+ @note If you want to define multiple operations within the same transaction,
+ then you need to call NdbTransaction::getNdbOperation() or
+ NdbTransaction::getNdbIndexOperation() for each operation.
+
+ <h4>Step 2: Specify Search Conditions</h4>
+ The search condition is used to select tuples. Search conditions are set using NdbOperation::equal().
+
+ <h4>Step 3: Specify Attribute Actions</h4>
+ Next, it is necessary to determine which attributes should be read or updated.
+ It is important to remember that:
+ - Deletes can neither read nor set values, but only delete them
+ - Reads can only read values
+ - Updates can only set values
+ Normally the attribute is identified by name, but it is
+ also possible to use the attribute's identity to determine the
+ attribute.
+
+ NdbOperation::getValue() returns an NdbRecAttr object
+ containing the read value.
+ To obtain the actual value, one of two methods can be used;
+ the application can either
+ - use its own memory (passed through a pointer aValue) to
+ NdbOperation::getValue(), or
+ - receive the attribute value in an NdbRecAttr object allocated
+ by the NDB API.
+
+ The NdbRecAttr object is released when Ndb::closeTransaction()
+ is called.
+ Thus, the application cannot reference this object following
+ any subsequent call to Ndb::closeTransaction().
+ Attempting to read data from an NdbRecAttr object before
+ calling NdbTransaction::execute() yields an undefined result.
+
+
+ @subsection secScan Scan Operations
+
+ Scans are roughly the equivalent of SQL cursors, providing a means to
+ preform high-speed row processing. A scan can be performed
+ on either a table (using @ref NdbScanOperation) or
+ an ordered index (by means of an @ref NdbIndexScanOperation).
+
+ Scan operations are characterised by the following:
+ - They can perform only reads (shared, exclusive or dirty)
+ - They can potentially work with multiple rows
+ - They can be used to update or delete multiple rows
+ - They can operate on several nodes in parallel
+
+ After the operation is created using NdbTransaction::getNdbScanOperation()
+ (or NdbTransaction::getNdbIndexScanOperation()),
+ it is carried out in the following three steps:
+ -# Define the standard operation type, using NdbScanOperation::readTuples()
+ -# Specify search conditions, using @ref NdbScanFilter and/or
+ @ref NdbIndexScanOperation::setBound()
+ -# Specify attribute actions, using NdbOperation::getValue()
+ -# Executing the transaction, using NdbTransaction::execute()
+ -# Traversing the result set by means of succssive calls to
+ NdbScanOperation::nextResult()
+
+ Here are two brief examples illustrating this process. Once again, in order
+ to keep things relatively short and simple, we will forego any error handling.
+
+ This first example performs a table scan, using an NdbScanOperation:
+ @code
+ // 1. Retrieve table object
+ myTable= myDict->getTable("MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbScanOperation(myTable);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuples(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ NdbScanFilter sf(myOperation);
+ sf.begin(NdbScanFilter::OR);
+ sf.eq(0, i); // Return rows with column 0 equal to i or
+ sf.eq(1, i+1); // column 1 equal to (i+1)
+ sf.end();
+
+ // 5. Attribute Actions
+ myRecAttr= myOperation->getValue("ATTR2", NULL);
+ @endcode
+
+ Our second example uses an NdbIndexScanOperation to perform an index scan:
+ @code
+ // 1. Retrieve index object
+ myIndex= myDict->getIndex("MYORDEREDINDEX", "MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbIndexScanOperation(myIndex);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuples(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ // All rows with ATTR1 between i and (i+1)
+ myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundGE, i);
+ myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundLE, i+1);
+
+ // 5. Attribute Actions
+ myRecAttr = MyOperation->getValue("ATTR2", NULL);
+ @endcode
+
+ Some additional discussion of each step required to perform a scan follows:
+
+ <h4>Step 1: Define Scan Operation Type</h4>
+ It is important to remember that only a single operation is supported for each scan operation
+ (@ref NdbScanOperation::readTuples() or @ref NdbIndexScanOperation::readTuples()).
+
+ @note If you want to define multiple scan operations within the same
+ transaction, then you need to call
+ NdbTransaction::getNdbScanOperation() or
+ NdbTransaction::getNdbIndexScanOperation() separately for <b>each</b> operation.
+
+ <h4>Step 2: Specify Search Conditions</h4>
+ The search condition is used to select tuples.
+ If no search condition is specified, the scan will return all rows
+ in the table.
+
+ The search condition can be an @ref NdbScanFilter (which can be used on both
+ @ref NdbScanOperation and @ref NdbIndexScanOperation) or bounds which
+ can only be used on index scans (@ref NdbIndexScanOperation::setBound()).
+ An index scan can use both NdbScanFilter and bounds.
+
+ @note When NdbScanFilter is used, each row is examined, whether or not it is
+ actually returned. However, when using bounds, only rows within the bounds will be examined.
+
+ <h4>Step 3: Specify Attribute Actions</h4>
+
+ Next, it is necessary to define which attributes should be read.
+ As with transaction attributes, scan attributes are defined by name but it is
+ also possible to use the attributes' identities to define attributes.
+
+ As previously discussed (see @ref secSync), the value read is returned as
+ an NdbRecAttr object by the NdbOperation::getValue() method.
+
+ <h3>Using Scan to Update/Delete</h3>
+ Scanning can also be used to update or delete rows.
+ This is performed by
+ -# Scanning using exclusive locks (using NdbOperation::LM_Exclusive)
+ -# When iterating through the result set, for each row optionally calling
+ either NdbScanOperation::updateCurrentTuple() or
+ NdbScanOperation::deleteCurrentTuple()
+ -# (If performing NdbScanOperation::updateCurrentTuple():)
+ Setting new values for records simply by using @ref NdbOperation::setValue().
+ NdbOperation::equal() should <em>not</em> be called in such cases, as the primary
+ key is retrieved from the scan.
+
+ @note The actual update or delete will not be performed until the next
+ call to NdbTransaction::execute(), just as with single row operations.
+ NdbTransaction::execute() also must be called before any locks are released;
+ see @ref secScanLocks for more information.
+
+ <h4>Features Specific to Index Scans</h4>
+
+ When performing an index scan, it is possible to
+ scan only a subset of a table using @ref NdbIndexScanOperation::setBound().
+ In addition, result sets can be sorted in either ascending or descending order, using
+ @ref NdbIndexScanOperation::readTuples(). Note that rows are returned unordered
+ by default, that is, unless <var>sorted</var> is set to <b>true</b>.
+ It is also important to note that, when using NdbIndexScanOperation::BoundEQ
+ on a partition key, only fragments containing rows will actually be scanned.
+
+ @note When performing a sorted scan, any value passed as the
+ NdbIndexScanOperation::readTuples() method's <code>parallel</code> argument
+ will be ignored and maximum parallelism will be used instead. In other words, all
+ fragments which it is possible to scan will be scanned simultaneously and in parallel
+ in such cases.
+
+ @subsection secScanLocks Lock handling with scans
+
+ Performing scans on either a tables or an index has the potential
+ return a great many records; however, Ndb will lock only a predetermined
+ number of rows per fragment at a time.
+ How many rows will be locked per fragment is controlled by the
+ <var>batch</var> parameter passed to NdbScanOperation::readTuples().
+
+ In order to allow the application to handle how locks are released,
+ NdbScanOperation::nextResult() has a Boolean parameter <var>fetch_allow</var>.
+ If NdbScanOperation::nextResult() is called with <var>fetch_allow</var> equal to
+ <b>false</b>, then no locks may be released as result of the function call.
+ Otherwise the locks for the current batch may be released.
+
+ This next example shows a scan delete that handle locks in an efficient manner.
+ For the sake of brevity, we omit error-handling.
+ @code
+ int check;
+
+ // Outer loop for each batch of rows
+ while((check = MyScanOperation->nextResult(true)) == 0)
+ {
+ do
+ {
+ // Inner loop for each row within batch
+ MyScanOperation->deleteCurrentTuple();
+ } while((check = MyScanOperation->nextResult(false)) == 0);
+
+ // When no more rows in batch, exeute all defined deletes
+ MyTransaction->execute(NoCommit);
+ }
+ @endcode
+
+ See @ref ndbapi_scan.cpp for a more complete example of a scan.
+
+ @section secError Error Handling
+
+ Errors can occur either when operations making up a transaction are being
+ defined, or when the transaction is actually being executed. Catching and
+ handling either sort of error requires testing the value returned by
+ NdbTransaction::execute(), and then, if an error is indicated (that is,
+ if this value is equal to -1), using the following two methods in order to
+ identify the error's type and location:
+
+ - NdbTransaction::getNdbErrorOperation() returns a reference to the
+ operation causing the most recent error.
+ - NdbTransaction::getNdbErrorLine() yields the method number of the
+ erroneous method in the operation.
+
+ This short example illustrates how to detect an error and to use these
+ two methods to identify it:
+
+ @code
+ theTransaction = theNdb->startTransaction();
+ theOperation = theTransaction->getNdbOperation("TEST_TABLE");
+ if (theOperation == NULL) goto error;
+ theOperation->readTuple(NdbOperation::LM_Read);
+ theOperation->setValue("ATTR_1", at1);
+ theOperation->setValue("ATTR_2", at1); // Error occurs here
+ theOperation->setValue("ATTR_3", at1);
+ theOperation->setValue("ATTR_4", at1);
+
+ if (theTransaction->execute(Commit) == -1) {
+ errorLine = theTransaction->getNdbErrorLine();
+ errorOperation = theTransaction->getNdbErrorOperation();
+ }
+ @endcode
+
+ Here <code>errorLine</code> will be 3, as the error occurred in the
+ third method called on the NdbOperation object (in this case,
+ <code>theOperation</code>); if the result of
+ NdbTransaction::getNdbErrorLine() is 0, this means that the error
+ occurred when the operations were executed. In this example,
+ <code>errorOperation</code> will be a pointer to the <code>theOperation</code>
+ object. The NdbTransaction::getNdbError() method returns an NdbError
+ object providing information about the error.
+
+ @note Transactions are <b>not</b> automatically closed when an error occurs. Call
+ Ndb::closeTransaction() to close the transaction.
+
+ One recommended way to handle a transaction failure
+ (i.e. an error is reported) is to:
+ -# Rollback transaction (call NdbTransaction::execute() with a special parameter)
+ -# Close transaction (call NdbTransaction::closeTransaction())
+ -# If the error was temporary, attempt to restart the transaction
+
+ Several errors can occur when a transaction contains multiple
+ operations which are simultaneously executed.
+ In this case the application has to go through all operations
+ and query their NdbError objects to find out what really happened.
+
+ It is also important to note that errors can occur even when a commit is
+ reported as successful. In order to handle such situations, the NDB API
+ provides an additional NdbTransaction::commitStatus() method to check the
+ transactions's commit status.
+
+******************************************************************************/
+
+/**
+ * @page ndbapi_simple.cpp ndbapi_simple.cpp
+ * @include ndbapi_simple.cpp
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ * @page ndbapi_async.cpp ndbapi_async.cpp
+ * @include ndbapi_async.cpp
+ */
+/**
+ * @page ndbapi_async1.cpp ndbapi_async1.cpp
+ * @include ndbapi_async1.cpp
+ */
+#endif
+
+/**
+ * @page ndbapi_retries.cpp ndbapi_retries.cpp
+ * @include ndbapi_retries.cpp
+ */
+
+/**
+ * @page ndbapi_simple_index.cpp ndbapi_simple_index.cpp
+ * @include ndbapi_simple_index.cpp
+ */
+
+/**
+ * @page ndbapi_scan.cpp ndbapi_scan.cpp
+ * @include ndbapi_scan.cpp
+ */
+
+/**
+ * @page ndbapi_event.cpp ndbapi_event.cpp
+ * @include ndbapi_event.cpp
+ */
+
+
+/**
+ @page secAdapt Adaptive Send Algorithm
+
+ At the time of "sending" a transaction
+ (using NdbTransaction::execute()), the transactions
+ are in reality <em>not</em> immediately transfered to the NDB Kernel.
+ Instead, the "sent" transactions are only kept in a
+ special send list (buffer) in the Ndb object to which they belong.
+ The adaptive send algorithm decides when transactions should
+ actually be transferred to the NDB kernel.
+
+ The NDB API is designed as a multi-threaded interface and so
+ it is often desirable to transfer database operations from more than
+ one thread at a time.
+ The NDB API keeps track of which Ndb objects are active in transferring
+ information to the NDB kernel and the expected amount of threads to
+ interact with the NDB kernel.
+ Note that a given instance of Ndb should be used in at most one thread;
+ different threads should <em>not</em> use the same Ndb object.
+
+ There are four conditions leading to the transfer of database
+ operations from Ndb object buffers to the NDB kernel:
+ -# The NDB Transporter (TCP/IP, SCI or shared memory)
+ decides that a buffer is full and sends it off.
+ The buffer size is implementation-dependent and
+ may change between MySQL Cluster releases.
+ On TCP/IP the buffer size is usually around 64 KB;
+ Since each Ndb object provides a single buffer per storage node,
+ the notion of a "full" buffer is local to this storage node.
+ -# The accumulation of statistical data on transferred information
+ may force sending of buffers to all storage nodes.
+ -# Every 10 ms, a special transmission thread checks whether or not
+ any send activity has occurred. If not, then the thread will
+ force transmission to all nodes.
+ This means that 20 ms is the maximum time database operations
+ are kept waiting before being sent off. The 10-millisecond limit
+ is likely to become a configuration parameter in
+ future releases of MySQL Cluster; however, for checks that
+ are more frequent than each 10 ms,
+ additional support from the operating system is required.
+ -# For methods that are affected by the adaptive send alorithm
+ (such as NdbTransaction::execute()), there is a <var>force</var>
+ parameter
+ that overrides its default behaviour in this regard and forces
+ immediate transmission to all nodes. See the inidvidual NDB API class
+ listings for more information.
+
+ @note The conditions listed above are subject to change in future releases
+ of MySQL Cluster.
+*/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+
+ For each of these "sent" transactions, there are three
+ possible states:
+ -# Waiting to be transferred to NDB Kernel.
+ -# Has been transferred to the NDB Kernel and is currently
+ being processed.
+ -# Has been transferred to the NDB Kernel and has
+ finished processing.
+ Now it is waiting for a call to a poll method.
+ (When the poll method is invoked,
+ then the transaction callback method will be executed.)
+
+ The poll method invoked (either Ndb::pollNdb() or Ndb::sendPollNdb())
+ will return when:
+ -# at least 'minNoOfEventsToWakeup' of the transactions
+ in the send list have transitioned to state 3 as described above, and
+ -# all of these transactions have executed their callback methods.
+*/
+#endif
+
+/**
+ @page secConcepts MySQL Cluster Concepts
+
+ The <em>NDB Kernel</em> is the collection of storage nodes
+ belonging to a MySQL Cluster.
+ The application programmer can for most purposes view the
+ set of all storage nodes as a single entity.
+ Each storage node is made up of three main components:
+ - TC : The transaction co-ordinator
+ - ACC : Index storage component
+ - TUP : Data storage component
+
+ When an application program executes a transaction,
+ it connects to one transaction co-ordinator on one storage node.
+ Usually, the programmer does not need to specify which TC should be used,
+ but in some cases when performance is important, the programmer can
+ provide "hints" to use a certain TC.
+ (If the node with the desired transaction co-ordinator is down, then another TC will
+ automatically take over the work.)
+
+ Every storage node has an ACC and a TUP which store
+ the indexes and data portions of the database table fragment.
+ Even though one TC is responsible for the transaction,
+ several ACCs and TUPs on other storage nodes might be involved in the
+ execution of the transaction.
+
+
+ @section secNdbKernelConnection Selecting a Transaction Co-ordinator
+
+ The default method is to select the transaction co-ordinator (TC) determined to be
+ the "closest" storage node, using a heuristic for proximity based on
+ the type of transporter connection. In order of closest to most distant, these are
+ - SCI
+ - SHM
+ - TCP/IP (localhost)
+ - TCP/IP (remote host)
+ If there are several connections available with the same proximity, they will each be
+ selected in a round robin fashion for every transaction. Optionally
+ one may set the method for TC selection to round-robin mode, where each new set of
+ transactions is placed on the next DB node. The pool of connections from which this
+ selection is made consists of all available connections.
+
+ As noted previously, the application programmer can provide hints to the NDB API as to
+ which transaction co-ordinator it should use. This is done by
+ providing a <em>table</em> and <em>partition key</em>
+ (usually the primary key).
+ By using the primary key as the partition key,
+ the transaction will be placed on the node where the primary replica
+ of that record resides.
+ Note that this is only a hint; the system can be
+ reconfigured at any time, in which case the NDB API will choose a transaction
+ co-ordinator without using the hint.
+ For more information, see NdbDictionary::Column::getPartitionKey() and
+ Ndb::startTransaction(). The application programmer can specify
+ the partition key from SQL by using the construct,
+ <code>CREATE TABLE ... ENGINE=NDB PARTITION BY KEY (<var>attribute-list</var>);</code>.
+
+
+ @section secRecordStruct NDB Record Structure
+ The NDB Cluster engine used by MySQL Cluster is a relational database engine
+ storing records in tables just as with any other RDBMS.
+ Table rows represent records as tuples of relational data.
+ When a new table is created, its attribute schema is specified for the table as a whole,
+ and thus each record of the table has the same structure. Again, this is typical
+ of relational databases, and NDB is no different in this regard.
+
+
+ @subsection secKeys Primary Keys
+ Each record has from 1 up to 32 attributes which belong
+ to the primary key of the table.
+
+ @section secTrans Transactions
+
+ Transactions are committed first to main memory,
+ and then to disk after a global checkpoint (GCP) is issued.
+ Since all data is (in most NDB Cluster configurations)
+ synchronously replicated and stored on multiple NDB nodes,
+ the system can still handle processor failures without loss
+ of data.
+ However, in the case of a system failure (e.g. the whole system goes down),
+ then all (committed or not) transactions occurring since the latest GCP are lost.
+
+
+ @subsection secConcur Concurrency Control
+ NDB Cluster uses pessimistic concurrency control based on locking.
+ If a requested lock (implicit and depending on database operation)
+ cannot be attained within a specified time,
+ then a timeout error occurs.
+
+ Concurrent transactions as requested by parallel application programs and
+ thread-based applications can sometimes deadlock when they try to access
+ the same information simultaneously.
+ Thus, applications need to be written in a manner so that timeout errors
+ occurring due to such deadlocks are handled gracefully. This generally
+ means that the transaction encountering a timeout should be rolled back
+ and restarted.
+
+
+ @section secHint Hints and Performance
+
+ Placing the transaction co-ordinator in close proximity
+ to the actual data used in the transaction can in many cases
+ improve performance significantly. This is particularly true for
+ systems using TCP/IP. For example, a Solaris system using a single 500 MHz processor
+ has a cost model for TCP/IP communication which can be represented by the formula
+
+ <code>[30 microseconds] + ([100 nanoseconds] * [<var>number of bytes</var>])</code>
+
+ This means that if we can ensure that we use "popular" links we increase
+ buffering and thus drastically reduce the communication cost.
+ The same system using SCI has a different cost model:
+
+ <code>[5 microseconds] + ([10 nanoseconds] * [<var>number of bytes</var>])</code>
+
+ Thus, the efficiency of an SCI system is much less dependent on selection of
+ transaction co-ordinators.
+ Typically, TCP/IP systems spend 30-60% of their working time on communication,
+ whereas for SCI systems this figure is closer to 5-10%.
+ Thus, employing SCI for data transport means that less care from the NDB API
+ programmer is required and greater scalability can be achieved, even for
+ applications using data from many different parts of the database.
+
+ A simple example is an application that uses many simple updates where
+ a transaction needs to update one record.
+ This record has a 32 bit primary key,
+ which is also the partition key.
+ Then the keyData will be the address of the integer
+ of the primary key and keyLen will be 4.
+*/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ (A transaction's execution can also be divided into three
+ steps: prepare, send, and poll. This allows us to perform asynchronous
+ transactions. More about this later.)
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ Another way to execute several parallel transactions is to use
+ asynchronous transactions.
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ Operations are of two different kinds:
+ -# standard operations, and
+ -# interpreted program operations.
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ <h3>Interpreted Program Operations</h3>
+ The following types of interpreted program operations exist:
+ -# NdbOperation::interpretedUpdateTuple :
+ updates a tuple using an interpreted program
+ -# NdbOperation::interpretedDeleteTuple :
+ delete a tuple using an interpreted program
+
+ The operations interpretedUpdateTuple and interpretedDeleteTuple both
+ work using the unique tuple key.
+
+ These <em>interpreted programs</em>
+ make it possible to perform computations
+ inside the NDB Cluster Kernel instead of in the application
+ program.
+ This is sometimes very effective, since no intermediate results
+ are sent to the application, only the final result.
+
+
+ <h3>Interpreted Update and Delete</h3>
+
+ Operations for interpreted updates and deletes must follow a
+ certain order when defining operations on a tuple.
+ As for read and write operations,
+ one must first define the operation type and then the search key.
+ -# The first step is to define the initial readings.
+ In this phase it is only allowed to use the
+ NdbOperation::getValue method.
+ This part might be empty.
+ -# The second step is to define the interpreted part.
+ The methods supported are the methods listed below except
+ NdbOperation::def_subroutine and NdbOperation::ret_sub
+ which can only be used in a subroutine.
+ NdbOperation::incValue and NdbOperation::subValue
+ increment and decrement attributes
+ (currently only unsigned integers supported).
+ This part can also be empty since interpreted updates
+ can be used for reading and updating the same tuple.
+ <p>
+ Even though getValue and setValue are not really interpreted
+ program instructions, it is still allowed to use them as
+ the last instruction of the program.
+ (If a getValue or setValue is found when an interpret_exit_ok
+ could have been issued then the interpreted_exit_ok
+ will be inserted.
+ A interpret_exit_ok should be viewed as a jump to the first
+ instruction after the interpreted instructions.)
+ -# The third step is to define all updates without any
+ interpreted program instructions.
+ Here a set of NdbOperation::setValue methods are called.
+ There might be zero such calls.
+ -# The fourth step is the final readings.
+ The initial readings reads the initial value of attributes
+ and the final readings reads them after their updates.
+ There might be zero NdbOperation::getValue calls.
+ -# The fifth step is possible subroutine definitions using
+ NdbOperation::def_subroutine and NdbOperation::ret_sub.
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ <h3>Interpreted Programs</h3>
+ Interpretation programs are executed in a
+ register-based virtual machine.
+ The virtual machine has eight 64 bit registers numbered 0-7.
+ Each register contains type information which is used both
+ for type conversion and for type checking.
+
+ @note Arrays are currently <b>not</b> supported in the virtual machine.
+ Currently only unsigned integers are supported and of size
+ maximum 64 bits.
+
+ All errors in the interpretation program will cause a
+ transaction abort, but will not affect any other transactions.
+
+ The following are legal interpreted program instructions:
+ -# incValue : Add to an attribute
+ -# subValue : Subtract from an attribute
+ -# def_label : Define a label in the interpreted program
+ -# add_reg : Add two registers
+ -# sub_reg : Subtract one register from another
+ -# load_const_u32 : Load an unsigned 32 bit value into a register
+ -# load_const_u64 : Load an unsigned 64 bit value into a register
+ -# load_const_null : Load a NULL value into a register
+ -# read_attr : Read attribute value into a register
+ -# write_attr : Write a register value into an attribute
+ -# branch_ge : Compares registers and possibly jumps to specified label
+ -# branch_gt : Compares registers and possibly jumps to specified label
+ -# branch_le : Compares registers and possibly jumps to specified label
+ -# branch_lt : Compares registers and possibly jumps to specified label
+ -# branch_eq : Compares registers and possibly jumps to specified label
+ -# branch_ne : Compares registers and possibly jumps to specified label
+ -# branch_ne_null : Jumps if register does not contain NULL value
+ -# branch_eq_null : Jumps if register contains NULL value
+ -# branch_label : Unconditional jump to label
+ -# interpret_exit_ok : Exit interpreted program
+ (approving tuple if used in scan)
+ -# interpret_exit_nok : Exit interpreted program
+ (disqualifying tuple if used in scan)
+
+ There are also three instructions for subroutines, which
+ are described in the next section.
+
+ @subsection subsubSub Interpreted Programs: Subroutines
+
+ The following are legal interpreted program instructions for
+ subroutines:
+ -# NdbOperation::def_subroutine :
+ Defines start of subroutine in interpreted program code
+ -# NdbOperation::call_sub :
+ Calls a subroutine
+ -# NdbOperation::ret_sub :
+ Return from subroutine
+
+ The virtual machine executes subroutines using a stack for
+ its operation.
+ The stack allows for up to 24 subroutine calls in succession.
+ Deeper subroutine nesting will cause an abort of the transaction.
+
+ All subroutines starts with the instruction
+ NdbOperation::def_subroutine and ends with the instruction
+ NdbOperation::ret_sub.
+ If it is necessary to return earlier in the subroutine
+ it has to be done using a branch_label instruction
+ to a label defined right before the
+ NdbOperation::ret_sub instruction.
+
+ @note The subroutines are automatically numbered starting with 0.
+ The parameter used by NdbOperation::def_subroutine
+ should match the automatic numbering to make it easier to
+ debug the interpreted program.
+*/
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ @section secAsync Asynchronous Transactions
+ The asynchronous interface is used to increase the speed of
+ transaction executing by better utilizing the connection
+ between the application and the NDB Kernel.
+ The interface is used to send many transactions
+ at the same time to the NDB kernel.
+ This is often much more efficient than using synchronous transactions.
+ The main reason for using this method is to ensure that
+ Sending many transactions at the same time ensures that bigger
+ chunks of data are sent when actually sending and thus decreasing
+ the operating system overhead.
+
+ The synchronous call to NdbTransaction::execute
+ normally performs three main steps:<br>
+ -# <b>Prepare</b>
+ Check transaction status
+ - if problems, abort the transaction
+ - if ok, proceed
+ -# <b>Send</b>
+ Send the defined operations since last execute
+ or since start of transaction.
+ -# <b>Poll</b>
+ Wait for response from NDB kernel.
+
+ The asynchronous method NdbTransaction::executeAsynchPrepare
+ only perform step 1.
+ (The abort part in step 1 is only prepared for. The actual
+ aborting of the transaction is performed in a later step.)
+
+ Asynchronous transactions are defined and executed
+ in the following way.
+ -# Start (create) transactions (same way as for the
+ synchronous transactions)
+ -# Add and define operations (also as in the synchronous case)
+ -# <b>Prepare</b> transactions
+ (using NdbTransaction::executeAsynchPrepare or
+ NdbTransaction::executeAsynch)
+ -# <b>Send</b> transactions to NDB Kernel
+ (using Ndb::sendPreparedTransactions,
+ NdbTransaction::executeAsynch, or Ndb::sendPollNdb)
+ -# <b>Poll</b> NDB kernel to find completed transactions
+ (using Ndb::pollNdb or Ndb::sendPollNdb)
+ -# Close transactions (same way as for the synchronous transactions)
+
+ See example program in section @ref ndbapi_example2.cpp.
+
+ This prepare-send-poll protocol actually exists in four variants:
+ - (Prepare-Send-Poll). This is the one-step variant provided
+ by synchronous transactions.
+ - (Prepare-Send)-Poll. This is the two-step variant using
+ NdbTransaction::executeAsynch and Ndb::pollNdb.
+ - Prepare-(Send-Poll). This is the two-step variant using
+ NdbTransaction::executeAsynchPrepare and Ndb::sendPollNdb.
+ - Prepare-Send-Poll. This is the three-step variant using
+ NdbTransaction::executeAsynchPrepare, Ndb::sendPreparedTransactions, and
+ Ndb::pollNdb.
+
+ Transactions first has to be prepared by using method
+ NdbTransaction::executeAsynchPrepare or NdbTransaction::executeAsynch.
+ The difference between these is that
+ NdbTransaction::executeAsynch also sends the transaction to
+ the NDB kernel.
+ One of the arguments to these methods is a callback method.
+ The callback method is executed during polling (item 5 above).
+
+ Note that NdbTransaction::executeAsynchPrepare does not
+ send the transaction to the NDB kernel. When using
+ NdbTransaction::executeAsynchPrepare, you either have to call
+ Ndb::sendPreparedTransactions or Ndb::sendPollNdb to send the
+ database operations.
+ (Ndb::sendPollNdb also polls Ndb for completed transactions.)
+
+ The methods Ndb::pollNdb and Ndb::sendPollNdb checks if any
+ sent transactions are completed. The method Ndb::sendPollNdb
+ also send all prepared transactions before polling NDB.
+ Transactions still in the definition phase (i.e. items 1-3 above,
+ transactions which has not yet been sent to the NDB kernel) are not
+ affected by poll-calls.
+ The poll method invoked (either Ndb::pollNdb or Ndb::sendPollNdb)
+ will return when:
+ -# at least 'minNoOfEventsToWakeup' of the transactions
+ are finished processing, and
+ -# all of these transactions have executed their
+ callback methods.
+
+ The poll method returns the number of transactions that
+ have finished processing and executed their callback methods.
+
+ @note When an asynchronous transaction has been started and sent to
+ the NDB kernel, it is not allowed to execute any methods on
+ objects belonging to this transaction until the transaction
+ callback method have been executed.
+ (The transaction is stated and sent by either
+ NdbTransaction::executeAsynch or through the combination of
+ NdbTransaction::executeAsynchPrepare and either
+ Ndb::sendPreparedTransactions or Ndb::sendPollNdb).
+
+ More about how transactions are sent the NDB Kernel is
+ available in section @ref secAdapt.
+*/
+#endif
+
+
+/**
+
+ Put this back when real array ops are supported
+ i.e. get/setValue("kalle[3]");
+
+ @subsection secArrays Array Attributes
+ A table attribute in NDB Cluster can be of type <var>Array</var>,
+ meaning that the attribute consists of an ordered sequence of
+ elements. In such cases, <var>attribute size</var> is the size
+ (expressed in bits) of any one element making up the array; the
+ <var>array size</var> is the number of elements in the array.
+
+*/
+
+#ifndef Ndb_H
+#define Ndb_H
+
+#include <ndb_types.h>
+#include <ndbapi_limits.h>
+#include <ndb_cluster_connection.hpp>
+#include <NdbError.hpp>
+#include <NdbDictionary.hpp>
+
+class NdbObjectIdMap;
+class NdbOperation;
+class NdbEventOperationImpl;
+class NdbScanOperation;
+class NdbIndexScanOperation;
+class NdbIndexOperation;
+class NdbTransaction;
+class NdbApiSignal;
+class NdbRecAttr;
+class NdbLabel;
+class NdbBranch;
+class NdbSubroutine;
+class NdbCall;
+class Table;
+class BaseString;
+class NdbEventOperation;
+class NdbBlob;
+class NdbReceiver;
+class TransporterFacade;
+class PollGuard;
+class Ndb_local_table_info;
+template <class T> struct Ndb_free_list_t;
+
+typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
+
+#define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds
+
+#define NDB_SYSTEM_DATABASE "sys"
+#define NDB_SYSTEM_SCHEMA "def"
+
+/**
+ * @class Ndb
+ * @brief Represents the NDB kernel and is the main class of the NDB API.
+ *
+ * Always start your application program by creating an Ndb object.
+ * By using several Ndb objects it is possible to design
+ * a multi-threaded application, but note that Ndb objects
+ * cannot be shared by several threads.
+ * Different threads should use different Ndb objects.
+ * A thread might however use multiple Ndb objects.
+ * Currently there is a limit of maximum 128 Ndb objects
+ * per application process.
+ *
+ * @note It is not allowed to call methods in the NDB API
+ * on the same Ndb object in different threads
+ * simultaneously (without special handling of the
+ * Ndb object).
+ *
+ * @note The Ndb object is multi-thread safe in the following manner.
+ * Each Ndb object can ONLY be handled in one thread.
+ * If an Ndb object is handed over to another thread then the
+ * application must ensure that a memory barrier is used to
+ * ensure that the new thread see all updates performed by
+ * the previous thread.
+ * Semaphores, mutexes and so forth are easy ways of issuing memory
+ * barriers without having to bother about the memory barrier concept.
+ *
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+// to be documented later
+/*
+ * If one Ndb object is used to handle parallel transactions through the
+ * asynchronous programming interface, please read the notes regarding
+ * asynchronous transactions (Section @ref secAsync).
+ * The asynchronous interface provides much higher performance
+ * in some situations, but is more complicated for the application designer.
+ *
+ * @note Each Ndb object should either use the methods for
+ * asynchronous transaction or the methods for
+ * synchronous transactions but not both.
+ */
+#endif
+
+class Ndb
+{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbReceiver;
+ friend class NdbOperation;
+ friend class NdbEventOperationImpl;
+ friend class NdbEventBuffer;
+ friend class NdbTransaction;
+ friend class Table;
+ friend class NdbApiSignal;
+ friend class NdbIndexOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexScanOperation;
+ friend class NdbDictionaryImpl;
+ friend class NdbDictInterface;
+ friend class NdbBlob;
+ friend class NdbImpl;
+#endif
+
+public:
+ /**
+ * @name General
+ * @{
+ */
+ /**
+ * The Ndb object represents a connection to a database.
+ *
+ * @note The init() method must be called before the Ndb object may actually be used.
+ *
+ * @param ndb_cluster_connection is a connection to the cluster containing
+ * the database to be used
+ * @param aCatalogName is the name of the catalog to be used.
+ * @note The catalog name provides a namespace for the tables and
+ * indexes created in any connection from the Ndb object.
+ * @param aSchemaName is the name of the schema you
+ * want to use.
+ * @note The schema name provides an additional namespace
+ * for the tables and indexes created in a given catalog.
+ */
+ Ndb(Ndb_cluster_connection *ndb_cluster_connection,
+ const char* aCatalogName = "", const char* aSchemaName = "def");
+
+ ~Ndb();
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * The current ndb_cluster_connection get_ndb_cluster_connection.
+ *
+ * @return the current connection
+ */
+ Ndb_cluster_connection& get_ndb_cluster_connection();
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * The current catalog name can be fetched by getCatalogName.
+ *
+ * @return the current catalog name
+ */
+ const char * getCatalogName() const;
+
+ /**
+ * The current catalog name can be set by setCatalogName.
+ *
+ * @param aCatalogName is the new name of the current catalog
+ */
+ void setCatalogName(const char * aCatalogName);
+
+ /**
+ * The current schema name can be fetched by getSchemaName.
+ *
+ * @return the current schema name
+ */
+ const char * getSchemaName() const;
+
+ /**
+ * The current schema name can be set by setSchemaName.
+ *
+ * @param aSchemaName is the new name of the current schema
+ */
+ void setSchemaName(const char * aSchemaName);
+#endif
+
+ /**
+ * The current database name can be fetched by getDatabaseName.
+ *
+ * @return the current database name
+ */
+ const char * getDatabaseName() const;
+
+ /**
+ * The current database name can be set by setDatabaseName.
+ *
+ * @param aDatabaseName is the new name of the current database
+ */
+ void setDatabaseName(const char * aDatabaseName);
+
+ /**
+ * The current database schema name can be fetched by getDatabaseSchemaName.
+ *
+ * @return the current database schema name
+ */
+ const char * getDatabaseSchemaName() const;
+
+ /**
+ * The current database schema name can be set by setDatabaseSchemaName.
+ *
+ * @param aDatabaseSchemaName is the new name of the current database schema
+ */
+ void setDatabaseSchemaName(const char * aDatabaseSchemaName);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** Set database and schema name to match previously retrieved table
+ *
+ * Returns non-zero if table internal name does not contain
+ * non-empty database and schema names
+ */
+ int setDatabaseAndSchemaName(const NdbDictionary::Table* t);
+#endif
+
+ /**
+ * Initializes the Ndb object
+ *
+ * @param maxNoOfTransactions
+ * Maximum number of parallel
+ * NdbTransaction objects that can be handled by the Ndb object.
+ * Maximum value is 1024.
+ *
+ * @note each scan or index scan operation uses one extra
+ * NdbTransaction object
+ *
+ * @return 0 if successful, -1 otherwise.
+ */
+ int init(int maxNoOfTransactions = 4);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Wait for Ndb object to successfully set-up connections to
+ * the NDB kernel.
+ * Starting to use the Ndb object without using this method
+ * gives unspecified behavior.
+ *
+ * @param timeout The maximum time we will wait for
+ * the initiation process to finish.
+ * Timeout is expressed in seconds.
+ * @return 0: Ndb is ready and timeout has not occurred.<br>
+ * -1: Timeout has expired
+ */
+ int waitUntilReady(int timeout = 60);
+#endif
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Meta Information
+ * @{
+ */
+
+ /**
+ * Get an object for retrieving or manipulating database schema information
+ *
+ * @note this object operates outside any transaction
+ *
+ * @return Object containing meta information about all tables
+ * in NDB Cluster.
+ */
+ class NdbDictionary::Dictionary* getDictionary() const;
+
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Event subscriptions
+ * @{
+ */
+
+ /**
+ * Create a subcription to an event defined in the database
+ *
+ * @param eventName
+ * unique identifier of the event
+ *
+ * @return Object representing an event, NULL on failure
+ */
+ NdbEventOperation* createEventOperation(const char* eventName);
+ /**
+ * Drop a subscription to an event
+ *
+ * @param eventOp
+ * Event operation
+ *
+ * @return 0 on success
+ */
+ int dropEventOperation(NdbEventOperation* eventOp);
+
+ /**
+ * Wait for an event to occur. Will return as soon as an event
+ * is detected on any of the created events.
+ *
+ * @param aMillisecondNumber
+ * maximum time to wait
+ *
+ * @return > 0 if events available, 0 if no events available, < 0 on failure
+ */
+ int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);
+
+ /**
+ * Returns an event operation that has data after a pollEvents
+ *
+ * @return an event operations that has data, NULL if no events left with data.
+ */
+ NdbEventOperation *nextEvent();
+
+ /**
+ * Iterate over distinct event operations which are part of current
+ * GCI. Valid after nextEvent. Used to get summary information for
+ * the epoch (e.g. list of all tables) before processing event data.
+ *
+ * Set *iter=0 to start. Returns NULL when no more. If event_types
+ * is not NULL, it returns bitmask of received event types.
+ */
+ const NdbEventOperation*
+ getGCIEventOperations(Uint32* iter, Uint32* event_types);
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ int flushIncompleteEvents(Uint64 gci);
+ NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
+ Uint64 getLatestGCI();
+ void forceGCP();
+ void setReportThreshEventGCISlip(unsigned thresh);
+ void setReportThreshEventFreeMem(unsigned thresh);
+#endif
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Starting and Closing Transactions
+ * @{
+ */
+
+ /**
+ * Start a transaction
+ *
+ * @note When the transaction is completed it must be closed using
+ * Ndb::closeTransaction or NdbTransaction::close.
+ * The transaction must be closed independent of its outcome, i.e.
+ * even if there is an error.
+ *
+ * @param table Pointer to table object used for deciding
+ * which node to run the Transaction Coordinator on
+ * @param keyData Pointer to partition key corresponding to
+ * <var>table</var>
+ * @param keyLen Length of partition key expressed in bytes
+ *
+ * @return NdbTransaction object, or NULL on failure.
+ */
+ NdbTransaction* startTransaction(const NdbDictionary::Table *table= 0,
+ const char *keyData = 0,
+ Uint32 keyLen = 0);
+
+ /**
+ * Close a transaction.
+ *
+ * @note should be called after the transaction has completed, irrespective
+ * of success or failure
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * @note It is not allowed to call Ndb::closeTransaction after sending the
+ * transaction asynchronously with either
+ * Ndb::sendPreparedTransactions or
+ * Ndb::sendPollNdb before the callback method has been called.
+ * (The application should keep track of the number of
+ * outstanding transactions and wait until all of them
+ * has completed before calling Ndb::closeTransaction).
+ * If the transaction is not committed it will be aborted.
+ */
+#endif
+ void closeTransaction(NdbTransaction*);
+
+ /** @} *********************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ // to be documented later
+ /**
+ * @name Asynchronous Transactions
+ * @{
+ */
+
+ /**
+ * Wait for prepared transactions.
+ * Will return as soon as at least 'minNoOfEventsToWakeUp'
+ * of them have completed, or the maximum time given as timeout has passed.
+ *
+ * @param aMillisecondNumber
+ * Maximum time to wait for transactions to complete. Polling
+ * without wait is achieved by setting the timer to zero.
+ * Time is expressed in milliseconds.
+ * @param minNoOfEventsToWakeup Minimum number of transactions
+ * which has to wake up before the poll-call will return.
+ * If minNoOfEventsToWakeup is
+ * set to a value larger than 1 then this is the minimum
+ * number of transactions that need to complete before the
+ * poll will return.
+ * Setting it to zero means that one should wait for all
+ * outstanding transactions to return before waking up.
+ * @return Number of transactions polled.
+ */
+ int pollNdb(int aMillisecondNumber = WAITFOR_RESPONSE_TIMEOUT,
+ int minNoOfEventsToWakeup = 1);
+
+ /**
+ * This send method will send all prepared database operations.
+ * The default method is to do it non-force and instead
+ * use the adaptive algorithm. (See Section @ref secAdapt.)
+ * The second option is to force the sending and
+ * finally there is the third alternative which is
+ * also non-force but also making sure that the
+ * adaptive algorithm do not notice the send.
+ * In this case the sending will be performed on a
+ * cyclical 10 millisecond event.
+ *
+ * @param forceSend When operations should be sent to NDB Kernel.
+ * (See @ref secAdapt.)
+ * - 0: non-force, adaptive algorithm notices it (default);
+ * - 1: force send, adaptive algorithm notices it;
+ * - 2: non-force, adaptive algorithm do not notice the send.
+ */
+ void sendPreparedTransactions(int forceSend = 0);
+
+ /**
+ * This is a send-poll variant that first calls
+ * Ndb::sendPreparedTransactions and then Ndb::pollNdb.
+ * It is however somewhat faster than calling the methods
+ * separately, since some mutex-operations are avoided.
+ * See documentation of Ndb::pollNdb and Ndb::sendPreparedTransactions
+ * for more details.
+ *
+ * @param aMillisecondNumber Timeout specifier
+ * Polling without wait is achieved by setting the
+ * millisecond timer to zero.
+ * @param minNoOfEventsToWakeup Minimum number of transactions
+ * which has to wake up before the poll-call will return.
+ * If minNoOfEventsToWakeup is
+ * set to a value larger than 1 then this is the minimum
+ * number of transactions that need to complete before the
+ * poll-call will return.
+ * Setting it to zero means that one should wait for all
+ * outstanding transactions to return before waking up.
+ * @param forceSend When operations should be sent to NDB Kernel.
+ * (See @ref secAdapt.)
+ * - 0: non-force, adaptive algorithm notices it (default);
+ * - 1: force send, adaptive algorithm notices it;
+ * - 2: non-force, adaptive algorithm does not notice the send.
+ * @return Number of transactions polled.
+ */
+ int sendPollNdb(int aMillisecondNumber = WAITFOR_RESPONSE_TIMEOUT,
+ int minNoOfEventsToWakeup = 1,
+ int forceSend = 0);
+ /** @} *********************************************************************/
+#endif
+
+ /**
+ * @name Error Handling
+ * @{
+ */
+
+ /**
+ * Get the NdbError object
+ *
+ * @note The NdbError object is valid until a new NDB API method is called.
+ */
+ const NdbError & getNdbError() const;
+
+ /**
+ * Get a NdbError object for a specific error code
+ *
+ * The NdbError object is valid until you call a new NDB API method.
+ */
+ const NdbError & getNdbError(int errorCode);
+
+
+ /** @} *********************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Get the application node identity.
+ *
+ * @return Node id of this application.
+ */
+ int getNodeId();
+
+ bool usingFullyQualifiedNames();
+
+ /**
+ * Different types of tampering with the NDB Cluster.
+ * <b>Only for debugging purposes only.</b>
+ */
+ enum TamperType {
+ LockGlbChp = 1, ///< Lock GCP
+ UnlockGlbChp, ///< Unlock GCP
+ CrashNode, ///< Crash an NDB node
+ ReadRestartGCI, ///< Request the restart GCI id from NDB Cluster
+ InsertError ///< Execute an error in NDB Cluster
+ ///< (may crash system)
+ };
+
+ /**
+ * For testing purposes it is possible to tamper with the NDB Cluster
+ * (i.e. send a special signal to DBDIH, the NDB distribution handler).
+ * <b>This feature should only used for debugging purposes.</b>
+ * In a release versions of NDB Cluster,
+ * this call always return -1 and does nothing.
+ *
+ * @param aAction Action to be taken according to TamperType above
+ *
+ * @param aNode Which node the action will be taken
+ * -1: Master DIH.
+ * 0-16: Nodnumber.
+ * @return -1 indicates error, other values have meaning dependent
+ * on type of tampering.
+ */
+ int NdbTamper(TamperType aAction, int aNode);
+
+ /**
+ * Return a unique tuple id for a table. The id sequence is
+ * ascending but may contain gaps. Methods which have no
+ * TupleIdRange argument use NDB API dict cache. They may
+ * not be called from mysqld.
+ *
+ * @param aTableName table name
+ *
+ * @param cacheSize number of values to cache in this Ndb object
+ *
+ * @return 0 or -1 on error, and tupleId in out parameter
+ */
+ struct TupleIdRange {
+ TupleIdRange() {}
+ Uint64 m_first_tuple_id;
+ Uint64 m_last_tuple_id;
+ void reset() {
+ m_first_tuple_id = ~(Uint64)0;
+ m_last_tuple_id = ~(Uint64)0;
+ };
+ };
+
+ int initAutoIncrement();
+
+ int getAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId, Uint32 cacheSize);
+ int getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId, Uint32 cacheSize);
+ int getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId,
+ Uint32 cacheSize);
+ int readAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId);
+ int readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId);
+ int readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 & tupleId);
+ int setAutoIncrementValue(const char* aTableName,
+ Uint64 tupleId, bool increase);
+ int setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 tupleId, bool increase);
+ int setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ TupleIdRange & range, Uint64 tupleId,
+ bool increase);
+private:
+ int getTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId,
+ Uint32 cacheSize);
+ int readTupleIdFromNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & tupleId);
+ int setTupleIdInNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 tupleId, bool increase);
+ int opTupleIdOnNdb(const NdbTableImpl* table,
+ TupleIdRange & range, Uint64 & opValue, Uint32 op);
+public:
+
+ /**
+ */
+ NdbTransaction* hupp( NdbTransaction* );
+ Uint32 getReference() const { return theMyRef;}
+
+ struct Free_list_usage
+ {
+ const char * m_name;
+ Uint32 m_created;
+ Uint32 m_free;
+ Uint32 m_sizeof;
+ };
+
+ Free_list_usage * get_free_list_usage(Free_list_usage*);
+#endif
+
+
+
+/*****************************************************************************
+ * These are service routines used by the other classes in the NDBAPI.
+ ****************************************************************************/
+ Uint32 get_cond_wait_index() { return cond_wait_index; }
+ void set_cond_wait_index(Uint32 index) { cond_wait_index = index; }
+private:
+ Uint32 cond_wait_index;
+ Ndb *cond_signal_ndb;
+ void cond_signal();
+
+ void setup(Ndb_cluster_connection *ndb_cluster_connection,
+ const char* aCatalogName, const char* aSchemaName);
+
+ void connected(Uint32 block_reference);
+ void report_node_connected(Uint32 nodeId);
+
+
+ NdbTransaction* startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId);
+
+// Connect the connection object to the Database.
+ int NDB_connect(Uint32 tNode);
+ NdbTransaction* doConnect(Uint32 nodeId);
+ void doDisconnect();
+
+ NdbReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list
+ NdbLabel* getNdbLabel(); // Get a NdbLabel from idle list
+ NdbBranch* getNdbBranch(); // Get a NdbBranch from idle list
+ NdbSubroutine* getNdbSubroutine();// Get a NdbSubroutine from idle
+ NdbCall* getNdbCall(); // Get a NdbCall from idle list
+ NdbApiSignal* getSignal(); // Get an operation from idle list
+ NdbRecAttr* getRecAttr(); // Get a receeive attribute object from
+ // idle list of the Ndb object.
+ NdbOperation* getOperation(); // Get an operation from idle list
+ NdbIndexScanOperation* getScanOperation(); // Get a scan operation from idle
+ NdbIndexOperation* getIndexOperation();// Get an index operation from idle
+
+ NdbBlob* getNdbBlob();// Get a blob handle etc
+
+ void releaseSignal(NdbApiSignal* anApiSignal);
+ void releaseSignalsInList(NdbApiSignal** pList);
+ void releaseNdbScanRec(NdbReceiver* aNdbScanRec);
+ void releaseNdbLabel(NdbLabel* anNdbLabel);
+ void releaseNdbBranch(NdbBranch* anNdbBranch);
+ void releaseNdbSubroutine(NdbSubroutine* anNdbSubroutine);
+ void releaseNdbCall(NdbCall* anNdbCall);
+ void releaseRecAttr (NdbRecAttr* aRecAttr);
+ void releaseOperation(NdbOperation* anOperation);
+ void releaseScanOperation(NdbIndexScanOperation*);
+ void releaseNdbBlob(NdbBlob* aBlob);
+
+ void check_send_timeout();
+ void remove_sent_list(Uint32);
+ Uint32 insert_completed_list(NdbTransaction*);
+ Uint32 insert_sent_list(NdbTransaction*);
+
+ // Handle a received signal. Used by both
+ // synchronous and asynchronous interface
+ void handleReceivedSignal(NdbApiSignal* anApiSignal, struct LinearSectionPtr ptr[3]);
+
+ int sendRecSignal(Uint16 aNodeId,
+ Uint32 aWaitState,
+ NdbApiSignal* aSignal,
+ Uint32 nodeSequence,
+ Uint32 *ret_conn_seq= 0);
+
+ // Sets Restart GCI in Ndb object
+ void RestartGCI(int aRestartGCI);
+
+ // Get block number of this NDBAPI object
+ int getBlockNumber();
+
+ /****************************************************************************
+ * These are local service routines used by this class.
+ ***************************************************************************/
+
+ int createConIdleList(int aNrOfCon);
+ int createOpIdleList( int nrOfOp );
+
+ void freeOperation(); // Free the first idle operation.
+ void freeScanOperation(); // Free the first idle scan operation.
+ void freeIndexOperation(); // Free the first idle index operation.
+ void freeNdbCon(); // Free the first idle connection.
+ void freeSignal(); // Free the first idle signal
+ void freeRecAttr(); // Free the first idle receive attr obj
+ void freeNdbLabel(); // Free the first idle NdbLabel obj
+ void freeNdbBranch();// Free the first idle NdbBranch obj
+ void freeNdbSubroutine();// Free the first idle NdbSubroutine obj
+ void freeNdbCall(); // Free the first idle NdbCall obj
+ void freeNdbScanRec(); // Free the first idle NdbScanRec obj
+ void freeNdbBlob(); // Free the first etc
+
+ NdbTransaction* getNdbCon(); // Get a connection from idle list
+
+ /**
+ * Get a connected NdbTransaction to nodeId
+ * Returns NULL if none found
+ */
+ NdbTransaction* getConnectedNdbTransaction(Uint32 nodeId);
+
+ // Release and disconnect from DBTC a connection
+ // and seize it to theConIdleList
+ void releaseConnectToNdb (NdbTransaction*);
+
+ // Release a connection to idle list
+ void releaseNdbCon (NdbTransaction*);
+
+ int checkInitState(); // Check that we are initialized
+ void report_node_failure(Uint32 node_id); // Report Failed node
+ void report_node_failure_completed(Uint32 node_id); // Report Failed node(NF comp.)
+
+ void checkFailedNode(); // Check for failed nodes
+
+ int NDB_connect(); // Perform connect towards NDB Kernel
+
+ // Release arrays of NdbTransaction pointers
+ void releaseTransactionArrays();
+
+ Uint32 pollCompleted(NdbTransaction** aCopyArray);
+ void sendPrepTrans(int forceSend);
+ void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfComplTrans);
+ int poll_trans(int milliSecs, int noOfEventsToWaitFor, PollGuard *pg);
+ void waitCompletedTransactions(int milliSecs, int noOfEventsToWaitFor,
+ PollGuard *pg);
+ void completedTransaction(NdbTransaction* aTransaction);
+ void completedScanTransaction(NdbTransaction* aTransaction);
+
+ void abortTransactionsAfterNodeFailure(Uint16 aNodeId);
+
+ static
+ const char * externalizeTableName(const char * internalTableName,
+ bool fullyQualifiedNames);
+ const char * externalizeTableName(const char * internalTableName);
+ const BaseString internalize_table_name(const char * external_name) const;
+
+ static
+ const char * externalizeIndexName(const char * internalIndexName,
+ bool fullyQualifiedNames);
+ const char * externalizeIndexName(const char * internalIndexName);
+ const BaseString old_internalize_index_name(const NdbTableImpl * table,
+ const char * external_name) const;
+ const BaseString internalize_index_name(const NdbTableImpl * table,
+ const char * external_name) const;
+
+ static
+ const BaseString getDatabaseFromInternalName(const char * internalName);
+ static
+ const BaseString getSchemaFromInternalName(const char * internalName);
+
+ void* int2void (Uint32 val);
+ NdbReceiver* void2rec (void* val);
+ NdbTransaction* void2con (void* val);
+ NdbOperation* void2rec_op (void* val);
+ NdbIndexOperation* void2rec_iop (void* val);
+
+/******************************************************************************
+ * These are the private variables in this class.
+ *****************************************************************************/
+ NdbTransaction** thePreparedTransactionsArray;
+ NdbTransaction** theSentTransactionsArray;
+ NdbTransaction** theCompletedTransactionsArray;
+
+ Uint32 theNoOfPreparedTransactions;
+ Uint32 theNoOfSentTransactions;
+ Uint32 theNoOfCompletedTransactions;
+ Uint32 theRemainingStartTransactions;
+ Uint32 theMaxNoOfTransactions;
+ Uint32 theMinNoOfEventsToWakeUp;
+
+ Uint32 theNextConnectNode;
+
+ bool fullyQualifiedNames;
+
+
+
+ class NdbImpl * theImpl;
+ class NdbDictionaryImpl* theDictionary;
+ class NdbEventBuffer* theEventBuffer;
+
+ NdbTransaction* theTransactionList;
+ NdbTransaction** theConnectionArray;
+
+ Uint32 theMyRef; // My block reference
+ Uint32 theNode; // The node number of our node
+
+ Uint64 the_last_check_time;
+ Uint64 theFirstTransId;
+ // The tupleId is retrieved from DB
+ const NdbDictionary::Table *m_sys_tab_0;
+
+ Uint32 theRestartGCI; // the Restart GCI used by DIHNDBTAMPER
+
+ NdbError theError;
+
+ Int32 theNdbBlockNumber;
+
+ enum InitType {
+ NotConstructed,
+ NotInitialised,
+ StartingInit,
+ Initialised,
+ InitConfigError
+ } theInitState;
+
+ NdbApiSignal* theCommitAckSignal;
+
+
+#ifdef POORMANSPURIFY
+ int cfreeSignals;
+ int cnewSignals;
+ int cgetSignals;
+ int creleaseSignals;
+#endif
+
+ static void executeMessage(void*, NdbApiSignal *,
+ struct LinearSectionPtr ptr[3]);
+ static void statusMessage(void*, Uint32, bool, bool);
+#ifdef VM_TRACE
+ void printState(const char* fmt, ...);
+#endif
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbApi.hpp b/storage/ndb/include/ndbapi/NdbApi.hpp
new file mode 100644
index 00000000000..aed4d5efbd7
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbApi.hpp
@@ -0,0 +1,35 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbApi_H
+#define NdbApi_H
+
+#include "ndb_init.h"
+#include "ndb_cluster_connection.hpp"
+#include "ndbapi_limits.h"
+#include "Ndb.hpp"
+#include "NdbTransaction.hpp"
+#include "NdbOperation.hpp"
+#include "NdbScanOperation.hpp"
+#include "NdbIndexOperation.hpp"
+#include "NdbIndexScanOperation.hpp"
+#include "NdbScanFilter.hpp"
+#include "NdbRecAttr.hpp"
+#include "NdbDictionary.hpp"
+#include "NdbEventOperation.hpp"
+#include "NdbPool.hpp"
+#include "NdbBlob.hpp"
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp
new file mode 100644
index 00000000000..e8944d684d3
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp
@@ -0,0 +1,410 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbBlob_H
+#define NdbBlob_H
+
+#include <ndb_types.h>
+#include <NdbDictionary.hpp>
+#include <NdbTransaction.hpp>
+#include <NdbError.hpp>
+
+class Ndb;
+class NdbTransaction;
+class NdbOperation;
+class NdbRecAttr;
+class NdbTableImpl;
+class NdbColumnImpl;
+class NdbEventOperationImpl;
+
+/**
+ * @class NdbBlob
+ * @brief Blob handle
+ *
+ * Blob data is stored in 2 places:
+ *
+ * - "header" and "inline bytes" stored in the blob attribute
+ * - "blob parts" stored in a separate table NDB$BLOB_<tid>_<cid>
+ *
+ * Inline and part sizes can be set via NdbDictionary::Column methods
+ * when the table is created.
+ *
+ * NdbBlob is a blob handle. To access blob data, the handle must be
+ * created using NdbOperation::getBlobHandle in operation prepare phase.
+ * The handle has following states:
+ *
+ * - prepared: before the operation is executed
+ * - active: after execute or next result but before transaction commit
+ * - closed: after transaction commit
+ * - invalid: after rollback or transaction close
+ *
+ * NdbBlob supports 3 styles of data access:
+ *
+ * - in prepare phase, NdbBlob methods getValue and setValue are used to
+ * prepare a read or write of a blob value of known size
+ *
+ * - in prepare phase, setActiveHook is used to define a routine which
+ * is invoked as soon as the handle becomes active
+ *
+ * - in active phase, readData and writeData are used to read or write
+ * blob data of arbitrary size
+ *
+ * The styles can be applied in combination (in above order).
+ *
+ * Blob operations take effect at next transaction execute. In some
+ * cases NdbBlob is forced to do implicit executes. To avoid this,
+ * operate on complete blob parts.
+ *
+ * Use NdbTransaction::executePendingBlobOps to flush your reads and
+ * writes. It avoids execute penalty if nothing is pending. It is not
+ * needed after execute (obviously) or after next scan result.
+ *
+ * NdbBlob also supports reading post or pre blob data from events. The
+ * handle can be read after next event on main table has been retrieved.
+ * The data is available immediately. See NdbEventOperation.
+ *
+ * Non-void NdbBlob methods return -1 on error and 0 on success. Output
+ * parameters are used when necessary.
+ *
+ * Usage notes for different operation types:
+ *
+ * - insertTuple must use setValue if blob attribute is non-nullable
+ *
+ * - readTuple or scan readTuples with lock mode LM_CommittedRead is
+ * automatically upgraded to lock mode LM_Read if any blob attributes
+ * are accessed (to guarantee consistent view)
+ *
+ * - readTuple (with any lock mode) can only read blob value
+ *
+ * - updateTuple can either overwrite existing value with setValue or
+ * update it in active phase
+ *
+ * - writeTuple always overwrites blob value and must use setValue if
+ * blob attribute is non-nullable
+ *
+ * - deleteTuple creates implicit non-accessible blob handles
+ *
+ * - scan readTuples (any lock mode) can use its blob handles only
+ * to read blob value
+ *
+ * - scan readTuples with lock mode LM_Exclusive can update row and blob
+ * value using updateCurrentTuple, where the operation returned must
+ * create its own blob handles explicitly
+ *
+ * - scan readTuples with lock mode LM_Exclusive can delete row (and
+ * therefore blob values) using deleteCurrentTuple, which creates
+ * implicit non-accessible blob handles
+ *
+ * - the operation returned by lockCurrentTuple cannot update blob value
+ *
+ * Bugs / limitations:
+ *
+ * - too many pending blob ops can blow up i/o buffers
+ *
+ * - table and its blob part tables are not created atomically
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ * - there is no support for an asynchronous interface
+ */
+#endif
+
+class NdbBlob {
+public:
+ /**
+ * State.
+ */
+ enum State {
+ Idle = 0,
+ Prepared = 1,
+ Active = 2,
+ Closed = 3,
+ Invalid = 9
+ };
+ /**
+ * Get the state of a NdbBlob object.
+ */
+ State getState();
+ /**
+ * Returns -1 for normal statement based blob and 0/1 for event
+ * operation post/pre data blob. Always succeeds.
+ */
+ void getVersion(int& version);
+ /**
+ * Inline blob header.
+ */
+ struct Head {
+ Uint64 length;
+ };
+ /**
+ * Prepare to read blob value. The value is available after execute.
+ * Use getNull() to check for NULL and getLength() to get the real length
+ * and to check for truncation. Sets current read/write position to
+ * after the data read.
+ */
+ int getValue(void* data, Uint32 bytes);
+ /**
+ * Prepare to insert or update blob value. An existing longer blob
+ * value will be truncated. The data buffer must remain valid until
+ * execute. Sets current read/write position to after the data. Set
+ * data to null pointer (0) to create a NULL value.
+ */
+ int setValue(const void* data, Uint32 bytes);
+ /**
+ * Callback for setActiveHook(). Invoked immediately when the prepared
+ * operation has been executed (but not committed). Any getValue() or
+ * setValue() is done first. The blob handle is active so readData or
+ * writeData() etc can be used to manipulate blob value. A user-defined
+ * argument is passed along. Returns non-zero on error.
+ */
+ typedef int ActiveHook(NdbBlob* me, void* arg);
+ /**
+ * Define callback for blob handle activation. The queue of prepared
+ * operations will be executed in no commit mode up to this point and
+ * then the callback is invoked.
+ */
+ int setActiveHook(ActiveHook* activeHook, void* arg);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int getDefined(int& isNull);
+ int getNull(bool& isNull);
+#endif
+ /**
+ * Return -1, 0, 1 if blob is undefined, non-null, or null. For
+ * non-event blob, undefined causes a state error.
+ */
+ int getNull(int& isNull);
+ /**
+ * Set blob to NULL.
+ */
+ int setNull();
+ /**
+ * Get current length in bytes. Use getNull to distinguish between
+ * length 0 blob and NULL blob.
+ */
+ int getLength(Uint64& length);
+ /**
+ * Truncate blob to given length. Has no effect if the length is
+ * larger than current length.
+ */
+ int truncate(Uint64 length = 0);
+ /**
+ * Get current read/write position.
+ */
+ int getPos(Uint64& pos);
+ /**
+ * Set read/write position. Must be between 0 and current length.
+ * "Sparse blobs" are not supported.
+ */
+ int setPos(Uint64 pos);
+ /**
+ * Read at current position and set new position to first byte after
+ * the data read. A read past blob end returns actual number of bytes
+ * read in the in/out bytes parameter.
+ */
+ int readData(void* data, Uint32& bytes);
+ /**
+ * Write at current position and set new position to first byte after
+ * the data written. A write past blob end extends the blob value.
+ */
+ int writeData(const void* data, Uint32 bytes);
+ /**
+ * Return the blob column.
+ */
+ const NdbDictionary::Column* getColumn();
+ /**
+ * Get blob parts table name. Useful only to test programs.
+ */
+ static int getBlobTableName(char* btname, Ndb* anNdb, const char* tableName, const char* columnName);
+ /**
+ * Get blob event name. The blob event is created if the main event
+ * monitors the blob column. The name includes main event name.
+ */
+ static int getBlobEventName(char* bename, Ndb* anNdb, const char* eventName, const char* columnName);
+ /**
+ * Return error object. The error may be blob specific or may be
+ * copied from a failed implicit operation.
+ *
+ * The error code is copied back to the operation unless the operation
+ * already has a non-zero error code.
+ */
+ const NdbError& getNdbError() const;
+ /**
+ * Return info about all blobs in this operation.
+ *
+ * Get first blob in list.
+ */
+ NdbBlob* blobsFirstBlob();
+ /**
+ * Return info about all blobs in this operation.
+ *
+ * Get next blob in list. Initialize with blobsFirstBlob().
+ */
+ NdbBlob* blobsNextBlob();
+
+private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbTransaction;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbDictionaryImpl;
+ friend class NdbResultSet; // atNextResult
+ friend class NdbEventBuffer;
+ friend class NdbEventOperationImpl;
+#endif
+ // state
+ State theState;
+ void setState(State newState);
+ // quick and dirty support for events (consider subclassing)
+ int theEventBlobVersion; // -1=normal blob 0=post event 1=pre event
+ // define blob table
+ static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c);
+ static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c);
+ static void getBlobEventName(char* bename, const NdbEventImpl* e, const NdbColumnImpl* c);
+ static void getBlobEvent(NdbEventImpl& be, const NdbEventImpl* e, const NdbColumnImpl* c);
+ // ndb api stuff
+ Ndb* theNdb;
+ NdbTransaction* theNdbCon;
+ NdbOperation* theNdbOp;
+ NdbEventOperationImpl* theEventOp;
+ NdbEventOperationImpl* theBlobEventOp;
+ NdbRecAttr* theBlobEventPkRecAttr;
+ NdbRecAttr* theBlobEventDistRecAttr;
+ NdbRecAttr* theBlobEventPartRecAttr;
+ NdbRecAttr* theBlobEventDataRecAttr;
+ const NdbTableImpl* theTable;
+ const NdbTableImpl* theAccessTable;
+ const NdbTableImpl* theBlobTable;
+ const NdbColumnImpl* theColumn;
+ char theFillChar;
+ // sizes
+ Uint32 theInlineSize;
+ Uint32 thePartSize;
+ Uint32 theStripeSize;
+ // getValue/setValue
+ bool theGetFlag;
+ char* theGetBuf;
+ bool theSetFlag;
+ const char* theSetBuf;
+ Uint32 theGetSetBytes;
+ // pending ops
+ Uint8 thePendingBlobOps;
+ // activation callback
+ ActiveHook* theActiveHook;
+ void* theActiveHookArg;
+ // buffers
+ struct Buf {
+ char* data;
+ unsigned size;
+ unsigned maxsize;
+ Buf();
+ ~Buf();
+ void alloc(unsigned n);
+ void zerorest();
+ void copyfrom(const Buf& src);
+ };
+ Buf theKeyBuf;
+ Buf theAccessKeyBuf;
+ Buf thePackKeyBuf;
+ Buf theHeadInlineBuf;
+ Buf theHeadInlineCopyBuf; // for writeTuple
+ Buf thePartBuf;
+ Buf theBlobEventDataBuf;
+ Uint32 thePartNumber; // for event
+ Head* theHead;
+ char* theInlineData;
+ NdbRecAttr* theHeadInlineRecAttr;
+ NdbOperation* theHeadInlineReadOp;
+ bool theHeadInlineUpdateFlag;
+ // length and read/write position
+ int theNullFlag;
+ Uint64 theLength;
+ Uint64 thePos;
+ // errors
+ NdbError theError;
+ // for keeping in lists
+ NdbBlob* theNext;
+ // initialization
+ NdbBlob(Ndb*);
+ void init();
+ void release();
+ // classify operations
+ bool isTableOp();
+ bool isIndexOp();
+ bool isKeyOp();
+ bool isReadOp();
+ bool isInsertOp();
+ bool isUpdateOp();
+ bool isWriteOp();
+ bool isDeleteOp();
+ bool isScanOp();
+ bool isReadOnlyOp();
+ bool isTakeOverOp();
+ // computations
+ Uint32 getPartNumber(Uint64 pos);
+ Uint32 getPartCount();
+ Uint32 getDistKey(Uint32 part);
+ // pack / unpack
+ int packKeyValue(const NdbTableImpl* aTable, const Buf& srcBuf);
+ int unpackKeyValue(const NdbTableImpl* aTable, Buf& dstBuf);
+ // getters and setters
+ int getTableKeyValue(NdbOperation* anOp);
+ int setTableKeyValue(NdbOperation* anOp);
+ int setAccessKeyValue(NdbOperation* anOp);
+ int setPartKeyValue(NdbOperation* anOp, Uint32 part);
+ int getHeadInlineValue(NdbOperation* anOp);
+ void getHeadFromRecAttr();
+ int setHeadInlineValue(NdbOperation* anOp);
+ // data operations
+ int readDataPrivate(char* buf, Uint32& bytes);
+ int writeDataPrivate(const char* buf, Uint32 bytes);
+ int readParts(char* buf, Uint32 part, Uint32 count);
+ int readTableParts(char* buf, Uint32 part, Uint32 count);
+ int readEventParts(char* buf, Uint32 part, Uint32 count);
+ int insertParts(const char* buf, Uint32 part, Uint32 count);
+ int updateParts(const char* buf, Uint32 part, Uint32 count);
+ int deleteParts(Uint32 part, Uint32 count);
+ int deletePartsUnknown(Uint32 part);
+ // pending ops
+ int executePendingBlobReads();
+ int executePendingBlobWrites();
+ // callbacks
+ int invokeActiveHook();
+ // blob handle maintenance
+ int atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
+ int atPrepare(NdbEventOperationImpl* anOp, NdbEventOperationImpl* aBlobOp, const NdbColumnImpl* aColumn, int version);
+ int prepareColumn();
+ int preExecute(NdbTransaction::ExecType anExecType, bool& batch);
+ int postExecute(NdbTransaction::ExecType anExecType);
+ int preCommit();
+ int atNextResult();
+ int atNextEvent();
+ // errors
+ void setErrorCode(int anErrorCode, bool invalidFlag = false);
+ void setErrorCode(NdbOperation* anOp, bool invalidFlag = false);
+ void setErrorCode(NdbTransaction* aCon, bool invalidFlag = false);
+ void setErrorCode(NdbEventOperationImpl* anOp, bool invalidFlag = false);
+#ifdef VM_TRACE
+ int getOperationType() const;
+ friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
+#endif
+ // list stuff
+ void next(NdbBlob* obj) { theNext= obj;}
+ NdbBlob* next() { return theNext;}
+ friend struct Ndb_free_list_t<NdbBlob>;
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp
new file mode 100644
index 00000000000..8d9ade2fb84
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp
@@ -0,0 +1,1918 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbDictionary_H
+#define NdbDictionary_H
+
+#include <ndb_types.h>
+
+class Ndb;
+struct charset_info_st;
+typedef struct charset_info_st CHARSET_INFO;
+
+/**
+ * @class NdbDictionary
+ * @brief Data dictionary class
+ *
+ * The preferred and supported way to create and drop tables and indexes
+ * in ndb is through the
+ * MySQL Server (see MySQL reference Manual, section MySQL Cluster).
+ *
+ * Tables and indexes that are created directly through the
+ * NdbDictionary class
+ * can not be viewed from the MySQL Server.
+ * Dropping indexes directly via the NdbApi will cause inconsistencies
+ * if they were originally created from a MySQL Cluster.
+ *
+ * This class supports schema data enquiries such as:
+ * -# Enquiries about tables
+ * (Dictionary::getTable, Table::getNoOfColumns,
+ * Table::getPrimaryKey, and Table::getNoOfPrimaryKeys)
+ * -# Enquiries about indexes
+ * (Dictionary::getIndex, Index::getNoOfColumns,
+ * and Index::getColumn)
+ *
+ * This class supports schema data definition such as:
+ * -# Creating tables (Dictionary::createTable) and table columns
+ * -# Dropping tables (Dictionary::dropTable)
+ * -# Creating secondary indexes (Dictionary::createIndex)
+ * -# Dropping secondary indexes (Dictionary::dropIndex)
+ *
+ * NdbDictionary has several help (inner) classes to support this:
+ * -# NdbDictionary::Dictionary the dictionary handling dictionary objects
+ * -# NdbDictionary::Table for creating tables
+ * -# NdbDictionary::Column for creating table columns
+ * -# NdbDictionary::Index for creating secondary indexes
+ *
+ * See @ref ndbapi_simple_index.cpp for details of usage.
+ */
+class NdbDictionary {
+public:
+ NdbDictionary() {} /* Remove gcc warning */
+ /**
+ * @class Object
+ * @brief Meta information about a database object (a table, index, etc)
+ */
+ class Object {
+ public:
+ Object() {} /* Remove gcc warning */
+ virtual ~Object() {} /* Remove gcc warning */
+ /**
+ * Status of object
+ */
+ enum Status {
+ New, ///< The object only exist in memory and
+ ///< has not been created in the NDB Kernel
+ Changed, ///< The object has been modified in memory
+ ///< and has to be commited in NDB Kernel for
+ ///< changes to take effect
+ Retrieved, ///< The object exist and has been read
+ ///< into main memory from NDB Kernel
+ Invalid, ///< The object has been invalidated
+ ///< and should not be used
+ Altered ///< Table has been altered in NDB kernel
+ ///< but is still valid for usage
+ };
+
+ /**
+ * Get status of object
+ */
+ virtual Status getObjectStatus() const = 0;
+
+ /**
+ * Get version of object
+ */
+ virtual int getObjectVersion() const = 0;
+
+ virtual int getObjectId() const = 0;
+
+ /**
+ * Object type
+ */
+ enum Type {
+ TypeUndefined = 0, ///< Undefined
+ SystemTable = 1, ///< System table
+ UserTable = 2, ///< User table (may be temporary)
+ UniqueHashIndex = 3, ///< Unique un-ordered hash index
+ OrderedIndex = 6, ///< Non-unique ordered index
+ HashIndexTrigger = 7, ///< Index maintenance, internal
+ IndexTrigger = 8, ///< Index maintenance, internal
+ SubscriptionTrigger = 9,///< Backup or replication, internal
+ ReadOnlyConstraint = 10,///< Trigger, internal
+ Tablespace = 20, ///< Tablespace
+ LogfileGroup = 21, ///< Logfile group
+ Datafile = 22, ///< Datafile
+ Undofile = 23 ///< Undofile
+ };
+
+ /**
+ * Object state
+ */
+ enum State {
+ StateUndefined = 0, ///< Undefined
+ StateOffline = 1, ///< Offline, not usable
+ StateBuilding = 2, ///< Building, not yet usable
+ StateDropping = 3, ///< Offlining or dropping, not usable
+ StateOnline = 4, ///< Online, usable
+ StateBackup = 5, ///< Online, being backuped, usable
+ StateBroken = 9 ///< Broken, should be dropped and re-created
+ };
+
+ /**
+ * Object store
+ */
+ enum Store {
+ StoreUndefined = 0, ///< Undefined
+ StoreNotLogged = 1, ///< Object or data deleted on system restart
+ StorePermanent = 2 ///< Permanent. logged to disk
+ };
+
+ /**
+ * Type of fragmentation.
+ *
+ * This parameter specifies how data in the table or index will
+ * be distributed among the db nodes in the cluster.<br>
+ * The bigger the table the more number of fragments should be used.
+ * Note that all replicas count as same "fragment".<br>
+ * For a table, default is FragAllMedium. For a unique hash index,
+ * default is taken from underlying table and cannot currently
+ * be changed.
+ */
+ enum FragmentType {
+ FragUndefined = 0, ///< Fragmentation type undefined or default
+ FragSingle = 1, ///< Only one fragment
+ FragAllSmall = 2, ///< One fragment per node, default
+ FragAllMedium = 3, ///< two fragments per node
+ FragAllLarge = 4, ///< Four fragments per node.
+ DistrKeyHash = 5,
+ DistrKeyLin = 6,
+ UserDefined = 7
+ };
+ };
+
+ class Dictionary; // Forward declaration
+
+ class ObjectId : public Object
+ {
+ public:
+ ObjectId();
+ virtual ~ObjectId();
+
+ /**
+ * Get status of object
+ */
+ virtual Status getObjectStatus() const;
+
+ /**
+ * Get version of object
+ */
+ virtual int getObjectVersion() const;
+
+ virtual int getObjectId() const;
+
+ private:
+ friend class NdbDictObjectImpl;
+ class NdbDictObjectImpl & m_impl;
+ };
+
+ class Table; // forward declaration
+ class Tablespace; // forward declaration
+// class NdbEventOperation; // forward declaration
+
+ /**
+ * @class Column
+ * @brief Represents a column in an NDB Cluster table
+ *
+ * Each column has a type. The type of a column is determined by a number
+ * of type specifiers.
+ * The type specifiers are:
+ * - Builtin type
+ * - Array length or max length
+ * - Precision and scale (not used yet)
+ * - Character set for string types
+ * - Inline and part sizes for blobs
+ *
+ * Types in general correspond to MySQL types and their variants.
+ * Data formats are same as in MySQL. NDB API provides no support for
+ * constructing such formats. NDB kernel checks them however.
+ */
+ class Column {
+ public:
+ /**
+ * The builtin column types
+ */
+ enum Type {
+ Undefined = NDB_TYPE_UNDEFINED, ///< Undefined
+ Tinyint = NDB_TYPE_TINYINT, ///< 8 bit. 1 byte signed integer, can be used in array
+ Tinyunsigned = NDB_TYPE_TINYUNSIGNED, ///< 8 bit. 1 byte unsigned integer, can be used in array
+ Smallint = NDB_TYPE_SMALLINT, ///< 16 bit. 2 byte signed integer, can be used in array
+ Smallunsigned = NDB_TYPE_SMALLUNSIGNED, ///< 16 bit. 2 byte unsigned integer, can be used in array
+ Mediumint = NDB_TYPE_MEDIUMINT, ///< 24 bit. 3 byte signed integer, can be used in array
+ Mediumunsigned = NDB_TYPE_MEDIUMUNSIGNED,///< 24 bit. 3 byte unsigned integer, can be used in array
+ Int = NDB_TYPE_INT, ///< 32 bit. 4 byte signed integer, can be used in array
+ Unsigned = NDB_TYPE_UNSIGNED, ///< 32 bit. 4 byte unsigned integer, can be used in array
+ Bigint = NDB_TYPE_BIGINT, ///< 64 bit. 8 byte signed integer, can be used in array
+ Bigunsigned = NDB_TYPE_BIGUNSIGNED, ///< 64 Bit. 8 byte signed integer, can be used in array
+ Float = NDB_TYPE_FLOAT, ///< 32-bit float. 4 bytes float, can be used in array
+ Double = NDB_TYPE_DOUBLE, ///< 64-bit float. 8 byte float, can be used in array
+ Olddecimal = NDB_TYPE_OLDDECIMAL, ///< MySQL < 5.0 signed decimal, Precision, Scale
+ Olddecimalunsigned = NDB_TYPE_OLDDECIMALUNSIGNED,
+ Decimal = NDB_TYPE_DECIMAL, ///< MySQL >= 5.0 signed decimal, Precision, Scale
+ Decimalunsigned = NDB_TYPE_DECIMALUNSIGNED,
+ Char = NDB_TYPE_CHAR, ///< Len. A fixed array of 1-byte chars
+ Varchar = NDB_TYPE_VARCHAR, ///< Length bytes: 1, Max: 255
+ Binary = NDB_TYPE_BINARY, ///< Len
+ Varbinary = NDB_TYPE_VARBINARY, ///< Length bytes: 1, Max: 255
+ Datetime = NDB_TYPE_DATETIME, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
+ Date = NDB_TYPE_DATE, ///< Precision down to 1 day(sizeof(Date) == 4 bytes )
+ Blob = NDB_TYPE_BLOB, ///< Binary large object (see NdbBlob)
+ Text = NDB_TYPE_TEXT, ///< Text blob
+ Bit = NDB_TYPE_BIT, ///< Bit, length specifies no of bits
+ Longvarchar = NDB_TYPE_LONGVARCHAR, ///< Length bytes: 2, little-endian
+ Longvarbinary = NDB_TYPE_LONGVARBINARY, ///< Length bytes: 2, little-endian
+ Time = NDB_TYPE_TIME, ///< Time without date
+ Year = NDB_TYPE_YEAR, ///< Year 1901-2155 (1 byte)
+ Timestamp = NDB_TYPE_TIMESTAMP ///< Unix time
+ };
+
+ /*
+ * Array type specifies internal attribute format.
+ *
+ * - ArrayTypeFixed is stored as fixed number of bytes. This type
+ * is fastest to access but can waste space.
+ *
+ * - ArrayTypeVar is stored as variable number of bytes with a fixed
+ * overhead of 2 bytes.
+ *
+ * Default is ArrayTypeVar for Var* types and ArrayTypeFixed for
+ * others. The default is normally ok.
+ */
+ enum ArrayType {
+ ArrayTypeFixed = NDB_ARRAYTYPE_FIXED, // 0 length bytes
+ ArrayTypeShortVar = NDB_ARRAYTYPE_SHORT_VAR, // 1 length bytes
+ ArrayTypeMediumVar = NDB_ARRAYTYPE_MEDIUM_VAR // 2 length bytes
+ };
+
+ /*
+ * Storage type specifies whether attribute is stored in memory or
+ * on disk. Default is memory. Disk attributes are potentially
+ * much slower to access and cannot be indexed in version 5.1.
+ */
+ enum StorageType {
+ StorageTypeMemory = NDB_STORAGETYPE_MEMORY,
+ StorageTypeDisk = NDB_STORAGETYPE_DISK
+ };
+
+ /**
+ * @name General
+ * @{
+ */
+
+ /**
+ * Get name of column
+ * @return Name of the column
+ */
+ const char* getName() const;
+
+ /**
+ * Get if the column is nullable or not
+ */
+ bool getNullable() const;
+
+ /**
+ * Check if column is part of primary key
+ */
+ bool getPrimaryKey() const;
+
+ /**
+ * Get number of column (horizontal position within table)
+ */
+ int getColumnNo() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ int getAttrId() const;
+#endif
+
+ /**
+ * Check if column is equal to some other column
+ * @param column Column to compare with
+ * @return true if column is equal to some other column otherwise false.
+ */
+ bool equal(const Column& column) const;
+
+
+ /** @} *******************************************************************/
+ /**
+ * @name Get Type Specifiers
+ * @{
+ */
+
+ /**
+ * Get type of column
+ */
+ Type getType() const;
+
+ /**
+ * Get precision of column.
+ * @note Only applicable for decimal types
+ */
+ int getPrecision() const;
+
+ /**
+ * Get scale of column.
+ * @note Only applicable for decimal types
+ */
+ int getScale() const;
+
+ /**
+ * Get length for column
+ * Array length for column or max length for variable length arrays.
+ */
+ int getLength() const;
+
+ /**
+ * For Char or Varchar or Text, get MySQL CHARSET_INFO. This
+ * specifies both character set and collation. See get_charset()
+ * etc in MySQL. (The cs is not "const" in MySQL).
+ */
+ CHARSET_INFO* getCharset() const;
+
+
+ /**
+ * For blob, get "inline size" i.e. number of initial bytes
+ * to store in table's blob attribute. This part is normally in
+ * main memory and can be indexed and interpreted.
+ */
+ int getInlineSize() const;
+
+ /**
+ * For blob, get "part size" i.e. number of bytes to store in
+ * each tuple of the "blob table". Can be set to zero to omit parts
+ * and to allow only inline bytes ("tinyblob").
+ */
+ int getPartSize() const;
+
+ /**
+ * For blob, set or get "stripe size" i.e. number of consecutive
+ * <em>parts</em> to store in each node group.
+ */
+ int getStripeSize() const;
+
+ /**
+ * Get size of element
+ */
+ int getSize() const;
+
+ /**
+ * Check if column is part of partition key
+ *
+ * A <em>partition key</em> is a set of attributes which are used
+ * to distribute the tuples onto the NDB nodes.
+ * The partition key uses the NDB Cluster hashing function.
+ *
+ * An example where this is useful is TPC-C where it might be
+ * good to use the warehouse id and district id as the partition key.
+ * This would place all data for a specific district and warehouse
+ * in the same database node.
+ *
+ * Locally in the fragments the full primary key
+ * will still be used with the hashing algorithm.
+ *
+ * @return true then the column is part of
+ * the partition key.
+ */
+ bool getPartitionKey() const;
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ inline bool getDistributionKey() const { return getPartitionKey(); };
+#endif
+
+ ArrayType getArrayType() const;
+ StorageType getStorageType() const;
+
+ /** @} *******************************************************************/
+
+
+ /**
+ * @name Column creation
+ * @{
+ *
+ * These operations should normally not be performed in an NbdApi program
+ * as results will not be visable in the MySQL Server
+ *
+ */
+
+ /**
+ * Constructor
+ * @param name Name of column
+ */
+ Column(const char * name = "");
+ /**
+ * Copy constructor
+ * @param column Column to be copied
+ */
+ Column(const Column& column);
+ ~Column();
+
+ /**
+ * Set name of column
+ * @param name Name of the column
+ */
+ void setName(const char * name);
+
+ /**
+ * Set whether column is nullable or not
+ */
+ void setNullable(bool);
+
+ /**
+ * Set that column is part of primary key
+ */
+ void setPrimaryKey(bool);
+
+ /**
+ * Set type of column
+ * @param type Type of column
+ *
+ * @note setType resets <em>all</em> column attributes
+ * to (type dependent) defaults and should be the first
+ * method to call. Default type is Unsigned.
+ */
+ void setType(Type type);
+
+ /**
+ * Set precision of column.
+ * @note Only applicable for decimal types
+ */
+ void setPrecision(int);
+
+ /**
+ * Set scale of column.
+ * @note Only applicable for decimal types
+ */
+ void setScale(int);
+
+ /**
+ * Set length for column
+ * Array length for column or max length for variable length arrays.
+ */
+ void setLength(int length);
+
+ /**
+ * For Char or Varchar or Text, get MySQL CHARSET_INFO. This
+ * specifies both character set and collation. See get_charset()
+ * etc in MySQL. (The cs is not "const" in MySQL).
+ */
+ void setCharset(CHARSET_INFO* cs);
+
+ /**
+ * For blob, get "inline size" i.e. number of initial bytes
+ * to store in table's blob attribute. This part is normally in
+ * main memory and can be indexed and interpreted.
+ */
+ void setInlineSize(int size);
+
+ /**
+ * For blob, get "part size" i.e. number of bytes to store in
+ * each tuple of the "blob table". Can be set to zero to omit parts
+ * and to allow only inline bytes ("tinyblob").
+ */
+ void setPartSize(int size);
+
+ /**
+ * For blob, get "stripe size" i.e. number of consecutive
+ * <em>parts</em> to store in each node group.
+ */
+ void setStripeSize(int size);
+
+ /**
+ * Set partition key
+ * @see getPartitionKey
+ *
+ * @param enable If set to true, then the column will be part of
+ * the partition key.
+ */
+ void setPartitionKey(bool enable);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ inline void setDistributionKey(bool enable)
+ { setPartitionKey(enable); };
+#endif
+
+ void setArrayType(ArrayType type);
+ void setStorageType(StorageType type);
+
+ /** @} *******************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const Table * getBlobTable() const;
+
+ void setAutoIncrement(bool);
+ bool getAutoIncrement() const;
+ void setAutoIncrementInitialValue(Uint64 val);
+ void setDefaultValue(const char*);
+ const char* getDefaultValue() const;
+
+ static const Column * FRAGMENT;
+ static const Column * FRAGMENT_FIXED_MEMORY;
+ static const Column * FRAGMENT_VARSIZED_MEMORY;
+ static const Column * ROW_COUNT;
+ static const Column * COMMIT_COUNT;
+ static const Column * ROW_SIZE;
+ static const Column * RANGE_NO;
+ static const Column * DISK_REF;
+ static const Column * RECORDS_IN_RANGE;
+ static const Column * ROWID;
+ static const Column * ROW_GCI;
+
+ int getSizeInBytes() const;
+#endif
+
+ private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbRecAttr;
+ friend class NdbColumnImpl;
+#endif
+ class NdbColumnImpl & m_impl;
+ Column(NdbColumnImpl&);
+ Column& operator=(const Column&);
+ };
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * ???
+ */
+ typedef Column Attribute;
+#endif
+
+ /**
+ * @brief Represents a table in NDB Cluster
+ *
+ * <em>TableSize</em><br>
+ * When calculating the data storage one should add the size of all
+ * attributes (each attributeconsumes at least 4 bytes) and also an overhead
+ * of 12 byte. Variable size attributes (not supported yet) will have a
+ * size of 12 bytes plus the actual data storage parts where there is an
+ * additional overhead based on the size of the variable part.<br>
+ * An example table with 5 attributes:
+ * one 64 bit attribute, one 32 bit attribute,
+ * two 16 bit attributes and one array of 64 8 bits.
+ * This table will consume
+ * 12 (overhead) + 8 + 4 + 2*4 (4 is minimum) + 64 = 96 bytes per record.
+ * Additionally an overhead of about 2 % as page headers and waste should
+ * be allocated. Thus, 1 million records should consume 96 MBytes
+ * plus the overhead 2 MByte and rounded up to 100 000 kBytes.<br>
+ *
+ */
+ class Table : public Object {
+ public:
+ /**
+ * @name General
+ * @{
+ */
+
+ /**
+ * Get table name
+ */
+ const char * getName() const;
+
+ /**
+ * Get table id
+ */
+ int getTableId() const;
+
+ /**
+ * Get column definition via name.
+ * @return null if none existing name
+ */
+ const Column* getColumn(const char * name) const;
+
+ /**
+ * Get column definition via index in table.
+ * @return null if none existing name
+ */
+ Column* getColumn(const int attributeId);
+
+ /**
+ * Get column definition via name.
+ * @return null if none existing name
+ */
+ Column* getColumn(const char * name);
+
+ /**
+ * Get column definition via index in table.
+ * @return null if none existing name
+ */
+ const Column* getColumn(const int attributeId) const;
+
+ /** @} *******************************************************************/
+ /**
+ * @name Storage
+ * @{
+ */
+
+ /**
+ * If set to false, then the table is a temporary
+ * table and is not logged to disk.
+ *
+ * In case of a system restart the table will still
+ * be defined and exist but will be empty.
+ * Thus no checkpointing and no logging is performed on the table.
+ *
+ * The default value is true and indicates a normal table
+ * with full checkpointing and logging activated.
+ */
+ bool getLogging() const;
+
+ /**
+ * Get fragmentation type
+ */
+ FragmentType getFragmentType() const;
+
+ /**
+ * Get KValue (Hash parameter.)
+ * Only allowed value is 6.
+ * Later implementations might add flexibility in this parameter.
+ */
+ int getKValue() const;
+
+ /**
+ * Get MinLoadFactor (Hash parameter.)
+ * This value specifies the load factor when starting to shrink
+ * the hash table.
+ * It must be smaller than MaxLoadFactor.
+ * Both these factors are given in percentage.
+ */
+ int getMinLoadFactor() const;
+
+ /**
+ * Get MaxLoadFactor (Hash parameter.)
+ * This value specifies the load factor when starting to split
+ * the containers in the local hash tables.
+ * 100 is the maximum which will optimize memory usage.
+ * A lower figure will store less information in each container and thus
+ * find the key faster but consume more memory.
+ */
+ int getMaxLoadFactor() const;
+
+ /** @} *******************************************************************/
+ /**
+ * @name Other
+ * @{
+ */
+
+ /**
+ * Get number of columns in the table
+ */
+ int getNoOfColumns() const;
+
+ /**
+ * Get number of primary keys in the table
+ */
+ int getNoOfPrimaryKeys() const;
+
+ /**
+ * Get name of primary key
+ */
+ const char* getPrimaryKey(int no) const;
+
+ /**
+ * Check if table is equal to some other table
+ */
+ bool equal(const Table&) const;
+
+ /**
+ * Get frm file stored with this table
+ */
+ const void* getFrmData() const;
+ Uint32 getFrmLength() const;
+
+ /**
+ * Get Fragment Data (id, state and node group)
+ */
+ const void *getFragmentData() const;
+ Uint32 getFragmentDataLen() const;
+
+ /**
+ * Get Range or List Array (value, partition)
+ */
+ const void *getRangeListData() const;
+ Uint32 getRangeListDataLen() const;
+
+ /**
+ * Get Tablespace Data (id, version)
+ */
+ const void *getTablespaceData() const;
+ Uint32 getTablespaceDataLen() const;
+
+ /** @} *******************************************************************/
+
+ /**
+ * @name Table creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result is not accessible from the MySQL Server
+ *
+ */
+
+ /**
+ * Constructor
+ * @param name Name of table
+ */
+ Table(const char * name = "");
+
+ /**
+ * Copy constructor
+ * @param table Table to be copied
+ */
+ Table(const Table& table);
+ virtual ~Table();
+
+ /**
+ * Assignment operator, deep copy
+ * @param table Table to be copied
+ */
+ Table& operator=(const Table& table);
+
+ /**
+ * Name of table
+ * @param name Name of table
+ */
+ void setName(const char * name);
+
+ /**
+ * Add a column definition to a table
+ * @note creates a copy
+ */
+ void addColumn(const Column &);
+
+ /**
+ * @see NdbDictionary::Table::getLogging.
+ */
+ void setLogging(bool);
+
+ /**
+ * Set/Get Linear Hash Flag
+ */
+ void setLinearFlag(Uint32 flag);
+ bool getLinearFlag() const;
+
+ /**
+ * Set fragment count
+ */
+ void setFragmentCount(Uint32);
+
+ /**
+ * Get fragment count
+ */
+ Uint32 getFragmentCount() const;
+
+ /**
+ * Set fragmentation type
+ */
+ void setFragmentType(FragmentType);
+
+ /**
+ * Set KValue (Hash parameter.)
+ * Only allowed value is 6.
+ * Later implementations might add flexibility in this parameter.
+ */
+ void setKValue(int kValue);
+
+ /**
+ * Set MinLoadFactor (Hash parameter.)
+ * This value specifies the load factor when starting to shrink
+ * the hash table.
+ * It must be smaller than MaxLoadFactor.
+ * Both these factors are given in percentage.
+ */
+ void setMinLoadFactor(int);
+
+ /**
+ * Set MaxLoadFactor (Hash parameter.)
+ * This value specifies the load factor when starting to split
+ * the containers in the local hash tables.
+ * 100 is the maximum which will optimize memory usage.
+ * A lower figure will store less information in each container and thus
+ * find the key faster but consume more memory.
+ */
+ void setMaxLoadFactor(int);
+
+ void setTablespace(const char * name);
+ void setTablespace(const class Tablespace &);
+ const char * getTablespace() const;
+ bool getTablespace(Uint32 *id= 0, Uint32 *version= 0) const;
+
+ /**
+ * Get table object type
+ */
+ Object::Type getObjectType() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+ void setStatusInvalid() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Set/Get indicator if default number of partitions is used in table.
+ */
+ void setDefaultNoPartitionsFlag(Uint32 indicator);
+ Uint32 getDefaultNoPartitionsFlag() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ /**
+ * Set frm file to store with this table
+ */
+ void setFrm(const void* data, Uint32 len);
+
+ /**
+ * Set array of fragment information containing
+ * Fragment Identity
+ * Node group identity
+ * Fragment State
+ */
+ void setFragmentData(const void* data, Uint32 len);
+
+ /**
+ * Set/Get tablespace names per fragment
+ */
+ void setTablespaceNames(const void* data, Uint32 len);
+ const void *getTablespaceNames();
+ Uint32 getTablespaceNamesLen() const;
+
+ /**
+ * Set tablespace information per fragment
+ * Contains a tablespace id and a tablespace version
+ */
+ void setTablespaceData(const void* data, Uint32 len);
+
+ /**
+ * Set array of information mapping range values and list values
+ * to fragments. This is essentially a sorted map consisting of
+ * pairs of value, fragment identity. For range partitions there is
+ * one pair per fragment. For list partitions it could be any number
+ * of pairs, at least as many as there are fragments.
+ */
+ void setRangeListData(const void* data, Uint32 len);
+
+ /**
+ * Set table object type
+ */
+ void setObjectType(Object::Type type);
+
+ /**
+ * Set/Get Maximum number of rows in table (only used to calculate
+ * number of partitions).
+ */
+ void setMaxRows(Uint64 maxRows);
+ Uint64 getMaxRows() const;
+
+ /**
+ * Set/Get Minimum number of rows in table (only used to calculate
+ * number of partitions).
+ */
+ void setMinRows(Uint64 minRows);
+ Uint64 getMinRows() const;
+
+ /** @} *******************************************************************/
+
+ /**
+ *
+ */
+ void setRowGCIIndicator(bool value);
+ bool getRowGCIIndicator() const;
+
+ void setRowChecksumIndicator(bool value);
+ bool getRowChecksumIndicator() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const char *getMysqlName() const;
+
+ void setStoredTable(bool x) { setLogging(x); }
+ bool getStoredTable() const { return getLogging(); }
+
+ int getRowSizeInBytes() const ;
+ int createTableInDb(Ndb*, bool existingEqualIsOk = true) const ;
+
+ int getReplicaCount() const ;
+
+ bool getTemporary();
+ void setTemporary(bool);
+
+ /**
+ * Check if any of column in bitmaps are disk columns
+ * returns bitmap of different columns
+ * bit 0 = atleast 1 pk column is set
+ * bit 1 = atleast 1 disk column set
+ * bit 2 = atleast 1 non disk column set
+ * passing NULL pointer will equal to bitmap with all columns set
+ */
+ int checkColumns(const Uint32* bitmap, unsigned len_in_bytes) const;
+#endif
+
+ // these 2 are not de-doxygenated
+
+ /**
+ * This method is not needed in normal usage.
+ *
+ * Compute aggregate data on table being defined. Required for
+ * aggregate methods such as getNoOfPrimaryKeys() to work before
+ * table has been created and retrieved via getTable().
+ *
+ * May adjust some column flags. If no PK is so far marked as
+ * distribution key then all PK's will be marked.
+ *
+ * Returns 0 on success. Returns -1 and sets error if an
+ * inconsistency is detected.
+ */
+ int aggregate(struct NdbError& error);
+
+ /**
+ * This method is not needed in normal usage.
+ *
+ * Validate new table definition before create. Does aggregate()
+ * and additional checks. There may still be errors which are
+ * detected only by NDB kernel at create table.
+ *
+ * Create table and retrieve table do validate() automatically.
+ *
+ * Returns 0 on success. Returns -1 and sets error if an
+ * inconsistency is detected.
+ */
+ int validate(struct NdbError& error);
+
+ private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbDictionaryImpl;
+ friend class NdbTableImpl;
+ friend class NdbEventOperationImpl;
+#endif
+ class NdbTableImpl & m_impl;
+ Table(NdbTableImpl&);
+ };
+
+ /**
+ * @class Index
+ * @brief Represents an index in an NDB Cluster
+ */
+ class Index : public Object {
+ public:
+
+ /**
+ * @name Getting Index properties
+ * @{
+ */
+
+ /**
+ * Get the name of an index
+ */
+ const char * getName() const;
+
+ /**
+ * Get the name of the table being indexed
+ */
+ const char * getTable() const;
+
+ /**
+ * Get the number of columns in the index
+ */
+ unsigned getNoOfColumns() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get the number of columns in the index
+ * Depricated, use getNoOfColumns instead.
+ */
+ int getNoOfIndexColumns() const;
+#endif
+
+ /**
+ * Get a specific column in the index
+ */
+ const Column * getColumn(unsigned no) const ;
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get a specific column name in the index
+ * Depricated, use getColumn instead.
+ */
+ const char * getIndexColumn(int no) const ;
+#endif
+
+ /**
+ * Represents type of index
+ */
+ enum Type {
+ Undefined = 0, ///< Undefined object type (initial value)
+ UniqueHashIndex = 3, ///< Unique un-ordered hash index
+ ///< (only one currently supported)
+ OrderedIndex = 6 ///< Non-unique ordered index
+ };
+
+ /**
+ * Get index type of the index
+ */
+ Type getType() const;
+
+ /**
+ * Check if index is set to be stored on disk
+ *
+ * @return if true then logging id enabled
+ *
+ * @note Non-logged indexes are rebuilt at system restart.
+ * @note Ordered index does not currently support logging.
+ */
+ bool getLogging() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ /** @} *******************************************************************/
+
+ /**
+ * @name Index creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
+ *
+ */
+
+ /**
+ * Constructor
+ * @param name Name of index
+ */
+ Index(const char * name = "");
+ virtual ~Index();
+
+ /**
+ * Set the name of an index
+ */
+ void setName(const char * name);
+
+ /**
+ * Define the name of the table to be indexed
+ */
+ void setTable(const char * name);
+
+ /**
+ * Add a column to the index definition
+ * Note that the order of columns will be in
+ * the order they are added (only matters for ordered indexes).
+ */
+ void addColumn(const Column & c);
+
+ /**
+ * Add a column name to the index definition
+ * Note that the order of indexes will be in
+ * the order they are added (only matters for ordered indexes).
+ */
+ void addColumnName(const char * name);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Add a column name to the index definition
+ * Note that the order of indexes will be in
+ * the order they are added (only matters for ordered indexes).
+ * Depricated, use addColumnName instead.
+ */
+ void addIndexColumn(const char * name);
+#endif
+
+ /**
+ * Add several column names to the index definition
+ * Note that the order of indexes will be in
+ * the order they are added (only matters for ordered indexes).
+ */
+ void addColumnNames(unsigned noOfNames, const char ** names);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Add several column names to the index definition
+ * Note that the order of indexes will be in
+ * the order they are added (only matters for ordered indexes).
+ * Depricated, use addColumnNames instead.
+ */
+ void addIndexColumns(int noOfNames, const char ** names);
+#endif
+
+ /**
+ * Set index type of the index
+ */
+ void setType(Type type);
+
+ /**
+ * Enable/Disable index storage on disk
+ *
+ * @param enable If enable is set to true, then logging becomes enabled
+ *
+ * @see NdbDictionary::Index::getLogging
+ */
+ void setLogging(bool enable);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ void setStoredIndex(bool x) { setLogging(x); }
+ bool getStoredIndex() const { return getLogging(); }
+
+ bool getTemporary();
+ void setTemporary(bool);
+#endif
+
+ /** @} *******************************************************************/
+
+ private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbIndexImpl;
+ friend class NdbIndexStat;
+#endif
+ class NdbIndexImpl & m_impl;
+ Index(NdbIndexImpl&);
+ };
+
+ /**
+ * @brief Represents an Event in NDB Cluster
+ *
+ */
+ class Event : public Object {
+ public:
+ /**
+ * Specifies the type of database operations an Event listens to
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** TableEvent must match 1 << TriggerEvent */
+#endif
+ enum TableEvent {
+ TE_INSERT =1<<0, ///< Insert event on table
+ TE_DELETE =1<<1, ///< Delete event on table
+ TE_UPDATE =1<<2, ///< Update event on table
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ TE_SCAN =1<<3, ///< Scan event on table
+ TE_FIRST_NON_DATA_EVENT =1<<4,
+#endif
+ TE_DROP =1<<4, ///< Drop of table
+ TE_ALTER =1<<5, ///< Alter of table
+ TE_CREATE =1<<6, ///< Create of table
+ TE_GCP_COMPLETE=1<<7, ///< GCP is complete
+ TE_CLUSTER_FAILURE=1<<8, ///< Cluster is unavailable
+ TE_STOP =1<<9, ///< Stop of event operation
+ TE_NODE_FAILURE=1<<10, ///< Node failed
+ TE_SUBSCRIBE =1<<11, ///< Node subscribes
+ TE_UNSUBSCRIBE =1<<12, ///< Node unsubscribes
+ TE_ALL=0xFFFF ///< Any/all event on table (not relevant when
+ ///< events are received)
+ };
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ enum _TableEvent {
+ _TE_INSERT=0,
+ _TE_DELETE=1,
+ _TE_UPDATE=2,
+ _TE_SCAN=3,
+ _TE_FIRST_NON_DATA_EVENT=4,
+ _TE_DROP=4,
+ _TE_ALTER=5,
+ _TE_CREATE=6,
+ _TE_GCP_COMPLETE=7,
+ _TE_CLUSTER_FAILURE=8,
+ _TE_STOP=9,
+ _TE_NODE_FAILURE=10,
+ _TE_SUBSCRIBE=11,
+ _TE_UNSUBSCRIBE=12,
+ _TE_NUL=13, // internal (e.g. INS o DEL within same GCI)
+ _TE_ACTIVE=14 // internal (node becomes active)
+ };
+#endif
+ /**
+ * Specifies the durability of an event
+ * (future version may supply other types)
+ */
+ enum EventDurability {
+ ED_UNDEFINED
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 0
+#endif
+#if 0 // not supported
+ ,ED_SESSION = 1,
+ // Only this API can use it
+ // and it's deleted after api has disconnected or ndb has restarted
+
+ ED_TEMPORARY = 2
+ // All API's can use it,
+ // But's its removed when ndb is restarted
+#endif
+ ,ED_PERMANENT ///< All API's can use it.
+ ///< It's still defined after a cluster system restart
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 3
+#endif
+ };
+
+ /**
+ * Specifies reporting options for table events
+ */
+ enum EventReport {
+ ER_UPDATED = 0,
+ ER_ALL = 1, // except not-updated blob inlines
+ ER_SUBSCRIBE = 2
+ };
+
+ /**
+ * Constructor
+ * @param name Name of event
+ */
+ Event(const char *name);
+ /**
+ * Constructor
+ * @param name Name of event
+ * @param table Reference retrieved from NdbDictionary
+ */
+ Event(const char *name, const NdbDictionary::Table& table);
+ virtual ~Event();
+ /**
+ * Set unique identifier for the event
+ */
+ void setName(const char *name);
+ /**
+ * Get unique identifier for the event
+ */
+ const char *getName() const;
+ /**
+ * Get table that the event is defined on
+ *
+ * @return pointer to table or NULL if no table has been defined
+ */
+ const NdbDictionary::Table * getTable() const;
+ /**
+ * Define table on which events should be detected
+ *
+ * @note calling this method will default to detection
+ * of events on all columns. Calling subsequent
+ * addEventColumn calls will override this.
+ *
+ * @param table reference retrieved from NdbDictionary
+ */
+ void setTable(const NdbDictionary::Table& table);
+ /**
+ * Set table for which events should be detected
+ *
+ * @note preferred way is using setTable(const NdbDictionary::Table&)
+ * or constructor with table object parameter
+ */
+ void setTable(const char *tableName);
+ /**
+ * Get table name for events
+ *
+ * @return table name
+ */
+ const char* getTableName() const;
+ /**
+ * Add type of event that should be detected
+ */
+ void addTableEvent(const TableEvent te);
+ /**
+ * Check if a specific table event will be detected
+ */
+ bool getTableEvent(const TableEvent te) const;
+ /**
+ * Set durability of the event
+ */
+ void setDurability(EventDurability);
+ /**
+ * Get durability of the event
+ */
+ EventDurability getDurability() const;
+ /**
+ * Set report option of the event
+ */
+ void setReport(EventReport);
+ /**
+ * Get report option of the event
+ */
+ EventReport getReport() const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void addColumn(const Column &c);
+#endif
+ /**
+ * Add a column on which events should be detected
+ *
+ * @param attrId Column id
+ *
+ * @note errors will mot be detected until createEvent() is called
+ */
+ void addEventColumn(unsigned attrId);
+ /**
+ * Add a column on which events should be detected
+ *
+ * @param columnName Column name
+ *
+ * @note errors will not be detected until createEvent() is called
+ */
+ void addEventColumn(const char * columnName);
+ /**
+ * Add several columns on which events should be detected
+ *
+ * @param n Number of columns
+ * @param columnNames Column names
+ *
+ * @note errors will mot be detected until
+ * NdbDictionary::Dictionary::createEvent() is called
+ */
+ void addEventColumns(int n, const char ** columnNames);
+
+ /**
+ * Get no of columns defined in an Event
+ *
+ * @return Number of columns, -1 on error
+ */
+ int getNoOfEventColumns() const;
+
+ /**
+ * Get a specific column in the event
+ */
+ const Column * getEventColumn(unsigned no) const;
+
+ /**
+ * The merge events flag is false by default. Setting it true
+ * implies that events are merged in following ways:
+ *
+ * - for given NdbEventOperation associated with this event,
+ * events on same PK within same GCI are merged into single event
+ *
+ * - a blob table event is created for each blob attribute
+ * and blob events are handled as part of main table events
+ *
+ * - blob post/pre data from the blob part events can be read
+ * via NdbBlob methods as a single value
+ *
+ * NOTE: Currently this flag is not inherited by NdbEventOperation
+ * and must be set on NdbEventOperation explicitly.
+ */
+ void mergeEvents(bool flag);
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void print();
+#endif
+
+ private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbEventImpl;
+ friend class NdbEventOperationImpl;
+#endif
+ class NdbEventImpl & m_impl;
+ Event(NdbEventImpl&);
+ };
+
+ struct AutoGrowSpecification {
+ Uint32 min_free;
+ Uint64 max_size;
+ Uint64 file_size;
+ const char * filename_pattern;
+ };
+
+ /**
+ * @class LogfileGroup
+ */
+ class LogfileGroup : public Object {
+ public:
+ LogfileGroup();
+ LogfileGroup(const LogfileGroup&);
+ virtual ~LogfileGroup();
+
+ void setName(const char * name);
+ const char* getName() const;
+
+ void setUndoBufferSize(Uint32 sz);
+ Uint32 getUndoBufferSize() const;
+
+ void setAutoGrowSpecification(const AutoGrowSpecification&);
+ const AutoGrowSpecification& getAutoGrowSpecification() const;
+
+ Uint64 getUndoFreeWords() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ private:
+ friend class NdbDictionaryImpl;
+ friend class NdbLogfileGroupImpl;
+ class NdbLogfileGroupImpl & m_impl;
+ LogfileGroup(NdbLogfileGroupImpl&);
+ };
+
+ /**
+ * @class Tablespace
+ */
+ class Tablespace : public Object {
+ public:
+ Tablespace();
+ Tablespace(const Tablespace&);
+ virtual ~Tablespace();
+
+ void setName(const char * name);
+ const char* getName() const;
+
+ void setExtentSize(Uint32 sz);
+ Uint32 getExtentSize() const;
+
+ void setAutoGrowSpecification(const AutoGrowSpecification&);
+ const AutoGrowSpecification& getAutoGrowSpecification() const;
+
+ void setDefaultLogfileGroup(const char * name);
+ void setDefaultLogfileGroup(const class LogfileGroup&);
+
+ const char * getDefaultLogfileGroup() const;
+ Uint32 getDefaultLogfileGroupId() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ private:
+ friend class NdbTablespaceImpl;
+ class NdbTablespaceImpl & m_impl;
+ Tablespace(NdbTablespaceImpl&);
+ };
+
+ class Datafile : public Object {
+ public:
+ Datafile();
+ Datafile(const Datafile&);
+ virtual ~Datafile();
+
+ void setPath(const char * name);
+ const char* getPath() const;
+
+ void setSize(Uint64);
+ Uint64 getSize() const;
+ Uint64 getFree() const;
+
+ void setTablespace(const char * name);
+ void setTablespace(const class Tablespace &);
+ const char * getTablespace() const;
+ void getTablespaceId(ObjectId * dst) const;
+
+ void setNode(Uint32 nodeId);
+ Uint32 getNode() const;
+
+ Uint32 getFileNo() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ private:
+ friend class NdbDatafileImpl;
+ class NdbDatafileImpl & m_impl;
+ Datafile(NdbDatafileImpl&);
+ };
+
+ class Undofile : public Object {
+ public:
+ Undofile();
+ Undofile(const Undofile&);
+ virtual ~Undofile();
+
+ void setPath(const char * path);
+ const char* getPath() const;
+
+ void setSize(Uint64);
+ Uint64 getSize() const;
+
+ void setLogfileGroup(const char * name);
+ void setLogfileGroup(const class LogfileGroup &);
+ const char * getLogfileGroup() const;
+ void getLogfileGroupId(ObjectId * dst) const;
+
+ void setNode(Uint32 nodeId);
+ Uint32 getNode() const;
+
+ Uint32 getFileNo() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /**
+ * Get object id
+ */
+ virtual int getObjectId() const;
+
+ private:
+ friend class NdbUndofileImpl;
+ class NdbUndofileImpl & m_impl;
+ Undofile(NdbUndofileImpl&);
+ };
+
+ /**
+ * @class Dictionary
+ * @brief Dictionary for defining and retreiving meta data
+ */
+ class Dictionary {
+ public:
+ /**
+ * @class List
+ * @brief Structure for retrieving lists of object names
+ */
+ struct List {
+ /**
+ * @struct Element
+ * @brief Object to be stored in an NdbDictionary::Dictionary::List
+ */
+ struct Element {
+ unsigned id; ///< Id of object
+ Object::Type type; ///< Type of object
+ Object::State state; ///< State of object
+ Object::Store store; ///< How object is logged
+ Uint32 temp; ///< Temporary status of object
+ char * database; ///< In what database the object resides
+ char * schema; ///< What schema the object is defined in
+ char * name; ///< Name of object
+ Element() :
+ id(0),
+ type(Object::TypeUndefined),
+ state(Object::StateUndefined),
+ store(Object::StoreUndefined),
+ temp(NDB_TEMP_TAB_PERMANENT),
+ database(0),
+ schema(0),
+ name(0) {
+ }
+ };
+ unsigned count; ///< Number of elements in list
+ Element * elements; ///< Pointer to array of elements
+ List() : count(0), elements(0) {}
+ ~List() {
+ if (elements != 0) {
+ for (unsigned i = 0; i < count; i++) {
+ delete[] elements[i].database;
+ delete[] elements[i].schema;
+ delete[] elements[i].name;
+ elements[i].name = 0;
+ }
+ delete[] elements;
+ count = 0;
+ elements = 0;
+ }
+ }
+ };
+
+ /**
+ * @name General
+ * @{
+ */
+
+ /**
+ * Fetch list of all objects, optionally restricted to given type.
+ *
+ * @param list List of objects returned in the dictionary
+ * @param type Restrict returned list to only contain objects of
+ * this type
+ *
+ * @return -1 if error.
+ *
+ */
+ int listObjects(List & list, Object::Type type = Object::TypeUndefined);
+ int listObjects(List & list,
+ Object::Type type = Object::TypeUndefined) const;
+
+ /**
+ * Get the latest error
+ *
+ * @return Error object.
+ */
+ const struct NdbError & getNdbError() const;
+
+ /** @} *******************************************************************/
+
+ /**
+ * @name Retrieving references to Tables and Indexes
+ * @{
+ */
+
+ /**
+ * Get table with given name, NULL if undefined
+ * @param name Name of table to get
+ * @return table if successful otherwise NULL.
+ */
+ const Table * getTable(const char * name) const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Given main table, get blob table.
+ */
+ const Table * getBlobTable(const Table *, const char * col_name);
+ const Table * getBlobTable(const Table *, Uint32 col_no);
+
+ /*
+ * Save a table definition in dictionary cache
+ * @param table Object to put into cache
+ */
+ void putTable(const Table * table);
+#endif
+
+ /**
+ * Get index with given name, NULL if undefined
+ * @param indexName Name of index to get.
+ * @param tableName Name of table that index belongs to.
+ * @return index if successful, otherwise 0.
+ */
+ const Index * getIndex(const char * indexName,
+ const char * tableName) const;
+
+ /**
+ * Fetch list of indexes of given table.
+ * @param list Reference to list where to store the listed indexes
+ * @param tableName Name of table that index belongs to.
+ * @return 0 if successful, otherwise -1
+ */
+ int listIndexes(List & list, const char * tableName);
+ int listIndexes(List & list, const char * tableName) const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Fetch list of indexes of given table.
+ * @param list Reference to list where to store the listed indexes
+ * @param table Reference to table that index belongs to.
+ * @return 0 if successful, otherwise -1
+ */
+ int listIndexes(List & list, const Table &table) const;
+#endif
+
+ /** @} *******************************************************************/
+ /**
+ * @name Events
+ * @{
+ */
+
+ /**
+ * Create event given defined Event instance
+ * @param event Event to create
+ * @return 0 if successful otherwise -1.
+ */
+ int createEvent(const Event &event);
+
+ /**
+ * Drop event with given name
+ * @param eventName Name of event to drop.
+ * @return 0 if successful otherwise -1.
+ */
+ int dropEvent(const char * eventName);
+
+ /**
+ * Get event with given name.
+ * @param eventName Name of event to get.
+ * @return an Event if successful, otherwise NULL.
+ */
+ const Event * getEvent(const char * eventName);
+
+ /** @} *******************************************************************/
+
+ /**
+ * @name Table creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
+ */
+
+ /**
+ * Create defined table given defined Table instance
+ * @param table Table to create
+ * @return 0 if successful otherwise -1.
+ */
+ int createTable(const Table &table);
+
+ /**
+ * Drop table given retrieved Table instance
+ * @param table Table to drop
+ * @return 0 if successful otherwise -1.
+ */
+ int dropTable(Table & table);
+
+ /**
+ * Drop table given table name
+ * @param name Name of table to drop
+ * @return 0 if successful otherwise -1.
+ */
+ int dropTable(const char * name);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Alter defined table given defined Table instance
+ * @param table Table to alter
+ * @return -2 (incompatible version) <br>
+ * -1 general error <br>
+ * 0 success
+ */
+ int alterTable(const Table &table);
+
+ /**
+ * Invalidate cached table object
+ * @param name Name of table to invalidate
+ */
+ void invalidateTable(const char * name);
+#endif
+
+ /**
+ * Remove table from local cache
+ */
+ void removeCachedTable(const char * table);
+ /**
+ * Remove index from local cache
+ */
+ void removeCachedIndex(const char * index, const char * table);
+
+
+ /** @} *******************************************************************/
+ /**
+ * @name Index creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
+ *
+ */
+
+ /**
+ * Create index given defined Index instance
+ * @param index Index to create
+ * @return 0 if successful otherwise -1.
+ */
+ int createIndex(const Index &index);
+ int createIndex(const Index &index, const Table &table);
+
+ /**
+ * Drop index with given name
+ * @param indexName Name of index to drop.
+ * @param tableName Name of table that index belongs to.
+ * @return 0 if successful otherwise -1.
+ */
+ int dropIndex(const char * indexName,
+ const char * tableName);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void removeCachedTable(const Table *table);
+ void removeCachedIndex(const Index *index);
+ void invalidateTable(const Table *table);
+ /**
+ * Invalidate cached index object
+ */
+ void invalidateIndex(const char * indexName,
+ const char * tableName);
+ void invalidateIndex(const Index *index);
+ /**
+ * Force gcp and wait for gcp complete
+ */
+ int forceGCPWait();
+#endif
+
+ /** @} *******************************************************************/
+
+ /** @} *******************************************************************/
+ /**
+ * @name Disk data objects
+ * @{
+ */
+
+ int createLogfileGroup(const LogfileGroup &, ObjectId* = 0);
+ int dropLogfileGroup(const LogfileGroup&);
+ LogfileGroup getLogfileGroup(const char * name);
+
+ int createTablespace(const Tablespace &, ObjectId* = 0);
+ int dropTablespace(const Tablespace&);
+ Tablespace getTablespace(const char * name);
+ Tablespace getTablespace(Uint32 tablespaceId);
+
+ int createDatafile(const Datafile &, bool overwrite_existing = false, ObjectId* = 0);
+ int dropDatafile(const Datafile&);
+ Datafile getDatafile(Uint32 node, const char * path);
+
+ int createUndofile(const Undofile &, bool overwrite_existing = false, ObjectId * = 0);
+ int dropUndofile(const Undofile&);
+ Undofile getUndofile(Uint32 node, const char * path);
+
+ /** @} *******************************************************************/
+
+ protected:
+ Dictionary(Ndb & ndb);
+ ~Dictionary();
+
+ private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbDictionaryImpl;
+ friend class UtilTransactions;
+ friend class NdbBlob;
+#endif
+ class NdbDictionaryImpl & m_impl;
+ Dictionary(NdbDictionaryImpl&);
+ const Table * getIndexTable(const char * indexName,
+ const char * tableName) const;
+ public:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const Table * getTable(const char * name, void **data) const;
+ void set_local_table_data_size(unsigned sz);
+
+ const Index * getIndexGlobal(const char * indexName,
+ const Table &ndbtab) const;
+ const Table * getTableGlobal(const char * tableName) const;
+ int alterTableGlobal(const Table &f, const Table &t);
+ int dropTableGlobal(const Table &ndbtab);
+ int dropIndexGlobal(const Index &index);
+ int removeIndexGlobal(const Index &ndbidx, int invalidate) const;
+ int removeTableGlobal(const Table &ndbtab, int invalidate) const;
+#endif
+ };
+};
+
+class NdbOut& operator <<(class NdbOut& out, const NdbDictionary::Column& col);
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbError.hpp b/storage/ndb/include/ndbapi/NdbError.hpp
new file mode 100644
index 00000000000..83f24b36313
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbError.hpp
@@ -0,0 +1,250 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NDB_ERROR_HPP
+#define NDB_ERROR_HPP
+
+#include <ndberror.h>
+
+/**
+ * @struct NdbError
+ * @brief Contains error information
+ *
+ * A NdbError consists of five parts:
+ * -# Error status : Application impact
+ * -# Error classification : Logical error group
+ * -# Error code : Internal error code
+ * -# Error message : Context independent description of error
+ * -# Error details : Context dependent information
+ * (not always available)
+ *
+ * <em>Error status</em> is usually used for programming against errors.
+ * If more detailed error control is needed, it is possible to
+ * use the <em>error classification</em>.
+ *
+ * It is not recommended to write application programs dependent on
+ * specific <em>error codes</em>.
+ *
+ * The <em>error messages</em> and <em>error details</em> may
+ * change without notice.
+ *
+ * For example of use, see @ref ndbapi_retries.cpp.
+ */
+struct NdbError {
+ /**
+ * Status categorizes error codes into status values reflecting
+ * what the application should do when encountering errors
+ */
+ enum Status {
+ /**
+ * The error code indicate success<br>
+ * (Includes classification: NdbError::NoError)
+ */
+ Success = ndberror_st_success,
+
+ /**
+ * The error code indicates a temporary error.
+ * The application should typically retry.<br>
+ * (Includes classifications: NdbError::InsufficientSpace,
+ * NdbError::TemporaryResourceError, NdbError::NodeRecoveryError,
+ * NdbError::OverloadError, NdbError::NodeShutdown
+ * and NdbError::TimeoutExpired.)
+ */
+ TemporaryError = ndberror_st_temporary,
+
+ /**
+ * The error code indicates a permanent error.<br>
+ * (Includes classificatons: NdbError::PermanentError,
+ * NdbError::ApplicationError, NdbError::NoDataFound,
+ * NdbError::ConstraintViolation, NdbError::SchemaError,
+ * NdbError::UserDefinedError, NdbError::InternalError, and,
+ * NdbError::FunctionNotImplemented.)
+ */
+ PermanentError = ndberror_st_permanent,
+
+ /**
+ * The result/status is unknown.<br>
+ * (Includes classifications: NdbError::UnknownResultError, and
+ * NdbError::UnknownErrorCode.)
+ */
+ UnknownResult = ndberror_st_unknown
+ };
+
+ /**
+ * Type of error
+ */
+ enum Classification {
+ /**
+ * Success. No error occurred.
+ */
+ NoError = ndberror_cl_none,
+
+ /**
+ * Error in application program.
+ */
+ ApplicationError = ndberror_cl_application,
+
+ /**
+ * Read operation failed due to missing record.
+ */
+ NoDataFound = ndberror_cl_no_data_found,
+
+ /**
+ * E.g. inserting a tuple with a primary key already existing
+ * in the table.
+ */
+ ConstraintViolation = ndberror_cl_constraint_violation,
+
+ /**
+ * Error in creating table or usage of table.
+ */
+ SchemaError = ndberror_cl_schema_error,
+
+ /**
+ * Error occurred in interpreted program.
+ */
+ UserDefinedError = ndberror_cl_user_defined,
+
+ /**
+ * E.g. insufficient memory for data or indexes.
+ */
+ InsufficientSpace = ndberror_cl_insufficient_space,
+
+ /**
+ * E.g. too many active transactions.
+ */
+ TemporaryResourceError = ndberror_cl_temporary_resource,
+
+ /**
+ * Temporary failures which are probably inflicted by a node
+ * recovery in progress. Examples: information sent between
+ * application and NDB lost, distribution change.
+ */
+ NodeRecoveryError = ndberror_cl_node_recovery,
+
+ /**
+ * E.g. out of log file space.
+ */
+ OverloadError = ndberror_cl_overload,
+
+ /**
+ * Timeouts, often inflicted by deadlocks in NDB.
+ */
+ TimeoutExpired = ndberror_cl_timeout_expired,
+
+ /**
+ * Is is unknown whether the transaction was committed or not.
+ */
+ UnknownResultError = ndberror_cl_unknown_result,
+
+ /**
+ * A serious error in NDB has occurred.
+ */
+ InternalError = ndberror_cl_internal_error,
+
+ /**
+ * A function used is not yet implemented.
+ */
+ FunctionNotImplemented = ndberror_cl_function_not_implemented,
+
+ /**
+ * Error handler could not determine correct error code.
+ */
+ UnknownErrorCode = ndberror_cl_unknown_error_code,
+
+ /**
+ * Node shutdown
+ */
+ NodeShutdown = ndberror_cl_node_shutdown,
+
+ /**
+ * Schema object already exists
+ */
+ SchemaObjectExists = ndberror_cl_schema_object_already_exists,
+
+ /**
+ * Request sent to non master
+ */
+ InternalTemporary = ndberror_cl_internal_temporary
+ };
+
+ /**
+ * Error status.
+ */
+ Status status;
+
+ /**
+ * Error type
+ */
+ Classification classification;
+
+ /**
+ * Error code
+ */
+ int code;
+
+ /**
+ * Mysql error code
+ */
+ int mysql_code;
+
+ /**
+ * Error message
+ */
+ const char * message;
+
+ /**
+ * The detailed description. This is extra information regarding the
+ * error which is not included in the error message.
+ *
+ * @note Is NULL when no details specified
+ */
+ char * details;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NdbError(){
+ status = UnknownResult;
+ classification = NoError;
+ code = 0;
+ mysql_code = 0;
+ message = 0;
+ details = 0;
+ }
+ NdbError(const ndberror_struct & ndberror){
+ status = (NdbError::Status) ndberror.status;
+ classification = (NdbError::Classification) ndberror.classification;
+ code = ndberror.code;
+ mysql_code = ndberror.mysql_code;
+ message = ndberror.message;
+ details = ndberror.details;
+ }
+ operator ndberror_struct() const {
+ ndberror_struct ndberror;
+ ndberror.status = (ndberror_status_enum) status;
+ ndberror.classification = (ndberror_classification_enum) classification;
+ ndberror.code = code;
+ ndberror.mysql_code = mysql_code;
+ ndberror.message = message;
+ ndberror.details = details;
+ return ndberror;
+ }
+#endif
+};
+
+class NdbOut& operator <<(class NdbOut&, const NdbError &);
+class NdbOut& operator <<(class NdbOut&, const NdbError::Status&);
+class NdbOut& operator <<(class NdbOut&, const NdbError::Classification&);
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbEventOperation.hpp b/storage/ndb/include/ndbapi/NdbEventOperation.hpp
new file mode 100644
index 00000000000..25d7b8c6644
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbEventOperation.hpp
@@ -0,0 +1,261 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbEventOperation_H
+#define NdbEventOperation_H
+
+class NdbGlobalEventBuffer;
+class NdbEventOperationImpl;
+
+/**
+ * @class NdbEventOperation
+ * @brief Class of operations for getting change events from database.
+ *
+ * Brief description on how to work with events:
+ *
+ * - An event, represented by an NdbDictionary::Event, i created in the
+ * Database through
+ * NdbDictionary::Dictionary::createEvent() (note that this can be done
+ * by any application or thread and not necessarily by the "listener")
+ * - To listen to events, an NdbEventOperation object is instantiated by
+ * Ndb::createEventOperation()
+ * - execute() starts the event flow. Use Ndb::pollEvents() to wait
+ * for an event to occur. Use Ndb::nextEvent() to iterate
+ * through the events that have occured.
+ * - The instance is removed by Ndb::dropEventOperation()
+ *
+ * For more info see:
+ * @ref ndbapi_event.cpp
+ *
+ * Known limitations:
+ *
+ * - Maximum number of active NdbEventOperations are now set at compile time.
+ * Today 100. This will become a configuration parameter later.
+ * - Maximum number of NdbEventOperations tied to same event are maximum 16
+ * per process.
+ *
+ * Known issues:
+ *
+ * - When several NdbEventOperation's are tied to the same event in the same
+ * process they will share the circular buffer. The BufferLength will then
+ * be the same for all and decided by the first NdbEventOperation
+ * instantiation. Just make sure to instantiate the "largest" one first.
+ * - Today all events INSERT/DELETE/UPDATE and all changed attributes are
+ * sent to the API, even if only specific attributes have been specified.
+ * These are however hidden from the user and only relevant data is shown
+ * after Ndb::nextEvent().
+ * - "False" exits from Ndb::pollEvents() may occur and thus
+ * the subsequent Ndb::nextEvent() will return NULL,
+ * since there was no available data. Just do Ndb::pollEvents() again.
+ * - Event code does not check table schema version. Make sure to drop events
+ * after table is dropped. Will be fixed in later
+ * versions.
+ * - If a node failure has occured not all events will be recieved
+ * anymore. Drop NdbEventOperation and Create again after nodes are up
+ * again. Will be fixed in later versions.
+ *
+ * Test status:
+ *
+ * - Tests have been run on 1-node and 2-node systems
+ *
+ * Useful API programs:
+ *
+ * - ndb_select_all -d sys 'NDB$EVENTS_0'
+ * shows contents in the system table containing created events.
+ *
+ * @note this is an inteface to viewing events that is subject to change
+ */
+class NdbEventOperation {
+public:
+ /**
+ * State of the NdbEventOperation object
+ */
+ enum State {
+ EO_CREATED, ///< Created but execute() not called
+ EO_EXECUTING, ///< execute() called
+ EO_DROPPED, ///< Waiting to be deleted, Object unusable.
+ EO_ERROR ///< An error has occurred. Object unusable.
+ };
+ /**
+ * Retrieve current state of the NdbEventOperation object
+ */
+ State getState();
+ /**
+ * See NdbDictionary::Event. Default is false.
+ */
+ void mergeEvents(bool flag);
+
+ /**
+ * Activates the NdbEventOperation to start receiving events. The
+ * changed attribute values may be retrieved after Ndb::nextEvent()
+ * has returned not NULL. The getValue() methods must be called
+ * prior to execute().
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int execute();
+
+ /**
+ * Defines a retrieval operation of an attribute value.
+ * The NDB API allocate memory for the NdbRecAttr object that
+ * will hold the returned attribute value.
+ *
+ * @note Note that it is the applications responsibility
+ * to allocate enough memory for aValue (if non-NULL).
+ * The buffer aValue supplied by the application must be
+ * aligned appropriately. The buffer is used directly
+ * (avoiding a copy penalty) only if it is aligned on a
+ * 4-byte boundary and the attribute size in bytes
+ * (i.e. NdbRecAttr::attrSize() times NdbRecAttr::arraySize() is
+ * a multiple of 4).
+ *
+ * @note There are two versions, getValue() and
+ * getPreValue() for retrieving the current and
+ * previous value repectively.
+ *
+ * @note This method does not fetch the attribute value from
+ * the database! The NdbRecAttr object returned by this method
+ * is <em>not</em> readable/printable before the
+ * execute() has been made and
+ * Ndb::nextEvent() has returned not NULL.
+ * If a specific attribute has not changed the corresponding
+ * NdbRecAttr will be in state UNDEFINED. This is checked by
+ * NdbRecAttr::isNULL() which then returns -1.
+ *
+ * @param anAttrName Attribute name
+ * @param aValue If this is non-NULL, then the attribute value
+ * will be returned in this parameter.<br>
+ * If NULL, then the attribute value will only
+ * be stored in the returned NdbRecAttr object.
+ * @return An NdbRecAttr object to hold the value of
+ * the attribute, or a NULL pointer
+ * (indicating error).
+ */
+ NdbRecAttr *getValue(const char *anAttrName, char *aValue = 0);
+ /**
+ * See getValue().
+ */
+ NdbRecAttr *getPreValue(const char *anAttrName, char *aValue = 0);
+
+ /**
+ * These methods replace getValue/getPreValue for blobs. Each
+ * method creates a blob handle NdbBlob. The handle supports only
+ * read operations. See NdbBlob.
+ */
+ NdbBlob* getBlobHandle(const char *anAttrName);
+ NdbBlob* getPreBlobHandle(const char *anAttrName);
+
+ int isOverrun() const;
+
+ /**
+ * In the current implementation a nodefailiure may cause loss of events,
+ * in which case isConsistent() will return false
+ */
+ bool isConsistent() const;
+
+ /**
+ * Query for occured event type.
+ *
+ * @note Only valid after Ndb::nextEvent() has been called and
+ * returned a not NULL value
+ *
+ * @return type of event
+ */
+ NdbDictionary::Event::TableEvent getEventType() const;
+
+ /**
+ * Check if table name has changed, for event TE_ALTER
+ */
+ const bool tableNameChanged() const;
+
+ /**
+ * Check if table frm has changed, for event TE_ALTER
+ */
+ const bool tableFrmChanged() const;
+
+ /**
+ * Check if table fragmentation has changed, for event TE_ALTER
+ */
+ const bool tableFragmentationChanged() const;
+
+ /**
+ * Check if table range partition list name has changed, for event TE_ALTER
+ */
+ const bool tableRangeListChanged() const;
+
+ /**
+ * Retrieve the GCI of the latest retrieved event
+ *
+ * @return GCI number
+ */
+ Uint64 getGCI() const;
+
+ /**
+ * Retrieve the complete GCI in the cluster (not necessarily
+ * associated with an event)
+ *
+ * @return GCI number
+ */
+ Uint64 getLatestGCI() const;
+
+ /**
+ * Get the latest error
+ *
+ * @return Error object.
+ */
+ const struct NdbError & getNdbError() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** these are subject to change at any time */
+ const NdbDictionary::Table* getTable() const;
+ const NdbDictionary::Event *getEvent() const;
+ const NdbRecAttr *getFirstPkAttr() const;
+ const NdbRecAttr *getFirstPkPreAttr() const;
+ const NdbRecAttr *getFirstDataAttr() const;
+ const NdbRecAttr *getFirstDataPreAttr() const;
+
+// bool validateTable(NdbDictionary::Table &table) const;
+
+ void setCustomData(void * data);
+ void * getCustomData() const;
+
+ void clearError();
+ int hasError() const;
+
+ int getReqNodeId() const;
+ int getNdbdNodeId() const;
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /*
+ *
+ */
+ void print();
+#endif
+
+private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbEventOperationImpl;
+ friend class NdbEventBuffer;
+#endif
+ NdbEventOperation(Ndb *theNdb, const char* eventName);
+ ~NdbEventOperation();
+ class NdbEventOperationImpl &m_impl;
+ NdbEventOperation(NdbEventOperationImpl& impl);
+};
+
+typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbIndexOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp
new file mode 100644
index 00000000000..d16cd071f77
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -0,0 +1,192 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbIndexOperation_H
+#define NdbIndexOperation_H
+
+#include "NdbOperation.hpp"
+
+class Index;
+class NdbResultSet;
+
+/**
+ * @class NdbIndexOperation
+ * @brief Class of index operations for use in transactions
+ */
+class NdbIndexOperation : public NdbOperation
+{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbTransaction;
+#endif
+
+public:
+ /**
+ * @name Define Standard Operation
+ * @{
+ */
+
+ /** insert is not allowed */
+ int insertTuple();
+
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type readTuple.
+ * When calling NdbTransaction::execute, this operation
+ * reads a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int readTuple(LockMode);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type readTuple.
+ * When calling NdbTransaction::execute, this operation
+ * reads a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int readTuple();
+
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type
+ * readTupleExclusive.
+ * When calling NdbTransaction::execute, this operation
+ * read a tuple using an exclusive lock.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int readTupleExclusive();
+
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type simpleRead.
+ * When calling NdbTransaction::execute, this operation
+ * reads an existing tuple (using shared read lock),
+ * but releases lock immediately after read.
+ *
+ * @note Using this operation twice in the same transaction
+ * may produce different results (e.g. if there is another
+ * transaction which updates the value between the
+ * simple reads).
+ *
+ * Note that simpleRead can read the value from any database node while
+ * standard read always read the value on the database node which is
+ * primary for the record.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int simpleRead();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type committedRead.
+ * When calling NdbTransaction::execute, this operation
+ * read latest committed value of the record.
+ *
+ * This means that if another transaction is updating the
+ * record, then the current transaction will not wait.
+ * It will instead use the latest committed value of the
+ * record.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int dirtyRead();
+
+ int committedRead();
+#endif
+
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type
+ * updateTuple.
+ *
+ * When calling NdbTransaction::execute, this operation
+ * updates a tuple in the table.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int updateTuple();
+
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type
+ * deleteTuple.
+ *
+ * When calling NdbTransaction::execute, this operation
+ * deletes a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int deleteTuple();
+
+ /**
+ * Get index object for this operation
+ */
+ const NdbDictionary::Index * getIndex() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Define the NdbIndexOperation to be a standard operation of type
+ * dirtyUpdate.
+ *
+ * When calling NdbTransaction::execute, this operation
+ * updates without two-phase commit.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int dirtyUpdate();
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** @} *********************************************************************/
+ /**
+ * @name Define Interpreted Program Operation
+ * @{
+ */
+
+ /**
+ * Update a tuple using an interpreted program.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int interpretedUpdateTuple();
+
+ /**
+ * Delete a tuple using an interpreted program.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int interpretedDeleteTuple();
+#endif
+
+ /** @} *********************************************************************/
+
+private:
+ NdbIndexOperation(Ndb* aNdb);
+ ~NdbIndexOperation();
+
+ int receiveTCINDXREF(NdbApiSignal* aSignal);
+
+ // Overloaded methods from NdbCursorOperation
+ int indxInit(const class NdbIndexImpl* anIndex,
+ const class NdbTableImpl* aTable,
+ NdbTransaction*);
+
+ int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
+
+ // Private attributes
+ const NdbIndexImpl* m_theIndex;
+ friend struct Ndb_free_list_t<NdbIndexOperation>;
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
new file mode 100644
index 00000000000..eeafe98b46e
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -0,0 +1,204 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbIndexScanOperation_H
+#define NdbIndexScanOperation_H
+
+#include <NdbScanOperation.hpp>
+
+/**
+ * @class NdbIndexScanOperation
+ * @brief Class of scan operations for use to scan ordered index
+ */
+class NdbIndexScanOperation : public NdbScanOperation {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbTransaction;
+ friend class NdbResultSet;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexStat;
+#endif
+
+public:
+ /**
+ * readTuples using ordered index
+ *
+ * @param lock_mode Lock mode
+ * @param scan_flags see @ref ScanFlag
+ * @param parallel No of fragments to scan in parallel (0=max)
+ */
+ virtual int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 scan_flags = 0,
+ Uint32 parallel = 0,
+ Uint32 batch = 0);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * readTuples using ordered index
+ *
+ * @param lock_mode Lock mode
+ * @param batch No of rows to fetch from each fragment at a time
+ * @param parallel No of fragments to scan in parallel
+ * @param order_by Order result set in index order
+ * @param order_desc Order descending, ignored unless order_by
+ * @param read_range_no Enable reading of range no using @ref get_range_no
+ * @returns 0 for success and -1 for failure
+ * @see NdbScanOperation::readTuples
+ */
+ inline int readTuples(LockMode lock_mode,
+ Uint32 batch,
+ Uint32 parallel,
+ bool order_by,
+ bool order_desc = false,
+ bool read_range_no = false,
+ bool keyinfo = false) {
+ Uint32 scan_flags =
+ (SF_OrderBy & -(Int32)order_by) |
+ (SF_Descending & -(Int32)order_desc) |
+ (SF_ReadRangeNo & -(Int32)read_range_no) |
+ (SF_KeyInfo & -(Int32)keyinfo);
+
+ return readTuples(lock_mode, scan_flags, parallel, batch);
+ }
+#endif
+
+ /**
+ * Type of ordered index key bound. The values (0-4) will not change
+ * and can be used explicitly (e.g. they could be computed).
+ */
+ enum BoundType {
+ BoundLE = 0, ///< lower bound
+ BoundLT = 1, ///< lower bound, strict
+ BoundGE = 2, ///< upper bound
+ BoundGT = 3, ///< upper bound, strict
+ BoundEQ = 4 ///< equality
+ };
+
+ /**
+ * Define bound on index key in range scan.
+ *
+ * Each index key can have lower and/or upper bound. Setting the key
+ * equal to a value defines both upper and lower bounds. The bounds
+ * can be defined in any order. Conflicting definitions is an error.
+ *
+ * For equality, it is better to use BoundEQ instead of the equivalent
+ * pair of BoundLE and BoundGE. This is especially true when table
+ * partition key is an initial part of the index key.
+ *
+ * The sets of lower and upper bounds must be on initial sequences of
+ * index keys. All but possibly the last bound must be non-strict.
+ * So "a >= 2 and b > 3" is ok but "a > 2 and b >= 3" is not.
+ *
+ * The scan may currently return tuples for which the bounds are not
+ * satisfied. For example, "a <= 2 and b <= 3" scans the index up to
+ * (a=2, b=3) but also returns any (a=1, b=4).
+ *
+ * NULL is treated like a normal value which is less than any not-NULL
+ * value and equal to another NULL value. To compare against NULL use
+ * setBound with null pointer (0).
+ *
+ * An index stores also all-NULL keys. Doing index scan with empty
+ * bound set returns all table tuples.
+ *
+ * @param attr Attribute name, alternatively:
+ * @param type Type of bound
+ * @param value Pointer to bound value, 0 for NULL
+ * @return 0 if successful otherwise -1
+ *
+ * @note See comment under equal() about data format and length.
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int setBound(const char* attr, int type, const void* value, Uint32 len);
+#endif
+ int setBound(const char* attr, int type, const void* value);
+
+ /**
+ * Define bound on index key in range scan using index column id.
+ * See the other setBound() method for details.
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len);
+#endif
+ int setBound(Uint32 anAttrId, int type, const void* aValue);
+
+ /**
+ * Reset bounds and put operation in list that will be
+ * sent on next execute
+ */
+ int reset_bounds(bool forceSend = false);
+
+ /**
+ * Marks end of a bound,
+ * used when batching index reads (multiple ranges)
+ */
+ int end_of_bound(Uint32 range_no);
+
+ /**
+ * Return range no for current row
+ */
+ int get_range_no();
+
+ /**
+ * Is current scan sorted
+ */
+ bool getSorted() const { return m_ordered; }
+
+ /**
+ * Is current scan sorted descending
+ */
+ bool getDescending() const { return m_descending; }
+
+private:
+ NdbIndexScanOperation(Ndb* aNdb);
+ virtual ~NdbIndexScanOperation();
+
+ int setBound(const NdbColumnImpl*, int type, const void* aValue);
+ int insertBOUNDS(Uint32 * data, Uint32 sz);
+ Uint32 getKeyFromSCANTABREQ(Uint32* data, Uint32 size);
+
+ virtual int equal_impl(const NdbColumnImpl*, const char*);
+ virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);
+
+ void fix_get_values();
+ int next_result_ordered(bool fetchAllowed, bool forceSend = false);
+ int send_next_scan_ordered(Uint32 idx);
+ int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*);
+
+ Uint32 m_sort_columns;
+ Uint32 m_this_bound_start;
+ Uint32 * m_first_bound_word;
+
+ friend struct Ndb_free_list_t<NdbIndexScanOperation>;
+};
+
+inline
+int
+NdbIndexScanOperation::setBound(const char* attr, int type, const void* value,
+ Uint32 len)
+{
+ return setBound(attr, type, value);
+}
+
+inline
+int
+NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* value,
+ Uint32 len)
+{
+ return setBound(anAttrId, type, value);
+}
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbIndexStat.hpp b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
new file mode 100644
index 00000000000..ddd27ed24d4
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
@@ -0,0 +1,147 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbIndexStat_H
+#define NdbIndexStat_H
+
+#include <ndb_global.h>
+#include <NdbDictionary.hpp>
+#include <NdbError.hpp>
+class NdbIndexImpl;
+class NdbIndexScanOperation;
+
+/*
+ * Statistics for an ordered index.
+ */
+class NdbIndexStat {
+public:
+ NdbIndexStat(const NdbDictionary::Index* index);
+ ~NdbIndexStat();
+ /*
+ * Allocate memory for cache. Argument is minimum number of stat
+ * entries and applies to lower and upper bounds separately. More
+ * entries may fit (keys have variable size). If not used, db is
+ * contacted always.
+ */
+ int alloc_cache(Uint32 entries);
+ /*
+ * Flags for records_in_range.
+ */
+ enum {
+ RR_UseDb = 1, // contact db
+ RR_NoUpdate = 2 // but do not update cache
+ };
+ /*
+ * Estimate how many index records need to be scanned. The scan
+ * operation must be prepared with lock mode LM_CommittedRead and must
+ * have the desired bounds set. The routine may use local cache or
+ * may contact db by executing the operation.
+ *
+ * If returned count is zero then db was contacted and the count is
+ * exact. Otherwise the count is approximate. If cache is used then
+ * caller must provide estimated number of table rows. It will be
+ * multiplied by a percentage obtained from the cache (result zero is
+ * returned as 1).
+ */
+ int records_in_range(const NdbDictionary::Index* index,
+ NdbIndexScanOperation* op,
+ Uint64 table_rows,
+ Uint64* count,
+ int flags);
+ /*
+ * Get latest error.
+ */
+ const NdbError& getNdbError() const;
+
+private:
+ /*
+ * There are 2 areas: start keys and end keys. An area has pointers
+ * at beginning and entries at end. Pointers are sorted by key.
+ *
+ * A pointer contains entry offset and also entry timestamp. An entry
+ * contains the key and percentage of rows _not_ satisfying the bound
+ * i.e. less than start key or greater than end key.
+ *
+ * A key is an array of index key bounds. Each has type (0-4) in
+ * first word followed by data with AttributeHeader.
+ *
+ * Stat update comes as pair of start and end key and associated
+ * percentages. Stat query takes best match of start and end key from
+ * each area separately. Rows in range percentage is then computed by
+ * excluding the two i.e. as 100 - (start key pct + end key pct).
+ *
+ * TODO use more compact key format
+ */
+ struct Pointer;
+ friend struct Pointer;
+ struct Entry;
+ friend struct Entry;
+ struct Area;
+ friend struct Area;
+ struct Pointer {
+ Uint16 m_pos;
+ Uint16 m_seq;
+ };
+ struct Entry {
+ float m_pct;
+ Uint32 m_keylen;
+ };
+ STATIC_CONST( EntrySize = sizeof(Entry) >> 2 );
+ STATIC_CONST( PointerSize = sizeof(Pointer) >> 2 );
+ struct Area {
+ Uint32* m_data;
+ Uint32 m_offset;
+ Uint32 m_free;
+ Uint16 m_entries;
+ Uint8 m_idir;
+ Uint8 pad1;
+ Area() {}
+ Pointer& get_pointer(unsigned i) const {
+ return *(Pointer*)&m_data[i];
+ }
+ Entry& get_entry(unsigned i) const {
+ return *(Entry*)&m_data[get_pointer(i).m_pos];
+ }
+ Uint32 get_pos(const Entry& e) const {
+ return (const Uint32*)&e - m_data;
+ }
+ unsigned get_firstpos() const {
+ return PointerSize * m_entries + m_free;
+ }
+ };
+ const NdbIndexImpl& m_index;
+ Uint32 m_areasize;
+ Uint16 m_seq;
+ Area m_area[2];
+ Uint32* m_cache;
+ NdbError m_error;
+#ifdef VM_TRACE
+ void stat_verify();
+#endif
+ int stat_cmpkey(const Area& a, const Uint32* key1, Uint32 keylen1,
+ const Uint32* key2, Uint32 keylen2);
+ int stat_search(const Area& a, const Uint32* key, Uint32 keylen,
+ Uint32* idx, bool* match);
+ int stat_oldest(const Area& a);
+ int stat_delete(Area& a, Uint32 k);
+ int stat_update(const Uint32* key1, Uint32 keylen1,
+ const Uint32* key2, Uint32 keylen2, const float pct[2]);
+ int stat_select(const Uint32* key1, Uint32 keylen1,
+ const Uint32* key2, Uint32 keylen2, float pct[2]);
+ void set_error(int code);
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp
new file mode 100644
index 00000000000..7f026e29578
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp
@@ -0,0 +1,1311 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbOperation_H
+#define NdbOperation_H
+
+#include <ndb_types.h>
+#include "ndbapi_limits.h"
+#include "NdbError.hpp"
+#include "NdbReceiver.hpp"
+#include "NdbDictionary.hpp"
+#include "Ndb.hpp"
+
+class Ndb;
+class NdbApiSignal;
+class NdbRecAttr;
+class NdbOperation;
+class NdbTransaction;
+class NdbColumnImpl;
+class NdbBlob;
+
+/**
+ * @class NdbOperation
+ * @brief Class of operations for use in transactions.
+ */
+class NdbOperation
+{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbTransaction;
+ friend class NdbScanOperation;
+ friend class NdbScanReceiver;
+ friend class NdbScanFilter;
+ friend class NdbScanFilterImpl;
+ friend class NdbReceiver;
+ friend class NdbBlob;
+#endif
+
+public:
+ /**
+ * @name Define Standard Operation Type
+ * @{
+ */
+
+ /**
+ * Different access types (supported by sub-classes of NdbOperation)
+ */
+
+ enum Type {
+ PrimaryKeyAccess ///< Read, insert, update, or delete using pk
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 0 // NdbOperation
+#endif
+ ,UniqueIndexAccess ///< Read, update, or delete using unique index
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 1 // NdbIndexOperation
+#endif
+ ,TableScan ///< Full table scan
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 2 // NdbScanOperation
+#endif
+ ,OrderedIndexScan ///< Ordered index scan
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 3 // NdbIndexScanOperation
+#endif
+ };
+
+ /**
+ * Lock when performing read
+ */
+
+ enum LockMode {
+ LM_Read ///< Read with shared lock
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 0
+#endif
+ ,LM_Exclusive ///< Read with exclusive lock
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 1
+#endif
+ ,LM_CommittedRead ///< Ignore locks, read last committed value
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 2,
+ LM_Dirty = 2
+#endif
+ };
+
+ /**
+ * Define the NdbOperation to be a standard operation of type insertTuple.
+ * When calling NdbTransaction::execute, this operation
+ * adds a new tuple to the table.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int insertTuple();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type updateTuple.
+ * When calling NdbTransaction::execute, this operation
+ * updates a tuple in the table.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int updateTuple();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type writeTuple.
+ * When calling NdbTransaction::execute, this operation
+ * writes a tuple to the table.
+ * If the tuple exists, it updates it, otherwise an insert takes place.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int writeTuple();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type deleteTuple.
+ * When calling NdbTransaction::execute, this operation
+ * delete a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int deleteTuple();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type readTuple.
+ * When calling NdbTransaction::execute, this operation
+ * reads a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int readTuple(LockMode);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Define the NdbOperation to be a standard operation of type readTuple.
+ * When calling NdbTransaction::execute, this operation
+ * reads a tuple.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int readTuple();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type
+ * readTupleExclusive.
+ * When calling NdbTransaction::execute, this operation
+ * read a tuple using an exclusive lock.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int readTupleExclusive();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type
+ * simpleRead.
+ * When calling NdbTransaction::execute, this operation
+ * reads an existing tuple (using shared read lock),
+ * but releases lock immediately after read.
+ *
+ * @note Using this operation twice in the same transaction
+ * may produce different results (e.g. if there is another
+ * transaction which updates the value between the
+ * simple reads).
+ *
+ * Note that simpleRead can read the value from any database node while
+ * standard read always read the value on the database node which is
+ * primary for the record.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int simpleRead();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type committedRead.
+ * When calling NdbTransaction::execute, this operation
+ * read latest committed value of the record.
+ *
+ * This means that if another transaction is updating the
+ * record, then the current transaction will not wait.
+ * It will instead use the latest committed value of the
+ * record.
+ * dirtyRead is a deprecated name for committedRead
+ *
+ * @return 0 if successful otherwise -1.
+ * @depricated
+ */
+ virtual int dirtyRead();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type committedRead.
+ * When calling NdbTransaction::execute, this operation
+ * read latest committed value of the record.
+ *
+ * This means that if another transaction is updating the
+ * record, then the current transaction will not wait.
+ * It will instead use the latest committed value of the
+ * record.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int committedRead();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type dirtyUpdate.
+ * When calling NdbTransaction::execute, this operation
+ * updates without two-phase commit.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int dirtyUpdate();
+
+ /**
+ * Define the NdbOperation to be a standard operation of type dirtyWrite.
+ * When calling NdbTransaction::execute, this operation
+ * writes without two-phase commit.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int dirtyWrite();
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** @} *********************************************************************/
+ /**
+ * @name Define Interpreted Program Operation Type
+ * @{
+ */
+
+ /**
+ * Update a tuple using an interpreted program.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int interpretedUpdateTuple();
+
+ /**
+ * Delete a tuple using an interpreted program.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ virtual int interpretedDeleteTuple();
+#endif
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Specify Search Conditions
+ * @{
+ */
+ /**
+ * Define a search condition with equality.
+ * The condition is true if the attribute has the given value.
+ * To set search conditions on multiple attributes,
+ * use several equals (then all of them must be satisfied for the
+ * tuple to be selected).
+ *
+ * @note For insertTuple() it is also allowed to define the
+ * search key by using setValue().
+ *
+ * @note There are 10 versions of equal() with
+ * slightly different parameters.
+ *
+ * @note If attribute has fixed size, value must include all bytes.
+ * In particular a Char must be native-blank padded.
+ * If attribute has variable size, value must start with
+ * 1 or 2 little-endian length bytes (2 if Long*).
+ *
+ * @param anAttrName Attribute name
+ * @param aValue Attribute value.
+ * @return -1 if unsuccessful.
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int equal(const char* anAttrName, const char* aValue, Uint32 len);
+#endif
+ int equal(const char* anAttrName, const char* aValue);
+ int equal(const char* anAttrName, Int32 aValue);
+ int equal(const char* anAttrName, Uint32 aValue);
+ int equal(const char* anAttrName, Int64 aValue);
+ int equal(const char* anAttrName, Uint64 aValue);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int equal(Uint32 anAttrId, const char* aValue, Uint32 len);
+#endif
+ int equal(Uint32 anAttrId, const char* aValue);
+ int equal(Uint32 anAttrId, Int32 aValue);
+ int equal(Uint32 anAttrId, Uint32 aValue);
+ int equal(Uint32 anAttrId, Int64 aValue);
+ int equal(Uint32 anAttrId, Uint64 aValue);
+
+ /** @} *********************************************************************/
+ /**
+ * @name Specify Attribute Actions for Operations
+ * @{
+ */
+
+ /**
+ * Defines a retrieval operation of an attribute value.
+ * The NDB API allocate memory for the NdbRecAttr object that
+ * will hold the returned attribute value.
+ *
+ * @note Note that it is the applications responsibility
+ * to allocate enough memory for aValue (if non-NULL).
+ * The buffer aValue supplied by the application must be
+ * aligned appropriately. The buffer is used directly
+ * (avoiding a copy penalty) only if it is aligned on a
+ * 4-byte boundary and the attribute size in bytes
+ * (i.e. NdbRecAttr::attrSize times NdbRecAttr::arraySize is
+ * a multiple of 4).
+ *
+ * @note There are two versions of NdbOperation::getValue with
+ * slightly different parameters.
+ *
+ * @note This method does not fetch the attribute value from
+ * the database! The NdbRecAttr object returned by this method
+ * is <em>not</em> readable/printable before the
+ * transaction has been executed with NdbTransaction::execute.
+ *
+ * @param anAttrName Attribute name
+ * @param aValue If this is non-NULL, then the attribute value
+ * will be returned in this parameter.<br>
+ * If NULL, then the attribute value will only
+ * be stored in the returned NdbRecAttr object.
+ * @return An NdbRecAttr object to hold the value of
+ * the attribute, or a NULL pointer
+ * (indicating error).
+ */
+ NdbRecAttr* getValue(const char* anAttrName, char* aValue = 0);
+ NdbRecAttr* getValue(Uint32 anAttrId, char* aValue = 0);
+ NdbRecAttr* getValue(const NdbDictionary::Column*, char* val = 0);
+
+ /**
+ * Define an attribute to set or update in query.
+ *
+ * To set a NULL value, use the following construct:
+ * @code
+ * setValue("ATTR_NAME", (char*)NULL);
+ * @endcode
+ *
+ * There are a number of NdbOperation::setValue methods that
+ * take a certain type as input
+ * (pass by value rather than passing a pointer).
+ * As the interface is currently implemented it is the responsibility
+ * of the application programmer to use the correct types.
+ *
+ * The NDB API will however check that the application sends
+ * a correct length to the interface as given in the length parameter.
+ * The passing of char* as the value can contain any type or
+ * any type of array.
+ * If length is not provided or set to zero,
+ * then the API will assume that the pointer
+ * is correct and not bother with checking it.
+ *
+ * @note For insertTuple() the NDB API will automatically detect that
+ * it is supposed to use equal() instead.
+ *
+ * @note For insertTuple() it is not necessary to use
+ * setValue() on key attributes before other attributes.
+ *
+ * @note There are 14 versions of NdbOperation::setValue with
+ * slightly different parameters.
+ *
+ * @note See note under equal() about value format and length.
+ *
+ * @param anAttrName Name (or Id) of attribute.
+ * @param aValue Attribute value to set.
+ * @return -1 if unsuccessful.
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int setValue(const char* anAttrName, const char* aValue, Uint32 len);
+#endif
+ int setValue(const char* anAttrName, const char* aValue);
+ int setValue(const char* anAttrName, Int32 aValue);
+ int setValue(const char* anAttrName, Uint32 aValue);
+ int setValue(const char* anAttrName, Int64 aValue);
+ int setValue(const char* anAttrName, Uint64 aValue);
+ int setValue(const char* anAttrName, float aValue);
+ int setValue(const char* anAttrName, double aValue);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int setValue(Uint32 anAttrId, const char* aValue, Uint32 len);
+#endif
+ int setValue(Uint32 anAttrId, const char* aValue);
+ int setValue(Uint32 anAttrId, Int32 aValue);
+ int setValue(Uint32 anAttrId, Uint32 aValue);
+ int setValue(Uint32 anAttrId, Int64 aValue);
+ int setValue(Uint32 anAttrId, Uint64 aValue);
+ int setValue(Uint32 anAttrId, float aValue);
+ int setValue(Uint32 anAttrId, double aValue);
+
+ /**
+ * This method replaces getValue/setValue for blobs. It creates
+ * a blob handle NdbBlob. A second call with same argument returns
+ * the previously created handle. The handle is linked to the
+ * operation and is maintained automatically.
+ *
+ * See NdbBlob for details.
+ */
+ virtual NdbBlob* getBlobHandle(const char* anAttrName);
+ virtual NdbBlob* getBlobHandle(Uint32 anAttrId);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** @} *********************************************************************/
+ /**
+ * @name Specify Interpreted Program Instructions
+ * @{
+ */
+
+ /**
+ * Interpreted program instruction: Add a value to an attribute.
+ *
+ * @note Destroys the contents of registers 6 and 7.
+ * (The instruction uses these registers for its operation.)
+ *
+ * @note There are four versions of NdbOperation::incValue with
+ * slightly different parameters.
+ *
+ * @param anAttrName Attribute name.
+ * @param aValue Value to add.
+ * @return -1 if unsuccessful.
+ */
+ int incValue(const char* anAttrName, Uint32 aValue);
+ int incValue(const char* anAttrName, Uint64 aValue);
+ int incValue(Uint32 anAttrId, Uint32 aValue);
+ int incValue(Uint32 anAttrId, Uint64 aValue);
+
+ /**
+ * Interpreted program instruction:
+ * Subtract a value from an attribute in an interpreted operation.
+ *
+ * @note Destroys the contents of registers 6 and 7.
+ * (The instruction uses these registers for its operation.)
+ *
+ * @note There are four versions of NdbOperation::subValue with
+ * slightly different parameters.
+ *
+ * @param anAttrName Attribute name.
+ * @param aValue Value to subtract.
+ * @return -1 if unsuccessful.
+ */
+ int subValue(const char* anAttrName, Uint32 aValue);
+ int subValue(const char* anAttrName, Uint64 aValue);
+ int subValue(Uint32 anAttrId, Uint32 aValue);
+ int subValue(Uint32 anAttrId, Uint64 aValue);
+
+ /**
+ * Interpreted program instruction:
+ * Define a jump label in an interpreted operation.
+ *
+ * @note The labels are automatically numbered starting with 0.
+ * The parameter used by NdbOperation::def_label should
+ * match the automatic numbering to make it easier to
+ * debug the interpreted program.
+ *
+ * @param labelNumber Label number.
+ * @return -1 if unsuccessful.
+ */
+ int def_label(int labelNumber);
+
+ /**
+ * Interpreted program instruction:
+ * Add two registers into a third.
+ *
+ * @param RegSource1 First register.
+ * @param RegSource2 Second register.
+ * @param RegDest Destination register where the result will be stored.
+ * @return -1 if unsuccessful.
+ */
+ int add_reg(Uint32 RegSource1, Uint32 RegSource2, Uint32 RegDest);
+
+ /**
+ * Interpreted program instruction:
+ * Substract RegSource2 from RegSource1 and put the result in RegDest.
+ *
+ * @param RegSource1 First register.
+ * @param RegSource2 Second register.
+ * @param RegDest Destination register where the result will be stored.
+ * @return -1 if unsuccessful.
+ */
+ int sub_reg(Uint32 RegSource1, Uint32 RegSource2, Uint32 RegDest);
+
+ /**
+ * Interpreted program instruction:
+ * Load a constant into a register.
+ *
+ * @param RegDest Destination register.
+ * @param Constant Value to load.
+ * @return -1 if unsuccessful.
+ */
+ int load_const_u32(Uint32 RegDest, Uint32 Constant);
+ int load_const_u64(Uint32 RegDest, Uint64 Constant);
+
+ /**
+ * Interpreted program instruction:
+ * Load NULL value into a register.
+ *
+ * @param RegDest Destination register.
+ * @return -1 if unsuccessful.
+ */
+ int load_const_null(Uint32 RegDest);
+
+ /**
+ * Interpreted program instruction:
+ * Read an attribute into a register.
+ *
+ * @param anAttrName Attribute name.
+ * @param RegDest Destination register.
+ * @return -1 if unsuccessful.
+ */
+ int read_attr(const char* anAttrName, Uint32 RegDest);
+
+ /**
+ * Interpreted program instruction:
+ * Write an attribute from a register.
+ *
+ * @param anAttrName Attribute name.
+ * @param RegSource Source register.
+ * @return -1 if unsuccessful.
+ */
+ int write_attr(const char* anAttrName, Uint32 RegSource);
+
+ /**
+ * Interpreted program instruction:
+ * Read an attribute into a register.
+ *
+ * @param anAttrId the attribute id.
+ * @param RegDest the destination register.
+ * @return -1 if unsuccessful.
+ */
+ int read_attr(Uint32 anAttrId, Uint32 RegDest);
+
+ /**
+ * Interpreted program instruction:
+ * Write an attribute from a register.
+ *
+ * @param anAttrId the attribute id.
+ * @param RegSource the source register.
+ * @return -1 if unsuccessful.
+ */
+ int write_attr(Uint32 anAttrId, Uint32 RegSource);
+
+ /**
+ * Interpreted program instruction:
+ * Define a search condition. Last two letters in the function name
+ * describes the search condition.
+ * The condition compares RegR with RegL and therefore appears
+ * to be reversed.
+ *
+ * - ge RegR >= RegL
+ * - gt RegR > RegL
+ * - le RegR <= RegL
+ * - lt RegR < RegL
+ * - eq RegR = RegL
+ * - ne RegR <> RegL
+ *
+ * @param RegLvalue left value.
+ * @param RegRvalue right value.
+ * @param Label the label to jump to.
+ * @return -1 if unsuccessful.
+ */
+ int branch_ge(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+ int branch_gt(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+ int branch_le(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+ int branch_lt(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+ int branch_eq(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+ int branch_ne(Uint32 RegLvalue, Uint32 RegRvalue, Uint32 Label);
+
+ /**
+ * Interpreted program instruction:
+ * Jump to Label if RegLvalue is not NULL.
+ *
+ * @param RegLvalue the value to check.
+ * @param Label the label to jump to.
+ * @return -1 if unsuccessful.
+ */
+ int branch_ne_null(Uint32 RegLvalue, Uint32 Label);
+
+ /**
+ * Interpreted program instruction:
+ * Jump to Label if RegLvalue is equal to NULL.
+ *
+ * @param RegLvalue Value to check.
+ * @param Label Label to jump to.
+ * @return -1 if unsuccessful.
+ */
+ int branch_eq_null(Uint32 RegLvalue, Uint32 Label);
+
+ /**
+ * Interpreted program instruction:
+ * Jump to Label.
+ *
+ * @param Label Label to jump to.
+ * @return -1 if unsuccessful.
+ */
+ int branch_label(Uint32 Label);
+
+ /**
+ * Interpreted program instruction: branch after memcmp
+ * @param ColId Column to check
+ * @param Label Label to jump to
+ * @return -1 if unsuccessful
+ */
+ int branch_col_eq_null(Uint32 ColId, Uint32 Label);
+ int branch_col_ne_null(Uint32 ColId, Uint32 Label);
+
+ /**
+ * Interpreted program instruction: branch after memcmp
+ * @param ColId column to check
+ * @param val search value
+ * @param len length of search value
+ * @param nopad force non-padded comparison for a Char column
+ * @param Label label to jump to
+ * @return -1 if unsuccessful
+ */
+ int branch_col_eq(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_ne(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_lt(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_le(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_gt(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_ge(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label);
+ /**
+ * The argument is always plain char, even if the field is varchar
+ * (changed in 5.0.22).
+ */
+ int branch_col_like(Uint32 ColId, const void *, Uint32 len,
+ bool nopad, Uint32 Label);
+ int branch_col_notlike(Uint32 ColId, const void *, Uint32 len,
+ bool nopad, Uint32 Label);
+
+ /**
+ * Interpreted program instruction: Exit with Ok
+ *
+ * For scanning transactions,
+ * end interpreted operation and return the row to the application.
+ *
+ * For non-scanning transactions,
+ * exit interpreted program.
+ *
+ * @return -1 if unsuccessful.
+ */
+ int interpret_exit_ok();
+
+ /**
+ * Interpreted program instruction: Exit with Not Ok
+ *
+ * For scanning transactions,
+ * continue with the next row without returning the current row.
+ *
+ * For non-scanning transactions,
+ * abort the whole transaction.
+ *
+ * @note A method also exists without the error parameter.
+ *
+ * @param ErrorCode An error code given by the application programmer.
+ * @return -1 if unsuccessful.
+ */
+ int interpret_exit_nok(Uint32 ErrorCode);
+ int interpret_exit_nok();
+
+
+ /**
+ * Interpreted program instruction:
+ *
+ * For scanning transactions,
+ * return this row, but no more from this fragment
+ *
+ * For non-scanning transactions,
+ * abort the whole transaction.
+ *
+ * @return -1 if unsuccessful.
+ */
+ int interpret_exit_last_row();
+
+ /**
+ * Interpreted program instruction:
+ * Define a subroutine in an interpreted operation.
+ *
+ * @param SubroutineNumber the subroutine number.
+ * @return -1 if unsuccessful.
+ */
+ int def_subroutine(int SubroutineNumber);
+
+ /**
+ * Interpreted program instruction:
+ * Call a subroutine.
+ *
+ * @param Subroutine the subroutine to call.
+ * @return -1 if unsuccessful.
+ */
+ int call_sub(Uint32 Subroutine);
+
+ /**
+ * Interpreted program instruction:
+ * End a subroutine.
+ *
+ * @return -1 if unsuccessful.
+ */
+ int ret_sub();
+#endif
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Error Handling
+ * @{
+ */
+
+ /**
+ * Get the latest error code.
+ *
+ * @return error code.
+ */
+ const NdbError & getNdbError() const;
+
+ /**
+ * Get the method number where the error occured.
+ *
+ * @return method number where the error occured.
+ */
+ int getNdbErrorLine();
+
+ /**
+ * Get table name of this operation.
+ */
+ const char* getTableName() const;
+
+ /**
+ * Get table object for this operation
+ */
+ const NdbDictionary::Table * getTable() const;
+
+ /**
+ * Get the type of access for this operation
+ */
+ const Type getType() const;
+
+ /** @} *********************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Type of operation
+ */
+ enum OperationType {
+ ReadRequest = 0, ///< Read operation
+ UpdateRequest = 1, ///< Update Operation
+ InsertRequest = 2, ///< Insert Operation
+ DeleteRequest = 3, ///< Delete Operation
+ WriteRequest = 4, ///< Write Operation
+ ReadExclusive = 5, ///< Read exclusive
+ OpenScanRequest, ///< Scan Operation
+ OpenRangeScanRequest, ///< Range scan operation
+ NotDefined2, ///< Internal for debugging
+ NotDefined ///< Internal for debugging
+ };
+#endif
+
+ /**
+ * Return lock mode for operation
+ */
+ LockMode getLockMode() const { return theLockMode; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void setAbortOption(Int8 ao) { m_abortOption = ao; }
+
+ /**
+ * Set/get partition key
+ */
+ void setPartitionId(Uint32 id);
+ void setPartitionHash(Uint32 key);
+ void setPartitionHash(const Uint64 *, Uint32 len);
+ Uint32 getPartitionId() const;
+#endif
+protected:
+ int handle_distribution_key(const Uint64 *, Uint32 len);
+protected:
+/******************************************************************************
+ * These are the methods used to create and delete the NdbOperation objects.
+ *****************************************************************************/
+
+ bool needReply();
+/******************************************************************************
+ * These methods are service routines used by the other NDB API classes.
+ *****************************************************************************/
+//--------------------------------------------------------------
+// Initialise after allocating operation to a transaction
+//--------------------------------------------------------------
+ int init(const class NdbTableImpl*, NdbTransaction* aCon);
+ void initInterpreter();
+
+ NdbOperation(Ndb* aNdb, Type aType = PrimaryKeyAccess);
+ virtual ~NdbOperation();
+ void next(NdbOperation*); // Set next pointer
+ NdbOperation* next(); // Get next pointer
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbOperation* next() const;
+ const NdbRecAttr* getFirstRecAttr() const;
+#endif
+protected:
+
+ enum OperationStatus
+ {
+ Init,
+ OperationDefined,
+ TupleKeyDefined,
+ GetValue,
+ SetValue,
+ ExecInterpretedValue,
+ SetValueInterpreted,
+ FinalGetValue,
+ SubroutineExec,
+ SubroutineEnd,
+ WaitResponse,
+ WaitCommitResponse,
+ Finished,
+ ReceiveFinished
+ };
+
+ OperationStatus Status(); // Read the status information
+
+ void Status(OperationStatus); // Set the status information
+
+ void NdbCon(NdbTransaction*); // Set reference to connection
+ // object.
+
+ virtual void release(); // Release all operations
+ // connected to
+ // the operations object.
+ void setStartIndicator();
+
+/******************************************************************************
+ * The methods below is the execution part of the NdbOperation
+ * class. This is where the NDB signals are sent and received. The
+ * operation can send TC[KEY/INDX]REQ, [INDX]ATTRINFO.
+ * It can receive TC[KEY/INDX]CONF, TC[KEY/INDX]REF, [INDX]ATTRINFO.
+ * When an operation is received in its fulness or a refuse message
+ * was sent, then the connection object is told about this situation.
+ *****************************************************************************/
+
+ int doSend(int ProcessorId, Uint32 lastFlag);
+ virtual int prepareSend(Uint32 TC_ConnectPtr,
+ Uint64 TransactionId);
+ virtual void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag);
+
+ int prepareSendInterpreted(); // Help routine to prepare*
+
+ int receiveTCKEYREF(NdbApiSignal*);
+
+ int checkMagicNumber(bool b = true); // Verify correct object
+
+ int checkState_TransId(NdbApiSignal* aSignal);
+
+/******************************************************************************
+ * These are support methods only used locally in this class.
+******************************************************************************/
+
+ virtual int equal_impl(const NdbColumnImpl*,const char* aValue);
+ virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0);
+ int setValue(const NdbColumnImpl* anAttrObject, const char* aValue);
+ NdbBlob* getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* anAttrObject);
+ int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue);
+ int incValue(const NdbColumnImpl* anAttrObject, Uint64 aValue);
+ int subValue(const NdbColumnImpl* anAttrObject, Uint32 aValue);
+ int subValue(const NdbColumnImpl* anAttrObject, Uint64 aValue);
+ int read_attr(const NdbColumnImpl* anAttrObject, Uint32 RegDest);
+ int write_attr(const NdbColumnImpl* anAttrObject, Uint32 RegSource);
+ int branch_reg_reg(Uint32 type, Uint32, Uint32, Uint32);
+ int branch_col(Uint32 type, Uint32, const void *, Uint32, bool, Uint32 Label);
+ int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
+
+ // Handle ATTRINFO signals
+ int insertATTRINFO(Uint32 aData);
+ int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
+
+ int insertKEYINFO(const char* aValue,
+ Uint32 aStartPosition,
+ Uint32 aKeyLenInByte);
+ void reorderKEYINFO();
+
+ virtual void setErrorCode(int aErrorCode);
+ virtual void setErrorCodeAbort(int aErrorCode);
+
+ void handleFailedAI_ElemLen(); // When not all attribute data
+ // were received
+
+ int incCheck(const NdbColumnImpl* anAttrObject);
+ int initial_interpreterCheck();
+ int intermediate_interpreterCheck();
+ int read_attrCheck(const NdbColumnImpl* anAttrObject);
+ int write_attrCheck(const NdbColumnImpl* anAttrObject);
+ int labelCheck();
+ int insertCall(Uint32 aCall);
+ int insertBranch(Uint32 aBranch);
+
+ Uint32 ptr2int() { return theReceiver.getId(); };
+
+ // get table or index key from prepared signals
+ int getKeyFromTCREQ(Uint32* data, Uint32 & size);
+
+/******************************************************************************
+ * These are the private variables that are defined in the operation objects.
+ *****************************************************************************/
+
+ Type m_type;
+
+ NdbReceiver theReceiver;
+
+ NdbError theError; // Errorcode
+ int theErrorLine; // Error line
+
+ Ndb* theNdb; // Point back to the Ndb object.
+ NdbTransaction* theNdbCon; // Point back to the connection object.
+ NdbOperation* theNext; // Next pointer to operation.
+
+ union {
+ NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
+ NdbApiSignal* theSCAN_TABREQ;
+ };
+
+ NdbApiSignal* theFirstATTRINFO; // The first ATTRINFO signal object
+ NdbApiSignal* theCurrentATTRINFO; // The current ATTRINFO signal object
+ Uint32 theTotalCurrAI_Len; // The total number of attribute info
+ // words currently defined
+ Uint32 theAI_LenInCurrAI; // The number of words defined in the
+ // current ATTRINFO signal
+ NdbApiSignal* theLastKEYINFO; // The first KEYINFO signal object
+
+ class NdbLabel* theFirstLabel;
+ class NdbLabel* theLastLabel;
+ class NdbBranch* theFirstBranch;
+ class NdbBranch* theLastBranch;
+ class NdbCall* theFirstCall;
+ class NdbCall* theLastCall;
+ class NdbSubroutine* theFirstSubroutine;
+ class NdbSubroutine* theLastSubroutine;
+ Uint32 theNoOfLabels;
+ Uint32 theNoOfSubroutines;
+
+ Uint32* theKEYINFOptr; // Pointer to where to write KEYINFO
+ Uint32* theATTRINFOptr; // Pointer to where to write ATTRINFO
+
+ const class NdbTableImpl* m_currentTable; // The current table
+ const class NdbTableImpl* m_accessTable; // Index table (== current for pk)
+
+ // Set to TRUE when a tuple key attribute has been defined.
+ Uint32 theTupleKeyDefined[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY][3];
+
+ Uint32 theTotalNrOfKeyWordInSignal; // The total number of
+ // keyword in signal.
+
+ Uint32 theTupKeyLen; // Length of the tuple key in words
+ // left until done
+ Uint8 theNoOfTupKeyLeft; // The number of tuple key attributes
+ OperationType theOperationType; // Read Request, Update Req......
+
+ LockMode theLockMode; // Can be set to WRITE if read operation
+ OperationStatus theStatus; // The status of the operation.
+
+ Uint32 theMagicNumber; // Magic number to verify that object
+ // is correct
+ Uint32 theScanInfo; // Scan info bits (take over flag etc)
+ Uint32 theDistributionKey; // Distribution Key size if used
+
+ Uint32 theSubroutineSize; // Size of subroutines for interpretation
+ Uint32 theInitialReadSize; // Size of initial reads for interpretation
+ Uint32 theInterpretedSize; // Size of interpretation
+ Uint32 theFinalUpdateSize; // Size of final updates for interpretation
+ Uint32 theFinalReadSize; // Size of final reads for interpretation
+
+ Uint8 theStartIndicator; // Indicator of whether start operation
+ Uint8 theCommitIndicator; // Indicator of whether commit operation
+ Uint8 theSimpleIndicator; // Indicator of whether simple operation
+ Uint8 theDirtyIndicator; // Indicator of whether dirty operation
+ Uint8 theInterpretIndicator; // Indicator of whether interpreted operation
+ Int8 theDistrKeyIndicator_; // Indicates whether distr. key is used
+ Uint8 m_no_disk_flag;
+
+ Uint16 m_tcReqGSN;
+ Uint16 m_keyInfoGSN;
+ Uint16 m_attrInfoGSN;
+
+ // Blobs in this operation
+ NdbBlob* theBlobList;
+
+ /*
+ * Abort option per operation, used by blobs. Default -1. If set,
+ * overrides abort option on connection level. If set to IgnoreError,
+ * does not cause execute() to return failure. This is different from
+ * IgnoreError on connection level.
+ */
+ Int8 m_abortOption;
+
+ friend struct Ndb_free_list_t<NdbOperation>;
+};
+
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+inline
+int
+NdbOperation::checkMagicNumber(bool b)
+{
+ if (theMagicNumber != 0xABCDEF01){
+#ifdef NDB_NO_DROPPED_SIGNAL
+ if(b) abort();
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+inline
+void
+NdbOperation::setStartIndicator()
+{
+ theStartIndicator = 1;
+}
+
+inline
+int
+NdbOperation::getNdbErrorLine()
+{
+ return theErrorLine;
+}
+
+/******************************************************************************
+void next(NdbOperation* aNdbOperation);
+
+Parameters: aNdbOperation: Pointers to the NdbOperation object.
+Remark: Set the next variable of the operation object.
+******************************************************************************/
+inline
+void
+NdbOperation::next(NdbOperation* aNdbOperation)
+{
+ theNext = aNdbOperation;
+}
+
+/******************************************************************************
+NdbOperation* next();
+
+Return Value: Return next pointer to NdbOperation object.
+Remark: Get the next variable of the operation object.
+******************************************************************************/
+inline
+NdbOperation*
+NdbOperation::next()
+{
+ return theNext;
+}
+
+inline
+const NdbOperation*
+NdbOperation::next() const
+{
+ return theNext;
+}
+
+inline
+const NdbRecAttr*
+NdbOperation::getFirstRecAttr() const
+{
+ return theReceiver.theFirstRecAttr;
+}
+
+/******************************************************************************
+Type getType()
+
+Return Value Return the Type.
+Remark: Gets type of access.
+******************************************************************************/
+inline
+const NdbOperation::Type
+NdbOperation::getType() const
+{
+ return m_type;
+}
+
+/******************************************************************************
+OperationStatus Status();
+
+Return Value Return the OperationStatus.
+Parameters: aStatus: The status.
+Remark: Sets Operation status.
+******************************************************************************/
+inline
+NdbOperation::OperationStatus
+NdbOperation::Status()
+{
+ return theStatus;
+}
+
+/******************************************************************************
+void Status(OperationStatus aStatus);
+
+Parameters: aStatus: The status.
+Remark: Sets Operation
+ status.
+******************************************************************************/
+inline
+void
+NdbOperation::Status( OperationStatus aStatus )
+{
+ theStatus = aStatus;
+}
+
+/******************************************************************************
+void NdbCon(NdbTransaction* aNdbCon);
+
+Parameters: aNdbCon: Pointers to NdbTransaction object.
+Remark: Set the reference to the connection in the operation object.
+******************************************************************************/
+inline
+void
+NdbOperation::NdbCon(NdbTransaction* aNdbCon)
+{
+ theNdbCon = aNdbCon;
+}
+
+inline
+int
+NdbOperation::equal(const char* anAttrName, const char* aValue, Uint32 len)
+{
+ return equal(anAttrName, aValue);
+}
+
+inline
+int
+NdbOperation::equal(const char* anAttrName, Int32 aPar)
+{
+ return equal(anAttrName, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::equal(const char* anAttrName, Uint32 aPar)
+{
+ return equal(anAttrName, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::equal(const char* anAttrName, Int64 aPar)
+{
+ return equal(anAttrName, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::equal(const char* anAttrName, Uint64 aPar)
+{
+ return equal(anAttrName, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::equal(Uint32 anAttrId, const char* aValue, Uint32 len)
+{
+ return equal(anAttrId, aValue);
+}
+
+inline
+int
+NdbOperation::equal(Uint32 anAttrId, Int32 aPar)
+{
+ return equal(anAttrId, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::equal(Uint32 anAttrId, Uint32 aPar)
+{
+ return equal(anAttrId, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::equal(Uint32 anAttrId, Int64 aPar)
+{
+ return equal(anAttrId, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::equal(Uint32 anAttrId, Uint64 aPar)
+{
+ return equal(anAttrId, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, const char* aValue, Uint32 len)
+{
+ return setValue(anAttrName, aValue);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, Int32 aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, Uint32 aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, Int64 aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, Uint64 aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, float aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(const char* anAttrName, double aPar)
+{
+ return setValue(anAttrName, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, const char* aValue, Uint32 len)
+{
+ return setValue(anAttrId, aValue);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, Int32 aPar)
+{
+ return setValue(anAttrId, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, Uint32 aPar)
+{
+ return setValue(anAttrId, (const char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, Int64 aPar)
+{
+ return setValue(anAttrId, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, Uint64 aPar)
+{
+ return setValue(anAttrId, (const char*)&aPar, (Uint32)8);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, float aPar)
+{
+ return setValue(anAttrId, (char*)&aPar, (Uint32)4);
+}
+
+inline
+int
+NdbOperation::setValue(Uint32 anAttrId, double aPar)
+{
+ return setValue(anAttrId, (const char*)&aPar, (Uint32)8);
+}
+
+#endif // doxygen
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbPool.hpp b/storage/ndb/include/ndbapi/NdbPool.hpp
new file mode 100644
index 00000000000..64cba5a008c
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbPool.hpp
@@ -0,0 +1,35 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+class Ndb;
+class NdbPool;
+
+bool
+create_instance(Uint32 max_ndb_objects,
+ Uint32 no_conn_obj,
+ Uint32 init_no_ndb_objects);
+
+void
+drop_instance();
+
+Ndb*
+get_ndb_object(Uint32 &hint_id,
+ const char* a_catalog_name,
+ const char* a_schema_name);
+
+void
+return_ndb_object(Ndb* returned_object, Uint32 id);
+
diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp
new file mode 100644
index 00000000000..5d9b0832e18
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp
@@ -0,0 +1,416 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbRecAttr_H
+#define NdbRecAttr_H
+
+#include "NdbDictionary.hpp"
+#include "Ndb.hpp"
+
+class NdbOperation;
+
+/**
+ * @class NdbRecAttr
+ * @brief Contains value of an attribute.
+ *
+ * NdbRecAttr objects are used to store the attribute value
+ * after retrieving the value from the NDB Cluster using the method
+ * NdbOperation::getValue. The objects are allocated by the NDB API.
+ * An example application program follows:
+ *
+ * @code
+ * MyRecAttr = MyOperation->getValue("ATTR2", NULL);
+ * if (MyRecAttr == NULL) goto error;
+ *
+ * if (MyTransaction->execute(Commit) == -1) goto error;
+ *
+ * ndbout << MyRecAttr->u_32_value();
+ * @endcode
+ * For more examples, see
+ * @ref ndbapi_simple.cpp.
+ *
+ * @note The NdbRecAttr object is instantiated with its value when
+ * NdbTransaction::execute is called. Before this, the value is
+ * undefined. (NdbRecAttr::isNULL can be used to check
+ * if the value is defined or not.)
+ * This means that an NdbRecAttr object only has valid information
+ * between the time of calling NdbTransaction::execute and
+ * the time of Ndb::closeTransaction.
+ * The value of the null indicator is -1 until the
+ * NdbTransaction::execute method have been called.
+ *
+ * For simple types, there are methods which directly getting the value
+ * from the NdbRecAttr object.
+ *
+ * To get a reference to the value, there are two methods:
+ * NdbRecAttr::aRef (memory is released by NDB API) and
+ * NdbRecAttr::getAttributeObject (memory must be released
+ * by application program).
+ * The two methods may return different pointers.
+ *
+ * There are also methods to check attribute type, attribute size and
+ * array size.
+ * The method NdbRecAttr::arraySize returns the number of elements in the
+ * array (where each element is of size given by NdbRecAttr::attrSize).
+ * The NdbRecAttr::arraySize method is needed when reading variable-sized
+ * attributes.
+ *
+ * @note Variable-sized attributes are not yet supported.
+ */
+class NdbRecAttr
+{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbOperation;
+ friend class NdbIndexScanOperation;
+ friend class NdbEventOperationImpl;
+ friend class NdbReceiver;
+ friend class Ndb;
+ friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&);
+#endif
+
+public:
+ /**
+ * @name Getting meta information
+ * @{
+ */
+ const NdbDictionary::Column * getColumn() const;
+
+ /**
+ * Get type of column
+ * @return Data type of the column
+ */
+ NdbDictionary::Column::Type getType() const;
+
+ /**
+ * Get attribute (element) size in bytes.
+ *
+ */
+ Uint32 get_size_in_bytes() const { return m_size_in_bytes; }
+
+ /** @} *********************************************************************/
+ /**
+ * @name Getting stored value
+ * @{
+ */
+
+ /**
+ * Check if attribute value is NULL.
+ *
+ * @return -1 = Not defined (Failure or
+ * NdbTransaction::execute not yet called).<br>
+ * 0 = Attribute value is defined, but not equal to NULL.<br>
+ * 1 = Attribute value is defined and equal to NULL.
+ */
+ int isNULL() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return 64 bit long value.
+ */
+ Int64 int64_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return 32 bit int value.
+ */
+ Int32 int32_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Short value.
+ */
+ short short_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Char value.
+ */
+ char char_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return 64 bit unsigned value.
+ */
+ Uint64 u_64_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return 32 bit unsigned value.
+ */
+ Uint32 u_32_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Unsigned short value.
+ */
+ Uint16 u_short_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Unsigned char value.
+ */
+ Uint8 u_char_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Float value.
+ */
+ float float_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
+ * @return Double value.
+ */
+ double double_value() const;
+
+ /** @} *********************************************************************/
+ /**
+ * @name Getting reference to stored value
+ * @{
+ */
+
+ /**
+ * Get reference to attribute value.
+ *
+ * Returns a char*-pointer to the value.
+ * The pointer is aligned appropriately for the data type.
+ * The memory is released when Ndb::closeTransaction is executed
+ * for the transaction which read the value.
+ *
+ * @note The memory is released by NDB API.
+ *
+ * @note The pointer to the attribute value stored in an NdbRecAttr
+ * object (i.e. the pointer returned by aRef) is constant.
+ * This means that this method can be called anytime after
+ * NdbOperation::getValue has been called.
+ *
+ * @return Pointer to attribute value.
+ */
+ char* aRef() const;
+
+ /** @} *********************************************************************/
+
+ /**
+ * Make a copy of RecAttr object including all data.
+ *
+ * @note Copy needs to be deleted by application program.
+ */
+ NdbRecAttr * clone() const;
+
+ /**
+ * Destructor
+ *
+ * @note You should only delete RecAttr-copies,
+ * i.e. objects that has been cloned.
+ */
+ ~NdbRecAttr();
+
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbRecAttr* next() const;
+#endif
+private:
+
+ Uint32 attrId() const; /* Get attribute id */
+ bool setNULL(); /* Set NULL indicator */
+ void setUNDEFINED(); //
+
+ bool receive_data(const Uint32*, Uint32);
+
+ void release(); /* Release memory if allocated */
+ void init(); /* Initialise object when allocated */
+
+ NdbRecAttr(Ndb*);
+ void next(NdbRecAttr* aRecAttr);
+ NdbRecAttr* next();
+
+ int setup(const class NdbDictionary::Column* col, char* aValue);
+ int setup(const class NdbColumnImpl* anAttrInfo, char* aValue);
+ /* Set up attributes and buffers */
+ bool copyoutRequired() const; /* Need to copy data to application */
+ void copyout(); /* Copy from storage to application */
+
+ Uint64 theStorage[4]; /* The data storage here if <= 32 bytes */
+ Uint64* theStorageX; /* The data storage here if > 32 bytes */
+ char* theValue; /* The data storage in the application */
+ void* theRef; /* Pointer to one of above */
+
+ NdbRecAttr* theNext; /* Next pointer */
+ Uint32 theAttrId; /* The attribute id */
+
+ Int32 m_size_in_bytes;
+ const NdbDictionary::Column* m_column;
+
+ friend struct Ndb_free_list_t<NdbRecAttr>;
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+inline
+NdbDictionary::Column::Type
+NdbRecAttr::getType() const {
+ return m_column->getType();
+}
+
+inline
+const NdbDictionary::Column *
+NdbRecAttr::getColumn() const {
+ return m_column;
+}
+
+inline
+Int32
+NdbRecAttr::int32_value() const
+{
+ return *(Int32*)theRef;
+}
+
+inline
+short
+NdbRecAttr::short_value() const
+{
+ return *(short*)theRef;
+}
+
+inline
+char
+NdbRecAttr::char_value() const
+{
+ return *(char*)theRef;
+}
+
+inline
+Uint32
+NdbRecAttr::u_32_value() const
+{
+ return *(Uint32*)theRef;
+}
+
+inline
+Uint16
+NdbRecAttr::u_short_value() const
+{
+ return *(Uint16*)theRef;
+}
+
+inline
+Uint8
+NdbRecAttr::u_char_value() const
+{
+ return *(Uint8*)theRef;
+}
+
+inline
+void
+NdbRecAttr::release()
+{
+ if (theStorageX != 0) {
+ delete [] theStorageX;
+ theStorageX = 0;
+ }
+}
+
+inline
+void
+NdbRecAttr::init()
+{
+ theStorageX = 0;
+ theValue = 0;
+ theRef = 0;
+ theNext = 0;
+ theAttrId = 0xFFFF;
+}
+
+inline
+void
+NdbRecAttr::next(NdbRecAttr* aRecAttr)
+{
+ theNext = aRecAttr;
+}
+
+inline
+NdbRecAttr*
+NdbRecAttr::next()
+{
+ return theNext;
+}
+
+inline
+const NdbRecAttr*
+NdbRecAttr::next() const
+{
+ return theNext;
+}
+
+inline
+char*
+NdbRecAttr::aRef() const
+{
+ return (char*)theRef;
+}
+
+inline
+bool
+NdbRecAttr::copyoutRequired() const
+{
+ return theRef != theValue && theValue != 0;
+}
+
+inline
+Uint32
+NdbRecAttr::attrId() const
+{
+ return theAttrId;
+}
+
+inline
+bool
+NdbRecAttr::setNULL()
+{
+ m_size_in_bytes= 0;
+ return true;
+}
+
+inline
+int
+NdbRecAttr::isNULL() const
+{
+ return m_size_in_bytes == 0 ? 1 : (m_size_in_bytes > 0 ? 0 : -1);
+}
+
+inline
+void
+NdbRecAttr::setUNDEFINED()
+{
+ m_size_in_bytes= -1;
+}
+
+class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+#endif
+
diff --git a/storage/ndb/include/ndbapi/NdbReceiver.hpp b/storage/ndb/include/ndbapi/NdbReceiver.hpp
new file mode 100644
index 00000000000..ff6debc7fd3
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbReceiver.hpp
@@ -0,0 +1,150 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbReceiver_H
+#define NdbReceiver_H
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL // Not part of public interface
+
+#include <ndb_types.h>
+
+class Ndb;
+class NdbTransaction;
+
+class NdbReceiver
+{
+ friend class Ndb;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexOperation;
+ friend class NdbIndexScanOperation;
+ friend class NdbTransaction;
+public:
+ enum ReceiverType { NDB_UNINITIALIZED,
+ NDB_OPERATION = 1,
+ NDB_SCANRECEIVER = 2,
+ NDB_INDEX_OPERATION = 3
+ };
+
+ NdbReceiver(Ndb *aNdb);
+ void init(ReceiverType type, void* owner);
+ void release();
+ ~NdbReceiver();
+
+ Uint32 getId(){
+ return m_id;
+ }
+
+ ReceiverType getType(){
+ return m_type;
+ }
+
+ inline NdbTransaction * getTransaction();
+ void* getOwner(){
+ return m_owner;
+ }
+
+ bool checkMagicNumber() const;
+
+ inline void next(NdbReceiver* next) { m_next = next;}
+ inline NdbReceiver* next() { return m_next; }
+
+ void setErrorCode(int);
+private:
+ Uint32 theMagicNumber;
+ Ndb* m_ndb;
+ Uint32 m_id;
+ Uint32 m_tcPtrI;
+ Uint32 m_hidden_count;
+ ReceiverType m_type;
+ void* m_owner;
+ NdbReceiver* m_next;
+
+ /**
+ * At setup
+ */
+ class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr);
+ void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size, Uint32 range);
+ void prepareSend();
+ void calculate_batch_size(Uint32, Uint32, Uint32&, Uint32&, Uint32&);
+
+ int execKEYINFO20(Uint32 info, const Uint32* ptr, Uint32 len);
+ int execTRANSID_AI(const Uint32* ptr, Uint32 len);
+ int execTCOPCONF(Uint32 len);
+ int execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows);
+ class NdbRecAttr* theFirstRecAttr;
+ class NdbRecAttr* theCurrentRecAttr;
+ class NdbRecAttr** m_rows;
+
+ Uint32 m_list_index; // When using multiple
+ Uint32 m_current_row;
+ Uint32 m_result_rows;
+ Uint32 m_defined_rows;
+
+ Uint32 m_expected_result_length;
+ Uint32 m_received_result_length;
+
+ bool nextResult() const { return m_current_row < m_result_rows; }
+ NdbRecAttr* copyout(NdbReceiver&);
+};
+
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
+inline
+bool
+NdbReceiver::checkMagicNumber() const {
+ bool retVal = (theMagicNumber == 0x11223344);
+#ifdef NDB_NO_DROPPED_SIGNAL
+ if(!retVal){
+ abort();
+ }
+#endif
+ return retVal;
+}
+
+inline
+void
+NdbReceiver::prepareSend(){
+ m_current_row = 0;
+ m_received_result_length = 0;
+ m_expected_result_length = 0;
+ theCurrentRecAttr = theFirstRecAttr;
+}
+
+inline
+int
+NdbReceiver::execTCOPCONF(Uint32 len){
+ Uint32 tmp = m_received_result_length;
+ m_expected_result_length = len;
+#ifdef assert
+ assert(!(tmp && !len));
+#endif
+ return ((bool)len ^ (bool)tmp ? 0 : 1);
+}
+
+inline
+int
+NdbReceiver::execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows){
+ m_tcPtrI = tcPtrI;
+ m_result_rows = rows;
+ Uint32 tmp = m_received_result_length;
+ m_expected_result_length = len;
+ return (tmp == len ? 1 : 0);
+}
+
+#endif // DOXYGEN_SHOULD_SKIP_INTERNAL
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbScanFilter.hpp b/storage/ndb/include/ndbapi/NdbScanFilter.hpp
new file mode 100644
index 00000000000..b5457bab99b
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbScanFilter.hpp
@@ -0,0 +1,178 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NDB_SCAN_FILTER_HPP
+#define NDB_SCAN_FILTER_HPP
+
+#include <ndb_types.h>
+
+/**
+ * @class NdbScanFilter
+ * @brief A simple way to specify filters for scan operations
+ *
+ * @note This filter interface is under development and may change in
+ * the future!
+ *
+ */
+class NdbScanFilter {
+public:
+ /**
+ * Constructor
+ * @param op The NdbOperation that the filter belongs to (is applied to).
+ */
+ NdbScanFilter(class NdbOperation * op);
+ ~NdbScanFilter();
+
+ /**
+ * Group operators
+ */
+ enum Group {
+ AND = 1, ///< (x1 AND x2 AND x3)
+ OR = 2, ///< (x1 OR x2 OR X3)
+ NAND = 3, ///< NOT (x1 AND x2 AND x3)
+ NOR = 4 ///< NOT (x1 OR x2 OR x3)
+ };
+
+ enum BinaryCondition
+ {
+ COND_LE = 0, ///< lower bound
+ COND_LT = 1, ///< lower bound, strict
+ COND_GE = 2, ///< upper bound
+ COND_GT = 3, ///< upper bound, strict
+ COND_EQ = 4, ///< equality
+ COND_NE = 5, ///< not equal
+ COND_LIKE = 6, ///< like
+ COND_NOT_LIKE = 7 ///< not like
+ };
+
+ /**
+ * @name Grouping
+ * @{
+ */
+
+ /**
+ * Begin of compound.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int begin(Group group = AND);
+
+ /**
+ * End of compound.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int end();
+
+ /** @} *********************************************************************/
+
+ /**
+ * <i>Explanation missing</i>
+ */
+ int istrue();
+
+ /**
+ * <i>Explanation missing</i>
+ */
+ int isfalse();
+
+ /**
+ * Compare column <b>ColId</b> with <b>val</b>
+ */
+ int cmp(BinaryCondition cond, int ColId, const void *val, Uint32 len = 0);
+
+ /**
+ * @name Integer Comparators
+ * @{
+ */
+ /** Compare column value with integer for equal
+ * ®return 0 if successful, -1 otherwize
+ */
+ int eq(int ColId, Uint32 value) { return cmp(COND_EQ, ColId, &value, 4);}
+
+ /** Compare column value with integer for not equal.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int ne(int ColId, Uint32 value) { return cmp(COND_NE, ColId, &value, 4);}
+ /** Compare column value with integer for less than.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int lt(int ColId, Uint32 value) { return cmp(COND_LT, ColId, &value, 4);}
+ /** Compare column value with integer for less than or equal.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int le(int ColId, Uint32 value) { return cmp(COND_LE, ColId, &value, 4);}
+ /** Compare column value with integer for greater than.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int gt(int ColId, Uint32 value) { return cmp(COND_GT, ColId, &value, 4);}
+ /** Compare column value with integer for greater than or equal.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int ge(int ColId, Uint32 value) { return cmp(COND_GE, ColId, &value, 4);}
+
+ /** Compare column value with integer for equal. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int eq(int ColId, Uint64 value) { return cmp(COND_EQ, ColId, &value, 8);}
+ /** Compare column value with integer for not equal. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int ne(int ColId, Uint64 value) { return cmp(COND_NE, ColId, &value, 8);}
+ /** Compare column value with integer for less than. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int lt(int ColId, Uint64 value) { return cmp(COND_LT, ColId, &value, 8);}
+ /** Compare column value with integer for less than or equal. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int le(int ColId, Uint64 value) { return cmp(COND_LE, ColId, &value, 8);}
+ /** Compare column value with integer for greater than. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int gt(int ColId, Uint64 value) { return cmp(COND_GT, ColId, &value, 8);}
+ /** Compare column value with integer for greater than or equal. 64-bit.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int ge(int ColId, Uint64 value) { return cmp(COND_GE, ColId, &value, 8);}
+ /** @} *********************************************************************/
+
+ /** Check if column value is NULL */
+ int isnull(int ColId);
+ /** Check if column value is non-NULL */
+ int isnotnull(int ColId);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Like comparison operator.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int like(int ColId, const char * val, Uint32 len, bool nopad=false);
+ /**
+ * Notlike comparison operator.
+ * ®return 0 if successful, -1 otherwize
+ */
+ int notlike(int ColId, const char * val, Uint32 len, bool nopad=false);
+ /** @} *********************************************************************/
+#endif
+
+private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class NdbScanFilterImpl;
+#endif
+ class NdbScanFilterImpl & m_impl;
+ NdbScanFilter& operator=(const NdbScanFilter&); ///< Defined not implemented
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbScanOperation.hpp b/storage/ndb/include/ndbapi/NdbScanOperation.hpp
new file mode 100644
index 00000000000..209cd7e29b8
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -0,0 +1,313 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbScanOperation_H
+#define NdbScanOperation_H
+
+#include <NdbOperation.hpp>
+
+class NdbBlob;
+class NdbResultSet;
+class PollGuard;
+
+/**
+ * @class NdbScanOperation
+ * @brief Class of scan operations for use in transactions.
+ */
+class NdbScanOperation : public NdbOperation {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbTransaction;
+ friend class NdbResultSet;
+ friend class NdbOperation;
+ friend class NdbBlob;
+#endif
+
+public:
+ /**
+ * Scan flags. OR-ed together and passed as second argument to
+ * readTuples.
+ */
+ enum ScanFlag {
+ SF_TupScan = (1 << 16), // scan TUP order
+ SF_DiskScan = (2 << 16), // scan in DISK order
+ SF_OrderBy = (1 << 24), // index scan in order
+ SF_Descending = (2 << 24), // index scan in descending order
+ SF_ReadRangeNo = (4 << 24), // enable @ref get_range_no
+ SF_KeyInfo = 1 // request KeyInfo to be sent back
+ };
+
+ /**
+ * readTuples
+ *
+ * @param lock_mode Lock mode
+ * @param scan_flags see @ref ScanFlag
+ * @param parallel No of fragments to scan in parallel (0=max)
+ */
+ virtual
+ int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 scan_flags = 0,
+ Uint32 parallel = 0,
+ Uint32 batch = 0);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * readTuples
+ * @param lock_mode Lock mode
+ * @param batch No of rows to fetch from each fragment at a time
+ * @param parallel No of fragments to scan in parallell
+ * @note specifying 0 for batch and parallell means max performance
+ */
+#ifdef ndb_readtuples_impossible_overload
+ int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 batch = 0, Uint32 parallel = 0, bool keyinfo = false);
+#endif
+
+ inline int readTuples(int parallell){
+ return readTuples(LM_Read, 0, parallell);
+ }
+
+ inline int readTuplesExclusive(int parallell = 0){
+ return readTuples(LM_Exclusive, 0, parallell);
+ }
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NdbBlob* getBlobHandle(const char* anAttrName);
+ NdbBlob* getBlobHandle(Uint32 anAttrId);
+#endif
+
+ /**
+ * Get the next tuple in a scan transaction.
+ *
+ * After each call to nextResult
+ * the buffers and NdbRecAttr objects defined in
+ * NdbOperation::getValue are updated with values
+ * from the scanned tuple.
+ *
+ * @param fetchAllowed If set to false, then fetching is disabled
+ * @param forceSend If true send will occur immediately (see @ref secAdapt)
+ *
+ * The NDB API will contact the NDB Kernel for more tuples
+ * when necessary to do so unless you set the fetchAllowed
+ * to false.
+ * This will force NDB to process any records it
+ * already has in it's caches. When there are no more cached
+ * records it will return 2. You must then call nextResult
+ * with fetchAllowed = true in order to contact NDB for more
+ * records.
+ *
+ * fetchAllowed = false is useful when you want to update or
+ * delete all the records fetched in one transaction(This will save a
+ * lot of round trip time and make updates or deletes of scanned
+ * records a lot faster).
+ * While nextResult(false)
+ * returns 0 take over the record to another transaction. When
+ * nextResult(false) returns 2 you must execute and commit the other
+ * transaction. This will cause the locks to be transferred to the
+ * other transaction, updates or deletes will be made and then the
+ * locks will be released.
+ * After that, call nextResult(true) which will fetch new records and
+ * cache them in the NdbApi.
+ *
+ * @note If you don't take over the records to another transaction the
+ * locks on those records will be released the next time NDB Kernel
+ * is contacted for more records.
+ *
+ * @note Please contact for examples of efficient scan
+ * updates and deletes.
+ *
+ * @note See ndb/examples/ndbapi_scan_example for usage.
+ *
+ * @return
+ * - -1: if unsuccessful,<br>
+ * - 0: if another tuple was received, and<br>
+ * - 1: if there are no more tuples to scan.
+ * - 2: if there are no more cached records in NdbApi
+ */
+ int nextResult(bool fetchAllowed = true, bool forceSend = false);
+
+ /**
+ * Close scan
+ */
+ void close(bool forceSend = false, bool releaseOp = false);
+
+ /**
+ * Lock current tuple
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* lockCurrentTuple();
+ /**
+ * Lock current tuple
+ *
+ * @param lockTrans Transaction that should perform the lock
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* lockCurrentTuple(NdbTransaction* lockTrans);
+ /**
+ * Update current tuple
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* updateCurrentTuple();
+ /**
+ * Update current tuple
+ *
+ * @param updateTrans Transaction that should perform the update
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* updateCurrentTuple(NdbTransaction* updateTrans);
+
+ /**
+ * Delete current tuple
+ * @return 0 on success or -1 on failure
+ */
+ int deleteCurrentTuple();
+ /**
+ * Delete current tuple
+ *
+ * @param takeOverTransaction Transaction that should perform the delete
+ *
+ * @return 0 on success or -1 on failure
+ */
+ int deleteCurrentTuple(NdbTransaction* takeOverTransaction);
+
+ /**
+ * Restart scan with exactly the same
+ * getValues and search conditions
+ */
+ int restart(bool forceSend = false);
+
+protected:
+ NdbScanOperation(Ndb* aNdb,
+ NdbOperation::Type aType = NdbOperation::TableScan);
+ virtual ~NdbScanOperation();
+
+ int nextResultImpl(bool fetchAllowed = true, bool forceSend = false);
+ virtual void release();
+
+ int close_impl(class TransporterFacade*, bool forceSend,
+ PollGuard *poll_guard);
+
+ // Overloaded methods from NdbCursorOperation
+ int executeCursor(int ProcessorId);
+
+ // Overloaded private methods from NdbOperation
+ int init(const NdbTableImpl* tab, NdbTransaction*);
+ int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
+ int doSend(int ProcessorId);
+
+ virtual void setErrorCode(int aErrorCode);
+ virtual void setErrorCodeAbort(int aErrorCode);
+
+ NdbTransaction *m_transConnection;
+
+ // Scan related variables
+ Uint32 theParallelism;
+ Uint32 m_keyInfo;
+
+ int getFirstATTRINFOScan();
+ int doSendScan(int ProcessorId);
+ int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId);
+
+ int fix_receivers(Uint32 parallel);
+ void reset_receivers(Uint32 parallel, Uint32 ordered);
+ Uint32* m_array; // containing all arrays below
+ Uint32 m_allocated_receivers;
+ NdbReceiver** m_receivers; // All receivers
+
+ Uint32* m_prepared_receivers; // These are to be sent
+
+ /**
+ * owned by API/user thread
+ */
+ Uint32 m_current_api_receiver;
+ Uint32 m_api_receivers_count;
+ NdbReceiver** m_api_receivers; // These are currently used by api
+
+ /**
+ * owned by receiver thread
+ */
+ Uint32 m_conf_receivers_count; // NOTE needs mutex to access
+ NdbReceiver** m_conf_receivers; // receive thread puts them here
+
+ /**
+ * owned by receiver thread
+ */
+ Uint32 m_sent_receivers_count; // NOTE needs mutex to access
+ NdbReceiver** m_sent_receivers; // receive thread puts them here
+
+ int send_next_scan(Uint32 cnt, bool close);
+ void receiver_delivered(NdbReceiver*);
+ void receiver_completed(NdbReceiver*);
+ void execCLOSE_SCAN_REP();
+
+ int getKeyFromKEYINFO20(Uint32* data, Uint32 & size);
+ NdbOperation* takeOverScanOp(OperationType opType, NdbTransaction*);
+
+ bool m_ordered;
+ bool m_descending;
+ Uint32 m_read_range_no;
+ NdbRecAttr *m_curr_row; // Pointer to last returned row
+ bool m_executed; // Marker if operation should be released at close
+};
+
+inline
+NdbOperation*
+NdbScanOperation::lockCurrentTuple(){
+ return lockCurrentTuple(m_transConnection);
+}
+
+inline
+NdbOperation*
+NdbScanOperation::lockCurrentTuple(NdbTransaction* takeOverTrans){
+ return takeOverScanOp(NdbOperation::ReadRequest,
+ takeOverTrans);
+}
+
+inline
+NdbOperation*
+NdbScanOperation::updateCurrentTuple(){
+ return updateCurrentTuple(m_transConnection);
+}
+
+inline
+NdbOperation*
+NdbScanOperation::updateCurrentTuple(NdbTransaction* takeOverTrans){
+ return takeOverScanOp(NdbOperation::UpdateRequest,
+ takeOverTrans);
+}
+
+inline
+int
+NdbScanOperation::deleteCurrentTuple(){
+ return deleteCurrentTuple(m_transConnection);
+}
+
+inline
+int
+NdbScanOperation::deleteCurrentTuple(NdbTransaction * takeOverTrans){
+ void * res = takeOverScanOp(NdbOperation::DeleteRequest,
+ takeOverTrans);
+ if(res == 0)
+ return -1;
+ return 0;
+}
+
+#endif
diff --git a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp
new file mode 100644
index 00000000000..8d367f1620a
--- /dev/null
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp
@@ -0,0 +1,1060 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NdbTransaction_H
+#define NdbTransaction_H
+
+#include <ndb_types.h>
+#include "NdbError.hpp"
+#include "NdbDictionary.hpp"
+#include "Ndb.hpp"
+
+class NdbTransaction;
+class NdbOperation;
+class NdbScanOperation;
+class NdbIndexScanOperation;
+class NdbIndexOperation;
+class NdbApiSignal;
+class Ndb;
+class NdbBlob;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+// to be documented later
+/**
+ * NdbAsynchCallback functions are used when executing asynchronous
+ * transactions (using NdbTransaction::executeAsynchPrepare, or
+ * NdbTransaction::executeAsynch).
+ * The functions are called when the execute has finished.
+ * See @ref secAsync for more information.
+ */
+typedef void (* NdbAsynchCallback)(int, NdbTransaction*, void*);
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+enum AbortOption {
+ CommitIfFailFree= 0,
+ TryCommit= 0,
+ AbortOnError= 0,
+ CommitAsMuchAsPossible= 2,
+ AO_IgnoreError= 2
+};
+enum ExecType {
+ NoExecTypeDef = -1,
+ Prepare,
+ NoCommit,
+ Commit,
+ Rollback
+};
+#endif
+
+/**
+ * @class NdbTransaction
+ * @brief Represents a transaction.
+ *
+ * A transaction (represented by an NdbTransaction object)
+ * belongs to an Ndb object and is created using
+ * Ndb::startTransaction().
+ * A transaction consists of a list of operations
+ * (represented by NdbOperation, NdbScanOperation, NdbIndexOperation,
+ * and NdbIndexScanOperation objects).
+ * Each operation access exactly one table.
+ *
+ * After getting the NdbTransaction object,
+ * the first step is to get (allocate) an operation given the table name using
+ * one of the methods getNdbOperation(), getNdbScanOperation(),
+ * getNdbIndexOperation(), or getNdbIndexScanOperation().
+ * Then the operation is defined.
+ * Several operations can be defined on the same
+ * NdbTransaction object, they will in that case be executed in parallell.
+ * When all operations are defined, the execute()
+ * method sends them to the NDB kernel for execution.
+ *
+ * The execute() method returns when the NDB kernel has
+ * completed execution of all operations defined before the call to
+ * execute(). All allocated operations should be properly defined
+ * before calling execute().
+ *
+ * A call to execute() uses one out of three types of execution:
+ * -# NdbTransaction::NoCommit Executes operations without committing them.
+ * -# NdbTransaction::Commit Executes remaining operation and commits the
+ * complete transaction
+ * -# NdbTransaction::Rollback Rollbacks the entire transaction.
+ *
+ * execute() is equipped with an extra error handling parameter.
+ * There are two alternatives:
+ * -# NdbTransaction::AbortOnError (default).
+ * The transaction is aborted if there are any error during the
+ * execution
+ * -# NdbTransaction::AO_IgnoreError
+ * Continue execution of transaction even if operation fails
+ *
+ */
+
+/* FUTURE IMPLEMENTATION:
+ * Later a prepare mode will be added when Ndb supports Prepare-To-Commit
+ * The NdbTransaction can deliver the Transaction Id of the transaction.
+ * After committing a transaction it is also possible to retrieve the
+ * global transaction checkpoint which the transaction was put in.
+ *
+ * FUTURE IMPLEMENTATION:
+ * There are three methods for acquiring the NdbOperation.
+ * -# The first method is the normal where a table name is
+ * provided. In this case the primary key must be supplied through
+ * the use of the NdbOperation::equal methods on the NdbOperation object.
+ * -# The second method provides the tuple identity of the tuple to be
+ * read. The tuple identity contains a table identifier and will
+ * thus be possible to use to ensure the attribute names provided
+ * are correct. If an object-oriented layer is put on top of NDB
+ * Cluster it is essential that all tables derived from a base
+ * class has the same attributes with the same type and the same
+ * name. Thus the application can use the tuple identity and need
+ * not known the table of the tuple. As long as the table is
+ * derived from the known base class everything is ok.
+ * It is not possible to provide any primary key since it is
+ * already supplied with the call to NdbTransaction::getNdbOperation.
+ * -# The third method is used when a scanned tuple is to be transferred to
+ * another transaction. In this case it is not possible to define the
+ * primary key since it came along from the scanned tuple.
+ *
+ */
+
+class NdbTransaction
+{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ friend class Ndb;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexOperation;
+ friend class NdbIndexScanOperation;
+ friend class NdbBlob;
+ friend class ha_ndbcluster;
+#endif
+
+public:
+
+ /**
+ * Commit type of transaction
+ */
+ enum AbortOption {
+ AbortOnError= ///< Abort transaction on failed operation
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::AbortOnError
+#endif
+ ,AO_IgnoreError= ///< Transaction continues on failed operation
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::AO_IgnoreError
+#endif
+ };
+
+ /**
+ * Execution type of transaction
+ */
+ enum ExecType {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NoExecTypeDef=
+ ::NoExecTypeDef, ///< Erroneous type (Used for debugging only)
+ Prepare= ::Prepare, ///< <i>Missing explanation</i>
+#endif
+ NoCommit= ///< Execute the transaction as far as it has
+ ///< been defined, but do not yet commit it
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::NoCommit
+#endif
+ ,Commit= ///< Execute and try to commit the transaction
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::Commit
+#endif
+ ,Rollback ///< Rollback transaction
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = ::Rollback
+#endif
+ };
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get an NdbOperation for a table.
+ * Note that the operation has to be defined before it is executed.
+ *
+ * @note All operations within the same transaction need to
+ * be initialized with this method.
+ *
+ * @param aTableName The table name.
+ * @return Pointer to an NdbOperation object if successful, otherwise NULL.
+ */
+ NdbOperation* getNdbOperation(const char* aTableName);
+#endif
+
+ /**
+ * Get an NdbOperation for a table.
+ * Note that the operation has to be defined before it is executed.
+ *
+ * @note All operations within the same transaction need to
+ * be initialized with this method.
+ *
+ * @param aTable
+ * A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return Pointer to an NdbOperation object if successful, otherwise NULL.
+ */
+ NdbOperation* getNdbOperation(const NdbDictionary::Table * aTable);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get an operation from NdbScanOperation idlelist and
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param aTableName The table name.
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbScanOperation* getNdbScanOperation(const char* aTableName);
+#endif
+
+ /**
+ * Get an operation from NdbScanOperation idlelist and
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param aTable
+ * A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * aTable);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndexName The index name.
+ * @param aTableName The table name.
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbIndexScanOperation* getNdbIndexScanOperation(const char* anIndexName,
+ const char* aTableName);
+ NdbIndexScanOperation* getNdbIndexScanOperation
+ (const NdbDictionary::Index *anIndex, const NdbDictionary::Table *aTable);
+#endif
+
+ /**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex
+ An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbIndexScanOperation* getNdbIndexScanOperation
+ (const NdbDictionary::Index *anIndex);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get an operation from NdbIndexOperation idlelist and
+ * get the NdbTransaction object that
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndexName The index name (as created by createIndex).
+ * @param aTableName The table name.
+ * @return Pointer to an NdbIndexOperation object if
+ * successful, otherwise NULL
+ */
+ NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
+ const char* aTableName);
+ NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *anIndex,
+ const NdbDictionary::Table *aTable);
+#endif
+
+ /**
+ * Get an operation from NdbIndexOperation idlelist and
+ * get the NdbTransaction object that
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex
+ * An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @return Pointer to an NdbIndexOperation object if
+ * successful, otherwise NULL
+ */
+ NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *anIndex);
+
+ /**
+ * @name Execute Transaction
+ * @{
+ */
+
+ /**
+ * Executes transaction.
+ *
+ * @param execType Execution type:<br>
+ * ExecType::NoCommit executes operations without
+ * committing them.<br>
+ * ExecType::Commit executes remaining operations and
+ * commits the complete transaction.<br>
+ * ExecType::Rollback rollbacks the entire transaction.
+ * @param abortOption Handling of error while excuting
+ * AbortOnError - Abort transaction if an operation fail
+ * IgnoreError - Accept failing operations
+ * @param force When operations should be sent to NDB Kernel.
+ * (See @ref secAdapt.)
+ * - 0: non-force, adaptive algorithm notices it
+ * (default);
+ * - 1: force send, adaptive algorithm notices it;
+ * - 2: non-force, adaptive algorithm do not notice
+ * the send.
+ * @return 0 if successful otherwise -1.
+ */
+ int execute(ExecType execType,
+ AbortOption abortOption = AbortOnError,
+ int force = 0 );
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int execute(::ExecType execType,
+ ::AbortOption abortOption = ::AbortOnError,
+ int force = 0 )
+ { return execute ((ExecType)execType,(AbortOption)abortOption,force); }
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ // to be documented later
+ /**
+ * Prepare an asynchronous transaction.
+ *
+ * See @ref secAsync for more information on
+ * how to use this method.
+ *
+ * @param execType Execution type:<br>
+ * ExecType::NoCommit executes operations without committing them.<br>
+ * ExecType::Commit executes remaining operations and commits the
+ * complete transaction.<br>
+ * ExecType::Rollback rollbacks the entire transaction.
+ * @param callback A callback method. This method gets
+ * called when the transaction has been
+ * executed. See @ref ndbapi_async1.cpp
+ * for an example on how to specify and use
+ * a callback method.
+ * @param anyObject A void pointer. This pointer is forwarded to the
+ * callback method and can be used to give
+ * the callback method some data to work on.
+ * It is up to the application programmer
+ * to decide on the use of this pointer.
+ * @param abortOption see @ref execute
+ */
+ void executeAsynchPrepare(ExecType execType,
+ NdbAsynchCallback callback,
+ void* anyObject,
+ AbortOption abortOption = AbortOnError);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ void executeAsynchPrepare(::ExecType execType,
+ NdbAsynchCallback callback,
+ void* anyObject,
+ ::AbortOption abortOption = ::AbortOnError)
+ { executeAsynchPrepare((ExecType)execType, callback, anyObject,
+ (AbortOption)abortOption); }
+#endif
+
+ /**
+ * Prepare and send an asynchronous transaction.
+ *
+ * This method perform the same action as
+ * NdbTransaction::executeAsynchPrepare
+ * but also sends the operations to the NDB kernel.
+ *
+ * See NdbTransaction::executeAsynchPrepare for information
+ * about the parameters of this method.
+ *
+ * See @ref secAsync for more information on
+ * how to use this method.
+ */
+ void executeAsynch(ExecType aTypeOfExec,
+ NdbAsynchCallback aCallback,
+ void* anyObject,
+ AbortOption abortOption = AbortOnError);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ void executeAsynch(::ExecType aTypeOfExec,
+ NdbAsynchCallback aCallback,
+ void* anyObject,
+ ::AbortOption abortOption= ::AbortOnError)
+ { executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject,
+ (AbortOption)abortOption); }
+#endif
+#endif
+ /**
+ * Refresh
+ * Update timeout counter of this transaction
+ * in the database. If you want to keep the transaction
+ * active in the database longer than the
+ * transaction abort timeout.
+ * @note It's not advised to take a lock on a record and keep it
+ * for a extended time since this can impact other transactions.
+ *
+ */
+ int refresh();
+
+ /**
+ * Close transaction
+ *
+ * @note Equivalent to to calling Ndb::closeTransaction()
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * @note It is not allowed to call NdbTransaction::close after sending the
+ * transaction asynchronously before the callback method has
+ * been called.
+ * (The application should keep track of the number of
+ * outstanding transactions and wait until all of them
+ * has completed before calling NdbTransaction::close).
+ * If the transaction is not committed it will be aborted.
+ */
+#endif
+ void close();
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Restart transaction
+ *
+ * Once a transaction has been completed successfully
+ * it can be started again wo/ calling closeTransaction/startTransaction
+ *
+ * @note This method also releases completed operations
+ *
+ * @note This method does not close open scans,
+ * c.f. NdbScanOperation::close()
+ *
+ * @note This method can only be called _directly_ after commit
+ * and only if commit is successful
+ */
+ int restart();
+#endif
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Meta Information
+ * @{
+ */
+
+ /**
+ * Get global checkpoint identity (GCI) of transaction.
+ *
+ * Each committed transaction belong to a GCI.
+ * The log for the committed transaction is saved on
+ * disk when a global checkpoint occurs.
+ *
+ * Whether or not the global checkpoint with this GCI has been
+ * saved on disk or not cannot be determined by this method.
+ *
+ * By comparing the GCI of a transaction with the value
+ * last GCI restored in a restarted NDB Cluster one can determine
+ * whether the transaction was restored or not.
+ *
+ * @note Global Checkpoint Identity is undefined for scan transactions
+ * (This is because no updates are performed in scan transactions.)
+ *
+ * @return GCI of transaction or -1 if GCI is not available.
+ * (Note that there has to be an NdbTransaction::execute call
+ * with Ndb::Commit for the GCI to be available.)
+ */
+ int getGCI();
+
+ /**
+ * Get transaction identity.
+ *
+ * @return Transaction id.
+ */
+ Uint64 getTransactionId();
+
+ /**
+ * The commit status of the transaction.
+ */
+ enum CommitStatusType {
+ NotStarted, ///< Transaction not yet started
+ Started, ///< <i>Missing explanation</i>
+ Committed, ///< Transaction has been committed
+ Aborted, ///< Transaction has been aborted
+ NeedAbort ///< <i>Missing explanation</i>
+ };
+
+ /**
+ * Get the commit status of the transaction.
+ *
+ * @return The commit status of the transaction
+ */
+ CommitStatusType commitStatus();
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Error Handling
+ * @{
+ */
+
+ /**
+ * Get error object with information about the latest error.
+ *
+ * @return An error object with information about the latest error.
+ */
+ const NdbError & getNdbError() const;
+
+ /**
+ * Get the latest NdbOperation which had an error.
+ * This method is used on the NdbTransaction object to find the
+ * NdbOperation causing an error.
+ * To find more information about the
+ * actual error, use method NdbOperation::getNdbError()
+ * on the returned NdbOperation object.
+ *
+ * @return The NdbOperation causing the latest error.
+ */
+ NdbOperation* getNdbErrorOperation();
+
+ /**
+ * Get the method number where the latest error occured.
+ *
+ * @return Line number where latest error occured.
+ */
+ int getNdbErrorLine();
+
+ /**
+ * Get completed (i.e. executed) operations of a transaction
+ *
+ * This method should only be used <em>after</em> a transaction
+ * has been executed.
+ * - NdbTransaction::getNextCompletedOperation(NULL) returns the
+ * first NdbOperation object.
+ * - NdbTransaction::getNextCompletedOperation(op) returns the
+ * NdbOperation object defined after the NdbOperation "op".
+ *
+ * This method is typically used to fetch all NdbOperation:s of
+ * a transaction to check for errors (use NdbOperation::getNdbError
+ * to fetch the NdbError object of an NdbOperation).
+ *
+ * @note This method should only be used after the transaction has been
+ * executed and before the transaction has been closed.
+ *
+ * @param op Operation, NULL means get first operation
+ * @return Operation "after" op
+ */
+ const NdbOperation * getNextCompletedOperation(const NdbOperation * op)const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbOperation* getFirstDefinedOperation()const{return theFirstOpInList;}
+ const NdbOperation* getLastDefinedOperation()const{return theLastOpInList;}
+
+ /** @} *********************************************************************/
+
+ /**
+ * Execute the transaction in NoCommit mode if there are any not-yet
+ * executed blob part operations of given types. Otherwise do
+ * nothing. The flags argument is bitwise OR of (1 << optype) where
+ * optype comes from NdbOperation::OperationType. Only the basic PK
+ * ops are used (read, insert, update, delete).
+ */
+ int executePendingBlobOps(Uint8 flags = 0xFF);
+
+ /**
+ * Get nodeId of TC for this transaction
+ */
+ Uint32 getConnectedNodeId(); // Get Connected node id
+#endif
+
+private:
+ /**
+ * Release completed operations
+ */
+ void releaseCompletedOperations();
+
+ typedef Uint64 TimeMillis_t;
+ /**************************************************************************
+ * These methods are service methods to other classes in the NDBAPI. *
+ **************************************************************************/
+
+ /**************************************************************************
+ * These are the create and delete methods of this class. *
+ **************************************************************************/
+ NdbTransaction(Ndb* aNdb);
+ ~NdbTransaction();
+
+ void init(); // Initialize connection object for new transaction
+
+ int executeNoBlobs(ExecType execType,
+ AbortOption abortOption = AbortOnError,
+ int force = 0 );
+
+ /**
+ * Set Connected node id
+ * and sequence no
+ */
+ void setConnectedNodeId( Uint32 nodeId, Uint32 sequence);
+
+ void setMyBlockReference( int ); // Set my block refrerence
+ void setTC_ConnectPtr( Uint32 ); // Sets TC Connect pointer
+ int getTC_ConnectPtr(); // Gets TC Connect pointer
+ void setBuddyConPtr(Uint32); // Sets Buddy Con Ptr
+ Uint32 getBuddyConPtr(); // Gets Buddy Con Ptr
+ NdbTransaction* next(); // Returns the next pointer
+ void next(NdbTransaction*); // Sets the next pointer
+
+ enum ConStatusType {
+ NotConnected,
+ Connecting,
+ Connected,
+ DisConnecting,
+ ConnectFailure
+ };
+ ConStatusType Status(); // Read the status information
+ void Status(ConStatusType); // Set the status information
+
+ Uint32 get_send_size(); // Get size to send
+ void set_send_size(Uint32); // Set size to send;
+
+ int receiveDIHNDBTAMPER(NdbApiSignal* anApiSignal);
+ int receiveTCSEIZECONF(NdbApiSignal* anApiSignal);
+ int receiveTCSEIZEREF(NdbApiSignal* anApiSignal);
+ int receiveTCRELEASECONF(NdbApiSignal* anApiSignal);
+ int receiveTCRELEASEREF(NdbApiSignal* anApiSignal);
+ int receiveTC_COMMITCONF(const class TcCommitConf *);
+ int receiveTCKEYCONF(const class TcKeyConf *, Uint32 aDataLength);
+ int receiveTCKEY_FAILCONF(const class TcKeyFailConf *);
+ int receiveTCKEY_FAILREF(NdbApiSignal* anApiSignal);
+ int receiveTC_COMMITREF(NdbApiSignal* anApiSignal);
+ int receiveTCROLLBACKCONF(NdbApiSignal* anApiSignal); // Rec TCPREPARECONF ?
+ int receiveTCROLLBACKREF(NdbApiSignal* anApiSignal); // Rec TCPREPAREREF ?
+ int receiveTCROLLBACKREP(NdbApiSignal* anApiSignal);
+ int receiveTCINDXCONF(const class TcIndxConf *, Uint32 aDataLength);
+ int receiveTCINDXREF(NdbApiSignal*);
+ int receiveSCAN_TABREF(NdbApiSignal*);
+ int receiveSCAN_TABCONF(NdbApiSignal*, const Uint32*, Uint32 len);
+
+ int doSend(); // Send all operations
+ int sendROLLBACK(); // Send of an ROLLBACK
+ int sendTC_HBREP(); // Send a TCHBREP signal;
+ int sendCOMMIT(); // Send a TC_COMMITREQ signal;
+ void setGCI(int GCI); // Set the global checkpoint identity
+
+ int OpCompleteFailure(Uint8 abortoption, bool setFailure = true);
+ int OpCompleteSuccess();
+ void CompletedOperations(); // Move active ops to list of completed
+
+ void OpSent(); // Operation Sent with success
+
+ // Free connection related resources and close transaction
+ void release();
+
+ // Release all operations in connection
+ void releaseOperations();
+
+ // Release all cursor operations in connection
+ void releaseOps(NdbOperation*);
+ void releaseScanOperations(NdbIndexScanOperation*);
+ bool releaseScanOperation(NdbIndexScanOperation** listhead,
+ NdbIndexScanOperation** listtail,
+ NdbIndexScanOperation* op);
+ void releaseExecutedScanOperation(NdbIndexScanOperation*);
+
+ // Set the transaction identity of the transaction
+ void setTransactionId(Uint64 aTransactionId);
+
+ // Indicate something went wrong in the definition phase
+ void setErrorCode(int anErrorCode);
+
+ // Indicate something went wrong in the definition phase
+ void setOperationErrorCode(int anErrorCode);
+
+ // Indicate something went wrong in the definition phase
+ void setOperationErrorCodeAbort(int anErrorCode, int abortOption = -1);
+
+ int checkMagicNumber(); // Verify correct object
+ NdbOperation* getNdbOperation(const class NdbTableImpl* aTable,
+ NdbOperation* aNextOp = 0);
+ NdbIndexScanOperation* getNdbScanOperation(const class NdbTableImpl* aTable);
+ NdbIndexOperation* getNdbIndexOperation(const class NdbIndexImpl* anIndex,
+ const class NdbTableImpl* aTable,
+ NdbOperation* aNextOp = 0);
+ NdbIndexScanOperation* getNdbIndexScanOperation(const NdbIndexImpl* index,
+ const NdbTableImpl* table);
+
+ void handleExecuteCompletion();
+
+ /****************************************************************************
+ * These are the private variables of this class.
+ ****************************************************************************/
+
+ Uint32 ptr2int();
+ Uint32 theId;
+
+ // Keeps track of what the send method should do.
+ enum SendStatusType {
+ NotInit,
+ InitState,
+ sendOperations,
+ sendCompleted,
+ sendCOMMITstate,
+ sendABORT,
+ sendABORTfail,
+ sendTC_ROLLBACK,
+ sendTC_COMMIT,
+ sendTC_OP
+ };
+ SendStatusType theSendStatus;
+ NdbAsynchCallback theCallbackFunction; // Pointer to the callback function
+ void* theCallbackObject; // The callback object pointer
+ Uint32 theTransArrayIndex; // Current index in a transaction
+ // array for this object
+ TimeMillis_t theStartTransTime; // Start time of the transaction
+
+ NdbError theError; // Errorcode on transaction
+ int theErrorLine; // Method number of last error in NdbOperation
+ NdbOperation* theErrorOperation; // The NdbOperation where the error occurred
+
+ Ndb* theNdb; // Pointer to Ndb object
+ NdbTransaction* theNext; // Next pointer. Used in idle list.
+
+ NdbOperation* theFirstOpInList; // First operation in defining list.
+ NdbOperation* theLastOpInList; // Last operation in defining list.
+
+ NdbOperation* theFirstExecOpInList; // First executing operation in list
+ NdbOperation* theLastExecOpInList; // Last executing operation in list.
+
+
+ NdbOperation* theCompletedFirstOp; // First & last operation in completed
+ NdbOperation* theCompletedLastOp; // operation list.
+
+ Uint32 theNoOfOpSent; // How many operations have been sent
+ Uint32 theNoOfOpCompleted; // How many operations have completed
+ Uint32 theNoOfOpFetched; // How many operations was actually fetched
+ Uint32 theMyRef; // Our block reference
+ Uint32 theTCConPtr; // Transaction Co-ordinator connection pointer.
+ Uint64 theTransactionId; // theTransactionId of the transaction
+ Uint32 theGlobalCheckpointId; // The gloabl checkpoint identity of the transaction
+ Uint64 *p_latest_trans_gci; // Reference to latest gci for connection
+ ConStatusType theStatus; // The status of the connection
+ enum CompletionStatus {
+ NotCompleted,
+ CompletedSuccess,
+ CompletedFailure,
+ DefinitionFailure
+ } theCompletionStatus; // The Completion status of the transaction
+ CommitStatusType theCommitStatus; // The commit status of the transaction
+ Uint32 theMagicNumber; // Magic Number to verify correct object
+
+ Uint32 thePriority; // Transaction Priority
+
+ enum ReturnType { ReturnSuccess, ReturnFailure };
+ ReturnType theReturnStatus; // Did we have any read/update/delete failing
+ // to find the tuple.
+ bool theTransactionIsStarted;
+ bool theInUseState;
+ bool theSimpleState;
+ Uint8 m_abortOption; // Type of commi
+
+ enum ListState {
+ NotInList,
+ InPreparedList,
+ InSendList,
+ InCompletedList
+ } theListState;
+
+ Uint32 theDBnode; // The database node we are connected to
+ Uint32 theNodeSequence; // The sequence no of the db node
+ bool theReleaseOnClose;
+
+ /**
+ * handle transaction spanning
+ * multiple TC/db nodes
+ *
+ * 1) Bitmask with used nodes
+ * 2) Bitmask with nodes failed during op
+ */
+ Uint32 m_db_nodes[2];
+ Uint32 m_failed_db_nodes[2];
+
+ int report_node_failure(Uint32 id);
+
+ // Scan operations
+ bool m_waitForReply;
+ NdbIndexScanOperation* m_theFirstScanOperation;
+ NdbIndexScanOperation* m_theLastScanOperation;
+
+ NdbIndexScanOperation* m_firstExecutedScanOp;
+
+ // Scan operations
+ // The operation actually performing the scan
+ NdbScanOperation* theScanningOp;
+ Uint32 theBuddyConPtr;
+ // optim: any blobs
+ bool theBlobFlag;
+ Uint8 thePendingBlobOps;
+ inline bool hasBlobOperation() { return theBlobFlag; }
+
+ static void sendTC_COMMIT_ACK(class TransporterFacade *, NdbApiSignal *,
+ Uint32 transId1, Uint32 transId2,
+ Uint32 aBlockRef);
+
+ void completedFail(const char * s);
+#ifdef VM_TRACE
+ void printState();
+#endif
+ bool checkState_TransId(const Uint32 * transId) const;
+
+ void remove_list(NdbOperation*& head, NdbOperation*);
+ void define_scan_op(NdbIndexScanOperation*);
+
+ friend class HugoOperations;
+ friend struct Ndb_free_list_t<NdbTransaction>;
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+inline
+Uint32
+NdbTransaction::get_send_size()
+{
+ return 0;
+}
+
+inline
+void
+NdbTransaction::set_send_size(Uint32 send_size)
+{
+ return;
+}
+
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
+inline
+int
+NdbTransaction::checkMagicNumber()
+{
+ if (theMagicNumber == 0x37412619)
+ return 0;
+ else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ return -1;
+ }
+}
+
+inline
+bool
+NdbTransaction::checkState_TransId(const Uint32 * transId) const {
+ const Uint32 tTmp1 = transId[0];
+ const Uint32 tTmp2 = transId[1];
+ Uint64 tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
+ bool b = theStatus == Connected && theTransactionId == tRecTransId;
+ return b;
+}
+
+/************************************************************************************************
+void setTransactionId(Uint64 aTransactionId);
+
+Remark: Set the transaction identity.
+************************************************************************************************/
+inline
+void
+NdbTransaction::setTransactionId(Uint64 aTransactionId)
+{
+ theTransactionId = aTransactionId;
+}
+
+inline
+void
+NdbTransaction::setConnectedNodeId(Uint32 aNode, Uint32 aSequenceNo)
+{
+ theDBnode = aNode;
+ theNodeSequence = aSequenceNo;
+}
+/******************************************************************************
+int getConnectedNodeId();
+
+Return Value: Return theDBnode.
+Remark: Get Connected node id.
+******************************************************************************/
+inline
+Uint32
+NdbTransaction::getConnectedNodeId()
+{
+ return theDBnode;
+}
+/******************************************************************************
+void setMyBlockReference(int aBlockRef);
+
+Parameters: aBlockRef: The block refrerence.
+Remark: Set my block refrerence.
+******************************************************************************/
+inline
+void
+NdbTransaction::setMyBlockReference(int aBlockRef)
+{
+ theMyRef = aBlockRef;
+}
+/******************************************************************************
+void setTC_ConnectPtr(Uint32 aTCConPtr);
+
+Parameters: aTCConPtr: The connection pointer.
+Remark: Sets TC Connect pointer.
+******************************************************************************/
+inline
+void
+NdbTransaction::setTC_ConnectPtr(Uint32 aTCConPtr)
+{
+ theTCConPtr = aTCConPtr;
+}
+
+/******************************************************************************
+int getTC_ConnectPtr();
+
+Return Value: Return theTCConPtr.
+Remark: Gets TC Connect pointer.
+******************************************************************************/
+inline
+int
+NdbTransaction::getTC_ConnectPtr()
+{
+ return theTCConPtr;
+}
+
+inline
+void
+NdbTransaction::setBuddyConPtr(Uint32 aBuddyConPtr)
+{
+ theBuddyConPtr = aBuddyConPtr;
+}
+
+inline
+Uint32 NdbTransaction::getBuddyConPtr()
+{
+ return theBuddyConPtr;
+}
+
+/******************************************************************************
+NdbTransaction* next();
+
+inline
+void
+NdbTransaction::setBuddyConPtr(Uint32 aBuddyConPtr)
+{
+ theBuddyConPtr = aBuddyConPtr;
+}
+
+inline
+Uint32 NdbTransaction::getBuddyConPtr()
+{
+ return theBuddyConPtr;
+}
+
+Return Value: Return next pointer to NdbTransaction object.
+Remark: Get the next pointer.
+******************************************************************************/
+inline
+NdbTransaction*
+NdbTransaction::next()
+{
+ return theNext;
+}
+
+/******************************************************************************
+void next(NdbTransaction aTransaction);
+
+Parameters: aTransaction: The connection object.
+Remark: Sets the next pointer.
+******************************************************************************/
+inline
+void
+NdbTransaction::next(NdbTransaction* aTransaction)
+{
+ theNext = aTransaction;
+}
+
+/******************************************************************************
+ConStatusType Status();
+
+Return Value Return the ConStatusType.
+Parameters: aStatus: The status.
+Remark: Sets Connect status.
+******************************************************************************/
+inline
+NdbTransaction::ConStatusType
+NdbTransaction::Status()
+{
+ return theStatus;
+}
+
+/******************************************************************************
+void Status(ConStatusType aStatus);
+
+Parameters: aStatus: The status.
+Remark: Sets Connect status.
+******************************************************************************/
+inline
+void
+NdbTransaction::Status( ConStatusType aStatus )
+{
+ theStatus = aStatus;
+}
+
+
+/******************************************************************************
+ void setGCI();
+
+Remark: Set global checkpoint identity of the transaction
+******************************************************************************/
+inline
+void
+NdbTransaction::setGCI(int aGlobalCheckpointId)
+{
+ theGlobalCheckpointId = aGlobalCheckpointId;
+}
+
+/******************************************************************************
+void OpSent();
+
+Remark: An operation was sent with success that expects a response.
+******************************************************************************/
+inline
+void
+NdbTransaction::OpSent()
+{
+ theNoOfOpSent++;
+}
+
+/******************************************************************************
+void executePendingBlobOps();
+******************************************************************************/
+#include <stdlib.h>
+inline
+int
+NdbTransaction::executePendingBlobOps(Uint8 flags)
+{
+ if (thePendingBlobOps & flags) {
+ // not executeNoBlobs because there can be new ops with blobs
+ return execute(NoCommit);
+ }
+ return 0;
+}
+
+inline
+Uint32
+NdbTransaction::ptr2int(){
+ return theId;
+}
+
+typedef NdbTransaction NdbConnection;
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+#endif
diff --git a/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp b/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
new file mode 100644
index 00000000000..bc8993c4000
--- /dev/null
+++ b/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
@@ -0,0 +1,130 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+
+#ifndef CLUSTER_CONNECTION_HPP
+#define CLUSTER_CONNECTION_HPP
+#include <ndb_types.h>
+
+class Ndb_cluster_connection_node_iter
+{
+ friend class Ndb_cluster_connection_impl;
+public:
+ Ndb_cluster_connection_node_iter() : scan_state(~0),
+ init_pos(0),
+ cur_pos(0) {};
+private:
+ unsigned char scan_state;
+ unsigned char init_pos;
+ unsigned char cur_pos;
+};
+
+/**
+ * @class Ndb_cluster_connection
+ * @brief Represents a connection to a cluster of storage nodes.
+ *
+ * Any NDB application program should begin with the creation of a
+ * single Ndb_cluster_connection object, and should make use of one
+ * and only one Ndb_cluster_connection. The application connects to
+ * a cluster management server when this object's connect() method is called.
+ * By using the wait_until_ready() method it is possible to wait
+ * for the connection to reach one or more storage nodes.
+ */
+class Ndb_cluster_connection {
+public:
+ /**
+ * Create a connection to a cluster of storage nodes
+ *
+ * @param connectstring The connectstring for where to find the
+ * management server
+ */
+ Ndb_cluster_connection(const char * connectstring = 0);
+ ~Ndb_cluster_connection();
+
+ /**
+ * Set a name on the connection, which will be reported in cluster log
+ *
+ * @param name
+ *
+ */
+ void set_name(const char *name);
+
+ /**
+ * Connect to a cluster management server
+ *
+ * @param no_retries specifies the number of retries to attempt
+ * in the event of connection failure; a negative value
+ * will result in the attempt to connect being repeated
+ * indefinitely
+ *
+ * @param retry_delay_in_seconds specifies how often retries should
+ * be performed
+ *
+ * @param verbose specifies if the method should print a report of its progess
+ *
+ * @return 0 = success,
+ * 1 = recoverable error,
+ * -1 = non-recoverable error
+ */
+ int connect(int no_retries=0, int retry_delay_in_seconds=1, int verbose=0);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ int start_connect_thread(int (*connect_callback)(void)= 0);
+#endif
+
+ /**
+ * Wait until the requested connection with one or more storage nodes is successful
+ *
+ * @param timeout_for_first_alive Number of seconds to wait until
+ * first live node is detected
+ * @param timeout_after_first_alive Number of seconds to wait after
+ * first live node is detected
+ *
+ * @return = 0 all nodes live,
+ * > 0 at least one node live,
+ * < 0 error
+ */
+ int wait_until_ready(int timeout_for_first_alive,
+ int timeout_after_first_alive);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ int get_no_ready();
+ const char *get_connectstring(char *buf, int buf_sz) const;
+ int get_connected_port() const;
+ const char *get_connected_host() const;
+
+ void set_optimized_node_selection(int val);
+
+ unsigned no_db_nodes();
+ unsigned node_id();
+ unsigned get_connect_count() const;
+
+ void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
+ unsigned int get_next_node(Ndb_cluster_connection_node_iter &iter);
+ unsigned get_active_ndb_objects() const;
+
+ Uint64 *get_latest_trans_gci();
+#endif
+
+private:
+ friend class Ndb;
+ friend class NdbImpl;
+ friend class Ndb_cluster_connection_impl;
+ class Ndb_cluster_connection_impl & m_impl;
+ Ndb_cluster_connection(Ndb_cluster_connection_impl&);
+};
+
+#endif
diff --git a/storage/ndb/include/ndbapi/ndb_opt_defaults.h b/storage/ndb/include/ndbapi/ndb_opt_defaults.h
new file mode 100644
index 00000000000..d03a9dcc36f
--- /dev/null
+++ b/storage/ndb/include/ndbapi/ndb_opt_defaults.h
@@ -0,0 +1,23 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NDB_OPT_DEFAULTS_H
+#define NDB_OPT_DEFAULTS_H
+
+#define OPT_NDB_SHM_SIGNUM_DEFAULT 0
+#define OPT_NDB_SHM_DEFAULT 0
+
+#endif
diff --git a/storage/ndb/include/ndbapi/ndbapi_limits.h b/storage/ndb/include/ndbapi/ndbapi_limits.h
new file mode 100644
index 00000000000..5c4db71b747
--- /dev/null
+++ b/storage/ndb/include/ndbapi/ndbapi_limits.h
@@ -0,0 +1,30 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NDBAPI_LIMITS_H
+#define NDBAPI_LIMITS_H
+
+#define NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY 32
+#define NDB_MAX_ATTRIBUTES_IN_INDEX NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY
+#define NDB_MAX_ATTRIBUTES_IN_TABLE 128
+
+#define NDB_MAX_TUPLE_SIZE_IN_WORDS 2013
+#define NDB_MAX_KEYSIZE_IN_WORDS 1023
+#define NDB_MAX_KEY_SIZE (NDB_MAX_KEYSIZE_IN_WORDS*4)
+#define NDB_MAX_TUPLE_SIZE (NDB_MAX_TUPLE_SIZE_IN_WORDS*4)
+#define NDB_MAX_ACTIVE_EVENTS 100
+
+#endif
diff --git a/storage/ndb/include/ndbapi/ndberror.h b/storage/ndb/include/ndbapi/ndberror.h
new file mode 100644
index 00000000000..009818f5f4f
--- /dev/null
+++ b/storage/ndb/include/ndbapi/ndberror.h
@@ -0,0 +1,110 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef NDBERROR_H
+#define NDBERROR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+typedef enum
+{
+ ndberror_st_success = 0,
+ ndberror_st_temporary = 1,
+ ndberror_st_permanent = 2,
+ ndberror_st_unknown = 3
+} ndberror_status_enum;
+
+typedef enum
+{
+ ndberror_cl_none = 0,
+ ndberror_cl_application = 1,
+ ndberror_cl_no_data_found = 2,
+ ndberror_cl_constraint_violation = 3,
+ ndberror_cl_schema_error = 4,
+ ndberror_cl_user_defined = 5,
+ ndberror_cl_insufficient_space = 6,
+ ndberror_cl_temporary_resource = 7,
+ ndberror_cl_node_recovery = 8,
+ ndberror_cl_overload = 9,
+ ndberror_cl_timeout_expired = 10,
+ ndberror_cl_unknown_result = 11,
+ ndberror_cl_internal_error = 12,
+ ndberror_cl_function_not_implemented = 13,
+ ndberror_cl_unknown_error_code = 14,
+ ndberror_cl_node_shutdown = 15,
+ ndberror_cl_configuration = 16,
+ ndberror_cl_schema_object_already_exists = 17,
+ ndberror_cl_internal_temporary = 18
+} ndberror_classification_enum;
+
+
+typedef struct {
+
+ /**
+ * Error status.
+ */
+ ndberror_status_enum status;
+
+ /**
+ * Error type
+ */
+ ndberror_classification_enum classification;
+
+ /**
+ * Error code
+ */
+ int code;
+
+ /**
+ * Mysql error code
+ */
+ int mysql_code;
+
+ /**
+ * Error message
+ */
+ const char * message;
+
+ /**
+ * The detailed description. This is extra information regarding the
+ * error which is not included in the error message.
+ *
+ * @note Is NULL when no details specified
+ */
+ char * details;
+
+} ndberror_struct;
+
+
+typedef ndberror_status_enum ndberror_status;
+typedef ndberror_classification_enum ndberror_classification;
+
+const char *ndberror_status_message(ndberror_status);
+const char *ndberror_classification_message(ndberror_classification);
+void ndberror_update(ndberror_struct *);
+int ndb_error_string(int err_no, char *str, int size);
+
+#endif /* doxygen skip internal*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif