Below is the list of changes that have just been committed into a local
5.1 repository of knielsen. When knielsen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-11-07 09:46:01+01:00, knielsen@ymer.(none) +10 -0
WL#1190
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/include/kernel/signaldata/AlterTab.hpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +27 -3
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/include/kernel/signaldata/AlterTable.hpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +18 -1
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +223 -46
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +2 -0
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +57 -15
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +30 -0
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +599 -207
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +26 -10
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/kernel/vm/DLFifoList.hpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +2 -2
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp@stripped, 2006-11-07 09:45:59+01:00,
knielsen@ymer.(none) +37 -6
Implement NDB-API level ALTER TABLE ADD ATTRIBUTE.
# 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: knielsen
# Host: ymer.(none)
# Root: /usr/local/mysql/mysql-5.1-ndb-dynattr
--- 1.4/storage/ndb/include/kernel/signaldata/AlterTab.hpp 2006-11-07 09:46:08 +01:00
+++ 1.5/storage/ndb/include/kernel/signaldata/AlterTab.hpp 2006-11-07 09:46:08 +01:00
@@ -23,7 +23,7 @@
/**
* AlterTab
*
- * Implemenatation of AlterTable
+ * Implemetation of AlterTable
*/
class AlterTabReq {
/**
@@ -34,6 +34,7 @@ class AlterTabReq {
friend class Dbtc;
friend class Dblqh;
friend class Suma;
+ friend class Dbtup;
/**
* For printing
@@ -41,7 +42,7 @@ class AlterTabReq {
friend bool printALTER_TAB_REQ(FILE*, const Uint32*, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 9 );
+ STATIC_CONST( SignalLength = 12 );
enum RequestType {
AlterTablePrepare = 0, // Prepare alter table
@@ -60,7 +61,16 @@ private:
Uint32 gci;
Uint32 requestType;
+ /* Only used when sending to TUP. */
+ Uint32 noOfNewAttr;
+ Uint32 newNoOfCharsets;
+ Uint32 newNoOfKeyAttrs;
+
SECTION( DICT_TAB_INFO = 0 );
+ /*
+ When sent to DICT, the first section contains the new table definition.
+ When sent to TUP, the first section contains the new attributes.
+ */
};
struct AlterTabRef {
@@ -111,7 +121,7 @@ class AlterTabConf {
friend bool printALTER_TAB_CONF(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 7 );
+ STATIC_CONST( SignalLength = 8 );
private:
Uint32 senderRef;
@@ -121,6 +131,20 @@ private:
Uint32 tableVersion;
Uint32 gci;
Uint32 requestType;
+
+ /* Only used when sent from TUP. */
+ Uint32 clientData;
+};
+
+/*
+ This union can be used to safely refer to a signal data part
+ simultaneously as AlterTab{Req,Ref,Conf} without violating the
+ strict aliasing rule.
+*/
+union AlterTabAll {
+ AlterTabReq req;
+ AlterTabRef ref;
+ AlterTabConf conf;
};
#endif
--- 1.10/storage/ndb/include/kernel/signaldata/AlterTable.hpp 2006-11-07 09:46:08 +01:00
+++ 1.11/storage/ndb/include/kernel/signaldata/AlterTable.hpp 2006-11-07 09:46:08 +01:00
@@ -39,6 +39,7 @@ class AlterTableReq {
friend class NdbEventOperationImpl;
friend class NdbDictInterface;
friend class Dbdict;
+ friend class Dbtup;
friend class Suma;
/**
@@ -69,10 +70,11 @@ private:
r = Changed range or list array
t = Changed tablespace name array
s = Changed tablespace id array
+ a = Add attribute
1111111111222222222233
01234567890123456789012345678901
- nf------------------------------
+ nfdrtsa-------------------------
*/
#define NAME_SHIFT (0)
#define FRM_SHIFT (1)
@@ -80,6 +82,7 @@ private:
#define RANGE_LIST_SHIFT (3)
#define TS_NAME_SHIFT (4)
#define TS_SHIFT (5)
+#define ADD_ATTR_SHIFT (6)
/**
* Getters and setters
@@ -96,6 +99,8 @@ private:
static void setTsNameFlag(UintR & changeMask, Uint32 tsNameFlg);
static Uint8 getTsFlag(const UintR & changeMask);
static void setTsFlag(UintR & changeMask, Uint32 tsFlg);
+ static Uint8 getAddAttrFlag(const UintR & changeMask);
+ static void setAddAttrFlag(UintR & changeMask, Uint32 tsFlg);
};
inline
@@ -168,6 +173,18 @@ inline
void
AlterTableReq::setTsNameFlag(UintR & changeMask, Uint32 tsNameFlg){
changeMask |= (tsNameFlg << TS_NAME_SHIFT);
+}
+
+inline
+Uint8
+AlterTableReq::getAddAttrFlag(const UintR & changeMask){
+ return (Uint8)((changeMask >> ADD_ATTR_SHIFT) & 1);
+}
+
+inline
+void
+AlterTableReq::setAddAttrFlag(UintR & changeMask, Uint32 addAttrFlg){
+ changeMask |= (addAttrFlg << ADD_ATTR_SHIFT);
}
--- 1.105/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2006-11-07 09:46:08 +01:00
+++ 1.106/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2006-11-07 09:46:08 +01:00
@@ -4017,6 +4017,7 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
alterTabPtr.p->m_alterTableFailed = false;
alterTabPtr.p->m_coordinatorRef = reference();
+ alterTabPtr.p->m_tupAlterTabPtr= RNIL;
alterTabPtr.p->m_fragmentsPtrI = RNIL;
alterTabPtr.p->m_dihAddFragPtr = RNIL;
alterTabPtr.p->m_alterTableId = tablePtr.p->tableId;
@@ -4256,16 +4257,20 @@ Dbdict::execALTER_TAB_REQ(Signal * signa
alterTabPtr.p->m_senderRef = senderRef;
alterTabPtr.p->m_senderData = senderData;
alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
+ alterTabPtr.p->m_tupAlterTabPtr= RNIL;
alterTabPtr.p->m_fragmentsPtrI = RNIL;
alterTabPtr.p->m_dihAddFragPtr = RNIL;
newTablePtr = parseRecord.tablePtr;
newTablePtr.p->tableVersion = tableVersion;
+ ndbrequire(newTablePtr.p->noOfAttributes >= tablePtr.p->noOfAttributes);
}
else { // (req->senderRef == reference())
jam();
c_tableRecordPool.getPtr(newTablePtr, alterTabPtr.p->m_tablePtrI);
newTablePtr.p->tableVersion = tableVersion;
}
+ Uint32 oldNoOfAttributes= tablePtr.p->noOfAttributes;
+ alterTabPtr.p->m_new_cols= newTablePtr.p->noOfAttributes-oldNoOfAttributes;
if (handleAlterTab(req, alterTabPtr.p, tablePtr, newTablePtr) == -1) {
jam();
c_opCreateTable.release(alterTabPtr);
@@ -4273,69 +4278,96 @@ Dbdict::execALTER_TAB_REQ(Signal * signa
return;
}
releaseSections(signal);
+
// Propagate alter table to other local blocks
- AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- req->changeMask = changeMask;
+ // First to TUP, which is the only one that needs info about added attrs
+
+ /* Copy out descriptor and charset for any new attributes. */
+ Uint32 *attrData= &(signal->theData[0])+25;
+ Uint32 *p= attrData;
+ LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
+ tablePtr.p->m_attributes);
+ AttributeRecordPtr attrPtr;
+ list.first(attrPtr);
+ for(Uint32 i= 0; i<tablePtr.p->noOfAttributes; i++)
+ {
+ if (i >= oldNoOfAttributes)
+ {
+ *p++= attrPtr.p->attributeDescriptor;
+ *p++= attrPtr.p->extPrecision & ~0xFFFF;
+ }
+ list.next(attrPtr);
+ }
+
+ AlterTabReq *req= (AlterTabReq *)signal->getDataPtrSend();
+ req->senderRef= reference();
+ req->changeMask= changeMask;
+ req->senderData= senderData;
req->tableId = tableId;
req->tableVersion = tableVersion;
req->gci = gci;
req->requestType = requestType;
- sendSignal(DBLQH_REF, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
+ req->noOfNewAttr= alterTabPtr.p->m_new_cols;
+ req->newNoOfCharsets= newTablePtr.p->noOfCharsets;
+ req->newNoOfKeyAttrs= newTablePtr.p->noOfPrimkey;
+
+ if (req->noOfNewAttr>0)
+ {
+ ndbrequire(AlterTableReq::getAddAttrFlag(changeMask));
+ /* Send long signal with info for all attributes to TUP. */
+ LinearSectionPtr ptr[3];
+ ptr[0].p= attrData;
+ ptr[0].sz= 2*req->noOfNewAttr;
+ sendSignal(DBTUP_REF, GSN_ALTER_TAB_REQ, signal,
+ AlterTabReq::SignalLength, JBB, ptr, 1);
+ }
+ else
+ {
+ ndbrequire(!AlterTableReq::getAddAttrFlag(changeMask));
+ /* No linear section since no attributes to send. */
+ sendSignal(DBTUP_REF, GSN_ALTER_TAB_REQ, signal,
+ AlterTabReq::SignalLength, JBB);
+ }
return;
}
case(AlterTabReq::AlterTableCommit): {
jam();
- // Write schema for altered table to disk
+
SegmentedSectionPtr tabInfoPtr;
signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
- bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
-
signal->header.m_noOfSections = 0;
- // Update table record
- tablePtr.p->packedSize = tabInfoPtr.sz;
- tablePtr.p->tableVersion = tableVersion;
- tablePtr.p->gciTableCreated = gci;
-
- SchemaFile::TableEntry tabEntry;
- tabEntry.m_tableVersion = tableVersion;
- tabEntry.m_tableType = tablePtr.p->tableType;
- if (savetodisk)
- tabEntry.m_tableState = SchemaFile::ALTER_TABLE_COMMITTED;
- else
- tabEntry.m_tableState = SchemaFile::TEMPORARY_TABLE_COMMITTED;
- tabEntry.m_gcp = gci;
- tabEntry.m_info_words = tabInfoPtr.sz;
- memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
-
- Callback callback;
- callback.m_callbackData = senderData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::alterTab_writeSchemaConf);
-
- updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
- break;
+ /* Send alter table commit to TUP. */
+ AlterTabReq *req= (AlterTabReq *)signal->getDataPtrSend();
+ req->senderRef= reference();
+ req->changeMask= changeMask;
+ req->senderData= senderData;
+ req->clientData= alterTabPtr.p->m_tupAlterTabPtr;
+ req->tableId = tableId;
+ req->tableVersion = tableVersion;
+ req->gci = gci;
+ req->requestType = requestType;
+ sendSignal(DBTUP_REF, GSN_ALTER_TAB_REQ, signal,
+ AlterTabReq::SignalLength, JBB);
+ return;
+
}
case(AlterTabReq::AlterTableRevert): {
jam();
- // Revert failed alter table
- revertAlterTable(signal, changeMask, tableId, alterTabPtr.p);
- // Acknowledge the reverted alter table
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
- break;
+ /* Send alter table abort to TUP. */
+ AlterTabReq *req= (AlterTabReq *)signal->getDataPtrSend();
+ req->senderRef= reference();
+ req->changeMask= changeMask;
+ req->senderData= senderData;
+ req->clientData= alterTabPtr.p->m_tupAlterTabPtr;
+ req->tableId = tableId;
+ req->tableVersion = tableVersion;
+ req->gci = gci;
+ req->requestType = requestType;
+ sendSignal(DBTUP_REF, GSN_ALTER_TAB_REQ, signal,
+ AlterTabReq::SignalLength, JBB);
+ return;
}
default: ndbrequire(false);
}
@@ -4387,6 +4419,28 @@ void Dbdict::execALTER_TAB_REF(Signal *
(AlterTabReq::RequestType) ref->requestType;
CreateTableRecordPtr alterTabPtr;
ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
+
+ if(refToBlock(signal->getSendersBlockRef())==DBTUP)
+ {
+ /* Error from TUP causes abort of alter table. */
+ jam();
+
+ ref= (AlterTabRef*)signal->getDataPtrSend();
+ ref->senderData = senderData;
+ ref->senderRef = reference();
+ ref->errorCode = errorCode;
+ ref->errorLine = 0;
+ ref->errorKey = 0;
+ ref->errorStatus = 0;
+ sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TAB_REF, signal,
+ AlterTabRef::SignalLength, JBB);
+
+ c_blockState = BS_IDLE;
+
+ return;
+ }
+
+ /* Else it is coordinator receiving abort from local DICT alter table. */
Uint32 changeMask = alterTabPtr.p->m_changeMask;
SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
safeCounter.clearWaitingFor(refToNode(senderRef));
@@ -4477,6 +4531,24 @@ Dbdict::execALTER_TAB_CONF(Signal * sign
switch (requestType) {
case(AlterTabReq::AlterTablePrepare): {
switch(refToBlock(signal->getSendersBlockRef())) {
+ case DBTUP: {
+ jam();
+
+ /* Need to store TUP's operation record reference for commit/revert. */
+ alterTabPtr.p->m_tupAlterTabPtr= conf->clientData;
+
+ AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
+ req->senderRef = reference();
+ req->senderData = senderData;
+ req->changeMask = changeMask;
+ req->tableId = tableId;
+ req->tableVersion = tableVersion;
+ req->gci = gci;
+ req->requestType = requestType;
+ sendSignal(DBLQH_REF, GSN_ALTER_TAB_REQ, signal,
+ AlterTabReq::SignalLength, JBB);
+ return;
+ }
case DBLQH: {
jam();
AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
@@ -4598,7 +4670,66 @@ Dbdict::execALTER_TAB_CONF(Signal * sign
}
case(AlterTabReq::AlterTableRevert):
jam();
+ if(refToBlock(signal->getSendersBlockRef())==DBTUP)
+ {
+ jam();
+ // Revert failed alter table
+ revertAlterTable(signal, changeMask, tableId, alterTabPtr.p);
+ // Acknowledge the reverted alter table
+ AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ conf->changeMask = changeMask;
+ conf->tableId = tableId;
+ conf->tableVersion = tableVersion;
+ conf->gci = gci;
+ conf->requestType = requestType;
+ sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TAB_CONF, signal,
+ AlterTabConf::SignalLength, JBB);
+ return;
+ }
+ /* Else fall through to commit case... */
+
case(AlterTabReq::AlterTableCommit): {
+ jam();
+ if(refToBlock(signal->getSendersBlockRef())==DBTUP)
+ {
+ jam();
+ // TUP alter tab commit done. Write schema for altered table to disk
+ SegmentedSectionPtr tabInfoPtr;
+ getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
+ TableRecordPtr tablePtr;
+ c_tableRecordPool.getPtr(tablePtr, tableId, false);
+ ndbrequire(!tablePtr.isNull());
+
+ bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
+
+ // Update table record
+ tablePtr.p->packedSize = tabInfoPtr.sz;
+ tablePtr.p->tableVersion = tableVersion;
+ tablePtr.p->gciTableCreated = gci;
+
+ SchemaFile::TableEntry tabEntry;
+ tabEntry.m_tableVersion = tableVersion;
+ tabEntry.m_tableType = tablePtr.p->tableType;
+ if (savetodisk)
+ tabEntry.m_tableState = SchemaFile::ALTER_TABLE_COMMITTED;
+ else
+ tabEntry.m_tableState = SchemaFile::TEMPORARY_TABLE_COMMITTED;
+ tabEntry.m_gcp = gci;
+ tabEntry.m_info_words = tabInfoPtr.sz;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
+
+ Callback callback;
+ callback.m_callbackData = senderData;
+ callback.m_callbackFunction =
+ safe_cast(&Dbdict::alterTab_writeSchemaConf);
+
+ updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
+ return;
+ }
+
+ /* A confirm signal from local DICT nodes to coordinator DICT. */
SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
safeCounter.clearWaitingFor(refToNode(senderRef));
if (safeCounter.done()) {
@@ -4709,6 +4840,35 @@ int Dbdict::handleAlterTab(AlterTabReq *
ndbrequire(org.assign(tmp, src.size()));
}
+ if (AlterTableReq::getAddAttrFlag(changeMask))
+ {
+ /* Attribute(s) added. */
+ supportedAlteration= true;
+
+ /* Move the column definitions to the real table definitions. */
+ LocalDLFifoList<AttributeRecord> origlist(c_attributeRecordPool,
+ origTablePtr.p->m_attributes);
+ LocalDLFifoList<AttributeRecord> newlist(c_attributeRecordPool,
+ newTablePtr.p->m_attributes);
+
+ /* Move back to find the first column to move. */
+ AttributeRecordPtr p;
+ ndbrequire(alterTabPtrP->m_new_cols>0);
+ ndbrequire(newlist.last(p));
+ for (Uint32 i= 1; i<alterTabPtrP->m_new_cols; i++)
+ ndbrequire(newlist.prev(p));
+
+ /* Move columns. */
+ for (Uint32 i= 0; i<alterTabPtrP->m_new_cols; i++)
+ {
+ AttributeRecordPtr q= p;
+ newlist.next(q);
+ newlist.remove(p);
+ origlist.addLast(p);
+ }
+ origTablePtr.p->noOfAttributes+= alterTabPtrP->m_new_cols;
+ }
+
/*
TODO RONM: Lite ny kod för FragmentData och RangeOrListData
*/
@@ -4767,6 +4927,23 @@ void Dbdict::revertAlterTable(Signal * s
}
+ if (AlterTableReq::getAddAttrFlag(changeMask))
+ {
+ /* Attribute(s) added. */
+ supportedAlteration= true;
+
+ /* Release the extra columns, not to be used anyway. */
+ LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
+ tablePtr.p->m_attributes);
+
+ ndbrequire(alterTabPtrP->m_new_cols>0);
+ for (Uint32 i= 0; i<alterTabPtrP->m_new_cols; i++)
+ {
+ AttributeRecordPtr p;
+ ndbrequire(list.last(p));
+ list.release(p);
+ }
+ }
if (supportedAlteration)
{
--- 1.43/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2006-11-07 09:46:08 +01:00
+++ 1.44/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2006-11-07 09:46:08 +01:00
@@ -1155,9 +1155,11 @@ private:
// For alter table
Uint32 m_changeMask;
+ Uint32 m_new_cols;
bool m_alterTableFailed;
AlterTableRef m_alterTableRef;
Uint32 m_alterTableId;
+ Uint32 m_tupAlterTabPtr; // Connect ptr towards TUP
/* Previous table name (used for reverting failed table rename) */
char previousTableName[MAX_TAB_NAME_SIZE];
--- 1.53/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2006-11-07 09:46:08 +01:00
+++ 1.54/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2006-11-07 09:46:08 +01:00
@@ -28,6 +28,7 @@
#include <signaldata/DropTrig.hpp>
#include <signaldata/TrigAttrInfo.hpp>
#include <signaldata/BuildIndx.hpp>
+#include <signaldata/AlterTab.hpp>
#include <AttributeDescriptor.hpp>
#include "AttributeOffset.hpp"
#include "Undo_buffer.hpp"
@@ -188,6 +189,7 @@ inline const Uint32* ALIGN_WORD(const vo
#define ZINVALID_CHAR_FORMAT 744
#define ZROWID_ALLOCATED 899
+#define ZINVALID_ALTER_TAB 741
/* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
@@ -342,18 +344,27 @@ struct Fragoperrec {
Uint32 attributeCount;
Uint32 charsetIndex;
Uint32 m_null_bits[2];
- /* Number of NULL bits used in the dynamic bitmap. */
- /* ToDo: Should this be here, or in Tablerec ? */
- Uint32 m_dyn_null_bits[2];
- Uint32 m_fix_attributes_size[2]; // In words
- Uint32 m_var_attributes_size[2]; // In bytes
- Uint32 m_dyn_attributes_size[2]; // In bytes
BlockReference lqhBlockrefFrag;
bool inUse;
bool definingFragment;
};
typedef Ptr<Fragoperrec> FragoperrecPtr;
+ /* Operation record used during alter table. */
+ struct AlterTabOperation {
+ Uint32 nextAlterTabOp;
+ Uint32 newNoOfAttrs;
+ Uint32 noOfDynNullBits;
+ Uint32 noOfDynVar;
+ Uint32 noOfDynFix;
+ Uint32 tabDesOffset[7];
+ Uint32 desAllocSize;
+ Uint32 tableDescriptor;
+ Uint32 dynTabDesOffset[3];
+ Uint32 dynDesAllocSize;
+ Uint32 dynTableDescriptor;
+ };
+ typedef Ptr<AlterTabOperation> AlterTabOperationPtr;
typedef Tup_page Page;
typedef Ptr<Page> PagePtr;
@@ -894,18 +905,21 @@ ArrayPool<TupTriggerData> c_triggerPool;
Bitmask<MAXNROFATTRIBUTESINWORDS> blobAttributeMask;
/*
- Mask of variable-sized dynamic attributes.
- Total size of dynamic bitmap in worst-case is 16 bits/attribute, for
- CHAR(64).
+ Extra table descriptor for dynamic attributes, or RNIL if none.
+ The size of this depends on actual column definitions, so it is allocated
+ _after_ seeing all columns, hence must be separate from the readKeyArray
+ et al descriptor, which is allocated before seeing columns.
*/
- /* ToDo: Should probably be type Bitmask<...> ? */
- Uint32 dynVarSizeMask[(MAX_ATTRIBUTES_IN_TABLE+1)>>1];
+ Uint32 dynTabDescriptor;
+
+ /* Mask of variable-sized dynamic attributes. */
+ Uint32* dynVarSizeMask;
/*
Mask of fixed-sized dynamic attributes. There is one bit set for each
- 32-bit work occupied by fixed-size attributes, so fixed-size dynamic
+ 32-bit word occupied by fixed-size attributes, so fixed-size dynamic
attributes >32bit have multiple bits here.
*/
- Uint32 dynFixSizeMask[(MAX_ATTRIBUTES_IN_TABLE+1)>>1];
+ Uint32* dynFixSizeMask;
ReadFunction* readFunctionArray;
UpdateFunction* updateFunctionArray;
@@ -949,6 +963,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
Uint16 m_no_of_disk_attributes;
Uint16 noOfKeyAttr;
Uint16 noOfCharsets;
+ Uint16 m_dyn_null_bits;
bool need_expand() const {
return m_no_of_attributes > m_attributes[MM].m_no_of_fixsize;
@@ -2115,6 +2130,21 @@ private:
bool updateDiskBitsNotNULL(Uint32*, KeyReqStruct*, Uint32);
+ /* Alter table methods. */
+ void handleAlterTabPrepare(Signal *signal, const Tablerec *regTabPtr);
+ void sendAlterTabRef(Signal *signal, AlterTabReq *req, Uint32 errorCode);
+ void sendAlterTabConf(Signal *, AlterTabReq *, Uint32 clientData=RNIL);
+ void handleAlterTableCommit(Signal *signal,
+ AlterTabOperationPtr regAlterTabOpPtr,
+ Tablerec *regTabPtr);
+ void handleAlterTableAbort(Signal *signal,
+ AlterTabOperationPtr regAlterTabOpPtr,
+ Tablerec *regTabPtr);
+ void handleCharsetPos(Uint32 csNumber, CHARSET_INFO** charsetArray,
+ Uint32 noOfCharsets,
+ Uint32 & charsetIndex, Uint32 & attrDes2);
+ void computeTableMetaData(Tablerec *regTabPtr);
+
//------------------------------------------------------------------
//------------------------------------------------------------------
bool nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2);
@@ -2538,6 +2568,9 @@ private:
void setUpDescriptorReferences(Uint32 descriptorReference,
Tablerec* regTabPtr,
const Uint32* offset);
+ void setupDynDescriptorReferences(Uint32 dynDescr,
+ Tablerec* const regTabPtr,
+ const Uint32* offset);
void setUpKeyArray(Tablerec* regTabPtr);
bool addfragtotab(Tablerec* regTabPtr, Uint32 fragId, Uint32 fragIndex);
void deleteFragTab(Tablerec* regTabPtr, Uint32 fragId);
@@ -2551,6 +2584,7 @@ private:
void initializeDiskBufferSegmentRecord();
void initializeFragoperrec();
void initializeFragrecord();
+ void initializeAlterTabOperation();
void initializeHostBuffer();
void initializeLocalLogInfo();
void initializeOperationrec();
@@ -2614,8 +2648,9 @@ private:
//-----------------------------------------------------------------------------
// Public methods
- Uint32 getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset);
- Uint32 allocTabDescr(const Tablerec* regTabPtr, Uint32* offset);
+ Uint32 getTabDescrOffsets(Uint32, Uint32, Uint32, Uint32*);
+ Uint32 getDynTabDescrOffsets(Uint32 MaskSize, Uint32* offset);
+ Uint32 allocTabDescr(Uint32 allocSize);
void freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal = true);
Uint32 getTabDescrWord(Uint32 index);
void setTabDescrWord(Uint32 index, Uint32 word);
@@ -2632,8 +2667,11 @@ private:
void seizeOpRec(OperationrecPtr& regOperPtr);
void seizeFragrecord(FragrecordPtr& regFragPtr);
void seizeFragoperrec(FragoperrecPtr& fragOperPtr);
+ void seizeAlterTabOperation(AlterTabOperationPtr& alterTabOpPtr);
void releaseFragoperrec(FragoperrecPtr fragOperPtr);
void releaseFragrec(FragrecordPtr);
+ void releaseAlterTabOpRec(AlterTabOperationPtr regAlterTabOpPtr);
+
//----------------------------------------------------------------------------
// Page Memory Manager
//----------------------------------------------------------------------------
@@ -2768,6 +2806,10 @@ private:
Fragrecord *fragrecord;
Uint32 cfirstfreefrag;
Uint32 cnoOfFragrec;
+
+ AlterTabOperation *alterTabOperRec;
+ Uint32 cfirstfreeAlterTabOp;
+ Uint32 cnoOfAlterTabOps;
HostBuffer *hostBuffer;
--- 1.31/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2006-11-07 09:46:08 +01:00
+++ 1.32/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2006-11-07 09:46:08 +01:00
@@ -43,6 +43,7 @@ void Dbtup::initData()
cnoOfAttrbufrec = ZNO_OF_ATTRBUFREC;
cnoOfFragrec = MAX_FRAG_PER_NODE;
cnoOfFragoprec = MAX_FRAG_PER_NODE;
+ cnoOfAlterTabOps = MAX_FRAG_PER_NODE;
cnoOfPageRangeRec = ZNO_OF_PAGE_RANGE_REC;
c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE;
c_noOfBuildIndexRec = 32;
@@ -77,6 +78,7 @@ Dbtup::Dbtup(Block_context& ctx, Pgman*
addRecSignal(GSN_STORED_PROCREQ, &Dbtup::execSTORED_PROCREQ);
addRecSignal(GSN_TUPFRAGREQ, &Dbtup::execTUPFRAGREQ);
addRecSignal(GSN_TUP_ADD_ATTRREQ, &Dbtup::execTUP_ADD_ATTRREQ);
+ addRecSignal(GSN_ALTER_TAB_REQ, &Dbtup::execALTER_TAB_REQ);
addRecSignal(GSN_TUP_COMMITREQ, &Dbtup::execTUP_COMMITREQ);
addRecSignal(GSN_TUP_ABORTREQ, &Dbtup::execTUP_ABORTREQ);
addRecSignal(GSN_NDB_STTOR, &Dbtup::execNDB_STTOR);
@@ -106,6 +108,7 @@ Dbtup::Dbtup(Block_context& ctx, Pgman*
attrbufrec = 0;
fragoperrec = 0;
fragrecord = 0;
+ alterTabOperRec = 0;
hostBuffer = 0;
pageRange = 0;
tablerec = 0;
@@ -130,6 +133,10 @@ Dbtup::~Dbtup()
deallocRecord((void **)&fragrecord,"Fragrecord",
sizeof(Fragrecord),
cnoOfFragrec);
+
+ deallocRecord((void **)&alterTabOperRec,"AlterTabOperRec",
+ sizeof(alterTabOperRec),
+ cnoOfAlterTabOps);
deallocRecord((void **)&hostBuffer,"HostBuffer",
sizeof(HostBuffer),
@@ -365,6 +372,10 @@ void Dbtup::initRecords()
sizeof(Fragrecord),
cnoOfFragrec);
+ alterTabOperRec = (AlterTabOperation*)allocRecord("AlterTabOperation",
+ sizeof(AlterTabOperation),
+ cnoOfAlterTabOps);
+
hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
sizeof(HostBuffer),
MAX_NODES);
@@ -434,6 +445,7 @@ void Dbtup::initialiseRecordsLab(Signal*
break;
case 10:
ljam();
+ initializeAlterTabOperation();
break;
case 11:
ljam();
@@ -556,6 +568,24 @@ void Dbtup::initializeFragrecord()
regFragPtr.p->nextfreefrag = RNIL;
cfirstfreefrag = 0;
}//Dbtup::initializeFragrecord()
+
+void Dbtup::initializeAlterTabOperation()
+{
+ AlterTabOperationPtr regAlterTabOpPtr;
+ for (regAlterTabOpPtr.i= 0;
+ regAlterTabOpPtr.i<cnoOfAlterTabOps;
+ regAlterTabOpPtr.i++)
+ {
+ refresh_watch_dog();
+ ptrAss(regAlterTabOpPtr, alterTabOperRec);
+ new (regAlterTabOpPtr.p) AlterTabOperation();
+ regAlterTabOpPtr.p->nextAlterTabOp= regAlterTabOpPtr.i+1;
+ }
+ regAlterTabOpPtr.i= cnoOfAlterTabOps-1;
+ ptrAss(regAlterTabOpPtr, alterTabOperRec);
+ regAlterTabOpPtr.p->nextAlterTabOp= RNIL;
+ cfirstfreeAlterTabOp= 0;
+}
void Dbtup::initializeHostBuffer()
{
--- 1.32/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2006-11-07 09:46:08 +01:00
+++ 1.33/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2006-11-07 09:46:08 +01:00
@@ -25,6 +25,7 @@
#include <signaldata/FsRemoveReq.hpp>
#include <signaldata/DropTab.hpp>
#include <signaldata/AlterTab.hpp>
+#include <signaldata/AlterTable.hpp>
#include <signaldata/CreateFilegroupImpl.hpp>
#include <AttributeDescriptor.hpp>
#include "AttributeOffset.hpp"
@@ -97,15 +98,6 @@ void Dbtup::execTUPFRAGREQ(Signal* signa
fragOperPtr.p->attributeCount = noOfAttributes;
memset(fragOperPtr.p->m_null_bits, 0, sizeof(fragOperPtr.p->m_null_bits));
- memset(fragOperPtr.p->m_dyn_null_bits, 0,
- sizeof(fragOperPtr.p->m_dyn_null_bits));
- fragOperPtr.p->m_dyn_null_bits[MM]= 8; // Reserve space for bitmap length
- memset(fragOperPtr.p->m_fix_attributes_size, 0,
- sizeof(fragOperPtr.p->m_fix_attributes_size));
- memset(fragOperPtr.p->m_var_attributes_size, 0,
- sizeof(fragOperPtr.p->m_var_attributes_size));
- memset(fragOperPtr.p->m_dyn_attributes_size, 0,
- sizeof(fragOperPtr.p->m_var_attributes_size));
fragOperPtr.p->charsetIndex = 0;
fragOperPtr.p->minRows = minRows;
@@ -175,6 +167,8 @@ void Dbtup::execTUPFRAGREQ(Signal* signa
// bits. Each time a new word is needed we allocate the
// complete word. Zero nullable attributes means that there
// is no word at all
+// Note that the null-bits are also used for storing the
+// data for (non-dynamic) bit types.
//-----------------------------------------------------------------------------
fragOperPtr.p->definingFragment= true;
regTabPtr.p->tableStatus= DEFINING;
@@ -207,17 +201,17 @@ void Dbtup::execTUPFRAGREQ(Signal* signa
regTabPtr.p->m_attributes[DD].m_no_of_dyn_fix= 0;
regTabPtr.p->m_attributes[DD].m_no_of_dyn_var= 0;
+ regTabPtr.p->m_dyn_null_bits= 8; // Reserve space for bitmap length
regTabPtr.p->noOfKeyAttr= noOfKeyAttr;
regTabPtr.p->noOfCharsets= noOfCharsets;
regTabPtr.p->m_no_of_attributes= noOfAttributes;
- regTabPtr.p->notNullAttributeMask.clear();
- regTabPtr.p->blobAttributeMask.clear();
- bzero(regTabPtr.p->dynVarSizeMask, sizeof(regTabPtr.p->dynVarSizeMask));
- bzero(regTabPtr.p->dynFixSizeMask, sizeof(regTabPtr.p->dynFixSizeMask));
+ regTabPtr.p->dynTabDescriptor= RNIL;
Uint32 offset[10];
- Uint32 tableDescriptorRef= allocTabDescr(regTabPtr.p, offset);
+ Uint32 allocSize= getTabDescrOffsets(noOfAttributes, noOfCharsets,
+ noOfKeyAttr, offset);
+ Uint32 tableDescriptorRef= allocTabDescr(allocSize);
if (tableDescriptorRef == RNIL) {
ljam();
fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
@@ -286,6 +280,14 @@ void Dbtup::seizeFragoperrec(Fragoperrec
fragOperPtr.p->inUse = true;
}//Dbtup::seizeFragoperrec()
+void Dbtup::seizeAlterTabOperation(AlterTabOperationPtr& alterTabOpPtr)
+{
+ alterTabOpPtr.i= cfirstfreeAlterTabOp;
+ ptrCheckGuard(alterTabOpPtr, cnoOfAlterTabOps, alterTabOperRec);
+ cfirstfreeAlterTabOp= alterTabOpPtr.p->nextAlterTabOp;
+ alterTabOpPtr.p->nextAlterTabOp= RNIL;
+}
+
/* **************************************************************** */
/* ************** TUP_ADD_ATTRREQ ****************** */
/* **************************************************************** */
@@ -302,7 +304,6 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
Uint32 attrDescriptor = signal->theData[3];
/* ToDo: Just for testing... */
//if((AttributeDescriptor::getArrayType(attrDescriptor) !=
NDB_ARRAYTYPE_FIXED||AttributeDescriptor::getNullable(attrDescriptor)||attrId>0)
&& (AttributeDescriptor::getSizeInBytes(attrDescriptor) < 64 ||
AttributeDescriptor::getArrayType(attrDescriptor) != NDB_ARRAYTYPE_FIXED) &&
!AttributeDescriptor::getDiskBased(attrDescriptor) &&
AttributeDescriptor::getSize(attrDescriptor) > 0){
AttributeDescriptor::setDynamic(attrDescriptor, 1); ndbout_c("AAA setting attrid %d to
dynamic ...", attrId);}
- Uint32 extType = AttributeDescriptor::getType(attrDescriptor);
// DICT sends charset number in upper half
Uint32 csNumber = (signal->theData[4] >> 16);
@@ -356,7 +357,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
ljam();
- Uint32 pos= 0, null_pos;
+ Uint32 null_pos;
ndbrequire(ind <= 1);
null_pos= fragOperPtr.p->m_null_bits[ind];
@@ -365,50 +366,29 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
ljam();
fragOperPtr.p->m_null_bits[ind]++;
}
- else
- {
- regTabPtr.p->notNullAttributeMask.set(attrId);
- }
- if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT) {
- regTabPtr.p->blobAttributeMask.set(attrId);
- }
-
- switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
- case NDB_ARRAYTYPE_FIXED:
+ if (AttributeDescriptor::getArrayType(attrDescriptor)==NDB_ARRAYTYPE_FIXED)
{
ljam();
regTabPtr.p->m_attributes[ind].m_no_of_fixsize++;
- if(attrLen != 0)
- {
- /* A byte-sized element type (char, int, ...). */
- ljam();
- pos= fragOperPtr.p->m_fix_attributes_size[ind];
- fragOperPtr.p->m_fix_attributes_size[ind] += words;
- }
- else
+ if(attrLen == 0)
{
+ /* Static bit type. */
ljam();
Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
fragOperPtr.p->m_null_bits[ind] += bitCount;
}
- break;
}
- default:
+ else
{
- ljam();
- fragOperPtr.p->m_var_attributes_size[ind] += bytes;
- pos= regTabPtr.p->m_attributes[ind].m_no_of_varsize++;
- break;
+ regTabPtr.p->m_attributes[ind].m_no_of_varsize++;
}
- }//switch
- AttributeOffset::setOffset(attrDes2, pos);
AttributeOffset::setNullFlagPos(attrDes2, null_pos);
} else {
/* A dynamic attribute. */
- if(!AttributeDescriptor::getNullable(attrDescriptor))
- regTabPtr.p->notNullAttributeMask.set(attrId);
+ ndbrequire(ind==MM);
+ regTabPtr.p->m_attributes[ind].m_no_of_dynamic++;
/*
The dynamic attribute format always require a 'null' bit. So
storing NOT NULL attributes as dynamic is not all that useful
@@ -417,19 +397,15 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
xxx internally as 'null'.
*/
- ndbrequire(extType != NDB_TYPE_BLOB && extType != NDB_TYPE_TEXT);
- Uint32 null_pos= fragOperPtr.p->m_dyn_null_bits[ind];
+ Uint32 null_pos= regTabPtr.p->m_dyn_null_bits;
AttributeOffset::setNullFlagPos(attrDes2, null_pos);
- Uint32 off;
- switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
- case NDB_ARRAYTYPE_FIXED:
+ if (AttributeDescriptor::getArrayType(attrDescriptor)==NDB_ARRAYTYPE_FIXED)
{
/* A fixed-size dynamic attribute. */
ljam();
- off= regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix++;
- regTabPtr.p->m_attributes[ind].m_no_of_dynamic++;
- fragOperPtr.p->m_dyn_attributes_size[ind] += (bytes+3)&~3;
+ regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix++;
+ /* ToDo: Handle bit type. */
ndbrequire(bytes > 0);
/*
We use one NULL bit per 4 bytes of dynamic fixed-size attribute. So
@@ -440,43 +416,22 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
*/
ndbrequire(bytes <= 64);
Uint32 null_bits= (bytes+3) >> 2;
- fragOperPtr.p->m_dyn_null_bits[ind]+= null_bits;
- while(null_bits-- > 0)
- dynSetBit(regTabPtr.p->dynFixSizeMask, null_pos++);
- break;
+ regTabPtr.p->m_dyn_null_bits+= null_bits;
}
- default:
+ else
{
/* A variable-sized dynamic attribute. */
ljam();
- off= regTabPtr.p->m_attributes[ind].m_no_of_dyn_var++;
- regTabPtr.p->m_attributes[ind].m_no_of_dynamic++;
- fragOperPtr.p->m_dyn_attributes_size[ind] += (bytes+3)&~3;
- fragOperPtr.p->m_dyn_null_bits[ind]++;
- dynSetBit(regTabPtr.p->dynVarSizeMask, null_pos);
+ regTabPtr.p->m_attributes[ind].m_no_of_dyn_var++;
+ regTabPtr.p->m_dyn_null_bits++;
}
- }//switch
-
- AttributeOffset::setOffset(attrDes2, off);
- }
- if (csNumber != 0) {
- CHARSET_INFO* cs = all_charsets[csNumber];
- ndbrequire(cs != NULL);
- Uint32 i = 0;
- while (i < fragOperPtr.p->charsetIndex) {
- ljam();
- if (regTabPtr.p->charsetArray[i] == cs)
- break;
- i++;
- }
- if (i == fragOperPtr.p->charsetIndex) {
- ljam();
- fragOperPtr.p->charsetIndex++;
- }
- ndbrequire(i < regTabPtr.p->noOfCharsets);
- regTabPtr.p->charsetArray[i]= cs;
- AttributeOffset::setCharsetPos(attrDes2, i);
- }
+ ndbassert((regTabPtr.p->m_attributes[ind].m_no_of_dyn_var +
+ regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix) ==
+ regTabPtr.p->m_attributes[ind].m_no_of_dynamic);
+ }
+ handleCharsetPos(csNumber, regTabPtr.p->charsetArray,
+ regTabPtr.p->noOfCharsets,
+ fragOperPtr.p->charsetIndex, attrDes2);
setTabDescrWord(firstTabDesIndex + 1, attrDes2);
if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId &&
attrId == 0||
@@ -508,131 +463,23 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
#define BTW(x) ((x+31) >> 5)
regTabPtr.p->m_offsets[MM].m_null_words= BTW(fragOperPtr.p->m_null_bits[MM]);
- regTabPtr.p->m_offsets[MM].m_dyn_null_words=
BTW(fragOperPtr.p->m_dyn_null_bits[MM]);
regTabPtr.p->m_offsets[DD].m_null_words= BTW(fragOperPtr.p->m_null_bits[DD]);
+#undef BTW
- /**
- * Fix offsets
- */
- Uint32 pos[2] = { 0, 0 };
- if (regTabPtr.p->m_bits & Tablerec::TR_Checksum)
- {
- pos[0]= 1;
- }
-
- if (regTabPtr.p->m_bits & Tablerec::TR_RowGCI)
- {
- pos[MM]++;
- pos[DD]++;
- }
-
- regTabPtr.p->m_no_of_disk_attributes=
- regTabPtr.p->m_attributes[DD].m_no_of_fixsize +
- regTabPtr.p->m_attributes[DD].m_no_of_varsize;
-
- if(regTabPtr.p->m_no_of_disk_attributes > 0)
- {
- regTabPtr.p->m_offsets[MM].m_disk_ref_offset= pos[MM];
- pos[MM] += 2; // 8 bytes
+ /* Allocate dynamic descriptor. */
+ Uint32 offset[3];
+ Uint32 allocSize= getDynTabDescrOffsets((regTabPtr.p->m_dyn_null_bits+31)>>5,
+ offset);
+ Uint32 dynTableDescriptorRef= allocTabDescr(allocSize);
+ if (dynTableDescriptorRef == RNIL) {
+ ljam();
+ addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+ return;
}
-
- regTabPtr.p->m_offsets[MM].m_null_offset= pos[MM];
- regTabPtr.p->m_offsets[DD].m_null_offset= pos[DD];
-
- pos[MM]+= regTabPtr.p->m_offsets[MM].m_null_words;
- pos[DD]+= regTabPtr.p->m_offsets[DD].m_null_words;
-
- Uint32 *tabDesc = (Uint32*)(tableDescriptor+regTabPtr.p->tabDescriptor);
- for(Uint32 i= 0; i<regTabPtr.p->m_no_of_attributes; i++)
- {
- Uint32 ind= AttributeDescriptor::getDiskBased(* tabDesc);
- Uint32 dynattr= AttributeDescriptor::getDynamic(* tabDesc);
- Uint32 arr= AttributeDescriptor::getArrayType(* tabDesc++);
-
- if(arr == NDB_ARRAYTYPE_FIXED)
- {
- /*
- Adjust the dynamic fixed-size offsets to take into account the
- number of variable-sized attributes before them.
- Adjust the static fixed-size offsets to take into account the header.
- */
+ setupDynDescriptorReferences(dynTableDescriptorRef, regTabPtr.p, offset);
- Uint32 desc= * tabDesc;
- Uint32 off;
- if(dynattr)
- off= AttributeOffset::getOffset(desc) +
- regTabPtr.p->m_attributes[ind].m_no_of_dyn_var;
- else
- off= AttributeOffset::getOffset(desc) + pos[ind];
- AttributeOffset::setOffset(desc, off);
- * tabDesc= desc;
- }
- tabDesc++;
- }
-
- regTabPtr.p->m_offsets[MM].m_fix_header_size=
- fragOperPtr.p->m_fix_attributes_size[MM] +
- pos[MM];
-
- regTabPtr.p->m_offsets[DD].m_fix_header_size=
- fragOperPtr.p->m_fix_attributes_size[DD] +
- pos[DD];
-
- if((regTabPtr.p->m_attributes[MM].m_no_of_varsize +
- regTabPtr.p->m_attributes[MM].m_no_of_dynamic) == 0)
- regTabPtr.p->m_offsets[MM].m_fix_header_size += Tuple_header::HeaderSize;
-
- if(regTabPtr.p->m_attributes[DD].m_no_of_varsize == 0 &&
- regTabPtr.p->m_attributes[DD].m_no_of_fixsize > 0)
- regTabPtr.p->m_offsets[DD].m_fix_header_size += Tuple_header::HeaderSize;
-
- Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
- Uint32 mm_dyns= regTabPtr.p->m_attributes[MM].m_no_of_dynamic;
- Uint32 dd_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
- Uint32 dd_dyns= regTabPtr.p->m_attributes[DD].m_no_of_dynamic;
-
- regTabPtr.p->m_offsets[MM].m_max_var_offset=
- fragOperPtr.p->m_var_attributes_size[MM];
- regTabPtr.p->m_offsets[MM].m_max_dyn_offset=
- (regTabPtr.p->m_offsets[MM].m_dyn_null_words<<2) + 4*((mm_dyns+2)>>1)
+
- fragOperPtr.p->m_dyn_attributes_size[MM];
-
- regTabPtr.p->m_offsets[DD].m_max_var_offset=
- fragOperPtr.p->m_var_attributes_size[DD];
- regTabPtr.p->m_offsets[DD].m_max_dyn_offset=
- (regTabPtr.p->m_offsets[DD].m_dyn_null_words<<2) + 4*((dd_dyns+2)>>1)
+
- fragOperPtr.p->m_dyn_attributes_size[DD];
-
- /* Room for data for all the attributes. */
- Uint32 total_rec_size=
- pos[MM] + fragOperPtr.p->m_fix_attributes_size[MM] +
- pos[DD] + fragOperPtr.p->m_fix_attributes_size[DD] +
- ((fragOperPtr.p->m_var_attributes_size[MM] + 3) >> 2) +
- ((fragOperPtr.p->m_dyn_attributes_size[MM] + 3) >> 2) +
- ((fragOperPtr.p->m_var_attributes_size[DD] + 3) >> 2);
- /*
- Room for offset arrays and dynamic bitmaps. There is one extra 16-bit
- offset in each offset array (for easy computation of final length).
- Also one word for storing total length of varsize+dynamic part
- */
- if(mm_vars + mm_dyns)
- {
- total_rec_size+= (mm_vars + 2) >> 1;
- total_rec_size+= regTabPtr.p->m_offsets[MM].m_dyn_null_words;
- total_rec_size+= (mm_dyns + 2) >> 1;
- total_rec_size+= 1;
- }
- /* Disk data varsize offset array (not currently used). */
- if(dd_vars)
- total_rec_size+= (dd_vars + 2) >> 1;
- /* Room for the header. */
- total_rec_size+= Tuple_header::HeaderSize;
- if(regTabPtr.p->m_no_of_disk_attributes)
- total_rec_size+= Tuple_header::HeaderSize;
- regTabPtr.p->total_rec_size= total_rec_size;
-
- setUpQueryRoutines(regTabPtr.p);
- setUpKeyArray(regTabPtr.p);
+ /* Compute table aggregate metadata. */
+ computeTableMetaData(regTabPtr.p);
#if 0
ndbout << *regTabPtr.p << endl;
@@ -649,7 +496,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
{
Uint32 fix_tupheader = regTabPtr.p->m_offsets[MM].m_fix_header_size;
if((regTabPtr.p->m_attributes[MM].m_no_of_varsize +
- regTabPtr.p->m_attributes[MM].m_no_of_varsize) != 0)
+ regTabPtr.p->m_attributes[MM].m_no_of_dynamic) != 0)
fix_tupheader += Tuple_header::HeaderSize + 1;
ndbassert(fix_tupheader > 0);
Uint32 noRowsPerPage = ZWORDS_ON_PAGE / fix_tupheader;
@@ -726,6 +573,517 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
}
void
+Dbtup::execALTER_TAB_REQ(Signal *signal)
+{
+ ljamEntry();
+ if(!assembleFragments(signal))
+ return;
+ AlterTabReq *const req= (AlterTabReq *)signal->getDataPtr();
+ if (!AlterTableReq::getAddAttrFlag(req->changeMask))
+ {
+ /* Nothing to do in TUP. */
+ releaseSections(signal);
+ sendAlterTabConf(signal, req);
+ return;
+ }
+
+ TablerecPtr regTabPtr;
+ regTabPtr.i= req->tableId;
+ ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
+
+ AlterTabReq::RequestType alterType=
+ (AlterTabReq::RequestType)req->requestType;
+
+ if(alterType==AlterTabReq::AlterTablePrepare)
+ {
+ handleAlterTabPrepare(signal, regTabPtr.p);
+ return;
+ }
+
+ AlterTabOperationPtr regAlterTabOpPtr;
+ if (req->clientData==RNIL)
+ {
+ /* This means that we failed in prepare, or never got there. */
+ sendAlterTabConf(signal, req);
+ return;
+ }
+ regAlterTabOpPtr.i= req->clientData;
+ ptrCheckGuard(regAlterTabOpPtr, cnoOfAlterTabOps, alterTabOperRec);
+
+ if(alterType==AlterTabReq::AlterTableCommit)
+ {
+ handleAlterTableCommit(signal, regAlterTabOpPtr, regTabPtr.p);
+ }
+ else if(alterType==AlterTabReq::AlterTableRevert)
+ {
+ handleAlterTableAbort(signal, regAlterTabOpPtr, regTabPtr.p);
+ }
+ else
+ {
+ ndbrequire(false);
+ }
+}
+
+void
+Dbtup::handleAlterTabPrepare(Signal *signal, const Tablerec *regTabPtr)
+{
+ AlterTabReq *const req= (AlterTabReq *)signal->getDataPtr();
+
+ Uint32 noOfNewAttr= req->noOfNewAttr;
+ Uint32 newNoOfCharsets= req->newNoOfCharsets;
+ Uint32 newNoOfKeyAttrs= req->newNoOfKeyAttrs;
+
+ ndbrequire(signal->getNoOfSections() == 1);
+ ndbrequire((25+noOfNewAttr*2)<<2 < sizeof(signal->theData));
+
+ /* Get the array of attribute descriptor words. */
+ SegmentedSectionPtr ssPtr;
+ Uint32 *attrInfo= signal->theData+25;
+ signal->getSection(ssPtr, 0);
+ copy(attrInfo, ssPtr);
+ releaseSections(signal);
+
+ Uint32 oldNoOfAttr= regTabPtr->m_no_of_attributes;
+ Uint32 newNoOfAttr= oldNoOfAttr+noOfNewAttr;
+
+ /* Can only add attributes if varpart already present. */
+ if((regTabPtr->m_attributes[MM].m_no_of_varsize +
+ regTabPtr->m_attributes[MM].m_no_of_dynamic) == 0)
+ {
+ sendAlterTabRef(signal, req, ZINVALID_ALTER_TAB);
+ return;
+ }
+
+ AlterTabOperationPtr regAlterTabOpPtr;
+ seizeAlterTabOperation(regAlterTabOpPtr);
+
+ regAlterTabOpPtr.p->newNoOfAttrs= newNoOfAttr;
+
+ /* Allocate a new (possibly larger) table descriptor buffer. */
+ Uint32 allocSize= getTabDescrOffsets(newNoOfAttr, newNoOfCharsets,
+ newNoOfKeyAttrs,
+ regAlterTabOpPtr.p->tabDesOffset);
+ Uint32 tableDescriptorRef= allocTabDescr(allocSize);
+ if (tableDescriptorRef == RNIL) {
+ ljam();
+ releaseAlterTabOpRec(regAlterTabOpPtr);
+ sendAlterTabRef(signal, req, terrorCode);
+ return;
+ }
+ regAlterTabOpPtr.p->tableDescriptor= tableDescriptorRef;
+ regAlterTabOpPtr.p->desAllocSize= allocSize;
+
+ /*
+ Get new pointers into tableDescriptor, and copy over old data.
+ (Rest will be recomputed in computeTableMetaData() in case of
+ ALTER_TAB_REQ[commit]).
+ */
+ Uint32* desc= &tableDescriptor[tableDescriptorRef].tabDescr;
+ CHARSET_INFO** CharsetArray=
+ (CHARSET_INFO**)(desc + regAlterTabOpPtr.p->tabDesOffset[2]);
+ memcpy(CharsetArray, regTabPtr->charsetArray,
+ sizeof(*CharsetArray)*regTabPtr->noOfCharsets);
+ Uint32 *attrDesPtr= desc + regAlterTabOpPtr.p->tabDesOffset[4];
+ memcpy(attrDesPtr,
+ &tableDescriptor[regTabPtr->tabDescriptor].tabDescr,
+ (ZAD_SIZE<<2)*oldNoOfAttr);
+ attrDesPtr+= ZAD_SIZE*oldNoOfAttr;
+
+ /*
+ Loop over the new attributes to add.
+ - Save AttributeDescriptor word in new TabDescriptor record.
+ - Compute charset pos, as we will not save original csNumber.
+ - Compute size needed for dynamic bitmap mask allocation.
+ - Compute number of dynamic varsize, needed for fixsize offset calculation
+ in ALTER_TAB_REQ[commit];
+ */
+ Uint32 charsetIndex= regTabPtr->noOfCharsets;
+ Uint32 dyn_nullbits= regTabPtr->m_dyn_null_bits;
+ Uint32 noDynFix= regTabPtr->m_attributes[MM].m_no_of_dyn_fix;
+ Uint32 noDynVar= regTabPtr->m_attributes[MM].m_no_of_dyn_var;
+ for (Uint32 i= 0; i<noOfNewAttr; i++)
+ {
+ Uint32 attrDescriptor= *attrInfo++;
+ Uint32 csNumber= (*attrInfo++ >> 16);
+ Uint32 attrDes2= 0;
+
+ /* Only dynamic attributes possible for add attr */
+ ndbassert(AttributeDescriptor::getDynamic(attrDescriptor));
+ ndbassert(!AttributeDescriptor::getDiskBased(attrDescriptor));
+
+ handleCharsetPos(csNumber, CharsetArray, newNoOfCharsets,
+ charsetIndex, attrDes2);
+
+ AttributeOffset::setNullFlagPos(attrDes2, dyn_nullbits);
+ Uint32 arrType= AttributeDescriptor::getArrayType(attrDescriptor);
+ if (arrType==NDB_ARRAYTYPE_FIXED)
+ {
+ Uint32 words= AttributeDescriptor::getSizeInWords(attrDescriptor);
+ noDynFix++;
+
+ if(AttributeDescriptor::getSize(attrDescriptor) > 0)
+ dyn_nullbits+= words;
+ else
+ ndbrequire(false); // ToDo: Handle bit types
+
+ ndbrequire(words <= 16); // ToDo: Handle fix>64 bytes
+ }
+ else
+ {
+ noDynVar++;
+ dyn_nullbits++;
+ }
+
+ *attrDesPtr++= attrDescriptor;
+ *attrDesPtr++= attrDes2;
+ }
+ ndbassert(newNoOfCharsets==charsetIndex);
+
+ regAlterTabOpPtr.p->noOfDynNullBits= dyn_nullbits;
+ ndbassert(noDynFix + noDynVar ==
+ regTabPtr->m_attributes[MM].m_no_of_dynamic + noOfNewAttr);
+ regAlterTabOpPtr.p->noOfDynFix= noDynFix;
+ regAlterTabOpPtr.p->noOfDynVar= noDynVar;
+
+ /* Allocate the new (possibly larger) dynamic descriptor. */
+ allocSize= getDynTabDescrOffsets((dyn_nullbits+31)>>5,
+ regAlterTabOpPtr.p->dynTabDesOffset);
+ Uint32 dynTableDescriptorRef= allocTabDescr(allocSize);
+ if (dynTableDescriptorRef == RNIL) {
+ ljam();
+ freeTabDescr(tableDescriptorRef, regAlterTabOpPtr.p->desAllocSize);
+ releaseAlterTabOpRec(regAlterTabOpPtr);
+ sendAlterTabRef(signal, req, terrorCode);
+ return;
+ }
+ regAlterTabOpPtr.p->dynDesAllocSize= allocSize;
+ regAlterTabOpPtr.p->dynTableDescriptor= dynTableDescriptorRef;
+
+ sendAlterTabConf(signal, req, regAlterTabOpPtr.i);
+}
+
+void
+Dbtup::sendAlterTabRef(Signal *signal, AlterTabReq *req, Uint32 errorCode)
+{
+ signal->header.m_noOfSections = 0;
+
+ AlterTabAll *const src= (AlterTabAll *)req;
+ Uint32 senderRef= src->req.senderRef;
+ Uint32 senderData= src->req.senderData;
+ Uint32 requestType= src->req.requestType;
+
+ AlterTabAll *const dst= (AlterTabAll *)signal->getDataPtrSend();
+ dst->ref.senderRef= reference();
+ dst->ref.senderData= senderData;
+ dst->ref.errorCode= errorCode;
+ dst->ref.errorLine= 0;
+ dst->ref.errorKey= 0;
+ dst->ref.errorStatus= 0;
+ dst->ref.requestType= requestType;
+
+ sendSignal(senderRef, GSN_ALTER_TAB_REF, signal,
+ AlterTabRef::SignalLength, JBB);
+}
+
+void
+Dbtup::sendAlterTabConf(Signal *signal, AlterTabReq *req, Uint32 clientData)
+{
+ signal->header.m_noOfSections = 0;
+
+ AlterTabAll *const src= (AlterTabAll *)req;
+ Uint32 senderRef= src->req.senderRef;
+ Uint32 senderData= src->req.senderData;
+ Uint32 changeMask= src->req.changeMask;
+ Uint32 tableId= src->req.tableId;
+ Uint32 tableVersion= src->req.tableVersion;
+ Uint32 gci= src->req.gci;
+ Uint32 requestType= src->req.requestType;
+
+ AlterTabAll *const dst= (AlterTabAll *)signal->getDataPtrSend();
+ dst->conf.senderRef= reference();
+ dst->conf.senderData= senderData;
+ dst->conf.changeMask= changeMask;
+ dst->conf.tableId= tableId;
+ dst->conf.tableVersion= tableVersion;
+ dst->conf.gci= gci;
+ dst->conf.requestType= requestType;
+ dst->conf.clientData= clientData;
+
+ sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
+ AlterTabConf::SignalLength, JBB);
+}
+
+void
+Dbtup::handleAlterTableCommit(Signal *signal,
+ AlterTabOperationPtr regAlterTabOpPtr,
+ Tablerec *regTabPtr)
+{
+ /* Free old table descriptors. */
+ releaseTabDescr(regTabPtr);
+
+ /* Set new attribute counts. */
+ regTabPtr->m_no_of_attributes= regAlterTabOpPtr.p->newNoOfAttrs;
+ regTabPtr->m_attributes[MM].m_no_of_dyn_fix= regAlterTabOpPtr.p->noOfDynFix;
+ regTabPtr->m_attributes[MM].m_no_of_dyn_var= regAlterTabOpPtr.p->noOfDynVar;
+ regTabPtr->m_attributes[MM].m_no_of_dynamic=
+ regAlterTabOpPtr.p->noOfDynFix + regAlterTabOpPtr.p->noOfDynVar;
+ regTabPtr->m_dyn_null_bits= regAlterTabOpPtr.p->noOfDynNullBits;
+
+ /* Install the new (larger) table descriptors. */
+ setUpDescriptorReferences(regAlterTabOpPtr.p->tableDescriptor,
+ regTabPtr,
+ regAlterTabOpPtr.p->tabDesOffset);
+ setupDynDescriptorReferences(regAlterTabOpPtr.p->dynTableDescriptor,
+ regTabPtr,
+ regAlterTabOpPtr.p->dynTabDesOffset);
+
+ releaseAlterTabOpRec(regAlterTabOpPtr);
+
+ /* Recompute aggregate table meta data. */
+ computeTableMetaData(regTabPtr);
+
+ sendAlterTabConf(signal, (AlterTabReq *)signal->getDataPtr());
+}
+
+void
+Dbtup::handleAlterTableAbort(Signal *signal,
+ AlterTabOperationPtr regAlterTabOpPtr,
+ Tablerec *regTabPtr)
+{
+ freeTabDescr(regAlterTabOpPtr.p->tableDescriptor,
+ regAlterTabOpPtr.p->desAllocSize);
+ freeTabDescr(regAlterTabOpPtr.p->dynTableDescriptor,
+ regAlterTabOpPtr.p->dynDesAllocSize);
+ releaseAlterTabOpRec(regAlterTabOpPtr);
+
+ sendAlterTabConf(signal, (AlterTabReq *)signal->getDataPtr());
+}
+
+/*
+ Update information for charset for a new attribute.
+ If needed, attrDes2 will be updated with the correct charsetPos and
+ charsetIndex will be updated to point to next free charsetPos slot.
+*/
+void
+Dbtup::handleCharsetPos(Uint32 csNumber, CHARSET_INFO** charsetArray,
+ Uint32 noOfCharsets,
+ Uint32 & charsetIndex, Uint32 & attrDes2)
+{
+ if (csNumber != 0)
+ {
+ CHARSET_INFO* cs = all_charsets[csNumber];
+ ndbrequire(cs != NULL);
+ Uint32 i= 0;
+ while (i < charsetIndex)
+ {
+ ljam();
+ if (charsetArray[i] == cs)
+ break;
+ i++;
+ }
+ if (i == charsetIndex) {
+ ljam();
+ ndbrequire(i < noOfCharsets);
+ charsetArray[i]= cs;
+ charsetIndex++;
+ }
+ AttributeOffset::setCharsetPos(attrDes2, i);
+ }
+}
+
+/*
+ This function (re-)computes aggregated metadata. It is called for
+ both ALTER TABLE and CREATE TABLE.
+ */
+void
+Dbtup::computeTableMetaData(Tablerec *regTabPtr)
+{
+
+ Uint32 dyn_null_words= (regTabPtr->m_dyn_null_bits+31)>>5;
+ regTabPtr->m_offsets[MM].m_dyn_null_words= dyn_null_words;
+
+ /* Compute the size of the static headers. */
+ Uint32 pos[2] = { 0, 0 };
+ if (regTabPtr->m_bits & Tablerec::TR_Checksum)
+ {
+ pos[MM]++;
+ }
+
+ if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
+ {
+ pos[MM]++;
+ pos[DD]++;
+ }
+
+ regTabPtr->m_no_of_disk_attributes=
+ regTabPtr->m_attributes[DD].m_no_of_fixsize +
+ regTabPtr->m_attributes[DD].m_no_of_varsize;
+ if(regTabPtr->m_no_of_disk_attributes > 0)
+ {
+ /* Room for disk part location. */
+ regTabPtr->m_offsets[MM].m_disk_ref_offset= pos[MM];
+ pos[MM] += 2; // 8 bytes
+ }
+
+ regTabPtr->m_offsets[MM].m_null_offset= pos[MM];
+ regTabPtr->m_offsets[DD].m_null_offset= pos[DD];
+ pos[MM]+= regTabPtr->m_offsets[MM].m_null_words;
+ pos[DD]+= regTabPtr->m_offsets[DD].m_null_words;
+
+ /*
+ Compute the offsets for the attributes.
+ For static fixed-size, this is the offset from the tuple pointer of the
+ actual data.
+ For static var-size and dynamic, this is the index into the offset array.
+
+ We also compute the dynamic bitmasks here.
+ */
+ Uint32 *tabDesc= (Uint32*)(tableDescriptor+regTabPtr->tabDescriptor);
+ Uint32 *dynDesc= (Uint32*)(tableDescriptor+regTabPtr->dynTabDescriptor);
+ Uint32 fix_size[2]= {0, 0};
+ Uint32 var_size[2]= {0, 0};
+ Uint32 dyn_size[2]= {0, 0};
+ Uint32 statvar_count= 0;
+ Uint32 dynfix_count= 0;
+ Uint32 dynvar_count= 0;
+ regTabPtr->blobAttributeMask.clear();
+ regTabPtr->notNullAttributeMask.clear();
+ bzero(regTabPtr->dynVarSizeMask, dyn_null_words<<2);
+ bzero(regTabPtr->dynFixSizeMask, dyn_null_words<<2);
+
+ for(Uint32 i= 0; i<regTabPtr->m_no_of_attributes; i++)
+ {
+ Uint32 attrDescriptor= *tabDesc++;
+ Uint32 attrDes2= *tabDesc;
+ Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
+ Uint32 dynattr= AttributeDescriptor::getDynamic(attrDescriptor);
+ Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
+ Uint32 arr= AttributeDescriptor::getArrayType(attrDescriptor);
+ Uint32 size_in_words= AttributeDescriptor::getSizeInWords(attrDescriptor);
+ Uint32 size_in_bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ Uint32 extType = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 nullable= AttributeDescriptor::getNullable(attrDescriptor);
+ Uint32 off;
+
+ if(!nullable)
+ regTabPtr->notNullAttributeMask.set(i);
+ if (!dynattr)
+ {
+ if(arr == NDB_ARRAYTYPE_FIXED)
+ {
+ if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT)
+ regTabPtr->blobAttributeMask.set(i);
+
+ if (attrLen!=0)
+ {
+ off= fix_size[ind] + pos[ind];
+ fix_size[ind]+= size_in_words;
+ }
+ else
+ off= 0; // Bit type
+ }
+ else
+ {
+ /* Static varsize. */
+ ndbassert(ind==MM);
+ off= statvar_count++;
+ var_size[ind]+= size_in_bytes;
+ }
+ }
+ else
+ {
+ /* Dynamic attribute. */
+ ndbassert(ind==MM);
+ ndbrequire(extType != NDB_TYPE_BLOB && extType != NDB_TYPE_TEXT);
+ Uint32 null_pos= AttributeOffset::getNullFlagPos(attrDes2);
+ dyn_size[ind]+= (size_in_words<<2);
+ if(arr == NDB_ARRAYTYPE_FIXED)
+ {
+ if (attrLen!=0)
+ {
+ off= dynfix_count++ + regTabPtr->m_attributes[ind].m_no_of_dyn_var;
+ while(size_in_words-- > 0)
+ dynSetBit(regTabPtr->dynFixSizeMask, null_pos++);
+ }
+ else
+ off= 0; // Bit type
+ }
+ else
+ {
+ off= dynvar_count++;
+ dynSetBit(regTabPtr->dynVarSizeMask, null_pos);
+ }
+ }
+ AttributeOffset::setOffset(attrDes2, off);
+ *tabDesc++= attrDes2;
+ }
+ ndbassert(dynvar_count==regTabPtr->m_attributes[MM].m_no_of_dyn_var);
+ ndbassert(dynfix_count==regTabPtr->m_attributes[MM].m_no_of_dyn_fix);
+ ndbassert(statvar_count==regTabPtr->m_attributes[MM].m_no_of_varsize);
+
+ regTabPtr->m_offsets[MM].m_fix_header_size=
+ fix_size[MM] + pos[MM];
+ regTabPtr->m_offsets[DD].m_fix_header_size=
+ fix_size[DD] + pos[DD];
+
+ if((regTabPtr->m_attributes[MM].m_no_of_varsize +
+ regTabPtr->m_attributes[MM].m_no_of_dynamic) == 0)
+ regTabPtr->m_offsets[MM].m_fix_header_size += Tuple_header::HeaderSize;
+
+ if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0 &&
+ regTabPtr->m_attributes[DD].m_no_of_fixsize > 0)
+ regTabPtr->m_offsets[DD].m_fix_header_size += Tuple_header::HeaderSize;
+
+ Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
+ Uint32 mm_dyns= regTabPtr->m_attributes[MM].m_no_of_dynamic;
+ Uint32 dd_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
+ Uint32 dd_dyns= regTabPtr->m_attributes[DD].m_no_of_dynamic;
+
+ regTabPtr->m_offsets[MM].m_max_var_offset= var_size[MM];
+ /*
+ Size of the expanded dynamic part. Needs room for bitmap, (N+1) 16-bit
+ offset words with 32-bit padding, and all attribute data.
+ */
+ regTabPtr->m_offsets[MM].m_max_dyn_offset=
+ (regTabPtr->m_offsets[MM].m_dyn_null_words<<2) + 4*((mm_dyns+2)>>1) +
+ dyn_size[MM];
+
+ regTabPtr->m_offsets[DD].m_max_var_offset= var_size[DD];
+ regTabPtr->m_offsets[DD].m_max_dyn_offset=
+ (regTabPtr->m_offsets[DD].m_dyn_null_words<<2) + 4*((dd_dyns+2)>>1) +
+ dyn_size[DD];
+
+ /* Room for data for all the attributes. */
+ Uint32 total_rec_size=
+ pos[MM] + fix_size[MM] + pos[DD] + fix_size[DD] +
+ ((var_size[MM] + 3) >> 2) + ((dyn_size[MM] + 3) >> 2) +
+ ((var_size[DD] + 3) >> 2) + ((dyn_size[DD] + 3) >> 2);
+ /*
+ Room for offset arrays and dynamic bitmaps. There is one extra 16-bit
+ offset in each offset array (for easy computation of final length).
+ Also one word for storing total length of varsize+dynamic part
+ */
+ if(mm_vars + mm_dyns)
+ {
+ total_rec_size+= (mm_vars + 2) >> 1;
+ total_rec_size+= regTabPtr->m_offsets[MM].m_dyn_null_words;
+ total_rec_size+= (mm_dyns + 2) >> 1;
+ total_rec_size+= 1;
+ }
+ /* Disk data varsize offset array (not currently used). */
+ if(dd_vars)
+ total_rec_size+= (dd_vars + 2) >> 1;
+ /* Room for the header. */
+ total_rec_size+= Tuple_header::HeaderSize;
+ if(regTabPtr->m_no_of_disk_attributes)
+ total_rec_size+= Tuple_header::HeaderSize;
+ regTabPtr->total_rec_size= total_rec_size;
+
+ setUpQueryRoutines(regTabPtr);
+ setUpKeyArray(regTabPtr);
+}
+
+void
Dbtup::undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused)
{
FragrecordPtr regFragPtr;
@@ -806,6 +1164,16 @@ void Dbtup::setUpDescriptorReferences(Ui
regTabPtr->m_real_order_descriptor = descriptorReference + offset[5];
}
+void Dbtup::setupDynDescriptorReferences(Uint32 dynDescr,
+ Tablerec* const regTabPtr,
+ const Uint32* offset)
+{
+ regTabPtr->dynTabDescriptor= dynDescr;
+ Uint32* desc= &tableDescriptor[dynDescr].tabDescr;
+ regTabPtr->dynVarSizeMask= desc+offset[0];
+ regTabPtr->dynFixSizeMask= desc+offset[1];
+}
+
Uint32
Dbtup::sizeOfReadFunction()
{
@@ -944,6 +1312,12 @@ void Dbtup::releaseFragoperrec(Fragoperr
cfirstfreeFragopr = fragOperPtr.i;
}//Dbtup::releaseFragoperrec()
+void Dbtup::releaseAlterTabOpRec(AlterTabOperationPtr regAlterTabOpPtr)
+{
+ regAlterTabOpPtr.p->nextAlterTabOp= cfirstfreeAlterTabOp;
+ cfirstfreeAlterTabOp= regAlterTabOpPtr.i;
+}
+
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
{
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
@@ -1002,7 +1376,10 @@ void Dbtup::releaseTabDescr(Tablerec* co
if (descriptor != RNIL) {
ljam();
Uint32 offset[10];
- getTabDescrOffsets(regTabPtr, offset);
+ getTabDescrOffsets(regTabPtr->m_no_of_attributes,
+ regTabPtr->noOfCharsets,
+ regTabPtr->noOfKeyAttr,
+ offset);
regTabPtr->tabDescriptor= RNIL;
regTabPtr->readKeyArray= RNIL;
@@ -1012,6 +1389,21 @@ void Dbtup::releaseTabDescr(Tablerec* co
// move to start of descriptor
descriptor -= offset[3];
+ Uint32 retNo= getTabDescrWord(descriptor + ZTD_DATASIZE);
+ ndbrequire(getTabDescrWord(descriptor + ZTD_HEADER) == ZTD_TYPE_NORMAL);
+ ndbrequire(retNo == getTabDescrWord((descriptor + retNo) - ZTD_TR_SIZE));
+ ndbrequire(ZTD_TYPE_NORMAL ==
+ getTabDescrWord((descriptor + retNo) - ZTD_TR_TYPE));
+ freeTabDescr(descriptor, retNo);
+ }
+
+ descriptor= regTabPtr->dynTabDescriptor;
+ if(descriptor != RNIL)
+ {
+ ljam();
+ regTabPtr->dynTabDescriptor= RNIL;
+ regTabPtr->dynVarSizeMask= NULL;
+ regTabPtr->dynFixSizeMask= NULL;
Uint32 retNo= getTabDescrWord(descriptor + ZTD_DATASIZE);
ndbrequire(getTabDescrWord(descriptor + ZTD_HEADER) == ZTD_TYPE_NORMAL);
ndbrequire(retNo == getTabDescrWord((descriptor + retNo) - ZTD_TR_SIZE));
--- 1.5/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp 2006-11-07 09:46:08 +01:00
+++ 1.6/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp 2006-11-07 09:46:08 +01:00
@@ -35,7 +35,8 @@
*/
Uint32
-Dbtup::getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset)
+Dbtup::getTabDescrOffsets(Uint32 noOfAttrs, Uint32 noOfCharsets,
+ Uint32 noOfKeyAttr, Uint32* offset)
{
// belongs to configure.in
unsigned sizeOfPointer = sizeof(CHARSET_INFO*);
@@ -45,21 +46,33 @@ Dbtup::getTabDescrOffsets(const Tablerec
Uint32 allocSize = 0;
// magically aligned to 8 bytes
offset[0] = allocSize += ZTD_SIZE;
- offset[1] = allocSize += regTabPtr->m_no_of_attributes* sizeOfReadFunction();
- offset[2] = allocSize += regTabPtr->m_no_of_attributes* sizeOfReadFunction();
- offset[3] = allocSize += regTabPtr->noOfCharsets * sizeOfPointer;
- offset[4] = allocSize += regTabPtr->noOfKeyAttr;
- offset[5] = allocSize += regTabPtr->m_no_of_attributes * ZAD_SIZE;
- offset[6] = allocSize += (regTabPtr->m_no_of_attributes + 1) >> 1; // real
order
+ offset[1] = allocSize += noOfAttrs * sizeOfReadFunction();
+ offset[2] = allocSize += noOfAttrs * sizeOfReadFunction();
+ offset[3] = allocSize += noOfCharsets * sizeOfPointer;
+ offset[4] = allocSize += noOfKeyAttr;
+ offset[5] = allocSize += noOfAttrs * ZAD_SIZE;
+ offset[6] = allocSize += (noOfAttrs+1) >> 1; // real order
allocSize += ZTD_TRAILER_SIZE;
// return number of words
return allocSize;
}
-Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset)
+Uint32
+Dbtup::getDynTabDescrOffsets(Uint32 MaskSize, Uint32* offset)
+{
+ // do in layout order and return offsets (see DbtupMeta.cpp)
+ Uint32 allocSize= 0;
+ offset[0]= allocSize += ZTD_SIZE;
+ offset[1]= allocSize += MaskSize;
+ offset[2]= allocSize += MaskSize;
+ allocSize+= ZTD_TRAILER_SIZE;
+ // return number of words
+ return allocSize;
+}
+
+Uint32 Dbtup::allocTabDescr(Uint32 allocSize)
{
Uint32 reference = RNIL;
- Uint32 allocSize = getTabDescrOffsets(regTabPtr, offset);
/* ---------------------------------------------------------------- */
/* ALWAYS ALLOCATE A MULTIPLE OF 16 WORDS */
/* ---------------------------------------------------------------- */
@@ -280,7 +293,10 @@ Dbtup::verifytabdes()
ptrAss(ptr, tablerec);
if (ptr.p->tableStatus == DEFINED) {
Uint32 offset[10];
- const Uint32 alloc = getTabDescrOffsets(ptr.p, offset);
+ const Uint32 alloc = getTabDescrOffsets(ptr.p->m_no_of_attributes,
+ ptr.p->noOfCharsets,
+ ptr.p->noOfKeyAttr,
+ offset);
const Uint32 desc = ptr.p->readKeyArray - offset[3];
Uint32 size = alloc;
if (size % ZTD_FREE_SIZE != 0)
--- 1.10/storage/ndb/src/kernel/vm/DLFifoList.hpp 2006-11-07 09:46:08 +01:00
+++ 1.11/storage/ndb/src/kernel/vm/DLFifoList.hpp 2006-11-07 09:46:08 +01:00
@@ -83,14 +83,14 @@ public:
/**
* Update ptr to first element in list
*
- * Return i
+ * Return true if ok, false if empty
*/
bool first(Ptr<T> &) const ;
/**
* Update ptr to first element in list
*
- * Return i
+ * Return true if ok, false if empty
*/
bool last(Ptr<T> &) const ;
--- 1.154/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2006-11-07 09:46:08 +01:00
+++ 1.155/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2006-11-07 09:46:08 +01:00
@@ -2360,6 +2360,7 @@ NdbDictInterface::compChangeMask(const N
const NdbTableImpl &impl,
Uint32 &change_mask)
{
+ bool found_varpart;
change_mask= 0;
/* These are the supported properties that may be altered. */
@@ -2380,6 +2381,7 @@ NdbDictInterface::compChangeMask(const N
AlterTableReq::setTsFlag(change_mask, true);
/* No other property can be changed in alter table. */
+ Uint32 old_sz= old_impl.m_columns.size();
Uint32 sz= impl.m_columns.size();
if(impl.m_fragmentCount != old_impl.m_fragmentCount ||
impl.m_logging != old_impl.m_logging ||
@@ -2400,18 +2402,47 @@ NdbDictInterface::compChangeMask(const N
impl.m_tablespace_version != old_impl.m_tablespace_version ||
impl.m_id != old_impl.m_id ||
impl.m_version != old_impl.m_version ||
- sz != old_impl.m_columns.size())
+ sz < old_sz)
goto invalid_alter_table;
/*
- Also check that all columns are the same.
- Later, when we implement online add column, we will still check that
- columns are equal, but will allow additional columns in the new table.
+ Check for new columns.
+ We can add one or more new columns at the end, with some restrictions:
+ - All existing columns must be unchanged.
+ - The new column must be dynamic.
+ - The new column must be memory based.
+ - The new column can not be a primary key or distribution key.
+ - There must already be at least one existing memory-stored dynamic or
+ variable-sized column (so that the varpart is already allocated).
*/
- for(Uint32 i= 0; i<sz; i++)
+ found_varpart= false;
+ for(Uint32 i= 0; i<old_sz; i++)
{
- if(!impl.m_columns[i]->equal(*(old_impl.m_columns[i])))
+ const NdbColumnImpl *col= impl.m_columns[i];
+ if(!col->equal(*(old_impl.m_columns[i])))
goto invalid_alter_table;
+ if(col->m_storageType == NDB_STORAGETYPE_MEMORY &&
+ (col->m_dynamic || col->m_arrayType != NDB_ARRAYTYPE_FIXED))
+ found_varpart= true;
+ }
+
+ if(sz > old_sz)
+ {
+ if(!found_varpart)
+ goto invalid_alter_table;
+
+ for(Uint32 i=old_sz; i<sz; i++)
+ {
+ const NdbColumnImpl *col= impl.m_columns[i];
+ if(!col->m_dynamic ||
+ col->m_storageType == NDB_STORAGETYPE_DISK ||
+ col->m_pk ||
+ col->m_distributionKey ||
+ col->m_autoIncrement // ToDo: allow this?
+ )
+ goto invalid_alter_table;
+ }
+ AlterTableReq::setAddAttrFlag(change_mask, true);
}
return 0;
| Thread |
|---|
| • bk commit into 5.1 tree (knielsen:1.2328) | knielsen | 7 Nov |