summaryrefslogtreecommitdiff
path: root/public/gcsdk/sqlaccess/columnset.h
blob: f61aa5bce65f496e07555c092dd3187bb47b3baf (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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Sets of columns in queries
//
// $NoKeywords: $
//=============================================================================

#ifndef COLUMNSET_H
#define COLUMNSET_H

#ifdef _WIN32
#pragma once
#endif

namespace GCSDK
{

//-----------------------------------------------------------------------------
// Purpose: Sets of columns in queries
//-----------------------------------------------------------------------------
class CColumnSet
{
public:
	CColumnSet( const CRecordInfo *pRecordInfo );
	CColumnSet( const CColumnSet & rhs );
	CColumnSet & operator=( const CColumnSet & rhs );
	const CColumnSet operator+( const CColumnSet & rhs ) const;
	CColumnSet & operator+=( const CColumnSet & rhs );

	//NOTE: These do not ensure uniqueness, the CSET_ macros below should be used instead as they will compile time enforce uniqueness
	CColumnSet( const CRecordInfo *pRecordInfo, int col1 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3, int col4 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3, int col4, int col5 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3, int col4, int col5, int col6 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3, int col4, int col5, int col6, int col7 );
	CColumnSet( const CRecordInfo *pRecordInfo, int col1, int col2, int col3, int col4, int col5, int col6, int col7, int col8 );

	void BAddColumn( int nColumn );
	void BRemoveColumn( int nColumn );
	bool IsSet( int nColumn ) const;
	bool IsEmpty() const { return m_vecColumns.Count() ==  0;}

	uint32 GetColumnCount() const;
	int GetColumn( int nIndex ) const;
	const CColumnInfo & GetColumnInfo( int nIndex ) const;

	const CRecordInfo *GetRecordInfo() const { return m_pRecordInfo; }

	void MakeEmpty();
	void MakeFull();
	void MakeInsertable();
	void MakeNoninsertable();
	void MakePrimaryKey();
	void MakeInverse( const CColumnSet & columnSet );
	//determines if the current column set has all fields set. Useful for detection of new columns being added to the schema
	bool BAreAllFieldsSet() const;

	template< typename TSchClass >
	static CColumnSet Empty();
	template< typename TSchClass >
	static CColumnSet Full();
	template< typename TSchClass >
	static CColumnSet Insertable();
	template< typename TSchClass >
	static CColumnSet Noninsertable();
	template< typename TSchClass >
	static CColumnSet PrimaryKey();
	static CColumnSet Inverse( const CColumnSet & columnSet );

#ifdef DBGFLAG_VALIDATE
	void Validate( CValidator &validator, const char *pchName );
#endif

private:
	CUtlVector<int> m_vecColumns;
	const CRecordInfo *m_pRecordInfo;
};

//this is a utility class which can at compile time ensure that all of the provided column values are unique and will generate an error if that doesn't
//hold true. The default values just need to be unique and greater than what is expected for real columns
template < int n1 = 10001, int n2 = 10002, int n3 = 10003, int n4 = 10004, int n5 = 10005, int n6 = 10006, int n7 = 10007, int n8 = 10008 >
class CUniqueColChecker
{
public:

	//this is a simple pass through so that it can wrap the declaration of a column set
	static const CColumnSet& VerifyUnique( const CColumnSet& cs )
	{
		COMPILE_TIME_ASSERT( n1 != n2 && n1 != n3 && n1 != n4 && n1 != n5 && n1 != n6 && n1 != n7 && n1 != n8 );
		COMPILE_TIME_ASSERT( n2 != n3 && n2 != n4 && n2 != n5 && n2 != n6 && n2 != n7 && n2 != n8 );
		COMPILE_TIME_ASSERT( n3 != n4 && n3 != n5 && n3 != n6 && n3 != n7 && n3 != n8 );
		COMPILE_TIME_ASSERT( n4 != n5 && n4 != n6 && n4 != n7 && n4 != n8 );
		COMPILE_TIME_ASSERT( n5 != n6 && n5 != n7 && n5 != n8 );
		COMPILE_TIME_ASSERT( n6 != n7 && n6 != n8 );
		COMPILE_TIME_ASSERT( n7 != n8 );
		return cs;
	}
};

// Usage notes:
//		The fields in a column set are order-dependent, and must match the order of the fields in
//		the query used to generate the data. The code that reads values doesn't do any fancy
//		name-matching and will copy values to incorrect locations silently if there is a
//		disagreement between the fields in the query and the fields in the column set.
//
// Examples:
//		// This is broken.
//		query	  = "SELECT * FROM Items";
//		columnSet = CSET_12_COL( CSchItem, individual_field_names );
//
//		// This is fixed.
//		query	  = "SELECT * FROM Items";
//		columnSet = CSET_FULL( ... );

#define FOR_EACH_COLUMN_IN_SET( columnSet, iterName )		for( uint32 iterName = 0; iterName < (columnSet).GetColumnCount(); iterName++ )

#define CSET_EMPTY( schClass ) CColumnSet::Empty<schClass>()
#define CSET_FULL( schClass ) CColumnSet::Full<schClass>()
#define CSET_INSERTABLE( schClass ) CColumnSet::Insertable<schClass>()
#define CSET_NONINSERTABLE( schClass ) CColumnSet::Noninsertable<schClass>()
#define CSET_PK( schClass ) CColumnSet::PrimaryKey<schClass>()

#define CSET_1_COL( schClass, col1 ) \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1 )

#define CSET_2_COL( schClass, col1, col2 ) \
	CUniqueColChecker< schClass::col1, schClass::col2 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2 ) )

#define CSET_3_COL( schClass, col1, col2, col3 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3 ) )

#define CSET_4_COL( schClass, col1, col2, col3, col4 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3, schClass::col4 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3, schClass::col4 ) )

#define CSET_5_COL( schClass, col1, col2, col3, col4, col5 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5 ) )

#define CSET_6_COL( schClass, col1, col2, col3, col4, col5, col6 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6 ) )

#define CSET_7_COL( schClass, col1, col2, col3, col4, col5, col6, col7 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6, schClass::col7 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6, schClass::col7 ) )

#define CSET_8_COL( schClass, col1, col2, col3, col4, col5, col6, col7, col8 ) \
	CUniqueColChecker< schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6, schClass::col7, schClass::col8 >::VerifyUnique( \
	CColumnSet( GSchemaFull().GetSchema( schClass::k_iTable ).GetRecordInfo(), schClass::col1, schClass::col2, schClass::col3, schClass::col4, schClass::col5, schClass::col6, schClass::col7, schClass::col8 ) )


//-----------------------------------------------------------------------------
// Purpose: Returns an empty Column Set for a schema class
//-----------------------------------------------------------------------------
template< typename TSchClass >
CColumnSet CColumnSet::Empty()
{
	CColumnSet set( GSchemaFull().GetSchema( TSchClass::k_iTable ).GetRecordInfo() );
	return set;
}


//-----------------------------------------------------------------------------
// Purpose: Returns a Column Set for a schema class which contains every field
//-----------------------------------------------------------------------------
template< typename TSchClass >
CColumnSet CColumnSet::Full()
{
	CColumnSet set( GSchemaFull().GetSchema( TSchClass::k_iTable ).GetRecordInfo() );
	set.MakeFull();
	return set;
}


//-----------------------------------------------------------------------------
// Purpose: Returns a Column Set for a schema class which contains every 
//			insertable field
//-----------------------------------------------------------------------------
template< typename TSchClass >
CColumnSet CColumnSet::Insertable()
{
	CColumnSet set( GSchemaFull().GetSchema( TSchClass::k_iTable ).GetRecordInfo() );
	set.MakeInsertable();
	return set;
}


//-----------------------------------------------------------------------------
// Purpose: Returns a Column Set for a schema class which contains every 
//			noninsertable field
//-----------------------------------------------------------------------------
template< typename TSchClass >
CColumnSet CColumnSet::Noninsertable()
{
	CColumnSet set( GSchemaFull().GetSchema( TSchClass::k_iTable ).GetRecordInfo() );
	set.MakeNoninsertable();
	return set;
}


//-----------------------------------------------------------------------------
// Purpose: Returns a Column Set for a schema class which contains every 
//			primary key field
//-----------------------------------------------------------------------------
template< typename TSchClass >
CColumnSet CColumnSet::PrimaryKey()
{
	CColumnSet set( GSchemaFull().GetSchema( TSchClass::k_iTable ).GetRecordInfo() );
	set.MakePrimaryKey();
	return set;
}

} // namespace GCSDK
#endif // COLUMNSET_H