SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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