Skip to content

Commit 42a425a

Browse files
committed
Bugfix. Fix omissions related to shifting from 32-bit query hash to 64-bit hash
1 parent fbc853f commit 42a425a

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,
@@ -203,11 +203,11 @@ automatical_query_tuning(uint64 query_hash, QueryStat * stat)
203203
query_context.learn_aqo = query_context.use_aqo;
204204
}
205205
if (num_iterations <= auto_tuning_max_iterations || p_use > 0.5)
206-
update_query(query_hash,
206+
update_query(qhash,
207207
query_context.fspace_hash,
208208
query_context.learn_aqo,
209209
query_context.use_aqo,
210210
true);
211211
else
212-
update_query(query_hash, query_context.fspace_hash, false, false, false);
212+
update_query(qhash, query_context.fspace_hash, false, false, false);
213213
}

expected/plancache.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ BEGIN
3737
END $$ LANGUAGE 'plpgsql';
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
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
@@ -175,8 +175,6 @@ aqo_planner(Query *parse,
175175
ParamListInfo boundParams)
176176
{
177177
bool query_is_stored = false;
178-
Datum query_params[5];
179-
bool query_nulls[5] = {false, false, false, false, false};
180178
LOCKTAG tag;
181179
MemoryContext oldCxt;
182180

@@ -226,7 +224,7 @@ aqo_planner(Query *parse,
226224
boundParams);
227225
}
228226

229-
elog(DEBUG1, "AQO will be used for query '%s', class %ld",
227+
elog(DEBUG1, "AQO will be used for query '%s', class "UINT64_FORMAT,
230228
query_string ? query_string : "null string", query_context.query_hash);
231229

232230
oldCxt = MemoryContextSwitchTo(AQOMemoryContext);
@@ -240,8 +238,7 @@ aqo_planner(Query *parse,
240238
goto ignore_query_settings;
241239
}
242240

243-
query_is_stored = find_query(query_context.query_hash, &query_params[0],
244-
&query_nulls[0]);
241+
query_is_stored = find_query(query_context.query_hash, &query_context);
245242

246243
if (!query_is_stored)
247244
{
@@ -295,16 +292,12 @@ aqo_planner(Query *parse,
295292
else /* Query class exists in a ML knowledge base. */
296293
{
297294
query_context.adding_query = false;
298-
query_context.learn_aqo = DatumGetBool(query_params[1]);
299-
query_context.use_aqo = DatumGetBool(query_params[2]);
300-
query_context.fspace_hash = DatumGetInt64(query_params[3]);
301-
query_context.auto_tuning = DatumGetBool(query_params[4]);
302-
query_context.collect_stat = query_context.auto_tuning;
295+
296+
/* Other query_context fields filled in the find_query() routine. */
303297

304298
/*
305299
* Deactivate query if no one reason exists for usage of an AQO machinery.
306300
*/
307-
Assert(query_context.query_hash>=0);
308301
if (!query_context.learn_aqo && !query_context.use_aqo &&
309302
!query_context.auto_tuning && !force_collect_stat)
310303
add_deactivated_query(query_context.query_hash);
@@ -330,7 +323,6 @@ aqo_planner(Query *parse,
330323
* In this mode we want to learn with incoming query (if it is not
331324
* suppressed manually) and collect stats.
332325
*/
333-
Assert(query_context.query_hash>=0);
334326
query_context.collect_stat = true;
335327
query_context.fspace_hash = query_context.query_hash;
336328
break;
@@ -354,15 +346,13 @@ aqo_planner(Query *parse,
354346
* find-add query and query text must be atomic operation to prevent
355347
* concurrent insertions.
356348
*/
357-
Assert(query_context.query_hash>=0);
358-
init_lock_tag(&tag, (uint32) query_context.query_hash, (uint32) 0);//my code
349+
init_lock_tag(&tag, query_context.query_hash, 0);
359350
LockAcquire(&tag, ExclusiveLock, false, false);
360351
/*
361352
* Add query into the AQO knowledge base. To process an error with
362353
* concurrent addition from another backend we will try to restart
363354
* preprocessing routine.
364355
*/
365-
Assert(query_context.query_hash>=0);
366356
update_query(query_context.query_hash, query_context.fspace_hash,
367357
query_context.learn_aqo, query_context.use_aqo,
368358
query_context.auto_tuning);
@@ -371,7 +361,6 @@ aqo_planner(Query *parse,
371361
* Add query text into the ML-knowledge base. Just for further
372362
* analysis. In the case of cached plans we could have NULL query text.
373363
*/
374-
Assert(query_context.query_hash>=0);
375364
if (query_string != NULL)
376365
add_query_text(query_context.query_hash, query_string);
377366

@@ -385,7 +374,6 @@ aqo_planner(Query *parse,
385374
* query execution statistics in any mode.
386375
*/
387376
query_context.collect_stat = true;
388-
Assert(query_context.query_hash>=0);
389377
query_context.fspace_hash = query_context.query_hash;
390378
}
391379

sql/plancache.sql

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

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

storage.c

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

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

114117
InitDirtySnapshot(snap);
115118
scan = index_beginscan(hrel, irel, &snap, 1, 0);
116-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int64GetDatum(qhash));
119+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
117120

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

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

129139
ExecDropSingleTupleTableSlot(slot);
130140
index_endscan(scan);
131141
index_close(irel, AccessShareLock);
132142
table_close(hrel, AccessShareLock);
133-
134143
return find_ok;
135144
}
136145

@@ -176,7 +185,7 @@ update_query(uint64 qhash, uint64 fhash,
176185
*/
177186
InitDirtySnapshot(snap);
178187
scan = index_beginscan(hrel, irel, &snap, 1, 0);
179-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(qhash));
188+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
180189

181190
index_rescan(scan, &key, 1, NULL, 0);
182191
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
@@ -221,7 +230,8 @@ update_query(uint64 qhash, uint64 fhash,
221230
* Ooops, somebody concurrently updated the tuple. It is possible
222231
* only in the case of changes made by third-party code.
223232
*/
224-
elog(ERROR, "AQO feature space data for signature (%ld, %ld) concurrently"
233+
elog(ERROR, "AQO feature space data for signature ("UINT64_FORMAT \
234+
", "UINT64_FORMAT") concurrently"
225235
" updated by a stranger backend.",
226236
qhash, fhash);
227237
result = false;
@@ -283,7 +293,7 @@ add_query_text(uint64 qhash, const char *query_string)
283293
*/
284294
InitDirtySnapshot(snap);
285295
scan = index_beginscan(hrel, irel, &snap, 1, 0);
286-
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(qhash));
296+
ScanKeyInit(&key, 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(qhash));
287297

288298
index_rescan(scan, &key, 1, NULL, 0);
289299
slot = MakeSingleTupleTableSlot(hrel->rd_att, &TTSOpsBufferHeapTuple);
@@ -390,7 +400,7 @@ load_fss(uint64 fhash, int fss_hash,
390400
return false;
391401

392402
scan = index_beginscan(hrel, irel, SnapshotSelf, 2, 0);
393-
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fhash));
403+
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(fhash));
394404
ScanKeyInit(&key[1], 2, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fss_hash));
395405
index_rescan(scan, key, 2, NULL, 0);
396406

@@ -422,9 +432,10 @@ load_fss(uint64 fhash, int fss_hash,
422432
*relids = deform_oids_vector(values[5]);
423433
}
424434
else
425-
elog(ERROR, "unexpected number of features for hash (%ld, %d):\
426-
expected %d features, obtained %d",
427-
fhash, fss_hash, ncols, DatumGetInt32(values[2]));
435+
elog(ERROR, "unexpected number of features for hash (" \
436+
UINT64_FORMAT", %d):\
437+
expected %d features, obtained %d",
438+
fhash, fss_hash, ncols, DatumGetInt32(values[2]));
428439
}
429440
else
430441
success = false;
@@ -483,7 +494,7 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
483494
InitDirtySnapshot(snap);
484495
scan = index_beginscan(hrel, irel, &snap, 2, 0);
485496

486-
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fhash));
497+
ScanKeyInit(&key[0], 1, BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(fhash));
487498
ScanKeyInit(&key[1], 2, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(fsshash));
488499

489500
index_rescan(scan, key, 2, NULL, 0);
@@ -493,7 +504,7 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
493504

494505
if (!find_ok)
495506
{
496-
values[0] = Int32GetDatum(fhash);
507+
values[0] = Int64GetDatum(fhash);
497508
values[1] = Int32GetDatum(fsshash);
498509
values[2] = Int32GetDatum(ncols);
499510

@@ -548,8 +559,8 @@ update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
548559
* Ooops, somebody concurrently updated the tuple. It is possible
549560
* only in the case of changes made by third-party code.
550561
*/
551-
elog(ERROR, "AQO data piece (%ld %d) concurrently updated"
552-
" by a stranger backend.",
562+
elog(ERROR, "AQO data piece ("UINT64_FORMAT" %d) concurrently"
563+
" updated by a stranger backend.",
553564
fhash, fsshash);
554565
result = false;
555566
}
@@ -595,7 +606,7 @@ get_aqo_stat(uint64 qhash)
595606
return false;
596607

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

@@ -666,7 +677,7 @@ update_aqo_stat(uint64 qhash, QueryStat *stat)
666677

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

@@ -712,8 +723,8 @@ update_aqo_stat(uint64 qhash, QueryStat *stat)
712723
* Ooops, somebody concurrently updated the tuple. It is possible
713724
* only in the case of changes made by third-party code.
714725
*/
715-
elog(ERROR, "AQO statistic data for query signature %ld concurrently"
716-
" updated by a stranger backend.",
726+
elog(ERROR, "AQO statistic data for query signature "UINT64_FORMAT
727+
" concurrently updated by a stranger backend.",
717728
qhash);
718729
}
719730
}
@@ -913,8 +924,8 @@ init_deactivated_queries_storage(void)
913924

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

0 commit comments

Comments
 (0)