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.

409 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "stdafx.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. namespace GCSDK
  11. {
  12. CSchemaFull g_SchemaFull;
  13. CSchemaFull & GSchemaFull()
  14. {
  15. return g_SchemaFull;
  16. }
  17. //-----------------------------------------------------------------------------
  18. // Purpose: Constructor
  19. //-----------------------------------------------------------------------------
  20. CSchemaFull::CSchemaFull()
  21. {
  22. m_pubScratchBuffer = NULL;
  23. m_cubScratchBuffer = 0;
  24. m_unCheckSum = 0;
  25. m_mapFTSEnabled.SetLessFunc( DefLessFunc( enum ESchemaCatalog ) );
  26. }
  27. //-----------------------------------------------------------------------------
  28. // Purpose: Destructor
  29. //-----------------------------------------------------------------------------
  30. CSchemaFull::~CSchemaFull()
  31. {
  32. Uninit();
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Purpose: Call this after you've finished setting up the SchemaFull (either
  36. // by loading it or by in GenerateIntrinsic). It calculates our checksum
  37. // and allocates our scratch buffer.
  38. //-----------------------------------------------------------------------------
  39. void CSchemaFull::FinishInit()
  40. {
  41. // Calculate our checksum
  42. m_unCheckSum = 0;
  43. for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ )
  44. m_unCheckSum += m_VecSchema[iSchema].CalcChecksum();
  45. // Allocate our scratch buffer
  46. Assert( NULL == m_pubScratchBuffer );
  47. // Include some slop for field IDs and sizes in a sparse record
  48. // 2k is way overkill but still no big deal
  49. m_cubScratchBuffer = k_cubRecordMax + 2048;
  50. m_pubScratchBuffer = ( uint8 * ) malloc( m_cubScratchBuffer );
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Call this after you've finished setting up the SchemaFull (either
  54. // by loading it or by in GenerateIntrinsic). It calculates our checksum
  55. // and allocates our scratch buffer.
  56. //-----------------------------------------------------------------------------
  57. void CSchemaFull::SetITable( CSchema* pSchema, int iTable )
  58. {
  59. // make sure we don't have this schema anywhere already
  60. for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ )
  61. {
  62. if ( pSchema != &m_VecSchema[iSchema] )
  63. AssertFatalMsg( m_VecSchema[iSchema].GetITable() != iTable, "Duplicate iTable in schema definition.\n" );
  64. }
  65. // set the pSchema object
  66. pSchema->SetITable( iTable );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: Uninits the schema. Need to call this explicitly before app shutdown
  70. // on static instances of this object, as the CSchema objects
  71. // point to memory in static memory pools which may destruct
  72. // before static instances of this object.
  73. //-----------------------------------------------------------------------------
  74. void CSchemaFull::Uninit()
  75. {
  76. m_VecSchema.RemoveAll();
  77. if ( NULL != m_pubScratchBuffer )
  78. {
  79. free( m_pubScratchBuffer );
  80. m_pubScratchBuffer = NULL;
  81. }
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Get the scratch buffer. It is large enough to handle any
  85. // record, sparse or otherwise
  86. //
  87. //-----------------------------------------------------------------------------
  88. uint8* CSchemaFull::GetPubScratchBuffer( )
  89. {
  90. return m_pubScratchBuffer;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose: This is used during the generation of our intrinsic schema. We've
  94. // added a new schema to ourselves, and we need to make sure that it
  95. // matches the corresponding C class.
  96. // Input: pSchema - Schema to check
  97. // cField - Number of fields the schema should contain.
  98. // cubRecord - Size of a record in the schema
  99. //-----------------------------------------------------------------------------
  100. void CSchemaFull::CheckSchema( CSchema *pSchema, int cField, uint32 cubRecord )
  101. {
  102. // We generate our structures and our schema using macros that operate on the
  103. // same source. We check a couple of things to make sure that they're properly in sync.
  104. // This will fail if the schema's definition specifies the wrong iTable
  105. if ( pSchema != &m_VecSchema[pSchema->GetITable()] )
  106. {
  107. EmitError( SPEW_SQL, "Table %s has a bad iTable\n", pSchema->GetPchName() );
  108. }
  109. // This will fail if there are missing lines in the schema definition
  110. if ( pSchema->GetCField() != cField )
  111. {
  112. EmitError( SPEW_SQL, "Badly formed table %s (blank line in schema def?)\n", pSchema->GetPchName() );
  113. AssertFatal( false );
  114. }
  115. // This is unlikely to fail. It indicates some kind of size mismatch (maybe a packing problem?)
  116. if ( pSchema->CubRecordFixed() != cubRecord )
  117. {
  118. // You may hit this if END_FIELDDATA_HAS_VAR_FIELDS is not used properly
  119. EmitError( SPEW_SQL, "Table %s has an inconsistent size (class = %d, schema = %d)\n",
  120. pSchema->GetPchName(), cubRecord, pSchema->CubRecordFixed() );
  121. AssertFatal( false );
  122. }
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Purpose: Finds the table with a given name.
  126. // Input: pchName - Name of the table to search for
  127. // Output: Index of the matching table ( k_iTableNil if there isn't one)
  128. //-----------------------------------------------------------------------------
  129. int CSchemaFull::FindITable( const char *pchName )
  130. {
  131. for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ )
  132. {
  133. if ( 0 == Q_strcmp( pchName, m_VecSchema[iSchema].GetPchName() ) )
  134. return iSchema;
  135. }
  136. return k_iTableNil;
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Purpose: Finds the table with a given iTable (iSchema)
  140. // Input: iTable -
  141. // Output: NULL or a const char * to the name (for temporary use only)
  142. //-----------------------------------------------------------------------------
  143. const char * CSchemaFull::PchTableFromITable( int iTable )
  144. {
  145. if ( iTable < 0 || iTable >= m_VecSchema.Count() )
  146. return NULL;
  147. else
  148. return m_VecSchema[ iTable ].GetPchName();
  149. }
  150. //-----------------------------------------------------------------------------
  151. //-----------------------------------------------------------------------------
  152. void CSchemaFull::AddFullTextCatalog( enum ESchemaCatalog eCatalog, const char *pstrCatalogName, int nFileGroup )
  153. {
  154. CFTSCatalogInfo info;
  155. info.m_eCatalog = eCatalog;
  156. info.m_nFileGroup = nFileGroup;
  157. info.m_pstrName = strdup(pstrCatalogName);
  158. m_vecFTSCatalogs.AddToTail( info );
  159. }
  160. //-----------------------------------------------------------------------------
  161. //-----------------------------------------------------------------------------
  162. int CSchemaFull::GetFTSCatalogByName( enum ESchemaCatalog eCatalog, const char *pstrCatalogName )
  163. {
  164. int nIndex = -1;
  165. FOR_EACH_VEC( m_vecFTSCatalogs, i )
  166. {
  167. CFTSCatalogInfo &refInfo = m_vecFTSCatalogs[ i ];
  168. if ( 0 == Q_stricmp( pstrCatalogName, refInfo.m_pstrName ) )
  169. {
  170. nIndex = i;
  171. break;
  172. }
  173. }
  174. return nIndex;
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Purpose: turn on FTS for the named schema catalog. Called by the
  178. // InitIntrinsic() function.
  179. //-----------------------------------------------------------------------------
  180. void CSchemaFull::EnableFTS( enum ESchemaCatalog eCatalog )
  181. {
  182. // mark it enabled in the map
  183. m_mapFTSEnabled.Insert( eCatalog, true );
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Purpose: is FTS enabled for the supplied schema catalog?
  187. //-----------------------------------------------------------------------------
  188. bool CSchemaFull::GetFTSEnabled( enum ESchemaCatalog eCatalog )
  189. {
  190. int iEntry = m_mapFTSEnabled.Find( eCatalog );
  191. if ( iEntry == m_mapFTSEnabled.InvalidIndex() )
  192. return false;
  193. return true;
  194. }
  195. //-----------------------------------------------------------------------------
  196. // Purpose: Adds a schema conversion instruction (for use in converting from
  197. // a different SchemaFull to this one).
  198. //-----------------------------------------------------------------------------
  199. void CSchemaFull::AddDeleteTable( const char *pchTableName )
  200. {
  201. DeleteTable_t &deleteTable = m_VecDeleteTable[m_VecDeleteTable.AddToTail()];
  202. Q_strncpy( deleteTable.m_rgchTableName, pchTableName, sizeof( deleteTable.m_rgchTableName ) );
  203. }
  204. //-----------------------------------------------------------------------------
  205. // Purpose: Adds a schema conversion instruction (for use in converting from
  206. // a different SchemaFull to this one).
  207. //-----------------------------------------------------------------------------
  208. void CSchemaFull::AddRenameTable( const char *pchTableNameOld, const char *pchTableNameNew )
  209. {
  210. RenameTable_t &renameTable = m_VecRenameTable[m_VecRenameTable.AddToTail()];
  211. Q_strncpy( renameTable.m_rgchTableNameOld, pchTableNameOld, sizeof( renameTable.m_rgchTableNameOld ) );
  212. renameTable.m_iTableDst = FindITable( pchTableNameNew );
  213. Assert( k_iTableNil != renameTable.m_iTableDst );
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose: Adds a schema conversion instruction (for use in converting from
  217. // a different SchemaFull to this one).
  218. //-----------------------------------------------------------------------------
  219. void CSchemaFull::AddDeleteField( const char *pchTableName, const char *pchFieldName )
  220. {
  221. int iSchema = FindITable( pchTableName );
  222. AssertFatal( k_iTableNil != iSchema );
  223. m_VecSchema[iSchema].AddDeleteField( pchFieldName );
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose: Adds a schema conversion instruction (for use in converting from
  227. // a different SchemaFull to this one).
  228. //-----------------------------------------------------------------------------
  229. void CSchemaFull::AddRenameField( const char *pchTableName, const char *pchFieldNameOld, const char *pchFieldNameNew )
  230. {
  231. int iSchema = FindITable( pchTableName );
  232. AssertFatal( k_iTableNil != iSchema );
  233. m_VecSchema[iSchema].AddRenameField( pchFieldNameOld, pchFieldNameNew );
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose: Adds a schema conversion instruction (for use in converting from
  237. // a different SchemaFull to this one).
  238. //-----------------------------------------------------------------------------
  239. void CSchemaFull::AddAlterField( const char *pchTableName, const char *pchFieldNameOld, const char *pchFieldnameNew, PfnAlterField_t pfnAlterField )
  240. {
  241. int iSchema = FindITable( pchTableName );
  242. AssertFatal( k_iTableNil != iSchema );
  243. m_VecSchema[iSchema].AddAlterField( pchFieldNameOld, pchFieldnameNew, pfnAlterField );
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose: Add a trigger to the desired schema
  247. //-----------------------------------------------------------------------------
  248. void CSchemaFull::AddTrigger( ESchemaCatalog eCatalog, const char *pchTableName, const char *pchTriggerName, ETriggerType eTriggerType, const char *pchTriggerText )
  249. {
  250. CTriggerInfo trigger;
  251. trigger.m_eTriggerType = eTriggerType;
  252. trigger.m_eSchemaCatalog = eCatalog;
  253. Q_strncpy( trigger.m_szTriggerName, pchTriggerName, Q_ARRAYSIZE( trigger.m_szTriggerName ) );
  254. Q_strncpy( trigger.m_szTriggerTableName, pchTableName, Q_ARRAYSIZE( trigger.m_szTriggerTableName ) );
  255. trigger.m_strText = pchTriggerText;
  256. // add it to our list
  257. m_VecTriggers.AddToTail( trigger );
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose: Figures out how to map a table from another SchemaFull into us.
  261. // First we check our conversion instructions to see if any apply,
  262. // and then we look for a straightforward match.
  263. // Input: pchTableName - Name of the table we're trying to map
  264. // piTableDst - [Return] Index of the table to map it to
  265. // Output: true if we know what to do with this table (if false, the conversion
  266. // is undefined and dangerous).
  267. //-----------------------------------------------------------------------------
  268. bool CSchemaFull::BCanConvertTable( const char *pchTableName, int *piTableDst )
  269. {
  270. // Should this table be deleted?
  271. for ( int iDeleteTable = 0; iDeleteTable < m_VecDeleteTable.Count(); iDeleteTable++ )
  272. {
  273. if ( 0 == Q_strcmp( pchTableName, m_VecDeleteTable[iDeleteTable].m_rgchTableName ) )
  274. {
  275. *piTableDst = k_iTableNil;
  276. return true;
  277. }
  278. }
  279. // Should this table be renamed?
  280. for ( int iRenameTable = 0; iRenameTable < m_VecRenameTable.Count(); iRenameTable++ )
  281. {
  282. if ( 0 == Q_strcmp( pchTableName, m_VecRenameTable[iRenameTable].m_rgchTableNameOld ) )
  283. {
  284. *piTableDst = m_VecRenameTable[iRenameTable].m_iTableDst;
  285. return true;
  286. }
  287. }
  288. // Find out which of our tables this table maps to (if it doesn't map
  289. // to any of them, we don't know what to do with it).
  290. *piTableDst = FindITable( pchTableName );
  291. return ( k_iTableNil != *piTableDst );
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Purpose: Gets the default SQL schema name for a catalog
  295. //-----------------------------------------------------------------------------
  296. const char *CSchemaFull::GetDefaultSchemaNameForCatalog( ESchemaCatalog eCatalog )
  297. {
  298. // For all catalogs it's actually the same
  299. if ( m_strDefaultSchemaName.IsEmpty() )
  300. {
  301. m_strDefaultSchemaName.Set( CFmtStr( "App%u", GGCBase()->GetAppID() ) );
  302. }
  303. return m_strDefaultSchemaName.Get();
  304. }
  305. #ifdef DBGFLAG_VALIDATE
  306. //-----------------------------------------------------------------------------
  307. // Purpose: Run a global validation pass on all of our data structures and memory
  308. // allocations.
  309. // Input: validator - Our global validator object
  310. // pchName - Our name (typically a member var in our container)
  311. //-----------------------------------------------------------------------------
  312. void CSchemaFull::Validate( CValidator &validator, const char *pchName )
  313. {
  314. VALIDATE_SCOPE();
  315. ValidateObj( m_VecSchema );
  316. for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ )
  317. {
  318. ValidateObj( m_VecSchema[iSchema] );
  319. }
  320. ValidateObj( m_VecDeleteTable );
  321. ValidateObj( m_VecRenameTable );
  322. ValidateObj( m_mapFTSEnabled );
  323. ValidateObj( m_vecFTSCatalogs );
  324. FOR_EACH_VEC( m_vecFTSCatalogs, i )
  325. {
  326. ValidateObj( m_vecFTSCatalogs[i] );
  327. }
  328. ValidateObj( m_VecTriggers );
  329. FOR_EACH_VEC( m_VecTriggers, i )
  330. {
  331. ValidateObj( m_VecTriggers[i] );
  332. }
  333. validator.ClaimMemory( m_pubScratchBuffer );
  334. }
  335. #endif // DBGFLAG_VALIDATE
  336. } // namespace GCSDK