diff --git a/hypopg.c b/hypopg.c index 8e4e6d4..7f65481 100644 --- a/hypopg.c +++ b/hypopg.c @@ -538,12 +538,15 @@ hypo_get_relation_info_hook(PlannerInfo *root, * is a hypothetical partition, root table oid is equal to * relationObjectId, so nothing to do */ - AppendRelInfo *appinfo; RelOptInfo *parentrel = rel; do { +#if PG_VERSION_NUM >= 110000 appinfo = root->append_rel_array[parentrel->relid]; +#else + appinfo = find_childrel_appendrelinfo(root, parentrel); +#endif /* pg10 only */ parentrel = find_base_rel(root, appinfo->parent_relid); } while (parentrel->reloptkind == RELOPT_OTHER_MEMBER_REL); parentId = appinfo->parent_reloid; @@ -556,7 +559,7 @@ hypo_get_relation_info_hook(PlannerInfo *root, if (entry->relid == parentId #if PG_VERSION_NUM >= 100000 - && !rel->part_scheme + && rel->reloptkind != RELOPT_OTHER_MEMBER_REL #endif ) { diff --git a/hypopg_analyze.c b/hypopg_analyze.c index 9518eaa..88874b2 100644 --- a/hypopg_analyze.c +++ b/hypopg_analyze.c @@ -42,8 +42,10 @@ #endif #include "utils/guc.h" #include "utils/lsyscache.h" -#if PG_VERSION_NUM >= 100000 +#if PG_VERSION_NUM >= 110000 #include "utils/partcache.h" +#endif +#if PG_VERSION_NUM >= 100000 #include "utils/ruleutils.h" #endif #include "utils/selfuncs.h" @@ -220,6 +222,7 @@ static void hypo_do_analyze_partition(Relation onerel, Relation pgstats, Assert(hypoStatsHash); +#if PG_VERSION_NUM >= 110000 /* * We can't use the same heuristics for hash partitions selectivity * estimation, because its constraint is using satisfies_hash_partition(), @@ -234,6 +237,7 @@ static void hypo_do_analyze_partition(Relation onerel, Relation pgstats, " skipping", part->tablename); return; } +#endif /* * Set up a working context so that we can easily free whatever junk gets diff --git a/hypopg_import.c b/hypopg_import.c index 34be8d4..df64d90 100644 --- a/hypopg_import.c +++ b/hypopg_import.c @@ -37,6 +37,9 @@ #include "utils/ruleutils.h" #endif #include "optimizer/clauses.h" +#if PG_VERSION_NUM >= 100000 +#include "catalog/partition.h" +#endif #if PG_VERSION_NUM >= 110000 #include "catalog/partition.h" #include "optimizer/cost.h" @@ -61,6 +64,262 @@ #include "include/hypopg_import.h" +/* pg10 only imports */ +#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 110000 +static int32 partition_rbound_datum_cmp(PartitionKey key, + Datum *rb_datums, PartitionRangeDatumKind *rb_kind, + Datum *tuple_datums); + +/* + * Copied from src/backend/catalog/partition.c + * + * make_one_range_bound + * + * Return a PartitionRangeBound given a list of PartitionRangeDatum elements + * and a flag telling whether the bound is lower or not. Made into a function + * because there are multiple sites that want to use this facility. + */ +PartitionRangeBound * +make_one_range_bound(PartitionKey key, int index, List *datums, bool lower) +{ + PartitionRangeBound *bound; + ListCell *lc; + int i; + + bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound)); + bound->index = index; + bound->datums = (Datum *) palloc0(key->partnatts * sizeof(Datum)); + bound->kind = (PartitionRangeDatumKind *) palloc0(key->partnatts * + sizeof(PartitionRangeDatumKind)); + bound->lower = lower; + + i = 0; + foreach(lc, datums) + { + PartitionRangeDatum *datum = castNode(PartitionRangeDatum, lfirst(lc)); + + /* What's contained in this range datum? */ + bound->kind[i] = datum->kind; + + if (datum->kind == PARTITION_RANGE_DATUM_VALUE) + { + Const *val = castNode(Const, datum->value); + + if (val->constisnull) + elog(ERROR, "invalid range bound datum"); + bound->datums[i] = val->constvalue; + } + + i++; + } + + return bound; +} + +/* + * Copied from src/backend/catalog/partition.c + * + * Binary search on a collection of partition bounds. Returns greatest + * bound in array boundinfo->datums which is less than or equal to *probe. + * If all bounds in the array are greater than *probe, -1 is returned. + * + * *probe could either be a partition bound or a Datum array representing + * the partition key of a tuple being routed; probe_is_bound tells which. + * We pass that down to the comparison function so that it can interpret the + * contents of *probe accordingly. + * + * *is_equal is set to whether the bound at the returned index is equal with + * *probe. + */ +int +partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo, + void *probe, bool probe_is_bound, bool *is_equal) +{ + int lo, + hi, + mid; + + lo = -1; + hi = boundinfo->ndatums - 1; + while (lo < hi) + { + int32 cmpval; + + mid = (lo + hi + 1) / 2; + cmpval = partition_bound_cmp(key, boundinfo, mid, probe, + probe_is_bound); + if (cmpval <= 0) + { + lo = mid; + *is_equal = (cmpval == 0); + + if (*is_equal) + break; + } + else + hi = mid - 1; + } + + return lo; +} + +/* + * Copied from src/backend/catalog/partition.c + * + * partition_bound_cmp + * + * Return whether the bound at offset in boundinfo is <, =, or > the argument + * specified in *probe. + */ +int32 +partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, + int offset, void *probe, bool probe_is_bound) +{ + Datum *bound_datums = boundinfo->datums[offset]; + int32 cmpval = -1; + + switch (key->strategy) + { + case PARTITION_STRATEGY_LIST: + cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0], + key->partcollation[0], + bound_datums[0], + *(Datum *) probe)); + break; + + case PARTITION_STRATEGY_RANGE: + { + PartitionRangeDatumKind *kind = boundinfo->kind[offset]; + + if (probe_is_bound) + { + /* + * We need to pass whether the existing bound is a lower + * bound, so that two equal-valued lower and upper bounds + * are not regarded equal. + */ + bool lower = boundinfo->indexes[offset] < 0; + + cmpval = partition_rbound_cmp(key, + bound_datums, kind, lower, + (PartitionRangeBound *) probe); + } + else + cmpval = partition_rbound_datum_cmp(key, + bound_datums, kind, + (Datum *) probe); + break; + } + + default: + elog(ERROR, "unexpected partition strategy: %d", + (int) key->strategy); + } + + return cmpval; +} + +/* + * Imported from src/backend/catalog/partition.c, not exported in pg10 + * + * partition_rbound_cmp + * + * Return for two range bounds whether the 1st one (specified in datum1, + * kind1, and lower1) is <, =, or > the bound specified in *b2. + * + * Note that if the values of the two range bounds compare equal, then we take + * into account whether they are upper or lower bounds, and an upper bound is + * considered to be smaller than a lower bound. This is important to the way + * that RelationBuildPartitionDesc() builds the PartitionBoundInfoData + * structure, which only stores the upper bound of a common boundary between + * two contiguous partitions. + */ +int32 +partition_rbound_cmp(PartitionKey key, + Datum *datums1, PartitionRangeDatumKind *kind1, + bool lower1, PartitionRangeBound *b2) +{ + int32 cmpval = 0; /* placate compiler */ + int i; + Datum *datums2 = b2->datums; + PartitionRangeDatumKind *kind2 = b2->kind; + bool lower2 = b2->lower; + + for (i = 0; i < key->partnatts; i++) + { + /* + * First, handle cases where the column is unbounded, which should not + * invoke the comparison procedure, and should not consider any later + * columns. Note that the PartitionRangeDatumKind enum elements + * compare the same way as the values they represent. + */ + if (kind1[i] < kind2[i]) + return -1; + else if (kind1[i] > kind2[i]) + return 1; + else if (kind1[i] != PARTITION_RANGE_DATUM_VALUE) + + /* + * The column bounds are both MINVALUE or both MAXVALUE. No later + * columns should be considered, but we still need to compare + * whether they are upper or lower bounds. + */ + break; + + cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[i], + key->partcollation[i], + datums1[i], + datums2[i])); + if (cmpval != 0) + break; + } + + /* + * If the comparison is anything other than equal, we're done. If they + * compare equal though, we still have to consider whether the boundaries + * are inclusive or exclusive. Exclusive one is considered smaller of the + * two. + */ + if (cmpval == 0 && lower1 != lower2) + cmpval = lower1 ? 1 : -1; + + return cmpval; +} + +/* + * Imported from src/backend/catalog/partition.c, not exported in pg10 + * + * partition_rbound_datum_cmp + * + * Return whether range bound (specified in rb_datums, rb_kind, and rb_lower) + * is <, =, or > partition key of tuple (tuple_datums) + */ +static int32 +partition_rbound_datum_cmp(PartitionKey key, + Datum *rb_datums, PartitionRangeDatumKind *rb_kind, + Datum *tuple_datums) +{ + int i; + int32 cmpval = -1; + + for (i = 0; i < key->partnatts; i++) + { + if (rb_kind[i] == PARTITION_RANGE_DATUM_MINVALUE) + return -1; + else if (rb_kind[i] == PARTITION_RANGE_DATUM_MAXVALUE) + return 1; + + cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[i], + key->partcollation[i], + rb_datums[i], + tuple_datums[i])); + if (cmpval != 0) + break; + } + + return cmpval; +} +#endif /* pg10 only imports */ /* Copied from src/backend/optimizer/util/plancat.c, not exported. * @@ -730,6 +989,7 @@ looks_like_function(Node *node) return false; } +#if PG_VERSION_NUM >= 110000 /* * Copied from src/backend/catalog/partition.c, not exported * @@ -746,6 +1006,7 @@ qsort_partition_hbound_cmp(const void *a, const void *b) return partition_hbound_cmp(h1->modulus, h1->remainder, h2->modulus, h2->remainder); } +#endif /* * Copied from src/backend/catalog/partition.c, not exported @@ -778,9 +1039,13 @@ qsort_partition_rbound_cmp(const void *a, const void *b, void *arg) PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b); PartitionKey key = (PartitionKey) arg; +#if PG_VERSION_NUM < 110000 + return partition_rbound_cmp(key, b1->datums, b1->kind, b1->lower, b2); +#else return partition_rbound_cmp(key->partnatts, key->partsupfunc, key->partcollation, b1->datums, b1->kind, b1->lower, b2); +#endif } /* ---------- diff --git a/hypopg_table.c b/hypopg_table.c index 634b3ff..787f112 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -28,6 +28,9 @@ #include "catalog/namespace.h" #include "catalog/partition.h" #include "catalog/pg_class.h" +#if PG_VERSION_NUM < 110000 +#include "catalog/pg_inherits_fn.h" +#endif #include "catalog/pg_inherits.h" #include "catalog/pg_opclass.h" #include "catalog/pg_type.h" @@ -50,10 +53,12 @@ #include "utils/datum.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" +#if PG_VERSION_NUM >= 110000 #include "utils/partcache.h" +#include "partitioning/partbounds.h" +#endif #include "utils/ruleutils.h" #include "utils/syscache.h" -#include "partitioning/partbounds.h" #endif #include "include/hypopg.h" @@ -93,7 +98,9 @@ static PartitionScheme hypo_find_partition_scheme(PlannerInfo *root, static void hypo_generate_partition_key_exprs(hypoTable *entry, RelOptInfo *rel); static PartitionBoundSpec *hypo_get_boundspec(Oid tableid); +#if PG_VERSION_NUM >= 110000 static Oid hypo_get_default_partition_oid(hypoTable *parent); +#endif static char *hypo_get_partbounddef(hypoTable *entry); static char *hypo_get_partkeydef(hypoTable *entry); static hypoTable *hypo_newTable(Oid parentid); @@ -439,6 +446,7 @@ hypo_generate_partitiondesc(hypoTable *parent) boundspec = (Node *) hypo_get_boundspec(inhrelid); +#if PG_VERSION_NUM >= 110000 /* * Sanity check: If the PartitionBoundSpec says this is the default * partition, its OID should correspond to whatever's stored in @@ -453,6 +461,7 @@ hypo_generate_partitiondesc(hypoTable *parent) elog(ERROR, "expected partdefid %u, but got %u", inhrelid, partdefid); } +#endif boundspecs = lappend(boundspecs, boundspec); partoids = lappend_oid(partoids, inhrelid); @@ -468,6 +477,7 @@ hypo_generate_partitiondesc(hypoTable *parent) oids[i++] = lfirst_oid(cell); /* Convert from node to the internal representation */ +#if PG_VERSION_NUM >= 110000 if (key->strategy == PARTITION_STRATEGY_HASH) { ndatums = nparts; @@ -496,7 +506,9 @@ hypo_generate_partitiondesc(hypoTable *parent) qsort(hbounds, nparts, sizeof(PartitionHashBound *), qsort_partition_hbound_cmp); } - else if (key->strategy == PARTITION_STRATEGY_LIST) + else +#endif + if (key->strategy == PARTITION_STRATEGY_LIST) { List *non_null_values = NIL; @@ -514,6 +526,7 @@ hypo_generate_partitiondesc(hypoTable *parent) if (spec->strategy != PARTITION_STRATEGY_LIST) elog(ERROR, "invalid strategy in partition bound spec"); +#if PG_VERSION_NUM >= 110000 /* * Note the index of the partition bound spec for the default * partition. There's no datum to add to the list of non-null @@ -525,6 +538,7 @@ hypo_generate_partitiondesc(hypoTable *parent) i++; continue; } +#endif foreach(c, spec->listdatums) { @@ -605,6 +619,7 @@ hypo_generate_partitiondesc(hypoTable *parent) if (spec->strategy != PARTITION_STRATEGY_RANGE) elog(ERROR, "invalid strategy in partition bound spec"); +#if PG_VERSION_NUM >= 110000 /* * Note the index of the partition bound spec for the default * partition. There's no datum to add to the allbounds array @@ -615,11 +630,19 @@ hypo_generate_partitiondesc(hypoTable *parent) default_index = i++; continue; } +#endif +#if PG_VERSION_NUM < 110000 + lower = make_one_range_bound(key, i, spec->lowerdatums, + true); + upper = make_one_range_bound(key, i, spec->upperdatums, + false); +#else lower = make_one_partition_rbound(key, i, spec->lowerdatums, true); upper = make_one_partition_rbound(key, i, spec->upperdatums, false); +#endif all_bounds[ndatums++] = lower; all_bounds[ndatums++] = upper; i++; @@ -719,6 +742,7 @@ hypo_generate_partitiondesc(hypoTable *parent) switch (key->strategy) { +#if PG_VERSION_NUM >= 110000 case PARTITION_STRATEGY_HASH: { /* Modulus are stored in ascending order */ @@ -754,6 +778,7 @@ hypo_generate_partitiondesc(hypoTable *parent) pfree(hbounds); break; } +#endif case PARTITION_STRATEGY_LIST: { @@ -978,9 +1003,13 @@ hypo_generate_partkey(CreateStmt *stmt, Oid parentid, hypoTable *entry) MemoryContextSwitchTo(oldcontext); +#if PG_VERSION_NUM >= 110000 /* determine support function number to search for */ procnum = (key->strategy == PARTITION_STRATEGY_HASH) ? HASHEXTENDED_PROC : BTORDER_PROC; +#else + procnum = BTORDER_PROC; +#endif /* Copy partattrs and fill other per-attribute info */ memcpy(key->partattrs, partattrs, key->partnatts * sizeof(int16)); @@ -1012,8 +1041,12 @@ hypo_generate_partkey(CreateStmt *stmt, Oid parentid, hypoTable *entry) (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("operator class \"%s\" of access method %s is missing support function %d for type %s", NameStr(opclassform->opcname), +#if PG_VERSION_NUM >= 110000 (key->strategy == PARTITION_STRATEGY_HASH) ? "hash" : "btree", +#else + "btree", +#endif procnum, format_type_be(opclassform->opcintype)))); @@ -1259,6 +1292,7 @@ hypo_get_boundspec(Oid tableid) return NULL; } +#if PG_VERSION_NUM >= 110000 /* * Return the Oid of the default partition if any, otherwise return InvalidOid */ @@ -1277,6 +1311,7 @@ hypo_get_default_partition_oid(hypoTable *parent) return InvalidOid; } +#endif /* * Deparse the stored PartitionBoundSpec data @@ -1299,14 +1334,17 @@ hypo_get_partbounddef(hypoTable *entry) buf = &_buf; _context.buf = &_buf; +#if PG_VERSION_NUM >= 110000 if (spec->is_default) { appendStringInfoString(buf, "DEFAULT"); return buf->data; } +#endif switch (spec->strategy) { +#if PG_VERSION_NUM >= 110000 case PARTITION_STRATEGY_HASH: Assert(spec->modulus > 0 && spec->remainder >= 0); Assert(spec->modulus > spec->remainder); @@ -1315,6 +1353,7 @@ hypo_get_partbounddef(hypoTable *entry) appendStringInfo(buf, " WITH (modulus %d, remainder %d)", spec->modulus, spec->remainder); break; +#endif case PARTITION_STRATEGY_LIST: Assert(spec->listdatums != NIL); @@ -1383,9 +1422,11 @@ hypo_get_partkeydef(hypoTable *entry) appendStringInfo(&buf, "PARTITION BY "); switch(partkey->strategy) { +#if PG_VERSION_NUM >= 110000 case PARTITION_STRATEGY_HASH: appendStringInfo(&buf, "HASH"); break; +#endif case PARTITION_STRATEGY_LIST: appendStringInfo(&buf, "LIST"); break; @@ -1414,7 +1455,11 @@ hypo_get_partkeydef(hypoTable *entry) char *attname; int32 keycoltypmod; +#if PG_VERSION_NUM < 110000 + attname = get_attname(relid, attnum); +#else attname = get_attname(relid, attnum, false); +#endif appendStringInfoString(&buf, quote_identifier(attname)); get_atttypetypmodcoll(relid, attnum, &keycoltype, &keycoltypmod, @@ -1839,6 +1884,7 @@ hypo_transformPartitionBound(ParseState *pstate, hypoTable *parent, /* Avoid scribbling on input */ result_spec = copyObject(spec); +#if PG_VERSION_NUM >= 110000 if (spec->is_default) { if (strategy == PARTITION_STRATEGY_HASH) @@ -1876,7 +1922,9 @@ hypo_transformPartitionBound(ParseState *pstate, hypoTable *parent, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("remainder for hash partition must be less than modulus"))); } - else if (strategy == PARTITION_STRATEGY_LIST) + else +#endif + if (strategy == PARTITION_STRATEGY_LIST) { ListCell *cell; char *colname; @@ -1891,8 +1939,13 @@ hypo_transformPartitionBound(ParseState *pstate, hypoTable *parent, /* Get the only column's name in case we need to output an error */ if (key->partattrs[0] != 0) +#if PG_VERSION_NUM < 110000 + colname = get_attname(parent->rootid, + key->partattrs[0]); +#else colname = get_attname(parent->rootid, key->partattrs[0], false); +#endif else colname = deparse_expression((Node *) linitial(partexprs), deparse_context_for(parent->tablename, @@ -1976,8 +2029,13 @@ hypo_transformPartitionBound(ParseState *pstate, hypoTable *parent, /* Get the column's name in case we need to output an error */ if (key->partattrs[i] != 0) +#if PG_VERSION_NUM < 110000 + colname = get_attname(parent->rootid, + key->partattrs[i]); +#else colname = get_attname(parent->rootid, key->partattrs[i], false); +#endif else { colname = deparse_expression((Node *) list_nth(partexprs, j), @@ -2075,7 +2133,10 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, &&HYPO_RTI_IS_TAGGED(rel->relid,root)) { Oid partoid; - hypoTable *part, *cur_part; + hypoTable *part; +#if PG_VERSION_NUM >= 110000 + hypoTable *cur_part; +#endif RangeTblEntry *rte = planner_rt_fetch(rel->relid, root); Selectivity selectivity; double pages; @@ -2096,6 +2157,7 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, return; } +#if PG_VERSION_NUM >= 110000 /* * Selectivity for hash partitions cannot be done using the standard * clauselist_selectivity(), because the underlying constraint is using @@ -2119,7 +2181,9 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, } elog(DEBUG1, "hypopg: total modulus for partition %s: %d", part->tablename, total_modulus); - +#else + Assert(total_modulus == 1); +#endif if (part->set_tuples) { @@ -2154,6 +2218,7 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, } } +#if PG_VERSION_NUM >= 110000 /* * This is done in query_planner just before add_base_rels_to_query() is * called, so before get_relation_info_hook is called and setup @@ -2168,6 +2233,7 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, root->append_rel_array = NULL; } setup_append_rel_array(root); +#endif } @@ -2299,6 +2365,7 @@ hypo_get_qual_from_partbound(hypoTable *parent, PartitionBoundSpec *spec) switch (key->strategy) { +#if PG_VERSION_NUM >= 110000 case PARTITION_STRATEGY_HASH: Assert(spec->strategy == PARTITION_STRATEGY_HASH); /* @@ -2307,6 +2374,7 @@ hypo_get_qual_from_partbound(hypoTable *parent, PartitionBoundSpec *spec) * selectivity estimation */ break; +#endif case PARTITION_STRATEGY_LIST: Assert(spec->strategy == PARTITION_STRATEGY_LIST); @@ -2362,6 +2430,7 @@ hypo_get_qual_for_list(hypoTable *parent, PartitionBoundSpec *spec) else keyCol = (Expr *) copyObject(linitial(key->partexprs)); +#if PG_VERSION_NUM >= 110000 /* * For default list partition, collect datums for all the partitions. The * default partition constraint should check that the partition key is @@ -2412,6 +2481,7 @@ hypo_get_qual_for_list(hypoTable *parent, PartitionBoundSpec *spec) } } else +#endif { /* * Create list of Consts for the allowed values, excluding any nulls. @@ -2483,6 +2553,7 @@ hypo_get_qual_for_list(hypoTable *parent, PartitionBoundSpec *spec) result = list_make1(nulltest); } +#if PG_VERSION_NUM >= 110000 /* * Note that, in general, applying NOT to a constraint expression doesn't * necessarily invert the set of rows it accepts, because NOT (NULL) is @@ -2494,6 +2565,7 @@ hypo_get_qual_for_list(hypoTable *parent, PartitionBoundSpec *spec) result = list_make1(make_ands_explicit(result)); result = list_make1(makeBoolExpr(NOT_EXPR, result, -1)); } +#endif return result; } @@ -2531,6 +2603,7 @@ hypo_get_qual_for_range(hypoTable *parent, PartitionBoundSpec *spec, bool for_de bool need_next_lower_arm, need_next_upper_arm; +#if PG_VERSION_NUM >= 110000 if (spec->is_default) { List *or_expr_args = NIL; @@ -2601,6 +2674,7 @@ hypo_get_qual_for_range(hypoTable *parent, PartitionBoundSpec *spec, bool for_de return result; } +#endif lower_or_start_datum = list_head(spec->lowerdatums); upper_or_start_datum = list_head(spec->upperdatums); @@ -2865,6 +2939,7 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, int with = -1; bool overlap = false; +#if PG_VERSION_NUM >= 110000 if (spec->is_default) { /* @@ -2883,9 +2958,11 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, relname, get_rel_name(partdesc->oids[boundinfo->default_index])), parser_errposition(pstate, spec->location))); } +#endif switch (key->strategy) { +#if PG_VERSION_NUM >= 110000 case PARTITION_STRATEGY_HASH: { Assert(spec->strategy == PARTITION_STRATEGY_HASH); @@ -2967,6 +3044,7 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, break; } +#endif case PARTITION_STRATEGY_LIST: { @@ -2979,8 +3057,11 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, Assert(boundinfo && boundinfo->strategy == PARTITION_STRATEGY_LIST && (boundinfo->ndatums > 0 || - partition_bound_accepts_nulls(boundinfo) || - partition_bound_has_default(boundinfo))); + partition_bound_accepts_nulls(boundinfo) +#if PG_VERSION_NUM >= 110000 + || partition_bound_has_default(boundinfo) +#endif + )); foreach(cell, spec->listdatums) { @@ -2991,11 +3072,17 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, int offset; bool equal; +#if PG_VERSION_NUM < 110000 + offset = partition_bound_bsearch(key, boundinfo, + &val->constvalue, + true, &equal); +#else offset = partition_list_bsearch(&key->partsupfunc[0], key->partcollation, boundinfo, val->constvalue, &equal); +#endif if (offset >= 0 && equal) { overlap = true; @@ -3021,16 +3108,26 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, *upper; Assert(spec->strategy == PARTITION_STRATEGY_RANGE); +#if PG_VERSION_NUM < 110000 + lower = make_one_range_bound(key, -1, spec->lowerdatums, true); + upper = make_one_range_bound(key, -1, spec->upperdatums, false); +#else lower = make_one_partition_rbound(key, -1, spec->lowerdatums, true); upper = make_one_partition_rbound(key, -1, spec->upperdatums, false); +#endif /* * First check if the resulting range would be empty with * specified lower and upper bounds */ +#if PG_VERSION_NUM < 110000 + if (partition_rbound_cmp(key, lower->datums, + lower->kind, true, upper) >= 0) +#else if (partition_rbound_cmp(key->partnatts, key->partsupfunc, key->partcollation, lower->datums, lower->kind, true, upper) >= 0) +#endif { ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -3049,8 +3146,13 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, Assert(boundinfo && boundinfo->strategy == PARTITION_STRATEGY_RANGE && +#if PG_VERSION_NUM < 110000 + boundinfo->ndatums > 0 +#else (boundinfo->ndatums > 0 || - partition_bound_has_default(boundinfo))); + partition_bound_has_default(boundinfo)) +#endif + ); /* * Test whether the new lower bound (which is treated @@ -3067,11 +3169,16 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, * since the index array is initialised with an extra -1 * at the end. */ +#if PG_VERSION_NUM < 110000 + offset = partition_bound_bsearch(key, boundinfo, lower, + true, &equal); +#else offset = partition_range_bsearch(key->partnatts, key->partsupfunc, key->partcollation, boundinfo, lower, &equal); +#endif if (boundinfo->indexes[offset + 1] < 0) { @@ -3084,6 +3191,11 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, if (offset + 1 < boundinfo->ndatums) { int32 cmpval; +#if PG_VERSION_NUM < 110000 + cmpval = partition_bound_cmp(key, boundinfo, + offset + 1, upper, + true); +#else Datum *datums; PartitionRangeDatumKind *kind; bool is_lower; @@ -3097,6 +3209,7 @@ hypo_check_new_partition_bound(char *relname, hypoTable *parent, key->partcollation, datums, kind, is_lower, upper); +#endif if (cmpval < 0) { /* diff --git a/include/hypopg_import.h b/include/hypopg_import.h index 20ca60e..ca91562 100644 --- a/include/hypopg_import.h +++ b/include/hypopg_import.h @@ -16,7 +16,7 @@ #include "nodes/pg_list.h" #include "optimizer/planner.h" #include "optimizer/pathnode.h" -#if PG_VERSION_NUM >= 100000 +#if PG_VERSION_NUM >= 110000 #include "partitioning/partbounds.h" #endif #include "utils/rel.h" @@ -41,6 +41,8 @@ extern char *get_am_name(Oid amOid); extern void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf); #if PG_VERSION_NUM >= 100000 + +/* pg10 only imports */ #if PG_VERSION_NUM < 110000 /* * Imported from src/backend/catalog/partition.c, not exported @@ -83,7 +85,19 @@ typedef struct PartitionRangeBound PartitionRangeDatumKind *kind; /* the kind of each datum */ bool lower; /* this is the lower (vs upper) bound */ } PartitionRangeBound; -#endif + +PartitionRangeBound *make_one_range_bound(PartitionKey key, int index, + List *datums, bool lower); +int partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo, + void *probe, bool probe_is_bound, bool *is_equal); +int32 partition_bound_cmp(PartitionKey key, + PartitionBoundInfo boundinfo, + int offset, void *probe, bool probe_is_bound); + +int32 partition_rbound_cmp(PartitionKey key, + Datum *datums1, PartitionRangeDatumKind *kind1, + bool lower1, PartitionRangeBound *b2); +#endif /* pg10 only imports */ /* Context info needed for invoking a recursive querytree display routine */ typedef struct