1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-29 00:08:14 +03:00
Files
mariadb/ndb/src/ndbapi/NdbDictionaryImpl.cpp
unknown 9b55605460 wl1504 - scan using distribution key and EQ_BOUND
ndb/include/kernel/signaldata/ScanTab.hpp:
  Add distribution key to ScanTab to enable scanning of specific fragment
ndb/include/ndbapi/NdbOperation.hpp:
  New methods for controlling distribution/partitioning
ndb/include/ndbapi/NdbScanOperation.hpp:
  New methods for controlling distribution/partitioning
ndb/src/kernel/blocks/dbdih/DbdihMain.cpp:
  Don't mask away kvalue from hash while computing fragId
ndb/src/kernel/blocks/dbtc/DbtcMain.cpp:
  Add distribution key to ScanTab to enable scanning of specific fragment
ndb/src/ndbapi/NdbBlob.cpp:
  removed m_sizeOfKeysInWords which was the same a m_keyLenInWords
ndb/src/ndbapi/NdbConnection.cpp:
  removed explicit cast
ndb/src/ndbapi/NdbDictionaryImpl.cpp:
  removed m_sizeOfKeysInWords which was the same a m_keyLenInWords
ndb/src/ndbapi/NdbDictionaryImpl.hpp:
  removed m_sizeOfKeysInWords which was the same a m_keyLenInWords
ndb/src/ndbapi/NdbIndexOperation.cpp:
  removed theFirstKEYINFO and replaced that with theTCREQ->next
ndb/src/ndbapi/NdbOperation.cpp:
  removed theFirstKEYINFO and replaced that with theTCREQ->next
ndb/src/ndbapi/NdbOperationExec.cpp:
  removed theFirstKEYINFO and replaced that with theTCREQ->next
ndb/src/ndbapi/NdbOperationSearch.cpp:
  removed theFirstKEYINFO and replaced that with theTCREQ->next
  Enable partition scan
ndb/src/ndbapi/NdbScanOperation.cpp:
  removed theFirstKEYINFO and replaced that with theTCREQ->next
  Enable partition scan
2004-11-01 23:23:26 +01:00

2988 lines
78 KiB
C++

/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "NdbDictionaryImpl.hpp"
#include "API.hpp"
#include <NdbOut.hpp>
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include <signaldata/GetTabInfo.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/CreateTable.hpp>
#include <signaldata/CreateIndx.hpp>
#include <signaldata/CreateEvnt.hpp>
#include <signaldata/SumaImpl.hpp>
#include <signaldata/DropTable.hpp>
#include <signaldata/AlterTable.hpp>
#include <signaldata/DropIndx.hpp>
#include <signaldata/ListTables.hpp>
#include <SimpleProperties.hpp>
#include <Bitmask.hpp>
#include <AttributeList.hpp>
#include <NdbEventOperation.hpp>
#include "NdbEventOperationImpl.hpp"
#include "NdbBlob.hpp"
#include <AttributeHeader.hpp>
#include <my_sys.h>
#define DEBUG_PRINT 0
#define INCOMPATIBLE_VERSION -2
//#define EVENT_DEBUG
/**
* Column
*/
NdbColumnImpl::NdbColumnImpl()
: NdbDictionary::Column(* this), m_facade(this)
{
init();
}
NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
: NdbDictionary::Column(* this), m_facade(&f)
{
init();
}
NdbColumnImpl&
NdbColumnImpl::operator=(const NdbColumnImpl& col)
{
m_attrId = col.m_attrId;
m_name = col.m_name;
m_type = col.m_type;
m_precision = col.m_precision;
m_cs = col.m_cs;
m_scale = col.m_scale;
m_length = col.m_length;
m_pk = col.m_pk;
m_distributionKey = col.m_distributionKey;
m_nullable = col.m_nullable;
m_autoIncrement = col.m_autoIncrement;
m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
m_defaultValue = col.m_defaultValue;
m_attrType = col.m_attrType;
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
m_keyInfoPos = col.m_keyInfoPos;
m_blobTable = col.m_blobTable;
// Do not copy m_facade !!
return *this;
}
void
NdbColumnImpl::init(Type t)
{
// do not use default_charset_info as it may not be initialized yet
// use binary collation until NDB tests can handle charsets
CHARSET_INFO* default_cs = &my_charset_latin1_bin;
m_attrId = -1;
m_type = t;
switch (m_type) {
case Tinyint:
case Tinyunsigned:
case Smallint:
case Smallunsigned:
case Mediumint:
case Mediumunsigned:
case Int:
case Unsigned:
case Bigint:
case Bigunsigned:
case Float:
case Double:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
break;
case Decimal:
m_precision = 10;
m_scale = 0;
m_length = 1;
m_cs = NULL;
break;
case Char:
case Varchar:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = default_cs;
break;
case Binary:
case Varbinary:
case Datetime:
case Timespec:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
break;
case Blob:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = NULL;
break;
case Text:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = default_cs;
break;
case Undefined:
assert(false);
break;
}
m_pk = false;
m_nullable = false;
m_distributionKey = false;
m_keyInfoPos = 0;
// next 2 are set at run time
m_attrSize = 0;
m_arraySize = 0;
m_autoIncrement = false;
m_autoIncrementInitialValue = 1;
m_blobTable = NULL;
}
NdbColumnImpl::~NdbColumnImpl()
{
}
bool
NdbColumnImpl::equal(const NdbColumnImpl& col) const
{
if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
return false;
}
if(m_type != col.m_type){
return false;
}
if(m_pk != col.m_pk){
return false;
}
if(m_nullable != col.m_nullable){
return false;
}
if(m_pk){
if(m_distributionKey != col.m_distributionKey){
return false;
}
}
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length ||
m_cs != col.m_cs) {
return false;
}
if (m_autoIncrement != col.m_autoIncrement){
return false;
}
if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
return false;
}
return true;
}
NdbDictionary::Column *
NdbColumnImpl::create_psuedo(const char * name){
NdbDictionary::Column * col = new NdbDictionary::Column();
col->setName(name);
if(!strcmp(name, "NDB$FRAGMENT")){
col->setType(NdbDictionary::Column::Unsigned);
col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
col->m_impl.m_attrSize = 4;
col->m_impl.m_arraySize = 1;
} else if(!strcmp(name, "NDB$ROW_COUNT")){
col->setType(NdbDictionary::Column::Bigunsigned);
col->m_impl.m_attrId = AttributeHeader::ROW_COUNT;
col->m_impl.m_attrSize = 8;
col->m_impl.m_arraySize = 1;
} else if(!strcmp(name, "NDB$COMMIT_COUNT")){
col->setType(NdbDictionary::Column::Bigunsigned);
col->m_impl.m_attrId = AttributeHeader::COMMIT_COUNT;
col->m_impl.m_attrSize = 8;
col->m_impl.m_arraySize = 1;
} else {
abort();
}
return col;
}
/**
* NdbTableImpl
*/
NdbTableImpl::NdbTableImpl()
: NdbDictionary::Table(* this), m_facade(this)
{
init();
}
NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
: NdbDictionary::Table(* this), m_facade(&f)
{
init();
}
NdbTableImpl::~NdbTableImpl()
{
if (m_index != 0) {
delete m_index;
m_index = 0;
}
for (unsigned i = 0; i < m_columns.size(); i++)
delete m_columns[i];
}
void
NdbTableImpl::init(){
clearNewProperties();
m_frm.clear();
m_fragmentType = NdbDictionary::Object::FragAllMedium;
m_logging = true;
m_kvalue = 6;
m_minLoadFactor = 78;
m_maxLoadFactor = 80;
m_index = 0;
m_indexType = NdbDictionary::Index::Undefined;
m_noOfKeys = 0;
m_noOfDistributionKeys = 0;
m_fragmentCount = 0;
m_keyLenInWords = 0;
m_noOfBlobs = 0;
}
bool
NdbTableImpl::equal(const NdbTableImpl& obj) const
{
if ((m_internalName.c_str() == NULL) ||
(strcmp(m_internalName.c_str(), "") == 0) ||
(obj.m_internalName.c_str() == NULL) ||
(strcmp(obj.m_internalName.c_str(), "") == 0)) {
// Shallow equal
if(strcmp(getName(), obj.getName()) != 0){
return false;
}
} else
// Deep equal
if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
return false;
}
if(m_fragmentType != obj.m_fragmentType){
return false;
}
if(m_columns.size() != obj.m_columns.size()){
return false;
}
for(unsigned i = 0; i<obj.m_columns.size(); i++){
if(!m_columns[i]->equal(* obj.m_columns[i])){
return false;
}
}
if(m_logging != obj.m_logging){
return false;
}
if(m_kvalue != obj.m_kvalue){
return false;
}
if(m_minLoadFactor != obj.m_minLoadFactor){
return false;
}
if(m_maxLoadFactor != obj.m_maxLoadFactor){
return false;
}
return true;
}
void
NdbTableImpl::assign(const NdbTableImpl& org)
{
m_tableId = org.m_tableId;
m_internalName.assign(org.m_internalName);
m_externalName.assign(org.m_externalName);
m_newExternalName.assign(org.m_newExternalName);
m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
m_fragmentType = org.m_fragmentType;
m_fragmentCount = org.m_fragmentCount;
for(unsigned i = 0; i<org.m_columns.size(); i++){
NdbColumnImpl * col = new NdbColumnImpl();
const NdbColumnImpl * iorg = org.m_columns[i];
(* col) = (* iorg);
m_columns.push_back(col);
}
m_logging = org.m_logging;
m_kvalue = org.m_kvalue;
m_minLoadFactor = org.m_minLoadFactor;
m_maxLoadFactor = org.m_maxLoadFactor;
if (m_index != 0)
delete m_index;
m_index = org.m_index;
m_noOfDistributionKeys = org.m_noOfDistributionKeys;
m_noOfKeys = org.m_noOfKeys;
m_keyLenInWords = org.m_keyLenInWords;
m_noOfBlobs = org.m_noOfBlobs;
m_version = org.m_version;
m_status = org.m_status;
}
void NdbTableImpl::setName(const char * name)
{
m_newExternalName.assign(name);
}
const char *
NdbTableImpl::getName() const
{
if (m_newExternalName.empty())
return m_externalName.c_str();
else
return m_newExternalName.c_str();
}
void NdbTableImpl::clearNewProperties()
{
m_newExternalName.assign("");
m_changeMask = 0;
}
void NdbTableImpl::copyNewProperties()
{
if (!m_newExternalName.empty()) {
m_externalName.assign(m_newExternalName);
AlterTableReq::setNameFlag(m_changeMask, true);
}
}
void
NdbTableImpl::buildColumnHash(){
const Uint32 size = m_columns.size();
int i;
for(i = 31; i >= 0; i--){
if(((1 << i) & size) != 0){
m_columnHashMask = (1 << (i + 1)) - 1;
break;
}
}
Vector<Uint32> hashValues;
Vector<Vector<Uint32> > chains; chains.fill(size, hashValues);
for(i = 0; i< (int) size; i++){
Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE;
Uint32 bucket = hv & m_columnHashMask;
bucket = (bucket < size ? bucket : bucket - size);
assert(bucket < size);
hashValues.push_back(hv);
chains[bucket].push_back(i);
}
m_columnHash.clear();
Uint32 tmp = 1;
m_columnHash.fill((unsigned)size-1, tmp); // Default no chaining
Uint32 pos = 0; // In overflow vector
for(i = 0; i< (int) size; i++){
Uint32 sz = chains[i].size();
if(sz == 1){
Uint32 col = chains[i][0];
Uint32 hv = hashValues[col];
Uint32 bucket = hv & m_columnHashMask;
bucket = (bucket < size ? bucket : bucket - size);
m_columnHash[bucket] = (col << 16) | hv | 1;
} else if(sz > 1){
Uint32 col = chains[i][0];
Uint32 hv = hashValues[col];
Uint32 bucket = hv & m_columnHashMask;
bucket = (bucket < size ? bucket : bucket - size);
m_columnHash[bucket] = (sz << 16) | (((size - bucket) + pos) << 1);
for(size_t j = 0; j<sz; j++, pos++){
Uint32 col = chains[i][j];
Uint32 hv = hashValues[col];
m_columnHash.push_back((col << 16) | hv);
}
}
}
m_columnHash.push_back(0); // Overflow when looping in end of array
#if 0
for(size_t i = 0; i<m_columnHash.size(); i++){
Uint32 tmp = m_columnHash[i];
int col = -1;
if(i < size && (tmp & 1) == 1){
col = (tmp >> 16);
} else if(i >= size){
col = (tmp >> 16);
}
ndbout_c("m_columnHash[%d] %s = %x",
i, col > 0 ? m_columns[col]->getName() : "" , m_columnHash[i]);
}
#endif
}
/**
* NdbIndexImpl
*/
NdbIndexImpl::NdbIndexImpl() :
NdbDictionary::Index(* this),
m_facade(this)
{
m_logging = true;
}
NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
NdbDictionary::Index(* this),
m_facade(&f)
{
m_logging = true;
}
NdbIndexImpl::~NdbIndexImpl(){
for (unsigned i = 0; i < m_columns.size(); i++)
delete m_columns[i];
}
void NdbIndexImpl::setName(const char * name)
{
m_externalName.assign(name);
}
const char *
NdbIndexImpl::getName() const
{
return m_externalName.c_str();
}
void
NdbIndexImpl::setTable(const char * table)
{
m_tableName.assign(table);
}
const char *
NdbIndexImpl::getTable() const
{
return m_tableName.c_str();
}
const NdbTableImpl *
NdbIndexImpl::getIndexTable() const
{
return m_table;
}
/**
* NdbEventImpl
*/
NdbEventImpl::NdbEventImpl() :
NdbDictionary::Event(* this),
m_facade(this)
{
mi_type = 0;
m_dur = NdbDictionary::Event::ED_UNDEFINED;
eventOp = NULL;
m_tableImpl = NULL;
}
NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
NdbDictionary::Event(* this),
m_facade(&f)
{
mi_type = 0;
m_dur = NdbDictionary::Event::ED_UNDEFINED;
eventOp = NULL;
m_tableImpl = NULL;
}
NdbEventImpl::~NdbEventImpl()
{
for (unsigned i = 0; i < m_columns.size(); i++)
delete m_columns[i];
}
void NdbEventImpl::setName(const char * name)
{
m_externalName.assign(name);
}
void
NdbEventImpl::setTable(const char * table)
{
m_tableName.assign(table);
}
const char *
NdbEventImpl::getTable() const
{
return m_tableName.c_str();
}
const char *
NdbEventImpl::getName() const
{
return m_externalName.c_str();
}
void
NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t = NdbDictionary::Event::TE_ALL)
{
switch (t) {
case NdbDictionary::Event::TE_INSERT : mi_type |= 1; break;
case NdbDictionary::Event::TE_DELETE : mi_type |= 2; break;
case NdbDictionary::Event::TE_UPDATE : mi_type |= 4; break;
default: mi_type = 4 | 2 | 1; // all types
}
}
void
NdbEventImpl::setDurability(const NdbDictionary::Event::EventDurability d)
{
m_dur = d;
}
/**
* NdbDictionaryImpl
*/
NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb)
: NdbDictionary::Dictionary(* this),
m_facade(this),
m_receiver(m_error),
m_ndb(ndb)
{
m_globalHash = 0;
m_local_table_data_size= 0;
}
NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb,
NdbDictionary::Dictionary & f)
: NdbDictionary::Dictionary(* this),
m_facade(&f),
m_receiver(m_error),
m_ndb(ndb)
{
m_globalHash = 0;
m_local_table_data_size= 0;
}
static int f_dictionary_count = 0;
NdbDictionaryImpl::~NdbDictionaryImpl()
{
NdbElement_t<Ndb_local_table_info> * curr = m_localHash.m_tableHash.getNext(0);
if(m_globalHash){
while(curr != 0){
m_globalHash->lock();
m_globalHash->release(curr->theData->m_table_impl);
Ndb_local_table_info::destroy(curr->theData);
m_globalHash->unlock();
curr = m_localHash.m_tableHash.getNext(curr);
}
m_globalHash->lock();
if(--f_dictionary_count == 0){
delete NdbDictionary::Column::FRAGMENT;
delete NdbDictionary::Column::ROW_COUNT;
delete NdbDictionary::Column::COMMIT_COUNT;
NdbDictionary::Column::FRAGMENT= 0;
NdbDictionary::Column::ROW_COUNT= 0;
NdbDictionary::Column::COMMIT_COUNT= 0;
}
m_globalHash->unlock();
} else {
assert(curr == 0);
}
}
Ndb_local_table_info *
NdbDictionaryImpl::fetchGlobalTableImpl(const char * internalTableName)
{
NdbTableImpl *impl;
m_globalHash->lock();
impl = m_globalHash->get(internalTableName);
m_globalHash->unlock();
if (impl == 0){
impl = m_receiver.getTable(internalTableName,
m_ndb.usingFullyQualifiedNames());
m_globalHash->lock();
m_globalHash->put(internalTableName, impl);
m_globalHash->unlock();
if(impl == 0){
return 0;
}
}
Ndb_local_table_info *info=
Ndb_local_table_info::create(impl, m_local_table_data_size);
m_localHash.put(internalTableName, info);
m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
m_ndb.theLastTupleId[impl->getTableId()] = ~0;
return info;
}
#if 0
bool
NdbDictionaryImpl::setTransporter(class TransporterFacade * tf)
{
if(tf != 0){
m_globalHash = &tf->m_globalDictCache;
return m_receiver.setTransporter(tf);
}
return false;
}
#endif
bool
NdbDictionaryImpl::setTransporter(class Ndb* ndb,
class TransporterFacade * tf)
{
m_globalHash = &tf->m_globalDictCache;
if(m_receiver.setTransporter(ndb, tf)){
m_globalHash->lock();
if(f_dictionary_count++ == 0){
NdbDictionary::Column::FRAGMENT=
NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
NdbDictionary::Column::ROW_COUNT=
NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
NdbDictionary::Column::COMMIT_COUNT=
NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
}
m_globalHash->unlock();
return true;
}
return false;
}
NdbTableImpl *
NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table)
{
const char * internalName =
m_ndb.internalizeIndexName(table, index->getName());
return getTable(m_ndb.externalizeTableName(internalName));
}
#if 0
bool
NdbDictInterface::setTransporter(class TransporterFacade * tf)
{
if(tf == 0)
return false;
Guard g(tf->theMutexPtr);
m_blockNumber = tf->open(this,
execSignal,
execNodeStatus);
if ( m_blockNumber == -1 ) {
m_error.code = 4105;
return false; // no more free blocknumbers
}//if
Uint32 theNode = tf->ownId();
m_reference = numberToRef(m_blockNumber, theNode);
m_transporter = tf;
m_waiter.m_mutex = tf->theMutexPtr;
return true;
}
#endif
bool
NdbDictInterface::setTransporter(class Ndb* ndb, class TransporterFacade * tf)
{
m_reference = ndb->getReference();
m_transporter = tf;
m_waiter.m_mutex = tf->theMutexPtr;
return true;
}
NdbDictInterface::~NdbDictInterface()
{
}
void
NdbDictInterface::execSignal(void* dictImpl,
class NdbApiSignal* signal,
class LinearSectionPtr ptr[3])
{
NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
const Uint32 gsn = signal->readSignalNumber();
switch(gsn){
case GSN_GET_TABINFOREF:
tmp->execGET_TABINFO_REF(signal, ptr);
break;
case GSN_GET_TABINFO_CONF:
tmp->execGET_TABINFO_CONF(signal, ptr);
break;
case GSN_CREATE_TABLE_REF:
tmp->execCREATE_TABLE_REF(signal, ptr);
break;
case GSN_CREATE_TABLE_CONF:
tmp->execCREATE_TABLE_CONF(signal, ptr);
break;
case GSN_DROP_TABLE_REF:
tmp->execDROP_TABLE_REF(signal, ptr);
break;
case GSN_DROP_TABLE_CONF:
tmp->execDROP_TABLE_CONF(signal, ptr);
break;
case GSN_ALTER_TABLE_REF:
tmp->execALTER_TABLE_REF(signal, ptr);
break;
case GSN_ALTER_TABLE_CONF:
tmp->execALTER_TABLE_CONF(signal, ptr);
break;
case GSN_CREATE_INDX_REF:
tmp->execCREATE_INDX_REF(signal, ptr);
break;
case GSN_CREATE_INDX_CONF:
tmp->execCREATE_INDX_CONF(signal, ptr);
break;
case GSN_DROP_INDX_REF:
tmp->execDROP_INDX_REF(signal, ptr);
break;
case GSN_DROP_INDX_CONF:
tmp->execDROP_INDX_CONF(signal, ptr);
break;
case GSN_CREATE_EVNT_REF:
tmp->execCREATE_EVNT_REF(signal, ptr);
break;
case GSN_CREATE_EVNT_CONF:
tmp->execCREATE_EVNT_CONF(signal, ptr);
break;
case GSN_SUB_START_CONF:
tmp->execSUB_START_CONF(signal, ptr);
break;
case GSN_SUB_START_REF:
tmp->execSUB_START_REF(signal, ptr);
break;
case GSN_SUB_TABLE_DATA:
tmp->execSUB_TABLE_DATA(signal, ptr);
break;
case GSN_SUB_GCP_COMPLETE_REP:
tmp->execSUB_GCP_COMPLETE_REP(signal, ptr);
break;
case GSN_SUB_STOP_CONF:
tmp->execSUB_STOP_CONF(signal, ptr);
break;
case GSN_SUB_STOP_REF:
tmp->execSUB_STOP_REF(signal, ptr);
break;
case GSN_DROP_EVNT_REF:
tmp->execDROP_EVNT_REF(signal, ptr);
break;
case GSN_DROP_EVNT_CONF:
tmp->execDROP_EVNT_CONF(signal, ptr);
break;
case GSN_LIST_TABLES_CONF:
tmp->execLIST_TABLES_CONF(signal, ptr);
break;
default:
abort();
}
}
void
NdbDictInterface::execNodeStatus(void* dictImpl, Uint32 aNode,
bool alive, bool nfCompleted)
{
NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
if(!alive && !nfCompleted){
return;
}
if (!alive && nfCompleted){
tmp->m_waiter.nodeFail(aNode);
}
}
int
NdbDictInterface::dictSignal(NdbApiSignal* signal,
LinearSectionPtr ptr[3],int noLSP,
const int useMasterNodeId,
const Uint32 RETRIES,
const WaitSignalType wst,
const int theWait,
const int *errcodes,
const int noerrcodes,
const int temporaryMask)
{
DBUG_ENTER("NdbDictInterface::dictSignal");
DBUG_PRINT("enter", ("useMasterNodeId: %d", useMasterNodeId));
for(Uint32 i = 0; i<RETRIES; i++){
//if (useMasterNodeId == 0)
m_buffer.clear();
// Protected area
m_transporter->lock_mutex();
Uint32 aNodeId;
if (useMasterNodeId) {
if ((m_masterNodeId == 0) ||
(!m_transporter->get_node_alive(m_masterNodeId))) {
m_masterNodeId = m_transporter->get_an_alive_node();
}//if
aNodeId = m_masterNodeId;
} else {
aNodeId = m_transporter->get_an_alive_node();
}
if(aNodeId == 0){
m_error.code = 4009;
m_transporter->unlock_mutex();
DBUG_RETURN(-1);
}
{
int r;
if (ptr) {
#ifdef EVENT_DEBUG
printf("Long signal %d ptr", noLSP);
for (int q=0;q<noLSP;q++) {
printf(" sz %d", ptr[q].sz);
}
printf("\n");
#endif
r = m_transporter->sendFragmentedSignal(signal, aNodeId, ptr, noLSP);
} else {
#ifdef EVENT_DEBUG
printf("Short signal\n");
#endif
r = m_transporter->sendSignal(signal, aNodeId);
}
if(r != 0){
m_transporter->unlock_mutex();
continue;
}
}
m_error.code = 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = wst;
m_waiter.wait(theWait);
m_transporter->unlock_mutex();
// End of Protected area
if(m_waiter.m_state == NO_WAIT && m_error.code == 0){
// Normal return
DBUG_RETURN(0);
}
/**
* Handle error codes
*/
if(m_waiter.m_state == WAIT_NODE_FAILURE)
continue;
if ( (temporaryMask & m_error.code) != 0 ) {
continue;
}
if (errcodes) {
int doContinue = 0;
for (int j=0; j < noerrcodes; j++)
if(m_error.code == errcodes[j]) {
doContinue = 1;
continue;
}
if (doContinue)
continue;
}
DBUG_RETURN(-1);
}
DBUG_RETURN(-1);
}
/*****************************************************************
* get tab info
*/
NdbTableImpl *
NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->requestType =
GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
req->tableId = tableId;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
tSignal.theLength = GetTabInfoReq::SignalLength;
return getTable(&tSignal, 0, 0, fullyQualifiedNames);
}
NdbTableImpl *
NdbDictInterface::getTable(const char * name, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
const Uint32 strLen = strlen(name) + 1; // NULL Terminated
if(strLen > MAX_TAB_NAME_SIZE) {//sizeof(req->tableName)){
m_error.code = 4307;
return 0;
}
req->senderRef = m_reference;
req->senderData = 0;
req->requestType =
GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
req->tableNameLen = strLen;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
// tSignal.theLength = GetTabInfoReq::HeaderLength + ((strLen + 3) / 4);
tSignal.theLength = GetTabInfoReq::SignalLength;
LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)name;
ptr[0].sz = strLen;
return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
}
NdbTableImpl *
NdbDictInterface::getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames)
{
//GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, signal->getDataPtrSend());
int r = dictSignal(signal,ptr,noOfSections,
0/*do not use masternode id*/,
100,
WAIT_GET_TAB_INFO_REQ,
WAITFOR_RESPONSE_TIMEOUT,
NULL,0);
if (r) return 0;
NdbTableImpl * rt = 0;
m_error.code = parseTableInfo(&rt,
(Uint32*)m_buffer.get_data(),
m_buffer.length() / 4, fullyQualifiedNames);
rt->buildColumnHash();
return rt;
}
void
NdbDictInterface::execGET_TABINFO_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const GetTabInfoConf* conf = CAST_CONSTPTR(GetTabInfoConf, signal->getDataPtr());
if(signal->isFirstFragment()){
m_fragmentId = signal->getFragmentId();
m_buffer.grow(4 * conf->totalLen);
} else {
if(m_fragmentId != signal->getFragmentId()){
abort();
}
}
const Uint32 i = GetTabInfoConf::DICT_TAB_INFO;
m_buffer.append(ptr[i].p, 4 * ptr[i].sz);
if(!signal->isLastFragment()){
return;
}
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
m_error.code = ref->errorCode;
m_waiter.signal(NO_WAIT);
}
/*****************************************************************
* Pack/Unpack tables
*/
struct ApiKernelMapping {
Int32 kernelConstant;
Int32 apiConstant;
};
Uint32
getApiConstant(Int32 kernelConstant, const ApiKernelMapping map[], Uint32 def)
{
int i = 0;
while(map[i].kernelConstant != kernelConstant){
if(map[i].kernelConstant == -1 &&
map[i].apiConstant == -1){
return def;
}
i++;
}
return map[i].apiConstant;
}
Uint32
getKernelConstant(Int32 apiConstant, const ApiKernelMapping map[], Uint32 def)
{
int i = 0;
while(map[i].apiConstant != apiConstant){
if(map[i].kernelConstant == -1 &&
map[i].apiConstant == -1){
return def;
}
i++;
}
return map[i].kernelConstant;
}
static const
ApiKernelMapping
fragmentTypeMapping[] = {
{ DictTabInfo::AllNodesSmallTable, NdbDictionary::Object::FragAllSmall },
{ DictTabInfo::AllNodesMediumTable, NdbDictionary::Object::FragAllMedium },
{ DictTabInfo::AllNodesLargeTable, NdbDictionary::Object::FragAllLarge },
{ DictTabInfo::SingleFragment, NdbDictionary::Object::FragSingle },
{ -1, -1 }
};
static const
ApiKernelMapping
objectTypeMapping[] = {
{ DictTabInfo::SystemTable, NdbDictionary::Object::SystemTable },
{ DictTabInfo::UserTable, NdbDictionary::Object::UserTable },
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Object::UniqueHashIndex },
{ DictTabInfo::HashIndex, NdbDictionary::Object::HashIndex },
{ DictTabInfo::UniqueOrderedIndex, NdbDictionary::Object::UniqueOrderedIndex },
{ DictTabInfo::OrderedIndex, NdbDictionary::Object::OrderedIndex },
{ DictTabInfo::HashIndexTrigger, NdbDictionary::Object::HashIndexTrigger },
{ DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
{ DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
{ DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
{ -1, -1 }
};
static const
ApiKernelMapping
objectStateMapping[] = {
{ DictTabInfo::StateOffline, NdbDictionary::Object::StateOffline },
{ DictTabInfo::StateBuilding, NdbDictionary::Object::StateBuilding },
{ DictTabInfo::StateDropping, NdbDictionary::Object::StateDropping },
{ DictTabInfo::StateOnline, NdbDictionary::Object::StateOnline },
{ DictTabInfo::StateBroken, NdbDictionary::Object::StateBroken },
{ -1, -1 }
};
static const
ApiKernelMapping
objectStoreMapping[] = {
{ DictTabInfo::StoreTemporary, NdbDictionary::Object::StoreTemporary },
{ DictTabInfo::StorePermanent, NdbDictionary::Object::StorePermanent },
{ -1, -1 }
};
static const
ApiKernelMapping
indexTypeMapping[] = {
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Index::UniqueHashIndex },
{ DictTabInfo::HashIndex, NdbDictionary::Index::HashIndex },
{ DictTabInfo::UniqueOrderedIndex, NdbDictionary::Index::UniqueOrderedIndex},
{ DictTabInfo::OrderedIndex, NdbDictionary::Index::OrderedIndex },
{ -1, -1 }
};
// TODO: remove, api-kernel type codes must match now
static const
ApiKernelMapping
columnTypeMapping[] = {
{ DictTabInfo::ExtTinyint, NdbDictionary::Column::Tinyint },
{ DictTabInfo::ExtTinyunsigned, NdbDictionary::Column::Tinyunsigned },
{ DictTabInfo::ExtSmallint, NdbDictionary::Column::Smallint },
{ DictTabInfo::ExtSmallunsigned, NdbDictionary::Column::Smallunsigned },
{ DictTabInfo::ExtMediumint, NdbDictionary::Column::Mediumint },
{ DictTabInfo::ExtMediumunsigned, NdbDictionary::Column::Mediumunsigned },
{ DictTabInfo::ExtInt, NdbDictionary::Column::Int },
{ DictTabInfo::ExtUnsigned, NdbDictionary::Column::Unsigned },
{ DictTabInfo::ExtBigint, NdbDictionary::Column::Bigint },
{ DictTabInfo::ExtBigunsigned, NdbDictionary::Column::Bigunsigned },
{ DictTabInfo::ExtFloat, NdbDictionary::Column::Float },
{ DictTabInfo::ExtDouble, NdbDictionary::Column::Double },
{ DictTabInfo::ExtDecimal, NdbDictionary::Column::Decimal },
{ DictTabInfo::ExtChar, NdbDictionary::Column::Char },
{ DictTabInfo::ExtVarchar, NdbDictionary::Column::Varchar },
{ DictTabInfo::ExtBinary, NdbDictionary::Column::Binary },
{ DictTabInfo::ExtVarbinary, NdbDictionary::Column::Varbinary },
{ DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
{ DictTabInfo::ExtTimespec, NdbDictionary::Column::Timespec },
{ DictTabInfo::ExtBlob, NdbDictionary::Column::Blob },
{ DictTabInfo::ExtText, NdbDictionary::Column::Text },
{ -1, -1 }
};
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const Uint32 * data, Uint32 len,
bool fullyQualifiedNames)
{
SimplePropertiesLinearReader it(data, len);
DictTabInfo::Table tableDesc; tableDesc.init();
SimpleProperties::UnpackStatus s;
s = SimpleProperties::unpack(it, &tableDesc,
DictTabInfo::TableMapping,
DictTabInfo::TableMappingSize,
true, true);
if(s != SimpleProperties::Break){
return 703;
}
const char * internalName = tableDesc.TableName;
const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
NdbTableImpl * impl = new NdbTableImpl();
impl->m_tableId = tableDesc.TableId;
impl->m_version = tableDesc.TableVersion;
impl->m_status = NdbDictionary::Object::Retrieved;
impl->m_internalName.assign(internalName);
impl->m_externalName.assign(externalName);
impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen);
impl->m_fragmentType = (NdbDictionary::Object::FragmentType)
getApiConstant(tableDesc.FragmentType,
fragmentTypeMapping,
(Uint32)NdbDictionary::Object::FragUndefined);
impl->m_logging = tableDesc.TableLoggedFlag;
impl->m_kvalue = tableDesc.TableKValue;
impl->m_minLoadFactor = tableDesc.MinLoadFactor;
impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
impl->m_fragmentCount = tableDesc.FragmentCount;
impl->m_indexType = (NdbDictionary::Index::Type)
getApiConstant(tableDesc.TableType,
indexTypeMapping,
NdbDictionary::Index::Undefined);
if(impl->m_indexType == NdbDictionary::Index::Undefined){
} else {
const char * externalPrimary =
Ndb::externalizeTableName(tableDesc.PrimaryTable, fullyQualifiedNames);
impl->m_primaryTable.assign(externalPrimary);
}
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
Uint32 blobCount = 0;
Uint32 distKeys = 0;
for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
s = SimpleProperties::unpack(it,
&attrDesc,
DictTabInfo::AttributeMapping,
DictTabInfo::AttributeMappingSize,
true, true);
if(s != SimpleProperties::Break){
delete impl;
return 703;
}
NdbColumnImpl * col = new NdbColumnImpl();
col->m_attrId = attrDesc.AttributeId;
col->setName(attrDesc.AttributeName);
col->m_type = (NdbDictionary::Column::Type)
getApiConstant(attrDesc.AttributeExtType,
columnTypeMapping,
NdbDictionary::Column::Undefined);
if (col->m_type == NdbDictionary::Column::Undefined) {
delete impl;
return 703;
}
col->m_extType = attrDesc.AttributeExtType;
col->m_precision = (attrDesc.AttributeExtPrecision & 0xFFFF);
col->m_scale = attrDesc.AttributeExtScale;
col->m_length = attrDesc.AttributeExtLength;
// charset in upper half of precision
unsigned cs_number = (attrDesc.AttributeExtPrecision >> 16);
// charset is defined exactly for char types
if (col->getCharType() != (cs_number != 0)) {
delete impl;
return 703;
}
if (col->getCharType()) {
col->m_cs = get_charset(cs_number, MYF(0));
if (col->m_cs == NULL) {
delete impl;
return 743;
}
}
// translate to old kernel types and sizes
if (! attrDesc.translateExtType()) {
delete impl;
return 703;
}
col->m_attrType =attrDesc.AttributeType;
col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
col->m_arraySize = attrDesc.AttributeArraySize;
col->m_pk = attrDesc.AttributeKeyFlag;
col->m_distributionKey = attrDesc.AttributeDKey;
col->m_nullable = attrDesc.AttributeNullableFlag;
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
if(attrDesc.AttributeKeyFlag){
col->m_keyInfoPos = keyInfoPos + 1;
keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
keyCount++;
if(attrDesc.AttributeDKey)
distKeys++;
} else {
col->m_keyInfoPos = 0;
}
if (col->getBlobType())
blobCount++;
NdbColumnImpl * null = 0;
impl->m_columns.fill(attrDesc.AttributeId, null);
if(impl->m_columns[attrDesc.AttributeId] != 0){
delete col;
delete impl;
return 703;
}
impl->m_columns[attrDesc.AttributeId] = col;
it.next();
}
impl->m_noOfKeys = keyCount;
impl->m_keyLenInWords = keyInfoPos;
impl->m_noOfBlobs = blobCount;
impl->m_noOfDistributionKeys = distKeys;
* ret = impl;
return 0;
}
/*****************************************************************
* Create table and alter table
*/
int
NdbDictionaryImpl::createTable(NdbTableImpl &t)
{
if (m_receiver.createTable(m_ndb, t) != 0)
return -1;
if (t.m_noOfBlobs == 0)
return 0;
// update table def from DICT
Ndb_local_table_info *info=
get_local_table_info(t.m_internalName.c_str(),false);
if (info == NULL) {
m_error.code = 709;
return -1;
}
if (createBlobTables(*(info->m_table_impl)) != 0) {
int save_code = m_error.code;
(void)dropTable(t);
m_error.code = save_code;
return -1;
}
return 0;
}
int
NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
{
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
NdbTableImpl bt;
NdbBlob::getBlobTable(bt, &t, &c);
if (createTable(bt) != 0)
return -1;
// Save BLOB table handle
Ndb_local_table_info *info=
get_local_table_info(bt.m_internalName.c_str(),false);
if (info == 0) {
return -1;
}
c.m_blobTable = info->m_table_impl;
}
return 0;
}
int
NdbDictionaryImpl::addBlobTables(NdbTableImpl &t)
{
unsigned n= t.m_noOfBlobs;
// optimized for blob column being the last one
// and not looking for more than one if not neccessary
for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
i--;
NdbColumnImpl & c = *t.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
n--;
char btname[NdbBlob::BlobTableNameSize];
NdbBlob::getBlobTableName(btname, &t, &c);
// Save BLOB table handle
NdbTableImpl * cachedBlobTable = getTable(btname);
if (cachedBlobTable == 0) {
return -1;
}
c.m_blobTable = cachedBlobTable;
}
return 0;
}
int
NdbDictInterface::createTable(Ndb & ndb,
NdbTableImpl & impl)
{
return createOrAlterTable(ndb, impl, false);
}
int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
{
BaseString internalName = impl.m_internalName;
const char * originalInternalName = internalName.c_str();
BaseString externalName = impl.m_externalName;
const char * originalExternalName = externalName.c_str();
NdbTableImpl * oldTab = getTable(originalExternalName);
if(!oldTab){
m_error.code = 709;
return -1;
}
// Alter the table
int ret = m_receiver.alterTable(m_ndb, impl);
if(ret == 0){
// Remove cached information and let it be refreshed at next access
if (m_localHash.get(originalInternalName) != NULL) {
m_localHash.drop(originalInternalName);
m_globalHash->lock();
NdbTableImpl * cachedImpl = m_globalHash->get(originalInternalName);
// If in local cache it must be in global
if (!cachedImpl)
abort();
m_globalHash->drop(cachedImpl);
m_globalHash->unlock();
}
}
return ret;
}
int
NdbDictInterface::alterTable(Ndb & ndb,
NdbTableImpl & impl)
{
return createOrAlterTable(ndb, impl, true);
}
int
NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbTableImpl & impl,
bool alter)
{
unsigned i;
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
m_error.code = 4317;
return -1;
}
unsigned sz = impl.m_columns.size();
if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
m_error.code = 4318;
return -1;
}
impl.copyNewProperties();
//validate();
//aggregate();
const char * internalName =
ndb.internalizeTableName(impl.m_externalName.c_str());
impl.m_internalName.assign(internalName);
UtilBufferWriter w(m_buffer);
DictTabInfo::Table tmpTab; tmpTab.init();
BaseString::snprintf(tmpTab.TableName,
sizeof(tmpTab.TableName),
internalName);
bool haveAutoIncrement = false;
Uint64 autoIncrementValue = 0;
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
if (col->m_autoIncrement) {
if (haveAutoIncrement) {
m_error.code = 4335;
return -1;
}
haveAutoIncrement = true;
autoIncrementValue = col->m_autoIncrementInitialValue;
}
}
// Check max length of frm data
if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
m_error.code = 1229;
return -1;
}
tmpTab.FrmLen = impl.m_frm.length();
memcpy(tmpTab.FrmData, impl.m_frm.get_data(), impl.m_frm.length());
tmpTab.TableLoggedFlag = impl.m_logging;
tmpTab.TableKValue = impl.m_kvalue;
tmpTab.MinLoadFactor = impl.m_minLoadFactor;
tmpTab.MaxLoadFactor = impl.m_maxLoadFactor;
tmpTab.TableType = DictTabInfo::UserTable;
tmpTab.NoOfAttributes = sz;
tmpTab.FragmentType = getKernelConstant(impl.m_fragmentType,
fragmentTypeMapping,
DictTabInfo::AllNodesSmallTable);
tmpTab.TableVersion = rand();
SimpleProperties::UnpackStatus s;
s = SimpleProperties::pack(w,
&tmpTab,
DictTabInfo::TableMapping,
DictTabInfo::TableMappingSize, true);
if(s != SimpleProperties::Eof){
abort();
}
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
DictTabInfo::Attribute tmpAttr; tmpAttr.init();
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
tmpAttr.AttributeId = i;
tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
tmpAttr.AttributeStoredInd = 1;
tmpAttr.AttributeDKey = col->m_distributionKey;
tmpAttr.AttributeDGroup = 0;
tmpAttr.AttributeExtType =
getKernelConstant(col->m_type,
columnTypeMapping,
DictTabInfo::ExtUndefined);
tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
tmpAttr.AttributeExtScale = col->m_scale;
tmpAttr.AttributeExtLength = col->m_length;
// charset is defined exactly for char types
if (col->getCharType() != (col->m_cs != NULL)) {
m_error.code = 703;
return -1;
}
// primary key type check
if (col->m_pk && ! NdbSqlUtil::usable_in_pk(col->m_type, col->m_cs)) {
m_error.code = 743;
return -1;
}
// charset in upper half of precision
if (col->getCharType()) {
tmpAttr.AttributeExtPrecision |= (col->m_cs->number << 16);
}
// DICT will ignore and recompute this
(void)tmpAttr.translateExtType();
tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
BaseString::snprintf(tmpAttr.AttributeDefaultValue,
sizeof(tmpAttr.AttributeDefaultValue),
col->m_defaultValue.c_str());
s = SimpleProperties::pack(w,
&tmpAttr,
DictTabInfo::AttributeMapping,
DictTabInfo::AttributeMappingSize, true);
w.add(DictTabInfo::AttributeEnd, 1);
}
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
if (alter) {
AlterTableReq * const req =
CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->changeMask = impl.m_changeMask;
req->tableId = impl.m_tableId;
req->tableVersion = impl.m_version;;
tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
tSignal.theLength = AlterTableReq::SignalLength;
}
else {
CreateTableReq * const req =
CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
tSignal.theLength = CreateTableReq::SignalLength;
}
LinearSectionPtr ptr[3];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
int ret = (alter) ?
alterTable(&tSignal, ptr)
: createTable(&tSignal, ptr);
if (!alter && haveAutoIncrement) {
if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
autoIncrementValue)) {
if (ndb.theError.code == 0) {
m_error.code = 4336;
ndb.theError = m_error;
} else
m_error= ndb.theError;
ret = -1; // errorcode set in initialize_autoincrement
}
}
return ret;
}
int
NdbDictInterface::createTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
{
#if DEBUG_PRINT
ndbout_c("BufferLen = %d", ptr[0].sz);
SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
r.printAll(ndbout);
#endif
const int noErrCodes = 2;
int errCodes[noErrCodes] =
{CreateTableRef::Busy,
CreateTableRef::NotMaster};
return dictSignal(signal,ptr,1,
1/*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ,
WAITFOR_RESPONSE_TIMEOUT,
errCodes,noErrCodes);
}
void
NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const CreateTableConf* const conf=
CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
Uint32 tableId= conf->tableId;
Uint32 tableVersion= conf->tableVersion;
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const CreateTableRef* const ref=
CAST_CONSTPTR(CreateTableRef, signal->getDataPtr());
m_error.code = ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
int
NdbDictInterface::alterTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
{
#if DEBUG_PRINT
ndbout_c("BufferLen = %d", ptr[0].sz);
SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
r.printAll(ndbout);
#endif
const int noErrCodes = 2;
int errCodes[noErrCodes] =
{AlterTableRef::NotMaster,
AlterTableRef::Busy};
int r = dictSignal(signal,ptr,1,
1/*use masternode id*/,
100,WAIT_ALTER_TAB_REQ,
WAITFOR_RESPONSE_TIMEOUT,
errCodes, noErrCodes);
if(m_error.code == AlterTableRef::InvalidTableVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
}
return r;
}
void
NdbDictInterface::execALTER_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
//AlterTableConf* const conf = CAST_CONSTPTR(AlterTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const AlterTableRef * const ref =
CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
m_error.code = ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
/*****************************************************************
* Drop table
*/
int
NdbDictionaryImpl::dropTable(const char * name)
{
DBUG_ENTER("NdbDictionaryImpl::dropTable");
DBUG_PRINT("enter",("name: %s", name));
NdbTableImpl * tab = getTable(name);
if(tab == 0){
return -1;
}
int ret = dropTable(* tab);
// If table stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
const char * internalTableName = m_ndb.internalizeTableName(name);
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
m_localHash.drop(internalTableName);
m_globalHash->lock();
m_globalHash->drop(tab);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
DBUG_RETURN(ret);
}
int
NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
{
int res;
const char * name = impl.getName();
if(impl.m_status == NdbDictionary::Object::New){
return dropTable(name);
}
if (impl.m_indexType != NdbDictionary::Index::Undefined) {
m_receiver.m_error.code = 1228;
return -1;
}
List list;
if ((res = listIndexes(list, impl.m_tableId)) == -1){
return -1;
}
for (unsigned i = 0; i < list.count; i++) {
const List::Element& element = list.elements[i];
if ((res = dropIndex(element.name, name)) == -1)
{
return -1;
}
}
if (impl.m_noOfBlobs != 0) {
if (dropBlobTables(impl) != 0){
return -1;
}
}
int ret = m_receiver.dropTable(impl);
if(ret == 0 || m_error.code == 709){
const char * internalTableName = impl.m_internalName.c_str();
m_localHash.drop(internalTableName);
m_globalHash->lock();
m_globalHash->drop(&impl);
m_globalHash->unlock();
return 0;
}
return ret;
}
int
NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
DBUG_ENTER("NdbDictionaryImpl::dropBlobTables");
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
char btname[NdbBlob::BlobTableNameSize];
NdbBlob::getBlobTableName(btname, &t, &c);
if (dropTable(btname) != 0) {
if (m_error.code != 709){
DBUG_PRINT("exit",("error %u - exiting",m_error.code));
DBUG_RETURN(-1);
}
DBUG_PRINT("info",("error %u - continuing",m_error.code));
}
}
DBUG_RETURN(0);
}
int
NdbDictInterface::dropTable(const NdbTableImpl & impl)
{
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_TABLE_REQ;
tSignal.theLength = DropTableReq::SignalLength;
DropTableReq * const req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->tableId = impl.m_tableId;
req->tableVersion = impl.m_version;
return dropTable(&tSignal, 0);
}
int
NdbDictInterface::dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
{
const int noErrCodes = 3;
int errCodes[noErrCodes] =
{DropTableRef::NoDropTableRecordAvailable,
DropTableRef::NotMaster,
DropTableRef::Busy};
int r = dictSignal(signal,NULL,0,
1/*use masternode id*/,
100,WAIT_DROP_TAB_REQ,
WAITFOR_RESPONSE_TIMEOUT,
errCodes, noErrCodes);
if(m_error.code == DropTableRef::InvalidTableVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
}
return r;
}
void
NdbDictInterface::execDROP_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
//DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
m_error.code = ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
int
NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
{
const char * internalTableName = impl.m_internalName.c_str();
m_localHash.drop(internalTableName);
m_globalHash->lock();
m_globalHash->drop(&impl);
m_globalHash->unlock();
return 0;
}
int
NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
{
const char * internalTableName = impl.m_internalName.c_str();
m_localHash.drop(internalTableName);
m_globalHash->lock();
m_globalHash->release(&impl);
m_globalHash->unlock();
return 0;
}
/*****************************************************************
* Get index info
*/
NdbIndexImpl*
NdbDictionaryImpl::getIndexImpl(const char * externalName,
const char * internalName)
{
Ndb_local_table_info * info = get_local_table_info(internalName,
false);
if(info == 0){
m_error.code = 4243;
return 0;
}
NdbTableImpl * tab = info->m_table_impl;
if(tab->m_indexType == NdbDictionary::Index::Undefined){
// Not an index
m_error.code = 4243;
return 0;
}
NdbTableImpl* prim = getTable(tab->m_primaryTable.c_str());
if(prim == 0){
m_error.code = 4243;
return 0;
}
/**
* Create index impl
*/
NdbIndexImpl* idx;
if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
idx->m_table = tab;
idx->m_externalName.assign(externalName);
idx->m_internalName.assign(internalName);
// TODO Assign idx to tab->m_index
// Don't do it right now since assign can't asign a table with index
// tab->m_index = idx;
return idx;
}
return 0;
}
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
const NdbTableImpl* tab,
const NdbTableImpl* prim){
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
idx->m_status = tab->m_status;
idx->m_indexId = tab->m_tableId;
idx->m_externalName.assign(tab->getName());
idx->m_tableName.assign(prim->m_externalName);
idx->m_type = tab->m_indexType;
idx->m_logging = tab->m_logging;
// skip last attribute (NDB$PK or NDB$TNODE)
for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
NdbColumnImpl* col = new NdbColumnImpl;
// Copy column definition
*col = *tab->m_columns[i];
idx->m_columns.push_back(col);
/**
* reverse map
*/
int key_id = prim->getColumn(col->getName())->getColumnNo();
int fill = -1;
idx->m_key_ids.fill(key_id, fill);
idx->m_key_ids[key_id] = i;
col->m_keyInfoPos = key_id;
}
* dst = idx;
return 0;
}
/*****************************************************************
* Create index
*/
int
NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
{
NdbTableImpl* tab = getTable(ix.getTable());
if(tab == 0){
m_error.code = 4249;
return -1;
}
return m_receiver.createIndex(m_ndb, ix, * tab);
}
int
NdbDictInterface::createIndex(Ndb & ndb,
NdbIndexImpl & impl,
const NdbTableImpl & table)
{
//validate();
//aggregate();
unsigned i;
UtilBufferWriter w(m_buffer);
const size_t len = strlen(impl.m_externalName.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code = 4241;
return -1;
}
const char * internalName =
ndb.internalizeIndexName(&table, impl.getName());
impl.m_internalName.assign(internalName);
w.add(DictTabInfo::TableName, internalName);
w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_CREATE_INDX_REQ;
tSignal.theLength = CreateIndxReq::SignalLength;
CreateIndxReq * const req = CAST_PTR(CreateIndxReq, tSignal.getDataPtrSend());
req->setUserRef(m_reference);
req->setConnectionPtr(0);
req->setRequestType(CreateIndxReq::RT_USER);
Uint32 it = getKernelConstant(impl.m_type,
indexTypeMapping,
DictTabInfo::UndefTableType);
if(it == DictTabInfo::UndefTableType){
m_error.code = 4250;
return -1;
}
req->setIndexType((DictTabInfo::TableType) it);
req->setTableId(table.m_tableId);
req->setOnline(true);
AttributeList attributeList;
attributeList.sz = impl.m_columns.size();
for(i = 0; i<attributeList.sz; i++){
const NdbColumnImpl* col =
table.getColumn(impl.m_columns[i]->m_name.c_str());
if(col == 0){
m_error.code = 4247;
return -1;
}
// Copy column definition
*impl.m_columns[i] = *col;
// index key type check
if (it == DictTabInfo::UniqueHashIndex &&
! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) ||
it == DictTabInfo::OrderedIndex &&
! NdbSqlUtil::usable_in_ordered_index(col->m_type, col->m_cs)) {
m_error.code = 743;
return -1;
}
attributeList.id[i] = col->m_attrId;
}
if (it == DictTabInfo::UniqueHashIndex) {
// Sort index attributes according to primary table (using insertion sort)
for(i = 1; i < attributeList.sz; i++) {
unsigned int temp = attributeList.id[i];
unsigned int j = i;
while((j > 0) && (attributeList.id[j - 1] > temp)) {
attributeList.id[j] = attributeList.id[j - 1];
j--;
}
attributeList.id[j] = temp;
}
// Check for illegal duplicate attributes
for(i = 0; i<attributeList.sz; i++) {
if ((i != (attributeList.sz - 1)) &&
(attributeList.id[i] == attributeList.id[i+1])) {
m_error.code = 4258;
return -1;
}
}
}
LinearSectionPtr ptr[3];
ptr[0].p = (Uint32*)&attributeList;
ptr[0].sz = 1 + attributeList.sz;
ptr[1].p = (Uint32*)m_buffer.get_data();
ptr[1].sz = m_buffer.length() >> 2; //BUG?
return createIndex(&tSignal, ptr);
}
int
NdbDictInterface::createIndex(NdbApiSignal* signal,
LinearSectionPtr ptr[3])
{
const int noErrCodes = 1;
int errCodes[noErrCodes] = {CreateIndxRef::Busy};
return dictSignal(signal,ptr,2,
1 /*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ,
-1,
errCodes,noErrCodes);
}
void
NdbDictInterface::execCREATE_INDX_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
//CreateTableConf* const conf = CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const CreateIndxRef* const ref = CAST_CONSTPTR(CreateIndxRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
m_waiter.signal(NO_WAIT);
}
/*****************************************************************
* Drop index
*/
int
NdbDictionaryImpl::dropIndex(const char * indexName,
const char * tableName)
{
NdbIndexImpl * idx = getIndex(indexName, tableName);
if (idx == 0) {
m_error.code = 4243;
return -1;
}
int ret = dropIndex(*idx, tableName);
// If index stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
const char * internalIndexName = (tableName)
?
m_ndb.internalizeIndexName(getTable(tableName), indexName)
:
m_ndb.internalizeTableName(indexName); // Index is also a table
m_localHash.drop(internalIndexName);
m_globalHash->lock();
m_globalHash->drop(idx->m_table);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
return ret;
}
int
NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
{
const char * indexName = impl.getName();
if (tableName || m_ndb.usingFullyQualifiedNames()) {
NdbTableImpl * timpl = impl.m_table;
if (timpl == 0) {
m_error.code = 709;
return -1;
}
const char * internalIndexName = (tableName)
?
m_ndb.internalizeIndexName(getTable(tableName), indexName)
:
m_ndb.internalizeTableName(indexName); // Index is also a table
if(impl.m_status == NdbDictionary::Object::New){
return dropIndex(indexName, tableName);
}
int ret = m_receiver.dropIndex(impl, *timpl);
if(ret == 0){
m_localHash.drop(internalIndexName);
m_globalHash->lock();
m_globalHash->drop(impl.m_table);
m_globalHash->unlock();
}
return ret;
}
m_error.code = 4243;
return -1;
}
int
NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
const NdbTableImpl & timpl)
{
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_INDX_REQ;
tSignal.theLength = DropIndxReq::SignalLength;
DropIndxReq * const req = CAST_PTR(DropIndxReq, tSignal.getDataPtrSend());
req->setUserRef(m_reference);
req->setConnectionPtr(0);
req->setRequestType(DropIndxReq::RT_USER);
req->setTableId(~0); // DICT overwrites
req->setIndexId(timpl.m_tableId);
req->setIndexVersion(timpl.m_version);
return dropIndex(&tSignal, 0);
}
int
NdbDictInterface::dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3])
{
const int noErrCodes = 1;
int errCodes[noErrCodes] = {DropIndxRef::Busy};
int r = dictSignal(signal,NULL,0,
1/*Use masternode id*/,
100,
WAIT_DROP_INDX_REQ,
WAITFOR_RESPONSE_TIMEOUT,
errCodes,noErrCodes);
if(m_error.code == DropIndxRef::InvalidIndexVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
}
return r;
}
void
NdbDictInterface::execDROP_INDX_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const DropIndxRef* const ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
m_waiter.signal(NO_WAIT);
}
/*****************************************************************
* Create event
*/
int
NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
{
int i;
NdbTableImpl* tab = getTable(evnt.getTable());
if(tab == 0){
// m_error.code = 3249;
ndbout_c(":createEvent: table %s not found", evnt.getTable());
#ifdef EVENT_DEBUG
ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s", evnt.getTable());
#endif
return -1;
}
evnt.m_tableId = tab->m_tableId;
evnt.m_tableImpl = tab;
#ifdef EVENT_DEBUG
ndbout_c("Event on tableId=%d", evnt.m_tableId);
#endif
NdbTableImpl &table = *evnt.m_tableImpl;
int attributeList_sz = evnt.m_attrIds.size();
for (i = 0; i < attributeList_sz; i++) {
NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]);
if (col_impl) {
evnt.m_facade->addColumn(*(col_impl->m_facade));
} else {
ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
evnt.getTable());
return -1;
}
}
evnt.m_attrIds.clear();
attributeList_sz = evnt.m_columns.size();
#ifdef EVENT_DEBUG
ndbout_c("creating event %s", evnt.m_externalName.c_str());
ndbout_c("no of columns %d", evnt.m_columns.size());
#endif
int pk_count = 0;
evnt.m_attrListBitmask.clear();
for(i = 0; i<attributeList_sz; i++){
const NdbColumnImpl* col =
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
m_error.code = 4247;
return -1;
}
// Copy column definition
*evnt.m_columns[i] = *col;
if(col->m_pk){
pk_count++;
}
evnt.m_attrListBitmask.set(col->m_attrId);
}
// Sort index attributes according to primary table (using insertion sort)
for(i = 1; i < attributeList_sz; i++) {
NdbColumnImpl* temp = evnt.m_columns[i];
unsigned int j = i;
while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) {
evnt.m_columns[j] = evnt.m_columns[j - 1];
j--;
}
evnt.m_columns[j] = temp;
}
// Check for illegal duplicate attributes
for(i = 1; i<attributeList_sz; i++) {
if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
m_error.code = 4258;
return -1;
}
}
#ifdef EVENT_DEBUG
char buf[128] = {0};
evnt.m_attrListBitmask.getText(buf);
ndbout_c("createEvent: mask = %s", buf);
#endif
// NdbDictInterface m_receiver;
return m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */);
}
int
NdbDictInterface::createEvent(class Ndb & ndb,
NdbEventImpl & evnt,
int getFlag)
{
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_CREATE_EVNT_REQ;
if (getFlag)
tSignal.theLength = CreateEvntReq::SignalLengthGet;
else
tSignal.theLength = CreateEvntReq::SignalLengthCreate;
CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend());
req->setUserRef(m_reference);
req->setUserData(0);
if (getFlag) {
// getting event from Dictionary
req->setRequestType(CreateEvntReq::RT_USER_GET);
} else {
// creating event in Dictionary
req->setRequestType(CreateEvntReq::RT_USER_CREATE);
req->setTableId(evnt.m_tableId);
req->setAttrListBitmask(evnt.m_attrListBitmask);
req->setEventType(evnt.mi_type);
}
UtilBufferWriter w(m_buffer);
const size_t len = strlen(evnt.m_externalName.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code = 4241;
return -1;
}
w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
if (getFlag == 0)
w.add(SimpleProperties::StringValue,
ndb.internalizeTableName(evnt.m_tableName.c_str()));
LinearSectionPtr ptr[3];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
int ret = createEvent(&tSignal, ptr, 1);
if (ret) {
return ret;
}
char *dataPtr = (char *)m_buffer.get_data();
unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
dataPtr += sizeof(lenCreateEvntConf);
CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr;
dataPtr += lenCreateEvntConf;
// NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
if (getFlag) {
evnt.m_tableId = evntConf->getTableId();
evnt.m_attrListBitmask = evntConf->getAttrListBitmask();
evnt.mi_type = evntConf->getEventType();
evnt.setTable(dataPtr);
} else {
if (evnt.m_tableId != evntConf->getTableId() ||
//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
evnt.mi_type != evntConf->getEventType()) {
ndbout_c("ERROR*************");
return 1;
}
}
evnt.m_eventId = evntConf->getEventId();
evnt.m_eventKey = evntConf->getEventKey();
return ret;
}
int
NdbDictInterface::createEvent(NdbApiSignal* signal,
LinearSectionPtr ptr[3], int noLSP)
{
const int noErrCodes = 1;
int errCodes[noErrCodes] = {CreateEvntRef::Busy};
return dictSignal(signal,ptr,noLSP,
1 /*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
-1,
errCodes,noErrCodes, CreateEvntRef::Temporary);
}
int
NdbDictionaryImpl::executeSubscribeEvent(NdbEventImpl & ev)
{
// NdbDictInterface m_receiver;
return m_receiver.executeSubscribeEvent(m_ndb, ev);
}
int
NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
NdbEventImpl & evnt)
{
NdbApiSignal tSignal(m_reference);
// tSignal.theReceiversBlockNumber = SUMA;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_SUB_START_REQ;
tSignal.theLength = SubStartReq::SignalLength2;
SubStartReq * sumaStart = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
sumaStart->subscriptionId = evnt.m_eventId;
sumaStart->subscriptionKey = evnt.m_eventKey;
sumaStart->part = SubscriptionData::TableData;
sumaStart->subscriberData = evnt.m_bufferId & 0xFF;
sumaStart->subscriberRef = m_reference;
return executeSubscribeEvent(&tSignal, NULL);
}
int
NdbDictInterface::executeSubscribeEvent(NdbApiSignal* signal,
LinearSectionPtr ptr[3])
{
return dictSignal(signal,NULL,0,
1 /*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
-1,
NULL,0);
}
int
NdbDictionaryImpl::stopSubscribeEvent(NdbEventImpl & ev)
{
// NdbDictInterface m_receiver;
return m_receiver.stopSubscribeEvent(m_ndb, ev);
}
int
NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
NdbEventImpl & evnt)
{
#ifdef EVENT_DEBUG
ndbout_c("SUB_STOP_REQ");
#endif
NdbApiSignal tSignal(m_reference);
// tSignal.theReceiversBlockNumber = SUMA;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_SUB_STOP_REQ;
tSignal.theLength = SubStopReq::SignalLength;
SubStopReq * sumaStop = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
sumaStop->subscriptionId = evnt.m_eventId;
sumaStop->subscriptionKey = evnt.m_eventKey;
sumaStop->subscriberData = evnt.m_bufferId & 0xFF;
sumaStop->part = (Uint32) SubscriptionData::TableData;
sumaStop->subscriberRef = m_reference;
return stopSubscribeEvent(&tSignal, NULL);
}
int
NdbDictInterface::stopSubscribeEvent(NdbApiSignal* signal,
LinearSectionPtr ptr[3])
{
return dictSignal(signal,NULL,0,
1 /*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
-1,
NULL,0);
}
NdbEventImpl *
NdbDictionaryImpl::getEvent(const char * eventName)
{
NdbEventImpl *ev = new NdbEventImpl();
if (ev == NULL) {
return NULL;
}
ev->setName(eventName);
int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
if (ret) {
delete ev;
return NULL;
}
// We only have the table name with internal name
ev->setTable(m_ndb.externalizeTableName(ev->getTable()));
ev->m_tableImpl = getTable(ev->getTable());
// get the columns from the attrListBitmask
NdbTableImpl &table = *ev->m_tableImpl;
AttributeMask & mask = ev->m_attrListBitmask;
int attributeList_sz = mask.count();
int id = -1;
#ifdef EVENT_DEBUG
ndbout_c("NdbDictionaryImpl::getEvent attributeList_sz = %d",
attributeList_sz);
char buf[128] = {0};
mask.getText(buf);
ndbout_c("mask = %s", buf);
#endif
for(int i = 0; i < attributeList_sz; i++) {
id++; while (!mask.get(id)) id++;
const NdbColumnImpl* col = table.getColumn(id);
if(col == 0) {
#ifdef EVENT_DEBUG
ndbout_c("NdbDictionaryImpl::getEvent could not find column id %d", id);
#endif
m_error.code = 4247;
delete ev;
return NULL;
}
NdbColumnImpl* new_col = new NdbColumnImpl;
// Copy column definition
*new_col = *col;
ev->m_columns.push_back(new_col);
}
return ev;
}
void
NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_CONF" << endl;
#endif
m_buffer.clear();
unsigned int len = signal->getLength() << 2;
m_buffer.append((char *)&len, sizeof(len));
m_buffer.append(signal->getDataPtr(), len);
if (signal->m_noOfSections > 0) {
m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
}
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_REF" << endl;
ndbout << "Exiting" << endl;
exit(-1);
#endif
const CreateEvntRef* const ref = CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
#ifdef EVENT_DEBUG
ndbout_c("execCREATE_EVNT_REF");
ndbout_c("ErrorCode %u", ref->getErrorCode());
ndbout_c("Errorline %u", ref->getErrorLine());
ndbout_c("ErrorNode %u", ref->getErrorNode());
#endif
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "Got GSN_SUB_STOP_CONF" << endl;
#endif
// SubRemoveConf * const sumaRemoveConf = CAST_CONSTPTR(SubRemoveConf, signal->getDataPtr());
// Uint32 subscriptionId = sumaRemoveConf->subscriptionId;
// Uint32 subscriptionKey = sumaRemoveConf->subscriptionKey;
// Uint32 senderData = sumaRemoveConf->senderData;
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "Got GSN_SUB_STOP_REF" << endl;
#endif
// SubRemoveConf * const sumaRemoveRef = CAST_CONSTPTR(SubRemoveRef, signal->getDataPtr());
// Uint32 subscriptionId = sumaRemoveRef->subscriptionId;
// Uint32 subscriptionKey = sumaRemoveRef->subscriptionKey;
// Uint32 senderData = sumaRemoveRef->senderData;
m_error.code = 1;
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "Got GSN_SUB_START_CONF" << endl;
#endif
const SubStartConf * const sumaStartConf = CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
// Uint32 subscriptionId = sumaStartConf->subscriptionId;
// Uint32 subscriptionKey = sumaStartConf->subscriptionKey;
SubscriptionData::Part part =
(SubscriptionData::Part)sumaStartConf->part;
// Uint32 subscriberData = sumaStartConf->subscriberData;
switch(part) {
case SubscriptionData::MetaData: {
#ifdef EVENT_DEBUG
ndbout << "SubscriptionData::MetaData" << endl;
#endif
m_error.code = 1;
break;
}
case SubscriptionData::TableData: {
#ifdef EVENT_DEBUG
ndbout << "SubscriptionData::TableData" << endl;
#endif
break;
}
default: {
#ifdef EVENT_DEBUG
ndbout_c("NdbDictInterface::execSUB_START_CONF wrong data");
#endif
m_error.code = 1;
break;
}
}
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "Got GSN_SUB_START_REF" << endl;
#endif
m_error.code = 1;
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
const SubGcpCompleteRep * const rep = CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr());
const Uint32 gci = rep->gci;
// const Uint32 senderRef = rep->senderRef;
const Uint32 subscriberData = rep->subscriberData;
const Uint32 bufferId = subscriberData;
const Uint32 ref = signal->theSendersBlockRef;
NdbApiSignal tSignal(m_reference);
SubGcpCompleteAcc * acc = CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend());
acc->rep = *rep;
tSignal.theReceiversBlockNumber = refToBlock(ref);
tSignal.theVerId_signalNumber = GSN_SUB_GCP_COMPLETE_ACC;
tSignal.theLength = SubGcpCompleteAcc::SignalLength;
Uint32 aNodeId = refToNode(ref);
// m_transporter->lock_mutex();
int r;
r = m_transporter->sendSignal(&tSignal, aNodeId);
// m_transporter->unlock_mutex();
NdbGlobalEventBufferHandle::latestGCI(bufferId, gci);
}
void
NdbDictInterface::execSUB_TABLE_DATA(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
const char * FNAME = "NdbDictInterface::execSUB_TABLE_DATA";
#endif
//TODO
const SubTableData * const sdata = CAST_CONSTPTR(SubTableData, signal->getDataPtr());
// const Uint32 gci = sdata->gci;
// const Uint32 operation = sdata->operation;
// const Uint32 tableId = sdata->tableId;
// const Uint32 noOfAttrs = sdata->noOfAttributes;
// const Uint32 dataLen = sdata->dataSize;
const Uint32 subscriberData = sdata->subscriberData;
// const Uint32 logType = sdata->logType;
for (int i=signal->m_noOfSections;i < 3; i++) {
ptr[i].p = NULL;
ptr[i].sz = 0;
}
#ifdef EVENT_DEBUG
ndbout_c("%s: senderData %d, gci %d, operation %d, tableId %d, noOfAttrs %d, dataLen %d",
FNAME, subscriberData, gci, operation, tableId, noOfAttrs, dataLen);
ndbout_c("ptr[0] %u %u ptr[1] %u %u ptr[2] %u %u\n",
ptr[0].p,ptr[0].sz,ptr[1].p,ptr[1].sz,ptr[2].p,ptr[2].sz);
#endif
const Uint32 bufferId = subscriberData;
NdbGlobalEventBufferHandle::insertDataL(bufferId,
sdata, ptr);
}
/*****************************************************************
* Drop event
*/
int
NdbDictionaryImpl::dropEvent(const char * eventName)
{
NdbEventImpl *ev = new NdbEventImpl();
ev->setName(eventName);
int ret = m_receiver.dropEvent(*ev);
delete ev;
// printf("__________________RET %u\n", ret);
return ret;
}
int
NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
{
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_EVNT_REQ;
tSignal.theLength = DropEvntReq::SignalLength;
DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend());
req->setUserRef(m_reference);
req->setUserData(0);
UtilBufferWriter w(m_buffer);
w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
return dropEvent(&tSignal, ptr, 1);
}
int
NdbDictInterface::dropEvent(NdbApiSignal* signal,
LinearSectionPtr ptr[3], int noLSP)
{
//TODO
const int noErrCodes = 1;
int errCodes[noErrCodes] = {DropEvntRef::Busy};
return dictSignal(signal,ptr,noLSP,
1 /*use masternode id*/,
100,
WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
-1,
errCodes,noErrCodes, DropEvntRef::Temporary);
}
void
NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_CONF" << endl;
#endif
m_waiter.signal(NO_WAIT);
}
void
NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
#ifdef EVENT_DEBUG
ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_REF" << endl;
#endif
const DropEvntRef* const ref = CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
#if 0
ndbout_c("execDROP_EVNT_REF");
ndbout_c("ErrorCode %u", ref->getErrorCode());
ndbout_c("Errorline %u", ref->getErrorLine());
ndbout_c("ErrorNode %u", ref->getErrorNode());
#endif
m_waiter.signal(NO_WAIT);
}
/*****************************************************************
* List objects or indexes
*/
int
NdbDictionaryImpl::listObjects(List& list, NdbDictionary::Object::Type type)
{
ListTablesReq req;
req.requestData = 0;
req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
req.setListNames(true);
return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
}
int
NdbDictionaryImpl::listIndexes(List& list, Uint32 indexId)
{
ListTablesReq req;
req.requestData = 0;
req.setTableId(indexId);
req.setListNames(true);
req.setListIndexes(true);
return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
}
int
NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
Uint32 requestData, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
ListTablesReq* const req = CAST_PTR(ListTablesReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->requestData = requestData;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_LIST_TABLES_REQ;
tSignal.theLength = ListTablesReq::SignalLength;
if (listObjects(&tSignal) != 0)
return -1;
// count
const Uint32* data = (const Uint32*)m_buffer.get_data();
const unsigned length = m_buffer.length() / 4;
list.count = 0;
bool ok = true;
unsigned pos, count;
pos = count = 0;
while (pos < length) {
// table id - name length - name
pos++;
if (pos >= length) {
ok = false;
break;
}
Uint32 n = (data[pos++] + 3) >> 2;
pos += n;
if (pos > length) {
ok = false;
break;
}
count++;
}
if (! ok) {
// bad signal data
m_error.code = 4213;
return -1;
}
list.count = count;
list.elements = new NdbDictionary::Dictionary::List::Element[count];
pos = count = 0;
while (pos < length) {
NdbDictionary::Dictionary::List::Element& element = list.elements[count];
Uint32 d = data[pos++];
element.id = ListTablesConf::getTableId(d);
element.type = (NdbDictionary::Object::Type)
getApiConstant(ListTablesConf::getTableType(d), objectTypeMapping, 0);
element.state = (NdbDictionary::Object::State)
getApiConstant(ListTablesConf::getTableState(d), objectStateMapping, 0);
element.store = (NdbDictionary::Object::Store)
getApiConstant(ListTablesConf::getTableStore(d), objectStoreMapping, 0);
// table or index name
Uint32 n = (data[pos++] + 3) >> 2;
BaseString databaseName;
BaseString schemaName;
BaseString objectName;
if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
(element.type == NdbDictionary::Object::HashIndex) ||
(element.type == NdbDictionary::Object::UniqueOrderedIndex) ||
(element.type == NdbDictionary::Object::OrderedIndex)) {
char * indexName = new char[n << 2];
memcpy(indexName, &data[pos], n << 2);
databaseName = Ndb::getDatabaseFromInternalName(indexName);
schemaName = Ndb::getSchemaFromInternalName(indexName);
objectName = BaseString(Ndb::externalizeIndexName(indexName, fullyQualifiedNames));
delete [] indexName;
} else if ((element.type == NdbDictionary::Object::SystemTable) ||
(element.type == NdbDictionary::Object::UserTable)) {
char * tableName = new char[n << 2];
memcpy(tableName, &data[pos], n << 2);
databaseName = Ndb::getDatabaseFromInternalName(tableName);
schemaName = Ndb::getSchemaFromInternalName(tableName);
objectName = BaseString(Ndb::externalizeTableName(tableName, fullyQualifiedNames));
delete [] tableName;
}
else {
char * otherName = new char[n << 2];
memcpy(otherName, &data[pos], n << 2);
objectName = BaseString(otherName);
delete [] otherName;
}
element.database = new char[databaseName.length() + 1];
strcpy(element.database, databaseName.c_str());
element.schema = new char[schemaName.length() + 1];
strcpy(element.schema, schemaName.c_str());
element.name = new char[objectName.length() + 1];
strcpy(element.name, objectName.c_str());
pos += n;
count++;
}
return 0;
}
int
NdbDictInterface::listObjects(NdbApiSignal* signal)
{
const Uint32 RETRIES = 100;
for (Uint32 i = 0; i < RETRIES; i++) {
m_buffer.clear();
// begin protected
m_transporter->lock_mutex();
Uint16 aNodeId = m_transporter->get_an_alive_node();
if (aNodeId == 0) {
m_error.code = 4009;
m_transporter->unlock_mutex();
return -1;
}
if (m_transporter->sendSignal(signal, aNodeId) != 0) {
m_transporter->unlock_mutex();
continue;
}
m_error.code = 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = WAIT_LIST_TABLES_CONF;
m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT);
m_transporter->unlock_mutex();
// end protected
if (m_waiter.m_state == NO_WAIT && m_error.code == 0)
return 0;
if (m_waiter.m_state == WAIT_NODE_FAILURE)
continue;
return -1;
}
return -1;
}
void
NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
LinearSectionPtr ptr[3])
{
const unsigned off = ListTablesConf::HeaderLength;
const unsigned len = (signal->getLength() - off);
m_buffer.append(signal->getDataPtr() + off, len << 2);
if (signal->getLength() < ListTablesConf::SignalLength) {
// last signal has less than full length
m_waiter.signal(NO_WAIT);
}
}
template class Vector<int>;
template class Vector<Uint32>;
template class Vector<Vector<Uint32> >;
template class Vector<NdbTableImpl*>;
template class Vector<NdbColumnImpl*>;