1 /// \file DS_Table.h
2 ///
3 /// This file is part of RakNet Copyright 2003 Jenkins Software LLC
4 ///
5 /// Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3.
6 
7 #ifndef __TABLE_H
8 #define __TABLE_H
9 
10 #ifdef _MSC_VER
11 #pragma warning( push )
12 #endif
13 
14 #include "DS_List.h"
15 #include "DS_BPlusTree.h"
16 #include "RakMemoryOverride.h"
17 #include "Export.h"
18 #include "RakString.h"
19 
20 #define _TABLE_BPLUS_TREE_ORDER 16
21 #define _TABLE_MAX_COLUMN_NAME_LENGTH 64
22 
23 /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
24 /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
25 namespace DataStructures
26 {
27 
28 	/// \brief Holds a set of columns, a set of rows, and rows times columns cells.
29 	/// \details The table data structure is useful if you want to store a set of structures and perform queries on those structures.<BR>
30 	/// This is a relatively simple and fast implementation of the types of tables commonly used in databases.<BR>
31 	/// See TableSerializer to serialize data members of the table.<BR>
32 	/// See LightweightDatabaseClient and LightweightDatabaseServer to transmit the table over the network.
33 	class RAK_DLL_EXPORT Table
34 	{
35 	public:
36 
37 		enum ColumnType
38 		{
39 			// Cell::i used
40 			NUMERIC,
41 
42 			// Cell::c used to hold a null terminated string.
43 			STRING,
44 
45 			// Cell::c holds data.  Cell::i holds data length of c in bytes.
46 			BINARY,
47 
48 			// Cell::c holds data.  Not deallocated. Set manually by assigning ptr.
49 			POINTER,
50 		};
51 
52 
53 		/// Holds the actual data in the table
54 		// Note: If this structure is changed the struct in the swig files need to be changed as well
55 		struct RAK_DLL_EXPORT Cell
56 		{
57 			Cell();
58 			~Cell();
59 			Cell(double numericValue, char *charValue, void *ptr, ColumnType type);
60 			void SetByType(double numericValue, char *charValue, void *ptr, ColumnType type);
61 			void Clear(void);
62 
63 			/// Numeric
64 			void Set(int input);
65 			void Set(unsigned int input);
66 			void Set(double input);
67 
68 			/// String
69 			void Set(const char *input);
70 
71 			/// Binary
72 			void Set(const char *input, int inputLength);
73 
74 			/// Pointer
75 			void SetPtr(void* p);
76 
77 			/// Numeric
78 			void Get(int *output);
79 			void Get(double *output);
80 
81 			/// String
82 			void Get(char *output);
83 
84 			/// Binary
85 			void Get(char *output, int *outputLength);
86 
87 			RakNet::RakString ToString(ColumnType columnType);
88 
89 			// assignment operator and copy constructor
90 			Cell& operator = ( const Cell& input );
91 			Cell( const Cell & input);
92 
93 			ColumnType EstimateColumnType(void) const;
94 
95 			bool isEmpty;
96 			double i;
97 			char *c;
98 			void *ptr;
99 		};
100 
101 		/// Stores the name and type of the column
102 		/// \internal
103 		// Note: If this structure is changed the struct in the swig files need to be changed as well
104 		struct RAK_DLL_EXPORT ColumnDescriptor
105 		{
106 			ColumnDescriptor();
107 			~ColumnDescriptor();
108 			ColumnDescriptor(const char cn[_TABLE_MAX_COLUMN_NAME_LENGTH],ColumnType ct);
109 
110 			char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH];
111 			ColumnType columnType;
112 		};
113 
114 		/// Stores the list of cells for this row, and a special flag used for internal sorting
115 		// Note: If this structure is changed the struct in the swig files need to be changed as well
116 		struct RAK_DLL_EXPORT Row
117 		{
118 			// list of cells
119 			DataStructures::List<Cell*> cells;
120 
121 			/// Numeric
122 			void UpdateCell(unsigned columnIndex, double value);
123 
124 			/// String
125 			void UpdateCell(unsigned columnIndex, const char *str);
126 
127 			/// Binary
128 			void UpdateCell(unsigned columnIndex, int byteLength, const char *data);
129 		};
130 
131 		// Operations to perform for cell comparison
132 		enum FilterQueryType
133 		{
134 			QF_EQUAL,
135 			QF_NOT_EQUAL,
136 			QF_GREATER_THAN,
137 			QF_GREATER_THAN_EQ,
138 			QF_LESS_THAN,
139 			QF_LESS_THAN_EQ,
140 			QF_IS_EMPTY,
141 			QF_NOT_EMPTY,
142 		};
143 
144 		// Compare the cell value for a row at columnName to the cellValue using operation.
145 		// Note: If this structure is changed the struct in the swig files need to be changed as well
146 		struct RAK_DLL_EXPORT FilterQuery
147 		{
148 			FilterQuery();
149 			~FilterQuery();
150 			FilterQuery(unsigned column, Cell *cell, FilterQueryType op);
151 
152 			// If columnName is specified, columnIndex will be looked up using it.
153 			char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH];
154 			unsigned columnIndex;
155 			Cell *cellValue;
156 			FilterQueryType operation;
157 		};
158 
159 		/// Increasing or decreasing sort order
160 		enum SortQueryType
161 		{
162 			QS_INCREASING_ORDER,
163 			QS_DECREASING_ORDER,
164 		};
165 
166 		// Sort on increasing or decreasing order for a particular column
167 		// Note: If this structure is changed the struct in the swig files need to be changed as well
168 		struct RAK_DLL_EXPORT SortQuery
169 		{
170 			/// The index of the table column we are sorting on
171 			unsigned columnIndex;
172 
173 			/// See SortQueryType
174 			SortQueryType operation;
175 		};
176 
177 		// Constructor
178 		Table();
179 
180 		// Destructor
181 		~Table();
182 
183 		/// \brief Adds a column to the table
184 		/// \param[in] columnName The name of the column
185 		/// \param[in] columnType What type of data this column will hold
186 		/// \return The index of the new column
187 		unsigned AddColumn(const char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH], ColumnType columnType);
188 
189 		/// \brief Removes a column by index
190 		/// \param[in] columnIndex The index of the column to remove
191 		void RemoveColumn(unsigned columnIndex);
192 
193 		/// \brief Gets the index of a column by name
194 		/// \details Column indices are stored in the order they are added.
195 		/// \param[in] columnName The name of the column
196 		/// \return The index of the column, or (unsigned)-1 if no such column
197 		unsigned ColumnIndex(char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH]) const;
198 		unsigned ColumnIndex(const char *columnName) const;
199 
200 		/// \brief Gives the string name of the column at a certain index
201 		/// \param[in] index The index of the column
202 		/// \return The name of the column, or 0 if an invalid index
203 		char* ColumnName(unsigned index) const;
204 
205 		/// \brief Returns the type of a column, referenced by index
206 		/// \param[in] index The index of the column
207 		/// \return The type of the column
208 		ColumnType GetColumnType(unsigned index) const;
209 
210 		/// Returns the number of columns
211 		/// \return The number of columns in the table
212 		unsigned GetColumnCount(void) const;
213 
214 		/// Returns the number of rows
215 		/// \return The number of rows in the table
216 		unsigned GetRowCount(void) const;
217 
218 		/// \brief Adds a row to the table
219 		/// \details New rows are added with empty values for all cells.  However, if you specify initialCelLValues you can specify initial values
220 		/// It's up to you to ensure that the values in the specific cells match the type of data used by that row
221 		/// rowId can be considered the primary key for the row.  It is much faster to lookup a row by its rowId than by searching keys.
222 		/// rowId must be unique
223 		/// Rows are stored in sorted order in the table, using rowId as the sort key
224 		/// \param[in] rowId The UNIQUE primary key for the row.  This can never be changed.
225 		/// \param[in] initialCellValues Initial values to give the row (optional)
226 		/// \return The newly added row
227 		Table::Row* AddRow(unsigned rowId);
228 		Table::Row* AddRow(unsigned rowId, DataStructures::List<Cell> &initialCellValues);
229 		Table::Row* AddRow(unsigned rowId, DataStructures::List<Cell*> &initialCellValues, bool copyCells=false);
230 
231 		/// \brief Removes a row specified by rowId.
232 		/// \param[in] rowId The ID of the row
233 		/// \return true if the row was deleted. False if not.
234 		bool RemoveRow(unsigned rowId);
235 
236 		/// \brief Removes all the rows with IDs that the specified table also has.
237 		/// \param[in] tableContainingRowIDs The IDs of the rows
238 		void RemoveRows(Table *tableContainingRowIDs);
239 
240 		/// \brief Updates a particular cell in the table.
241 		/// \note If you are going to update many cells of a particular row, it is more efficient to call GetRow and perform the operations on the row directly.
242 		/// \note Row pointers do not change, so you can also write directly to the rows for more efficiency.
243         /// \param[in] rowId The ID of the row
244 		/// \param[in] columnIndex The column of the cell
245 		/// \param[in] value The data to set
246 		bool UpdateCell(unsigned rowId, unsigned columnIndex, int value);
247 		bool UpdateCell(unsigned rowId, unsigned columnIndex, char *str);
248 		bool UpdateCell(unsigned rowId, unsigned columnIndex, int byteLength, char *data);
249 		bool UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int value);
250 		bool UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, char *str);
251 		bool UpdateCellByIndex(unsigned rowIndex, unsigned columnIndex, int byteLength, char *data);
252 
253 		/// \brief Note this is much less efficient to call than GetRow, then working with the cells directly.
254 		/// Numeric, string, binary
255 		void GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, int *output);
256 		void GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output);
257 		void GetCellValueByIndex(unsigned rowIndex, unsigned columnIndex, char *output, int *outputLength);
258 
259 		/// \brief Gets a row.  More efficient to do this and access Row::cells than to repeatedly call GetCell.
260 		/// You can also update cells in rows from this function.
261 		/// \param[in] rowId The ID of the row
262 		/// \return The desired row, or 0 if no such row.
263 		Row* GetRowByID(unsigned rowId) const;
264 
265 		/// \brief Gets a row at a specific index.
266 		/// rowIndex should be less than GetRowCount()
267 		/// \param[in] rowIndex The index of the row
268 		/// \param[out] key The ID of the row returned
269 		/// \return The desired row, or 0 if no such row.
270 		Row* GetRowByIndex(unsigned rowIndex, unsigned *key) const;
271 
272 		/// \brief Queries the table, optionally returning only a subset of columns and rows.
273 		/// \param[in] columnSubset An array of column indices.  Only columns in this array are returned.  Pass 0 for all columns
274 		/// \param[in] numColumnSubset The number of elements in \a columnSubset
275 		/// \param[in] inclusionFilters An array of FilterQuery.  All filters must pass for the row to be returned.
276 		/// \param[in] numInclusionFilters The number of elements in \a inclusionFilters
277 		/// \param[in] rowIds An arrow of row IDs.  Only these rows with these IDs are returned.  Pass 0 for all rows.
278 		/// \param[in] numRowIDs The number of elements in \a rowIds
279 		/// \param[out] result The result of the query.  If no rows are returned, the table will only have columns.
280 		void QueryTable(unsigned *columnIndicesSubset, unsigned numColumnSubset, FilterQuery *inclusionFilters, unsigned numInclusionFilters, unsigned *rowIds, unsigned numRowIDs, Table *result);
281 
282 		/// \brief Sorts the table by rows
283 		/// \details You can sort the table in ascending or descending order on one or more columns
284 		/// Columns have precedence in the order they appear in the \a sortQueries array
285 		/// If a row cell on column n has the same value as a a different row on column n, then the row will be compared on column n+1
286 		/// \param[in] sortQueries A list of SortQuery structures, defining the sorts to perform on the table
287 		/// \param[in] numColumnSubset The number of elements in \a numSortQueries
288 		/// \param[out] out The address of an array of Rows, which will receive the sorted output.  The array must be long enough to contain all returned rows, up to GetRowCount()
289 		void SortTable(Table::SortQuery *sortQueries, unsigned numSortQueries, Table::Row** out);
290 
291 		/// \brief Frees all memory in the table.
292 		void Clear(void);
293 
294 		/// \brief Prints out the names of all the columns.
295 		/// \param[out] out A pointer to an array of bytes which will hold the output.
296 		/// \param[in] outLength The size of the \a out array
297 		/// \param[in] columnDelineator What character to print to delineate columns
298 		void PrintColumnHeaders(char *out, int outLength, char columnDelineator) const;
299 
300 		/// \brief Writes a text representation of the row to \a out.
301 		/// \param[out] out A pointer to an array of bytes which will hold the output.
302 		/// \param[in] outLength The size of the \a out array
303 		/// \param[in] columnDelineator What character to print to delineate columns
304 		/// \param[in] printDelineatorForBinary Binary output is not printed.  True to still print the delineator.
305 		/// \param[in] inputRow The row to print
306 		void PrintRow(char *out, int outLength, char columnDelineator, bool printDelineatorForBinary, Table::Row* inputRow) const;
307 
308 		/// \brief Direct access to make things easier.
309 		const DataStructures::List<ColumnDescriptor>& GetColumns(void) const;
310 
311 		/// \brief Direct access to make things easier.
312 		const DataStructures::BPlusTree<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER>& GetRows(void) const;
313 
314 		/// \brief Get the head of a linked list containing all the row data.
315 		DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> * GetListHead(void);
316 
317 		/// \brief Get the first free row id.
318 		/// This could be made more efficient.
319 		unsigned GetAvailableRowId(void) const;
320 
321 		Table& operator = ( const Table& input );
322 
323 	protected:
324 		Table::Row* AddRowColumns(unsigned rowId, Row *row, DataStructures::List<unsigned> columnIndices);
325 
326 		void DeleteRow(Row *row);
327 
328 		void QueryRow(DataStructures::List<unsigned> &inclusionFilterColumnIndices, DataStructures::List<unsigned> &columnIndicesToReturn, unsigned key, Table::Row* row, FilterQuery *inclusionFilters, Table *result);
329 
330 		// 16 is arbitrary and is the order of the BPlus tree.  Higher orders are better for searching while lower orders are better for
331 		// Insertions and deletions.
332 		DataStructures::BPlusTree<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> rows;
333 
334 		// Columns in the table.
335 		DataStructures::List<ColumnDescriptor> columns;
336 	};
337 }
338 
339 #ifdef _MSC_VER
340 #pragma warning( pop )
341 #endif
342 
343 #endif
344