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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
/*-------------------------------------------------------------------------
*
* version.c
* This file contains all the rules that govern all version semantics.
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* The version stuff has not been tested under postgres95 and probably
* doesn't work! - jolly 8/19/95
*
*
* $Id: version.c,v 1.24 2000/01/26 05:56:19 momjian Exp $
*
* NOTES
* At the point the version is defined, 2 physical relations are created
* <vname>_added and <vname>_deleted.
*
* In addition, 4 rules are defined which govern the semantics of
* versions w.r.t retrieves, appends, replaces and deletes.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#define MAX_QUERY_LEN 1024
char rule_buf[MAX_QUERY_LEN];
/*
* problem: the version system assumes that the rules it declares will
* be fired in the order of declaration, it also assumes
* goh's silly instead semantics. Unfortunately, it is a pain
* to make the version system work with the new semantics.
* However the whole problem can be solved, and some nice
* functionality can be achieved if we get multiple action rules
* to work. So thats what I did -- glass
*
* Well, at least they've been working for about 20 minutes.
*
* So any comments in this code about 1 rule per transction are false...:)
*
*/
/*
* This is needed because the rule system only allows
* *1* rule to be defined per transaction.
*
* NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* If you commit the current Xact all the palloced memory GOES AWAY
* and could be re-palloced in the new Xact and the whole hell breaks
* loose and poor people like me spend 2 hours of their live chassing
* a strange memory bug instead of watching the "Get Smart" marathon
* in NICK !
* DO NOT COMMIT THE XACT, just increase the Cid counter!
* _sp.
*/
#ifdef NOT_USED
static void
eval_as_new_xact(char *query)
{
/*
* WARNING! do not uncomment the following lines WARNING!
* CommitTransactionCommand(); StartTransactionCommand();
*/
CommandCounterIncrement();
pg_exec_query(query);
}
#endif
/*
* Define a version.
*/
#ifdef NOT_USED
void
DefineVersion(char *name, char *fromRelname, char *date)
{
char *bname;
static char saved_basename[512];
static char saved_snapshot[512];
if (date == NULL)
{
/* no time ranges */
bname = fromRelname;
strcpy(saved_basename, (char *) bname);
*saved_snapshot = (char) NULL;
}
else
{
/* version is a snapshot */
bname = fromRelname;
strcpy(saved_basename, (char *) bname);
sprintf(saved_snapshot, "['%s']", date);
}
/*
* Calls the routine ``GetAttrList'' get the list of attributes from
* the base relation. Code is put here so that we only need to look up
* the attribute once for both appends and replaces.
*/
setAttrList(bname);
VersionCreate(name, saved_basename);
VersionAppend(name, saved_basename);
VersionDelete(name, saved_basename, saved_snapshot);
VersionReplace(name, saved_basename, saved_snapshot);
VersionRetrieve(name, saved_basename, saved_snapshot);
}
#endif
/*
* Creates the deltas.
*/
#ifdef NOT_USED
void
VersionCreate(char *vname, char *bname)
{
static char query_buf[MAX_QUERY_LEN];
/*
* Creating the dummy version relation for triggering rules.
*/
sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2",
vname, bname);
pg_exec_query(query_buf);
/*
* Creating the ``v_added'' relation
*/
sprintf(query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2",
vname, bname);
eval_as_new_xact(query_buf);
/*
* Creating the ``v_deleted'' relation.
*/
sprintf(query_buf, "CREATE TABLE %s_del (DOID oid)", vname);
eval_as_new_xact(query_buf);
}
#endif
/*
* Given the relation name, does a catalog lookup for that relation and
* sets the global variable 'attr_list' with the list of attributes (names)
* for that relation.
*/
#ifdef NOT_USED
static void
setAttrList(char *bname)
{
Relation rel;
int i = 0;
int maxattrs = 0;
char *attrname;
char temp_buf[512];
int notfirst = 0;
rel = heap_openr(bname);
if (rel == NULL)
{
elog(ERROR, "Unable to expand all -- amopenr failed ");
return;
}
maxattrs = RelationGetNumberOfAttributes(rel);
attr_list[0] = '\0';
for (i = maxattrs - 1; i > -1; --i)
{
attrname = NameStr(rel->rd_att->attrs[i]->attname);
if (notfirst == 1)
sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
else
{
sprintf(temp_buf, "%s = new.%s", attrname, attrname);
notfirst = 1;
}
strcat(attr_list, temp_buf);
}
heap_close(rel);
return;
}
#endif
/*
* This routine defines the rule governing the append semantics of
* versions. All tuples appended to a version gets appended to the
* <vname>_added relation.
*/
#ifdef NOT_USED
static void
VersionAppend(char *vname, char *bname)
{
sprintf(rule_buf,
"define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)",
vname, vname, vname, attr_list);
eval_as_new_xact(rule_buf);
}
#endif
/*
* This routine defines the rule governing the retrieval semantics of
* versions. To retrieve tuples from a version , we need to:
*
* 1. Retrieve all tuples in the <vname>_added relation.
* 2. Retrieve all tuples in the base relation which are not in
* the <vname>_del relation.
*/
#ifdef NOT_USED
void
VersionRetrieve(char *vname, char *bname, char *snapshot)
{
sprintf(rule_buf,
"define rewrite rule %s_retrieve is on SELECT to %s do instead\n\
SELECT %s_1.oid, %s_1.* from _%s in %s%s, %s_1 in (%s_added | _%s) \
where _%s.oid !!= '%s_del.DOID'",
vname, vname, vname, vname, bname,
bname, snapshot,
vname, vname, bname, bname, vname);
eval_as_new_xact(rule_buf);
/* printf("%s\n",rule_buf); */
}
#endif
/*
* This routine defines the rules that govern the delete semantics of
* versions. Two things happens when we delete a tuple from a version:
*
* 1. If the tuple to be deleted was added to the version *after*
* the version was created, then we simply delete the tuple
* from the <vname>_added relation.
* 2. If the tuple to be deleted is actually in the base relation,
* then we have to mark that tuple as being deleted by adding
* it to the <vname>_del relation.
*/
#ifdef NOT_USED
void
VersionDelete(char *vname, char *bname, char *snapshot)
{
sprintf(rule_buf,
"define rewrite rule %s_delete1 is on delete to %s do instead\n \
[delete %s_added where current.oid = %s_added.oid\n \
append %s_del(DOID = current.oid) from _%s in %s%s \
where current.oid = _%s.oid] \n",
vname, vname, vname, vname, vname,
bname, bname, snapshot, bname);
eval_as_new_xact(rule_buf);
#ifdef OLD_REWRITE
sprintf(rule_buf,
"define rewrite rule %s_delete2 is on delete to %s do instead \n \
append %s_del(DOID = current.oid) from _%s in %s%s \
where current.oid = _%s.oid \n",
vname, vname, vname, bname, bname, snapshot, bname);
eval_as_new_xact(rule_buf);
#endif /* OLD_REWRITE */
}
#endif
/*
* This routine defines the rules that govern the update semantics
* of versions. To update a tuple in a version:
*
* 1. If the tuple is in <vname>_added, we simply ``replace''
* the tuple (as per postgres style).
* 2. if the tuple is in the base relation, then two things have to
* happen:
* 2.1 The tuple is marked ``deleted'' from the base relation by
* adding the tuple to the <vname>_del relation.
* 2.2 A copy of the tuple is appended to the <vname>_added relation
*/
#ifdef NOT_USED
void
VersionReplace(char *vname, char *bname, char *snapshot)
{
sprintf(rule_buf,
"define rewrite rule %s_replace1 is on replace to %s do instead \n\
[replace %s_added(%s) where current.oid = %s_added.oid \n\
append %s_del(DOID = current.oid) from _%s in %s%s \
where current.oid = _%s.oid\n\
append %s_added(%s) from _%s in %s%s \
where current.oid !!= '%s_added.oid' and current.oid = _%s.oid]\n",
vname, vname, vname, attr_list, vname,
vname, bname, bname, snapshot, bname,
vname, attr_list, bname, bname, snapshot, vname, bname);
eval_as_new_xact(rule_buf);
/* printf("%s\n",rule_buf); */
#ifdef OLD_REWRITE
sprintf(rule_buf,
"define rewrite rule %s_replace2 is on replace to %s do \n\
append %s_del(DOID = current.oid) from _%s in %s%s \
where current.oid = _%s.oid\n",
vname, vname, vname, bname, bname, snapshot, bname);
eval_as_new_xact(rule_buf);
sprintf(rule_buf,
"define rewrite rule %s_replace3 is on replace to %s do instead\n\
append %s_added(%s) from _%s in %s%s \
where current.oid !!= '%s_added.oid' and current.oid = \
_%s.oid\n",
vname, vname, vname, attr_list, bname, bname, snapshot, vname, bname);
eval_as_new_xact(rule_buf);
#endif /* OLD_REWRITE */
/* printf("%s\n",rule_buf); */
}
#endif
|