#pragma once #include namespace scdriver { class c_table_schema; /************************************** * * class: c _ c o l u m n _ s c h e m a * ************************************** * * Functional description * * store cached table's columns **************************************/ class c_column_schema { public: c_column_schema() { table_id= 0; pos = 0; id = 0; type = 0; type_sz = 0; default_func = 0; nullable = 0; uniqness= 0; avg_size= 0; default_val = 0; comment = 0; }; c_column_schema(const unsigned hyper&_table_id, const unsigned short&_pos, const unsigned short&_id, char *_name, const unsigned short&_type, const unsigned short&_type_sz, char *_default_val, const int &_default_func, const bool &_nullable, char *_comment, const double &_uniqness, const unsigned long &_avg_size) { table_id = _table_id; pos = _pos; id = _id; type = _type; type_sz = _type_sz; default_func = _default_func; nullable = _nullable; uniqness= _uniqness; avg_size= _avg_size; strcpy(name,_name); if(_default_val) { int len = strlen(_default_val)+1; default_val = (char*)malloc(len); memcpy(default_val,_default_val,len); } else default_val = 0; if(_comment) { int len = strlen(_comment)+1; comment = (char*)malloc(len); memcpy(comment,_comment,len); } else comment = 0; }; c_column_schema(const c_column_schema &col) { table_id= col.table_id; pos = col.pos; id = col.id; type = col.type; default_func = col.default_func; nullable = col.nullable; type_sz = col.type_sz; uniqness= col.uniqness; avg_size= col.avg_size; strcpy(name,col.name); if(col.default_val) { int len = strlen(col.default_val)+1; default_val = (char*)malloc(len); memcpy(default_val,col.default_val,len); } else default_val = 0; if(col.comment) { int len = strlen(col.comment)+1; comment = (char*)malloc(len); memcpy(comment,col.comment,len); } else comment = 0; }; void operator= (const c_column_schema &col) { table_id= col.table_id; pos = col.pos; id = col.id; type = col.type; default_func = col.default_func; nullable = col.nullable; type_sz = col.type_sz; uniqness= col.uniqness; avg_size= col.avg_size; strcpy(name,col.name); if(col.default_val) { int len = strlen(col.default_val)+1; default_val = (char*)malloc(len); memcpy(default_val,col.default_val,len); } else default_val = 0; if(col.comment) { int len = strlen(col.comment)+1; comment = (char*)malloc(len); memcpy(comment,col.comment,len); } else comment = 0; }; ~c_column_schema() { if(default_val) free(default_val); if(comment) free(comment); }; unsigned hyper table_id; unsigned short pos; // declaration position of the columns unsigned short id; // column's physical position in the table's file char name[128]; unsigned short type; char *default_val; int default_func; // 1 bool nullable; char *comment; unsigned short type_sz; double uniqness; unsigned long avg_size; }; /************************************** * * class: c _ i n d e x _ s c h e m a * ************************************** * * Functional description * * store cached table's indexes **************************************/ class c_index_schema { public: c_index_schema() { }; c_index_schema(c_table_schema *_table, std::deque &_columns, const short &_id, char *_name, char *_keys, const hyper &_ref_table_id, const short &_ref_id, const short &_on_update, const short &_on_delete, const bool &_unique, const unsigned long &_height, const unsigned long &_dpages) { nkeys = 0; table = _table; id = _id; strcpy(name,_name); ref_table_id = _ref_table_id; ref_id = _ref_id; on_update= _on_update; on_delete= _on_delete; unique = _unique; height = _height; dpages = _dpages; // parse key string: id1|id2|id3 char sid[32]; short ipos[32]; int i = 0; char *tmp = _keys; while(*tmp) { if(*tmp == '|') { sid[i] = 0; ipos[nkeys++] = atoi(sid); // translate to name i = 0; *tmp++; } else sid[i++] = *tmp++; } for(i = 0; i < nkeys; i++) { for(std::deque::iterator it = _columns.begin(); it != _columns.end(); it++) { if((*it).id == ipos[i]) { keys[i] = &(*it); break; } } } }; c_index_schema(c_table_schema *_table, std::deque &_columns, const short &_id, char *_name, const unsigned short &_nkeys, unsigned short *_keys, const hyper &_ref_table_id, const short &_ref_id, const short &_on_update, const short &_on_delete, const bool &_unique, const unsigned long &_height, const unsigned long &_dpages) { nkeys = _nkeys; table = _table; id = _id; strcpy(name,_name); ref_table_id = _ref_table_id; ref_id = _ref_id; on_update= _on_update; on_delete= _on_delete; unique = _unique; height = _height; dpages = _dpages; for(int i = 0; i < nkeys; i++) { for(std::deque::iterator it = _columns.begin(); it != _columns.end(); it++) { if((*it).id == _keys[i]) { keys[i] = &(*it); break; } } } }; c_table_schema *table; unsigned short id; char name[64]; c_column_schema *keys[32]; unsigned short nkeys; unsigned hyper ref_table_id; unsigned short ref_id; unsigned short on_update; unsigned short on_delete; bool unique; unsigned long height; unsigned long dpages; }; /************************************** * * class: c _ t a b l e _ s c h e m a * ************************************** * * Functional description * * store cached table's structure, columns, indexes * and statistics for the fast access during * SQL optimization **************************************/ class c_table_schema { public: typedef std::deque COLUMN_LIST; typedef std::deque INDEX_LIST; public: c_table_schema(const char *_catalog, const char *_name) { strcpy(catalog,_catalog); strcpy(name,_name); }; /************************************** * * function: g e t _ i n d e x * ************************************** * * Functional description * * return index properties instance **************************************/ c_index_schema &get_index(const unsigned short &_id) { return index_map.at(_id); }; /************************************** * * function: g e t _ i n d e x * ************************************** * * Functional description * * return index properties instance **************************************/ c_index_schema *get_index(const char *_name) { int sz = index_map.size(); for(int i = 0; i < sz; i++) { if(!stricmp(index_map.at(i).name,_name)) return &index_map.at(i); } return 0; }; /************************************** * * function: g e t _ c o l u m n * ************************************** * * Functional description * * return column properties **************************************/ c_column_schema &get_column(const char *_name) { for(COLUMN_LIST::iterator it = column_map.begin(); it != column_map.end(); it++) { if(!stricmp((*it).name,_name)) return (*it); } throw node_exception(12,1,0,_name); }; /************************************** * * function: has_identity_column * ************************************** * * Functional description * * return the list of columns having default function * AutoIdenity() **************************************/ int has_identity_column(unsigned short *ids/*[256]*/) { int nids = 0; for(COLUMN_LIST::iterator it = column_map.begin(); it != column_map.end(); it++) { if((*it).default_func == 34) ids[nids++] = (*it).id; } return nids; }; /************************************** * * function: l o a d * ************************************** * * Functional description * * read all table's columns & indexes **************************************/ void load(CConnection *conn) { char sql[8192]; // read columns sprintf(sql,"select * from system.syscolumns \ where table_id in (select id from system.systables where name = \'%s\' and \ catalog_id in (select id from system.syscatalogs where name=\'%s\') )",name,catalog); CRecordset cols; cols.Open(conn,sql); conn->GetCompletionStatus(); while(!cols.IsEOF()) { unsigned __int64 table_id; unsigned short pos; unsigned short id; char cname[128]; unsigned short type; unsigned short type_sz; char def_val[8000]; unsigned short def_func; unsigned short null; char comment[8000]; double unique; int avg; int size; size = 8; cols.GetFieldInfo(0)->data.ReadField(&table_id,&size); size = 2; cols.GetFieldInfo(1)->data.ReadField(&pos,&size); size = 2; cols.GetFieldInfo(2)->data.ReadField(&id,&size); size = 128; cols.GetFieldInfo(3)->data.ReadField(cname,&size); size = 2; cols.GetFieldInfo(4)->data.ReadField(&type,&size); size = 2; cols.GetFieldInfo(5)->data.ReadField(&type_sz,&size); size = 8000; cols.GetFieldInfo(6)->data.ReadField(def_val,&size); size = 2; cols.GetFieldInfo(7)->data.ReadField(&def_func,&size); size = 2; cols.GetFieldInfo(8)->data.ReadField(&null,&size); size = 8000; cols.GetFieldInfo(9)->data.ReadField(comment,&size); size = 8; cols.GetFieldInfo(10)->data.ReadField(&unique,&size); size = 4; cols.GetFieldInfo(11)->data.ReadField(&avg,&size); c_column_schema column( table_id, pos, id, cname, type, type_sz, (def_val[0])?def_val:0, def_func, null, (comment[0])?comment:0, unique, avg); column_map.push_back(column); cols.Next(); } // read indexes sprintf(sql,"select * from system.sysindexes \ where table_id in (select id from system.systables where name = \'%s\' and \ catalog_id in (select id from system.syscatalogs where name=\'%s\') )",name,catalog); CRecordset idx; idx.Open(conn,sql); conn->GetCompletionStatus(); while(!idx.IsEOF()) { unsigned __int64 table_id; unsigned short id; char iname[128]; char keys[128]; unsigned __int64 ref_table_id; unsigned short ref_id; unsigned short on_delete; unsigned short on_update; unsigned short unique; int height; int dpages; int size; size = 8; idx.GetFieldInfo(0)->data.ReadField(&table_id,&size); size = 2; idx.GetFieldInfo(1)->data.ReadField(&id,&size); size = 128; idx.GetFieldInfo(2)->data.ReadField(iname,&size); size = 128; idx.GetFieldInfo(3)->data.ReadField(keys,&size); size = 8; idx.GetFieldInfo(4)->data.ReadField(&ref_table_id,&size); size = 2; idx.GetFieldInfo(5)->data.ReadField(&ref_id,&size); size = 2; idx.GetFieldInfo(6)->data.ReadField(&on_update,&size); size = 2; idx.GetFieldInfo(7)->data.ReadField(&on_delete,&size); size = 2; idx.GetFieldInfo(8)->data.ReadField(&unique,&size); size = 4; idx.GetFieldInfo(9)->data.ReadField(&height,&size); size = 4; idx.GetFieldInfo(10)->data.ReadField(&dpages,&size); c_index_schema index(this, column_map, id, iname, keys, ref_table_id, ref_id, on_update, on_delete, unique, height, dpages); if(ref_id != 256) index_map.push_back(index); idx.Next(); } }; COLUMN_LIST *get_columns() { return &column_map; }; INDEX_LIST *get_indexes() { return &index_map; }; char catalog[64]; char name[64]; COLUMN_LIST column_map; INDEX_LIST index_map; }; };