Bug #22526 NdbOperation::equal() with too-long VARCHAR can cause tx->execute() to hang
Submitted: 20 Sep 2006 16:06 Modified: 26 Oct 2006 10:25
Reporter: John David Duncan Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Cluster: NDB API Severity:S2 (Serious)
Version:5.0.20 OS:MacOS (Mac OS X 10.4 PPC)
Assigned to: Hartmut Holzgraefe CPU Architecture:Any

[20 Sep 2006 16:06] John David Duncan
Description:
If you call NdbOperation::equal() for example with a 20-character VARCHAR, when the column is defined as VARCHAR(16), and then call tx->execute(), the execute call will hang for 6 minutes before returning an empty result.  I tested this on Mac OS X but I think it also effects other OSes.  

(This looks like a duplicate of some other issues, but those are reported as fixed before 5.0.20)

How to repeat:
Here is my basic test code for this (you will need to create a table and try a too-long varchar case)

#include <cstdlib>
#include <stdio.h>
#include <string.h>
#include "NdbApi.hpp"

int main() {
  Ndb *db;
  const NdbDictionary::Dictionary *dict;
  const NdbDictionary::Table *tab;
  const NdbDictionary::Index *idx;
  NdbTransaction *tx;
  NdbIndexOperation *op;
  NdbRecAttr *result_cols[4];
  char name[255];
  char *s;
  size_t l;
  char *connect_string = "";
  char *my_table = "table4";
  char *my_index = "name$unique";
  char my_search_param[255]; 

  my_search_param[0] = 5;
  strcpy( my_search_param + 1, "allen");
  printf("search on: '%s'\n", my_search_param);
  
  ndb_init();

  Ndb_cluster_connection conn(connect_string);
  conn.connect(4,5,1);
  conn.wait_until_ready(20, 0);
  
  db = new Ndb( & conn);

  db->init();

  db->setDatabaseName("ndb_test");
  dict = db->getDictionary();

  tab = dict->getTable(my_table);
  idx = dict->getIndex(my_index , my_table);
  
  tx = db->startTransaction();
  if(!tx) puts(db->getNdbError().message);
  
  op = tx->getNdbIndexOperation(idx);
  if(!op) puts(db->getNdbError().message);
  
  printf("table: %s \n", op->getTableName());

  op->readTuple(NdbOperation::LM_Read);
  op->equal("name", (const char *) my_search_param);
  
  result_cols[0] = op->getValue("i",0);
  result_cols[1] = op->getValue("j",0);
  result_cols[2] = op->getValue("name",0);
  if(! result_cols[2]) puts("op->getValue failed.\n");
  
  if(tx->execute( NdbTransaction::NoCommit, 
                  NdbTransaction::AbortOnError, 1))
    puts(db->getNdbError().message);
  
  l = (size_t) *(result_cols[2]->aRef());
  s = (result_cols[2]->aRef() + 1);
  printf("len: %lu, string: %s \n", l, s);
  strncpy(name, s, l);
  name[l] = 0;
  
  printf("RESULTS: %d %d %s \n", result_cols[0]->int32_value(),
         result_cols[1]->int32_value(), name);
  
  tx->close();
  
  delete db;
  return 0;
}
[20 Sep 2006 16:10] John David Duncan
And here's the table:

CREATE TABLE `table4` (
  `i` int(11) NOT NULL default '0',
  `j` int(11) NOT NULL default '0',
  `name` varchar(20) NOT NULL,
  PRIMARY KEY  USING HASH (`i`,`j`),
  UNIQUE KEY `name` USING HASH (`name`)
) ENGINE=ndbcluster
[26 Oct 2006 10:25] Hartmut Holzgraefe
can't repeat with current 5.0 source, as soon as the my_search_param length exceeds the table field length i'm getting a "op->getValue failed" error message immediately