List:Commits« Previous MessageNext Message »
From:msvensson Date:April 7 2006 10:13am
Subject:bk commit into 5.1 tree (msvensson:1.2302)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of msvensson. When msvensson 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
  1.2302 06/04/07 12:13:48 msvensson@neptunus.(none) +1 -0
  Merge neptunus.(none):/home/msvensson/mysql/bug13228/my51-bug13228
  into  neptunus.(none):/home/msvensson/mysql/mysql-5.1

  sql/ha_ndbcluster.cc
    1.291 06/04/07 12:13:42 msvensson@neptunus.(none) +0 -0
    Auto merged

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	msvensson
# Host:	neptunus.(none)
# Root:	/home/msvensson/mysql/mysql-5.1/RESYNC

--- 1.290/sql/ha_ndbcluster.cc	2006-04-07 11:18:39 +02:00
+++ 1.291/sql/ha_ndbcluster.cc	2006-04-07 12:13:42 +02:00
@@ -74,6 +74,8 @@
   DB_TYPE_NDBCLUSTER,
   ndbcluster_init,
   ~(uint)0, /* slot */
+  /* below are initialized by name in ndbcluster_init() */
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
 
 static handler *ndbcluster_create_handler(TABLE_SHARE *table)
@@ -101,8 +103,6 @@
 #define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0
 #define NDB_AUTO_INCREMENT_RETRIES 10
 
-#define NDB_INVALID_SCHEMA_OBJECT 241
-
 #define ERR_PRINT(err) \
   DBUG_PRINT("error", ("%d  message: %s", err.code, err.message))
 
@@ -1251,6 +1251,7 @@
   {
     char unique_index_name[FN_LEN];
     static const char* unique_suffix= "$unique";
+    m_has_unique_index= TRUE;
     strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
     DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name));
     const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname);
@@ -1277,7 +1278,7 @@
   KEY* key_info= tab->key_info;
   const char **key_name= tab->s->keynames.type_names;
   DBUG_ENTER("ha_ndbcluster::open_indexes");
-  
+  m_has_unique_index= FALSE;
   for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
   {
     if ((error= add_index_handle(thd, dict, key_info, *key_name, i)))
@@ -1579,6 +1580,25 @@
   DBUG_RETURN(0);
 }
 
+int ha_ndbcluster::set_index_key_from_record(NdbOperation *op, 
+                                             const byte *record, uint keyno)
+{
+  KEY* key_info= table->key_info + keyno;
+  KEY_PART_INFO* key_part= key_info->key_part;
+  KEY_PART_INFO* end= key_part+key_info->key_parts;
+  uint i;
+  DBUG_ENTER("set_index_key_from_record");
+                                                                                
+  for (i= 0; key_part != end; key_part++, i++)
+  {
+    Field* field= key_part->field;
+    if (set_ndb_key(op, field, m_index[keyno].unique_index_attrid_map[i],
+                    record+key_part->offset))
+      ERR_RETURN(m_active_trans->getNdbError());
+  }
+  DBUG_RETURN(0);
+}
+
 int 
 ha_ndbcluster::set_index_key(NdbOperation *op, 
                              const KEY *key_info, 
@@ -1787,46 +1807,154 @@
 }
 
 /*
-  Peek to check if a particular row already exists
+ * Check that all operations between first and last all
+ * have gotten the errcode
+ * If checking for HA_ERR_KEY_NOT_FOUND then update m_dupkey
+ * for all succeeding operations
+ */
+bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans,
+                                                   const NdbOperation *first,
+                                                   const NdbOperation *last,
+                                                   uint errcode)
+{
+  const NdbOperation *op= first;
+  DBUG_ENTER("ha_ndbcluster::check_all_operations_for_error");
+
+  while(op)
+  {
+    NdbError err= op->getNdbError();
+    if (err.status != NdbError::Success)
+    {
+      if (ndb_to_mysql_error(&err) != (int) errcode)
+        DBUG_RETURN(false);
+      if (op == last) break;
+      op= trans->getNextCompletedOperation(op);
+    }
+    else
+    {
+      // We found a duplicate
+      if (op->getType() == NdbOperation::UniqueIndexAccess)
+      {
+        if (errcode == HA_ERR_KEY_NOT_FOUND)
+        {
+          NdbIndexOperation *iop= (NdbIndexOperation *) op;
+          const NDBINDEX *index= iop->getIndex();
+          // Find the key_no of the index
+          for(uint i= 0; i<table->s->keys; i++)
+          {
+            if (m_index[i].unique_index == index)
+            {
+              m_dupkey= i;
+              break;
+            }
+          }
+        }
+      }
+      else
+      {
+        // Must have been primary key access
+        DBUG_ASSERT(op->getType() == NdbOperation::PrimaryKeyAccess);
+        if (errcode == HA_ERR_KEY_NOT_FOUND)
+          m_dupkey= table->s->primary_key;
+      }
+      DBUG_RETURN(false);      
+    }
+  }
+  DBUG_RETURN(true);
+}
+
+
+/*
+ * Peek to check if any rows already exist with conflicting
+ * primary key or unique index values
 */
 
-int ha_ndbcluster::peek_row(const byte *record)
+int ha_ndbcluster::peek_indexed_rows(const byte *record)
 {
   NdbTransaction *trans= m_active_trans;
   NdbOperation *op;
-  DBUG_ENTER("peek_row");
-
-  NdbOperation::LockMode lm=
-    (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
-  if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
-      op->readTuple(lm) != 0)
-    ERR_RETURN(trans->getNdbError());
-
+  const NdbOperation *first, *last;
+  uint i;
   int res;
-  if ((res= set_primary_key_from_record(op, record)))
-    ERR_RETURN(trans->getNdbError());
+  DBUG_ENTER("peek_indexed_rows");
 
-  if (m_use_partition_function)
+  NdbOperation::LockMode lm= NdbOperation::LM_Read;
+  first= NULL;
+  if (table->s->primary_key != MAX_KEY)
   {
-    uint32 part_id;
-    int error;
-    longlong func_value;
-    if ((error= m_part_info->get_partition_id(m_part_info, &part_id,
-                                              &func_value)))
+    /*
+     * Fetch any row with colliding primary key
+     */
+    if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
+        op->readTuple(lm) != 0)
+      ERR_RETURN(trans->getNdbError());
+    
+    first= op;
+    if ((res= set_primary_key_from_record(op, record)))
+      ERR_RETURN(trans->getNdbError());
+
+    if (m_use_partition_function)
     {
-      DBUG_RETURN(error);
+      uint32 part_id;
+      int error;
+      longlong func_value;
+      if ((error= m_part_info->get_partition_id(m_part_info, &part_id,
+                                                &func_value)))
+      {
+        DBUG_RETURN(error);
+      }
+      op->setPartitionId(part_id);
     }
-    op->setPartitionId(part_id);
   }
+  /*
+   * Fetch any rows with colliding unique indexes
+   */
+  KEY* key_info;
+  KEY_PART_INFO *key_part, *end;
+  for (i= 0, key_info= table->key_info; i < table->s->keys; i++, key_info++)
+  {
+    if (i != table->s->primary_key &&
+        key_info->flags & HA_NOSAME)
+    {
+      // A unique index is defined on table
+      NdbIndexOperation *iop;
+      NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
+      key_part= key_info->key_part;
+      end= key_part + key_info->key_parts;
+      if (!(iop= trans->getNdbIndexOperation(unique_index,
+                                             (const NDBTAB *) m_table)) ||
+          iop->readTuple(lm) != 0)
+        ERR_RETURN(trans->getNdbError());
 
-  if (execute_no_commit_ie(this,trans) != 0)
+      if (!first)
+        first= iop;
+      if ((res= set_index_key_from_record(iop, record, i)))
+        ERR_RETURN(trans->getNdbError());
+    }
+  }
+  last= trans->getLastDefinedOperation();
+  if (first)
+    res= execute_no_commit_ie(this,trans);
+  else
+  {
+    // Table has no keys
+    table->status= STATUS_NOT_FOUND;
+    DBUG_RETURN(HA_ERR_KEY_NOT_FOUND);
+  }
+  if (check_all_operations_for_error(trans, first, last, 
+                                     HA_ERR_KEY_NOT_FOUND))
   {
     table->status= STATUS_NOT_FOUND;
     DBUG_RETURN(ndb_err(trans));
   } 
+  else
+  {
+    DBUG_PRINT("info", ("m_dupkey %d", m_dupkey));
+  }
   DBUG_RETURN(0);
 }
 
+
 /*
   Read one record from NDB using unique secondary index
 */
@@ -2219,7 +2347,7 @@
     if (generate_scan_filter(m_cond_stack, op))
       DBUG_RETURN(ndb_err(trans));
 
-    if (res= define_read_attrs(buf, op))
+    if ((res= define_read_attrs(buf, op)))
     {
       DBUG_RETURN(res);
     }
@@ -2321,13 +2449,33 @@
   DBUG_ENTER("ha_ndbcluster::write_row");
 
   m_write_op= TRUE;
-  if (!m_use_write && m_ignore_dup_key && table_share->primary_key != MAX_KEY)
+  has_auto_increment= (table->next_number_field && record == table->record[0]);
+  if (table_share->primary_key != MAX_KEY)
+  {
+    /*
+     * Increase any auto_incremented primary key
+     */
+    if (has_auto_increment) 
+    {
+      THD *thd= table->in_use;
+
+      m_skip_auto_increment= FALSE;
+      update_auto_increment();
+      /* Ensure that handler is always called for auto_increment values */
+      thd->next_insert_id= 0;
+      m_skip_auto_increment= !auto_increment_column_changed;
+    }
+  }
+
+  /*
+   * If IGNORE the ignore constraint violations on primary and unique keys
+   */
+  if (!m_use_write && m_ignore_dup_key)
   {
-    int peek_res= peek_row(record);
+    int peek_res= peek_indexed_rows(record);
     
     if (!peek_res) 
     {
-      m_dupkey= table_share->primary_key;
       DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
     }
     if (peek_res != HA_ERR_KEY_NOT_FOUND)
@@ -2337,7 +2485,6 @@
   statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
     table->timestamp_field->set_time();
-  has_auto_increment= (table->next_number_field && record == table->record[0]);
 
   if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
     ERR_RETURN(trans->getNdbError());
@@ -2378,17 +2525,6 @@
   {
     int res;
 
-    if (has_auto_increment) 
-    {
-      THD *thd= table->in_use;
-
-      m_skip_auto_increment= FALSE;
-      update_auto_increment();
-      /* Ensure that handler is always called for auto_increment values */
-      thd->next_insert_id= 0;
-      m_skip_auto_increment= !auto_increment_column_changed;
-    }
-
     if ((res= set_primary_key_from_record(op, record)))
       return res;  
   }
@@ -3270,8 +3406,9 @@
           The partition id has been fetched from ndb
           and has been stored directly after the hidden key
         */
+        DBUG_DUMP("key+part", (char *)pos, key_length);
         key_length= ref_length - sizeof(m_part_id);
-        part_spec.start_part= part_spec.end_part= *(pos + key_length);
+        part_spec.start_part= part_spec.end_part= *(uint32 *)(pos + key_length);
       }
       else
       {
@@ -3286,6 +3423,7 @@
       }
       DBUG_PRINT("info", ("partition id %u", part_spec.start_part));
     }
+    DBUG_DUMP("key", (char *)pos, key_length);
     DBUG_RETURN(pk_read(pos, key_length, buf, part_spec.start_part));
   }
 }
@@ -3371,7 +3509,10 @@
 #endif
     memcpy(ref, m_ref, key_length);
   }
-  
+#ifndef DBUG_OFF
+  if (table_share->primary_key == MAX_KEY && m_use_partition_function) 
+    DBUG_DUMP("key+part", (char*)ref, key_length+sizeof(m_part_id));
+#endif
   DBUG_DUMP("ref", (char*)ref, key_length);
   DBUG_VOID_RETURN;
 }
@@ -3474,7 +3615,7 @@
     break;
   case HA_EXTRA_IGNORE_DUP_KEY:       /* Dup keys don't rollback everything*/
     DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY"));
-    if (current_thd->lex->sql_command == SQLCOM_REPLACE)
+    if (current_thd->lex->sql_command == SQLCOM_REPLACE && !m_has_unique_index)
     {
       DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
       m_use_write= TRUE;
@@ -5148,6 +5289,7 @@
   m_sorted(FALSE),
   m_use_write(FALSE),
   m_ignore_dup_key(FALSE),
+  m_has_unique_index(FALSE),
   m_primary_key_update(FALSE),
   m_ignore_no_key(FALSE),
   m_rows_to_insert((ha_rows) 1),
@@ -6934,7 +7076,6 @@
   hash_delete(&ndbcluster_open_tables, (byte*) *share);
   thr_lock_delete(&(*share)->lock);
   pthread_mutex_destroy(&(*share)->mutex);
-  free_root(&(*share)->mem_root, MYF(0));
 
 #ifdef HAVE_NDB_BINLOG
   if ((*share)->table)
@@ -6955,6 +7096,7 @@
 #endif
   }
 #endif
+  free_root(&(*share)->mem_root, MYF(0));
   my_free((gptr) *share, MYF(0));
   *share= 0;
 
@@ -7479,7 +7621,9 @@
     if ((* value).ptr)
     {
       DBUG_ASSERT(curr != 0);
-      (* value).rec= curr;
+      NdbValue* val= m_value + curr->getColumn()->getColumnNo();
+      DBUG_ASSERT(val->ptr);
+      val->rec= curr;
       curr= curr->next();
     }
   }
@@ -8068,7 +8212,12 @@
                      context->expecting_field_result(INT_RESULT))
                   : true)) &&
                 // Bit fields no yet supported in scan filter
-                type != MYSQL_TYPE_BIT)
+                type != MYSQL_TYPE_BIT &&
+                // No BLOB support in scan filter
+                type != MYSQL_TYPE_TINY_BLOB &&
+                type != MYSQL_TYPE_MEDIUM_BLOB &&
+                type != MYSQL_TYPE_LONG_BLOB &&
+                type != MYSQL_TYPE_BLOB)
             {
               const NDBCOL *col= tab->getColumn(field->field_name);
               DBUG_ASSERT(col);
@@ -9109,7 +9258,7 @@
   {
     NdbDictionary::Tablespace ts= ndbdict->getTablespace(id);
     ndberr= ndbdict->getNdbError();
-    if(ndberr.classification != ndberror_cl_none)
+    if(ndberr.classification != NdbError::NoError)
       goto err;
     return (my_strdup(ts.getName(), MYF(0)));
   }
@@ -9555,6 +9704,7 @@
   NDBDICT *dict = ndb->getDictionary();
   int error;
   const char * errmsg;
+  LINT_INIT(errmsg);
 
   switch (info->ts_cmd_type){
   case (CREATE_TABLESPACE):
Thread
bk commit into 5.1 tree (msvensson:1.2302)msvensson7 Apr