summaryrefslogtreecommitdiff
path: root/public/gcsdk/sqlaccess/recordinfo.h
blob: a4d332aba2d39b1b58dabec260fb67d6467917c5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#ifndef GCRECORDINFO_H
#define GCRECORDINFO_H

namespace GCSDK
{

typedef CUtlMap<const char *,int> CMapIColumnInfo;

// --------------------------------------------------------------------------
// Information about a column in a record (table or result set)
class CColumnInfo
{
public:
	CColumnInfo();
	~CColumnInfo() { }

	void Set( const char *pchName, int nSQLColumn, EGCSQLType eGCSQLType, int cubFixedSize, int nColFlags, int cubMaxSize );
	const char *GetName() const { return m_rgchName; }
	int GetSQLColumn() const { return m_nSQLColumn; }
	EGCSQLType GetType() const { return m_eType; }
	int GetFixedSize() const { return m_cubFixedSize; }
	int GetMaxSize() const { return m_cchMaxSize; }
	int	GetChecksum() const { Assert( m_bHaveChecksum ); return m_nChecksum; }
	bool BIsVariableLength() const;
	int GetColFlags() const { return m_nColFlags; }
	void GetColFlagDescription( char* pstrOut, int cubOutLength ) const;
	int GetConstraintColFlags() { return m_nColFlags & k_nColFlagAllConstraints; }
	void SetColFlagBits( int nColFlag );
	bool BIsIndexed() const { return 0 != ( m_nColFlags & k_nColFlagIndexed ); }
	bool BIsClustered() const { return 0 != ( m_nColFlags & k_nColFlagClustered ); }
	bool BIsUnique() const { return 0 != ( m_nColFlags & k_nColFlagUnique ); }
	bool BIsAutoIncrement()	const { return 0 != ( m_nColFlags & k_nColFlagAutoIncrement ); }
	bool BIsPrimaryKey() const { return 0 != ( m_nColFlags & k_nColFlagPrimaryKey ); }
	bool BIsExplicitlyIndexed() const { return BIsIndexed() && !( BIsPrimaryKey() || BIsUnique() ); }
	bool BIsExplicitlyUnique() const { return BIsUnique() && !BIsPrimaryKey(); }
	bool BIsInsertable() const { return !BIsAutoIncrement(); }
	void CalculateChecksum();
	void ValidateColFlags() const;
	bool operator==( const CColumnInfo& refOther ) const;
	bool operator!=( const CColumnInfo& refOther ) const
	{
		return ! operator==( refOther );
	}

#ifdef DBGFLAG_VALIDATE
	void Validate( CValidator &validator, const char *pchName );
#endif // DBGFLAG_VALIDATE
private:
	CColumnInfo( CColumnInfo& ); // no copy constructor, disable default copy constructor
	CColumnInfo& operator = ( CColumnInfo& );	// no assignment operator, disable default assignment operator
	char	m_rgchName[k_cSQLObjectNameMax+1];

	EGCSQLType	m_eType;		// GC-based enum data type of this column
	int		m_nColFlags;			// flags for this column
	int		m_nSQLColumn;			// column # in SQL database to bind to, starts at 1.  
	int		m_cubFixedSize;			// if fixed size, the fixed size in bytes; else 0
	int		m_cchMaxSize;			// if variable size, the maximum size; else 0
	int		m_nChecksum;			// checksum of this column info for quick comparisons
	bool	m_bHaveChecksum;		// have we calculated a checksum yet?
};

// --------------------------------------------------------------------------
// Information about a record (table or result set)
class CRecordInfo : public CRefCount
{
public:
	CRecordInfo();

	void InitFromDSSchema( CSchema *pSchema );

	void SetName( const char *pchName );
	const char *GetName() const { return m_rgchName; }
	void AddColumn( const char *pchName, int nSQLColumn, EGCSQLType eGCSQLType, int cubFixedSize, int nColFlags, int cubMaxSize );
	void SetAllColumnsAdded() { m_bAllColumnsAdded = true; }
	void PrepareForUse();
	int GetFixedSize() const { return m_cubFixedSize; }
	int GetNumColumns() const { return m_VecColumnInfo.Count(); }
	const CColumnInfo &GetColumnInfo( uint32 unColumn ) const { return m_VecColumnInfo[unColumn]; }
	CColumnInfo &GetColumnInfo( uint32 unColumn ) { return m_VecColumnInfo[unColumn]; }
	bool BFindColumnByName( const char *pchName, int *piColumn );
	bool BPreparedForUse() const { return m_bPreparedForUse; }
	void EnsureCapacity( int cColumns ) { m_VecColumnInfo.EnsureCapacity( cColumns ); }
	int	GetChecksum();
	ESchemaCatalog GetESchemaCatalog() const { return m_eSchemaCatalog; }
	void SetESchemaCatalog( ESchemaCatalog e ) { m_eSchemaCatalog = e; }
	bool EqualTo( CRecordInfo* pOther );
	bool CompareIndexLists( CRecordInfo *pOther );
	bool CompareFKs( CRecordInfo *pOther );
	bool CompareFTSIndexLists( CRecordInfo *pOther ) const;
	EPrimaryKeyType GetPrimaryKeyType() const { return m_nHasPrimaryKey; }
	bool BHasPrimaryKey() { return GetPrimaryKeyType() != k_EPrimaryKeyTypeNone; }
	const FieldSet_t& GetPKFields() { Assert( BHasPrimaryKey()); return GetIndexFields( )[ m_iPKIndex ]; }
	const CUtlVector<FieldSet_t>& GetIndexFields() const { return m_VecIndexes; }
	int GetIndexFieldCount() const { return m_VecIndexes.Count(); }
	int FindIndex( CRecordInfo *pRec, const FieldSet_t& fieldSet );
	int FindIndexByName( const char *pszName ) const;
	int GetPKIndex() const { return m_iPKIndex; }
	void SetPKIndex( int i ) { m_iPKIndex = i; }
	int AddIndex( const FieldSet_t& fieldSet );
	void GetIndexFieldList( CFmtStr1024 *pstr, int nIndents ) const;
	int GetTableID() const { return m_nTableID; }
	void SetTableID( int nTableID ) { m_nTableID = nTableID; }
	bool BHasIdentity() const;

	// full-text index
	CUtlVector<int> & GetFTSFields() { return m_vecFTSFields; }
	bool BHasFTSIndex() const { return m_vecFTSFields.Count() > 0; }
	void AddFTSFields( CUtlVector< int > &refVecFields );
	int GetFullTextCatalogIndex() { return m_nFullTextCatalogIndex; }

	// foreign keys
	void AddFK( const FKData_t &fkData );
	void GetFKListString( CFmtStr1024 *pstr, int nIndents );
	int GetFKCount();
	FKData_t &GetFKData( int iIndex );


	static CRecordInfo *Alloc();
#ifdef DBGFLAG_VALIDATE
	static void ValidateStatics( CValidator &validator, const char *pchName );
	void Validate( CValidator &validator, const char *pchName );
#endif //DBGFLAG_VALIDATE


	// note: destructor is private.  This is a ref-counted object, private destructor ensures callers can't accidentally delete
	// directly, or declare on stack
	virtual ~CRecordInfo() { }

private:
	virtual void DestroyThis();
	void CalculateChecksum();
	void BuildColumnNameIndex();

	char m_rgchName[k_cSQLObjectNameMax+1];
	int m_nTableID;										// Object_ID if this table in SQL Server
	CUtlVector<CColumnInfo> m_VecColumnInfo;			// Vector of columns in this record
	CMapIColumnInfo m_MapIColumnInfo;					// Map of name->column index for quick lookup by name
	EPrimaryKeyType m_nHasPrimaryKey;					// Does this table contain a column that is a primary key?
	int m_iPKIndex;										// index info m_VecIndexes of our PK index; -1 if no PK
	CUtlVector<FieldSet_t> m_VecIndexes;				// vector of all fields in all indexes
	int m_cubFixedSize;									// Sum of data sizes for all fixed size columns
	bool m_bAllColumnsAdded;							// Have all columns been added
	bool m_bPreparedForUse;								// Have we finished being initialized?
	bool m_bHaveColumnNameIndex;						// Have we created a column name index?  (Only generated if someone asks.)
	bool m_bHaveChecksum;								// Have we generated a checksum?  (Only generated if someone asks.)
	int m_nChecksum;									// checksum of this record info for quick comparisons - includes all columns
	ESchemaCatalog m_eSchemaCatalog;					// what catalog owns this object?
	CUtlVector< int > m_vecFTSFields;					// which fields have FTS indexing?
	int m_nFullTextCatalogIndex;						// index of catalog for FTS index, if we get one
	CUtlVector<FKData_t> m_VecFKData;					// vector of all FK relationships defined on this table

	CThreadMutex m_Mutex;
	static CThreadSafeClassMemoryPool<CRecordInfo>		sm_MemPoolRecordInfo;

#ifdef _DEBUG
	// validation tracking
	static CUtlRBTree<CRecordInfo *, int >	sm_mapPMemPoolRecordInfo;
	static CThreadMutex	sm_mutexMemPoolRecordInfo;
#endif
};


int __cdecl CompareColumnInfo( const CColumnInfo *pColumnInfoLeft, const CColumnInfo *pColumnInfoRight );


} // namespace GCSDK
#endif // GCRECORDINFO_H