1 #include "DS_Table.h"
2 #include "DS_OrderedList.h"
3 #include <string.h>
4 #include "RakAssert.h"
5 #include "RakAssert.h"
6 #include "Itoa.h"
7
8 using namespace DataStructures;
9
10 #ifdef _MSC_VER
11 #pragma warning( push )
12 #endif
13
ExtendRows(Table::Row * input,int index)14 void ExtendRows(Table::Row* input, int index)
15 {
16 (void) index;
17 input->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
18 }
FreeRow(Table::Row * input,int index)19 void FreeRow(Table::Row* input, int index)
20 {
21 (void) index;
22
23 unsigned i;
24 for (i=0; i < input->cells.Size(); i++)
25 {
26 RakNet::OP_DELETE(input->cells[i], __FILE__, __LINE__);
27 }
28 RakNet::OP_DELETE(input, __FILE__, __LINE__);
29 }
Cell()30 Table::Cell::Cell()
31 {
32 isEmpty=true;
33 c=0;
34 ptr=0;
35 i=0.0;
36 }
~Cell()37 Table::Cell::~Cell()
38 {
39 Clear();
40 }
operator =(const Table::Cell & input)41 Table::Cell& Table::Cell::operator = ( const Table::Cell& input )
42 {
43 isEmpty=input.isEmpty;
44 i=input.i;
45 ptr=input.ptr;
46 if (c)
47 rakFree_Ex(c, __FILE__, __LINE__);
48 if (input.c)
49 {
50 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
51 memcpy(c, input.c, (int) i);
52 }
53 else
54 c=0;
55 return *this;
56 }
Cell(const Table::Cell & input)57 Table::Cell::Cell( const Table::Cell & input)
58 {
59 isEmpty=input.isEmpty;
60 i=input.i;
61 ptr=input.ptr;
62 if (input.c)
63 {
64 if (c)
65 rakFree_Ex(c, __FILE__, __LINE__);
66 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
67 memcpy(c, input.c, (int) i);
68 }
69 }
Set(double input)70 void Table::Cell::Set(double input)
71 {
72 Clear();
73 i=input;
74 c=0;
75 ptr=0;
76 isEmpty=false;
77 }
Set(unsigned int input)78 void Table::Cell::Set(unsigned int input)
79 {
80 Set((int) input);
81 }
Set(int input)82 void Table::Cell::Set(int input)
83 {
84 Clear();
85 i=(double) input;
86 c=0;
87 ptr=0;
88 isEmpty=false;
89 }
90
Set(const char * input)91 void Table::Cell::Set(const char *input)
92 {
93 Clear();
94
95 if (input)
96 {
97 i=(int)strlen(input)+1;
98 c = (char*) rakMalloc_Ex( (int) i, __FILE__, __LINE__ );
99 strcpy(c, input);
100 }
101 else
102 {
103 c=0;
104 i=0;
105 }
106 ptr=0;
107 isEmpty=false;
108 }
Set(const char * input,int inputLength)109 void Table::Cell::Set(const char *input, int inputLength)
110 {
111 Clear();
112 if (input)
113 {
114 c = (char*) rakMalloc_Ex( inputLength, __FILE__, __LINE__ );
115 i=inputLength;
116 memcpy(c, input, inputLength);
117 }
118 else
119 {
120 c=0;
121 i=0;
122 }
123 ptr=0;
124 isEmpty=false;
125 }
SetPtr(void * p)126 void Table::Cell::SetPtr(void* p)
127 {
128 Clear();
129 c=0;
130 ptr=p;
131 isEmpty=false;
132 }
Get(int * output)133 void Table::Cell::Get(int *output)
134 {
135 RakAssert(isEmpty==false);
136 int o = (int) i;
137 *output=o;
138 }
Get(double * output)139 void Table::Cell::Get(double *output)
140 {
141 RakAssert(isEmpty==false);
142 *output=i;
143 }
Get(char * output)144 void Table::Cell::Get(char *output)
145 {
146 RakAssert(isEmpty==false);
147 strcpy(output, c);
148 }
Get(char * output,int * outputLength)149 void Table::Cell::Get(char *output, int *outputLength)
150 {
151 RakAssert(isEmpty==false);
152 memcpy(output, c, (int) i);
153 if (outputLength)
154 *outputLength=(int) i;
155 }
ToString(ColumnType columnType)156 RakNet::RakString Table::Cell::ToString(ColumnType columnType)
157 {
158 if (isEmpty)
159 return RakNet::RakString();
160
161 if (columnType==NUMERIC)
162 {
163 return RakNet::RakString("%f", i);
164 }
165 else if (columnType==STRING)
166 {
167 return RakNet::RakString(c);
168 }
169 else if (columnType==BINARY)
170 {
171 return RakNet::RakString("<Binary>");
172 }
173 else if (columnType==POINTER)
174 {
175 return RakNet::RakString("%p", ptr);
176 }
177
178 return RakNet::RakString();
179 }
Cell(double numericValue,char * charValue,void * ptr,ColumnType type)180 Table::Cell::Cell(double numericValue, char *charValue, void *ptr, ColumnType type)
181 {
182 SetByType(numericValue,charValue,ptr,type);
183 }
SetByType(double numericValue,char * charValue,void * ptr,ColumnType type)184 void Table::Cell::SetByType(double numericValue, char *charValue, void *ptr, ColumnType type)
185 {
186 isEmpty=true;
187 if (type==NUMERIC)
188 {
189 Set(numericValue);
190 }
191 else if (type==STRING)
192 {
193 Set(charValue);
194 }
195 else if (type==BINARY)
196 {
197 Set(charValue, (int) numericValue);
198 }
199 else if (type==POINTER)
200 {
201 SetPtr(ptr);
202 }
203 else
204 {
205 ptr=(void*) charValue;
206 }
207 }
EstimateColumnType(void) const208 Table::ColumnType Table::Cell::EstimateColumnType(void) const
209 {
210 if (c)
211 if (i!=0.0f)
212 return BINARY;
213 else
214 return STRING;
215 if (ptr)
216 return POINTER;
217 return NUMERIC;
218 }
Clear(void)219 void Table::Cell::Clear(void)
220 {
221 if (isEmpty==false && c)
222 {
223 rakFree_Ex(c, __FILE__, __LINE__);
224 c=0;
225 }
226 isEmpty=true;
227 }
ColumnDescriptor()228 Table::ColumnDescriptor::ColumnDescriptor()
229 {
230
231 }
~ColumnDescriptor()232 Table::ColumnDescriptor::~ColumnDescriptor()
233 {
234
235 }
ColumnDescriptor(const char cn[_TABLE_MAX_COLUMN_NAME_LENGTH],ColumnType ct)236 Table::ColumnDescriptor::ColumnDescriptor(const char cn[_TABLE_MAX_COLUMN_NAME_LENGTH], ColumnType ct)
237 {
238 columnType=ct;
239 strcpy(columnName, cn);
240 }
UpdateCell(unsigned columnIndex,double value)241 void Table::Row::UpdateCell(unsigned columnIndex, double value)
242 {
243 cells[columnIndex]->Clear();
244 cells[columnIndex]->Set(value);
245
246 // cells[columnIndex]->i=value;
247 // cells[columnIndex]->c=0;
248 // cells[columnIndex]->isEmpty=false;
249 }
UpdateCell(unsigned columnIndex,const char * str)250 void Table::Row::UpdateCell(unsigned columnIndex, const char *str)
251 {
252 cells[columnIndex]->Clear();
253 cells[columnIndex]->Set(str);
254 }
UpdateCell(unsigned columnIndex,int byteLength,const char * data)255 void Table::Row::UpdateCell(unsigned columnIndex, int byteLength, const char *data)
256 {
257 cells[columnIndex]->Clear();
258 cells[columnIndex]->Set(data,byteLength);
259 }
Table()260 Table::Table()
261 {
262 }
~Table()263 Table::~Table()
264 {
265 Clear();
266 }
AddColumn(const char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH],ColumnType columnType)267 unsigned Table::AddColumn(const char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH], ColumnType columnType)
268 {
269 if (columnName[0]==0)
270 return (unsigned) -1;
271
272 // Add this column.
273 columns.Insert(Table::ColumnDescriptor(columnName, columnType), __FILE__, __LINE__);
274
275 // Extend the rows by one
276 rows.ForEachData(ExtendRows);
277
278 return columns.Size()-1;
279 }
RemoveColumn(unsigned columnIndex)280 void Table::RemoveColumn(unsigned columnIndex)
281 {
282 if (columnIndex >= columns.Size())
283 return;
284
285 columns.RemoveAtIndex(columnIndex);
286
287 // Remove this index from each row.
288 int i;
289 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
290 while (cur)
291 {
292 for (i=0; i < cur->size; i++)
293 {
294 RakNet::OP_DELETE(cur->data[i]->cells[columnIndex], __FILE__, __LINE__);
295 cur->data[i]->cells.RemoveAtIndex(columnIndex);
296 }
297
298 cur=cur->next;
299 }
300 }
ColumnIndex(const char * columnName) const301 unsigned Table::ColumnIndex(const char *columnName) const
302 {
303 unsigned columnIndex;
304 for (columnIndex=0; columnIndex<columns.Size(); columnIndex++)
305 if (strcmp(columnName, columns[columnIndex].columnName)==0)
306 return columnIndex;
307 return (unsigned)-1;
308 }
ColumnIndex(char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH]) const309 unsigned Table::ColumnIndex(char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH]) const
310 {
311 return ColumnIndex((const char *) columnName);
312 }
ColumnName(unsigned index) const313 char* Table::ColumnName(unsigned index) const
314 {
315 if (index >= columns.Size())
316 return 0;
317 else
318 return (char*)columns[index].columnName;
319 }
GetColumnType(unsigned index) const320 Table::ColumnType Table::GetColumnType(unsigned index) const
321 {
322 if (index >= columns.Size())
323 return (Table::ColumnType) 0;
324 else
325 return columns[index].columnType;
326 }
GetColumnCount(void) const327 unsigned Table::GetColumnCount(void) const
328 {
329 return columns.Size();
330 }
GetRowCount(void) const331 unsigned Table::GetRowCount(void) const
332 {
333 return rows.Size();
334 }
AddRow(unsigned rowId)335 Table::Row* Table::AddRow(unsigned rowId)
336 {
337 Row *newRow;
338 newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
339 if (rows.Insert(rowId, newRow)==false)
340 {
341 RakNet::OP_DELETE(newRow, __FILE__, __LINE__);
342 return 0; // Already exists
343 }
344 unsigned rowIndex;
345 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
346 newRow->cells.Insert( RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
347 return newRow;
348 }
AddRow(unsigned rowId,DataStructures::List<Cell> & initialCellValues)349 Table::Row* Table::AddRow(unsigned rowId, DataStructures::List<Cell> &initialCellValues)
350 {
351 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
352 unsigned rowIndex;
353 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
354 {
355 if (rowIndex < initialCellValues.Size() && initialCellValues[rowIndex].isEmpty==false)
356 {
357 Table::Cell *c;
358 c = RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__);
359 c->SetByType(initialCellValues[rowIndex].i,initialCellValues[rowIndex].c,initialCellValues[rowIndex].ptr,columns[rowIndex].columnType);
360 newRow->cells.Insert(c, __FILE__, __LINE__ );
361 }
362 else
363 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__ );
364 }
365 rows.Insert(rowId, newRow);
366 return newRow;
367 }
AddRow(unsigned rowId,DataStructures::List<Cell * > & initialCellValues,bool copyCells)368 Table::Row* Table::AddRow(unsigned rowId, DataStructures::List<Cell*> &initialCellValues, bool copyCells)
369 {
370 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
371 unsigned rowIndex;
372 for (rowIndex=0; rowIndex < columns.Size(); rowIndex++)
373 {
374 if (rowIndex < initialCellValues.Size() && initialCellValues[rowIndex] && initialCellValues[rowIndex]->isEmpty==false)
375 {
376 if (copyCells==false)
377 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__);
378 else
379 {
380 Table::Cell *c = RakNet::OP_NEW<Table::Cell>( __FILE__, __LINE__ );
381 newRow->cells.Insert(c, __FILE__, __LINE__);
382 *c=*(initialCellValues[rowIndex]);
383 }
384 }
385 else
386 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__);
387 }
388 rows.Insert(rowId, newRow);
389 return newRow;
390 }
AddRowColumns(unsigned rowId,Row * row,DataStructures::List<unsigned> columnIndices)391 Table::Row* Table::AddRowColumns(unsigned rowId, Row *row, DataStructures::List<unsigned> columnIndices)
392 {
393 Row *newRow = RakNet::OP_NEW<Row>( __FILE__, __LINE__ );
394 unsigned columnIndex;
395 for (columnIndex=0; columnIndex < columnIndices.Size(); columnIndex++)
396 {
397 if (row->cells[columnIndices[columnIndex]]->isEmpty==false)
398 {
399 newRow->cells.Insert(RakNet::OP_NEW_4<Table::Cell>( __FILE__, __LINE__,
400 row->cells[columnIndices[columnIndex]]->i,
401 row->cells[columnIndices[columnIndex]]->c,
402 row->cells[columnIndices[columnIndex]]->ptr,
403 columns[columnIndex].columnType
404 ), __FILE__, __LINE__);
405 }
406 else
407 {
408 newRow->cells.Insert(RakNet::OP_NEW<Table::Cell>(__FILE__, __LINE__), __FILE__, __LINE__);
409 }
410 }
411 rows.Insert(rowId, newRow);
412 return newRow;
413 }
RemoveRow(unsigned rowId)414 bool Table::RemoveRow(unsigned rowId)
415 {
416 Row *out;
417 if (rows.Delete(rowId, out))
418 {
419 DeleteRow(out);
420 return true;
421 }
422 return false;
423 }
RemoveRows(Table * tableContainingRowIDs)424 void Table::RemoveRows(Table *tableContainingRowIDs)
425 {
426 unsigned i;
427 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = tableContainingRowIDs->GetRows().GetListHead();
428 while (cur)
429 {
430 for (i=0; i < (unsigned)cur->size; i++)
431 {
432 rows.Delete(cur->keys[i]);
433 }
434 cur=cur->next;
435 }
436 return;
437 }
UpdateCell(unsigned rowId,unsigned columnIndex,int value)438 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, int value)
439 {
440 RakAssert(columns[columnIndex].columnType==NUMERIC);
441
442 Row *row = GetRowByID(rowId);
443 if (row)
444 {
445 row->UpdateCell(columnIndex, value);
446 return true;
447 }
448 return false;
449 }
UpdateCell(unsigned rowId,unsigned columnIndex,char * str)450 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, char *str)
451 {
452 RakAssert(columns[columnIndex].columnType==STRING);
453
454 Row *row = GetRowByID(rowId);
455 if (row)
456 {
457 row->UpdateCell(columnIndex, str);
458 return true;
459 }
460 return false;
461 }
UpdateCell(unsigned rowId,unsigned columnIndex,int byteLength,char * data)462 bool Table::UpdateCell(unsigned rowId, unsigned columnIndex, int byteLength, char *data)
463 {
464 RakAssert(columns[columnIndex].columnType==BINARY);
465
466 Row *row = GetRowByID(rowId);
467 if (row)
468 {
469 row->UpdateCell(columnIndex, byteLength, data);
470 return true;
471 }
472 return false;
473 }
UpdateCellByIndex(unsigned rowIndex,unsigned columnIndex,int value)474 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int value)
475 {
476 RakAssert(columns[columnIndex].columnType==NUMERIC);
477
478 Row *row = GetRowByIndex(rowIndex,0);
479 if (row)
480 {
481 row->UpdateCell(columnIndex, value);
482 return true;
483 }
484 return false;
485 }
UpdateCellByIndex(unsigned rowIndex,unsigned columnIndex,char * str)486 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, char *str)
487 {
488 RakAssert(columns[columnIndex].columnType==STRING);
489
490 Row *row = GetRowByIndex(rowIndex,0);
491 if (row)
492 {
493 row->UpdateCell(columnIndex, str);
494 return true;
495 }
496 return false;
497 }
UpdateCellByIndex(unsigned rowIndex,unsigned columnIndex,int byteLength,char * data)498 bool Table::UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int byteLength, char *data)
499 {
500 RakAssert(columns[columnIndex].columnType==BINARY);
501
502 Row *row = GetRowByIndex(rowIndex,0);
503 if (row)
504 {
505 row->UpdateCell(columnIndex, byteLength, data);
506 return true;
507 }
508 return false;
509 }
GetCellValueByIndex(unsigned rowIndex,unsigned columnIndex,int * output)510 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, int *output)
511 {
512 RakAssert(columns[columnIndex].columnType==NUMERIC);
513
514 Row *row = GetRowByIndex(rowIndex,0);
515 if (row)
516 {
517 row->cells[columnIndex]->Get(output);
518 }
519 }
GetCellValueByIndex(unsigned rowIndex,unsigned columnIndex,char * output)520 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output)
521 {
522 RakAssert(columns[columnIndex].columnType==STRING);
523
524 Row *row = GetRowByIndex(rowIndex,0);
525 if (row)
526 {
527 row->cells[columnIndex]->Get(output);
528 }
529 }
GetCellValueByIndex(unsigned rowIndex,unsigned columnIndex,char * output,int * outputLength)530 void Table::GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output, int *outputLength)
531 {
532 RakAssert(columns[columnIndex].columnType==BINARY);
533
534 Row *row = GetRowByIndex(rowIndex,0);
535 if (row)
536 {
537 row->cells[columnIndex]->Get(output, outputLength);
538 }
539 }
FilterQuery()540 Table::FilterQuery::FilterQuery()
541 {
542 columnName[0]=0;
543 }
~FilterQuery()544 Table::FilterQuery::~FilterQuery()
545 {
546
547 }
FilterQuery(unsigned column,Cell * cell,FilterQueryType op)548 Table::FilterQuery::FilterQuery(unsigned column, Cell *cell, FilterQueryType op)
549 {
550 columnIndex=column;
551 cellValue=cell;
552 operation=op;
553 }
GetRowByID(unsigned rowId) const554 Table::Row* Table::GetRowByID(unsigned rowId) const
555 {
556 Row *row;
557 if (rows.Get(rowId, row))
558 return row;
559 return 0;
560 }
561
GetRowByIndex(unsigned rowIndex,unsigned * key) const562 Table::Row* Table::GetRowByIndex(unsigned rowIndex, unsigned *key) const
563 {
564 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
565 while (cur)
566 {
567 if (rowIndex < (unsigned)cur->size)
568 {
569 if (key)
570 *key=cur->keys[rowIndex];
571 return cur->data[rowIndex];
572 }
573 if (rowIndex <= (unsigned)cur->size)
574 rowIndex-=cur->size;
575 else
576 return 0;
577 cur=cur->next;
578 }
579 return 0;
580 }
581
QueryTable(unsigned * columnIndicesSubset,unsigned numColumnSubset,FilterQuery * inclusionFilters,unsigned numInclusionFilters,unsigned * rowIds,unsigned numRowIDs,Table * result)582 void Table::QueryTable(unsigned *columnIndicesSubset, unsigned numColumnSubset, FilterQuery *inclusionFilters, unsigned numInclusionFilters, unsigned *rowIds, unsigned numRowIDs, Table *result)
583 {
584 unsigned i;
585 DataStructures::List<unsigned> columnIndicesToReturn;
586
587 // Clear the result table.
588 result->Clear();
589
590 if (columnIndicesSubset && numColumnSubset>0)
591 {
592 for (i=0; i < numColumnSubset; i++)
593 {
594 if (columnIndicesSubset[i]<columns.Size())
595 columnIndicesToReturn.Insert(columnIndicesSubset[i], __FILE__, __LINE__);
596 }
597 }
598 else
599 {
600 for (i=0; i < columns.Size(); i++)
601 columnIndicesToReturn.Insert(i, __FILE__, __LINE__);
602 }
603
604 if (columnIndicesToReturn.Size()==0)
605 return; // No valid columns specified
606
607 for (i=0; i < columnIndicesToReturn.Size(); i++)
608 {
609 result->AddColumn(columns[columnIndicesToReturn[i]].columnName,columns[columnIndicesToReturn[i]].columnType);
610 }
611
612 // Get the column indices of the filter queries.
613 DataStructures::List<unsigned> inclusionFilterColumnIndices;
614 if (inclusionFilters && numInclusionFilters>0)
615 {
616 for (i=0; i < numInclusionFilters; i++)
617 {
618 if (inclusionFilters[i].columnName[0])
619 inclusionFilters[i].columnIndex=ColumnIndex(inclusionFilters[i].columnName);
620 if (inclusionFilters[i].columnIndex<columns.Size())
621 inclusionFilterColumnIndices.Insert(inclusionFilters[i].columnIndex, __FILE__, __LINE__);
622 else
623 inclusionFilterColumnIndices.Insert((unsigned)-1, __FILE__, __LINE__);
624 }
625 }
626
627 if (rowIds==0 || numRowIDs==0)
628 {
629 // All rows
630 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
631 while (cur)
632 {
633 for (i=0; i < (unsigned)cur->size; i++)
634 {
635 QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, cur->keys[i], cur->data[i], inclusionFilters, result);
636 }
637 cur=cur->next;
638 }
639 }
640 else
641 {
642 // Specific rows
643 Row *row;
644 for (i=0; i < numRowIDs; i++)
645 {
646 if (rows.Get(rowIds[i], row))
647 {
648 QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, rowIds[i], row, inclusionFilters, result);
649 }
650 }
651 }
652 }
653
QueryRow(DataStructures::List<unsigned> & inclusionFilterColumnIndices,DataStructures::List<unsigned> & columnIndicesToReturn,unsigned key,Table::Row * row,FilterQuery * inclusionFilters,Table * result)654 void Table::QueryRow(DataStructures::List<unsigned> &inclusionFilterColumnIndices, DataStructures::List<unsigned> &columnIndicesToReturn, unsigned key, Table::Row* row, FilterQuery *inclusionFilters, Table *result)
655 {
656 bool pass=false;
657 unsigned columnIndex;
658 unsigned j;
659
660 // If no inclusion filters, just add the row
661 if (inclusionFilterColumnIndices.Size()==0)
662 {
663 result->AddRowColumns(key, row, columnIndicesToReturn);
664 }
665 else
666 {
667 // Go through all inclusion filters. Only add this row if all filters pass.
668 for (j=0; j<inclusionFilterColumnIndices.Size(); j++)
669 {
670 columnIndex=inclusionFilterColumnIndices[j];
671 if (columnIndex!=(unsigned)-1 && row->cells[columnIndex]->isEmpty==false )
672 {
673 if (columns[inclusionFilterColumnIndices[j]].columnType==STRING &&
674 (row->cells[columnIndex]->c==0 ||
675 inclusionFilters[j].cellValue->c==0) )
676 continue;
677
678 switch (inclusionFilters[j].operation)
679 {
680 case QF_EQUAL:
681 switch(columns[inclusionFilterColumnIndices[j]].columnType)
682 {
683 case NUMERIC:
684 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i;
685 break;
686 case STRING:
687 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)==0;
688 break;
689 case BINARY:
690 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i &&
691 memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, (int) row->cells[columnIndex]->i)==0;
692 break;
693 case POINTER:
694 pass=row->cells[columnIndex]->ptr==inclusionFilters[j].cellValue->ptr;
695 break;
696 }
697 break;
698 case QF_NOT_EQUAL:
699 switch(columns[inclusionFilterColumnIndices[j]].columnType)
700 {
701 case NUMERIC:
702 pass=row->cells[columnIndex]->i!=inclusionFilters[j].cellValue->i;
703 break;
704 case STRING:
705 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)!=0;
706 break;
707 case BINARY:
708 pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i &&
709 memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, (int) row->cells[columnIndex]->i)==0;
710 break;
711 case POINTER:
712 pass=row->cells[columnIndex]->ptr!=inclusionFilters[j].cellValue->ptr;
713 break;
714 }
715 break;
716 case QF_GREATER_THAN:
717 switch(columns[inclusionFilterColumnIndices[j]].columnType)
718 {
719 case NUMERIC:
720 pass=row->cells[columnIndex]->i>inclusionFilters[j].cellValue->i;
721 break;
722 case STRING:
723 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>0;
724 break;
725 case BINARY:
726 break;
727 case POINTER:
728 pass=row->cells[columnIndex]->ptr>inclusionFilters[j].cellValue->ptr;
729 break;
730 }
731 break;
732 case QF_GREATER_THAN_EQ:
733 switch(columns[inclusionFilterColumnIndices[j]].columnType)
734 {
735 case NUMERIC:
736 pass=row->cells[columnIndex]->i>=inclusionFilters[j].cellValue->i;
737 break;
738 case STRING:
739 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>=0;
740 break;
741 case BINARY:
742 break;
743 case POINTER:
744 pass=row->cells[columnIndex]->ptr>=inclusionFilters[j].cellValue->ptr;
745 break;
746 }
747 break;
748 case QF_LESS_THAN:
749 switch(columns[inclusionFilterColumnIndices[j]].columnType)
750 {
751 case NUMERIC:
752 pass=row->cells[columnIndex]->i<inclusionFilters[j].cellValue->i;
753 break;
754 case STRING:
755 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<0;
756 break;
757 case BINARY:
758 break;
759 case POINTER:
760 pass=row->cells[columnIndex]->ptr<inclusionFilters[j].cellValue->ptr;
761 break;
762 }
763 break;
764 case QF_LESS_THAN_EQ:
765 switch(columns[inclusionFilterColumnIndices[j]].columnType)
766 {
767 case NUMERIC:
768 pass=row->cells[columnIndex]->i<=inclusionFilters[j].cellValue->i;
769 break;
770 case STRING:
771 pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<=0;
772 break;
773 case BINARY:
774 break;
775 case POINTER:
776 pass=row->cells[columnIndex]->ptr<=inclusionFilters[j].cellValue->ptr;
777 break;
778 }
779 break;
780 case QF_IS_EMPTY:
781 pass=false;
782 break;
783 case QF_NOT_EMPTY:
784 pass=true;
785 break;
786 default:
787 pass=false;
788 RakAssert(0);
789 break;
790 }
791 }
792 else
793 {
794 if (inclusionFilters[j].operation==QF_IS_EMPTY)
795 pass=true;
796 else
797 pass=false; // No value for this cell
798 }
799
800 if (pass==false)
801 break;
802 }
803
804 if (pass)
805 {
806 result->AddRowColumns(key, row, columnIndicesToReturn);
807 }
808 }
809 }
810
811 static Table::SortQuery *_sortQueries;
812 static unsigned _numSortQueries;
813 static DataStructures::List<unsigned> *_columnIndices;
814 static DataStructures::List<Table::ColumnDescriptor> *_columns;
RowSort(Table::Row * const & first,Table::Row * const & second)815 int RowSort(Table::Row* const &first, Table::Row* const &second) // first is the one inserting, second is the one already there.
816 {
817 unsigned i, columnIndex;
818 for (i=0; i<_numSortQueries; i++)
819 {
820 columnIndex=(*_columnIndices)[i];
821 if (columnIndex==(unsigned)-1)
822 continue;
823
824 if (first->cells[columnIndex]->isEmpty==true && second->cells[columnIndex]->isEmpty==false)
825 return 1; // Empty cells always go at the end
826
827 if (first->cells[columnIndex]->isEmpty==false && second->cells[columnIndex]->isEmpty==true)
828 return -1; // Empty cells always go at the end
829
830 if (_sortQueries[i].operation==Table::QS_INCREASING_ORDER)
831 {
832 if ((*_columns)[columnIndex].columnType==Table::NUMERIC)
833 {
834 if (first->cells[columnIndex]->i>second->cells[columnIndex]->i)
835 return 1;
836 if (first->cells[columnIndex]->i<second->cells[columnIndex]->i)
837 return -1;
838 }
839 else
840 {
841 // String
842 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)>0)
843 return 1;
844 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)<0)
845 return -1;
846 }
847 }
848 else
849 {
850 if ((*_columns)[columnIndex].columnType==Table::NUMERIC)
851 {
852 if (first->cells[columnIndex]->i<second->cells[columnIndex]->i)
853 return 1;
854 if (first->cells[columnIndex]->i>second->cells[columnIndex]->i)
855 return -1;
856 }
857 else
858 {
859 // String
860 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)<0)
861 return 1;
862 if (strcmp(first->cells[columnIndex]->c,second->cells[columnIndex]->c)>0)
863 return -1;
864 }
865 }
866 }
867
868 return 0;
869 }
SortTable(Table::SortQuery * sortQueries,unsigned numSortQueries,Table::Row ** out)870 void Table::SortTable(Table::SortQuery *sortQueries, unsigned numSortQueries, Table::Row** out)
871 {
872 unsigned i;
873 unsigned outLength;
874 DataStructures::List<unsigned> columnIndices;
875 _sortQueries=sortQueries;
876 _numSortQueries=numSortQueries;
877 _columnIndices=&columnIndices;
878 _columns=&columns;
879 bool anyValid=false;
880
881 for (i=0; i < numSortQueries; i++)
882 {
883 if (sortQueries[i].columnIndex<columns.Size() && columns[sortQueries[i].columnIndex].columnType!=BINARY)
884 {
885 columnIndices.Insert(sortQueries[i].columnIndex, __FILE__, __LINE__);
886 anyValid=true;
887 }
888 else
889 columnIndices.Insert((unsigned)-1, __FILE__, __LINE__); // Means don't check this column
890 }
891
892 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
893 cur = rows.GetListHead();
894 if (anyValid==false)
895 {
896 outLength=0;
897 while (cur)
898 {
899 for (i=0; i < (unsigned)cur->size; i++)
900 {
901 out[(outLength)++]=cur->data[i];
902 }
903 cur=cur->next;
904 }
905 return;
906 }
907
908 // Start adding to ordered list.
909 DataStructures::OrderedList<Row*, Row*, RowSort> orderedList;
910 while (cur)
911 {
912 for (i=0; i < (unsigned)cur->size; i++)
913 {
914 RakAssert(cur->data[i]);
915 orderedList.Insert(cur->data[i],cur->data[i], true, __FILE__,__LINE__);
916 }
917 cur=cur->next;
918 }
919
920 outLength=0;
921 for (i=0; i < orderedList.Size(); i++)
922 out[(outLength)++]=orderedList[i];
923 }
PrintColumnHeaders(char * out,int outLength,char columnDelineator) const924 void Table::PrintColumnHeaders(char *out, int outLength, char columnDelineator) const
925 {
926 if (outLength<=0)
927 return;
928 if (outLength==1)
929 {
930 *out=0;
931 return;
932 }
933
934 unsigned i;
935 out[0]=0;
936 int len;
937 for (i=0; i < columns.Size(); i++)
938 {
939 if (i!=0)
940 {
941 len = (int) strlen(out);
942 if (len < outLength-1)
943 sprintf(out+len, "%c", columnDelineator);
944 else
945 return;
946 }
947
948 len = (int) strlen(out);
949 if (len < outLength-(int) strlen(columns[i].columnName))
950 sprintf(out+len, "%s", columns[i].columnName);
951 else
952 return;
953 }
954 }
PrintRow(char * out,int outLength,char columnDelineator,bool printDelineatorForBinary,Table::Row * inputRow) const955 void Table::PrintRow(char *out, int outLength, char columnDelineator, bool printDelineatorForBinary, Table::Row* inputRow) const
956 {
957 if (outLength<=0)
958 return;
959 if (outLength==1)
960 {
961 *out=0;
962 return;
963 }
964
965 if (inputRow->cells.Size()!=columns.Size())
966 {
967 strncpy(out, "Cell width does not match column width.\n", outLength);
968 out[outLength-1]=0;
969 return;
970 }
971
972 char buff[512];
973 unsigned i;
974 int len;
975 out[0]=0;
976 for (i=0; i < columns.Size(); i++)
977 {
978 if (columns[i].columnType==NUMERIC)
979 {
980 if (inputRow->cells[i]->isEmpty==false)
981 {
982 sprintf(buff, "%f", inputRow->cells[i]->i);
983 len=(int)strlen(buff);
984 }
985 else
986 len=0;
987 if (i+1!=columns.Size())
988 buff[len++]=columnDelineator;
989 buff[len]=0;
990 }
991 else if (columns[i].columnType==STRING)
992 {
993 if (inputRow->cells[i]->isEmpty==false && inputRow->cells[i]->c)
994 {
995 strncpy(buff, inputRow->cells[i]->c, 512-2);
996 buff[512-2]=0;
997 len=(int)strlen(buff);
998 }
999 else
1000 len=0;
1001 if (i+1!=columns.Size())
1002 buff[len++]=columnDelineator;
1003 buff[len]=0;
1004 }
1005 else if (columns[i].columnType==POINTER)
1006 {
1007 if (inputRow->cells[i]->isEmpty==false && inputRow->cells[i]->ptr)
1008 {
1009 sprintf(buff, "%p", inputRow->cells[i]->ptr);
1010 len=(int)strlen(buff);
1011 }
1012 else
1013 len=0;
1014 if (i+1!=columns.Size())
1015 buff[len++]=columnDelineator;
1016 buff[len]=0;
1017 }
1018 else
1019 {
1020 if (printDelineatorForBinary)
1021 {
1022 if (i+1!=columns.Size())
1023 buff[0]=columnDelineator;
1024 buff[1]=0;
1025 }
1026 else
1027 buff[0]=0;
1028
1029 }
1030
1031 len=(int)strlen(out);
1032 if (outLength==len+1)
1033 break;
1034 strncpy(out+len, buff, outLength-len);
1035 out[outLength-1]=0;
1036 }
1037 }
1038
Clear(void)1039 void Table::Clear(void)
1040 {
1041 rows.ForEachData(FreeRow);
1042 rows.Clear();
1043 columns.Clear(true, __FILE__, __LINE__);
1044 }
GetColumns(void) const1045 const List<Table::ColumnDescriptor>& Table::GetColumns(void) const
1046 {
1047 return columns;
1048 }
GetRows(void) const1049 const DataStructures::BPlusTree<unsigned, Table::Row*, _TABLE_BPLUS_TREE_ORDER>& Table::GetRows(void) const
1050 {
1051 return rows;
1052 }
GetListHead(void)1053 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> * Table::GetListHead(void)
1054 {
1055 return rows.GetListHead();
1056 }
GetAvailableRowId(void) const1057 unsigned Table::GetAvailableRowId(void) const
1058 {
1059 bool setKey=false;
1060 unsigned key=0;
1061 int i;
1062 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
1063
1064 while (cur)
1065 {
1066 for (i=0; i < cur->size; i++)
1067 {
1068 if (setKey==false)
1069 {
1070 key=cur->keys[i]+1;
1071 setKey=true;
1072 }
1073 else
1074 {
1075 if (key!=cur->keys[i])
1076 return key;
1077 key++;
1078 }
1079 }
1080
1081 cur=cur->next;
1082 }
1083 return key;
1084 }
DeleteRow(Table::Row * row)1085 void Table::DeleteRow(Table::Row *row)
1086 {
1087 unsigned rowIndex;
1088 for (rowIndex=0; rowIndex < row->cells.Size(); rowIndex++)
1089 {
1090 RakNet::OP_DELETE(row->cells[rowIndex], __FILE__, __LINE__);
1091 }
1092 RakNet::OP_DELETE(row, __FILE__, __LINE__);
1093 }
operator =(const Table & input)1094 Table& Table::operator = ( const Table& input )
1095 {
1096 Clear();
1097
1098 unsigned int i;
1099 for (i=0; i < input.GetColumnCount(); i++)
1100 AddColumn(input.ColumnName(i), input.GetColumnType(i));
1101
1102 DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = input.GetRows().GetListHead();
1103 while (cur)
1104 {
1105 for (i=0; i < (unsigned int) cur->size; i++)
1106 {
1107 AddRow(cur->keys[i], cur->data[i]->cells, false);
1108 }
1109
1110 cur=cur->next;
1111 }
1112
1113 return *this;
1114 }
1115
1116 #ifdef _MSC_VER
1117 #pragma warning( pop )
1118 #endif
1119