MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Jan Wedvik Date:October 2 2009 6:40am
Subject:bzr commit into mysql-5.1-telco-7.0-spj branch (jan.wedvik:2987)
View as plain text  
#At file:///export/home2/tmp/jw1159207/mysql/mysql-5.1-telco-7.0-spj/ based on revid:jan.wedvik@stripped

 2987 Jan Wedvik	2009-10-02 [merge]
      Merged from bk-internal.mysql.com/bzrroot/server/mysql-5.1-telco-7.0-spj/.

    modified:
      storage/ndb/include/ndbapi/NdbQueryBuilder.hpp
      storage/ndb/ndbapi-examples/ndbapi_multi_cursor/main.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilder.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
      storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp
      storage/ndb/src/ndbapi/ndberror.c
=== modified file 'storage/ndb/include/ndbapi/NdbQueryBuilder.hpp'
--- a/storage/ndb/include/ndbapi/NdbQueryBuilder.hpp	2009-07-07 09:52:31 +0000
+++ b/storage/ndb/include/ndbapi/NdbQueryBuilder.hpp	2009-10-02 06:40:46 +0000
@@ -248,13 +248,17 @@ public:
 
   // NdbQueryOperand builders:
   // ::constValue constructors variants, considder to added/removed variants
+  // If the attribute is of a fixed size datatype, its value must include all bytes.
+  // A fixed-Char value must be native-blank padded
   // Partly based on value types currently supported through NdbOperation::equal()
-  NdbConstOperand* constValue(const char* value);
-  NdbConstOperand* constValue(const void* value, size_t length);
   NdbConstOperand* constValue(Int32  value); 
   NdbConstOperand* constValue(Uint32 value); 
   NdbConstOperand* constValue(Int64  value); 
   NdbConstOperand* constValue(Uint64 value); 
+  NdbConstOperand* constValue(const char* value);  // Null terminated char/varchar
+
+  // Raw data with specified length - no typesafety is provieded at all 
+  NdbConstOperand* constValue(const void* value, size_t length); 
 
   // ::paramValue()
   NdbParamOperand* paramValue(const char* name = 0);  // Parameterized

=== modified file 'storage/ndb/ndbapi-examples/ndbapi_multi_cursor/main.cpp'
--- a/storage/ndb/ndbapi-examples/ndbapi_multi_cursor/main.cpp	2009-09-28 08:12:13 +0000
+++ b/storage/ndb/ndbapi-examples/ndbapi_multi_cursor/main.cpp	2009-10-02 06:40:46 +0000
@@ -32,8 +32,6 @@
 #include "NdbQueryBuilder.hpp"
 #include "NdbQueryOperation.hpp"
 
-#include "NdbQueryOperationImpl.hpp"
-
 //#define USE_RECATTR
 
 /**
@@ -57,13 +55,12 @@
  */
   #define NDB_CONNECT_STRING "127.0.0.1:2360"
 
-
 /*****************************************************
 ** Defines record structure for the rows in our tables
 ******************************************************/
 struct ManagerRow
 {
-  char   dept_no[4];
+  char   dept_no[8];
   Uint32 emp_no;
   Int32  from_date;
   Int32  to_date;
@@ -73,7 +70,7 @@ struct ManagerRow
 struct ManagerPKRow
 {
   Uint32 emp_no;
-  char   dept_no[4+1];
+  char   dept_no[8+1];
 };
 
 struct EmployeeRow
@@ -98,7 +95,7 @@ struct SalaryRow
 const char* employeeDef = 
 "CREATE TABLE employees ("
 "    emp_no      INT             NOT NULL,"
-"    dept_no     CHAR(4)         NOT NULL,"   // Temporary added OJA
+"    dept_no     VARCHAR(4)         NOT NULL,"   // Temporary added OJA
 "    birth_date  DATE            NOT NULL,"
 "    first_name  VARCHAR(14)     NOT NULL,"
 "    last_name   VARCHAR(16)     NOT NULL,"
@@ -109,7 +106,7 @@ const char* employeeDef = 
 
 const char* departmentsDef = 
 "CREATE TABLE departments ("
-"    dept_no     CHAR(4)         NOT NULL,"
+"    dept_no     VARCHAR(4)         NOT NULL,"
 "    dept_name   VARCHAR(40)     NOT NULL,"
 "    PRIMARY KEY (dept_no),"
 "    UNIQUE  KEY (dept_name))"
@@ -117,7 +114,7 @@ const char* departmentsDef = 
 
 const char* dept_managerDef = 
 "CREATE TABLE dept_manager ("
-"   dept_no      CHAR(4)         NOT NULL,"
+"   dept_no      VARCHAR(4)         NOT NULL,"
 "   emp_no       INT             NOT NULL,"
 "   from_date    DATE            NOT NULL,"
 "   to_date      DATE            NOT NULL,"
@@ -135,7 +132,7 @@ const char* dept_managerDef = 
 const char* dept_empDef = 
 "CREATE TABLE dept_emp ("
 "    emp_no      INT             NOT NULL,"
-"    dept_no     CHAR(4)         NOT NULL,"
+"    dept_no     VARCHAR(4)         NOT NULL,"
 "    from_date   DATE            NOT NULL,"
 "    to_date     DATE            NOT NULL,"
 "    KEY         (emp_no),"
@@ -553,8 +550,9 @@ int testQueryBuilder(Ndb &myNdb)
 
     const NdbQueryOperand* joinManagerKey[] =  // Manager is indexed om {"dept_no", "emp_no"}
     {
+      qb->paramValue(),
       //qb->constValue(1005),   // dept_no = "d005"
-      qb->linkedValue(readEmployee,"dept_no"),
+      //qb->linkedValue(readEmployee,"dept_no"),
       qb->linkedValue(readEmployee,"emp_no"),   // emp_no  = 110567
       //qb->constValue(110567),
       //qb->paramValue(),
@@ -575,7 +573,8 @@ int testQueryBuilder(Ndb &myNdb)
   // within the same NdbTransaction::execute(). )
   ////////////////////////////////////////////////////
 
-  void* paramList_q4[] = {&emp_no};
+  void* paramList_q4[] = {&emp_no, dept_no};
+//void* paramList_q4[] = {dept_no};
 
   myTransaction= myNdb.startTransaction();
   if (myTransaction == NULL) APIERROR(myNdb.getNdbError());

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2009-09-28 08:12:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2009-10-02 06:40:46 +0000
@@ -94,9 +94,7 @@ public:
   explicit NdbInt32ConstOperandImpl (Int32 value) : 
     NdbConstOperandImpl(), 
     m_value(value) {}
-  size_t getLength()    const { return sizeof(m_value); }
-  const void* getAddr() const { return &m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Int; }
+  int convertInt32();
 private:
   const Int32 m_value;
 };
@@ -107,9 +105,7 @@ public:
   explicit NdbUint32ConstOperandImpl (Uint32 value) : 
     NdbConstOperandImpl(), 
     m_value(value) {}
-  size_t getLength()    const { return sizeof(m_value); }
-  const void* getAddr() const { return &m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Unsigned; }
+  int convertUint32();
 private:
   const Uint32 m_value;
 };
@@ -120,9 +116,7 @@ public:
   explicit NdbInt64ConstOperandImpl (Int64 value) : 
     NdbConstOperandImpl(), 
     m_value(value) {}
-  size_t getLength()    const { return sizeof(m_value); }
-  const void* getAddr() const { return &m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Bigint; }
+  int convertInt64();
 private:
   const Int64 m_value;
 };
@@ -133,9 +127,7 @@ public:
   explicit NdbUint64ConstOperandImpl (Uint64 value) : 
     NdbConstOperandImpl(), 
     m_value(value) {}
-  size_t getLength()    const { return sizeof(m_value); }
-  const void* getAddr() const { return &m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Bigunsigned; }
+  int convertUint64();
 private:
   const Uint64 m_value;
 };
@@ -145,9 +137,10 @@ class NdbCharConstOperandImpl : public N
 public:
   explicit NdbCharConstOperandImpl (const char* value) : 
     NdbConstOperandImpl(), m_value(value) {}
-  size_t getLength()    const { return strlen(m_value); }
-  const void* getAddr() const { return m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Char; }
+
+  int convertChar();
+  int convertVChar();
+//int convertLVChar();
 private:
   const char* const m_value;
 };
@@ -159,9 +152,8 @@ public:
   : NdbConstOperandImpl(), m_value(value), m_length(length)
   {}
 
-  size_t getLength()    const { return m_length; }
-  const void* getAddr() const { return m_value; }
-  NdbDictionary::Column::Type getType() const { return NdbDictionary::Column::Undefined; }
+  int convert2ColumnType();
+
 private:
   const void* const m_value;
   const size_t m_length;
@@ -182,9 +174,7 @@ public:
   virtual int serializeOperation(Uint32Buffer& serializedDef) const;
 
   virtual int prepareKeyInfo(Uint32Buffer& keyInfo,
-                             const constVoidPtr actualParam[],
-                             bool&   isPruned,
-                             Uint32& hashValue) const;
+                             const constVoidPtr actualParam[]) const;
 
 
 protected:
@@ -278,10 +268,7 @@ public:
   { return TableScan; }
 
   virtual int prepareKeyInfo(Uint32Buffer& keyInfo,
-                             const constVoidPtr actualParam[],
-                             bool&   isPruned,
-                             Uint32& hashValue) const {
-    isPruned = false;
+                             const constVoidPtr actualParam[]) const {
     return 0;
   }
 
@@ -317,9 +304,11 @@ public:
   { return OrderedIndexScan; }
 
   virtual int prepareKeyInfo(Uint32Buffer& keyInfo,
-                             const constVoidPtr actualParam[],
-                             bool&   isPruned,
-                             Uint32& hashValue) const;
+                             const constVoidPtr actualParam[]) const;
+
+  virtual int checkPrunable(const Uint32Buffer& keyInfo,
+                            bool&   isPruned,
+                            Uint32& hashValue) const;
 
 private:
   virtual ~NdbQueryIndexScanOperationDefImpl() {};
@@ -742,7 +731,7 @@ NdbQueryBuilder::readTuple(const NdbDict
               != static_cast<Uint32>(table->getObjectVersion()), 
               QRY_UNRELATED_INDEX);
 
-  // Only 'UNUQUE' indexes may be used for lookup operations:
+  // Only 'UNIQUE' indexes may be used for lookup operations:
   returnErrIf(index->getType()!=NdbDictionary::Index::UniqueHashIndex,
               QRY_WRONG_INDEX_TYPE);
 
@@ -1003,6 +992,250 @@ NdbQueryDefImpl::getQueryOperation(const
   return NULL;
 }
 
+////////////////////////////////////////////////////////////////
+// The (hidden) Impl of NdbQueryOperand (w/ various subclasses)
+////////////////////////////////////////////////////////////////
+
+/* Implicit typeconversion between related datatypes: */
+int NdbUint32ConstOperandImpl::convertUint32()
+{
+  m_converted.val.uint32 = m_value;
+  m_converted.len = sizeof(m_converted.val.uint32);
+  return 0;
+}
+int NdbInt32ConstOperandImpl::convertInt32()
+{
+  m_converted.val.int32 = m_value;
+  m_converted.len = sizeof(m_converted.val.int32);
+  return 0;
+}
+int NdbInt64ConstOperandImpl::convertInt64()
+{
+  m_converted.val.int64 = m_value;
+  m_converted.len = sizeof(m_converted.val.int64);
+  return 0;
+}
+int NdbUint64ConstOperandImpl::convertUint64()
+{
+  m_converted.val.uint64 = m_value;
+  m_converted.len = sizeof(m_converted.val.uint64);
+  return 0;
+}
+
+int NdbCharConstOperandImpl::convertChar()
+{
+  size_t len = m_column->getLength();
+  size_t srclen = (m_value) ? strlen(m_value) : 0;
+  if (unlikely(srclen > len)) {
+    // TODO: Truncates: May silently remove trailing spaces:
+    return QRY_CHAR_OPERAND_TRUNCATED;
+    srclen = len;
+  }
+
+  char* dst = m_converted.val.shortChar;
+  if (unlikely(len > sizeof(m_converted.val.shortChar))) {
+    dst = new char[len];
+    if (unlikely(dst==NULL))
+      return Err_MemoryAlloc;
+    m_converted.buffer = dst;
+  }
+
+  memcpy (dst, m_value, srclen);
+  if (unlikely(srclen < len)) {
+    memset (dst+srclen, ' ', len-srclen);
+  }
+  m_converted.len = len;
+  return 0;
+} //NdbCharConstOperandImpl::convertChar
+
+int NdbCharConstOperandImpl::convertVChar()
+{
+  size_t maxlen = m_column->getLength();
+  size_t len = (m_value) ? strlen(m_value) : 0;
+  if (unlikely(len > maxlen)) {
+    // TODO: Truncates: May silently remove trailing spaces:
+    return QRY_CHAR_OPERAND_TRUNCATED;
+    len = maxlen;
+  }
+
+  char* dst = m_converted.val.shortChar;
+  if (unlikely(len > sizeof(m_converted.val.shortChar))) {
+    dst = new char[len];
+    if (unlikely(dst==NULL))
+      return Err_MemoryAlloc;
+    m_converted.buffer = dst;
+  }
+
+  memcpy (dst, m_value, len);
+  m_converted.len = len;
+  return 0;
+} //NdbCharConstOperandImpl::convertVChar
+
+/**
+ * GenericConst is 'raw data' with minimal type checking and conversion capability.
+ */
+int
+NdbGenericConstOperandImpl::convert2ColumnType()
+{
+  size_t len = m_column->getSizeInBytes();
+  if (unlikely(len != m_length)) {
+    return QRY_OPERAND_HAS_WRONG_TYPE;
+  }
+
+  void* dst = &m_converted.val;
+  if (unlikely(len > sizeof(m_converted.val))) {
+    dst = new char[len];
+    if (unlikely(dst==NULL))
+      return Err_MemoryAlloc;
+    m_converted.buffer = dst;
+  }
+
+  memcpy (dst, m_value, len);
+  m_converted.len = len;
+  return 0;
+}
+
+int
+NdbConstOperandImpl::convert2ColumnType()
+{
+  switch(m_column->getType()) {
+    case NdbDictionary::Column::Tinyint:         return convertInt8();
+    case NdbDictionary::Column::Tinyunsigned:    return convertUint8();
+    case NdbDictionary::Column::Smallint:        return convertInt16();
+    case NdbDictionary::Column::Smallunsigned:   return convertUint16();
+    case NdbDictionary::Column::Mediumint:       return convertInt24();
+    case NdbDictionary::Column::Mediumunsigned:  return convertUint24();
+    case NdbDictionary::Column::Int:             return convertInt32();
+    case NdbDictionary::Column::Unsigned:        return convertUint32();
+    case NdbDictionary::Column::Bigint:          return convertInt64();
+    case NdbDictionary::Column::Bigunsigned:     return convertUint64();
+    case NdbDictionary::Column::Float:           return convertFloat();
+    case NdbDictionary::Column::Double:          return convertDouble();
+
+    case NdbDictionary::Column::Decimal:         return convertDec();
+    case NdbDictionary::Column::Decimalunsigned: return convertUDec();
+
+    case NdbDictionary::Column::Char:            return convertChar();
+    case NdbDictionary::Column::Varchar:         return convertVChar();
+    case NdbDictionary::Column::Longvarchar:     return convertLVChar();
+    case NdbDictionary::Column::Binary:          return convertBin();
+    case NdbDictionary::Column::Varbinary:       return convertVBin();
+    case NdbDictionary::Column::Longvarbinary:   return convertLVBin();
+    case NdbDictionary::Column::Bit:             return convertBit();
+
+    case NdbDictionary::Column::Date:            return convertDate();
+    case NdbDictionary::Column::Time:            return convertTime();
+    case NdbDictionary::Column::Datetime:        return convertDatetime();
+    case NdbDictionary::Column::Timestamp:       return convertTimestamp();
+    case NdbDictionary::Column::Year:            return convertYear();
+
+    // Type conversion intentionally not supported (yet)
+    case NdbDictionary::Column::Olddecimal:
+    case NdbDictionary::Column::Olddecimalunsigned: 
+    case NdbDictionary::Column::Blob:
+    case NdbDictionary::Column::Text: 
+      // Fall through:
+
+    default:
+    case NdbDictionary::Column::Undefined:    return QRY_OPERAND_HAS_WRONG_TYPE;
+  }
+
+  return 0;
+} //NdbConstOperandImpl::convert2ColumnType
+
+int
+NdbConstOperandImpl::bindOperand(
+                           const NdbColumnImpl& column,
+                           NdbQueryOperationDefImpl& operation)
+{
+  const int error = NdbQueryOperandImpl::bindOperand(column,operation);
+  if (unlikely(error))
+    return error;
+
+  return convert2ColumnType();
+}
+
+
+
+int
+NdbLinkedOperandImpl::bindOperand(
+                           const NdbColumnImpl& column,
+                           NdbQueryOperationDefImpl& operation)
+{
+  const NdbColumnImpl& parentColumn = getParentColumn();
+  
+  if (unlikely(column.m_type      != parentColumn.m_type ||
+               column.m_precision != parentColumn.m_precision ||
+               column.m_scale     != parentColumn.m_scale ||
+               column.m_length    != parentColumn.m_length ||
+               column.m_cs        != parentColumn.m_cs))
+    return QRY_OPERAND_HAS_WRONG_TYPE;  // Incompatible datatypes
+
+  if (unlikely(column.m_type == NdbDictionary::Column::Blob ||
+               column.m_type == NdbDictionary::Column::Text))
+    return QRY_OPERAND_HAS_WRONG_TYPE;  // BLOB/CLOB datatypes intentionally not supported
+
+  // TODO: Allow and autoconvert compatible datatypes
+
+  // Register parent/child operation relations
+  this->m_parentOperation.addChild(&operation);
+  operation.addParent(&this->m_parentOperation);
+
+  return NdbQueryOperandImpl::bindOperand(column,operation);
+}
+
+
+size_t
+NdbParamOperandImpl::getSizeInBytes(const constVoidPtr paramValue) const
+{
+  switch(m_column->getType()) {
+
+    case NdbDictionary::Column::Bit: 
+    case NdbDictionary::Column::Blob:
+    case NdbDictionary::Column::Text: 
+    case NdbDictionary::Column::Varbinary:
+    case NdbDictionary::Column::Longvarbinary:
+      // TODO, how to handle varsize binary: 
+      //   - These are not char strings so strlen() is unusable.
+      //   - Neither are they fixed size: m_column.getLength() does not make sense.
+      assert(false);
+
+    case NdbDictionary::Column::Varchar:
+    case NdbDictionary::Column::Longvarchar:
+    { size_t len = strlen((char*)paramValue);
+      assert (len <= (size_t)m_column->getLength());
+      return len;
+    }
+
+    // Fixed size assumed and required to match column maxsize
+    case NdbDictionary::Column::Char:
+      assert (strlen((char*)paramValue) == (size_t)m_column->getLength());
+      // Fall through:
+
+    default:
+      assert (m_column->getArrayType()==NdbDictionary::Column::ArrayTypeFixed );
+      return m_column->getSizeInBytes();
+  }
+}
+
+int
+NdbParamOperandImpl::bindOperand(
+                           const NdbColumnImpl& column,
+                           NdbQueryOperationDefImpl& operation)
+{
+  if (unlikely(column.m_type == NdbDictionary::Column::Blob ||
+               column.m_type == NdbDictionary::Column::Text))
+    return QRY_OPERAND_HAS_WRONG_TYPE;  // BLOB/CLOB datatypes intentionally not supported
+
+  operation.addParamRef(this);
+  return NdbQueryOperandImpl::bindOperand(column,operation);
+}
+
+
+
+/////////////////////////////////////////////////////////////////
+// The (hidden) Impl of NdbQueryOperation (w/ various subclasses)
+///////////////////////>/////////////////////////////////////////
 
 NdbQueryLookupOperationDefImpl::NdbQueryLookupOperationDefImpl (
                            const NdbTableImpl& table,
@@ -1067,13 +1300,48 @@ NdbQueryIndexScanOperationDefImpl::NdbQu
   }
 }
 
+
+
+static int
+formatAttr(const NdbColumnImpl* column,
+           constVoidPtr& value, size_t& len,
+           char* buffer, size_t buflen)
+{
+  // Check that column->shrink_varchar() not specified, only used by mySQL
+  // assert (!(column->flags & NdbDictionary::RecMysqldShrinkVarchar));
+
+  switch (column->getArrayType()) {
+    case NdbDictionary::Column::ArrayTypeFixed:
+      break;
+    case NdbDictionary::Column::ArrayTypeShortVar:
+      if (unlikely(len > 0xFF || len+1 > buflen))
+        return QRY_CHAR_OPERAND_TRUNCATED;
+      buffer[0] = (unsigned char)len;
+      memcpy(buffer+1, value, len);
+      len+=1;
+      value = buffer;
+      break;
+    case NdbDictionary::Column::ArrayTypeMediumVar:
+      if (unlikely(len > 0xFFFF || len+2 > buflen))
+        return QRY_CHAR_OPERAND_TRUNCATED;
+      buffer[0] = (unsigned char)(len & 0xFF);
+      buffer[1] = (unsigned char)(len >> 8);
+      memcpy(buffer+2, value, len);
+      len+=2;
+      value = buffer;
+      break;
+    default:
+      assert(false);
+  }
+  return 0;
+} // static formatAttr
+
 static int
 appendBound(Uint32Buffer& keyInfo,
             NdbIndexScanOperation::BoundType type, const NdbQueryOperandImpl* bound,
-            const constVoidPtr actualParam[],
-            Ndb::Key_part_ptr& keyPart) 
+            const constVoidPtr actualParam[]) 
 {
-  Uint32 len = 0;
+  size_t len = 0;
   constVoidPtr boundValue = NULL;
 
   assert (bound);
@@ -1081,8 +1349,8 @@ appendBound(Uint32Buffer& keyInfo,
   case NdbQueryOperandImpl::Const:
   {
     const NdbConstOperandImpl* constOp = static_cast<const NdbConstOperandImpl*>(bound);
-    len = constOp->getLength();
     boundValue = constOp->getAddr();
+    len = constOp->getSizeInBytes();
     break;
   }
   case NdbQueryOperandImpl::Param:
@@ -1093,38 +1361,39 @@ appendBound(Uint32Buffer& keyInfo,
     assert(actualParam != NULL);
     if (unlikely(actualParam[paramNo] == NULL))
       return 4316;  // Error: 'Key attributes are not allowed to be NULL attributes'
-    len = paramOp->getColumn()->getSizeInBytes();
     boundValue = actualParam[paramNo];
+    len = paramOp->getSizeInBytes(boundValue);
     break;
   }
   case NdbQueryOperandImpl::Linked:    // Root operation cannot have linked operands.
   default:
     assert(false);
   }
+    
+  char tmp[NDB_MAX_KEY_SIZE];
+  const NdbColumnImpl* column = bound->getColumn();
+
+  int error = formatAttr(column, boundValue, len, tmp, sizeof(tmp));
+  if (unlikely(error))
+    return error;
 
-//column->get_var_length(... ,len) .... TODO !
-
-  AttributeHeader ah(bound->getColumn()->m_attrId, len);
+  AttributeHeader ah(column->m_attrId, len);
 
   keyInfo.append(type);
   keyInfo.append(ah.m_value);
   keyInfo.append(boundValue,len);
 
-  keyPart.ptr = boundValue;
-  keyPart.len = len;
   return 0;
-} // appendBound()
+} // static appendBound()
+
 
 int
 NdbQueryLookupOperationDefImpl::prepareKeyInfo(
                               Uint32Buffer& keyInfo,
-                              const constVoidPtr actualParam[],
-                              bool&   isPruned,
-                              Uint32& hashValue) const  // 'hashValue' only defined if 'isPruned'
+                              const constVoidPtr actualParam[]) const
 { 
   assert(getQueryOperationIx()==0); // Should only be called for root operation.
   int startPos = keyInfo.getSize();
-  isPruned = false;
 
   const int keyCount = getIndex()==NULL ? 
     getTable().getNoOfPrimaryKeys() :
@@ -1132,7 +1401,7 @@ NdbQueryLookupOperationDefImpl::prepareK
 
   for (int keyNo = 0; keyNo<keyCount; keyNo++)
   {
-    Uint32 len = 0;
+    size_t len = 0;
     constVoidPtr boundValue = NULL;
 
     switch(m_keys[keyNo]->getKind()){
@@ -1140,8 +1409,8 @@ NdbQueryLookupOperationDefImpl::prepareK
     {
       const NdbConstOperandImpl* const constOp 
         = static_cast<const NdbConstOperandImpl*>(m_keys[keyNo]);
-      len = constOp->getLength();
       boundValue = constOp->getAddr();
+      len = constOp->getSizeInBytes();
       break;
     }
     case NdbQueryOperandImpl::Param:
@@ -1152,8 +1421,8 @@ NdbQueryLookupOperationDefImpl::prepareK
       assert(actualParam != NULL);
       if (unlikely(actualParam[paramNo] == NULL))
         return 4316;  // Error: 'Key attributes are not allowed to be NULL attributes'
-      len = paramOp->getColumn()->getSizeInBytes();
       boundValue = actualParam[paramNo];
+      len = paramOp->getSizeInBytes(boundValue);
       break;
     }
     case NdbQueryOperandImpl::Linked:    // Root operation cannot have linked operands.
@@ -1161,7 +1430,12 @@ NdbQueryLookupOperationDefImpl::prepareK
       assert(false);
     }
 
-    //column->get_var_length(... ,len) / column->shrink_varchar() .... TODO !
+    char tmp[NDB_MAX_KEY_SIZE];
+    const NdbColumnImpl* column = m_keys[keyNo]->getColumn();
+
+    int error = formatAttr(column, boundValue, len, tmp, sizeof(tmp));
+    if (unlikely(error))
+      return error;
 
     keyInfo.append(boundValue,len);
   }
@@ -1186,32 +1460,16 @@ NdbQueryLookupOperationDefImpl::prepareK
 int
 NdbQueryIndexScanOperationDefImpl::prepareKeyInfo(
                               Uint32Buffer& keyInfo,
-                              const constVoidPtr actualParam[],
-                              bool&   isPruned,
-                              Uint32& hashValue) const  // 'hashValue' only defined if 'isPruned'
+                              const constVoidPtr actualParam[]) const
 { 
   assert(getQueryOperationIx()==0); // Should only be called for root operation.
   int startPos = keyInfo.getSize();
+  assert (startPos == 0);  // Assumed by ::checkPrunable
 
-  // Required for partition pruning calculation
-  const NdbRecord* key_record = m_index.getDefaultRecord();
-
-  const Uint32 index_distkeys = key_record->m_no_of_distribution_keys;
-  const Uint32 distkey_min = key_record->m_min_distkey_prefix_length;
-  const Uint32 table_distkeys = getTable().getDefaultRecord()->m_no_of_distribution_keys;
-
-  bool isPrunable = (                             // Initial prunable propert:
-            index_distkeys == table_distkeys &&   // Index has all base table d-keys
-            m_bound.lowKeys >= distkey_min &&     // Low bounds have all d-keys
-            m_bound.highKeys >= distkey_min);     // High bounds have all d-keys
-
-  Ndb::Key_part_ptr lowKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY];
-  Ndb::Key_part_ptr highKey;
-
-  const Uint32 key_count = 
+  const unsigned key_count = 
      (m_bound.lowKeys >= m_bound.highKeys) ? m_bound.lowKeys : m_bound.highKeys;
 
-  for (Uint32 keyNo = 0; keyNo < key_count; keyNo++)
+  for (unsigned keyNo = 0; keyNo < key_count; keyNo++)
   {
     NdbIndexScanOperation::BoundType bound_type;
 
@@ -1220,7 +1478,7 @@ NdbQueryIndexScanOperationDefImpl::prepa
     {
       /* Inclusive if defined, or matching rows can include this value */
       bound_type= NdbIndexScanOperation::BoundEQ;
-      int error = appendBound(keyInfo, bound_type, m_bound.low[keyNo], actualParam, lowKey[keyNo]);
+      int error = appendBound(keyInfo, bound_type, m_bound.low[keyNo], actualParam);
       if (unlikely(error))
         return error;
 
@@ -1233,7 +1491,7 @@ NdbQueryIndexScanOperationDefImpl::prepa
         bound_type= m_bound.lowIncl  || keyNo+1 < m_bound.lowKeys ?
             NdbIndexScanOperation::BoundLE : NdbIndexScanOperation::BoundLT;
 
-        int error = appendBound(keyInfo, bound_type, m_bound.low[keyNo], actualParam, lowKey[keyNo]);
+        int error = appendBound(keyInfo, bound_type, m_bound.low[keyNo], actualParam);
         if (unlikely(error))
           return error;
       }
@@ -1245,15 +1503,65 @@ NdbQueryIndexScanOperationDefImpl::prepa
         bound_type= m_bound.highIncl  || keyNo+1 < m_bound.highKeys ?
             NdbIndexScanOperation::BoundGE : NdbIndexScanOperation::BoundGT;
 
-        int error = appendBound(keyInfo, bound_type, m_bound.high[keyNo], actualParam, highKey);
+        int error = appendBound(keyInfo, bound_type, m_bound.high[keyNo], actualParam);
         if (unlikely(error))
           return error;
       }
+    }
+  }
+
+  size_t length = keyInfo.getSize()-startPos;
+  if (unlikely(keyInfo.isMemoryExhausted())) {
+    return Err_MemoryAlloc;
+  } else if (unlikely(length > 0xFFFF)) {
+    return QRY_DEFINITION_TOO_LARGE; // Query definition too large.
+  } else if (likely(length > 0)) {
+    keyInfo.put(startPos, keyInfo.get(startPos) | (length << 16));
+  }
+
+#if 0
+  /**
+   * Determine if scan may be pruned to a single partition:
+   */
+  const NdbRecord* key_record = m_index.getDefaultRecord();
+
+  const Uint32 index_distkeys = key_record->m_no_of_distribution_keys;
+  const Uint32 distkey_min = key_record->m_min_distkey_prefix_length;
+  const Uint32 table_distkeys = getTable().getDefaultRecord()->m_no_of_distribution_keys;
+
+  bool isPrunable = (                             // Initial prunable propert:
+            index_distkeys == table_distkeys &&   // Index has all base table d-keys
+            m_bound.lowKeys >= distkey_min &&     // Low bounds have all d-keys
+            m_bound.highKeys >= distkey_min);     // High bounds have all d-keys
+
+  isPruned = false;
+  if (isPrunable) {
+    Ndb::Key_part_ptr lowKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY];
+    Ndb::Key_part_ptr highKey;
 
-      // Aggregate prunable propert:
-      // All hi/low keys within 'distkey_min' must be equal
-      if (isPrunable  &&  keyNo < distkey_min) 
+    // Aggregate prunable propert:
+    // All hi/low keys values within 'distkey_min' must be equal
+    int keyPos = startPos;
+    for (unsigned keyNo = 0; keyNo < distkey_min; keyNo++)
+    {
+      Uint32 type        = keyInfo.get(keyPos) & 0xFFFF;
+      AttributeHeader ah = keyInfo.get(keyPos+1);
+      lowKey[keyNo].len = ah.getByteSize();
+      lowKey[keyNo].ptr = keyInfo.addr(keyPos+2);
+
+      keyPos += 1+1+ah.getDataSize();  // Skip data read above.
+
+      // Only has to compare values if not known to be 'BoundEQ'
+      if (type != NdbIndexScanOperation::BoundEQ)
       {
+        assert ((keyInfo.get(keyPos) & 0xFFFF) != NdbIndexScanOperation::BoundEQ);
+        AttributeHeader ah = keyInfo.get(keyPos+1);
+        highKey.len = ah.getByteSize();
+        highKey.ptr = keyInfo.addr(keyPos+2);
+
+        keyPos += 1+1+ah.getDataSize();  // Skip data read above.
+
+        // Compare high and low bound value:
         const NdbColumnImpl& column = NdbColumnImpl::getImpl(*m_index.getColumn(keyNo));
         const NdbRecord::Attr& recAttr = key_record->columns[column.m_keyInfoPos];
         const int res=
@@ -1263,28 +1571,120 @@ NdbQueryIndexScanOperationDefImpl::prepa
         if (res!=0) {  // Not equal
           assert(res != NdbSqlUtil::CmpUnknown);
           isPrunable = false;
+          break;
         }
+      } // != BoundEQ
+    } // for()
+
+    // Scan is now known to be prunable, calculate hashValue
+    if (isPrunable) {
+      isPruned = true;
+      Ndb::Key_part_ptr distKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY+1];
+
+      // hi/low is equal and prunable bounds, remember key for later 
+      // hashValue calculation.
+      for (Uint32 i = 0; i<key_record->distkey_index_length; i++)  {
+        // Revers lookup the index column with the value of this distrubution key.
+        Uint32 keyPos = NdbColumnImpl::getImpl(*m_index.getColumn(key_record->distkey_indexes[i])).m_keyInfoPos;
+        distKey[i] = lowKey[keyPos];
       }
+      distKey[key_record->distkey_index_length].ptr = NULL;
+
+      int error = Ndb::computeHash(&hashValue, &getTable(), distKey, NULL, 0);
+      if (unlikely(error))
+        return error;
     }
-  }
+  } // if 'isPrunable'
+#endif
 
-  size_t length = keyInfo.getSize()-startPos;
-  if (unlikely(keyInfo.isMemoryExhausted())) {
-    return Err_MemoryAlloc;
-  } else if (unlikely(length > 0xFFFF)) {
-    return QRY_DEFINITION_TOO_LARGE; // Query definition too large.
-  } else if (likely(length > 0)) {
-    keyInfo.put(startPos, keyInfo.get(startPos) | (length << 16));
+#ifdef TRACE_SERIALIZATION
+  ndbout << "Serialized KEYINFO w/ bounds for scan root : ";
+  for (Uint32 i = startPos; i < keyInfo.getSize(); i++) {
+    char buf[12];
+    sprintf(buf, "%.8x", keyInfo.get(i));
+    ndbout << buf << " ";
   }
+  ndbout << endl;
+#endif
+
+  return 0;
+
+} // NdbQueryIndexScanOperationDefImpl::prepareKeyInfo
+
 
-  // Scan is pruned, calculate hashValue
-  isPruned = isPrunable;
+int
+NdbQueryIndexScanOperationDefImpl::checkPrunable(
+                              const Uint32Buffer& keyInfo,
+                              bool&   isPruned,
+                              Uint32& hashValue) const  // 'hashValue' only defined if 'isPruned'
+{ 
+
+  /**
+   * Determine if scan may be pruned to a single partition:
+   */
+  const NdbRecord* key_record = m_index.getDefaultRecord();
+
+  const Uint32 index_distkeys = key_record->m_no_of_distribution_keys;
+  const Uint32 distkey_min = key_record->m_min_distkey_prefix_length;
+  const Uint32 table_distkeys = getTable().getDefaultRecord()->m_no_of_distribution_keys;
+
+  bool isPrunable = (                             // Initial prunable propert:
+            index_distkeys == table_distkeys &&   // Index has all base table d-keys
+            m_bound.lowKeys >= distkey_min &&     // Low bounds have all d-keys
+            m_bound.highKeys >= distkey_min);     // High bounds have all d-keys
+
+  isPruned = false;
   if (isPrunable) {
+    Ndb::Key_part_ptr lowKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY];
+    Ndb::Key_part_ptr highKey;
+
+    // Aggregate prunable propert:
+    // All hi/low keys values within 'distkey_min' must be equal
+    int keyPos = 0;
+    for (unsigned keyNo = 0; keyNo < distkey_min; keyNo++)
+    {
+      Uint32 type        = keyInfo.get(keyPos) & 0xFFFF;
+      AttributeHeader ah = keyInfo.get(keyPos+1);
+      lowKey[keyNo].len = ah.getByteSize();
+      lowKey[keyNo].ptr = keyInfo.addr(keyPos+2);
+
+      keyPos += 1+1+ah.getDataSize();  // Skip data read above.
+
+      // Only has to compare values if not known to be 'BoundEQ'
+      if (type != NdbIndexScanOperation::BoundEQ)
+      {
+        assert ((keyInfo.get(keyPos) & 0xFFFF) != NdbIndexScanOperation::BoundEQ);
+        AttributeHeader ah = keyInfo.get(keyPos+1);
+        highKey.len = ah.getByteSize();
+        highKey.ptr = keyInfo.addr(keyPos+2);
+
+        keyPos += 1+1+ah.getDataSize();  // Skip data read above.
+
+        // Compare high and low bound value:
+        const NdbColumnImpl& column = NdbColumnImpl::getImpl(*m_index.getColumn(keyNo));
+        const NdbRecord::Attr& recAttr = key_record->columns[column.m_keyInfoPos];
+        const int res=
+          (*recAttr.compare_function)(recAttr.charset_info,
+                                       lowKey[keyNo].ptr, lowKey[keyNo].len,
+                                       highKey.ptr, highKey.len, true);
+        if (res!=0) {  // Not equal
+          assert(res != NdbSqlUtil::CmpUnknown);
+          isPrunable = false;
+          return 0;
+        }
+      } // != BoundEQ
+    } // for()
+
+
+    // Scan is now known to be prunable, calculate hashValue
+    assert (isPrunable);
+
+    isPruned = true;
     Ndb::Key_part_ptr distKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY+1];
 
     // hi/low is equal and prunable bounds, remember key for later 
     // hashValue calculation.
-    for (Uint32 i = 0; i<key_record->distkey_index_length; i++)  {
+    for (unsigned i = 0; i<key_record->distkey_index_length; i++)  {
       // Revers lookup the index column with the value of this distrubution key.
       Uint32 keyPos = NdbColumnImpl::getImpl(*m_index.getColumn(key_record->distkey_indexes[i])).m_keyInfoPos;
       distKey[i] = lowKey[keyPos];
@@ -1294,21 +1694,12 @@ NdbQueryIndexScanOperationDefImpl::prepa
     int error = Ndb::computeHash(&hashValue, &getTable(), distKey, NULL, 0);
     if (unlikely(error))
       return error;
-  }
-
-#ifdef TRACE_SERIALIZATION
-  ndbout << "Serialized KEYINFO w/ bounds for scan root : ";
-  for (Uint32 i = startPos; i < keyInfo.getSize(); i++) {
-    char buf[12];
-    sprintf(buf, "%.8x", keyInfo.get(i));
-    ndbout << buf << " ";
-  }
-  ndbout << endl;
-#endif
+  } // if 'isPrunable'
 
   return 0;
 
-} // NdbQueryIndexScanOperationDefImpl::prepareKeyInfo
+} // NdbQueryIndexScanOperationDefImpl::checkPrunable
+
 
 void
 NdbQueryOperationDefImpl::addParent(NdbQueryOperationDefImpl* parentOp)
@@ -1348,49 +1739,6 @@ NdbQueryOperationDefImpl::addColumnRef(c
 }
 
 
-int
-NdbLinkedOperandImpl::bindOperand(
-                           const NdbColumnImpl& column,
-                           NdbQueryOperationDefImpl& operation)
-{
-  NdbDictionary::Column::Type type = column.getType();
-  if (type != getParentColumn().getType())
-    return QRY_OPERAND_HAS_WRONG_TYPE ;  // Incompatible datatypes
-
-  // TODO? Check length if Char, and prec, scale if decimal type
-
-  // Register parent/child operation relations
-  this->m_parentOperation.addChild(&operation);
-  operation.addParent(&this->m_parentOperation);
-
-  return NdbQueryOperandImpl::bindOperand(column,operation);
-}
-
-
-int
-NdbParamOperandImpl::bindOperand(
-                           const NdbColumnImpl& column,
-                           NdbQueryOperationDefImpl& operation)
-{
-  operation.addParamRef(this);
-  return NdbQueryOperandImpl::bindOperand(column,operation);
-}
-
-
-int
-NdbConstOperandImpl::bindOperand(
-                           const NdbColumnImpl& column,
-                           NdbQueryOperationDefImpl& operation)
-{
-  NdbDictionary::Column::Type type = column.getType();
-  if (type != this->getType())
-    return QRY_OPERAND_HAS_WRONG_TYPE ;  // Incompatible datatypes
-
-  // TODO? Check length if Char, and prec,scale if decimal type
-
-  return NdbQueryOperandImpl::bindOperand(column,operation);
-}
-
 /** This class is used for serializing sequences of 16 bit integers,
  * where the first 16 bit integer specifies the length of the sequence.
  */
@@ -1495,13 +1843,13 @@ appendKeyPattern(Uint32Buffer& serialize
 	  = *static_cast<const NdbConstOperandImpl*>(key);
      
         // No of words needed for storing the constant data.
-        const Uint32 wordCount =  AttributeHeader::getDataSize(constOp.getLength());
+        const Uint32 wordCount =  AttributeHeader::getDataSize(constOp.getSizeInBytes());
         // Set type and length in words of key pattern field. 
         serializedDef.append(QueryPattern::data(wordCount));
-        serializedDef.append(constOp.getAddr(),constOp.getLength());
+        serializedDef.append(constOp.getAddr(),constOp.getSizeInBytes());
         break;
       }
-      case NdbQueryOperandImpl::Param:  // TODO: Convert to a Const immediately
+      case NdbQueryOperandImpl::Param:
       {
         appendedPattern |= DABits::NI_KEY_PARAMS;
         paramCnt++;

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2009-09-28 08:12:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2009-10-02 06:40:46 +0000
@@ -25,15 +25,17 @@
 #define QRY_TOO_FEW_KEY_VALUES 4801
 #define QRY_TOO_MANY_KEY_VALUES 4802
 #define QRY_OPERAND_HAS_WRONG_TYPE 4803
-#define QRY_UNKONWN_PARENT 4804
-#define QRY_UNKNOWN_COLUMN 4805
-#define QRY_UNRELATED_INDEX 4806
-#define QRY_WRONG_INDEX_TYPE 4807
-#define QRY_OPERAND_ALREADY_BOUND 4808
-#define QRY_DEFINITION_TOO_LARGE 4809
-#define QRY_DUPLICATE_COLUMN_IN_PROJ 4810
-#define QRY_NEED_PARAMETER 4811
-#define QRY_RESULT_ROW_ALREADY_DEFINED 4812
+#define QRY_CHAR_OPERAND_TRUNCATED 4804
+#define QRY_NUM_OPERAND_RANGE 4805
+#define QRY_UNKONWN_PARENT 4806
+#define QRY_UNKNOWN_COLUMN 4807
+#define QRY_UNRELATED_INDEX 4808
+#define QRY_WRONG_INDEX_TYPE 4809
+#define QRY_OPERAND_ALREADY_BOUND 4810
+#define QRY_DEFINITION_TOO_LARGE 4811
+#define QRY_DUPLICATE_COLUMN_IN_PROJ 4812
+#define QRY_NEED_PARAMETER 4813
+#define QRY_RESULT_ROW_ALREADY_DEFINED 4814
 
 #ifdef __cplusplus
 #include <Vector.hpp>
@@ -310,9 +312,14 @@ public:
    * Returns: 0 if OK, or possible an errorcode.
    */
   virtual int prepareKeyInfo(Uint32Buffer& keyInfo,
-                             const constVoidPtr actualParam[],
+                             const constVoidPtr actualParam[]) const = 0;
+
+  virtual int checkPrunable(const Uint32Buffer& keyInfo,
                              bool&   isPruned,
-                             Uint32& hashValue) const = 0;
+                             Uint32& hashValue) const {
+    isPruned = false;
+    return 0;
+  }
 
   virtual ~NdbQueryOperationDefImpl() = 0;
 
@@ -482,7 +489,7 @@ protected:
       m_kind(kind)
   {}
 
-private:
+protected:
   const NdbColumnImpl* m_column;       // Initial NULL, assigned w/ bindOperand()
   /** This is used to tell the type of an NdbQueryOperand. This allow safe
    * downcasting to a subclass.
@@ -496,9 +503,6 @@ class NdbLinkedOperandImpl : public NdbQ
   friend class NdbQueryBuilder;  // Allow privat access from builder interface
 
 public:
-  virtual int bindOperand(const NdbColumnImpl& column,
-                          NdbQueryOperationDefImpl& operation);
-
   const NdbQueryOperationDefImpl& getParentOperation() const
   { return m_parentOperation; }
 
@@ -513,6 +517,9 @@ public:
   virtual const NdbLinkedOperand& getInterface() const
   { return m_interface; }
 
+  virtual int bindOperand(const NdbColumnImpl& column,
+                          NdbQueryOperationDefImpl& operation);
+
 private:
   virtual ~NdbLinkedOperandImpl() {}
 
@@ -535,18 +542,20 @@ class NdbParamOperandImpl : public NdbQu
   friend class NdbQueryBuilder;  // Allow privat access from builder interface
 
 public:
-  virtual int bindOperand(const NdbColumnImpl& column,
-                          NdbQueryOperationDefImpl& operation);
-
   const char* getName() const
   { return m_name; }
 
   Uint32 getParamIx() const
   { return m_paramIx; }
 
+  size_t getSizeInBytes(const constVoidPtr paramValue) const;
+
   virtual const NdbParamOperand& getInterface() const
   { return m_interface; }
 
+  virtual int bindOperand(const NdbColumnImpl& column,
+                          NdbQueryOperationDefImpl& operation);
+
 private:
   virtual ~NdbParamOperandImpl() {}
   NdbParamOperandImpl (const char* name, Uint32 paramIx)
@@ -566,24 +575,88 @@ class NdbConstOperandImpl : public NdbQu
 {
   friend class NdbQueryBuilder;  // Allow privat access from builder interface
 public:
-  virtual size_t getLength() const = 0;
-  virtual const void* getAddr() const = 0;
-
-  virtual int bindOperand(const NdbColumnImpl& column,
-                          NdbQueryOperationDefImpl& operation);
-
-  virtual NdbDictionary::Column::Type getType() const = 0;
+  size_t getSizeInBytes()    const
+  { return m_converted.len; }
+  const void* getAddr() const
+  { return likely(m_converted.buffer==NULL) ? &m_converted.val : m_converted.buffer; }
 
   virtual const NdbConstOperand& getInterface() const
   { return m_interface; }
 
+  virtual int bindOperand(const NdbColumnImpl& column,
+                          NdbQueryOperationDefImpl& operation);
+
 protected:
   virtual ~NdbConstOperandImpl() {}
   NdbConstOperandImpl ()
     : NdbQueryOperandImpl(Const),
+      m_converted(),
       m_interface(*this)
   {}
 
+  #define UNDEFINED_CONVERSION	\
+  { return QRY_OPERAND_HAS_WRONG_TYPE; }
+
+  virtual int convertUint8()  UNDEFINED_CONVERSION;
+  virtual int convertInt8()   UNDEFINED_CONVERSION;
+  virtual int convertUint16() UNDEFINED_CONVERSION;
+  virtual int convertInt16()  UNDEFINED_CONVERSION;
+  virtual int convertUint24() UNDEFINED_CONVERSION;
+  virtual int convertInt24()  UNDEFINED_CONVERSION;
+  virtual int convertUint32() UNDEFINED_CONVERSION;
+  virtual int convertInt32()  UNDEFINED_CONVERSION;
+  virtual int convertUint64() UNDEFINED_CONVERSION;
+  virtual int convertInt64()  UNDEFINED_CONVERSION;
+  virtual int convertFloat()  UNDEFINED_CONVERSION;
+  virtual int convertDouble() UNDEFINED_CONVERSION
+
+  virtual int convertUDec()   UNDEFINED_CONVERSION;
+  virtual int convertDec()    UNDEFINED_CONVERSION;
+
+  virtual int convertBit()    UNDEFINED_CONVERSION;
+  virtual int convertChar()   UNDEFINED_CONVERSION;
+  virtual int convertVChar()  UNDEFINED_CONVERSION;
+  virtual int convertLVChar() UNDEFINED_CONVERSION;
+  virtual int convertBin()    UNDEFINED_CONVERSION;
+  virtual int convertVBin()   UNDEFINED_CONVERSION;
+  virtual int convertLVBin()  UNDEFINED_CONVERSION;
+
+  virtual int convertDate()   UNDEFINED_CONVERSION;
+  virtual int convertDatetime() UNDEFINED_CONVERSION;
+  virtual int convertTime()   UNDEFINED_CONVERSION;
+  virtual int convertYear()   UNDEFINED_CONVERSION;
+  virtual int convertTimestamp() UNDEFINED_CONVERSION;
+
+
+  virtual int convert2ColumnType();
+
+
+  STATIC_CONST(maxShortChar = 32);
+
+  /** Values converted to datatype format as expected by bound column 
+    * (available through ::getColumn())
+    */
+  class ConvertedValue {
+  public:
+    ConvertedValue()  : len(0), buffer(NULL) {};
+    ~ConvertedValue() {
+      if (buffer) delete[] ((char*)buffer);
+    };
+
+    union
+    {
+      Uint32    uint32;
+      Int32     int32;
+      Uint64    uint64;
+      Int64     int64;
+
+      char      shortChar[maxShortChar];
+    } val;
+
+    size_t len;
+    void*  buffer;  // Optional; storage for converted value
+  } m_converted;
+
 private:
   NdbConstOperand m_interface;
 }; // class NdbConstOperandImpl

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2009-10-01 12:36:09 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2009-10-02 06:40:46 +0000
@@ -316,8 +316,6 @@ NdbQueryImpl::NdbQueryImpl(NdbTransactio
   m_maxBatchRows(0),
   m_applStreams(),
   m_fullStreams(),
-  m_isPruned(false),
-  m_hashValue(0),
   m_signal(0),
   m_attrInfo(),
   m_keyInfo()
@@ -382,8 +380,7 @@ NdbQueryImpl::assignParameters(const con
    * Also calculate prunable property, and possibly its hashValue.
    */
   // Build explicit key/filter/bounds for root operation, possibly refering paramValues
-  const int error = getRoot().getQueryOperationDef()
-      .prepareKeyInfo(m_keyInfo, paramValues, m_isPruned, m_hashValue);
+  const int error = getRoot().getQueryOperationDef().prepareKeyInfo(m_keyInfo, paramValues);
   if (unlikely(error != 0))
     return error;
 
@@ -861,6 +858,12 @@ NdbQueryImpl::doSend(int nodeId, bool la
     bool tupScan = (scan_flags & NdbScanOperation::SF_TupScan);
     bool rangeScan= false;
 
+    bool   isPruned;
+    Uint32 hashValue;
+    const int error = rootDef.checkPrunable(m_keyInfo, isPruned, hashValue);
+    if (unlikely(error != 0))
+      return error;
+
     /* Handle IndexScan specifics */
     if ( (int) rootTable->m_indexType ==
          (int) NdbDictionary::Index::OrderedIndex )
@@ -914,11 +917,11 @@ NdbQueryImpl::doSend(int nodeId, bool la
 //  m_keyInfo = (scan_flags & NdbScanOperation::SF_KeyInfo) ? 1 : 0;
 
     // If scan is pruned, use optional 'distributionKey' to hold hashvalue
-    if (m_isPruned)
+    if (isPruned)
     {
-//    printf("Build pruned SCANREQ, w/ hashValue:%d\n", m_hashValue);
+//    printf("Build pruned SCANREQ, w/ hashValue:%d\n", hashValue);
       ScanTabReq::setDistributionKeyFlag(reqInfo, 1);
-      scanTabReq->distributionKey= m_hashValue;
+      scanTabReq->distributionKey= hashValue;
       m_signal->setLength(ScanTabReq::StaticLength + 1);
     } else {
       m_signal->setLength(ScanTabReq::StaticLength);
@@ -1562,7 +1565,7 @@ NdbQueryOperationImpl::UserProjection::s
 
 int NdbQueryOperationImpl::serializeParams(const constVoidPtr paramValues[])
 {
-  if (paramValues == NULL)
+  if (unlikely(paramValues == NULL))
   {
     return QRY_NEED_PARAMETER;
   }
@@ -1572,7 +1575,7 @@ int NdbQueryOperationImpl::serializePara
   {
     const NdbParamOperandImpl& paramDef = def.getParameter(i);
     const constVoidPtr paramValue = paramValues[paramDef.getParamIx()];
-    if (paramValue == NULL)  // FIXME: May also indicate a NULL value....
+    if (unlikely(paramValue == NULL))  // FIXME: May also indicate a NULL value....
     {
       return QRY_NEED_PARAMETER;
     }
@@ -1583,7 +1586,7 @@ int NdbQueryOperationImpl::serializePara
      *  the actuall value. Allocation is in Uint32 units with unused bytes
      *  zero padded.
      **/
-    Uint32 len = paramDef.getColumn()->getSizeInBytes();
+    Uint32 len = paramDef.getSizeInBytes(paramValue);
     m_params.append(len);          // paramValue length in #bytes
     m_params.append(paramValue,len);
 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp	2009-10-01 12:36:09 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp	2009-10-02 06:40:46 +0000
@@ -223,10 +223,6 @@ private:
    */
   StreamStack m_fullStreams;
 
-  /** Prunable property, and optional hashValue, valid for scans, */
-  bool m_isPruned;
-  Uint32 m_hashValue;
-
   /**
    * Signal building section:
    */

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2009-09-28 08:12:13 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2009-10-02 06:40:46 +0000
@@ -734,6 +734,10 @@ ErrorBundle ErrorCodes[] = {
     "Too many 'key' or 'bound' values was specified" },
   { QRY_OPERAND_HAS_WRONG_TYPE, DMEC, AE, 
     "Incompatible datatype specified in operand argument" },
+  { QRY_CHAR_OPERAND_TRUNCATED, DMEC, AE, 
+    "Character operand was right truncated" },
+  { QRY_NUM_OPERAND_RANGE, DMEC, AE, 
+    "Numeric operand out of range" },
   { QRY_UNKONWN_PARENT, DMEC, AE, 
     "Unknown 'parent' specified in linkedValue" },
   { QRY_UNKNOWN_COLUMN, DMEC, AE, 


Attachment: [text/bzr-bundle] bzr/jan.wedvik@sun.com-20091002064046-ftgwctf2c6ftnb2j.bundle
Thread
bzr commit into mysql-5.1-telco-7.0-spj branch (jan.wedvik:2987) Jan Wedvik2 Oct