Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

601 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #ifndef GCSCHEMA_H
  8. #define GCSCHEMA_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. namespace GCSDK
  13. {
  14. const int k_nColFlagIndexed = 0x0001; // this column is indexed.
  15. const int k_nColFlagUnique = 0x0002; // this column has a uniqueness constraint - creates implicit index
  16. const int k_nColFlagPrimaryKey = 0x0004; // this column has a primary key constraint - creates implicit uniqueness constraint & implicit index
  17. const int k_nColFlagAutoIncrement = 0x0008; // this column can have it's values created implicitly by the sql counter
  18. const int k_nColFlagClustered = 0x0010; // this column is clustered
  19. const int k_nColFlagAllConstraints = k_nColFlagUnique | k_nColFlagPrimaryKey;
  20. class CRecordInfo;
  21. struct VarFieldBlockInfo_t;
  22. struct VarFieldBlockInfo_t;
  23. struct Field_t;
  24. struct VarField_t;
  25. // Function type for altering field types when converting schemas
  26. typedef void (* PfnAlterField_t )( void *pvDest, const void *pvSrc );
  27. // EPrimaryKeyType
  28. // This shows if a table has a primary key and, if so, if it has multiple columns
  29. // or not.
  30. enum EPrimaryKeyType
  31. {
  32. k_EPrimaryKeyTypeNone = 0, // none at all
  33. k_EPrimaryKeyTypeSingle, // single-column primary key
  34. k_EPrimaryKeyTypeMulti, // multi-column primary key
  35. };
  36. // EWipePolicy
  37. // This tells us if a table is supposed to be wiped before all tests,
  38. // before all tests except stress tests, or not to be wiped before tests.
  39. enum EWipePolicy
  40. {
  41. k_EWipePolicyPreserveAlways = 0, // don't wipe table
  42. k_EWipePolicyPreserveForStress = 1, // preserve for stress tests, wipe before regular tests
  43. k_EWipePolicyWipeForAllTests = 2, // wipe table prior to all tests
  44. };
  45. //-----------------------------------------------------------------------------
  46. // Field
  47. // This defines the schema of a single field in one of our tables.
  48. //-----------------------------------------------------------------------------
  49. struct Field_t
  50. {
  51. bool BGetIntData( uint8 *pubRecord, uint64 *pulRet ) const;
  52. bool BGetFloatData( uint8 *pubRecord, float *fRet ) const;
  53. bool SetIntData( uint8 *pubRecord, uint64 ulValue ) const;
  54. // Not all fields are updated wholly at a time
  55. int CubFieldUpdateSize() const;
  56. // Handy helpers - complex fields like "rolling unique" are
  57. // still binary
  58. bool BIsStringType() const;
  59. bool BIsVariableLength() const;
  60. // Members that get serialized
  61. EGCSQLType m_EType; // Field type
  62. uint32 m_cubLength; // Length of the field in bytes
  63. uint32 m_cchMaxLength; // maximum length of the field in characters
  64. char m_rgchName[k_cSQLObjectNameMax]; // Human-readable name of this field
  65. char m_rgchSQLName[k_cSQLObjectNameMax]; // SQL name of this field
  66. // Members that don't get serialized
  67. uint32 m_nColFlags; // k_nColFlag* bits for this field
  68. uint32 m_dubOffset; // Offset of this field from beginning of record
  69. };
  70. // --------------------------------------------------------------------------
  71. // Information about a foreign key relationship defined on a table
  72. struct FKColumnRelation_t
  73. {
  74. char m_rgchCol[k_cSQLObjectNameMax+1];
  75. char m_rgchParentCol[k_cSQLObjectNameMax+1];
  76. FKColumnRelation_t()
  77. {
  78. Q_memset( m_rgchCol, 0, Q_ARRAYSIZE( m_rgchCol ) );
  79. Q_memset( m_rgchParentCol, 0, Q_ARRAYSIZE( m_rgchParentCol ) );
  80. }
  81. bool operator==( const FKColumnRelation_t &other ) const
  82. {
  83. if ( Q_stricmp( m_rgchCol, other.m_rgchCol ) )
  84. return false;
  85. if ( Q_stricmp( m_rgchParentCol, other.m_rgchParentCol ) )
  86. return false;
  87. return true;
  88. }
  89. };
  90. struct FKData_t
  91. {
  92. char m_rgchName[k_cSQLObjectNameMax+1];
  93. char m_rgchParentTableName[k_cSQLObjectNameMax+1];
  94. CCopyableUtlVector<FKColumnRelation_t> m_VecColumnRelations;
  95. EForeignKeyAction m_eOnDeleteAction;
  96. EForeignKeyAction m_eOnUpdateAction;
  97. FKData_t()
  98. {
  99. Q_memset( m_rgchName, 0, Q_ARRAYSIZE( m_rgchName ) );
  100. Q_memset( m_rgchParentTableName, 0, Q_ARRAYSIZE( m_rgchParentTableName ) );
  101. m_eOnDeleteAction = k_EForeignKeyActionNoAction;
  102. m_eOnUpdateAction = k_EForeignKeyActionNoAction;
  103. }
  104. bool operator==( const FKData_t &other ) const
  105. {
  106. if ( Q_stricmp( m_rgchName, other.m_rgchName ) )
  107. return false;
  108. if ( Q_stricmp( m_rgchParentTableName, other.m_rgchParentTableName ) )
  109. return false;
  110. if ( m_eOnDeleteAction != other.m_eOnDeleteAction || m_eOnUpdateAction != other.m_eOnUpdateAction )
  111. return false;
  112. FOR_EACH_VEC( m_VecColumnRelations, i )
  113. {
  114. bool bFoundInOther = false;
  115. const FKColumnRelation_t &cols = m_VecColumnRelations[i];
  116. FOR_EACH_VEC( other.m_VecColumnRelations, j )
  117. {
  118. const FKColumnRelation_t &colsOther = other.m_VecColumnRelations[j];
  119. if ( cols == colsOther )
  120. {
  121. bFoundInOther = true;
  122. break;
  123. }
  124. }
  125. if ( !bFoundInOther )
  126. return false;
  127. }
  128. return true;
  129. }
  130. #ifdef DBGFLAG_VALIDATE
  131. // Validate our internal structures
  132. void Validate( CValidator &validator, const char *pchName )
  133. {
  134. VALIDATE_SCOPE();
  135. ValidateObj( m_VecColumnRelations );
  136. }
  137. #endif
  138. };
  139. #pragma pack( push, 1 )
  140. //-----------------------------------------------------------------------------
  141. // SerSchema
  142. // Defines the binary serialization format for a schema.
  143. //-----------------------------------------------------------------------------
  144. struct SerSchema_t
  145. {
  146. uint32 m_cub; // Size of the whole schema (including header and fields)
  147. int32 m_iTable; // Our table's iTable
  148. char m_rgchName[k_cSQLObjectNameMax]; // Human-readable name of this table
  149. int16 m_cField; // # of fields in the schema (int16 for backward-compatibility reasons)
  150. int16 m_ETableGroup; // Our table's TableGroup (int16 for backward-compatibility reasons) - OBSOLETE
  151. };
  152. //-----------------------------------------------------------------------------
  153. // SerField
  154. // Defines the binary serialization format for a field in a schema
  155. // Note that certain fields are missing from this because we only use serialized
  156. // schemas for schema mapping. Fields that only affect runtime behavior (like
  157. // indexing) are always defined by the intrinsic schema.
  158. //-----------------------------------------------------------------------------
  159. struct SerField_t
  160. {
  161. int32 m_EType; // Field type
  162. uint32 m_cubLength; // Length of field data in bytes
  163. // For rolling fields, high 16 bits are the
  164. // size of each element
  165. char m_rgchName[k_cSQLObjectNameMax];// Human-readable name of this field
  166. char m_rgchSQLName[k_cSQLObjectNameMax]; // SQL name of this field
  167. };
  168. #pragma pack( pop )
  169. //-----------------------------------------------------------------------------
  170. // Schema conversion instructions
  171. // These specify various operations that can be performed when converting
  172. // from one Schema to another.
  173. //-----------------------------------------------------------------------------
  174. struct DeleteField_t
  175. {
  176. char m_rgchFieldName[k_cSQLObjectNameMax]; // Name of the field to delete
  177. };
  178. struct RenameField_t
  179. {
  180. char m_rgchFieldNameOld[k_cSQLObjectNameMax]; // Rename a field with this name
  181. int m_iFieldDst; // to this field
  182. };
  183. struct AlterField_t
  184. {
  185. char m_rgchFieldNameOld[k_cSQLObjectNameMax]; // Name of field in the old schema
  186. int m_iFieldDst; // iField of it in the new
  187. PfnAlterField_t m_pfnAlterFunc; // Function to translate the data
  188. };
  189. //-----------------------------------------------------------------------------
  190. // FieldSet_t describes a collection of fields in an index, as well as
  191. // attributes of the index itself
  192. //-----------------------------------------------------------------------------
  193. class FieldSet_t
  194. {
  195. public:
  196. FieldSet_t( bool bUnique, bool bClustered, const CUtlVector<int>& vecFields, const char* pstrIndexName )
  197. : m_bClustered( bClustered ), m_bUnique( bUnique )
  198. {
  199. m_VecFields = vecFields;
  200. // zero means to use the server default
  201. m_nFillFactor = 0;
  202. // null name is allowed for primary keys
  203. if ( pstrIndexName != NULL )
  204. Q_strncpy( m_szIndexName, pstrIndexName, Q_ARRAYSIZE( m_szIndexName ) );
  205. else
  206. m_szIndexName[0] = 0;
  207. }
  208. FieldSet_t( )
  209. {
  210. }
  211. ~FieldSet_t( )
  212. {
  213. }
  214. FieldSet_t( const FieldSet_t &refOther )
  215. {
  216. DoAssignment( refOther );
  217. }
  218. FieldSet_t& operator=( const FieldSet_t &refOther )
  219. {
  220. DoAssignment( refOther );
  221. return *this;
  222. }
  223. void DoAssignment( const FieldSet_t &refOther )
  224. {
  225. m_VecFields = refOther.m_VecFields;
  226. m_VecIncluded = refOther.m_VecIncluded;
  227. m_bClustered = refOther.m_bClustered;
  228. m_bUnique = refOther.m_bUnique;
  229. m_nFillFactor = refOther.m_nFillFactor;
  230. Q_strncpy( m_szIndexName, refOther.m_szIndexName, Q_ARRAYSIZE( m_szIndexName ) );
  231. }
  232. // get count of fields in this index
  233. int GetCount() const
  234. {
  235. return m_VecFields.Count();
  236. }
  237. // get count of included fields in this index
  238. int GetIncludedCount() const
  239. {
  240. return m_VecIncluded.Count();
  241. }
  242. void AddIncludedColumn( int nIndex )
  243. {
  244. m_VecIncluded.AddToTail( nIndex );
  245. }
  246. void AddIncludedColumns( const CUtlVector<int> &refVec )
  247. {
  248. m_VecIncluded.AddVectorToTail( refVec );
  249. }
  250. // get a particular field ID
  251. // the returned index is into the VecFields of the associated schema
  252. int GetField( int nIndex ) const
  253. {
  254. return m_VecFields[ nIndex ];
  255. }
  256. int GetIncludedField( int nIndex ) const
  257. {
  258. return m_VecIncluded[ nIndex ];
  259. }
  260. // is this index clustered?
  261. bool IsClustered() const
  262. {
  263. return m_bClustered;
  264. }
  265. // is this index unique?
  266. bool IsUnique() const
  267. {
  268. return m_bUnique;
  269. }
  270. void SetClustered( bool bIsClustered )
  271. {
  272. m_bClustered = bIsClustered;
  273. }
  274. void SetFillFactor( int nFactor )
  275. {
  276. Assert( nFactor >= 0 && nFactor <= 100 );
  277. m_nFillFactor = nFactor;
  278. }
  279. int GetFillFactor( ) const
  280. {
  281. return m_nFillFactor;
  282. }
  283. const char* GetIndexName() const
  284. {
  285. return m_szIndexName;
  286. }
  287. // determine if this fieldset is equal to the other one
  288. static bool CompareFieldSets( const FieldSet_t& refThis, CRecordInfo* pRecordInfoThis,
  289. const FieldSet_t& refOther, CRecordInfo* pRecordInfoOther );
  290. #ifdef DBGFLAG_VALIDATE
  291. // Validate our internal structures
  292. void Validate( CValidator &validator, const char *pchName )
  293. {
  294. VALIDATE_SCOPE();
  295. m_VecFields.Validate( validator, "m_VecFields" );
  296. m_VecIncluded.Validate( validator, "m_VecIncluded" );
  297. }
  298. #endif
  299. private:
  300. CUtlVector<int> m_VecFields; // ids of fields; indexes into m_VecFields of CSchema for a table
  301. CUtlVector<int> m_VecIncluded; // ids of included fields
  302. int m_nFillFactor; // fill factor for the index; zero means to use the server's default
  303. char m_szIndexName[k_cSQLObjectNameMax]; // name of this index
  304. bool m_bClustered:1; // is this index clustered?
  305. bool m_bUnique:1; // is this index unique?
  306. };
  307. //-----------------------------------------------------------------------------
  308. enum ESchemaCatalog
  309. {
  310. k_ESchemaCatalogInvalid = -1,
  311. k_ESchemaCatalogMain = 0, // main GC catalog
  312. k_ESchemaCatalogOGS = 4, // operational game stats
  313. };
  314. extern const char* PchNameFromESchemaCatalog( ESchemaCatalog e );
  315. //-----------------------------------------------------------------------------
  316. // CSchema
  317. // This defines the schema for a single table. The schema essentially defines
  318. // what's in the table (ie, field 0 is a 32 char string called "Name", etc.)
  319. // The schema is in charge of manipulating individual records within the table.
  320. //-----------------------------------------------------------------------------
  321. class CSchemaFull;
  322. class CSchema
  323. {
  324. public:
  325. // Constructors & destructors
  326. CSchema();
  327. ~CSchema();
  328. // Recalculates field offsets and maximum record size.
  329. // Must be called after changing schema.
  330. void CalcOffsets();
  331. // called to make final calculations when all fields/indexes/etc have been added and the schema is ready to be used
  332. void PrepareForUse();
  333. // Sizing information
  334. uint32 CubSerialSchema() const { return( sizeof( SerSchema_t ) + m_VecField.Count() * sizeof( SerField_t ) ); }
  335. // Size of total fixed-length portion of record
  336. uint32 CubRecordFixed() const { return( m_cubRecord ); }
  337. // Size of the total variable-length portion of record (zero if no var-length fields)
  338. uint32 CubRecordVariable( const void *pvRecord ) const;
  339. // Does this record have variable-length fields?
  340. bool BHasVariableFields() const { return m_bHasVarFields; }
  341. VarFieldBlockInfo_t* PVarFieldBlockInfoFromRecord( const void *pvRecord ) const;
  342. // Access field data - fixed or variable (may return NULL/0 for empty var field)
  343. bool BGetFieldData( const void *pvRecord, int iField, uint8 **ppubField, uint32 *pcubField ) const;
  344. bool BSetFieldData( void *pvRecord, int iField, uint8 *pubField, uint32 cubField, bool *pbVarBlockRealloced );
  345. bool BGetVarField( const void *pvRecord, const VarField_t *pVarField, uint8 **ppubField, uint32 *pcubField ) const;
  346. bool BSetVarField( void *pvRecord, VarField_t *pVarField, const void *pvData, uint32 cubData, bool *pbRealloced, bool bFreeOnRealloc );
  347. // Adjust var-block pointer, if present, to point just after the fixed part of the record
  348. void FixupDeserializedRecord( void *pvRecord );
  349. // Render a record in text format
  350. void RenderRecord( uint8 *pubRecord );
  351. void RenderField( uint8 *pubRecord, int iField, int cchBuffer, char *pchBuffer );
  352. // Accessors
  353. void SetITable( int iTable ) { m_iTable = iTable; }
  354. int GetITable() const { return m_iTable; }
  355. int GetCField() const { return m_VecField.Count(); }
  356. void SetReportingInterval( int nInterval ) { m_nReportingInterval = nInterval; }
  357. int GetReportingInterval( ) const { return m_nReportingInterval; }
  358. Field_t &GetField( int iField ) { return m_VecField[iField]; }
  359. const Field_t &GetField( int iField ) const { return m_VecField[iField]; }
  360. VarField_t *GetPVarField( void *pvRecord, int iField ) { return ( VarField_t * )( ( uint8 * ) pvRecord + m_VecField[iField].m_dubOffset ); }
  361. void SetName( const char *pchName ) { Q_strncpy( m_rgchName, pchName, sizeof( m_rgchName ) ); }
  362. const char *GetPchName() const { return m_rgchName; }
  363. const FieldSet_t& GetPKFields() { Assert( m_iPKIndex != -1 ); return GetIndexes()[m_iPKIndex]; }
  364. int GetPKIndex() const { return m_iPKIndex; }
  365. const CUtlVector<FieldSet_t>& GetIndexes() { return m_VecIndexes; }
  366. const CUtlVector<int>& GetFTSColumns() { return m_VecFullTextIndexes; }
  367. int GetFTSIndexCatalog() const { return m_nFullTextIndexCatalog; }
  368. ESchemaCatalog GetESchemaCatalog() const { return m_eSchemaCatalog; }
  369. void SetESchemaCatalog( ESchemaCatalog eSchemaCatalog ) { m_eSchemaCatalog = eSchemaCatalog; }
  370. // If cRecordMax is non-zero, this is a rolling table that only
  371. // holds on to cRecordMax records at most.
  372. void SetCRecordMax( int cRecordMax ) { m_cRecordMax = cRecordMax; }
  373. int GetCRecordMax() const { return m_cRecordMax; }
  374. // Is this table for TESTs only?
  375. void SetBTestTable( bool bTestTable ) { m_bTestTable = bTestTable; }
  376. bool GetBTestTable() const { return m_bTestTable; }
  377. // Randomly init a record or field to random values
  378. void InitRecordRandom( uint8 *pubRecord, uint32 unPrimaryIndex, bool *pbVarBlockRealloced, bool bFreeVarBlockOnRealloc );
  379. void SetFieldRandom( uint8 *pubRecord, int iField, bool *pbVarBlockRealloced, bool bFreeVarBlockOnRealloc );
  380. // Checksum the schema
  381. uint32 CalcChecksum();
  382. // pre-allocate space in the field array
  383. void EnsureFieldCount( int cFields )
  384. {
  385. m_VecField.EnsureCapacity( cFields );
  386. }
  387. // This adds a field from our intrinsic schema to us
  388. void AddField( char *pchName, char *pchSQLName, EGCSQLType eType, uint32 cubSize, int cchMaxLength );
  389. void AddIntField( char *pchName, char *pchSQLName, EGCSQLType eType, int cubSize );
  390. // We want to make a particular field the primary key
  391. int PrimaryKey( bool bClustered, int nFillFactor, const char *pchName );
  392. // we want to make a particular list of fields the primary key
  393. int PrimaryKeys( bool bClustered, int nFillFactor, const char *pchNames );
  394. // We want to index a particular field by name
  395. int IndexField( const char *pchName, const char *pchIndexName );
  396. // We want to index a particular list of fields in a group
  397. int IndexFields( const char *pchIndexName, const char *pchNames );
  398. // We want a certain index to additionally include a list of fields
  399. void AddIncludedFields( const char *pchIndexName, const char *pchNames );
  400. // We want to unique index a particular list of fields in a group
  401. int UniqueFields( const char *pchIndexName, const char *pchNames );
  402. // add a full-text index to the given column
  403. void AddFullTextIndex( CSchemaFull *pSchemaFull, const char *pchCatalogName, const char *pchColumnName );
  404. // We want to index a particular field by field number
  405. // (field number is an index into the m_VecField array)
  406. int AddIndexToFieldNumber( int iField, const char *pchIndexName, bool bClustered );
  407. // We want to index a particular set of fields
  408. // pchNames includes the names, separated by commas, of each field
  409. int AddIndexToFieldList( const char *pchNames, const char *pchIndexName, int nFlags, int nFillFactor );
  410. // We want a unique index on a particular field
  411. int UniqueField( const char *pchName, const char *pchIndexName );
  412. // We want to have a clustered index on a particular field by name
  413. int ClusteredIndexField( int nFillFactor, const char *pchName, const char *pchIndexName );
  414. // We want to index a particular list of fields in a group
  415. int ClusteredIndexFields( int nFillFactor, const char *pchIndexName, const char *pchNames );
  416. // We want an autoinc on a particular field
  417. void AutoIncrementField( char *pchName );
  418. // catalog on which we'll enable FTS
  419. void EnableFTS( ESchemaCatalog eCatalog );
  420. // adds a full text catalog with the given name on the identified fileset
  421. void AddFullTextCatalog( ESchemaCatalog eCatalog, const char *pstrCatalogName, const char *pstrFileGroupName );
  422. // Adds a FK on the table
  423. void AddFK( const char* pchName, const char* pchColumn, const char* pchParentTable, const char* pchParentColumn, EForeignKeyAction eOnDeleteAction, EForeignKeyAction eOnUpdateAction );
  424. // Access FK data
  425. int GetFKCount();
  426. FKData_t &GetFKData( int iIndex );
  427. void SetTestWipePolicy( EWipePolicy policy ) { m_wipePolicy = policy; }
  428. EWipePolicy GetTestWipePolicy() const { return m_wipePolicy; }
  429. void SetBAllowWipeTableInProd( bool bVal ) { m_bAllowWipeInProd = bVal; }
  430. bool BAllowWipeTableInProd() const { return m_bAllowWipeInProd; }
  431. void SetPrepopulatedTable( ) { m_bPrepopulatedTable = true; }
  432. bool BPrepopulatedTable( ) const { return m_bPrepopulatedTable; }
  433. // Find the field with a given name (returns k_iFieldNil if not found)
  434. int FindIField( const char *pchName );
  435. int FindIFieldSQL( const char *pchName );
  436. // Helper functions for recording schema conversion operations
  437. void AddDeleteField( const char *pchFieldName );
  438. void AddRenameField( const char *pchFieldNameOld, const char *pchFieldNameNew );
  439. void AddAlterField( const char *pchFieldNameOld, const char *pchFieldNameNew, PfnAlterField_t pfnAlterField );
  440. // Schema conversion helper: figure out what field to map a field from a different schema to
  441. bool BCanConvertField( const char *pchFieldSrc, int *piFieldDst, PfnAlterField_t *ppfnAlterField );
  442. CRecordInfo *GetRecordInfo() { return m_pRecordInfo; }
  443. const CRecordInfo *GetRecordInfo() const { return m_pRecordInfo; }
  444. void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  445. void ValidateRecord( uint8 *pubRecord ); // Validate a record that uses our schema
  446. // cached queries
  447. const char *GetInsertStatementText() const;
  448. const char *GetMergeStatementTextOnPKWhenMatchedUpdateWhenNotMatchedInsert();
  449. const char *GetMergeStatementTextOnPKWhenNotMatchedInsert();
  450. private:
  451. int m_iTable; // The index of our table
  452. int m_iPKIndex; // index into of m_VecIndexes of our PK index; k_iFieldNil if no PK
  453. char m_rgchName[k_cSQLObjectNameMax]; // Name of this table
  454. CUtlVector<Field_t> m_VecField; // All the fields that make up the schema
  455. CUtlVector<FieldSet_t> m_VecIndexes; // vector of all fields in all indexes
  456. int m_cRecordMax; // Max # records in the table (for rolling tables)
  457. bool m_bTestTable; // Table exists only for tests
  458. bool m_bAllowWipeInProd; // should we allow WipeTable operations on this table in the beta/public universe?
  459. EWipePolicy m_wipePolicy; // should this table be wiped between all tests, no tests, or non-stress tests?
  460. bool m_bHasVarFields; // True if this table has variable-length fields
  461. bool m_bPrepopulatedTable; // true if this table is pre-populated
  462. EPrimaryKeyType m_nHasPrimaryKey; // what kind of PK do we have, if any?
  463. CRecordInfo *m_pRecordInfo; // The record description corresponding to this schema. (Similar info, record description is new form, have both for a while during DS->SQL switch)
  464. CUtlVector<int> m_VecFullTextIndexes; // vector of indexes into m_VecField of fields covered by this table's full-text index.
  465. int m_nFullTextIndexCatalog; // index of catalog to use for creating full-text indexes
  466. CUtlVector<FKData_t> m_VecFKData; // data on foreign keys for this schema object
  467. uint32 m_cubRecord; // Binary record length
  468. int m_nReportingInterval; // reporting interval of this table if stats; 0 if not stats
  469. ESchemaCatalog m_eSchemaCatalog; // what catalog does this table live in?
  470. // Schema conversion instructions
  471. CUtlVector<DeleteField_t> m_VecDeleteField;
  472. CUtlVector<RenameField_t> m_VecRenameField;
  473. CUtlVector<AlterField_t> m_VecAlterField;
  474. // Cached queries
  475. mutable CUtlString m_sInsertStatementText; // Cached insert statement for the table
  476. CUtlString m_sMergeStatementTextOnPKWhenMatchedUpdateWhenNotMatchedInsert; // Cached insert or update via MERGE statement for the table
  477. CUtlString m_sMergeStatementTextOnPKWhenNotMatchedInsert; // Cached insert via MERGE statement for the table
  478. };
  479. } // namespace GCSDK
  480. #endif // GCSCHEMA_H