Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 68a8b71

Browse files
committed
Bugfix. Fix omissions related to shifting from 32-bit query hash to 64-bit hash
1 parent de3077a commit 68a8b71

File tree

8 files changed

+61
-63
lines changed

8 files changed

+61
-63
lines changed

aqo.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,13 @@ get_aqo_schema(void)
303303
* Init userlock
304304
*/
305305
void
306-
init_lock_tag(LOCKTAG *tag, uint32 key1, uint32 key2)
306+
init_lock_tag(LOCKTAG *tag, uint64 key1, int32 key2)
307307
{
308+
uint32 key = key1 % UINT32_MAX;
309+
308310
tag->locktag_field1 = AQO_MODULE_MAGIC;
309-
tag->locktag_field2 = key1;
310-
tag->locktag_field3 = key2;
311+
tag->locktag_field2 = key;
312+
tag->locktag_field3 = (uint32) key2;
311313
tag->locktag_field4 = 0;
312314
tag->locktag_type = LOCKTAG_USERLOCK;
313315
tag->locktag_lockmethodid = USER_LOCKMETHOD;

aqo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ int get_clause_hash(Expr *clause, int nargs, int *args_hash, int *eclass_hash);
280280

281281

282282
/* Storage interaction */
283-
extern bool find_query(uint64 qhash, Datum *search_values, bool *search_nulls);
283+
extern bool find_query(uint64 qhash, QueryContextData *ctx);
284284
extern bool update_query(uint64 qhash, uint64 fhash,
285285
bool learn_aqo, bool use_aqo, bool auto_tuning);
286286
extern bool add_query_text(uint64 query_hash, const char *query_string);
@@ -343,7 +343,7 @@ extern double *selectivity_cache_find_global_relid(int clause_hash,
343343
extern void selectivity_cache_clear(void);
344344

345345
extern Oid get_aqo_schema(void);
346-
extern void init_lock_tag(LOCKTAG *tag, uint32 key1, uint32 key2);
346+
extern void init_lock_tag(LOCKTAG *tag, uint64 key1, int32 key2);
347347
extern bool IsQueryDisabled(void);
348348

349349
extern List *cur_classes;

auto_tuning.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ is_in_infinite_loop_cq(double *elems, int nelems)
144144
* this query to false.
145145
*/
146146
void
147-
automatical_query_tuning(uint64 query_hash, QueryStat * stat)
147+
automatical_query_tuning(uint64 qhash, QueryStat * stat)
148148
{
149149
double unstability = auto_tuning_exploration;
150150
double t_aqo,
@@ -204,11 +204,11 @@ automatical_query_tuning(uint64 query_hash, QueryStat * stat)
204204
}
205205

206206
if (num_iterations <= auto_tuning_max_iterations || p_use > 0.5)
207-
update_query(query_hash,
207+
update_query(qhash,
208208
query_context.fspace_hash,
209209
query_context.learn_aqo,
210210
query_context.use_aqo,
211211
true);
212212
else
213-
update_query(query_hash, query_context.fspace_hash, false, false, false);
213+
update_query(qhash, query_context.fspace_hash, false, false, false);
214214
}

expected/plancache.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ BEGIN
3333
END $$ LANGUAGE 'plpgsql';
3434
-- The function shows 6 executions without an AQO support (nnex) and
3535
-- 4 executions with usage of an AQO knowledge base (nex). Planning time in the
36-
-- case of AQO support (pt) is equal to '-1', because the query plan is exracted
36+
-- case of AQO support (pt) is equal to '-1', because the query plan is extracted
3737
-- from the plan cache.
3838
SELECT * FROM f1();
3939
nnex | nex | pt

postprocessing.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ atomic_fss_learn_step(uint64 fhash, int fss_hash, int ncols,
9494
LOCKTAG tag;
9595
int nrows;
9696

97-
init_lock_tag(&tag, (uint32) fhash, fss_hash);
97+
init_lock_tag(&tag, fhash, fss_hash);
9898
LockAcquire(&tag, ExclusiveLock, false, false);
9999

100100
if (!load_fss(fhash, fss_hash, ncols, matrix, targets, &nrows, NULL))
@@ -671,10 +671,9 @@ aqo_ExecutorEnd(QueryDesc *queryDesc)
671671
cardinality_error = cardinality_sum_errors / cardinality_num_objects;
672672
else
673673
cardinality_error = -1;
674-
Assert(query_context.query_hash>=0);
674+
675675
/* Prevent concurrent updates. */
676-
init_lock_tag(&tag, (uint32) query_context.query_hash,//my code
677-
(uint32) query_context.fspace_hash);//possible here
676+
init_lock_tag(&tag, query_context.query_hash, query_context.fspace_hash);
678677
LockAcquire(&tag, ExclusiveLock, false, false);
679678

680679
if (stat != NULL)
@@ -706,7 +705,6 @@ aqo_ExecutorEnd(QueryDesc *queryDesc)
706705
&stat->executions_without_aqo);
707706

708707
/* Store all learn data into the AQO service relations. */
709-
Assert(query_context.query_hash>=0);
710708
if (!query_context.adding_query && query_context.auto_tuning)
711709
automatical_query_tuning(query_context.query_hash, stat);
712710

@@ -970,7 +968,6 @@ print_into_explain(PlannedStmt *plannedstmt, IntoClause *into,
970968
*/
971969
if (aqo_mode != AQO_MODE_DISABLED || force_collect_stat)
972970
{
973-
Assert(query_context.query_hash>=0);
974971
if (aqo_show_hash)
975972
ExplainPropertyInteger("Query hash", NULL,
976973
query_context.query_hash, es);

preprocessing.c

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ aqo_planner(Query *parse,
136136
ParamListInfo boundParams)
137137
{
138138
bool query_is_stored = false;
139-
Datum query_params[5];
140-
bool query_nulls[5] = {false, false, false, false, false};
141139
LOCKTAG tag;
142140
MemoryContext oldCxt;
143141

@@ -187,7 +185,7 @@ aqo_planner(Query *parse,
187185
boundParams);
188186
}
189187

190-
elog(DEBUG1, "AQO will be used for query '%s', class %ld",
188+
elog(DEBUG1, "AQO will be used for query '%s', class "UINT64_FORMAT,
191189
query_string ? query_string : "null string", query_context.query_hash);
192190

193191
oldCxt = MemoryContextSwitchTo(AQOMemoryContext);
@@ -201,8 +199,7 @@ aqo_planner(Query *parse,
201199
goto ignore_query_settings;
202200
}
203201

204-
query_is_stored = find_query(query_context.query_hash, &query_params[0],
205-
&query_nulls[0]);
202+
query_is_stored = find_query(query_context.query_hash, &query_context);
206203

207204
if (!query_is_stored)
208205
{
@@ -256,16 +253,12 @@ aqo_planner(Query *parse,
256253
else /* Query class exists in a ML knowledge base. */
257254
{
258255
query_context.adding_query = false;
259-
query_context.learn_aqo = DatumGetBool(query_params[1]);
260-
query_context.use_aqo = DatumGetBool(query_params[2]);
261-
query_context.fspace_hash = DatumGetInt64(query_params[3]);
262-
query_context.auto_tuning = DatumGetBool(query_params[4]);
263-
query_context.collect_stat = query_context.auto_tuning;
256+
257+
/* Other query_context fields filled in the find_query() routine. */
264258

265259
/*
266260
* Deactivate query if no one reason exists for usage of an AQO machinery.
267261
*/
268-
Assert(query_context.query_hash>=0);
269262
if (!query_context.learn_aqo && !query_context.use_aqo &&
270263
!query_context.auto_tuning && !force_collect_stat)
271264
add_deactivated_query(query_context.query_hash);
@@ -291,7 +284,6 @@ aqo_planner(Query *parse,
291284
* In this mode we want to learn with incoming query (if it is not
292285
* suppressed manually) and collect stats.
293286
*/
294-
Assert(query_context.query_hash>=0);
295287
query_context.collect_stat = true;
296288
query_context.fspace_hash = query_context.query_hash;
297289
break;
@@ -315,15 +307,13 @@ aqo_planner(Query *parse,
315307
* find-add query and query text must be atomic operation to prevent
316308
* concurrent insertions.
317309
*/
318-
Assert(query_context.query_hash>=0);
319-
init_lock_tag(&tag, (uint32) query_context.query_hash, (uint32) 0);//my code
310+
init_lock_tag(&tag, query_context.query_hash, 0);
320311
LockAcquire(&tag, ExclusiveLock, false, false);
321312
/*
322313
* Add query into the AQO knowledge base. To process an error with
323314
* concurrent addition from another backend we will try to restart
324315
* preprocessing routine.
325316
*/
326-
Assert(query_context.query_hash>=0);
327317
update_query(query_context.query_hash, query_context.fspace_hash,
328318
query_context.learn_aqo, query_context.use_aqo,
329319
query_context.auto_tuning);
@@ -332,7 +322,6 @@ aqo_planner(Query *parse,
332322
* Add query text into the ML-knowledge base. Just for further
333323
* analysis. In the case of cached plans we could have NULL query text.
334324
*/
335-
Assert(query_context.query_hash>=0);
336325
if (query_string != NULL)
337326
add_query_text(query_context.query_hash, query_string);
338327

@@ -346,7 +335,6 @@ aqo_planner(Query *parse,
346335
* query execution statistics in any mode.
347336
*/
348337
query_context.collect_stat = true;
349-
Assert(query_context.query_hash>=0);
350338
query_context.fspace_hash = query_context.query_hash;
351339
}
352340

sql/plancache.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ END $$ LANGUAGE 'plpgsql';
3737

3838
-- The function shows 6 executions without an AQO support (nnex) and
3939
-- 4 executions with usage of an AQO knowledge base (nex). Planning time in the
40-
-- case of AQO support (pt) is equal to '-1', because the query plan is exracted
40+
-- case of AQO support (pt) is equal to '-1', because the query plan is extracted
4141
-- from the plan cache.
4242
SELECT * FROM f1();
4343

storage.c

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,44 +94,53 @@ open_aqo_relation(char *heaprelnspname, char *heaprelname,
9494
*
9595
* Use dirty snapshot to see all (include in-progess) data. We want to prevent
9696
* wait in the XactLockTableWait routine.
97+
* If query is found in the knowledge base, fill the query context struct.
9798
*/
9899
bool
99-
find_query(uint64 qhash, Datum *search_values, bool *search_nulls)
100+
find_query(uint64 qhash, QueryContextData *ctx)
100101
{
101-
Relation hrel;
102-
Relation irel;
103-
HeapTuple tuple;
102+
Relation hrel;
103+
Relation irel;
104+
HeapTuple tuple;
104105
TupleTableSlot *slot;
105-
bool shouldFree;
106-
IndexScanDesc scan;
107-
ScanKeyData key;
108-
SnapshotData snap;
109-
bool find_ok = false;
106+
bool shouldFree = true;
107+
IndexScanDesc scan;
108+
ScanKeyData key;
109+
SnapshotData snap;
110+
bool find_ok = false;
111+
Datum values[5];
112+
bool nulls[5] = {false, false, false, false, false};
110113

111114
if (!open_aqo_relation("public", "aqo_queries", "aqo_queries_query_hash_idx",
112115
AccessShareLock, &hrel, &irel))
113116
return false;
114117

115118
InitDirtySnapshot(snap);
116119
scan = index_beginscan(hrel, irel, &snap, 1, 0);
117-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int64GetDatum(qhash));
120+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
118121

119122
index_rescan(scan, &key, 1, NULL, 0);
120123
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
121124
find_ok = index_getnext_slot(scan, ForwardScanDirection, slot);
122125

123-
if (find_ok && search_values != NULL)
126+
if (find_ok)
124127
{
125128
tuple = ExecFetchSlotHeapTuple(slot, true, &shouldFree);
126129
Assert(shouldFree != true);
127-
heap_deform_tuple(tuple, hrel->rd_att, search_values, search_nulls);
130+
heap_deform_tuple(tuple, hrel->rd_att, values, nulls);
131+
132+
/* Fill query context data */
133+
ctx->learn_aqo = DatumGetBool(values[1]);
134+
ctx->use_aqo = DatumGetBool(values[2]);
135+
ctx->fspace_hash = DatumGetInt64(values[3]);
136+
ctx->auto_tuning = DatumGetBool(values[4]);
137+
ctx->collect_stat = query_context.auto_tuning;
128138
}
129139

130140
ExecDropSingleTupleTableSlot(slot);
131141
index_endscan(scan);
132142
index_close(irel, AccessShareLock);
133143
table_close(hrel, AccessShareLock);
134-
135144
return find_ok;
136145
}
137146

@@ -177,7 +186,7 @@ update_query(uint64 qhash, uint64 fhash,
177186
*/
178187
InitDirtySnapshot(snap);
179188
scan = index_beginscan(hrel, irel, &snap, 1, 0);
180-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(qhash));
189+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
181190

182191
index_rescan(scan, &key, 1, NULL, 0);
183192
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
@@ -222,7 +231,8 @@ update_query(uint64 qhash, uint64 fhash,
222231
* Ooops, somebody concurrently updated the tuple. It is possible
223232
* only in the case of changes made by third-party code.
224233
*/
225-
elog(ERROR, "AQO feature space data for signature (%ld, %ld) concurrently"
234+
elog(ERROR, "AQO feature space data for signature ("UINT64_FORMAT \
235+
", "UINT64_FORMAT") concurrently"
226236
" updated by a stranger backend.",
227237
qhash, fhash);
228238
result = false;
@@ -284,7 +294,7 @@ add_query_text(uint64 qhash, const char *query_string)
284294
*/
285295
InitDirtySnapshot(snap);
286296
scan = index_beginscan(hrel, irel, &snap, 1, 0);
287-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(qhash));
297+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
288298

289299
index_rescan(scan, &key, 1, NULL, 0);
290300
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
@@ -391,7 +401,7 @@ load_fss(uint64 fhash, int fss_hash,
391401
return false;
392402

393403
scan = index_beginscan(hrel, irel, SnapshotSelf, 2, 0);
394-
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fhash));
404+
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(fhash));
395405
ScanKeyInit(&key[1], 2, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fss_hash));
396406
index_rescan(scan, key, 2, NULL, 0);
397407

@@ -423,9 +433,10 @@ load_fss(uint64 fhash, int fss_hash,
423433
*relids = deform_oids_vector(values[5]);
424434
}
425435
else
426-
elog(ERROR, "unexpected number of features for hash (%ld, %d):\
427-
expected %d features, obtained %d",
428-
fhash, fss_hash, ncols, DatumGetInt32(values[2]));
436+
elog(ERROR, "unexpected number of features for hash (" \
437+
UINT64_FORMAT", %d):\
438+
expected %d features, obtained %d",
439+
fhash, fss_hash, ncols, DatumGetInt32(values[2]));
429440
}
430441
else
431442
success = false;
@@ -484,7 +495,7 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
484495
InitDirtySnapshot(snap);
485496
scan = index_beginscan(hrel, irel, &snap, 2, 0);
486497

487-
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fhash));
498+
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(fhash));
488499
ScanKeyInit(&key[1], 2, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fsshash));
489500

490501
index_rescan(scan, key, 2, NULL, 0);
@@ -494,7 +505,7 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
494505

495506
if (!find_ok)
496507
{
497-
values[0] = Int32GetDatum(fhash);
508+
values[0] = Int64GetDatum(fhash);
498509
values[1] = Int32GetDatum(fsshash);
499510
values[2] = Int32GetDatum(ncols);
500511

@@ -549,8 +560,8 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
549560
* Ooops, somebody concurrently updated the tuple. It is possible
550561
* only in the case of changes made by third-party code.
551562
*/
552-
elog(ERROR, "AQO data piece (%ld %d) concurrently updated"
553-
" by a stranger backend.",
563+
elog(ERROR, "AQO data piece ("UINT64_FORMAT" %d) concurrently"
564+
" updated by a stranger backend.",
554565
fhash, fsshash);
555566
result = false;
556567
}
@@ -596,7 +607,7 @@ get_aqo_stat(uint64 qhash)
596607
return false;
597608

598609
scan = index_beginscan(hrel, irel, SnapshotSelf, 1, 0);
599-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(qhash));
610+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
600611
index_rescan(scan, &key, 1, NULL, 0);
601612
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
602613

@@ -667,7 +678,7 @@ update_aqo_stat(uint64 qhash, QueryStat *stat)
667678

668679
InitDirtySnapshot(snap);
669680
scan = index_beginscan(hrel, irel, &snap, 1, 0);
670-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int64GetDatum(qhash));
681+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
671682
index_rescan(scan, &key, 1, NULL, 0);
672683
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
673684

@@ -713,8 +724,8 @@ update_aqo_stat(uint64 qhash, QueryStat *stat)
713724
* Ooops, somebody concurrently updated the tuple. It is possible
714725
* only in the case of changes made by third-party code.
715726
*/
716-
elog(ERROR, "AQO statistic data for query signature %ld concurrently"
717-
" updated by a stranger backend.",
727+
elog(ERROR, "AQO statistic data for query signature "UINT64_FORMAT
728+
" concurrently updated by a stranger backend.",
718729
qhash);
719730
}
720731
}
@@ -914,8 +925,8 @@ init_deactivated_queries_storage(void)
914925

915926
/* Create the hashtable proper */
916927
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
917-
hash_ctl.keysize = sizeof(int);
918-
hash_ctl.entrysize = sizeof(int);
928+
hash_ctl.keysize = sizeof(uint64);
929+
hash_ctl.entrysize = sizeof(uint64);
919930
deactivated_queries = hash_create("aqo_deactivated_queries",
920931
128, /* start small and extend */
921932
&hash_ctl,

0 commit comments

Comments
 (0)