~vkolesnikov/pbxt/pbxt-preload-test-bug

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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/* Copyright (c) 2005 PrimeBase Technologies GmbH
 *
 * PrimeBase XT
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * 2004-01-03	Paul McCullagh
 *
 * H&G2JCtL
 *
 * Implementation of the PBXT internal data dictionary.
 */

#ifndef __datadic_xt_h__
#define __datadic_xt_h__

#include <stddef.h>
#include <limits.h>

#include "ccutils_xt.h"
#include "util_xt.h"

struct XTDatabase;
struct XTTable;
struct XTIndex;
struct XTOpenTable;
struct XTIndex;

/* Constraint types: */
#define XT_DD_UNKNOWN				((u_int) -1)
#define XT_DD_INDEX					0
#define XT_DD_INDEX_UNIQUE			1
#define XT_DD_KEY_PRIMARY			2
#define XT_DD_KEY_FOREIGN			3

#define XT_KEY_ACTION_RESTRICT		1
#define XT_KEY_ACTION_CASCADE		2
#define XT_KEY_ACTION_SET_NULL		3
#define XT_KEY_ACTION_SET_DEFAULT	4
#define XT_KEY_ACTION_NO_ACTION		5		/* Like RESTRICT, but check at end of statement. */ 

class XTDDEnumerableColumn;
class XTDDColumnFactory;

class XTDDColumn : public XTObject {

protected:

	XTDDColumn() : XTObject(),
		dc_name(NULL),
		dc_data_type(NULL),
		dc_null_ok(true),
		dc_auto_inc(false) {
	}

public:
	char	*dc_name;
	char	*dc_data_type;
	bool	dc_null_ok;
	bool	dc_auto_inc;

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDColumn()))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

	virtual void init(XTThreadPtr self) { 
		XTObject::init(self);
	}
	virtual void init(XTThreadPtr self, XTObject *obj);
	virtual void finalize(XTThreadPtr self);
	virtual void loadString(XTThreadPtr self, XTStringBufferPtr sb);

	virtual XTDDEnumerableColumn *castToEnumerable() { 
		return NULL;
	}

	friend class XTDDColumnFactory;
};

/*
 * subclass for ENUMs and SETs
 */
class XTDDEnumerableColumn : public XTDDColumn {

protected:
	XTDDEnumerableColumn() : XTDDColumn(), 
		enum_size(0), is_enum(0) {
	}

public:
	int enum_size;	/* number of elements in the ENUM or SET */
	xtBool is_enum;	/* TRUE if this is ENUM, FALSE if SET */

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDEnumerableColumn()))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

	virtual XTDDEnumerableColumn *castToEnumerable() { 
		return this;
	}

	friend class XTDDColumnFactory;
};

class XTDDColumnRef : public XTObject {
	public:
	char					*cr_col_name;

	XTDDColumnRef() : XTObject(), cr_col_name(NULL) { }

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDColumnRef()))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

	virtual void init(XTThreadPtr self) { XTObject::init(self); }
	virtual void init(XTThreadPtr self, XTObject *obj);
	virtual void finalize(XTThreadPtr self);
};

class XTDDConstraint : public XTObject {
	public:
	class XTDDTable			*co_table;								/* The table of this constraint (non-referenced). */
	u_int					co_type;
	char					*co_name;
	char					*co_ind_name;
	XTList<XTDDColumnRef>	co_cols;

	XTDDConstraint(u_int t) : XTObject(),
		co_table(NULL),
		co_type(t),
		co_name(NULL),
		co_ind_name(NULL) {
	}

	virtual void init(XTThreadPtr self) { XTObject::init(self); }
	virtual void init(XTThreadPtr self, XTObject *obj);
	virtual void finalize(XTThreadPtr self) {
		if (co_name)
			xt_free(self, co_name);
		if (co_ind_name)
			xt_free(self, co_ind_name);
		co_cols.deleteAll(self);
		XTObject::finalize(self);
	}
	virtual void loadString(XTThreadPtr self, XTStringBufferPtr sb);
	virtual void alterColumnName(XTThreadPtr self, char *from_name, char *to_name);
	void getColumnList(char *buffer, size_t size);
	bool sameColumns(XTDDConstraint *co);
	bool samePrefixColumns(XTDDConstraint *co);
	bool attachColumns();
};

class XTDDTableRef : public XTObject {
	public:
	class XTDDTableRef		*tr_next;								/* The next reference in the list. */
	class XTDDForeignKey	*tr_fkey;								/* The foreign key that references this table (if not-NULL). */

	XTDDTableRef() : XTObject(), tr_next(NULL), tr_fkey(NULL) { }
	virtual void finalize(XTThreadPtr self);
	bool modifyRow(struct XTOpenTable *tab, xtWord1 *before, xtWord1 *after, XTThreadPtr thread);
	bool checkReference(xtWord1 *before, XTThreadPtr thread);
	void deleteAllRows(XTThreadPtr self);
};

class XTDDIndex : public XTDDConstraint {	
	public:
	u_int					in_index;

	XTDDIndex(u_int type) : XTDDConstraint(type), in_index((u_int) -1) { }

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDIndex(XT_DD_UNKNOWN)))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

        virtual void init(XTThreadPtr self) { XTDDConstraint::init(self); };
	virtual void init(XTThreadPtr self, XTObject *obj);
	struct XTIndex *getIndexPtr();
};

/*
 * A foreign key is based on a local index.
 */
class XTDDForeignKey : public XTDDIndex {
	public:
	XTPathStrPtr			fk_ref_tab_name;
	XTDDTable				*fk_ref_table;
	u_int					fk_ref_index;							/* The index on which this foreign key references. */
	XTList<XTDDColumnRef>	fk_ref_cols;
	int						fk_on_delete;
	int						fk_on_update;

	XTDDForeignKey() : XTDDIndex(XT_DD_KEY_FOREIGN),
		fk_ref_tab_name(NULL),
		fk_ref_table(NULL),
		fk_ref_index(UINT_MAX),
		fk_on_delete(0),
		fk_on_update(0) {
	}

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDForeignKey()))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

        virtual void init(XTThreadPtr self) { XTDDIndex::init(self); }
	virtual void init(XTThreadPtr self, XTObject *obj);
	virtual void finalize(XTThreadPtr self);
	virtual void loadString(XTThreadPtr self, XTStringBufferPtr sb);
	void getReferenceList(char *buffer, size_t size);
	struct XTIndex *getReferenceIndexPtr();
	bool sameReferenceColumns(XTDDConstraint *co);
	bool samePrefixReferenceColumns(XTDDConstraint *co);
	bool checkReferencedTypes(XTDDTable *dt);
	void removeReference(XTThreadPtr self);
	bool insertRow(xtWord1 *before, xtWord1 *after, XTThreadPtr thread);
	bool updateRow(xtWord1 *before, xtWord1 *after, XTThreadPtr thread);

	static const char *actionTypeToString(int action);
};

class XTDDTable : public XTObject {
	private:

	public:
	struct XTTable			*dt_table;

	XTList<XTDDColumn>		dt_cols;
	XTList<XTDDIndex>		dt_indexes;

	XTRecurRWLockRec		dt_ref_lock;			/* The lock for adding and using references. */
	XTList<XTDDForeignKey>	dt_fkeys;				/* The foreign keys on this table. */
	XTDDTableRef			*dt_trefs;				/* A list of tables that reference this table. */

	virtual XTObject *factory(XTThreadPtr self) {
		XTObject *new_obj;
		
		if (!(new_obj = new XTDDTable()))
			xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
		return new_obj;
	}

	virtual void init(XTThreadPtr self);
	virtual void init(XTThreadPtr self, XTObject *obj);
	virtual void finalize(XTThreadPtr self);

	XTDDColumn *findColumn(char *name);
	void loadString(XTThreadPtr self, XTStringBufferPtr sb);
	void loadForeignKeyString(XTThreadPtr self, XTStringBufferPtr sb);
	void checkForeignKeyReference(XTThreadPtr self, XTDDForeignKey *fk);
	void attachReferences(XTThreadPtr self, struct XTDatabase *db);
	void attachReference(XTThreadPtr self, XTDDForeignKey *fk);
	void alterColumnName(XTThreadPtr self, char *from_name, char *to_name);
	void attachReference(XTThreadPtr self, XTDDTable *dt);
	void removeReferences(XTThreadPtr self);
	void removeReference(XTThreadPtr self, XTDDForeignKey *fk);
	void checkForeignKeys(XTThreadPtr self, bool temp_table);
	XTDDIndex *findIndex(XTDDConstraint *co);
	XTDDIndex *findReferenceIndex(XTDDForeignKey *fk);
	bool insertRow(struct XTOpenTable *rec_ot, xtWord1 *buffer);
	bool checkNoAction(struct XTOpenTable *ot, xtRecordID rec_id);
	xtBool checkCanDrop(xtBool drop_db);
	bool deleteRow(struct XTOpenTable *rec_ot, xtWord1 *buffer);
	void deleteAllRows(XTThreadPtr self);
	bool updateRow(struct XTOpenTable *rec_ot, xtWord1 *before, xtWord1 *after);
};

XTDDTable *xt_ri_create_table(XTThreadPtr self, bool convert, XTPathStrPtr tab_path, char *sql, XTDDTable *my_tab);

#endif