int create_table(){ NdbDictionary::Dictionary* dict = g_ndb->getDictionary(); assert(dict); if(g_paramters[P_CREATE].value){ g_ndb->getDictionary()->dropTable(g_tablename); const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename); assert(pTab); NdbDictionary::Table copy = * pTab; copy.setLogging(false); if(dict->createTable(copy) != 0){ g_err << "Failed to create table: " << g_tablename << endl; return -1; } NdbDictionary::Index x(g_indexname); x.setTable(g_tablename); x.setType(NdbDictionary::Index::OrderedIndex); x.setLogging(false); for (unsigned k = 0; k < copy.getNoOfColumns(); k++){ if(copy.getColumn(k)->getPrimaryKey()){ x.addColumnName(copy.getColumn(k)->getName()); } } if(dict->createIndex(x) != 0){ g_err << "Failed to create index: " << endl; return -1; } } g_table = dict->getTable(g_tablename); g_index = dict->getIndex(g_indexname, g_tablename); assert(g_table); assert(g_index); if(g_paramters[P_CREATE].value) { int rows = g_paramters[P_ROWS].value; HugoTransactions hugoTrans(* g_table); if (hugoTrans.loadTable(g_ndb, rows)){ g_err.println("Failed to load %s with %d rows", g_table->getName(), rows); return -1; } } return 0; }
int NDBT_TestSuite::createHook(Ndb* ndb, NdbDictionary::Table& tab, int when) { if (when == 0) { if (diskbased) { for (int i = 0; i < tab.getNoOfColumns(); i++) { NdbDictionary::Column* col = tab.getColumn(i); if (! col->getPrimaryKey()) { col->setStorageType(NdbDictionary::Column::StorageTypeDisk); } } } else if (temporaryTables) { tab.setTemporary(true); tab.setLogging(false); } if (tsname != NULL) { tab.setTablespaceName(tsname); } } return 0; }
Handle<Object> GetTableCall::buildDBIndex(const NdbDictionary::Index *idx) { HandleScope scope; Local<Object> obj = NdbDictIndexEnv.newWrapper(); wrapPointerInObject(idx, NdbDictIndexEnv, obj); obj->Set(String::NewSymbol("name"), String::New(idx->getName())); obj->Set(String::NewSymbol("isUnique"), Boolean::New(idx->getType() == NdbDictionary::Index::UniqueHashIndex), ReadOnly); obj->Set(String::NewSymbol("isOrdered"), Boolean::New(idx->getType() == NdbDictionary::Index::OrderedIndex), ReadOnly); /* Loop over the columns of the key. Build the "columns" array and the "record" object, then set both. */ int ncol = idx->getNoOfColumns(); Local<Array> idx_columns = Array::New(ncol); DEBUG_PRINT("Creating Index Record (%s)", idx->getName()); Record * idx_record = new Record(arg0->dict, ncol); for(int i = 0 ; i < ncol ; i++) { const char *colName = idx->getColumn(i)->getName(); const NdbDictionary::Column *col = ndb_table->getColumn(colName); idx_columns->Set(i, v8::Int32::New(col->getColumnNo())); idx_record->addColumn(col); } idx_record->completeIndexRecord(idx); obj->Set(String::NewSymbol("record"), Record_Wrapper(idx_record), ReadOnly); obj->Set(String::NewSymbol("columnNumbers"), idx_columns); return scope.Close(obj); }
/* DBIndex = { name : "" , // Index name; undefined for PK isPrimaryKey : true , // true for PK; otherwise undefined isUnique : true , // true or false isOrdered : true , // true or false; can scan if true columnNumbers : [] , // an ordered array of column numbers }; */ Handle<Object> GetTableCall::buildDBIndex_PK() { HandleScope scope; Local<Object> obj = Object::New(); obj->Set(String::NewSymbol("isPrimaryKey"), Boolean::New(true), ReadOnly); obj->Set(String::NewSymbol("isUnique"), Boolean::New(true), ReadOnly); obj->Set(String::NewSymbol("isOrdered"), Boolean::New(false), ReadOnly); /* Loop over the columns of the key. Build the "columnNumbers" array and the "record" object, then set both. */ int ncol = ndb_table->getNoOfPrimaryKeys(); DEBUG_PRINT("Creating Primary Key Record"); Record * pk_record = new Record(arg0->dict, ncol); Local<Array> idx_columns = Array::New(ncol); for(int i = 0 ; i < ncol ; i++) { const char * col_name = ndb_table->getPrimaryKey(i); const NdbDictionary::Column * col = ndb_table->getColumn(col_name); pk_record->addColumn(col); idx_columns->Set(i, v8::Int32::New(col->getColumnNo())); } pk_record->completeTableRecord(ndb_table); obj->Set(String::NewSymbol("columnNumbers"), idx_columns); obj->Set(String::NewSymbol("record"), Record_Wrapper(pk_record), ReadOnly); return scope.Close(obj); }
Handle<Object> GetTableCall::buildDBIndex(const NdbDictionary::Index *idx) { EscapableHandleScope scope(isolate); Local<Object> obj = NdbDictIndexEnv.newWrapper(); wrapPointerInObject(idx, NdbDictIndexEnv, obj); SET_RO_PROPERTY(obj, SYMBOL(isolate, "name"), String::NewFromUtf8(isolate, idx->getName())); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isPrimaryKey"), Boolean::New(isolate, false)); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isUnique"), Boolean::New(isolate, idx->getType() == NdbDictionary::Index::UniqueHashIndex)); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isOrdered"), Boolean::New(isolate, idx->getType() == NdbDictionary::Index::OrderedIndex)); /* Loop over the columns of the key. Build the "columns" array and the "record" object, then set both. */ int ncol = idx->getNoOfColumns(); Local<Array> idx_columns = Array::New(isolate, ncol); DEBUG_PRINT("Creating Index Record (%s)", idx->getName()); Record * idx_record = new Record(dict, ncol); for(int i = 0 ; i < ncol ; i++) { const char *colName = idx->getColumn(i)->getName(); const NdbDictionary::Column *col = ndb_table->getColumn(colName); idx_columns->Set(i, v8::Int32::New(isolate, col->getColumnNo())); idx_record->addColumn(col); } idx_record->completeIndexRecord(idx); SET_RO_PROPERTY(obj, SYMBOL(isolate, "record"), Record_Wrapper(idx_record)); obj->Set(SYMBOL(isolate, "columnNumbers"), idx_columns); return scope.Escape(obj); }
/* DBIndex = { name : "" , // Index name isPrimaryKey : true , // true for PK; otherwise undefined isUnique : true , // true or false isOrdered : true , // true or false; can scan if true columnNumbers : [] , // an ordered array of column numbers }; */ Handle<Object> GetTableCall::buildDBIndex_PK() { EscapableHandleScope scope(isolate); Local<Object> obj = Object::New(isolate); SET_RO_PROPERTY(obj, SYMBOL(isolate, "name"), String::NewFromUtf8(isolate, "PRIMARY_KEY")); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isPrimaryKey"), Boolean::New(isolate, true)); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isUnique"), Boolean::New(isolate, true)); SET_RO_PROPERTY(obj, SYMBOL(isolate, "isOrdered"), Boolean::New(isolate, false)); /* Loop over the columns of the key. Build the "columnNumbers" array and the "record" object, then set both. */ int ncol = ndb_table->getNoOfPrimaryKeys(); DEBUG_PRINT("Creating Primary Key Record"); Record * pk_record = new Record(dict, ncol); Local<Array> idx_columns = Array::New(isolate, ncol); for(int i = 0 ; i < ncol ; i++) { const char * col_name = ndb_table->getPrimaryKey(i); const NdbDictionary::Column * col = ndb_table->getColumn(col_name); pk_record->addColumn(col); idx_columns->Set(i, v8::Int32::New(isolate, col->getColumnNo())); } pk_record->completeTableRecord(ndb_table); obj->Set(SYMBOL(isolate, "columnNumbers"), idx_columns); SET_RO_PROPERTY(obj, SYMBOL(isolate, "record"), Record_Wrapper(pk_record)); return scope.Escape(obj); }
int create_table() { NdbDictionary::Dictionary* dict = g_ndb->getDictionary(); assert(dict); if(g_paramters[P_CREATE].value) { const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_table); assert(pTab); NdbDictionary::Table copy = * pTab; copy.setLogging(false); if(dict->createTable(copy) != 0) { g_err << "Failed to create table: " << g_table << endl; return -1; } NdbDictionary::Index x(g_ordered); x.setTable(g_table); x.setType(NdbDictionary::Index::OrderedIndex); x.setLogging(false); for (unsigned k = 0; k < copy.getNoOfColumns(); k++) { if(copy.getColumn(k)->getPrimaryKey()) { x.addColumn(copy.getColumn(k)->getName()); } } if(dict->createIndex(x) != 0) { g_err << "Failed to create index: " << endl; return -1; } x.setName(g_unique); x.setType(NdbDictionary::Index::UniqueHashIndex); if(dict->createIndex(x) != 0) { g_err << "Failed to create index: " << endl; return -1; } } g_tab = dict->getTable(g_table); g_i_unique = dict->getIndex(g_unique, g_table); g_i_ordered = dict->getIndex(g_ordered, g_table); assert(g_tab); assert(g_i_unique); assert(g_i_ordered); return 0; }
static int g_create_hook(Ndb* ndb, NdbDictionary::Table& tab, int when, void* arg) { if (when == 0) { if (g_diskbased) { for (int i = 0; i < tab.getNoOfColumns(); i++) { NdbDictionary::Column* col = tab.getColumn(i); if (! col->getPrimaryKey()) { col->setStorageType(NdbDictionary::Column::StorageTypeDisk); } } } if (g_tsname != NULL) { tab.setTablespaceName(g_tsname); } } return 0; }
NDBT_ResultRow::NDBT_ResultRow(const NdbDictionary::Table& tab, char attrib_delimiter) : cols(0), names(NULL), data(NULL), m_ownData(false), m_table(tab) { ad[0] = attrib_delimiter; ad[1] = 0; if (tab.getObjectStatus() == NdbDictionary::Object::Retrieved) { cols = tab.getNoOfColumns(); names = new char * [cols]; data = new NdbRecAttr * [cols]; for(int i = 0; i<cols; i++){ names[i] = new char[255]; strcpy(names[i], tab.getColumn(i)->getName()); } } }
/* * ForeignKeyMetadata = { name : "" , // Constraint name columnNames : null , // an ordered array of column numbers targetTable : "" , // referenced table name targetDatabase : "" , // referenced database name targetColumnNames: null , // an ordered array of target column names }; */ Handle<Object> GetTableCall::buildDBForeignKey(const NdbDictionary::ForeignKey *fk) { HandleScope scope; DictionaryNameSplitter localSplitter; Local<Object> js_fk = Object::New(); localSplitter.splitName(fk->getName()); // e.g. "12/20/fkname" js_fk->Set(String::NewSymbol("name"), String::New(localSplitter.part3)); // get child column names unsigned int childColumnCount = fk->getChildColumnCount(); Local<Array> fk_child_column_names = Array::New(childColumnCount); for (unsigned i = 0; i < childColumnCount; ++i) { int columnNumber = fk->getChildColumnNo(i); const NdbDictionary::Column * column = ndb_table->getColumn(columnNumber); fk_child_column_names->Set(i, String::New(column->getName())); } js_fk->Set(String::NewSymbol("columnNames"), fk_child_column_names); // get parent table (which might be in a different database) const char * fk_parent_name = fk->getParentTable(); localSplitter.splitName(fk_parent_name); const char * parent_db_name = localSplitter.part1; const char * parent_table_name = localSplitter.part3; js_fk->Set(String::NewSymbol("targetTable"), String::New(parent_table_name)); js_fk->Set(String::NewSymbol("targetDatabase"), String::New(parent_db_name)); ndb->setDatabaseName(parent_db_name); const NdbDictionary::Table * parent_table = dict->getTable(parent_table_name); ndb->setDatabaseName(dbName); // get parent column names unsigned int parentColumnCount = fk->getParentColumnCount(); Local<Array> fk_parent_column_names = Array::New(parentColumnCount); for (unsigned i = 0; i < parentColumnCount; ++i) { int columnNumber = fk->getParentColumnNo(i); const NdbDictionary::Column * column = parent_table->getColumn(columnNumber); fk_parent_column_names->Set(i, String::New( column->getName())); } js_fk->Set(String::NewSymbol("targetColumnNames"), fk_parent_column_names); return scope.Close(js_fk); }
int create_table(){ NdbDictionary::Dictionary* dict = g_ndb->getDictionary(); assert(dict); if(g_paramters[P_CREATE].value){ g_ndb->getDictionary()->dropTable(g_tablename); const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename); assert(pTab); NdbDictionary::Table copy = * pTab; copy.setLogging(false); if(dict->createTable(copy) != 0){ g_err << "Failed to create table: " << g_tablename << endl; return -1; } NdbDictionary::Index x(g_indexname); x.setTable(g_tablename); x.setType(NdbDictionary::Index::OrderedIndex); x.setLogging(false); for (unsigned k = 0; k < (unsigned) copy.getNoOfColumns(); k++){ if(copy.getColumn(k)->getPrimaryKey()){ x.addColumnName(copy.getColumn(k)->getName()); } } if(dict->createIndex(x) != 0){ g_err << "Failed to create index: " << endl; return -1; } } g_table = dict->getTable(g_tablename); g_index = dict->getIndex(g_indexname, g_tablename); assert(g_table); assert(g_index); /* Obtain NdbRecord instances for the table and index */ { NdbDictionary::RecordSpecification spec[ NDB_MAX_ATTRIBUTES_IN_TABLE ]; Uint32 offset=0; Uint32 cols= g_table->getNoOfColumns(); for (Uint32 colNum=0; colNum<cols; colNum++) { const NdbDictionary::Column* col= g_table->getColumn(colNum); Uint32 colLength= col->getLength(); spec[colNum].column= col; spec[colNum].offset= offset; offset+= colLength; spec[colNum].nullbit_byte_offset= offset++; spec[colNum].nullbit_bit_in_byte= 0; } g_table_record= dict->createRecord(g_table, &spec[0], cols, sizeof(NdbDictionary::RecordSpecification)); assert(g_table_record); } { NdbDictionary::RecordSpecification spec[ NDB_MAX_ATTRIBUTES_IN_TABLE ]; Uint32 offset=0; Uint32 cols= g_index->getNoOfColumns(); for (Uint32 colNum=0; colNum<cols; colNum++) { /* Get column from the underlying table */ // TODO : Add this mechanism to dict->createRecord // TODO : Add NdbRecord queryability methods so that an NdbRecord can // be easily built and later used to read out data. const NdbDictionary::Column* col= g_table->getColumn(g_index->getColumn(colNum)->getName()); Uint32 colLength= col->getLength(); spec[colNum].column= col; spec[colNum].offset= offset; offset+= colLength; spec[colNum].nullbit_byte_offset= offset++; spec[colNum].nullbit_bit_in_byte= 0; } g_index_record= dict->createRecord(g_index, &spec[0], cols, sizeof(NdbDictionary::RecordSpecification)); assert(g_index_record); } if(g_paramters[P_CREATE].value) { int rows = g_paramters[P_ROWS].value; HugoTransactions hugoTrans(* g_table); if (hugoTrans.loadTable(g_ndb, rows)){ g_err.println("Failed to load %s with %d rows", g_table->getName(), rows); return -1; } } return 0; }
/* doAsyncCallback() runs in the main thread. We don't want it to block. TODO: verify whether any IO is done by checking WaitMetaRequestCount at the start and end. */ void GetTableCall::doAsyncCallback(Local<Object> ctx) { HandleScope scope; DEBUG_PRINT("GetTableCall::doAsyncCallback: return_val %d", return_val); /* User callback arguments */ Handle<Value> cb_args[2]; cb_args[0] = Null(); cb_args[1] = Null(); /* TableMetadata = { database : "" , // Database name name : "" , // Table Name columns : [] , // ordered array of DBColumn objects indexes : [] , // array of DBIndex objects partitionKey : [] , // ordered array of column numbers in the partition key }; */ if(ndb_table && ! return_val) { Local<Object> table = NdbDictTableEnv.newWrapper(); wrapPointerInObject(ndb_table, NdbDictTableEnv, table); // database table->Set(String::NewSymbol("database"), String::New(arg1)); // name table->Set(String::NewSymbol("name"), String::New(ndb_table->getName())); // columns Local<Array> columns = Array::New(ndb_table->getNoOfColumns()); for(int i = 0 ; i < ndb_table->getNoOfColumns() ; i++) { Handle<Object> col = buildDBColumn(ndb_table->getColumn(i)); columns->Set(i, col); } table->Set(String::NewSymbol("columns"), columns); // indexes (primary key & secondary) Local<Array> js_indexes = Array::New(idx_list.count + 1); js_indexes->Set(0, buildDBIndex_PK()); // primary key for(unsigned int i = 0 ; i < idx_list.count ; i++) { // secondary indexes const NdbDictionary::Index * idx = arg0->dict->getIndex(idx_list.elements[i].name, arg2); js_indexes->Set(i+1, buildDBIndex(idx)); } table->Set(String::NewSymbol("indexes"), js_indexes, ReadOnly); // partitionKey // Table Record (implementation artifact; not part of spec) DEBUG_PRINT("Creating Table Record"); Record * rec = new Record(arg0->dict, ndb_table->getNoOfColumns()); for(int i = 0 ; i < ndb_table->getNoOfColumns() ; i++) { rec->addColumn(ndb_table->getColumn(i)); } rec->completeTableRecord(ndb_table); table->Set(String::NewSymbol("record"), Record_Wrapper(rec)); // User Callback cb_args[1] = table; } else { cb_args[0] = String::New(arg0->dict->getNdbError().message); } callback->Call(ctx, 2, cb_args); }
/* doAsyncCallback() runs in the main thread. We don't want it to block. TODO: verify whether any IO is done by checking WaitMetaRequestCount at the start and end. */ void GetTableCall::doAsyncCallback(Local<Object> ctx) { const char *tableName; HandleScope scope; DEBUG_PRINT("GetTableCall::doAsyncCallback: return_val %d", return_val); /* User callback arguments */ Handle<Value> cb_args[2]; cb_args[0] = Null(); cb_args[1] = Null(); /* TableMetadata = { database : "" , // Database name name : "" , // Table Name columns : [] , // ordered array of DBColumn objects indexes : [] , // array of DBIndex objects partitionKey : [] , // ordered array of column numbers in the partition key }; */ if(ndb_table && ! return_val) { Local<Object> table = NdbDictTableEnv.newWrapper(); const NdbDictionary::Table * js_ndb_table = ndb_table; wrapPointerInObject(js_ndb_table, NdbDictTableEnv, table); // database table->Set(String::NewSymbol("database"), String::New(arg1)); // name tableName = ndb_table->getName(); table->Set(String::NewSymbol("name"), String::New(tableName)); // partitionKey int nPartitionKeys = 0; Handle<Array> partitionKeys = Array::New(); table->Set(String::NewSymbol("partitionKey"), partitionKeys); // columns Local<Array> columns = Array::New(ndb_table->getNoOfColumns()); for(int i = 0 ; i < ndb_table->getNoOfColumns() ; i++) { const NdbDictionary::Column *ndb_col = ndb_table->getColumn(i); Handle<Object> col = buildDBColumn(ndb_col); columns->Set(i, col); if(ndb_col->getPartitionKey()) { /* partition key */ partitionKeys->Set(nPartitionKeys++, String::New(ndb_col->getName())); } } table->Set(String::NewSymbol("columns"), columns); // indexes (primary key & secondary) Local<Array> js_indexes = Array::New(idx_list.count + 1); js_indexes->Set(0, buildDBIndex_PK()); // primary key for(unsigned int i = 0 ; i < idx_list.count ; i++) { // secondary indexes const NdbDictionary::Index * idx = dict->getIndex(idx_list.elements[i].name, arg2); js_indexes->Set(i+1, buildDBIndex(idx)); } table->Set(String::NewSymbol("indexes"), js_indexes, ReadOnly); // Table Record (implementation artifact; not part of spec) DEBUG_PRINT("Creating Table Record"); Record * rec = new Record(dict, ndb_table->getNoOfColumns()); for(int i = 0 ; i < ndb_table->getNoOfColumns() ; i++) { rec->addColumn(ndb_table->getColumn(i)); } rec->completeTableRecord(ndb_table); table->Set(String::NewSymbol("record"), Record_Wrapper(rec)); // foreign keys (only foreign keys for which this table is the child) // now create the javascript foreign key metadata objects for dictionary objects cached earlier Local<Array> js_fks = Array::New(fk_count); int fk_number = 0; for(unsigned int i = 0 ; i < fk_list.count ; i++) { NdbDictionary::ForeignKey fk; if (fk_list.elements[i].type == NdbDictionary::Object::ForeignKey) { const char * fk_name = fk_list.elements[i].name; int fkGetCode = dict->getForeignKey(fk, fk_name); DEBUG_PRINT("getForeignKey for %s returned %i", fk_name, fkGetCode); // see if the foreign key child table is this table if(splitNameMatchesDbAndTable(fk.getChildTable())) { // the foreign key child table is this table; build the fk object DEBUG_PRINT("Adding foreign key for %s at %i", fk.getName(), fk_number); js_fks->Set(fk_number++, buildDBForeignKey(&fk)); } } } table->Set(String::NewSymbol("foreignKeys"), js_fks, ReadOnly); // Autoincrement Cache Impl (also not part of spec) if(per_table_ndb) { table->Set(String::NewSymbol("per_table_ndb"), Ndb_Wrapper(per_table_ndb)); } // User Callback cb_args[1] = table; } else { cb_args[0] = NdbError_Wrapper(* ndbError); } callback->Call(ctx, 2, cb_args); }
/* doAsyncCallback() runs in the main thread. We don't want it to block. TODO: verify whether any IO is done by checking WaitMetaRequestCount at the start and end. */ void GetTableCall::doAsyncCallback(Local<Object> ctx) { const char *ndbTableName; EscapableHandleScope scope(isolate); DEBUG_PRINT("GetTableCall::doAsyncCallback: return_val %d", return_val); /* User callback arguments */ Handle<Value> cb_args[2]; cb_args[0] = Null(isolate); cb_args[1] = Null(isolate); /* TableMetadata = { database : "" , // Database name name : "" , // Table Name columns : [] , // ordered array of DBColumn objects indexes : [] , // array of DBIndex objects partitionKey : [] , // ordered array of column numbers in the partition key sparseContainer : null // default column for sparse fields }; */ if(ndb_table && ! return_val) { Local<Object> table = NdbDictTableEnv.wrap(ndb_table)->ToObject(); // database table->Set(SYMBOL(isolate, "database"), String::NewFromUtf8(isolate, arg1)); // name ndbTableName = ndb_table->getName(); table->Set(SYMBOL(isolate, "name"), String::NewFromUtf8(isolate, ndbTableName)); // partitionKey int nPartitionKeys = 0; Handle<Array> partitionKeys = Array::New(isolate); table->Set(SYMBOL(isolate, "partitionKey"), partitionKeys); // sparseContainer table->Set(SYMBOL(isolate,"sparseContainer"), Null(isolate)); // columns Local<Array> columns = Array::New(isolate, ndb_table->getNoOfColumns()); for(int i = 0 ; i < ndb_table->getNoOfColumns() ; i++) { const NdbDictionary::Column *ndb_col = ndb_table->getColumn(i); Handle<Object> col = buildDBColumn(ndb_col); columns->Set(i, col); if(ndb_col->getPartitionKey()) { /* partition key */ partitionKeys->Set(nPartitionKeys++, String::NewFromUtf8(isolate, ndb_col->getName())); } if( ! strcmp(ndb_col->getName(), "SPARSE_FIELDS") && ( (! strncmp(getColumnType(ndb_col), "VARCHAR", 7) && (getEncoderCharsetForColumn(ndb_col)->isUnicode)) || ( ! strncmp(getColumnType(ndb_col), "VARBINARY", 9) || ! strncmp(getColumnType(ndb_col), "JSON", 4)))) { table->Set(SYMBOL(isolate,"sparseContainer"), String::NewFromUtf8(isolate, ndb_col->getName())); } } table->Set(SYMBOL(isolate, "columns"), columns); // indexes (primary key & secondary) Local<Array> js_indexes = Array::New(isolate, idx_list.count + 1); js_indexes->Set(0, buildDBIndex_PK()); // primary key for(unsigned int i = 0 ; i < idx_list.count ; i++) { // secondary indexes const NdbDictionary::Index * idx = dict->getIndex(idx_list.elements[i].name, arg2); js_indexes->Set(i+1, buildDBIndex(idx)); } SET_RO_PROPERTY(table, SYMBOL(isolate, "indexes"), js_indexes); // foreign keys (only foreign keys for which this table is the child) // now create the javascript foreign key metadata objects for dictionary objects cached earlier Local<Array> js_fks = Array::New(isolate, fk_count); int fk_number = 0; for(unsigned int i = 0 ; i < fk_list.count ; i++) { NdbDictionary::ForeignKey fk; if (fk_list.elements[i].type == NdbDictionary::Object::ForeignKey) { const char * fk_name = fk_list.elements[i].name; int fkGetCode = dict->getForeignKey(fk, fk_name); DEBUG_PRINT("getForeignKey for %s returned %i", fk_name, fkGetCode); // see if the foreign key child table is this table if(splitNameMatchesDbAndTable(fk.getChildTable())) { // the foreign key child table is this table; build the fk object DEBUG_PRINT("Adding foreign key for %s at %i", fk.getName(), fk_number); js_fks->Set(fk_number++, buildDBForeignKey(&fk)); } } } SET_RO_PROPERTY(table, SYMBOL(isolate, "foreignKeys"), js_fks); // Autoincrement Cache Impl (also not part of spec) if(per_table_ndb) { table->Set(SYMBOL(isolate, "per_table_ndb"), Ndb_Wrapper(per_table_ndb)); } // User Callback cb_args[1] = table; } else { cb_args[0] = NdbError_Wrapper(* ndbError); } ToLocal(& callback)->Call(ctx, 2, cb_args); }