00001 #include "DS_Table.h"
00002 #include "DS_OrderedList.h"
00003 #include <string.h>
00004 #include "RakAssert.h"
00005 #include "RakAssert.h"
00006 #include "Itoa.h"
00007
00008 using namespace DataStructures;
00009
00010 #ifdef _MSC_VER
00011 #pragma warning( push )
00012 #endif
00013
00014 void ExtendRows(Table::Row* input, int index)
00015 {
00016 (void) index;
00017 input->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
00018 }
00019 void FreeRow(Table::Row* input, int index)
00020 {
00021 (void) index;
00022
00023 unsigned i;
00024 for (i=0; i < input->cells.Size(); i++)
00025 {
00026 RakNet::OP_DELETE(input->cells[i], __FILE__, __LINE__);
00027 }
00028 RakNet::OP_DELETE(input, __FILE__, __LINE__);
00029 }
00030 Table::Cell::Cell()
00031 {
00032 isEmpty=true;
00033 c=0;
00034 ptr=0;
00035 i=0.0;
00036 }
00037 Table::Cell::~Cell()
00038 {
00039 Clear();
00040 }
00041 Table::Cell& Table::Cell::operator = ( const Table::Cell& input )
00042 {
00043 isEmpty=input.isEmpty;
00044 i=input.i;
00045 ptr=input.ptr;
00046 if (c)
00047 rakFree_Ex(c, __FILE__, __LINE__);
00048 if (input.c)
00049 {
00050 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
00051 memcpy(c, input.c, (int) i);
00052 }
00053 else
00054 c=0;
00055 return *this;
00056 }
00057 Table::Cell::Cell( const Table::Cell & input)
00058 {
00059 isEmpty=input.isEmpty;
00060 i=input.i;
00061 ptr=input.ptr;
00062 if (input.c)
00063 {
00064 if (c)
00065 rakFree_Ex(c, __FILE__, __LINE__);
00066 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
00067 memcpy(c, input.c, (int) i);
00068 }
00069 }
00070 void Table::Cell::Set(double input)
00071 {
00072 Clear();
00073 i=input;
00074 c=0;
00075 ptr=0;
00076 isEmpty=false;
00077 }
00078 void Table::Cell::Set(unsigned int input)
00079 {
00080 Set((int) input);
00081 }
00082 void Table::Cell::Set(int input)
00083 {
00084 Clear();
00085 i=(double) input;
00086 c=0;
00087 ptr=0;
00088 isEmpty=false;
00089 }
00090
00091 void Table::Cell::Set(const char *input)
00092 {
00093 Clear();
00094
00095 if (input)
00096 {
00097 i=(int)strlen(input)+1;
00098 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
00099 strcpy(c, input);
00100 }
00101 else
00102 {
00103 c=0;
00104 i=0;
00105 }
00106 ptr=0;
00107 isEmpty=false;
00108 }
00109 void Table::Cell::Set(const char *input, int inputLength)
00110 {
00111 Clear();
00112 if (input)
00113 {
00114 c = (char*) rakMalloc_Ex( inputLength, __FILE__, __LINE__ );
00115 i=inputLength;
00116 memcpy(c, input, inputLength);
00117 }
00118 else
00119 {
00120 c=0;
00121 i=0;
00122 }
00123 ptr=0;
00124 isEmpty=false;
00125 }
00126 void Table::Cell::SetPtr(void* p)
00127 {
00128 Clear();
00129 c=0;
00130 ptr=p;
00131 isEmpty=false;
00132 }
00133 void Table::Cell::Get(int *output)
00134 {
00135 RakAssert(isEmpty==false);
00136 int o = (int) i;
00137 *output=o;
00138 }
00139 void Table::Cell::Get(double *output)
00140 {
00141 RakAssert(isEmpty==false);
00142 *output=i;
00143 }
00144 void Table::Cell::Get(char *output)
00145 {
00146 RakAssert(isEmpty==false);
00147 strcpy(output, c);
00148 }
00149 void Table::Cell::Get(char *output, int *outputLength)
00150 {
00151 RakAssert(isEmpty==false);
00152 memcpy(output, c, (int) i);
00153 if (outputLength)
00154 *outputLength=(int) i;
00155 }
00156 RakNet::RakString Table::Cell::ToString(ColumnType columnType)
00157 {
00158 if (isEmpty)
00159 return RakNet::RakString();
00160
00161 if (columnType==NUMERIC)
00162 {
00163 return RakNet::RakString("%f", i);
00164 }
00165 else if (columnType==STRING)
00166 {
00167 return RakNet::RakString(c);
00168 }
00169 else if (columnType==BINARY)
00170 {
00171 return RakNet::RakString("<Binary>");
00172 }
00173 else if (columnType==POINTER)
00174 {
00175 return RakNet::RakString("%p", ptr);
00176 }
00177
00178 return RakNet::RakString();
00179 }
00180 Table::Cell::Cell(double numericValue, char *charValue, void *ptr, ColumnType type)
00181 {
00182 SetByType(numericValue,charValue,ptr,type);
00183 }
00184 void Table::Cell::SetByType(double numericValue, char *charValue, void *ptr, ColumnType type)
00185 {
00186 isEmpty=true;
00187 if (type==NUMERIC)
00188 {
00189 Set(numericValue);
00190 }
00191 else if (type==STRING)
00192 {
00193 Set(charValue);
00194 }
00195 else if (type==BINARY)
00196 {
00197 Set(charValue, (int) numericValue);
00198 }
00199 else if (type==POINTER)
00200 {
00201 SetPtr(ptr);
00202 }
00203 else
00204 {
00205 ptr=(void*) charValue;
00206 }
00207 }
00208 Table::ColumnType Table::Cell::EstimateColumnType(void) const
00209 {
00210 if (c)
00211 if (i!=0.0f)
00212 return BINARY;
00213 else
00214 return STRING;
00215 if (ptr)
00216 return POINTER;
00217 return NUMERIC;
00218 }
00219 void Table::Cell::Clear(void)
00220 {
00221 if (isEmpty==false && c)
00222 {
00223 rakFree_Ex(c, __FILE__, __LINE__);
00224 c=0;
00225 }
00226 isEmpty=true;
00227 }
00228 Table::ColumnDescriptor::ColumnDescriptor()
00229 {
00230
00231 }
00232 Table::ColumnDescriptor::~ColumnDescriptor()
00233 {
00234
00235 }
00236 Table::ColumnDescriptor::ColumnDescriptor(const char cn[_TABLE_MAX_COLUMN_NAME_LENGTH], ColumnType ct)
00237 {
00238 columnType=ct;
00239 strcpy(columnName, cn);
00240 }
00241 void Table::Row::UpdateCell(unsigned columnIndex, double value)
00242 {
00243 cells[columnIndex]->Clear();
00244 cells[columnIndex]->Set(value);
00245
00246
00247
00248
00249 }
00250 void Table::Row::UpdateCell(unsigned columnIndex, const char *str)
00251 {
00252 cells[columnIndex]->Clear();
00253 cells[columnIndex]->Set(str);
00254 }
00255 void Table::Row::UpdateCell(unsigned columnIndex, int byteLength, const char *data)
00256 {
00257 cells[columnIndex]->Clear();
00258 cells[columnIndex]->Set(data,byteLength);
00259 }
00260 Table::Table()
00261 {
00262 }
00263 Table::~Table()
00264 {
00265 Clear();
00266 }
00267 unsigned Table::AddColumn(const char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH], ColumnType columnType)
00268 {
00269 if (columnName[0]==0)
00270 return (unsigned) -1;
00271
00272
00273 columns.Insert(Table::ColumnDescriptor(columnName, columnType), __FILE__, __LINE__);
00274
00275
00276 rows.ForEachData(ExtendRows);
00277
00278 return columns.Size()-1;
00279 }
00280 void Table::RemoveColumn(unsigned columnIndex)
00281 {
00282 if (columnIndex >= columns.Size())
00283 return;
00284
00285 columns.RemoveAtIndex(columnIndex);
00286
00287
00288 int i;
00289 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
00290 while (cur)
00291 {
00292 for (i=0; i < cur->size; i++)
00293 {
00294 RakNet::OP_DELETE(cur->data[i]->cells[columnIndex], __FILE__, __LINE__);
00295 cur->data[i]->cells.RemoveAtIndex(columnIndex);
00296 }
00297
00298 cur=cur->next;
00299 }
00300 }
00301 unsigned Table::ColumnIndex(const char *columnName) const
00302 {
00303 unsigned columnIndex;
00304 for (columnIndex=0; columnIndex<columns.Size(); columnIndex++)
00305 if (strcmp(columnName, columns[columnIndex].columnName)==0)
00306 return columnIndex;
00307 return (unsigned)-1;
00308 }
00309 unsigned Table::ColumnIndex(char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH]) const
00310 {
00311 return ColumnIndex((const char *) columnName);
00312 }
00313 char* Table::ColumnName(unsigned index) const
00314 {
00315 if (index >= columns.Size())
00316 return 0;
00317 else
00318 return (char*)columns[index].columnName;
00319 }
00320 Table::ColumnType Table::GetColumnType(unsigned index) const
00321 {
00322 if (index >= columns.Size())
00323 return (Table::ColumnType) 0;
00324 else
00325 return columns[index].columnType;
00326 }
00327 unsigned Table::GetColumnCount(void) const
00328 {
00329 return columns.Size();
00330 }
00331 unsigned Table::GetRowCount(void) const
00332 {
00333 return rows.Size();
00334 }
00335 Table::Row* Table::AddRow(unsigned rowId)
00336 {
00337 Row *newRow;
00338 newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
00339 if (rows.Insert(rowId, newRow)==false)
00340 {
00341 RakNet::OP_DELETE(newRow, __FILE__, __LINE__);
00342 return 0;
00343 }
00344 unsigned rowIndex;
00345 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
00346 newRow->cells.Insert( RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
00347 return newRow;
00348 }
00349 Table::Row* Table::AddRow(unsigned rowId, DataStructures::List<Cell> &initialCellValues)
00350 {
00351 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
00352 unsigned rowIndex;
00353 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
00354 {
00355 if (rowIndex < initialCellValues.Size() && initialCellValues[rowIndex].isEmpty==false)
00356 {
00357 Table::Cell *c;
00358 c = RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__);
00359 c->SetByType(initialCellValues[rowIndex].i,initialCellValues[rowIndex].c,initialCellValues[rowIndex].ptr,columns[rowIndex].columnType);
00360 newRow->cells.Insert(c, __FILE__, __LINE__ );
00361 }
00362 else
00363 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
00364 }
00365 rows.Insert(rowId, newRow);
00366 return newRow;
00367 }
00368 Table::Row* Table::AddRow(unsigned rowId, DataStructures::List<Cell*> &initialCellValues, bool copyCells)
00369 {
00370 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
00371 unsigned rowIndex;
00372 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
00373 {
00374 if (rowIndex < initialCellValues.Size() && initialCellValues[rowIndex] && initialCellValues[rowIndex]->isEmpty==false)
00375 {
00376 if (copyCells==false)
00377 newRow->cells.Insert(RakNet::OP_NEW_4<Table::Cell>( __FILE__, __LINE__, initialCellValues[rowIndex]->i, initialCellValues[rowIndex]->c, initialCellValues[rowIndex]->ptr, columns[rowIndex].columnType), __FILE__, __LINE__);
00378 else
00379 {
00380 Table::Cell *c = RakNet::OP_NEW<Table::Cell>( __FILE__, __LINE__ );
00381 newRow->cells.Insert(c, __FILE__, __LINE__);
00382 *c=*(initialCellValues[rowIndex]);
00383 }
00384 }
00385 else
00386 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__);
00387 }
00388 rows.Insert(rowId, newRow);
00389 return newRow;
00390 }
00391 Table::Row* Table::AddRowColumns(unsigned rowId, Row *row, DataStructures::List<unsigned> columnIndices)
00392 {
00393 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
00394 unsigned columnIndex;
00395 for (columnIndex=0; columnIndex < columnIndices.Size(); columnIndex++)
00396 {
00397 if (row->cells[columnIndices[columnIndex]]->isEmpty==false)
00398 {
00399 newRow->cells.Insert(RakNet::OP_NEW_4<Table::Cell>( __FILE__, __LINE__,
00400 row->cells[columnIndices[columnIndex]]->i,
00401 row->cells[columnIndices[columnIndex]]->c,
00402 row->cells[columnIndices[columnIndex]]->ptr,
00403 columns[columnIndex].columnType
00404 ), __FILE__, __LINE__);
00405 }
00406 else
00407 {
00408 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__);
00409 }
00410 }
00411 rows.Insert(rowId, newRow);
00412 return newRow;
00413 }
00414 bool Table::RemoveRow(unsigned rowId)
00415 {
00416 Row *out;
00417 if (rows.Delete(rowId, out))
00418 {
00419 DeleteRow(out);
00420 return true;
00421 }
00422 return false;
00423 }
00424 void Table::RemoveRows(Table *tableContainingRowIDs)
00425 {
00426 unsigned i;
00427 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = tableContainingRowIDs->GetRows().GetListHead();
00428 while (cur)
00429 {
00430 for (i=0; i < (unsigned)cur->size; i++)
00431 {
00432 rows.Delete(cur->keys[i]);
00433 }
00434 cur=cur->next;
00435 }
00436 return;
00437 }
00438 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, int value)
00439 {
00440 RakAssert(columns[columnIndex].columnType==NUMERIC);
00441
00442 Row *row = GetRowByID(rowId);
00443 if (row)
00444 {
00445 row->UpdateCell(columnIndex, value);
00446 return true;
00447 }
00448 return false;
00449 }
00450 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, char *str)
00451 {
00452 RakAssert(columns[columnIndex].columnType==STRING);
00453
00454 Row *row = GetRowByID(rowId);
00455 if (row)
00456 {
00457 row->UpdateCell(columnIndex, str);
00458 return true;
00459 }
00460 return false;
00461 }
00462 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, int byteLength, char *data)
00463 {
00464 RakAssert(columns[columnIndex].columnType==BINARY);
00465
00466 Row *row = GetRowByID(rowId);
00467 if (row)
00468 {
00469 row->UpdateCell(columnIndex, byteLength, data);
00470 return true;
00471 }
00472 return false;
00473 }
00474 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int value)
00475 {
00476 RakAssert(columns[columnIndex].columnType==NUMERIC);
00477
00478 Row *row = GetRowByIndex(rowIndex,0);
00479 if (row)
00480 {
00481 row->UpdateCell(columnIndex, value);
00482 return true;
00483 }
00484 return false;
00485 }
00486 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, char *str)
00487 {
00488 RakAssert(columns[columnIndex].columnType==STRING);
00489
00490 Row *row = GetRowByIndex(rowIndex,0);
00491 if (row)
00492 {
00493 row->UpdateCell(columnIndex, str);
00494 return true;
00495 }
00496 return false;
00497 }
00498 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int byteLength, char *data)
00499 {
00500 RakAssert(columns[columnIndex].columnType==BINARY);
00501
00502 Row *row = GetRowByIndex(rowIndex,0);
00503 if (row)
00504 {
00505 row->UpdateCell(columnIndex, byteLength, data);
00506 return true;
00507 }
00508 return false;
00509 }
00510 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, int *output)
00511 {
00512 RakAssert(columns[columnIndex].columnType==NUMERIC);
00513
00514 Row *row = GetRowByIndex(rowIndex,0);
00515 if (row)
00516 {
00517 row->cells[columnIndex]->Get(output);
00518 }
00519 }
00520 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output)
00521 {
00522 RakAssert(columns[columnIndex].columnType==STRING);
00523
00524 Row *row = GetRowByIndex(rowIndex,0);
00525 if (row)
00526 {
00527 row->cells[columnIndex]->Get(output);
00528 }
00529 }
00530 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output, int *outputLength)
00531 {
00532 RakAssert(columns[columnIndex].columnType==BINARY);
00533
00534 Row *row = GetRowByIndex(rowIndex,0);
00535 if (row)
00536 {
00537 row->cells[columnIndex]->Get(output, outputLength);
00538 }
00539 }
00540 Table::FilterQuery::FilterQuery()
00541 {
00542 columnName[0]=0;
00543 }
00544 Table::FilterQuery::~FilterQuery()
00545 {
00546
00547 }
00548 Table::FilterQuery::FilterQuery(unsigned column, Cell *cell, FilterQueryType op)
00549 {
00550 columnIndex=column;
00551 cellValue=cell;
00552 operation=op;
00553 }
00554 Table::Row* Table::GetRowByID(unsigned rowId) const
00555 {
00556 Row *row;
00557 if (rows.Get(rowId, row))
00558 return row;
00559 return 0;
00560 }
00561
00562 Table::Row* Table::GetRowByIndex(unsigned rowIndex, unsigned *key) const
00563 {
00564 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
00565 while (cur)
00566 {
00567 if (rowIndex < (unsigned)cur->size)
00568 {
00569 if (key)
00570 *key=cur->keys[rowIndex];
00571 return cur->data[rowIndex];
00572 }
00573 if (rowIndex <= (unsigned)cur->size)
00574 rowIndex-=cur->size;
00575 else
00576 return 0;
00577 cur=cur->next;
00578 }
00579 return 0;
00580 }
00581
00582 void Table::QueryTable(unsigned *columnIndicesSubset, unsigned numColumnSubset, FilterQuery *inclusionFilters, unsigned numInclusionFilters, unsigned *rowIds, unsigned numRowIDs, Table *result)
00583 {
00584 unsigned i;
00585 DataStructures::List<unsigned> columnIndicesToReturn;
00586
00587
00588 result->Clear();
00589
00590 if (columnIndicesSubset && numColumnSubset>0)
00591 {
00592 for (i=0; i < numColumnSubset; i++)
00593 {
00594 if (columnIndicesSubset[i]<columns.Size())
00595 columnIndicesToReturn.Insert(columnIndicesSubset[i], __FILE__, __LINE__);
00596 }
00597 }
00598 else
00599 {
00600 for (i=0; i < columns.Size(); i++)
00601 columnIndicesToReturn.Insert(i, __FILE__, __LINE__);
00602 }
00603
00604 if (columnIndicesToReturn.Size()==0)
00605 return;
00606
00607 for (i=0; i < columnIndicesToReturn.Size(); i++)
00608 {
00609 result->AddColumn(columns[columnIndicesToReturn[i]].columnName,columns[columnIndicesToReturn[i]].columnType);
00610 }
00611
00612
00613 DataStructures::List<unsigned> inclusionFilterColumnIndices;
00614 if (inclusionFilters && numInclusionFilters>0)
00615 {
00616 for (i=0; i < numInclusionFilters; i++)
00617 {
00618 if (inclusionFilters[i].columnName[0])
00619 inclusionFilters[i].columnIndex=ColumnIndex(inclusionFilters[i].columnName);
00620 if (inclusionFilters[i].columnIndex<columns.Size())
00621 inclusionFilterColumnIndices.Insert(inclusionFilters[i].columnIndex, __FILE__, __LINE__);
00622 else
00623 inclusionFilterColumnIndices.Insert((unsigned)-1, __FILE__, __LINE__);
00624 }
00625 }
00626
00627 if (rowIds==0 || numRowIDs==0)
00628 {
00629
00630 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
00631 while (cur)
00632 {
00633 for (i=0; i < (unsigned)cur->size; i++)
00634 {
00635 QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, cur->keys[i], cur->data[i], inclusionFilters, result);
00636 }
00637 cur=cur->next;
00638 }
00639 }
00640 else
00641 {
00642
00643 Row *row;
00644 for (i=0; i < numRowIDs; i++)
00645 {
00646 if (rows.Get(rowIds[i], row))
00647 {
00648 QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, rowIds[i], row, inclusionFilters, result);
00649 }
00650 }
00651 }
00652 }
00653
00654 void Table::QueryRow(DataStructures::List<unsigned> &inclusionFilterColumnIndices, DataStructures::List<unsigned> &columnIndicesToReturn, unsigned key, Table::Row* row, FilterQuery *inclusionFilters, Table *result)
00655 {
00656 bool pass=false;
00657 unsigned columnIndex;
00658 unsigned j;
00659
00660
00661 if (inclusionFilterColumnIndices.Size()==0)
00662 {
00663 result->AddRowColumns(key, row, columnIndicesToReturn);
00664 }
00665 else
00666 {
00667
00668 for (j=0; j<inclusionFilterColumnIndices.Size(); j++)
00669 {
00670 columnIndex=inclusionFilterColumnIndices[j];
00671 if (columnIndex!=(unsigned)-1 && row->cells[columnIndex]->isEmpty==false )
00672 {
00673 if (columns[inclusionFilterColumnIndices[j]].columnType==STRING &&
00674 (row->cells[columnIndex]->c==0 ||
00675 inclusionFilters[j].cellValue->c==0) )
00676 continue;
00677
00678 switch (inclusionFilters[j].operation)
00679 {
00680 case QF_EQUAL:
00681 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00682 {
00683 case NUMERIC:
00684 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i;
00685 break;
00686 case STRING:
00687 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)==0;
00688 break;
00689 case BINARY:
00690 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i &&
00691 memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, (int) row->cells[columnIndex]->i)==0;
00692 break;
00693 case POINTER:
00694 pass=row->cells[columnIndex]->ptr==inclusionFilters[j].cellValue->ptr;
00695 break;
00696 }
00697 break;
00698 case QF_NOT_EQUAL:
00699 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00700 {
00701 case NUMERIC:
00702 pass=row->cells[columnIndex]->i!=inclusionFilters[j].cellValue->i;
00703 break;
00704 case STRING:
00705 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)!=0;
00706 break;
00707 case BINARY:
00708 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i &&
00709 memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, (int) row->cells[columnIndex]->i)==0;
00710 break;
00711 case POINTER:
00712 pass=row->cells[columnIndex]->ptr!=inclusionFilters[j].cellValue->ptr;
00713 break;
00714 }
00715 break;
00716 case QF_GREATER_THAN:
00717 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00718 {
00719 case NUMERIC:
00720 pass=row->cells[columnIndex]->i>inclusionFilters[j].cellValue->i;
00721 break;
00722 case STRING:
00723 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>0;
00724 break;
00725 case BINARY:
00726 break;
00727 case POINTER:
00728 pass=row->cells[columnIndex]->ptr>inclusionFilters[j].cellValue->ptr;
00729 break;
00730 }
00731 break;
00732 case QF_GREATER_THAN_EQ:
00733 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00734 {
00735 case NUMERIC:
00736 pass=row->cells[columnIndex]->i>=inclusionFilters[j].cellValue->i;
00737 break;
00738 case STRING:
00739 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>=0;
00740 break;
00741 case BINARY:
00742 break;
00743 case POINTER:
00744 pass=row->cells[columnIndex]->ptr>=inclusionFilters[j].cellValue->ptr;
00745 break;
00746 }
00747 break;
00748 case QF_LESS_THAN:
00749 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00750 {
00751 case NUMERIC:
00752 pass=row->cells[columnIndex]->i<inclusionFilters[j].cellValue->i;
00753 break;
00754 case STRING:
00755 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<0;
00756 break;
00757 case BINARY:
00758 break;
00759 case POINTER:
00760 pass=row->cells[columnIndex]->ptr<inclusionFilters[j].cellValue->ptr;
00761 break;
00762 }
00763 break;
00764 case QF_LESS_THAN_EQ:
00765 switch(columns[inclusionFilterColumnIndices[j]].columnType)
00766 {
00767 case NUMERIC:
00768 pass=row->cells[columnIndex]->i<=inclusionFilters[j].cellValue->i;
00769 break;
00770 case STRING:
00771 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<=0;
00772 break;
00773 case BINARY:
00774 break;
00775 case POINTER:
00776 pass=row->cells[columnIndex]->ptr<=inclusionFilters[j].cellValue->ptr;
00777 break;
00778 }
00779 break;
00780 case QF_IS_EMPTY:
00781 pass=false;
00782 break;
00783 case QF_NOT_EMPTY:
00784 pass=true;
00785 break;
00786 default:
00787 pass=false;
00788 RakAssert(0);
00789 break;
00790 }
00791 }
00792 else
00793 {
00794 if (inclusionFilters[j].operation==QF_IS_EMPTY)
00795 pass=true;
00796 else
00797 pass=false;
00798 }
00799
00800 if (pass==false)
00801 break;
00802 }
00803
00804 if (pass)
00805 {
00806 result->AddRowColumns(key, row, columnIndicesToReturn);
00807 }
00808 }
00809 }
00810
00811 static Table::SortQuery *_sortQueries;
00812 static unsigned _numSortQueries;
00813 static DataStructures::List<unsigned> *_columnIndices;
00814 static DataStructures::List<Table::ColumnDescriptor> *_columns;
00815 int RowSort(Table::Row* const &first, Table::Row* const &second)
00816 {
00817 unsigned i, columnIndex;
00818 for (i=0; i<_numSortQueries; i++)
00819 {
00820 columnIndex=(*_columnIndices)[i];
00821 if (columnIndex==(unsigned)-1)
00822 continue;
00823
00824 if (first->cells[columnIndex]->isEmpty==true && second->cells[columnIndex]->isEmpty==false)
00825 return 1;
00826
00827 if (first->cells[columnIndex]->isEmpty==false && second->cells[columnIndex]->isEmpty==true)
00828 return -1;
00829
00830 if (_sortQueries[i].operation==Table::QS_INCREASING_ORDER)
00831 {
00832 if ((*_columns)[columnIndex].columnType==Table::NUMERIC)
00833 {
00834 if (first->cells[columnIndex]->i>second->cells[columnIndex]->i)
00835 return 1;
00836 if (first->cells[columnIndex]->i<second->cells[columnIndex]->i)
00837 return -1;
00838 }
00839 else
00840 {
00841
00842 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)>0)
00843 return 1;
00844 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)<0)
00845 return -1;
00846 }
00847 }
00848 else
00849 {
00850 if ((*_columns)[columnIndex].columnType==Table::NUMERIC)
00851 {
00852 if (first->cells[columnIndex]->i<second->cells[columnIndex]->i)
00853 return 1;
00854 if (first->cells[columnIndex]->i>second->cells[columnIndex]->i)
00855 return -1;
00856 }
00857 else
00858 {
00859
00860 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)<0)
00861 return 1;
00862 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)>0)
00863 return -1;
00864 }
00865 }
00866 }
00867
00868 return 0;
00869 }
00870 void Table::SortTable(Table::SortQuery *sortQueries, unsigned numSortQueries, Table::Row** out)
00871 {
00872 unsigned i;
00873 unsigned outLength;
00874 DataStructures::List<unsigned> columnIndices;
00875 _sortQueries=sortQueries;
00876 _numSortQueries=numSortQueries;
00877 _columnIndices=&columnIndices;
00878 _columns=&columns;
00879 bool anyValid=false;
00880
00881 for (i=0; i < numSortQueries; i++)
00882 {
00883 if (sortQueries[i].columnIndex<columns.Size() && columns[sortQueries[i].columnIndex].columnType!=BINARY)
00884 {
00885 columnIndices.Insert(sortQueries[i].columnIndex, __FILE__, __LINE__);
00886 anyValid=true;
00887 }
00888 else
00889 columnIndices.Insert((unsigned)-1, __FILE__, __LINE__);
00890 }
00891
00892 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
00893 cur = rows.GetListHead();
00894 if (anyValid==false)
00895 {
00896 outLength=0;
00897 while (cur)
00898 {
00899 for (i=0; i < (unsigned)cur->size; i++)
00900 {
00901 out[(outLength)++]=cur->data[i];
00902 }
00903 cur=cur->next;
00904 }
00905 return;
00906 }
00907
00908
00909 DataStructures::OrderedList<Row*, Row*, RowSort> orderedList;
00910 while (cur)
00911 {
00912 for (i=0; i < (unsigned)cur->size; i++)
00913 {
00914 RakAssert(cur->data[i]);
00915 orderedList.Insert(cur->data[i],cur->data[i], true, __FILE__,__LINE__);
00916 }
00917 cur=cur->next;
00918 }
00919
00920 outLength=0;
00921 for (i=0; i < orderedList.Size(); i++)
00922 out[(outLength)++]=orderedList[i];
00923 }
00924 void Table::PrintColumnHeaders(char *out, int outLength, char columnDelineator) const
00925 {
00926 if (outLength<=0)
00927 return;
00928 if (outLength==1)
00929 {
00930 *out=0;
00931 return;
00932 }
00933
00934 unsigned i;
00935 out[0]=0;
00936 int len;
00937 for (i=0; i < columns.Size(); i++)
00938 {
00939 if (i!=0)
00940 {
00941 len = (int) strlen(out);
00942 if (len < outLength-1)
00943 sprintf(out+len, "%c", columnDelineator);
00944 else
00945 return;
00946 }
00947
00948 len = (int) strlen(out);
00949 if (len < outLength-(int) strlen(columns[i].columnName))
00950 sprintf(out+len, "%s", columns[i].columnName);
00951 else
00952 return;
00953 }
00954 }
00955 void Table::PrintRow(char *out, int outLength, char columnDelineator, bool printDelineatorForBinary, Table::Row* inputRow) const
00956 {
00957 if (outLength<=0)
00958 return;
00959 if (outLength==1)
00960 {
00961 *out=0;
00962 return;
00963 }
00964
00965 if (inputRow->cells.Size()!=columns.Size())
00966 {
00967 strncpy(out, "Cell width does not match column width.\n", outLength);
00968 out[outLength-1]=0;
00969 return;
00970 }
00971
00972 char buff[512];
00973 unsigned i;
00974 int len;
00975 out[0]=0;
00976 for (i=0; i < columns.Size(); i++)
00977 {
00978 if (columns[i].columnType==NUMERIC)
00979 {
00980 if (inputRow->cells[i]->isEmpty==false)
00981 {
00982 sprintf(buff, "%f", inputRow->cells[i]->i);
00983 len=(int)strlen(buff);
00984 }
00985 else
00986 len=0;
00987 if (i+1!=columns.Size())
00988 buff[len++]=columnDelineator;
00989 buff[len]=0;
00990 }
00991 else if (columns[i].columnType==STRING)
00992 {
00993 if (inputRow->cells[i]->isEmpty==false && inputRow->cells[i]->c)
00994 {
00995 strncpy(buff, inputRow->cells[i]->c, 512-2);
00996 buff[512-2]=0;
00997 len=(int)strlen(buff);
00998 }
00999 else
01000 len=0;
01001 if (i+1!=columns.Size())
01002 buff[len++]=columnDelineator;
01003 buff[len]=0;
01004 }
01005 else if (columns[i].columnType==POINTER)
01006 {
01007 if (inputRow->cells[i]->isEmpty==false && inputRow->cells[i]->ptr)
01008 {
01009 sprintf(buff, "%p", inputRow->cells[i]->ptr);
01010 len=(int)strlen(buff);
01011 }
01012 else
01013 len=0;
01014 if (i+1!=columns.Size())
01015 buff[len++]=columnDelineator;
01016 buff[len]=0;
01017 }
01018 else
01019 {
01020 if (printDelineatorForBinary)
01021 {
01022 if (i+1!=columns.Size())
01023 buff[0]=columnDelineator;
01024 buff[1]=0;
01025 }
01026 else
01027 buff[0]=0;
01028
01029 }
01030
01031 len=(int)strlen(out);
01032 if (outLength==len+1)
01033 break;
01034 strncpy(out+len, buff, outLength-len);
01035 out[outLength-1]=0;
01036 }
01037 }
01038
01039 void Table::Clear(void)
01040 {
01041 rows.ForEachData(FreeRow);
01042 rows.Clear();
01043 columns.Clear(true, __FILE__, __LINE__);
01044 }
01045 const List<Table::ColumnDescriptor>& Table::GetColumns(void) const
01046 {
01047 return columns;
01048 }
01049 const DataStructures::BPlusTree<unsigned, Table::Row*, _TABLE_BPLUS_TREE_ORDER>& Table::GetRows(void) const
01050 {
01051 return rows;
01052 }
01053 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> * Table::GetListHead(void)
01054 {
01055 return rows.GetListHead();
01056 }
01057 unsigned Table::GetAvailableRowId(void) const
01058 {
01059 bool setKey=false;
01060 unsigned key=0;
01061 int i;
01062 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
01063
01064 while (cur)
01065 {
01066 for (i=0; i < cur->size; i++)
01067 {
01068 if (setKey==false)
01069 {
01070 key=cur->keys[i]+1;
01071 setKey=true;
01072 }
01073 else
01074 {
01075 if (key!=cur->keys[i])
01076 return key;
01077 key++;
01078 }
01079 }
01080
01081 cur=cur->next;
01082 }
01083 return key;
01084 }
01085 void Table::DeleteRow(Table::Row *row)
01086 {
01087 unsigned rowIndex;
01088 for (rowIndex=0; rowIndex < row->cells.Size(); rowIndex++)
01089 {
01090 RakNet::OP_DELETE(row->cells[rowIndex], __FILE__, __LINE__);
01091 }
01092 RakNet::OP_DELETE(row, __FILE__, __LINE__);
01093 }
01094 Table& Table::operator = ( const Table& input )
01095 {
01096 Clear();
01097
01098 unsigned int i;
01099 for (i=0; i < input.GetColumnCount(); i++)
01100 AddColumn(input.ColumnName(i), input.GetColumnType(i));
01101
01102 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = input.GetRows().GetListHead();
01103 while (cur)
01104 {
01105 for (i=0; i < (unsigned int) cur->size; i++)
01106 {
01107 AddRow(cur->keys[i], cur->data[i]->cells, false);
01108 }
01109
01110 cur=cur->next;
01111 }
01112
01113 return *this;
01114 }
01115
01116 #ifdef _MSC_VER
01117 #pragma warning( pop )
01118 #endif