Below is the list of changes that have just been committed into a local
5.1 repository of frazer. When frazer does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-01-25 13:39:40+00:00, frazer@stripped +9 -0
Modify NdbIndexStat to use NdbRecord IndexBound API.
Allows some handler code cleanup and removal of broken signal scavenging method.
Add overloaded insertTuple() method.
Add missing DBUG_RETURN.
mysql-test/suite/ndb/r/ndb_index_ordered.result@stripped, 2008-01-25 13:39:12+00:00, frazer@stripped +2 -0
Testcase result fix
sql/ha_ndbcluster.cc@stripped, 2008-01-25 13:39:14+00:00, frazer@stripped +21 -193
Change records_in_range to use new NdbRecord API.
Remove old set_bounds code.
storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp@stripped, 2008-01-25 13:39:16+00:00, frazer@stripped +0 -1
Remove old method
storage/ndb/include/ndbapi/NdbIndexStat.hpp@stripped, 2008-01-25 13:39:18+00:00, frazer@stripped +17 -2
Remove old records_in_range API. Replace with NdbRecord IndexBound based variant
storage/ndb/include/ndbapi/NdbTransaction.hpp@stripped, 2008-01-25 13:39:20+00:00, frazer@stripped +4 -0
Overload insertTuple method with simpler variant.
storage/ndb/src/ndbapi/NdbIndexStat.cpp@stripped, 2008-01-25 13:39:21+00:00, frazer@stripped +177 -32
Implement NdbRecord based records_in_range. Remove old implementation.
storage/ndb/src/ndbapi/NdbScanOperation.cpp@stripped, 2008-01-25 13:39:23+00:00, frazer@stripped +6 -25
Add Api type check to setInterpretedCode()
Remove old, broken, unused method
storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2008-01-25 13:39:25+00:00, frazer@stripped +14 -1
Implement overloaded insertTuple and add missing DBUG_RETURN
storage/ndb/test/ndbapi/testIndexStat.cpp@stripped, 2008-01-25 13:39:27+00:00, frazer@stripped +184 -14
Modify test program to use new NdbIndexStat records_in_range Api
diff -Nrup a/mysql-test/suite/ndb/r/ndb_index_ordered.result b/mysql-test/suite/ndb/r/ndb_index_ordered.result
--- a/mysql-test/suite/ndb/r/ndb_index_ordered.result 2007-06-27 13:27:24 +01:00
+++ b/mysql-test/suite/ndb/r/ndb_index_ordered.result 2008-01-25 13:39:12 +00:00
@@ -645,6 +645,8 @@ select count(*) from t1;
count(*)
2
ALTER TABLE t1 ADD COLUMN c int;
+Warnings:
+Warning 1475 Converted FIXED field to DYNAMIC to enable on-line ADD COLUMN
select a from t1 where b = 2;
a
2
diff -Nrup a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
--- a/sql/ha_ndbcluster.cc 2008-01-17 12:42:43 +00:00
+++ b/sql/ha_ndbcluster.cc 2008-01-25 13:39:14 +00:00
@@ -2827,187 +2827,6 @@ ha_ndbcluster::pk_unique_index_read_key(
return op;
}
-/*
- Set bounds for ordered index scan.
-*/
-
-/* ToDo: remove if converting records_in_range() to NdbRecord. */
-int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
- uint inx,
- bool rir,
- const key_range *keys[2])
-{
- const KEY *const key_info= table->key_info + inx;
- const uint key_parts= key_info->key_parts;
- uint key_tot_len[2];
- uint tot_len;
- uint i, j;
-
- DBUG_ENTER("set_bounds");
- DBUG_PRINT("info", ("key_parts=%d", key_parts));
-
- for (j= 0; j <= 1; j++)
- {
- const key_range *key= keys[j];
- if (key != NULL)
- {
- // for key->flag see ha_rkey_function
- DBUG_PRINT("info", ("key %d length=%d flag=%d",
- j, key->length, key->flag));
- key_tot_len[j]= key->length;
- }
- else
- {
- DBUG_PRINT("info", ("key %d not present", j));
- key_tot_len[j]= 0;
- }
- }
- tot_len= 0;
-
- for (i= 0; i < key_parts; i++)
- {
- KEY_PART_INFO *key_part= &key_info->key_part[i];
- Field *field= key_part->field;
-#ifndef DBUG_OFF
- uint part_len= key_part->length;
-#endif
- uint part_store_len= key_part->store_length;
- // Info about each key part
- struct part_st {
- bool part_last;
- const key_range *key;
- const uchar *part_ptr;
- bool part_null;
- int bound_type;
- const uchar* bound_ptr;
- };
- struct part_st part[2];
-
- for (j= 0; j <= 1; j++)
- {
- struct part_st &p= part[j];
- p.key= NULL;
- p.bound_type= -1;
- if (tot_len < key_tot_len[j])
- {
- p.part_last= (tot_len + part_store_len >= key_tot_len[j]);
- p.key= keys[j];
- p.part_ptr= &p.key->key[tot_len];
- p.part_null= key_part->null_bit && *p.part_ptr;
- p.bound_ptr=
- p.part_null ? 0 : key_part->null_bit ? p.part_ptr + 1 : p.part_ptr;
-
- if (j == 0)
- {
- switch (p.key->flag)
- {
- case HA_READ_KEY_EXACT:
- if (! rir)
- p.bound_type= NdbIndexScanOperation::BoundEQ;
- else // differs for records_in_range
- p.bound_type= NdbIndexScanOperation::BoundLE;
- break;
- // ascending
- case HA_READ_KEY_OR_NEXT:
- p.bound_type= NdbIndexScanOperation::BoundLE;
- break;
- case HA_READ_AFTER_KEY:
- if (! p.part_last)
- p.bound_type= NdbIndexScanOperation::BoundLE;
- else
- p.bound_type= NdbIndexScanOperation::BoundLT;
- break;
- // descending
- case HA_READ_PREFIX_LAST: // weird
- p.bound_type= NdbIndexScanOperation::BoundEQ;
- break;
- case HA_READ_PREFIX_LAST_OR_PREV: // weird
- p.bound_type= NdbIndexScanOperation::BoundGE;
- break;
- case HA_READ_BEFORE_KEY:
- if (! p.part_last)
- p.bound_type= NdbIndexScanOperation::BoundGE;
- else
- p.bound_type= NdbIndexScanOperation::BoundGT;
- break;
- default:
- break;
- }
- }
- if (j == 1) {
- switch (p.key->flag)
- {
- // ascending
- case HA_READ_BEFORE_KEY:
- if (! p.part_last)
- p.bound_type= NdbIndexScanOperation::BoundGE;
- else
- p.bound_type= NdbIndexScanOperation::BoundGT;
- break;
- case HA_READ_AFTER_KEY: // weird
- p.bound_type= NdbIndexScanOperation::BoundGE;
- break;
- default:
- break;
- // descending strangely sets no end key
- }
- }
-
- if (p.bound_type == -1)
- {
- DBUG_PRINT("error", ("key %d unknown flag %d", j, p.key->flag));
- DBUG_ASSERT(FALSE);
- // Stop setting bounds but continue with what we have
- DBUG_RETURN(0);
- }
- }
- }
-
- // Seen with e.g. b = 1 and c > 1
- if (part[0].bound_type == NdbIndexScanOperation::BoundLE &&
- part[1].bound_type == NdbIndexScanOperation::BoundGE &&
- memcmp(part[0].part_ptr, part[1].part_ptr, part_store_len) == 0)
- {
- DBUG_PRINT("info", ("replace LE/GE pair by EQ"));
- part[0].bound_type= NdbIndexScanOperation::BoundEQ;
- part[1].bound_type= -1;
- }
- // Not seen but was in previous version
- if (part[0].bound_type == NdbIndexScanOperation::BoundEQ &&
- part[1].bound_type == NdbIndexScanOperation::BoundGE &&
- memcmp(part[0].part_ptr, part[1].part_ptr, part_store_len) == 0)
- {
- DBUG_PRINT("info", ("remove GE from EQ/GE pair"));
- part[1].bound_type= -1;
- }
-
- for (j= 0; j <= 1; j++)
- {
- struct part_st &p= part[j];
- // Set bound if not done with this key
- if (p.key != NULL)
- {
- DBUG_PRINT("info", ("key %d:%d offset: %d length: %d last: %d bound: %d",
- j, i, tot_len, part_len, p.part_last, p.bound_type));
- DBUG_DUMP("info", p.part_ptr, part_store_len);
-
- // Set bound if not cancelled via type -1
- if (p.bound_type != -1)
- {
- const uchar* ptr= p.bound_ptr;
- uchar buf[256];
- shrink_varchar(field, ptr, buf);
- if (op->setBound(i, p.bound_type, ptr))
- ERR_RETURN(op->getNdbError());
- }
- }
- }
-
- tot_len+= part_store_len;
- }
- DBUG_RETURN(0);
-}
-
/* Count number of columns in key part. */
static uint
count_key_columns(const KEY *key_info, const key_range *key)
@@ -9137,7 +8956,7 @@ void ha_ndbcluster::set_tabname(const ch
}
-/* ToDo: convert to NdbRecord? */
+/* Determine roughly how many records are in the range specified */
ha_rows
ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
key_range *max_key)
@@ -9163,14 +8982,13 @@ ha_ndbcluster::records_in_range(uint inx
if ((idx_type == PRIMARY_KEY_ORDERED_INDEX ||
idx_type == UNIQUE_ORDERED_INDEX ||
idx_type == ORDERED_INDEX) &&
- m_index[inx].index_stat != NULL)
+ m_index[inx].index_stat != NULL) // --ndb-index-stat-enable=1
{
NDB_INDEX_DATA& d=m_index[inx];
const NDBINDEX* index= d.index;
Ndb* ndb=get_ndb();
NdbTransaction* active_trans= m_thd_ndb ? m_thd_ndb->trans : 0;
NdbTransaction* trans=NULL;
- NdbIndexScanOperation* op=NULL;
int res=0;
Uint64 rows;
@@ -9201,7 +9019,9 @@ ha_ndbcluster::records_in_range(uint inx
}
}
- // Define scan op for the range
+ /*
+ Query the index statistics for our range.
+ */
if ((trans=active_trans) == NULL ||
trans->commitStatus() != NdbTransaction::Started)
{
@@ -9209,13 +9029,15 @@ ha_ndbcluster::records_in_range(uint inx
if (! (trans=ndb->startTransaction()))
ERR_BREAK(ndb->getNdbError(), res);
}
- if (! (op=trans->getNdbIndexScanOperation(index, (NDBTAB*)m_table)))
- ERR_BREAK(trans->getNdbError(), res);
- if ((op->readTuples(NdbOperation::LM_CommittedRead)) == -1)
- ERR_BREAK(op->getNdbError(), res);
- const key_range *keys[2]={ min_key, max_key };
- if ((res=set_bounds(op, inx, TRUE, keys)) != 0)
- break;
+
+ /* Create an IndexBound struct for the keys */
+ NdbIndexScanOperation::IndexBound ib;
+ compute_index_bounds(ib,
+ key_info,
+ min_key,
+ max_key);
+
+ ib.range_no= 0;
// Decide if db should be contacted
int flags=0;
@@ -9226,7 +9048,13 @@ ha_ndbcluster::records_in_range(uint inx
DBUG_PRINT("info", ("force stat from db"));
flags|=NdbIndexStat::RR_UseDb;
}
- if (d.index_stat->records_in_range(index, op, table_rows, &rows, flags) == -1)
+ if (d.index_stat->records_in_range(index,
+ trans,
+ d.ndb_record_key,
+ &ib,
+ table_rows,
+ &rows,
+ flags) == -1)
ERR_BREAK(d.index_stat->getNdbError(), res);
d.index_stat_query_count++;
} while (0);
diff -Nrup a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
--- a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp 2008-01-14 12:54:39 +00:00
+++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp 2008-01-25 13:39:16 +00:00
@@ -264,7 +264,6 @@ private:
Uint32 column_index,
const char *row,
Uint32 bound_type);
- Uint32 getKeyFromSCANTABREQ(Uint32* data, Uint32 size);
virtual int equal_impl(const NdbColumnImpl*, const char*);
virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);
diff -Nrup a/storage/ndb/include/ndbapi/NdbIndexStat.hpp b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
--- a/storage/ndb/include/ndbapi/NdbIndexStat.hpp 2006-12-23 19:33:29 +00:00
+++ b/storage/ndb/include/ndbapi/NdbIndexStat.hpp 2008-01-25 13:39:18 +00:00
@@ -19,8 +19,8 @@
#include <ndb_global.h>
#include <NdbDictionary.hpp>
#include <NdbError.hpp>
+#include <NdbIndexScanOperation.hpp>
class NdbIndexImpl;
-class NdbIndexScanOperation;
/*
* Statistics for an ordered index.
@@ -56,10 +56,13 @@ public:
* returned as 1).
*/
int records_in_range(const NdbDictionary::Index* index,
- NdbIndexScanOperation* op,
+ NdbTransaction* trans,
+ const NdbRecord* record,
+ const NdbIndexScanOperation::IndexBound* ib,
Uint64 table_rows,
Uint64* count,
int flags);
+
/*
* Get latest error.
*/
@@ -100,6 +103,12 @@ private:
};
STATIC_CONST( EntrySize = sizeof(Entry) >> 2 );
STATIC_CONST( PointerSize = sizeof(Pointer) >> 2 );
+ /* Need 2 words per column in a bound plus space for the
+ * bound data.
+ * Worst case is 32 cols in key and max key size used.
+ */
+ STATIC_CONST( BoundBufWords = (2 * NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY)
+ + NDB_MAX_KEYSIZE_IN_WORDS );
struct Area {
Uint32* m_data;
Uint32 m_offset;
@@ -141,6 +150,12 @@ private:
int stat_select(const Uint32* key1, Uint32 keylen1,
const Uint32* key2, Uint32 keylen2, float pct[2]);
void set_error(int code);
+ int addKeyPartInfo(const NdbRecord* record,
+ const char* keyRecordData,
+ Uint32 keyPartNum,
+ const NdbIndexScanOperation::BoundType boundType,
+ Uint32* keyStatData,
+ Uint32& keyLength);
};
#endif
diff -Nrup a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp
--- a/storage/ndb/include/ndbapi/NdbTransaction.hpp 2008-01-17 08:06:40 +00:00
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp 2008-01-25 13:39:20 +00:00
@@ -723,6 +723,10 @@ public:
const unsigned char *mask= 0,
const NdbOperation::OperationOptions *opts = 0,
Uint32 sizeOfOptions = 0);
+ const NdbOperation *insertTuple(const NdbRecord *combined_rec, const char *combined_row,
+ const unsigned char *mask = 0,
+ const NdbOperation::OperationOptions *opts = 0,
+ Uint32 sizeOfOptions = 0);
const NdbOperation *updateTuple(const NdbRecord *key_rec, const char *key_row,
const NdbRecord *attr_rec, const char *attr_row,
const unsigned char *mask= 0,
diff -Nrup a/storage/ndb/src/ndbapi/NdbIndexStat.cpp b/storage/ndb/src/ndbapi/NdbIndexStat.cpp
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp 2008-01-14 12:55:06 +00:00
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp 2008-01-25 13:39:21 +00:00
@@ -18,9 +18,9 @@
#include <NdbSqlUtil.hpp>
#include <NdbIndexStat.hpp>
#include <NdbTransaction.hpp>
-#include <NdbIndexScanOperation.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbInterpretedCode.hpp>
+#include <NdbRecord.hpp>
#include <my_sys.h>
NdbIndexStat::NdbIndexStat(const NdbDictionary::Index* index) :
@@ -375,13 +375,98 @@ NdbIndexStat::stat_select(const Uint32*
return 0;
}
+/**
+ * addKeyPartInfo
+ * This method is used to build a standard representation of a
+ * lower or upper index bound in a buffer, which can then
+ * be used to identify a range.
+ * The buffer format is :
+ * 1 word of NdbIndexScanOperation::BoundType
+ * 1 word of ATTRINFO header containing the index attrid
+ * and the size in words of the data.
+ * 0..N words of data.
+ * The data itself is formatted as usual (e.g. 1/2 length
+ * bytes for VAR* types)
+ * For NULLs, length==0
+ */
+
int
-NdbIndexStat::records_in_range(const NdbDictionary::Index* index, NdbIndexScanOperation* op, Uint64 table_rows, Uint64* count, int flags)
+NdbIndexStat::addKeyPartInfo(const NdbRecord* record,
+ const char* keyRecordData,
+ Uint32 keyPartNum,
+ const NdbIndexScanOperation::BoundType boundType,
+ Uint32* keyStatData,
+ Uint32& keyLength)
+{
+ char buf[256]; // For shrinking MySQLD varchars
+
+ Uint32 key_index= record->key_indexes[ keyPartNum ];
+ const NdbRecord::Attr *column= &record->columns[ key_index ];
+
+ bool is_null= column->is_null(keyRecordData);
+ Uint32 len= 0;
+ const void *aValue= keyRecordData + column->offset;
+
+ if (!is_null)
+ {
+ bool len_ok;
+ /* Support for special mysqld varchar format in keys. */
+ if (column->flags & NdbRecord::IsMysqldShrinkVarchar)
+ {
+ len_ok= column->shrink_varchar(keyRecordData,
+ len,
+ buf);
+ aValue= buf;
+ }
+ else
+ {
+ len_ok= column->get_var_length(keyRecordData, len);
+ }
+ if (!len_ok) {
+ set_error(4209);
+ return -1;
+ }
+ }
+
+ /* Insert attribute header. */
+ Uint32 tIndexAttrId= column->index_attrId;
+ Uint32 sizeInWords= (len + 3) / 4;
+ AttributeHeader ah(tIndexAttrId, sizeInWords << 2);
+ const Uint32 ahValue= ah.m_value;
+
+ if (keyLength + (2 + len) > BoundBufWords )
+ {
+ /* Something wrong, key data would be too big */
+ /* Key size is limited to 4092 bytes */
+ set_error(4207);
+ return -1;
+ }
+
+ /* Fill in key data */
+ keyStatData[ keyLength++ ]= boundType;
+ keyStatData[ keyLength++ ]= ahValue;
+ /* Zero last word prior to byte copy, in case we're not aligned */
+ keyStatData[ keyLength + sizeInWords - 1] = 0;
+ memcpy(&keyStatData[ keyLength ], aValue, len);
+
+ keyLength+= sizeInWords;
+
+ return 0;
+}
+
+int
+NdbIndexStat::records_in_range(const NdbDictionary::Index* index,
+ NdbTransaction* trans,
+ const NdbRecord* record,
+ const NdbIndexScanOperation::IndexBound* ib,
+ Uint64 table_rows,
+ Uint64* count,
+ int flags)
{
DBUG_ENTER("NdbIndexStat::records_in_range");
Uint64 rows;
- Uint32 key1[1000], keylen1;
- Uint32 key2[1000], keylen2;
+ Uint32 key1[BoundBufWords], keylen1;
+ Uint32 key2[BoundBufWords], keylen2;
if (m_cache == NULL)
flags |= RR_UseDb | RR_NoUpdate;
@@ -389,28 +474,54 @@ NdbIndexStat::records_in_range(const Ndb
flags |= RR_UseDb;
if ((flags & (RR_UseDb | RR_NoUpdate)) != RR_UseDb | RR_NoUpdate) {
- // get start and end key - assume bound is ordered, wellformed
- Uint32 bound[1000];
- Uint32 boundlen = op->getKeyFromSCANTABREQ(bound, 1000);
-
- keylen1 = keylen2 = 0;
- Uint32 n = 0;
- while (n < boundlen) {
- Uint32 t = bound[n];
- AttributeHeader ah(bound[n + 1]);
- Uint32 sz = 2 + ah.getDataSize();
- t &= 0xFFFF; // may contain length
- assert(t <= 4);
- bound[n] = t;
- if (t == 0 || t == 1 || t == 4) {
- memcpy(&key1[keylen1], &bound[n], sz << 2);
- keylen1 += sz;
+ // get start and end key from NdbIndexBound, using NdbRecord to
+ // get values into a standard format.
+ Uint32 maxBoundParts= (ib->low_key_count > ib->high_key_count) ?
+ ib->low_key_count : ib->high_key_count;
+
+ keylen1= keylen2= 0;
+
+ /* Fill in keyX buffers */
+ for (Uint32 keyPartNum=0; keyPartNum < maxBoundParts; keyPartNum++)
+ {
+ if (ib->low_key_count > keyPartNum)
+ {
+ /* Set bound to LT only if it's not inclusive
+ * and this is the last key
+ */
+ NdbIndexScanOperation::BoundType boundType=
+ NdbIndexScanOperation::BoundLE;
+ if ((! ib->low_inclusive) &&
+ (keyPartNum == (ib->low_key_count -1 )))
+ boundType= NdbIndexScanOperation::BoundLT;
+
+ if (addKeyPartInfo(record,
+ ib->low_key,
+ keyPartNum,
+ boundType,
+ key1,
+ keylen1) != 0)
+ DBUG_RETURN(-1);
}
- if (t == 2 || t == 3 || t == 4) {
- memcpy(&key2[keylen2], &bound[n], sz << 2);
- keylen2 += sz;
+ if (ib->high_key_count > keyPartNum)
+ {
+ /* Set bound to GT only if it's not inclusive
+ * and this is the last key
+ */
+ NdbIndexScanOperation::BoundType boundType=
+ NdbIndexScanOperation::BoundGE;
+ if ((! ib->high_inclusive) &&
+ (keyPartNum == (ib->high_key_count -1)))
+ boundType= NdbIndexScanOperation::BoundGT;
+
+ if (addKeyPartInfo(record,
+ ib->high_key,
+ keyPartNum,
+ boundType,
+ key2,
+ keylen2) != 0)
+ DBUG_RETURN(-1);
}
- n += sz;
}
}
@@ -419,7 +530,6 @@ NdbIndexStat::records_in_range(const Ndb
float tot[4] = { 0, 0, 0, 0 }; // totals of above
int cnt, ret;
bool forceSend = true;
- NdbTransaction* trans = op->m_transConnection;
const Uint32 codeWords= 1;
Uint32 codeSpace[ codeWords ];
NdbInterpretedCode code(NULL, // No table
@@ -428,15 +538,48 @@ NdbIndexStat::records_in_range(const Ndb
if ((code.interpret_exit_last_row() != 0) ||
(code.finalise() != 0))
{
- return code.getNdbError().code;
+ m_error= code.getNdbError();
+ DBUG_PRINT("error", ("code: %d", m_error.code));
+ DBUG_RETURN(-1);
}
- if (op->setInterpretedCode(&code) != 0 ||
- op->getValue(NdbDictionary::Column::RECORDS_IN_RANGE, (char*)out) == 0) {
- m_error = op->getNdbError();
- DBUG_PRINT("error", ("op:%d", op->getNdbError().code));
+ NdbIndexScanOperation* op= NULL;
+ NdbScanOperation::ScanOptions options;
+ NdbOperation::GetValueSpec extraGet;
+
+ options.optionsPresent=
+ NdbScanOperation::ScanOptions::SO_GETVALUE |
+ NdbScanOperation::ScanOptions::SO_INTERPRETED;
+
+ /* Read RECORDS_IN_RANGE pseudo column */
+ extraGet.column= NdbDictionary::Column::RECORDS_IN_RANGE;
+ extraGet.appStorage= (void*) out;
+ extraGet.recAttr= NULL;
+
+ options.extraGetValues= &extraGet;
+ options.numExtraGetValues= 1;
+
+ /* Add interpreted code to return on 1st row */
+ options.interpretedCode= &code;
+
+ const Uint32 keyBitmaskWords= (NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY + 31) >> 5;
+ Uint32 emptyMask[keyBitmaskWords];
+ memset(&emptyMask[0], 0, keyBitmaskWords << 2);
+
+ if (NULL ==
+ (op= trans->scanIndex(record,
+ record,
+ NdbOperation::LM_CommittedRead,
+ (const unsigned char*) &emptyMask[0],
+ ib,
+ &options,
+ sizeof(NdbScanOperation::ScanOptions))))
+ {
+ m_error= trans->getNdbError();
+ DBUG_PRINT("error", ("scanIndex : %d", m_error.code));
DBUG_RETURN(-1);
}
+
if (trans->execute(NdbTransaction::NoCommit,
NdbOperation::AbortOnError, forceSend) == -1) {
m_error = trans->getNdbError();
@@ -445,7 +588,9 @@ NdbIndexStat::records_in_range(const Ndb
DBUG_RETURN(-1);
}
cnt = 0;
- while ((ret = op->nextResult(true, forceSend)) == 0) {
+ const char* dummy_out_ptr= NULL;
+ while ((ret = op->nextResult(&dummy_out_ptr,
+ true, forceSend)) == 0) {
DBUG_PRINT("info", ("frag rows=%u in=%u before=%u after=%u [error=%d]",
out[0], out[1], out[2], out[3],
(int)(out[1] + out[2] + out[3]) - (int)out[0]));
@@ -456,7 +601,7 @@ NdbIndexStat::records_in_range(const Ndb
}
if (ret == -1) {
m_error = op->getNdbError();
- DBUG_PRINT("error", ("trans:%d op:%d", trans->getNdbError().code,
+ DBUG_PRINT("error nextResult ", ("trans:%d op:%d", trans->getNdbError().code,
op->getNdbError().code));
DBUG_RETURN(-1);
}
diff -Nrup a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2008-01-17 08:48:19 +00:00
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2008-01-25 13:39:23 +00:00
@@ -1006,6 +1006,12 @@ NdbScanOperation::processTableScanDefs(N
int
NdbScanOperation::setInterpretedCode(const NdbInterpretedCode *code)
{
+ if (theStatus == NdbOperation::UseNdbRecord)
+ {
+ setErrorCodeAbort(4284); // Cannot mix NdbRecAttr and NdbRecord methods...
+ return -1;
+ }
+
if ((code->m_flags & NdbInterpretedCode::Finalised) == 0)
{
setErrorCodeAbort(4519); // NdbInterpretedCode::finalise() not called.
@@ -2803,31 +2809,6 @@ NdbIndexScanOperation::ndbrecord_insert_
theTupKeyLen= tupKeyLen + totalLen;
return 0;
-}
-
-Uint32
-NdbIndexScanOperation::getKeyFromSCANTABREQ(Uint32* data, Uint32 size)
-{
- DBUG_ENTER("NdbIndexScanOperation::getKeyFromSCANTABREQ");
- assert(size >= theTotalNrOfKeyWordInSignal);
- size = theTotalNrOfKeyWordInSignal;
- NdbApiSignal* tSignal = theSCAN_TABREQ->next();
- Uint32 pos = 0;
- while (pos < size) {
- assert(tSignal != NULL);
- Uint32* tData = tSignal->getDataPtrSend();
- Uint32 rem = size - pos;
- if (rem > KeyInfo::DataLength)
- rem = KeyInfo::DataLength;
- Uint32 i = 0;
- while (i < rem) {
- data[pos + i] = tData[KeyInfo::HeaderLength + i];
- i++;
- }
- pos += rem;
- }
- DBUG_DUMP("key", (uchar*) data, size << 2);
- DBUG_RETURN(size);
}
/* IndexScan readTuples - part of old scan API
diff -Nrup a/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp 2008-01-17 08:48:19 +00:00
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp 2008-01-25 13:39:25 +00:00
@@ -2399,6 +2399,19 @@ NdbTransaction::insertTuple(const NdbRec
}
const NdbOperation *
+NdbTransaction::insertTuple(const NdbRecord *combined_rec, const char *combined_row,
+ const unsigned char *mask,
+ const NdbOperation::OperationOptions *opts,
+ Uint32 sizeOfOptions)
+{
+ return insertTuple(combined_rec, combined_row,
+ combined_rec, combined_row,
+ mask,
+ opts,
+ sizeOfOptions);
+}
+
+const NdbOperation *
NdbTransaction::updateTuple(const NdbRecord *key_rec, const char *key_row,
const NdbRecord *attr_rec, const char *attr_row,
const unsigned char *mask,
@@ -2532,7 +2545,7 @@ NdbTransaction::scanTable(const NdbRecor
options,
sizeOfOptions) == 0)
{
- return op_idx;
+ DBUG_RETURN(op_idx);
}
releaseScanOperation(&m_theFirstScanOperation, &m_theLastScanOperation,
diff -Nrup a/storage/ndb/test/ndbapi/testIndexStat.cpp b/storage/ndb/test/ndbapi/testIndexStat.cpp
--- a/storage/ndb/test/ndbapi/testIndexStat.cpp 2008-01-14 12:55:43 +00:00
+++ b/storage/ndb/test/ndbapi/testIndexStat.cpp 2008-01-25 13:39:27 +00:00
@@ -105,6 +105,17 @@ static Ndb* g_ndb = 0;
static NdbDictionary::Dictionary* g_dic = 0;
static const NdbDictionary::Table* g_tab = 0;
static const NdbDictionary::Index* g_ind = 0;
+static const NdbRecord* g_tab_rec = 0;
+static const NdbRecord* g_ind_rec = 0;
+
+/* Nasty consts for NdbRecord Api offsets */
+static const Uint32 g_ndbrec_a_offset=4;
+static const Uint32 g_ndbrec_b_offset=8;
+static const Uint32 g_ndbrec_c_offset=12;
+static const Uint32 g_ndbrec_c_nb_offset=2;
+static const Uint32 g_ndbrec_d_offset=24;
+static const Uint32 g_ndbrec_d_nb_offset=3;
+static const Uint32 g_ndbrecord_bytes=28;
static NdbIndexStat* g_stat = 0;
@@ -193,6 +204,53 @@ errdb()
ll0("unknown db error");
}
+/* Methods to create NdbRecord structs for the table and index */
+static int
+createNdbRecords()
+{
+ const Uint32 numCols=4;
+ const Uint32 numIndexCols=3;
+ NdbDictionary::RecordSpecification recSpec[numCols];
+
+ recSpec[0].column= g_tab->getColumn("a"); // 4 bytes
+ recSpec[0].offset= g_ndbrec_a_offset;
+ recSpec[0].nullbit_byte_offset= 0;
+ recSpec[0].nullbit_bit_in_byte= 0;
+
+ recSpec[1].column= g_tab->getColumn("b"); // 2 bytes
+ recSpec[1].offset= g_ndbrec_b_offset;
+ recSpec[1].nullbit_byte_offset= 0;
+ recSpec[1].nullbit_bit_in_byte= 0;
+
+ recSpec[2].column= g_tab->getColumn("c"); // Varchar(10) -> ~12 bytes
+ recSpec[2].offset= g_ndbrec_c_offset;
+ recSpec[2].nullbit_byte_offset= 0;
+ recSpec[2].nullbit_bit_in_byte= g_ndbrec_c_nb_offset;
+
+ recSpec[3].column= g_tab->getColumn("d"); // 4 bytes
+ recSpec[3].offset= g_ndbrec_d_offset;
+ recSpec[3].nullbit_byte_offset= 0;
+ recSpec[3].nullbit_bit_in_byte= g_ndbrec_d_nb_offset;
+
+ g_tab_rec= g_dic->createRecord(g_tab,
+ &recSpec[0],
+ numCols,
+ sizeof(NdbDictionary::RecordSpecification),
+ 0);
+
+ chkrc(g_tab_rec != NULL);
+
+ g_ind_rec= g_dic->createRecord(g_ind,
+ &recSpec[1],
+ numIndexCols,
+ sizeof(NdbDictionary::RecordSpecification),
+ 0);
+
+ chkrc(g_ind_rec != NULL);
+
+ return 0;
+}
+
// create table ts0 (
// a int unsigned, b smallint not null, c varchar(10), d int unsigned,
// primary key using hash (a), index (b, c, d) )
@@ -250,6 +308,9 @@ createtable()
}
chkdb((g_tab = g_dic->getTable(g_tabname)) != 0);
chkdb((g_ind = g_dic->getIndex(g_indname, g_tabname)) != 0);
+
+ chkrc(createNdbRecords() == 0);
+
g_dic = 0;
return 0;
}
@@ -725,7 +786,7 @@ Bnd::cmp(const Val& theval) const
int place; // debug
int ret;
do {
- assert(theval.numattrs == g_numattrs);
+ assert(theval.numattrs == (uint) g_numattrs);
int k = theval.cmp(val, val.numattrs);
if (k != 0) {
place = 1;
@@ -951,9 +1012,7 @@ makeranges()
range.bnd[1] = range.bnd[0];
range.bnd[0].side = -1;
range.bnd[1].side = +1;
- // fix types
- range.bnd[0];
- range.bnd[1];
+
assert(range.iseq());
}
}
@@ -984,10 +1043,12 @@ setbounds(const Range& range)
ll2("setbounds: " << range);
uint i;
const Bnd (&bnd)[2] = range.bnd;
- for (i = 0; i < g_numattrs; i++) {
+ for (i = 0; i < (uint)g_numattrs; i++) {
const Uint32 no = i; // index attribute number
uint j;
int type[2] = { -1, -1 };
+ // determine inclusivity (boundtype) of upper+lower bounds on this col.
+ // -1 == no bound on the col.
for (j = 0; j <= 1; j++) {
if (no < bnd[j].val.numattrs)
type[j] = bnd[j].type(j, no);
@@ -1001,11 +1062,11 @@ setbounds(const Range& range)
const Val& val = bnd[j].val;
const void* addr = 0;
if (no == 0)
- addr = (const void*)&val.b;
+ addr = (const void*)&val.b; // col a, not nullable
else if (no == 1)
- addr = ! val.c_null ? (const void*)val.c : 0;
+ addr = ! val.c_null ? (const void*)val.c : 0; // col b, nullable
else if (no == 2)
- addr = ! val.d_null ? (const void*)&val.d : 0;
+ addr = ! val.d_null ? (const void*)&val.d : 0; // col c, nullable
else
assert(false);
ll2("setBound attr:" << no << " type:" << t << " val: " << val);
@@ -1015,6 +1076,103 @@ setbounds(const Range& range)
return 0;
}
+/* This method initialises the passed in IndexBound
+ * to represent the range passed in.
+ * It assumes that the storage pointed to by low_key
+ * and high_key in the passed IndexBound can be overwritten
+ * and is long enough to store the data
+ */
+static int
+initialiseIndexBound(const Range& range,
+ NdbIndexScanOperation::IndexBound& ib)
+{
+ ll2("initialiseIndexBound: " << range);
+ uint i;
+ const Bnd (&bnd)[2] = range.bnd;
+ Uint32 colsInBound[2]= {0, 0};
+ bool boundInclusive[2]= {false, false};
+
+ // Clear nullbit storage
+ *((char *)ib.low_key) =
+ *((char *)ib.high_key) = 0;
+
+ for (i = 0; i < (uint)g_numattrs; i++) {
+ const Uint32 no = i; // index attribute number
+ uint j;
+ int type[2] = { -1, -1 };
+ // determine inclusivity (boundtype) of upper+lower bounds on this col.
+ // -1 == no bound on the col.
+ for (j = 0; j <= 1; j++) {
+ if (no < bnd[j].val.numattrs)
+ type[j] = bnd[j].type(j, no);
+ }
+ for (j = 0; j <= 1; j++) {
+ /* Get ptr to key storage space for this bound */
+ char* keyBuf= const_cast<char *>( (j==0) ? ib.low_key : ib.high_key);
+ int t = type[j];
+ if (t == -1)
+ continue;
+ colsInBound[j]++;
+
+ if (no + 1 >= bnd[j].val.numattrs)
+ // Last column in bound, inclusive if GE or LE (or EQ)
+ // i.e. bottom bit of boundtype is clear
+ boundInclusive[j]= !(t & 1);
+
+ const Val& val = bnd[j].val;
+ if (no == 0)
+ // b, not nullable
+ memcpy(&keyBuf[g_ndbrec_b_offset],
+ (const void*)&val.b,
+ 2);
+ else if (no == 1)
+ {
+ // c, nullable
+ if (! val.c_null)
+ memcpy(&keyBuf[g_ndbrec_c_offset],
+ (const void*)&val.c,
+ 1+ g_charlen);
+
+ // Set null bit
+ keyBuf[0] |= ((val.c_null?1:0) << g_ndbrec_c_nb_offset);
+ }
+ else if (no == 2)
+ {
+ // d, nullable
+ if (! val.d_null)
+ memcpy(&keyBuf[g_ndbrec_d_offset],
+ (const void*)&val.d,
+ 4);
+ // Set null bit
+ keyBuf[0] |= ((val.d_null?1:0) << g_ndbrec_d_nb_offset);
+ }
+ else
+ assert(false);
+ ll2("initialiseIndexBound attr:" << no << " type:" << t << " val: " << val);
+ }
+ }
+
+ /* Now have everything we need to initialise the IndexBound */
+ ib.low_key_count= colsInBound[0];
+ ib.low_inclusive= boundInclusive[0];
+ ib.high_key_count= colsInBound[1];
+ ib.high_inclusive= boundInclusive[1];
+ ib.range_no= 0;
+
+ ll2(" indexBound low_key_count=" << ib.low_key_count <<
+ " low_inc=" << ib.low_inclusive <<
+ " high_key_count=" << ib.high_key_count <<
+ " high_inc=" << ib.high_inclusive);
+ ll2(" low bound b=" << *((Uint16*) &ib.low_key[g_ndbrec_b_offset]) <<
+ " d=" << *((Uint32*) &ib.low_key[g_ndbrec_d_offset]) <<
+ " first byte=%xu" << ib.low_key[0]);
+ ll2(" high bound b=" << *((Uint16*) &ib.high_key[g_ndbrec_b_offset]) <<
+ " d=" << *((Uint32*) &ib.high_key[g_ndbrec_d_offset]) <<
+ " first byte=%xu" << ib.high_key[0]);
+
+ return 0;
+}
+
static int
allocstat()
{
@@ -1027,12 +1185,24 @@ static int
runstat(Range& range, int flags)
{
ll2("runstat: " << range << " flags=" << flags);
+
+ /* Create IndexBound and key storage space */
+ char keySpace[2][g_ndbrecord_bytes];
+ NdbIndexScanOperation::IndexBound ib;
+ ib.low_key= keySpace[0];
+ ib.high_key= keySpace[1];
+
chkdb((g_con = g_ndb->startTransaction()) != 0);
- chkdb((g_rangescan_op = g_con->getNdbIndexScanOperation(g_ind, g_tab)) != 0);
- chkdb(g_rangescan_op->readTuples(NdbOperation::LM_CommittedRead) == 0);
- chkrc(setbounds(range) == 0);
+ chkrc(initialiseIndexBound(range, ib) == 0);
+
Uint64 count = ~(Uint64)0;
- chkdb(g_stat->records_in_range(g_ind, g_rangescan_op, g_opts.rows, &count, flags) == 0);
+ chkdb(g_stat->records_in_range(g_ind,
+ g_con,
+ g_ind_rec,
+ &ib,
+ g_opts.rows,
+ &count,
+ flags) == 0);
g_ndb->closeTransaction(g_con);
g_con = 0;
g_rangescan_op = 0;
@@ -1261,7 +1431,7 @@ setseed(int n)
if (n == -1) {
if (g_opts.seed == 0)
return;
- if (g_opts.seed != -1)
+ if (g_opts.seed != (uint) -1)
seed = (uint)g_opts.seed;
else
seed = 1 + (ushort)getpid();
@@ -1398,7 +1568,7 @@ main(int argc, char** argv)
strchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
uint i;
ndbout << g_progname;
- for (i = 1; i < argc; i++)
+ for (i = 1; i < (uint)argc; i++)
ndbout << " " << argv[i];
ndbout << endl;
int ret;
| Thread |
|---|
| • bk commit into 5.1 tree (frazer:1.2641) | Frazer Clement | 25 Jan |