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