DS_Table.h 14 KB

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