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
409 lines
14 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//============================================================================= |
|
|
|
|
|
#include "stdafx.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
namespace GCSDK |
|
{ |
|
CSchemaFull g_SchemaFull; |
|
CSchemaFull & GSchemaFull() |
|
{ |
|
return g_SchemaFull; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CSchemaFull::CSchemaFull() |
|
{ |
|
m_pubScratchBuffer = NULL; |
|
m_cubScratchBuffer = 0; |
|
m_unCheckSum = 0; |
|
|
|
m_mapFTSEnabled.SetLessFunc( DefLessFunc( enum ESchemaCatalog ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
//----------------------------------------------------------------------------- |
|
CSchemaFull::~CSchemaFull() |
|
{ |
|
Uninit(); |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Call this after you've finished setting up the SchemaFull (either |
|
// by loading it or by in GenerateIntrinsic). It calculates our checksum |
|
// and allocates our scratch buffer. |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::FinishInit() |
|
{ |
|
// Calculate our checksum |
|
m_unCheckSum = 0; |
|
|
|
for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ ) |
|
m_unCheckSum += m_VecSchema[iSchema].CalcChecksum(); |
|
|
|
// Allocate our scratch buffer |
|
Assert( NULL == m_pubScratchBuffer ); |
|
// Include some slop for field IDs and sizes in a sparse record |
|
// 2k is way overkill but still no big deal |
|
m_cubScratchBuffer = k_cubRecordMax + 2048; |
|
m_pubScratchBuffer = ( uint8 * ) malloc( m_cubScratchBuffer ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Call this after you've finished setting up the SchemaFull (either |
|
// by loading it or by in GenerateIntrinsic). It calculates our checksum |
|
// and allocates our scratch buffer. |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSchemaFull::SetITable( CSchema* pSchema, int iTable ) |
|
{ |
|
// make sure we don't have this schema anywhere already |
|
for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ ) |
|
{ |
|
if ( pSchema != &m_VecSchema[iSchema] ) |
|
AssertFatalMsg( m_VecSchema[iSchema].GetITable() != iTable, "Duplicate iTable in schema definition.\n" ); |
|
} |
|
|
|
// set the pSchema object |
|
pSchema->SetITable( iTable ); |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Uninits the schema. Need to call this explicitly before app shutdown |
|
// on static instances of this object, as the CSchema objects |
|
// point to memory in static memory pools which may destruct |
|
// before static instances of this object. |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::Uninit() |
|
{ |
|
m_VecSchema.RemoveAll(); |
|
if ( NULL != m_pubScratchBuffer ) |
|
{ |
|
free( m_pubScratchBuffer ); |
|
m_pubScratchBuffer = NULL; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the scratch buffer. It is large enough to handle any |
|
// record, sparse or otherwise |
|
// |
|
//----------------------------------------------------------------------------- |
|
uint8* CSchemaFull::GetPubScratchBuffer( ) |
|
{ |
|
return m_pubScratchBuffer; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: This is used during the generation of our intrinsic schema. We've |
|
// added a new schema to ourselves, and we need to make sure that it |
|
// matches the corresponding C class. |
|
// Input: pSchema - Schema to check |
|
// cField - Number of fields the schema should contain. |
|
// cubRecord - Size of a record in the schema |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::CheckSchema( CSchema *pSchema, int cField, uint32 cubRecord ) |
|
{ |
|
// We generate our structures and our schema using macros that operate on the |
|
// same source. We check a couple of things to make sure that they're properly in sync. |
|
|
|
// This will fail if the schema's definition specifies the wrong iTable |
|
if ( pSchema != &m_VecSchema[pSchema->GetITable()] ) |
|
{ |
|
EmitError( SPEW_SQL, "Table %s has a bad iTable\n", pSchema->GetPchName() ); |
|
} |
|
|
|
// This will fail if there are missing lines in the schema definition |
|
if ( pSchema->GetCField() != cField ) |
|
{ |
|
EmitError( SPEW_SQL, "Badly formed table %s (blank line in schema def?)\n", pSchema->GetPchName() ); |
|
AssertFatal( false ); |
|
} |
|
|
|
// This is unlikely to fail. It indicates some kind of size mismatch (maybe a packing problem?) |
|
if ( pSchema->CubRecordFixed() != cubRecord ) |
|
{ |
|
// You may hit this if END_FIELDDATA_HAS_VAR_FIELDS is not used properly |
|
EmitError( SPEW_SQL, "Table %s has an inconsistent size (class = %d, schema = %d)\n", |
|
pSchema->GetPchName(), cubRecord, pSchema->CubRecordFixed() ); |
|
AssertFatal( false ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Finds the table with a given name. |
|
// Input: pchName - Name of the table to search for |
|
// Output: Index of the matching table ( k_iTableNil if there isn't one) |
|
//----------------------------------------------------------------------------- |
|
int CSchemaFull::FindITable( const char *pchName ) |
|
{ |
|
for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ ) |
|
{ |
|
if ( 0 == Q_strcmp( pchName, m_VecSchema[iSchema].GetPchName() ) ) |
|
return iSchema; |
|
} |
|
|
|
return k_iTableNil; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Finds the table with a given iTable (iSchema) |
|
// Input: iTable - |
|
// Output: NULL or a const char * to the name (for temporary use only) |
|
//----------------------------------------------------------------------------- |
|
const char * CSchemaFull::PchTableFromITable( int iTable ) |
|
{ |
|
if ( iTable < 0 || iTable >= m_VecSchema.Count() ) |
|
return NULL; |
|
else |
|
return m_VecSchema[ iTable ].GetPchName(); |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddFullTextCatalog( enum ESchemaCatalog eCatalog, const char *pstrCatalogName, int nFileGroup ) |
|
{ |
|
CFTSCatalogInfo info; |
|
info.m_eCatalog = eCatalog; |
|
info.m_nFileGroup = nFileGroup; |
|
info.m_pstrName = strdup(pstrCatalogName); |
|
|
|
m_vecFTSCatalogs.AddToTail( info ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
int CSchemaFull::GetFTSCatalogByName( enum ESchemaCatalog eCatalog, const char *pstrCatalogName ) |
|
{ |
|
int nIndex = -1; |
|
FOR_EACH_VEC( m_vecFTSCatalogs, i ) |
|
{ |
|
CFTSCatalogInfo &refInfo = m_vecFTSCatalogs[ i ]; |
|
if ( 0 == Q_stricmp( pstrCatalogName, refInfo.m_pstrName ) ) |
|
{ |
|
nIndex = i; |
|
break; |
|
} |
|
} |
|
|
|
return nIndex; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: turn on FTS for the named schema catalog. Called by the |
|
// InitIntrinsic() function. |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::EnableFTS( enum ESchemaCatalog eCatalog ) |
|
{ |
|
// mark it enabled in the map |
|
m_mapFTSEnabled.Insert( eCatalog, true ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: is FTS enabled for the supplied schema catalog? |
|
//----------------------------------------------------------------------------- |
|
bool CSchemaFull::GetFTSEnabled( enum ESchemaCatalog eCatalog ) |
|
{ |
|
int iEntry = m_mapFTSEnabled.Find( eCatalog ); |
|
if ( iEntry == m_mapFTSEnabled.InvalidIndex() ) |
|
return false; |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a schema conversion instruction (for use in converting from |
|
// a different SchemaFull to this one). |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddDeleteTable( const char *pchTableName ) |
|
{ |
|
DeleteTable_t &deleteTable = m_VecDeleteTable[m_VecDeleteTable.AddToTail()]; |
|
Q_strncpy( deleteTable.m_rgchTableName, pchTableName, sizeof( deleteTable.m_rgchTableName ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a schema conversion instruction (for use in converting from |
|
// a different SchemaFull to this one). |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddRenameTable( const char *pchTableNameOld, const char *pchTableNameNew ) |
|
{ |
|
RenameTable_t &renameTable = m_VecRenameTable[m_VecRenameTable.AddToTail()]; |
|
Q_strncpy( renameTable.m_rgchTableNameOld, pchTableNameOld, sizeof( renameTable.m_rgchTableNameOld ) ); |
|
renameTable.m_iTableDst = FindITable( pchTableNameNew ); |
|
Assert( k_iTableNil != renameTable.m_iTableDst ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a schema conversion instruction (for use in converting from |
|
// a different SchemaFull to this one). |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddDeleteField( const char *pchTableName, const char *pchFieldName ) |
|
{ |
|
int iSchema = FindITable( pchTableName ); |
|
AssertFatal( k_iTableNil != iSchema ); |
|
|
|
m_VecSchema[iSchema].AddDeleteField( pchFieldName ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a schema conversion instruction (for use in converting from |
|
// a different SchemaFull to this one). |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddRenameField( const char *pchTableName, const char *pchFieldNameOld, const char *pchFieldNameNew ) |
|
{ |
|
int iSchema = FindITable( pchTableName ); |
|
AssertFatal( k_iTableNil != iSchema ); |
|
|
|
m_VecSchema[iSchema].AddRenameField( pchFieldNameOld, pchFieldNameNew ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a schema conversion instruction (for use in converting from |
|
// a different SchemaFull to this one). |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddAlterField( const char *pchTableName, const char *pchFieldNameOld, const char *pchFieldnameNew, PfnAlterField_t pfnAlterField ) |
|
{ |
|
int iSchema = FindITable( pchTableName ); |
|
AssertFatal( k_iTableNil != iSchema ); |
|
|
|
m_VecSchema[iSchema].AddAlterField( pchFieldNameOld, pchFieldnameNew, pfnAlterField ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add a trigger to the desired schema |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::AddTrigger( ESchemaCatalog eCatalog, const char *pchTableName, const char *pchTriggerName, ETriggerType eTriggerType, const char *pchTriggerText ) |
|
{ |
|
CTriggerInfo trigger; |
|
trigger.m_eTriggerType = eTriggerType; |
|
trigger.m_eSchemaCatalog = eCatalog; |
|
Q_strncpy( trigger.m_szTriggerName, pchTriggerName, Q_ARRAYSIZE( trigger.m_szTriggerName ) ); |
|
Q_strncpy( trigger.m_szTriggerTableName, pchTableName, Q_ARRAYSIZE( trigger.m_szTriggerTableName ) ); |
|
trigger.m_strText = pchTriggerText; |
|
|
|
// add it to our list |
|
m_VecTriggers.AddToTail( trigger ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Figures out how to map a table from another SchemaFull into us. |
|
// First we check our conversion instructions to see if any apply, |
|
// and then we look for a straightforward match. |
|
// Input: pchTableName - Name of the table we're trying to map |
|
// piTableDst - [Return] Index of the table to map it to |
|
// Output: true if we know what to do with this table (if false, the conversion |
|
// is undefined and dangerous). |
|
//----------------------------------------------------------------------------- |
|
bool CSchemaFull::BCanConvertTable( const char *pchTableName, int *piTableDst ) |
|
{ |
|
// Should this table be deleted? |
|
for ( int iDeleteTable = 0; iDeleteTable < m_VecDeleteTable.Count(); iDeleteTable++ ) |
|
{ |
|
if ( 0 == Q_strcmp( pchTableName, m_VecDeleteTable[iDeleteTable].m_rgchTableName ) ) |
|
{ |
|
*piTableDst = k_iTableNil; |
|
return true; |
|
} |
|
} |
|
|
|
// Should this table be renamed? |
|
for ( int iRenameTable = 0; iRenameTable < m_VecRenameTable.Count(); iRenameTable++ ) |
|
{ |
|
if ( 0 == Q_strcmp( pchTableName, m_VecRenameTable[iRenameTable].m_rgchTableNameOld ) ) |
|
{ |
|
*piTableDst = m_VecRenameTable[iRenameTable].m_iTableDst; |
|
return true; |
|
} |
|
} |
|
|
|
// Find out which of our tables this table maps to (if it doesn't map |
|
// to any of them, we don't know what to do with it). |
|
*piTableDst = FindITable( pchTableName ); |
|
return ( k_iTableNil != *piTableDst ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Gets the default SQL schema name for a catalog |
|
//----------------------------------------------------------------------------- |
|
const char *CSchemaFull::GetDefaultSchemaNameForCatalog( ESchemaCatalog eCatalog ) |
|
{ |
|
// For all catalogs it's actually the same |
|
if ( m_strDefaultSchemaName.IsEmpty() ) |
|
{ |
|
m_strDefaultSchemaName.Set( CFmtStr( "App%u", GGCBase()->GetAppID() ) ); |
|
} |
|
|
|
return m_strDefaultSchemaName.Get(); |
|
} |
|
|
|
|
|
#ifdef DBGFLAG_VALIDATE |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Run a global validation pass on all of our data structures and memory |
|
// allocations. |
|
// Input: validator - Our global validator object |
|
// pchName - Our name (typically a member var in our container) |
|
//----------------------------------------------------------------------------- |
|
void CSchemaFull::Validate( CValidator &validator, const char *pchName ) |
|
{ |
|
VALIDATE_SCOPE(); |
|
|
|
ValidateObj( m_VecSchema ); |
|
for ( int iSchema = 0; iSchema < m_VecSchema.Count(); iSchema++ ) |
|
{ |
|
ValidateObj( m_VecSchema[iSchema] ); |
|
} |
|
|
|
ValidateObj( m_VecDeleteTable ); |
|
ValidateObj( m_VecRenameTable ); |
|
|
|
ValidateObj( m_mapFTSEnabled ); |
|
|
|
ValidateObj( m_vecFTSCatalogs ); |
|
FOR_EACH_VEC( m_vecFTSCatalogs, i ) |
|
{ |
|
ValidateObj( m_vecFTSCatalogs[i] ); |
|
} |
|
|
|
ValidateObj( m_VecTriggers ); |
|
FOR_EACH_VEC( m_VecTriggers, i ) |
|
{ |
|
ValidateObj( m_VecTriggers[i] ); |
|
} |
|
|
|
validator.ClaimMemory( m_pubScratchBuffer ); |
|
} |
|
#endif // DBGFLAG_VALIDATE |
|
|
|
} // namespace GCSDK
|
|
|