Below is the list of changes that have just been committed into a local
5.1 repository of pekka. When pekka 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.2169 06/05/21 21:58:00 pekka@stripped +3 -0
Merge pnousiainen@stripped:/home/bk/mysql-5.0
into mysql.com:/space/pekka/ndb/version/my51
storage/ndb/src/ndbapi/NdbOperationSearch.cpp
1.31 06/05/21 21:57:39 pekka@stripped +0 -14
use local
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
1.59 06/05/21 21:57:30 pekka@stripped +0 -25
use local
storage/ndb/src/ndbapi/NdbOperationSearch.cpp
1.24.1.2 06/05/21 21:55:35 pekka@stripped +0 -0
Merge rename: ndb/src/ndbapi/NdbOperationSearch.cpp -> storage/ndb/src/ndbapi/NdbOperationSearch.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
1.30.4.2 06/05/21 21:55:35 pekka@stripped +0 -0
Merge rename: ndb/src/ndbapi/NdbDictionaryImpl.hpp -> storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
mysql-test/r/ndb_blob.result
1.19 06/05/21 21:55:35 pekka@stripped +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: pekka
# Host: orca.ndb.mysql.com
# Root: /space/pekka/ndb/version/my51/RESYNC
--- 1.30.4.1/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2006-05-21 11:03:25 +02:00
+++ 1.59/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2006-05-21 21:57:30 +02:00
@@ -30,15 +30,27 @@
#include "NdbWaiter.hpp"
#include "DictCache.hpp"
+bool
+is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
+bool
+is_ndb_blob_table(const class NdbTableImpl* t);
+
+extern int ndb_dictionary_is_mysqld;
+#define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
+
class NdbDictObjectImpl {
public:
+ int m_id;
Uint32 m_version;
+ NdbDictionary::Object::Type m_type;
NdbDictionary::Object::Status m_status;
bool change();
protected:
- NdbDictObjectImpl() :
+ NdbDictObjectImpl(NdbDictionary::Object::Type type) :
+ m_type(type),
m_status(NdbDictionary::Object::New) {
+ m_id = -1;
}
};
@@ -59,10 +71,15 @@
int m_precision;
int m_scale;
int m_length;
+ int m_column_no;
CHARSET_INFO * m_cs; // not const in MySQL
bool m_pk;
- bool m_distributionKey;
+ /*
+ * Since "none" is "all" we distinguish between
+ * 1-set by us, 2-set by user
+ */
+ Uint32 m_distributionKey;
bool m_nullable;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
@@ -73,7 +90,13 @@
* Internal types and sizes, and aggregates
*/
Uint32 m_attrSize; // element size (size when arraySize==1)
- Uint32 m_arraySize; // length or length+2 for Var* types
+ Uint32 m_arraySize; // length or maxlength+1/2 for Var* types
+ Uint32 m_arrayType; // NDB_ARRAYTYPE_FIXED or _VAR
+ Uint32 m_storageType; // NDB_STORAGETYPE_MEMORY or _DISK
+ /*
+ * NdbTableImpl: if m_pk, 0-based index of key in m_attrId order
+ * NdbIndexImpl: m_column_no of primary table column
+ */
Uint32 m_keyInfoPos;
// TODO: use bits in attr desc 2
bool getInterpretableType() const ;
@@ -90,10 +113,9 @@
static const NdbColumnImpl & getImpl(const NdbDictionary::Column & t);
NdbDictionary::Column * m_facade;
- static NdbDictionary::Column * create_psuedo(const char *);
+ static NdbDictionary::Column * create_pseudo(const char *);
// Get total length in bytes, used by NdbOperation
- // backported from 5.1
bool get_var_length(const void* value, Uint32& len) const;
};
@@ -106,13 +128,43 @@
void init();
void setName(const char * name);
const char * getName() const;
+ void setFragmentCount(Uint32 count);
+ Uint32 getFragmentCount() const;
+ void setFrm(const void* data, Uint32 len);
+ const void * getFrmData() const;
+ Uint32 getFrmLength() const;
+ void setFragmentData(const void* data, Uint32 len);
+ const void * getFragmentData() const;
+ Uint32 getFragmentDataLen() const;
+ void setTablespaceNames(const void* data, Uint32 len);
+ Uint32 getTablespaceNamesLen() const;
+ const void * getTablespaceNames() const;
+ void setTablespaceData(const void* data, Uint32 len);
+ const void * getTablespaceData() const;
+ Uint32 getTablespaceDataLen() const;
+ void setRangeListData(const void* data, Uint32 len);
+ const void * getRangeListData() const;
+ Uint32 getRangeListDataLen() const;
+
+ const char * getMysqlName() const;
+ void updateMysqlName();
Uint32 m_changeMask;
- Uint32 m_tableId;
+ Uint32 m_primaryTableId;
BaseString m_internalName;
BaseString m_externalName;
+ BaseString m_mysqlName;
BaseString m_newExternalName; // Used for alter table
UtilBuffer m_frm;
+ UtilBuffer m_newFrm; // Used for alter table
+ UtilBuffer m_ts_name; //Tablespace Names
+ UtilBuffer m_new_ts_name; //Tablespace Names
+ UtilBuffer m_ts; //TablespaceData
+ UtilBuffer m_new_ts; //TablespaceData
+ UtilBuffer m_fd; //FragmentData
+ UtilBuffer m_new_fd; //FragmentData
+ UtilBuffer m_range; //Range Or List Array
+ UtilBuffer m_new_range; //Range Or List Array
NdbDictionary::Object::FragmentType m_fragmentType;
/**
@@ -121,6 +173,7 @@
Uint32 m_columnHashMask;
Vector<Uint32> m_columnHash;
Vector<NdbColumnImpl *> m_columns;
+ void computeAggregates();
void buildColumnHash();
/**
@@ -130,14 +183,18 @@
Uint32 m_hashpointerValue;
Vector<Uint16> m_fragments;
+ Uint64 m_max_rows;
+ Uint32 m_default_no_part_flag;
+ bool m_linear_flag;
bool m_logging;
+ bool m_row_gci;
+ bool m_row_checksum;
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
Uint16 m_keyLenInWords;
Uint16 m_fragmentCount;
- NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index;
NdbColumnImpl * getColumn(unsigned attrId);
NdbColumnImpl * getColumn(const char * name);
@@ -148,12 +205,13 @@
* Index only stuff
*/
BaseString m_primaryTable;
- NdbDictionary::Index::Type m_indexType;
+ NdbDictionary::Object::Type m_indexType;
/**
* Aggregates
*/
Uint8 m_noOfKeys;
+ // if all pk = dk then this is zero!
Uint8 m_noOfDistributionKeys;
Uint8 m_noOfBlobs;
@@ -173,6 +231,13 @@
* Return count
*/
Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
+
+ /**
+ * Disk stuff
+ */
+ BaseString m_tablespace_name;
+ Uint32 m_tablespace_id;
+ Uint32 m_tablespace_version;
};
class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
@@ -188,13 +253,13 @@
const char * getTable() const;
const NdbTableImpl * getIndexTable() const;
- Uint32 m_indexId;
BaseString m_internalName;
BaseString m_externalName;
BaseString m_tableName;
+ Uint32 m_table_id;
+ Uint32 m_table_version;
Vector<NdbColumnImpl *> m_columns;
Vector<int> m_key_ids;
- NdbDictionary::Index::Type m_type;
bool m_logging;
@@ -206,6 +271,13 @@
};
class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl {
+ friend class NdbDictInterface;
+ friend class NdbDictionaryImpl;
+ friend class NdbEventOperation;
+ friend class NdbEventOperationImpl;
+ friend class NdbEventBuffer;
+ friend class EventBufData_hash;
+ friend class NdbBlob;
public:
NdbEventImpl();
NdbEventImpl(NdbDictionary::Event &);
@@ -215,13 +287,17 @@
void setName(const char * name);
const char * getName() const;
void setTable(const NdbDictionary::Table& table);
+ const NdbDictionary::Table * getTable() const;
void setTable(const char * table);
const char * getTableName() const;
void addTableEvent(const NdbDictionary::Event::TableEvent t);
+ bool getTableEvent(const NdbDictionary::Event::TableEvent t) const;
void setDurability(NdbDictionary::Event::EventDurability d);
NdbDictionary::Event::EventDurability getDurability() const;
- void addEventColumn(const NdbColumnImpl &c);
+ void setReport(NdbDictionary::Event::EventReport r);
+ NdbDictionary::Event::EventReport getReport() const;
int getNoOfEventColumns() const;
+ const NdbDictionary::Column * getEventColumn(unsigned no) const;
void print() {
ndbout_c("NdbEventImpl: id=%d, key=%d",
@@ -231,28 +307,109 @@
Uint32 m_eventId;
Uint32 m_eventKey;
- Uint32 m_tableId;
AttributeMask m_attrListBitmask;
- //BaseString m_internalName;
- BaseString m_externalName;
+ Uint32 m_table_id;
+ Uint32 m_table_version;
+ BaseString m_name;
Uint32 mi_type;
NdbDictionary::Event::EventDurability m_dur;
+ NdbDictionary::Event::EventReport m_rep;
+ bool m_mergeEvents;
-
- NdbTableImpl *m_tableImpl;
BaseString m_tableName;
Vector<NdbColumnImpl *> m_columns;
Vector<unsigned> m_attrIds;
- int m_bufferId;
-
- NdbEventOperation *eventOp;
-
static NdbEventImpl & getImpl(NdbDictionary::Event & t);
static NdbEventImpl & getImpl(const NdbDictionary::Event & t);
NdbDictionary::Event * m_facade;
+private:
+ NdbTableImpl *m_tableImpl;
+ void setTable(NdbTableImpl *tableImpl);
+};
+
+struct NdbFilegroupImpl : public NdbDictObjectImpl {
+ NdbFilegroupImpl(NdbDictionary::Object::Type t);
+
+ BaseString m_name;
+ NdbDictionary::AutoGrowSpecification m_grow_spec;
+
+ union {
+ Uint32 m_extent_size;
+ Uint32 m_undo_buffer_size;
+ };
+
+ BaseString m_logfile_group_name;
+ Uint32 m_logfile_group_id;
+ Uint32 m_logfile_group_version;
+ Uint64 m_undo_free_words;
+};
+
+class NdbTablespaceImpl : public NdbDictionary::Tablespace,
+ public NdbFilegroupImpl {
+public:
+ NdbTablespaceImpl();
+ NdbTablespaceImpl(NdbDictionary::Tablespace &);
+ ~NdbTablespaceImpl();
+
+ void assign(const NdbTablespaceImpl&);
+
+ static NdbTablespaceImpl & getImpl(NdbDictionary::Tablespace & t);
+ static const NdbTablespaceImpl & getImpl(const NdbDictionary::Tablespace &);
+ NdbDictionary::Tablespace * m_facade;
+};
+
+class NdbLogfileGroupImpl : public NdbDictionary::LogfileGroup,
+ public NdbFilegroupImpl {
+public:
+ NdbLogfileGroupImpl();
+ NdbLogfileGroupImpl(NdbDictionary::LogfileGroup &);
+ ~NdbLogfileGroupImpl();
+
+ void assign(const NdbLogfileGroupImpl&);
+
+ static NdbLogfileGroupImpl & getImpl(NdbDictionary::LogfileGroup & t);
+ static const NdbLogfileGroupImpl& getImpl(const
+ NdbDictionary::LogfileGroup&);
+ NdbDictionary::LogfileGroup * m_facade;
};
+struct NdbFileImpl : public NdbDictObjectImpl {
+ NdbFileImpl(NdbDictionary::Object::Type t);
+
+ Uint64 m_size;
+ Uint32 m_free;
+ BaseString m_path;
+ BaseString m_filegroup_name;
+ Uint32 m_filegroup_id;
+ Uint32 m_filegroup_version;
+};
+
+class NdbDatafileImpl : public NdbDictionary::Datafile, public NdbFileImpl {
+public:
+ NdbDatafileImpl();
+ NdbDatafileImpl(NdbDictionary::Datafile &);
+ ~NdbDatafileImpl();
+
+ void assign(const NdbDatafileImpl&);
+
+ static NdbDatafileImpl & getImpl(NdbDictionary::Datafile & t);
+ static const NdbDatafileImpl & getImpl(const NdbDictionary::Datafile & t);
+ NdbDictionary::Datafile * m_facade;
+};
+
+class NdbUndofileImpl : public NdbDictionary::Undofile, public NdbFileImpl {
+public:
+ NdbUndofileImpl();
+ NdbUndofileImpl(NdbDictionary::Undofile &);
+ ~NdbUndofileImpl();
+
+ void assign(const NdbUndofileImpl&);
+
+ static NdbUndofileImpl & getImpl(NdbDictionary::Undofile & t);
+ static const NdbUndofileImpl & getImpl(const NdbDictionary::Undofile & t);
+ NdbDictionary::Undofile * m_facade;
+};
class NdbDictInterface {
public:
@@ -267,65 +424,65 @@
bool setTransporter(class TransporterFacade * tf);
// To abstract the stuff thats made in all create/drop/lists below
- int
- dictSignal(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLPTR,
- const int useMasterNodeId,
- const Uint32 RETRIES,
- const WaitSignalType wst,
- const int theWait,
- const int *errcodes,
- const int noerrcodes,
- const int temporaryMask = 0);
+ int dictSignal(NdbApiSignal* signal, LinearSectionPtr ptr[3], int secs,
+ int nodeId, // -1 any, 0 = master, >1 = specified
+ WaitSignalType wst,
+ int timeout, Uint32 RETRIES,
+ const int *errcodes = 0, int temporaryMask = 0);
int createOrAlterTable(class Ndb & ndb, NdbTableImpl &, bool alter);
int createTable(class Ndb & ndb, NdbTableImpl &);
- int createTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
int alterTable(class Ndb & ndb, NdbTableImpl &);
- int alterTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int createIndex(class Ndb & ndb,
- NdbIndexImpl &,
- const NdbTableImpl &);
- int createIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
- int createEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
-
int dropTable(const NdbTableImpl &);
- int dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
+ int createIndex(class Ndb & ndb, const NdbIndexImpl &, const NdbTableImpl &);
int dropIndex(const NdbIndexImpl &, const NdbTableImpl &);
- int dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
+
+ int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
int dropEvent(const NdbEventImpl &);
int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
- int executeSubscribeEvent(class Ndb & ndb, NdbEventImpl &);
- int executeSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int stopSubscribeEvent(class Ndb & ndb, NdbEventImpl &);
- int stopSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
+ int executeSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &);
+ int stopSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &);
int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames);
int listObjects(NdbApiSignal* signal);
-/* NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames); */
+ NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
NdbTableImpl * getTable(const BaseString& name, bool fullyQualifiedNames);
NdbTableImpl * getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames);
+ int forceGCPWait();
+
static int parseTableInfo(NdbTableImpl ** dst,
const Uint32 * data, Uint32 len,
- bool fullyQualifiedNames);
+ bool fullyQualifiedNames,
+ Uint32 version= 0xFFFFFFFF);
+
+ static int parseFileInfo(NdbFileImpl &dst,
+ const Uint32 * data, Uint32 len);
+
+ static int parseFilegroupInfo(NdbFilegroupImpl &dst,
+ const Uint32 * data, Uint32 len);
+
+ int create_file(const NdbFileImpl &, const NdbFilegroupImpl&, bool overwrite = false);
+ int drop_file(const NdbFileImpl &);
+ int create_filegroup(const NdbFilegroupImpl &);
+ int drop_filegroup(const NdbFilegroupImpl &);
+
+ int get_filegroup(NdbFilegroupImpl&, NdbDictionary::Object::Type, Uint32);
+ int get_filegroup(NdbFilegroupImpl&,NdbDictionary::Object::Type,const char*);
+ int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, int);
+ int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, const char *);
static int create_index_obj_from_table(NdbIndexImpl ** dst,
NdbTableImpl* index_table,
const NdbTableImpl* primary_table);
+ const NdbError &getNdbError() const;
NdbError & m_error;
private:
Uint32 m_reference;
@@ -335,6 +492,7 @@
class TransporterFacade * m_transporter;
friend class Ndb;
+ friend class NdbDictionaryImpl;
static void execSignal(void* dictImpl,
class NdbApiSignal* signal,
struct LinearSectionPtr ptr[3]);
@@ -358,8 +516,6 @@
void execCREATE_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execSUB_START_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execSUB_START_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_TABLE_DATA(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_GCP_COMPLETE_REP(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execSUB_STOP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execSUB_STOP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execDROP_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
@@ -369,10 +525,40 @@
void execDROP_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execLIST_TABLES_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execCREATE_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execDROP_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execDROP_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execDROP_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execDROP_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execWAIT_GCP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execWAIT_GCP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
Uint32 m_fragmentId;
UtilBuffer m_buffer;
};
+class NdbDictionaryImpl;
+class GlobalCacheInitObject
+{
+public:
+ NdbDictionaryImpl *m_dict;
+ const BaseString &m_name;
+ GlobalCacheInitObject(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ m_dict(dict),
+ m_name(name)
+ {}
+ virtual ~GlobalCacheInitObject() {}
+ virtual int init(NdbTableImpl &tab) const = 0;
+};
+
class NdbDictionaryImpl : public NdbDictionary::Dictionary {
public:
NdbDictionaryImpl(Ndb &ndb);
@@ -383,8 +569,7 @@
bool setTransporter(class TransporterFacade * tf);
int createTable(NdbTableImpl &t);
- int createBlobTables(NdbTableImpl &);
- int addBlobTables(NdbTableImpl &);
+ int createBlobTables(NdbTableImpl& t);
int alterTable(NdbTableImpl &t);
int dropTable(const char * name);
int dropTable(NdbTableImpl &);
@@ -393,6 +578,7 @@
int removeCachedObject(NdbTableImpl &);
int createIndex(NdbIndexImpl &ix);
+ int createIndex(NdbIndexImpl &ix, NdbTableImpl & tab);
int dropIndex(const char * indexName,
const char * tableName);
int dropIndex(NdbIndexImpl &, const char * tableName);
@@ -400,22 +586,53 @@
NdbTableImpl * table);
int createEvent(NdbEventImpl &);
+ int createBlobEvents(NdbEventImpl &);
int dropEvent(const char * eventName);
+ int dropEvent(const NdbEventImpl &);
+ int dropBlobEvents(const NdbEventImpl &);
+
+ int executeSubscribeEvent(NdbEventOperationImpl &);
+ int stopSubscribeEvent(NdbEventOperationImpl &);
- int executeSubscribeEvent(NdbEventImpl &);
- int stopSubscribeEvent(NdbEventImpl &);
+ int forceGCPWait();
int listObjects(List& list, NdbDictionary::Object::Type type);
int listIndexes(List& list, Uint32 indexId);
+ NdbTableImpl * getTableGlobal(const char * tableName);
+ NdbIndexImpl * getIndexGlobal(const char * indexName,
+ NdbTableImpl &ndbtab);
+ int alterTableGlobal(NdbTableImpl &orig_impl, NdbTableImpl &impl);
+ int dropTableGlobal(NdbTableImpl &);
+ int dropIndexGlobal(NdbIndexImpl & impl);
+ int releaseTableGlobal(NdbTableImpl & impl, int invalidate);
+ int releaseIndexGlobal(NdbIndexImpl & impl, int invalidate);
+
NdbTableImpl * getTable(const char * tableName, void **data= 0);
- Ndb_local_table_info* get_local_table_info(
- const BaseString& internalTableName, bool do_add_blob_tables);
+ NdbTableImpl * getBlobTable(const NdbTableImpl&, uint col_no);
+ NdbTableImpl * getBlobTable(uint tab_id, uint col_no);
+ void putTable(NdbTableImpl *impl);
+ int getBlobTables(NdbTableImpl &);
+ Ndb_local_table_info*
+ get_local_table_info(const BaseString& internalTableName);
NdbIndexImpl * getIndex(const char * indexName,
const char * tableName);
- NdbEventImpl * getEvent(const char * eventName);
+ NdbIndexImpl * getIndex(const char * indexName, const NdbTableImpl& prim);
+ NdbEventImpl * getEvent(const char * eventName, NdbTableImpl* = NULL);
+ NdbEventImpl * getBlobEvent(const NdbEventImpl& ev, uint col_no);
NdbEventImpl * getEventImpl(const char * internalName);
-
+
+ int createDatafile(const NdbDatafileImpl &, bool force = false);
+ int dropDatafile(const NdbDatafileImpl &);
+ int createUndofile(const NdbUndofileImpl &, bool force = false);
+ int dropUndofile(const NdbUndofileImpl &);
+
+ int createTablespace(const NdbTablespaceImpl &);
+ int dropTablespace(const NdbTablespaceImpl &);
+
+ int createLogfileGroup(const NdbLogfileGroupImpl &);
+ int dropLogfileGroup(const NdbLogfileGroupImpl &);
+
const NdbError & getNdbError() const;
NdbError m_error;
Uint32 m_local_table_data_size;
@@ -429,10 +646,15 @@
NdbDictInterface m_receiver;
Ndb & m_ndb;
-private:
+
+ NdbIndexImpl* getIndexImpl(const char * externalName,
+ const BaseString& internalName,
+ NdbTableImpl &tab,
+ NdbTableImpl &prim);
NdbIndexImpl * getIndexImpl(const char * name,
const BaseString& internalName);
- Ndb_local_table_info * fetchGlobalTableImpl(const BaseString& internalName);
+private:
+ NdbTableImpl * fetchGlobalTableImplRef(const GlobalCacheInitObject &obj);
};
inline
@@ -498,13 +720,11 @@
NdbColumnImpl::get_var_length(const void* value, Uint32& len) const
{
Uint32 max_len = m_attrSize * m_arraySize;
- switch (m_type) {
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Varbinary:
+ switch (m_arrayType) {
+ case NDB_ARRAYTYPE_SHORT_VAR:
len = 1 + *((Uint8*)value);
break;
- case NdbDictionary::Column::Longvarchar:
- case NdbDictionary::Column::Longvarbinary:
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
len = 2 + uint2korr((char*)value);
break;
default:
@@ -536,6 +756,13 @@
}
inline
+const char *
+NdbTableImpl::getMysqlName() const
+{
+ return m_mysqlName.c_str();
+}
+
+inline
Uint32
Hash( const char* str ){
Uint32 h = 0;
@@ -660,72 +887,270 @@
* Inline:d getters
*/
+class InitTable : public GlobalCacheInitObject
+{
+public:
+ InitTable(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ GlobalCacheInitObject(dict, name)
+ {}
+ int init(NdbTableImpl &tab) const
+ {
+ return m_dict->getBlobTables(tab);
+ }
+};
+
+inline
+NdbTableImpl *
+NdbDictionaryImpl::getTableGlobal(const char * table_name)
+{
+ const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
+ return fetchGlobalTableImplRef(InitTable(this, internal_tabname));
+}
+
inline
NdbTableImpl *
NdbDictionaryImpl::getTable(const char * table_name, void **data)
{
+ DBUG_ENTER("NdbDictionaryImpl::getTable");
+ DBUG_PRINT("enter", ("table: %s", table_name));
+
+ if (unlikely(strchr(table_name, '$') != 0)) {
+ Uint32 tab_id, col_no;
+ if (is_ndb_blob_table(table_name, &tab_id, &col_no)) {
+ NdbTableImpl* t = getBlobTable(tab_id, col_no);
+ DBUG_RETURN(t);
+ }
+ }
+
const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
Ndb_local_table_info *info=
- get_local_table_info(internal_tabname, true);
+ get_local_table_info(internal_tabname);
if (info == 0)
- return 0;
-
+ DBUG_RETURN(0);
if (data)
*data= info->m_local_data;
-
- return info->m_table_impl;
+ DBUG_RETURN(info->m_table_impl);
}
inline
Ndb_local_table_info *
-NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName,
- bool do_add_blob_tables)
+NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName)
{
+ DBUG_ENTER("NdbDictionaryImpl::get_local_table_info");
+ DBUG_PRINT("enter", ("table: %s", internalTableName.c_str()));
+
Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
- if (info == 0) {
- info= fetchGlobalTableImpl(internalTableName);
- if (info == 0) {
- return 0;
+ if (info == 0)
+ {
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitTable(this, internalTableName));
+ if (tab)
+ {
+ info= Ndb_local_table_info::create(tab, m_local_table_data_size);
+ if (info)
+ {
+ m_localHash.put(internalTableName.c_str(), info);
+ m_ndb.theFirstTupleId[tab->getTableId()] = ~0;
+ m_ndb.theLastTupleId[tab->getTableId()] = ~0;
+ }
}
}
- if (do_add_blob_tables && info->m_table_impl->m_noOfBlobs)
- addBlobTables(*(info->m_table_impl));
-
- return info; // autoincrement already initialized
+ DBUG_RETURN(info); // autoincrement already initialized
}
+class InitIndex : public GlobalCacheInitObject
+{
+public:
+ const char *m_index_name;
+ const NdbTableImpl &m_prim;
+
+ InitIndex(const BaseString &internal_indexname,
+ const char *index_name,
+ const NdbTableImpl &prim) :
+ GlobalCacheInitObject(0, internal_indexname),
+ m_index_name(index_name),
+ m_prim(prim)
+ {}
+
+ int init(NdbTableImpl &tab) const {
+ DBUG_ENTER("InitIndex::init");
+ DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
+ /**
+ * Create index impl
+ */
+ NdbIndexImpl* idx;
+ if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &m_prim) == 0)
+ {
+ idx->m_table = &tab;
+ idx->m_externalName.assign(m_index_name);
+ idx->m_internalName.assign(m_name);
+ tab.m_index = idx;
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(1);
+ }
+};
+
inline
NdbIndexImpl *
-NdbDictionaryImpl::getIndex(const char * index_name,
- const char * table_name)
+NdbDictionaryImpl::getIndexGlobal(const char * index_name,
+ NdbTableImpl &ndbtab)
{
- if (table_name || m_ndb.usingFullyQualifiedNames())
- {
- const BaseString internal_indexname(
- (table_name)
- ?
- m_ndb.internalize_index_name(getTable(table_name), index_name)
- :
- m_ndb.internalize_table_name(index_name)); // Index is also a table
+ DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
+ const BaseString
+ internal_indexname(m_ndb.internalize_index_name(&ndbtab, index_name));
+ int retry= 2;
- if (internal_indexname.length())
+ while (retry)
+ {
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitIndex(internal_indexname,
+ index_name, ndbtab));
+ if (tab)
{
- Ndb_local_table_info * info=
- get_local_table_info(internal_indexname, false);
- if (info)
+ // tab->m_index sould be set. otherwise tab == 0
+ NdbIndexImpl *idx= tab->m_index;
+ if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
+ idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
{
- NdbTableImpl * tab= info->m_table_impl;
- if (tab->m_index == 0)
- tab->m_index= getIndexImpl(index_name, internal_indexname);
- if (tab->m_index != 0)
- tab->m_index->m_table= tab;
- return tab->m_index;
+ releaseIndexGlobal(*idx, 1);
+ retry--;
+ continue;
}
+ DBUG_RETURN(idx);
}
+ break;
}
+ m_error.code= 4243;
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseTableGlobal(NdbTableImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseTableGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(&impl, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseIndexGlobal(NdbIndexImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseIndexGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(impl.m_table, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+inline
+NdbIndexImpl *
+NdbDictionaryImpl::getIndex(const char * index_name,
+ const char * table_name)
+{
+ if (table_name == 0)
+ {
+ assert(0);
+ m_error.code= 4243;
+ return 0;
+ }
+
+
+ NdbTableImpl* prim = getTable(table_name);
+ if (prim == 0)
+ {
+ m_error.code= 4243;
+ return 0;
+ }
+
+ return getIndex(index_name, *prim);
+}
+
+inline
+NdbIndexImpl *
+NdbDictionaryImpl::getIndex(const char* index_name,
+ const NdbTableImpl& prim)
+{
+
+ const BaseString
+ internal_indexname(m_ndb.internalize_index_name(&prim, index_name));
+
+ Ndb_local_table_info *info= m_localHash.get(internal_indexname.c_str());
+ NdbTableImpl *tab;
+ if (info == 0)
+ {
+ tab= fetchGlobalTableImplRef(InitIndex(internal_indexname,
+ index_name,
+ prim));
+ if (!tab)
+ goto err;
+
+ info= Ndb_local_table_info::create(tab, 0);
+ if (!info)
+ goto err;
+ m_localHash.put(internal_indexname.c_str(), info);
+ }
+ else
+ tab= info->m_table_impl;
+
+ return tab->m_index;
+
+err:
m_error.code= 4243;
return 0;
+}
+
+inline
+NdbTablespaceImpl &
+NdbTablespaceImpl::getImpl(NdbDictionary::Tablespace & t){
+ return t.m_impl;
+}
+
+inline
+const NdbTablespaceImpl &
+NdbTablespaceImpl::getImpl(const NdbDictionary::Tablespace & t){
+ return t.m_impl;
+}
+
+inline
+NdbLogfileGroupImpl &
+NdbLogfileGroupImpl::getImpl(NdbDictionary::LogfileGroup & t){
+ return t.m_impl;
+}
+
+inline
+const NdbLogfileGroupImpl &
+NdbLogfileGroupImpl::getImpl(const NdbDictionary::LogfileGroup & t){
+ return t.m_impl;
+}
+
+inline
+NdbDatafileImpl &
+NdbDatafileImpl::getImpl(NdbDictionary::Datafile & t){
+ return t.m_impl;
+}
+
+inline
+const NdbDatafileImpl &
+NdbDatafileImpl::getImpl(const NdbDictionary::Datafile & t){
+ return t.m_impl;
+}
+
+inline
+NdbUndofileImpl &
+NdbUndofileImpl::getImpl(NdbDictionary::Undofile & t){
+ return t.m_impl;
+}
+
+inline
+const NdbUndofileImpl &
+NdbUndofileImpl::getImpl(const NdbDictionary::Undofile & t){
+ return t.m_impl;
}
#endif
--- 1.24.1.1/ndb/src/ndbapi/NdbOperationSearch.cpp 2006-05-21 11:03:25 +02:00
+++ 1.31/storage/ndb/src/ndbapi/NdbOperationSearch.cpp 2006-05-21 21:57:39 +02:00
@@ -54,24 +54,16 @@
******************************************************************************/
int
NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
+ const char* aValuePassed)
{
DBUG_ENTER("NdbOperation::equal_impl");
- DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
- tAttrInfo->m_name.c_str(),
- theOperationType,
- aValuePassed, aVariableKeyLen));
- if (aValuePassed != NULL)
- DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen);
+ DBUG_PRINT("enter", ("col=%s op=%d val=%p",
+ tAttrInfo->m_name.c_str(), theOperationType,
+ aValuePassed));
- register Uint32 tAttrId;
-
Uint32 tData;
- Uint32 tKeyInfoPosition;
const char* aValue = aValuePassed;
Uint64 tempData[512];
- Uint64 tempData2[512];
if ((theStatus == OperationDefined) &&
(aValue != NULL) &&
@@ -84,10 +76,21 @@
* Finally check if all tuple key attributes have been defined. If
* this is true then set Operation state to tuple key defined.
*****************************************************************************/
- tAttrId = tAttrInfo->m_attrId;
- tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
- bool tDistrKey = tAttrInfo->m_distributionKey;
+ /*
+ * For each call theTupleKeyDefined stores 3 items:
+ *
+ * [0] = m_column_no (external column id)
+ * [1] = 1-based index of first word of accumulating keyinfo
+ * [2] = number of words of keyinfo
+ *
+ * This is used to re-order keyinfo if not in m_attrId order.
+ *
+ * Note: No point to "clean up" this code. The upcoming
+ * record-based ndb api makes it obsolete.
+ */
+
+ Uint32 tAttrId = tAttrInfo->m_column_no; // not m_attrId;
Uint32 i = 0;
if (tAttrInfo->m_pk) {
Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -125,25 +128,17 @@
* We have to retrieve the size of the attribute in words and bits.
*************************************************************************/
keyEntryFound:
- theTupleKeyDefined[i][0] = tAttrId;
- theTupleKeyDefined[i][1] = tKeyInfoPosition;
- theTupleKeyDefined[i][2] = true;
-
- OperationType tOpType = theOperationType;
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
-
- Uint32 real_len;
- if (! tAttrInfo->get_var_length(aValue, real_len)) {
+ Uint32 sizeInBytes;
+ if (! tAttrInfo->get_var_length(aValue, sizeInBytes)) {
setErrorCodeAbort(4209);
DBUG_RETURN(-1);
}
- // 5.0 fixed storage + NdbBlob uses full size => pad var* with nulls
- if (real_len < sizeInBytes && m_currentTable->m_noOfBlobs != 0) {
- memcpy(tempData2, aValue, real_len);
- memset((char*)tempData2 + real_len, 0, sizeInBytes - real_len);
- aValue = (char*)tempData2;
- }
+ Uint32 tKeyInfoPosition =
+ i == 0 ? 1 : theTupleKeyDefined[i-1][1] + theTupleKeyDefined[i-1][2];
+ theTupleKeyDefined[i][0] = tAttrId;
+ theTupleKeyDefined[i][1] = tKeyInfoPosition;
+ theTupleKeyDefined[i][2] = (sizeInBytes + 3) / 4;
{
/************************************************************************
@@ -152,6 +147,7 @@
* aValue. If it is not aligned then we start by copying the value to
* tempData and use this as aValue instead.
***********************************************************************/
+ const bool tDistrKey = tAttrInfo->m_distributionKey;
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
const int align = UintPtr(aValue) & 7;
@@ -165,18 +161,7 @@
}
Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
-
- if (true){ //tArraySize != 0) {
- Uint32 tTupKeyLen = theTupKeyLen;
-
- theTupKeyLen = tTupKeyLen + totalSizeInWords;
- if ((aVariableKeyLen == sizeInBytes) ||
- (aVariableKeyLen == 0)) {
- ;
- } else {
- goto equal_error3;
- }
- }
+ theTupKeyLen += totalSizeInWords;
#if 0
else {
/************************************************************************
@@ -205,26 +190,25 @@
* we also set the value in the stored part through putting the
* information in the ATTRINFO signals.
*************************************************************************/
+ OperationType tOpType = theOperationType;
if ((tOpType == InsertRequest) ||
(tOpType == WriteRequest)) {
Uint32 ahValue;
- const Uint32 sz = totalSizeInWords;
- // XXX
- if(m_accessTable == m_currentTable)
- {
- AttributeHeader::init(&ahValue, tAttrId, sz);
- }
- else
- {
- assert(m_accessTable->m_index);
- int attr_id_current_table =
+ if(m_accessTable == m_currentTable) {
+ AttributeHeader::init(&ahValue, tAttrInfo->m_attrId, sizeInBytes);
+ } else {
+ assert(tOpType == WriteRequest && m_accessTable->m_index);
+ // use attrId of primary table column
+ int column_no_current_table =
m_accessTable->m_index->m_columns[tAttrId]->m_keyInfoPos;
- AttributeHeader::init(&ahValue, attr_id_current_table, sz);
+ int attr_id_current_table =
+ m_currentTable->m_columns[column_no_current_table]->m_attrId;
+ AttributeHeader::init(&ahValue, attr_id_current_table, sizeInBytes);
}
insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValue, sz);
+ insertATTRINFOloop((Uint32*)aValue, totalSizeInWords);
}//if
/**************************************************************************
@@ -245,6 +229,19 @@
theErrorLine = tErrorLine;
if (tNoKeysDef == 0) {
+
+ // re-order keyinfo if not entered in order
+ if (m_accessTable->m_noOfKeys != 1) {
+ for (Uint32 i = 0; i < m_accessTable->m_noOfKeys; i++) {
+ Uint32 k = theTupleKeyDefined[i][0]; // column_no
+ if (m_accessTable->m_columns[k]->m_keyInfoPos != i) {
+ DBUG_PRINT("info", ("key disorder at %d", i));
+ reorderKEYINFO();
+ break;
+ }
+ }
+ }
+
if (tOpType == UpdateRequest) {
if (tInterpretInd == 1) {
theStatus = GetValue;
@@ -471,11 +468,44 @@
return 0;
}
+void
+NdbOperation::reorderKEYINFO()
+{
+ Uint32 data[4000];
+ Uint32 size = 4000;
+ getKeyFromTCREQ(data, size);
+ Uint32 pos = 1;
+ Uint32 k;
+ for (k = 0; k < m_accessTable->m_noOfKeys; k++) {
+ Uint32 i;
+ for (i = 0; i < m_accessTable->m_columns.size(); i++) {
+ NdbColumnImpl* col = m_accessTable->m_columns[i];
+ if (col->m_pk && col->m_keyInfoPos == k) {
+ Uint32 j;
+ for (j = 0; j < m_accessTable->m_noOfKeys; j++) {
+ if (theTupleKeyDefined[j][0] == i) {
+ Uint32 off = theTupleKeyDefined[j][1] - 1;
+ Uint32 len = theTupleKeyDefined[j][2];
+ assert(off < 4000 && off + len <= 4000);
+ int ret = insertKEYINFO((char*)&data[off], pos, len);
+ assert(ret == 0);
+ pos += len;
+ break;
+ }
+ }
+ assert(j < m_accessTable->m_columns.size());
+ break;
+ }
+ }
+ assert(i < m_accessTable->m_columns.size());
+ }
+}
+
int
-NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
+NdbOperation::getKeyFromTCREQ(Uint32* data, Uint32 & size)
{
- assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
- assert(m_accessTable->m_keyLenInWords == size);
+ assert(size >= theTupKeyLen && theTupKeyLen > 0);
+ size = theTupKeyLen;
unsigned pos = 0;
while (pos < 8 && pos < size) {
data[pos] = theKEYINFOptr[pos];
@@ -534,7 +564,20 @@
continue;
NdbColumnImpl* tAttrInfo = * cols;
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ Uint32 sizeInBytes;
+ switch(tAttrInfo->m_arrayType){
+ default:
+ case NDB_ARRAYTYPE_FIXED:
+ sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ break;
+ case NDB_ARRAYTYPE_SHORT_VAR:
+ sizeInBytes = 1 + *(char*)src;
+ break;
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
+ sizeInBytes = 2 + uint2korr((char*)src);
+ break;
+ }
+
Uint32 currLen = (sizeInBytes + 3) >> 2;
if (tAttrInfo->getDistributionKey())
{
@@ -597,10 +640,14 @@
{
theDistributionKey = value;
theDistrKeyIndicator_ = 1;
+ DBUG_PRINT("info", ("NdbOperation::setPartitionId: %u",
+ theDistributionKey));
}
Uint32
NdbOperation::getPartitionId() const
{
+ DBUG_PRINT("info", ("NdbOperation::getPartitionId: %u ind=%d",
+ theDistributionKey, theDistrKeyIndicator_));
return theDistributionKey;
}
--- 1.18/mysql-test/r/ndb_blob.result 2006-05-04 14:34:26 +02:00
+++ 1.19/mysql-test/r/ndb_blob.result 2006-05-21 21:55:35 +02:00
@@ -500,3 +500,69 @@
count(*)
0
drop table t1;
+create table t1 (
+a varchar(40) not null,
+b mediumint not null,
+t text,
+c varchar(2) not null,
+d bigint not null,
+primary key (a,b,c),
+key (c,a),
+unique key (d)
+) engine=ndb;
+insert into t1 (a,b,c,d,t) values ('a',1110,'a',1,@v1);
+insert into t1 (a,b,c,d,t) values ('b',1110,'a',2,@v2);
+insert into t1 (a,b,c,d,t) values ('a',1110,'b',3,@v3);
+insert into t1 (a,b,c,d,t) values ('b',1110,'b',4,@v4);
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='a';
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+select a,b,c,d,sha1(t) from t1 where a='a' and b=1110 and c='b';
+a b c d sha1(t)
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+update t1 set t=@v4 where a='b' and b=1110 and c='a';
+update t1 set t=@v2 where a='b' and b=1110 and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 NULL
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+update t1 set t=@v2 where d=2;
+update t1 set t=@v4 where d=4;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+update t1 set t=@v4 where a='b' and c='a';
+update t1 set t=@v2 where a='b' and c='b';
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 NULL
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+update t1 set t=@v2 where b+d=1112;
+update t1 set t=@v4 where b+d=1114;
+select a,b,c,d,sha1(t) from t1 order by c,a;
+a b c d sha1(t)
+a 1110 a 1 558a30713786aa72f66abc1e6a521d55aacdeeb5
+b 1110 a 2 b238654911689bfb626a3ef9dba4a1ca074e6a5e
+a 1110 b 3 2b6515f29c20b8e9e17cc597527e516c0de8d612
+b 1110 b 4 NULL
+delete from t1 where a='a' and b=1110 and c='a';
+delete from t1 where a='b' and c='a';
+delete from t1 where d=3;
+delete from t1 where b+d=1114;
+select count(*) from t1;
+count(*)
+0
+drop table t1;
| Thread |
|---|
| • bk commit into 5.1 tree (pekka:1.2169) | pekka | 21 May |