mirror of https://github.com/citusdata/citus.git
Compare commits
11 Commits
Author | SHA1 | Date |
---|---|---|
|
8e5b9a06ad | |
|
aed6776d1f | |
|
a9dced4291 | |
|
34744501ce | |
|
86b57f426b | |
|
9801f743ce | |
|
8e3246a2f3 | |
|
1feb7102b8 | |
|
9cde3d4122 | |
|
7da6d68675 | |
|
a913b90ff3 |
|
@ -451,7 +451,7 @@ workflows:
|
||||||
- build:
|
- build:
|
||||||
name: build-14
|
name: build-14
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
|
|
||||||
- check-style
|
- check-style
|
||||||
- check-sql-snapshots
|
- check-sql-snapshots
|
||||||
|
@ -607,74 +607,74 @@ workflows:
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-multi'
|
name: 'test-14_check-multi'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-multi
|
make: check-multi
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-multi-1'
|
name: 'test-14_check-multi-1'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-multi-1
|
make: check-multi-1
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-mx'
|
name: 'test-14_check-mx'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-multi-mx
|
make: check-multi-mx
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-vanilla'
|
name: 'test-14_check-vanilla'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-vanilla
|
make: check-vanilla
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-isolation'
|
name: 'test-14_check-isolation'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-isolation
|
make: check-isolation
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-worker'
|
name: 'test-14_check-worker'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-worker
|
make: check-worker
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-operations'
|
name: 'test-14_check-operations'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-operations
|
make: check-operations
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-follower-cluster'
|
name: 'test-14_check-follower-cluster'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-follower-cluster
|
make: check-follower-cluster
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-columnar'
|
name: 'test-14_check-columnar'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-columnar
|
make: check-columnar
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-columnar-isolation'
|
name: 'test-14_check-columnar-isolation'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-columnar-isolation
|
make: check-columnar-isolation
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- tap-test-citus:
|
- tap-test-citus:
|
||||||
name: 'test_14_tap-recovery'
|
name: 'test_14_tap-recovery'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
suite: recovery
|
suite: recovery
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-failure'
|
name: 'test-14_check-failure'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
image: citus/failtester
|
image: citus/failtester
|
||||||
image_tag: '14beta3'
|
image_tag: '14rc1'
|
||||||
make: check-failure
|
make: check-failure
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
|
|
||||||
|
@ -689,14 +689,14 @@ workflows:
|
||||||
name: 'test-12-14_check-pg-upgrade'
|
name: 'test-12-14_check-pg-upgrade'
|
||||||
old_pg_major: 12
|
old_pg_major: 12
|
||||||
new_pg_major: 14
|
new_pg_major: 14
|
||||||
image_tag: '12-13-14'
|
image_tag: '12.8-13.4-14rc1'
|
||||||
requires: [build-12,build-14]
|
requires: [build-12,build-14]
|
||||||
|
|
||||||
- test-pg-upgrade:
|
- test-pg-upgrade:
|
||||||
name: 'test-13-14_check-pg-upgrade'
|
name: 'test-13-14_check-pg-upgrade'
|
||||||
old_pg_major: 13
|
old_pg_major: 13
|
||||||
new_pg_major: 14
|
new_pg_major: 14
|
||||||
image_tag: '12-13-14'
|
image_tag: '12.8-13.4-14rc1'
|
||||||
requires: [build-13,build-14]
|
requires: [build-13,build-14]
|
||||||
|
|
||||||
- test-citus-upgrade:
|
- test-citus-upgrade:
|
||||||
|
|
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,3 +1,22 @@
|
||||||
|
### citus v10.2.1 (September 24, 2021) ###
|
||||||
|
|
||||||
|
* Adds missing version-mismatch checks for columnar tables
|
||||||
|
|
||||||
|
* Adds missing version-mismatch checks for internal functions
|
||||||
|
|
||||||
|
* Fixes a bug that could cause partition shards being not co-located with
|
||||||
|
parent shards
|
||||||
|
|
||||||
|
* Fixes a bug that prevents pushing down boolean expressions when using
|
||||||
|
columnar custom scan
|
||||||
|
|
||||||
|
* Fixes a clog lookup failure that could occur when writing to a columnar table
|
||||||
|
|
||||||
|
* Fixes an issue that could cause unexpected errors when there is an
|
||||||
|
in-progress write to a columnar table
|
||||||
|
|
||||||
|
* Revokes read access to `columnar.chunk` from unprivileged user
|
||||||
|
|
||||||
### citus v10.2.0 (September 14, 2021) ###
|
### citus v10.2.0 (September 14, 2021) ###
|
||||||
|
|
||||||
* Adds PostgreSQL 14 support
|
* Adds PostgreSQL 14 support
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for Citus 10.2devel.
|
# Generated by GNU Autoconf 2.69 for Citus 10.2.1.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||||
|
@ -579,8 +579,8 @@ MAKEFLAGS=
|
||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='Citus'
|
PACKAGE_NAME='Citus'
|
||||||
PACKAGE_TARNAME='citus'
|
PACKAGE_TARNAME='citus'
|
||||||
PACKAGE_VERSION='10.2devel'
|
PACKAGE_VERSION='10.2.1'
|
||||||
PACKAGE_STRING='Citus 10.2devel'
|
PACKAGE_STRING='Citus 10.2.1'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
|
@ -1260,7 +1260,7 @@ if test "$ac_init_help" = "long"; then
|
||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures Citus 10.2devel to adapt to many kinds of systems.
|
\`configure' configures Citus 10.2.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
|
@ -1322,7 +1322,7 @@ fi
|
||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of Citus 10.2devel:";;
|
short | recursive ) echo "Configuration of Citus 10.2.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
|
@ -1425,7 +1425,7 @@ fi
|
||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
Citus configure 10.2devel
|
Citus configure 10.2.1
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
@ -1908,7 +1908,7 @@ cat >config.log <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by Citus $as_me 10.2devel, which was
|
It was created by Citus $as_me 10.2.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
|
@ -5356,7 +5356,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by Citus $as_me 10.2devel, which was
|
This file was extended by Citus $as_me 10.2.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
|
@ -5418,7 +5418,7 @@ _ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
Citus config.status 10.2devel
|
Citus config.status 10.2.1
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
# everyone needing autoconf installed, the resulting files are checked
|
# everyone needing autoconf installed, the resulting files are checked
|
||||||
# into the SCM.
|
# into the SCM.
|
||||||
|
|
||||||
AC_INIT([Citus], [10.2devel])
|
AC_INIT([Citus], [10.2.1])
|
||||||
AC_COPYRIGHT([Copyright (c) Citus Data, Inc.])
|
AC_COPYRIGHT([Copyright (c) Citus Data, Inc.])
|
||||||
|
|
||||||
# we'll need sed and awk for some of the version commands
|
# we'll need sed and awk for some of the version commands
|
||||||
|
|
|
@ -605,10 +605,11 @@ RelationIdGetNumberOfAttributes(Oid relationId)
|
||||||
/*
|
/*
|
||||||
* CheckVarStats() checks whether a qual involving this Var is likely to be
|
* CheckVarStats() checks whether a qual involving this Var is likely to be
|
||||||
* useful based on the correlation stats. If so, or if stats are unavailable,
|
* useful based on the correlation stats. If so, or if stats are unavailable,
|
||||||
* return true; otherwise return false.
|
* return true; otherwise return false and sets absVarCorrelation in case
|
||||||
|
* caller wants to use for logging purposes.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
CheckVarStats(PlannerInfo *root, Var *var, Oid sortop)
|
CheckVarStats(PlannerInfo *root, Var *var, Oid sortop, float4 *absVarCorrelation)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Collect isunique, ndistinct, and varCorrelation.
|
* Collect isunique, ndistinct, and varCorrelation.
|
||||||
|
@ -642,6 +643,14 @@ CheckVarStats(PlannerInfo *root, Var *var, Oid sortop)
|
||||||
*/
|
*/
|
||||||
if (Abs(varCorrelation) < ColumnarQualPushdownCorrelationThreshold)
|
if (Abs(varCorrelation) < ColumnarQualPushdownCorrelationThreshold)
|
||||||
{
|
{
|
||||||
|
if (absVarCorrelation)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Report absVarCorrelation if caller wants to know why given
|
||||||
|
* var is rejected.
|
||||||
|
*/
|
||||||
|
*absVarCorrelation = Abs(varCorrelation);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +683,7 @@ ExprReferencesRelid(Expr *expr, Index relid)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CheckPushdownClause tests to see if clause is a candidate for pushing down
|
* ExtractPushdownClause extracts an Expr node from given clause for pushing down
|
||||||
* into the given rel (including join clauses). This test may not be exact in
|
* into the given rel (including join clauses). This test may not be exact in
|
||||||
* all cases; it's used to reduce the search space for parameterization.
|
* all cases; it's used to reduce the search space for parameterization.
|
||||||
*
|
*
|
||||||
|
@ -683,19 +692,134 @@ ExprReferencesRelid(Expr *expr, Index relid)
|
||||||
* and that doesn't seem worth the effort. Here we just look for "Var op Expr"
|
* and that doesn't seem worth the effort. Here we just look for "Var op Expr"
|
||||||
* or "Expr op Var", where Var references rel and Expr references other rels
|
* or "Expr op Var", where Var references rel and Expr references other rels
|
||||||
* (or no rels at all).
|
* (or no rels at all).
|
||||||
|
*
|
||||||
|
* Moreover, this function also looks into BoolExpr's to recursively extract
|
||||||
|
* pushdownable OpExpr's of them:
|
||||||
|
* i) AND_EXPR:
|
||||||
|
* Take pushdownable args of AND expressions by ignoring the other args.
|
||||||
|
* ii) OR_EXPR:
|
||||||
|
* Ignore the whole OR expression if we cannot exract a pushdownable Expr
|
||||||
|
* from one of its args.
|
||||||
|
* iii) NOT_EXPR:
|
||||||
|
* Simply ignore NOT expressions since we don't expect to see them before
|
||||||
|
* an expression that we can pushdown, see the comment in function.
|
||||||
|
*
|
||||||
|
* The reasoning for those three rules could also be summarized as such;
|
||||||
|
* for any expression that we cannot push-down, we must assume that it
|
||||||
|
* evaluates to true.
|
||||||
|
*
|
||||||
|
* For example, given following WHERE clause:
|
||||||
|
* (
|
||||||
|
* (a > random() OR a < 30)
|
||||||
|
* AND
|
||||||
|
* a < 200
|
||||||
|
* ) OR
|
||||||
|
* (
|
||||||
|
* a = 300
|
||||||
|
* OR
|
||||||
|
* a > 400
|
||||||
|
* );
|
||||||
|
* Even if we can pushdown (a < 30), we cannot pushdown (a > random() OR a < 30)
|
||||||
|
* due to (a > random()). However, we can pushdown (a < 200), so we extract
|
||||||
|
* (a < 200) from the lhs of the top level OR expression.
|
||||||
|
*
|
||||||
|
* For the rhs of the top level OR expression, since we can pushdown both (a = 300)
|
||||||
|
* and (a > 400), we take this part as is.
|
||||||
|
*
|
||||||
|
* Finally, since both sides of the top level OR expression yielded pushdownable
|
||||||
|
* expressions, we will pushdown the following:
|
||||||
|
* (a < 200) OR ((a = 300) OR (a > 400))
|
||||||
*/
|
*/
|
||||||
static bool
|
static Expr *
|
||||||
CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
ExtractPushdownClause(PlannerInfo *root, RelOptInfo *rel, Node *node)
|
||||||
{
|
{
|
||||||
if (!IsA(clause, OpExpr) || list_length(((OpExpr *) clause)->args) != 2)
|
CHECK_FOR_INTERRUPTS();
|
||||||
|
check_stack_depth();
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsA(node, BoolExpr))
|
||||||
|
{
|
||||||
|
BoolExpr *boolExpr = castNode(BoolExpr, node);
|
||||||
|
if (boolExpr->boolop == NOT_EXPR)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Standard planner should have already applied de-morgan rule to
|
||||||
|
* simple NOT expressions. If we encounter with such an expression
|
||||||
|
* here, then it can't be a pushdownable one, such as:
|
||||||
|
* WHERE id NOT IN (SELECT id FROM something).
|
||||||
|
*/
|
||||||
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
|
"must not contain a subplan")));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
List *pushdownableArgs = NIL;
|
||||||
|
|
||||||
|
Node *boolExprArg = NULL;
|
||||||
|
foreach_ptr(boolExprArg, boolExpr->args)
|
||||||
|
{
|
||||||
|
Expr *pushdownableArg = ExtractPushdownClause(root, rel,
|
||||||
|
(Node *) boolExprArg);
|
||||||
|
if (pushdownableArg)
|
||||||
|
{
|
||||||
|
pushdownableArgs = lappend(pushdownableArgs, pushdownableArg);
|
||||||
|
}
|
||||||
|
else if (boolExpr->boolop == OR_EXPR)
|
||||||
|
{
|
||||||
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
|
"all arguments of an OR expression must be "
|
||||||
|
"pushdownable but one of them was not, due "
|
||||||
|
"to the reason given above")));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* simply skip AND args that we cannot pushdown */
|
||||||
|
}
|
||||||
|
|
||||||
|
int npushdownableArgs = list_length(pushdownableArgs);
|
||||||
|
if (npushdownableArgs == 0)
|
||||||
|
{
|
||||||
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
|
"none of the arguments were pushdownable, "
|
||||||
|
"due to the reason(s) given above ")));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (npushdownableArgs == 1)
|
||||||
|
{
|
||||||
|
return (Expr *) linitial(pushdownableArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boolExpr->boolop == AND_EXPR)
|
||||||
|
{
|
||||||
|
return make_andclause(pushdownableArgs);
|
||||||
|
}
|
||||||
|
else if (boolExpr->boolop == OR_EXPR)
|
||||||
|
{
|
||||||
|
return make_orclause(pushdownableArgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* already discarded NOT expr, so should not be reachable */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsA(node, OpExpr) || list_length(((OpExpr *) node)->args) != 2)
|
||||||
{
|
{
|
||||||
ereport(ColumnarPlannerDebugLevel,
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"must be binary operator expression")));
|
"must be binary operator expression")));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpExpr *opExpr = castNode(OpExpr, clause);
|
OpExpr *opExpr = castNode(OpExpr, node);
|
||||||
Expr *lhs = list_nth(opExpr->args, 0);
|
Expr *lhs = list_nth(opExpr->args, 0);
|
||||||
Expr *rhs = list_nth(opExpr->args, 1);
|
Expr *rhs = list_nth(opExpr->args, 1);
|
||||||
|
|
||||||
|
@ -721,15 +845,15 @@ CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
||||||
"must match 'Var <op> Expr' or 'Expr <op> Var'"),
|
"must match 'Var <op> Expr' or 'Expr <op> Var'"),
|
||||||
errhint("Var must only reference this rel, "
|
errhint("Var must only reference this rel, "
|
||||||
"and Expr must not reference this rel")));
|
"and Expr must not reference this rel")));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (varSide->varattno <= 0)
|
if (varSide->varattno <= 0)
|
||||||
{
|
{
|
||||||
ereport(ColumnarPlannerDebugLevel,
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"var is whole-row reference")));
|
"var is whole-row reference or system column")));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contain_volatile_functions((Node *) exprSide))
|
if (contain_volatile_functions((Node *) exprSide))
|
||||||
|
@ -737,7 +861,7 @@ CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
||||||
ereport(ColumnarPlannerDebugLevel,
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"expr contains volatile functions")));
|
"expr contains volatile functions")));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only the default opclass is used for qual pushdown. */
|
/* only the default opclass is used for qual pushdown. */
|
||||||
|
@ -753,7 +877,7 @@ CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"cannot find default btree opclass and opfamily for type: %s",
|
"cannot find default btree opclass and opfamily for type: %s",
|
||||||
format_type_be(varSide->vartype))));
|
format_type_be(varSide->vartype))));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!op_in_opfamily(opExpr->opno, varOpFamily))
|
if (!op_in_opfamily(opExpr->opno, varOpFamily))
|
||||||
|
@ -762,7 +886,7 @@ CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"operator %d not a member of opfamily %d",
|
"operator %d not a member of opfamily %d",
|
||||||
opExpr->opno, varOpFamily)));
|
opExpr->opno, varOpFamily)));
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Oid sortop = get_opfamily_member(varOpFamily, varOpcInType,
|
Oid sortop = get_opfamily_member(varOpFamily, varOpcInType,
|
||||||
|
@ -773,15 +897,20 @@ CheckPushdownClause(PlannerInfo *root, RelOptInfo *rel, Expr *clause)
|
||||||
* Check that statistics on the Var support the utility of this
|
* Check that statistics on the Var support the utility of this
|
||||||
* clause.
|
* clause.
|
||||||
*/
|
*/
|
||||||
if (!CheckVarStats(root, varSide, sortop))
|
float4 absVarCorrelation = 0;
|
||||||
|
if (!CheckVarStats(root, varSide, sortop, &absVarCorrelation))
|
||||||
{
|
{
|
||||||
ereport(ColumnarPlannerDebugLevel,
|
ereport(ColumnarPlannerDebugLevel,
|
||||||
(errmsg("columnar planner: cannot push down clause: "
|
(errmsg("columnar planner: cannot push down clause: "
|
||||||
"var attribute %d is uncorrelated", varSide->varattno)));
|
"absolute correlation (%.3f) of var attribute %d is "
|
||||||
return false;
|
"smaller than the value configured in "
|
||||||
|
"\"columnar.qual_pushdown_correlation_threshold\" "
|
||||||
|
"(%.3f)", absVarCorrelation, varSide->varattno,
|
||||||
|
ColumnarQualPushdownCorrelationThreshold)));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return (Expr *) node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -806,12 +935,19 @@ FilterPushdownClauses(PlannerInfo *root, RelOptInfo *rel, List *inputClauses)
|
||||||
* there's something we should do with pseudoconstants here.
|
* there's something we should do with pseudoconstants here.
|
||||||
*/
|
*/
|
||||||
if (rinfo->pseudoconstant ||
|
if (rinfo->pseudoconstant ||
|
||||||
!bms_is_member(rel->relid, rinfo->required_relids) ||
|
!bms_is_member(rel->relid, rinfo->required_relids))
|
||||||
!CheckPushdownClause(root, rel, rinfo->clause))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *pushdownableExpr = ExtractPushdownClause(root, rel, (Node *) rinfo->clause);
|
||||||
|
if (!pushdownableExpr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rinfo = copyObject(rinfo);
|
||||||
|
rinfo->clause = pushdownableExpr;
|
||||||
filteredClauses = lappend(filteredClauses, rinfo);
|
filteredClauses = lappend(filteredClauses, rinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1178,8 +1178,18 @@ UpdateStripeMetadataRow(uint64 storageId, uint64 stripeId, bool *update,
|
||||||
|
|
||||||
heap_inplace_update(columnarStripes, modifiedTuple);
|
heap_inplace_update(columnarStripes, modifiedTuple);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Existing tuple now contains modifications, because we used
|
||||||
|
* heap_inplace_update().
|
||||||
|
*/
|
||||||
|
HeapTuple newTuple = oldTuple;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must not pass modifiedTuple, because BuildStripeMetadata expects a real
|
||||||
|
* heap tuple with MVCC fields.
|
||||||
|
*/
|
||||||
StripeMetadata *modifiedStripeMetadata = BuildStripeMetadata(columnarStripes,
|
StripeMetadata *modifiedStripeMetadata = BuildStripeMetadata(columnarStripes,
|
||||||
modifiedTuple);
|
newTuple);
|
||||||
|
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
|
|
||||||
|
@ -1233,6 +1243,8 @@ ReadDataFileStripeList(uint64 storageId, Snapshot snapshot)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BuildStripeMetadata builds a StripeMetadata object from given heap tuple.
|
* BuildStripeMetadata builds a StripeMetadata object from given heap tuple.
|
||||||
|
*
|
||||||
|
* NB: heapTuple must be a proper heap tuple with MVCC fields.
|
||||||
*/
|
*/
|
||||||
static StripeMetadata *
|
static StripeMetadata *
|
||||||
BuildStripeMetadata(Relation columnarStripes, HeapTuple heapTuple)
|
BuildStripeMetadata(Relation columnarStripes, HeapTuple heapTuple)
|
||||||
|
@ -1269,7 +1281,8 @@ BuildStripeMetadata(Relation columnarStripes, HeapTuple heapTuple)
|
||||||
* subtransaction id here.
|
* subtransaction id here.
|
||||||
*/
|
*/
|
||||||
TransactionId entryXmin = HeapTupleHeaderGetXmin(heapTuple->t_data);
|
TransactionId entryXmin = HeapTupleHeaderGetXmin(heapTuple->t_data);
|
||||||
stripeMetadata->aborted = TransactionIdDidAbort(entryXmin);
|
stripeMetadata->aborted = !TransactionIdIsInProgress(entryXmin) &&
|
||||||
|
TransactionIdDidAbort(entryXmin);
|
||||||
stripeMetadata->insertedByCurrentXact =
|
stripeMetadata->insertedByCurrentXact =
|
||||||
TransactionIdIsCurrentTransactionId(entryXmin);
|
TransactionIdIsCurrentTransactionId(entryXmin);
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,8 @@ columnar_beginscan(Relation relation, Snapshot snapshot,
|
||||||
ParallelTableScanDesc parallel_scan,
|
ParallelTableScanDesc parallel_scan,
|
||||||
uint32 flags)
|
uint32 flags)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
int natts = relation->rd_att->natts;
|
int natts = relation->rd_att->natts;
|
||||||
|
|
||||||
/* attr_needed represents 0-indexed attribute numbers */
|
/* attr_needed represents 0-indexed attribute numbers */
|
||||||
|
@ -418,6 +420,8 @@ columnar_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
|
||||||
static IndexFetchTableData *
|
static IndexFetchTableData *
|
||||||
columnar_index_fetch_begin(Relation rel)
|
columnar_index_fetch_begin(Relation rel)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
Oid relfilenode = rel->rd_node.relNode;
|
Oid relfilenode = rel->rd_node.relNode;
|
||||||
if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId()))
|
if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId()))
|
||||||
{
|
{
|
||||||
|
@ -638,6 +642,8 @@ static bool
|
||||||
columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
|
columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
|
||||||
Snapshot snapshot)
|
Snapshot snapshot)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
uint64 rowNumber = tid_to_row_number(slot->tts_tid);
|
uint64 rowNumber = tid_to_row_number(slot->tts_tid);
|
||||||
StripeMetadata *stripeMetadata = FindStripeByRowNumber(rel, rowNumber, snapshot);
|
StripeMetadata *stripeMetadata = FindStripeByRowNumber(rel, rowNumber, snapshot);
|
||||||
return stripeMetadata != NULL;
|
return stripeMetadata != NULL;
|
||||||
|
@ -670,6 +676,8 @@ static void
|
||||||
columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
|
columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
|
||||||
int options, BulkInsertState bistate)
|
int options, BulkInsertState bistate)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* columnar_init_write_state allocates the write state in a longer
|
* columnar_init_write_state allocates the write state in a longer
|
||||||
* lasting context, so no need to worry about it.
|
* lasting context, so no need to worry about it.
|
||||||
|
@ -716,6 +724,8 @@ static void
|
||||||
columnar_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
|
columnar_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
|
||||||
CommandId cid, int options, BulkInsertState bistate)
|
CommandId cid, int options, BulkInsertState bistate)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
ColumnarWriteState *writeState = columnar_init_write_state(relation,
|
ColumnarWriteState *writeState = columnar_init_write_state(relation,
|
||||||
RelationGetDescr(relation),
|
RelationGetDescr(relation),
|
||||||
GetCurrentSubTransactionId());
|
GetCurrentSubTransactionId());
|
||||||
|
@ -790,6 +800,8 @@ columnar_relation_set_new_filenode(Relation rel,
|
||||||
TransactionId *freezeXid,
|
TransactionId *freezeXid,
|
||||||
MultiXactId *minmulti)
|
MultiXactId *minmulti)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
if (persistence == RELPERSISTENCE_UNLOGGED)
|
if (persistence == RELPERSISTENCE_UNLOGGED)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
@ -825,6 +837,8 @@ columnar_relation_set_new_filenode(Relation rel,
|
||||||
static void
|
static void
|
||||||
columnar_relation_nontransactional_truncate(Relation rel)
|
columnar_relation_nontransactional_truncate(Relation rel)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
RelFileNode relfilenode = rel->rd_node;
|
RelFileNode relfilenode = rel->rd_node;
|
||||||
|
|
||||||
NonTransactionDropWriteState(relfilenode.relNode);
|
NonTransactionDropWriteState(relfilenode.relNode);
|
||||||
|
@ -871,6 +885,8 @@ columnar_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
|
||||||
double *tups_vacuumed,
|
double *tups_vacuumed,
|
||||||
double *tups_recently_dead)
|
double *tups_recently_dead)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
TupleDesc sourceDesc = RelationGetDescr(OldHeap);
|
TupleDesc sourceDesc = RelationGetDescr(OldHeap);
|
||||||
TupleDesc targetDesc = RelationGetDescr(NewHeap);
|
TupleDesc targetDesc = RelationGetDescr(NewHeap);
|
||||||
|
|
||||||
|
@ -967,6 +983,15 @@ static void
|
||||||
columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
||||||
BufferAccessStrategy bstrategy)
|
BufferAccessStrategy bstrategy)
|
||||||
{
|
{
|
||||||
|
if (!CheckCitusVersion(WARNING))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip if the extension catalogs are not up-to-date, but avoid
|
||||||
|
* erroring during auto-vacuum.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If metapage version of relation is older, then we hint users to VACUUM
|
* If metapage version of relation is older, then we hint users to VACUUM
|
||||||
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
|
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
|
||||||
|
@ -1276,6 +1301,8 @@ columnar_index_build_range_scan(Relation columnarRelation,
|
||||||
void *callback_state,
|
void *callback_state,
|
||||||
TableScanDesc scan)
|
TableScanDesc scan)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
if (start_blockno != 0 || numblocks != InvalidBlockNumber)
|
if (start_blockno != 0 || numblocks != InvalidBlockNumber)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1524,6 +1551,8 @@ columnar_index_validate_scan(Relation columnarRelation,
|
||||||
ValidateIndexState *
|
ValidateIndexState *
|
||||||
validateIndexState)
|
validateIndexState)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
ColumnarReportTotalVirtualBlocks(columnarRelation, snapshot,
|
ColumnarReportTotalVirtualBlocks(columnarRelation, snapshot,
|
||||||
PROGRESS_SCAN_BLOCKS_TOTAL);
|
PROGRESS_SCAN_BLOCKS_TOTAL);
|
||||||
|
|
||||||
|
@ -1694,6 +1723,8 @@ TupleSortSkipSmallerItemPointers(Tuplesortstate *tupleSort, ItemPointer targetIt
|
||||||
static uint64
|
static uint64
|
||||||
columnar_relation_size(Relation rel, ForkNumber forkNumber)
|
columnar_relation_size(Relation rel, ForkNumber forkNumber)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
uint64 nblocks = 0;
|
uint64 nblocks = 0;
|
||||||
|
|
||||||
/* Open it at the smgr level if not already done */
|
/* Open it at the smgr level if not already done */
|
||||||
|
@ -1719,6 +1750,8 @@ columnar_relation_size(Relation rel, ForkNumber forkNumber)
|
||||||
static bool
|
static bool
|
||||||
columnar_relation_needs_toast_table(Relation rel)
|
columnar_relation_needs_toast_table(Relation rel)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1728,6 +1761,8 @@ columnar_estimate_rel_size(Relation rel, int32 *attr_widths,
|
||||||
BlockNumber *pages, double *tuples,
|
BlockNumber *pages, double *tuples,
|
||||||
double *allvisfrac)
|
double *allvisfrac)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
RelationOpenSmgr(rel);
|
RelationOpenSmgr(rel);
|
||||||
*pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
|
*pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
|
||||||
*tuples = ColumnarTableRowCount(rel);
|
*tuples = ColumnarTableRowCount(rel);
|
||||||
|
@ -1899,6 +1934,8 @@ ColumnarTableDropHook(Oid relid)
|
||||||
|
|
||||||
if (IsColumnarTableAmTable(relid))
|
if (IsColumnarTableAmTable(relid))
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop metadata. No need to drop storage here since for
|
* Drop metadata. No need to drop storage here since for
|
||||||
* tableam tables storage is managed by postgres.
|
* tableam tables storage is managed by postgres.
|
||||||
|
@ -2020,6 +2057,8 @@ ColumnarProcessUtility(PlannedStmt *pstmt,
|
||||||
GetCreateIndexRelationLockMode(indexStmt));
|
GetCreateIndexRelationLockMode(indexStmt));
|
||||||
if (rel->rd_tableam == GetColumnarTableAmRoutine())
|
if (rel->rd_tableam == GetColumnarTableAmRoutine())
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
if (!ColumnarSupportsIndexAM(indexStmt->accessMethod))
|
if (!ColumnarSupportsIndexAM(indexStmt->accessMethod))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
@ -2356,6 +2395,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_set);
|
||||||
Datum
|
Datum
|
||||||
alter_columnar_table_set(PG_FUNCTION_ARGS)
|
alter_columnar_table_set(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
Oid relationId = PG_GETARG_OID(0);
|
Oid relationId = PG_GETARG_OID(0);
|
||||||
|
|
||||||
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
|
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
|
||||||
|
@ -2483,6 +2524,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_reset);
|
||||||
Datum
|
Datum
|
||||||
alter_columnar_table_reset(PG_FUNCTION_ARGS)
|
alter_columnar_table_reset(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
Oid relationId = PG_GETARG_OID(0);
|
Oid relationId = PG_GETARG_OID(0);
|
||||||
|
|
||||||
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
|
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- columnar--10.2-1--10.2-2.sql
|
||||||
|
|
||||||
|
-- revoke read access for columnar.chunk from unprivileged
|
||||||
|
-- user as it contains chunk min/max values
|
||||||
|
REVOKE SELECT ON columnar.chunk FROM PUBLIC;
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- columnar--10.2-2--10.2-1.sql
|
||||||
|
|
||||||
|
-- grant read access for columnar.chunk to unprivileged user
|
||||||
|
GRANT SELECT ON columnar.chunk TO PUBLIC;
|
|
@ -1,6 +1,6 @@
|
||||||
# Citus extension
|
# Citus extension
|
||||||
comment = 'Citus distributed database'
|
comment = 'Citus distributed database'
|
||||||
default_version = '10.2-1'
|
default_version = '10.2-2'
|
||||||
module_pathname = '$libdir/citus'
|
module_pathname = '$libdir/citus'
|
||||||
relocatable = false
|
relocatable = false
|
||||||
schema = pg_catalog
|
schema = pg_catalog
|
||||||
|
|
|
@ -554,11 +554,16 @@ CreateDistributedTable(Oid relationId, Var *distributionColumn, char distributio
|
||||||
{
|
{
|
||||||
List *partitionList = PartitionList(relationId);
|
List *partitionList = PartitionList(relationId);
|
||||||
Oid partitionRelationId = InvalidOid;
|
Oid partitionRelationId = InvalidOid;
|
||||||
|
Oid namespaceId = get_rel_namespace(relationId);
|
||||||
|
char *schemaName = get_namespace_name(namespaceId);
|
||||||
|
char *relationName = get_rel_name(relationId);
|
||||||
|
char *parentRelationName = quote_qualified_identifier(schemaName, relationName);
|
||||||
|
|
||||||
foreach_oid(partitionRelationId, partitionList)
|
foreach_oid(partitionRelationId, partitionList)
|
||||||
{
|
{
|
||||||
CreateDistributedTable(partitionRelationId, distributionColumn,
|
CreateDistributedTable(partitionRelationId, distributionColumn,
|
||||||
distributionMethod, shardCount, false,
|
distributionMethod, shardCount, false,
|
||||||
colocateWithTableName, viaDeprecatedAPI);
|
parentRelationName, viaDeprecatedAPI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2061,6 +2061,8 @@ ShouldInitiateMetadataSync(bool *lockFailure)
|
||||||
Datum
|
Datum
|
||||||
citus_internal_add_partition_metadata(PG_FUNCTION_ARGS)
|
citus_internal_add_partition_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
PG_ENSURE_ARGNOTNULL(0, "relation");
|
PG_ENSURE_ARGNOTNULL(0, "relation");
|
||||||
Oid relationId = PG_GETARG_OID(0);
|
Oid relationId = PG_GETARG_OID(0);
|
||||||
|
|
||||||
|
@ -2211,6 +2213,8 @@ EnsurePartitionMetadataIsSane(Oid relationId, char distributionMethod, int coloc
|
||||||
Datum
|
Datum
|
||||||
citus_internal_add_shard_metadata(PG_FUNCTION_ARGS)
|
citus_internal_add_shard_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
PG_ENSURE_ARGNOTNULL(0, "relation");
|
PG_ENSURE_ARGNOTNULL(0, "relation");
|
||||||
Oid relationId = PG_GETARG_OID(0);
|
Oid relationId = PG_GETARG_OID(0);
|
||||||
|
|
||||||
|
@ -2426,6 +2430,8 @@ EnsureShardMetadataIsSane(Oid relationId, int64 shardId, char storageType,
|
||||||
Datum
|
Datum
|
||||||
citus_internal_add_placement_metadata(PG_FUNCTION_ARGS)
|
citus_internal_add_placement_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
int64 shardId = PG_GETARG_INT64(0);
|
int64 shardId = PG_GETARG_INT64(0);
|
||||||
int32 shardState = PG_GETARG_INT32(1);
|
int32 shardState = PG_GETARG_INT32(1);
|
||||||
int64 shardLength = PG_GETARG_INT64(2);
|
int64 shardLength = PG_GETARG_INT64(2);
|
||||||
|
@ -2537,6 +2543,8 @@ ShouldSkipMetadataChecks(void)
|
||||||
Datum
|
Datum
|
||||||
citus_internal_update_placement_metadata(PG_FUNCTION_ARGS)
|
citus_internal_update_placement_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
int64 shardId = PG_GETARG_INT64(0);
|
int64 shardId = PG_GETARG_INT64(0);
|
||||||
int32 sourceGroupId = PG_GETARG_INT32(1);
|
int32 sourceGroupId = PG_GETARG_INT32(1);
|
||||||
int32 targetGroupId = PG_GETARG_INT32(2);
|
int32 targetGroupId = PG_GETARG_INT32(2);
|
||||||
|
@ -2602,6 +2610,8 @@ citus_internal_update_placement_metadata(PG_FUNCTION_ARGS)
|
||||||
Datum
|
Datum
|
||||||
citus_internal_delete_shard_metadata(PG_FUNCTION_ARGS)
|
citus_internal_delete_shard_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
int64 shardId = PG_GETARG_INT64(0);
|
int64 shardId = PG_GETARG_INT64(0);
|
||||||
|
|
||||||
if (!ShouldSkipMetadataChecks())
|
if (!ShouldSkipMetadataChecks())
|
||||||
|
@ -2640,6 +2650,8 @@ citus_internal_delete_shard_metadata(PG_FUNCTION_ARGS)
|
||||||
Datum
|
Datum
|
||||||
citus_internal_update_relation_colocation(PG_FUNCTION_ARGS)
|
citus_internal_update_relation_colocation(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
Oid relationId = PG_GETARG_OID(0);
|
Oid relationId = PG_GETARG_OID(0);
|
||||||
uint32 tagetColocationId = PG_GETARG_UINT32(1);
|
uint32 tagetColocationId = PG_GETARG_UINT32(1);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- citus--10.2-1--10.2-2
|
||||||
|
|
||||||
|
-- bump version to 10.2-2
|
||||||
|
|
||||||
|
#include "../../columnar/sql/columnar--10.2-1--10.2-2.sql"
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- citus--10.2-2--10.2-1
|
||||||
|
|
||||||
|
#include "../../../columnar/sql/downgrades/columnar--10.2-2--10.2-1.sql"
|
|
@ -246,3 +246,6 @@ s/TRIM\(BOTH FROM value\)/btrim\(value\)/g
|
||||||
s/pg14\.idx.*/pg14\.xxxxx/g
|
s/pg14\.idx.*/pg14\.xxxxx/g
|
||||||
|
|
||||||
s/CREATE TABLESPACE test_tablespace LOCATION.*/CREATE TABLESPACE test_tablespace LOCATION XXXX/g
|
s/CREATE TABLESPACE test_tablespace LOCATION.*/CREATE TABLESPACE test_tablespace LOCATION XXXX/g
|
||||||
|
|
||||||
|
# columnar log for var correlation
|
||||||
|
s/(.*absolute correlation \()([0,1]\.[0-9]+)(\) of var attribute [0-9]+ is smaller than.*)/\1X\.YZ\3/g
|
||||||
|
|
|
@ -645,7 +645,7 @@ alter table coltest add column x5 int default (random()*20000)::int;
|
||||||
analyze coltest;
|
analyze coltest;
|
||||||
-- test that expressions on whole-row references are not pushed down
|
-- test that expressions on whole-row references are not pushed down
|
||||||
select * from coltest where coltest = (1,1,1,1);
|
select * from coltest where coltest = (1,1,1,1);
|
||||||
NOTICE: columnar planner: cannot push down clause: var is whole-row reference
|
NOTICE: columnar planner: cannot push down clause: var is whole-row reference or system column
|
||||||
NOTICE: columnar planner: adding CustomScan path for coltest
|
NOTICE: columnar planner: adding CustomScan path for coltest
|
||||||
DETAIL: unparameterized; 0 clauses pushed down
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
id | x1 | x2 | x3 | x5
|
id | x1 | x2 | x3 | x5
|
||||||
|
@ -655,7 +655,7 @@ DETAIL: unparameterized; 0 clauses pushed down
|
||||||
-- test that expressions on uncorrelated attributes are not pushed down
|
-- test that expressions on uncorrelated attributes are not pushed down
|
||||||
set columnar.qual_pushdown_correlation to default;
|
set columnar.qual_pushdown_correlation to default;
|
||||||
select * from coltest where x5 = 23484;
|
select * from coltest where x5 = 23484;
|
||||||
NOTICE: columnar planner: cannot push down clause: var attribute 5 is uncorrelated
|
NOTICE: columnar planner: cannot push down clause: absolute correlation (X.YZ) of var attribute 5 is smaller than the value configured in "columnar.qual_pushdown_correlation_threshold" (0.900)
|
||||||
NOTICE: columnar planner: adding CustomScan path for coltest
|
NOTICE: columnar planner: adding CustomScan path for coltest
|
||||||
DETAIL: unparameterized; 0 clauses pushed down
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
id | x1 | x2 | x3 | x5
|
id | x1 | x2 | x3 | x5
|
||||||
|
@ -819,3 +819,250 @@ select * from numrange_test natural join numrange_test2 order by nr;
|
||||||
|
|
||||||
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
||||||
set default_table_access_method to default;
|
set default_table_access_method to default;
|
||||||
|
set columnar.planner_debug_level to notice;
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL columnar.stripe_row_limit = 2000;
|
||||||
|
SET LOCAL columnar.chunk_group_row_limit = 1000;
|
||||||
|
create table pushdown_test (a int, b int) using columnar;
|
||||||
|
insert into pushdown_test values (generate_series(1, 200000));
|
||||||
|
COMMIT;
|
||||||
|
SET columnar.max_custom_scan_paths TO 50;
|
||||||
|
SET columnar.qual_pushdown_correlation_threshold TO 0.0;
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=2 loops=1)
|
||||||
|
Filter: ((a = 204356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Rows Removed by Filter: 1998
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a = 204356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 198
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
180912
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3 loops=1)
|
||||||
|
Filter: ((a = 194356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Rows Removed by Filter: 2997
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a = 194356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 197
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
375268
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a > a*-1 + b;
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=0 loops=1)
|
||||||
|
Filter: ((a = 204356) OR (a > ((a * '-1'::integer) + b)))
|
||||||
|
Rows Removed by Filter: 200000
|
||||||
|
Columnar Projected Columns: a, b
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=38998 loops=1)
|
||||||
|
Filter: (((a > 1000) AND (a < 10000)) OR ((a > 20000) AND (a < 50000)))
|
||||||
|
Rows Removed by Filter: 2
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (((a > 1000) AND (a < 10000)) OR ((a > 20000) AND (a < 50000)))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 161
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1099459500
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: none of the arguments were pushdownable, due to the reason(s) given above
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=200000 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (a < (2 * a))) OR (a > 100))
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: none of the arguments were pushdownable, due to the reason(s) given above
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
20000100000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3010 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (a <= 2000)) OR (a > 198990))
|
||||||
|
Rows Removed by Filter: 990
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a <= 2000) OR (a > 198990))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 196
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
203491455
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must not contain a subplan
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3009 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (((a < 200) AND (NOT (SubPlan 1))) OR ((a > 1000) AND (a < 2000)))) OR (a > 197990))
|
||||||
|
Rows Removed by Filter: 1991
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (((a < 200) OR ((a > 1000) AND (a < 2000))) OR (a > 197990))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 195
|
||||||
|
SubPlan 1
|
||||||
|
-> Materialize (actual rows=100 loops=199)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test pushdown_test_1 (actual rows=199 loops=1)
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
(11 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must not contain a subplan
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
401479455
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
create function stable_1(arg int) returns int language plpgsql STRICT IMMUTABLE as
|
||||||
|
$$ BEGIN RETURN 1+arg; END; $$;
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=0 loops=1)
|
||||||
|
Filter: ((a < 6001) AND ((a)::double precision = random()) AND (a < stable_1(a)))
|
||||||
|
Rows Removed by Filter: 6000
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (a < 6001)
|
||||||
|
Columnar Chunk Groups Removed by Filter: 194
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
RESET columnar.max_custom_scan_paths;
|
||||||
|
RESET columnar.qual_pushdown_correlation_threshold;
|
||||||
|
RESET columnar.planner_debug_level;
|
||||||
|
DROP TABLE pushdown_test;
|
||||||
|
|
|
@ -645,7 +645,7 @@ alter table coltest add column x5 int default (random()*20000)::int;
|
||||||
analyze coltest;
|
analyze coltest;
|
||||||
-- test that expressions on whole-row references are not pushed down
|
-- test that expressions on whole-row references are not pushed down
|
||||||
select * from coltest where coltest = (1,1,1,1);
|
select * from coltest where coltest = (1,1,1,1);
|
||||||
NOTICE: columnar planner: cannot push down clause: var is whole-row reference
|
NOTICE: columnar planner: cannot push down clause: var is whole-row reference or system column
|
||||||
NOTICE: columnar planner: adding CustomScan path for coltest
|
NOTICE: columnar planner: adding CustomScan path for coltest
|
||||||
DETAIL: unparameterized; 0 clauses pushed down
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
id | x1 | x2 | x3 | x5
|
id | x1 | x2 | x3 | x5
|
||||||
|
@ -655,7 +655,7 @@ DETAIL: unparameterized; 0 clauses pushed down
|
||||||
-- test that expressions on uncorrelated attributes are not pushed down
|
-- test that expressions on uncorrelated attributes are not pushed down
|
||||||
set columnar.qual_pushdown_correlation to default;
|
set columnar.qual_pushdown_correlation to default;
|
||||||
select * from coltest where x5 = 23484;
|
select * from coltest where x5 = 23484;
|
||||||
NOTICE: columnar planner: cannot push down clause: var attribute 5 is uncorrelated
|
NOTICE: columnar planner: cannot push down clause: absolute correlation (X.YZ) of var attribute 5 is smaller than the value configured in "columnar.qual_pushdown_correlation_threshold" (0.900)
|
||||||
NOTICE: columnar planner: adding CustomScan path for coltest
|
NOTICE: columnar planner: adding CustomScan path for coltest
|
||||||
DETAIL: unparameterized; 0 clauses pushed down
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
id | x1 | x2 | x3 | x5
|
id | x1 | x2 | x3 | x5
|
||||||
|
@ -819,3 +819,250 @@ select * from numrange_test natural join numrange_test2 order by nr;
|
||||||
|
|
||||||
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
||||||
set default_table_access_method to default;
|
set default_table_access_method to default;
|
||||||
|
set columnar.planner_debug_level to notice;
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL columnar.stripe_row_limit = 2000;
|
||||||
|
SET LOCAL columnar.chunk_group_row_limit = 1000;
|
||||||
|
create table pushdown_test (a int, b int) using columnar;
|
||||||
|
insert into pushdown_test values (generate_series(1, 200000));
|
||||||
|
COMMIT;
|
||||||
|
SET columnar.max_custom_scan_paths TO 50;
|
||||||
|
SET columnar.qual_pushdown_correlation_threshold TO 0.0;
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=2 loops=1)
|
||||||
|
Filter: ((a = 204356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Rows Removed by Filter: 1998
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a = 204356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 198
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
180912
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3 loops=1)
|
||||||
|
Filter: ((a = 194356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Rows Removed by Filter: 2997
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a = 194356) OR (a = 104356) OR (a = 76556))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 197
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
375268
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a > a*-1 + b;
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=0 loops=1)
|
||||||
|
Filter: ((a = 204356) OR (a > ((a * '-1'::integer) + b)))
|
||||||
|
Rows Removed by Filter: 200000
|
||||||
|
Columnar Projected Columns: a, b
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=38998 loops=1)
|
||||||
|
Filter: (((a > 1000) AND (a < 10000)) OR ((a > 20000) AND (a < 50000)))
|
||||||
|
Rows Removed by Filter: 2
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (((a > 1000) AND (a < 10000)) OR ((a > 20000) AND (a < 50000)))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 161
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1099459500
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: none of the arguments were pushdownable, due to the reason(s) given above
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=200000 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (a < (2 * a))) OR (a > 100))
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: none of the arguments were pushdownable, due to the reason(s) given above
|
||||||
|
NOTICE: columnar planner: cannot push down clause: all arguments of an OR expression must be pushdownable but one of them was not, due to the reason given above
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
20000100000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3010 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (a <= 2000)) OR (a > 198990))
|
||||||
|
Rows Removed by Filter: 990
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: ((a <= 2000) OR (a > 198990))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 196
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
203491455
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must not contain a subplan
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=3009 loops=1)
|
||||||
|
Filter: ((((a)::double precision > random()) AND (((a < 200) AND (NOT (SubPlan 1))) OR ((a > 1000) AND (a < 2000)))) OR (a > 197990))
|
||||||
|
Rows Removed by Filter: 1991
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (((a < 200) OR ((a > 1000) AND (a < 2000))) OR (a > 197990))
|
||||||
|
Columnar Chunk Groups Removed by Filter: 195
|
||||||
|
SubPlan 1
|
||||||
|
-> Materialize (actual rows=100 loops=199)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test pushdown_test_1 (actual rows=199 loops=1)
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
(11 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 0 clauses pushed down
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must not contain a subplan
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
401479455
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
create function stable_1(arg int) returns int language plpgsql STRICT IMMUTABLE as
|
||||||
|
$$ BEGIN RETURN 1+arg; END; $$;
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Aggregate (actual rows=1 loops=1)
|
||||||
|
-> Custom Scan (ColumnarScan) on pushdown_test (actual rows=0 loops=1)
|
||||||
|
Filter: ((a < 6001) AND ((a)::double precision = random()) AND (a < stable_1(a)))
|
||||||
|
Rows Removed by Filter: 6000
|
||||||
|
Columnar Projected Columns: a
|
||||||
|
Columnar Chunk Group Filters: (a < 6001)
|
||||||
|
Columnar Chunk Groups Removed by Filter: 194
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: cannot push down clause: must match 'Var <op> Expr' or 'Expr <op> Var'
|
||||||
|
HINT: Var must only reference this rel, and Expr must not reference this rel
|
||||||
|
NOTICE: columnar planner: adding CustomScan path for pushdown_test
|
||||||
|
DETAIL: unparameterized; 1 clauses pushed down
|
||||||
|
sum
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
RESET columnar.max_custom_scan_paths;
|
||||||
|
RESET columnar.qual_pushdown_correlation_threshold;
|
||||||
|
RESET columnar.planner_debug_level;
|
||||||
|
DROP TABLE pushdown_test;
|
||||||
|
|
|
@ -750,6 +750,41 @@ SELECT * FROM multi_extension.print_extension_changes();
|
||||||
| view public.citus_tables
|
| view public.citus_tables
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- not print "HINT: " to hide current lib version
|
||||||
|
\set VERBOSITY terse
|
||||||
|
CREATE TABLE columnar_table(a INT, b INT) USING columnar;
|
||||||
|
SET citus.enable_version_checks TO ON;
|
||||||
|
-- all should throw an error due to version mismatch
|
||||||
|
VACUUM FULL columnar_table;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
INSERT INTO columnar_table SELECT i FROM generate_series(1, 10) i;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
VACUUM columnar_table;
|
||||||
|
WARNING: loaded Citus library version differs from installed extension version
|
||||||
|
TRUNCATE columnar_table;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
DROP TABLE columnar_table;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
CREATE INDEX ON columnar_table (a);
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
SELECT alter_columnar_table_set('columnar_table', compression => 'pglz');
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
SELECT alter_columnar_table_reset('columnar_table');
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
INSERT INTO columnar_table SELECT * FROM columnar_table;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
SELECT 1 FROM columnar_table; -- columnar custom scan
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
SET columnar.enable_custom_scan TO OFF;
|
||||||
|
SELECT 1 FROM columnar_table; -- seq scan
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
CREATE TABLE new_columnar_table (a int) USING columnar;
|
||||||
|
ERROR: loaded Citus library version differs from installed extension version
|
||||||
|
-- do cleanup for the rest of the tests
|
||||||
|
SET citus.enable_version_checks TO OFF;
|
||||||
|
DROP TABLE columnar_table;
|
||||||
|
RESET columnar.enable_custom_scan;
|
||||||
|
\set VERBOSITY default
|
||||||
-- Test downgrade to 10.0-4 from 10.1-1
|
-- Test downgrade to 10.0-4 from 10.1-1
|
||||||
ALTER EXTENSION citus UPDATE TO '10.1-1';
|
ALTER EXTENSION citus UPDATE TO '10.1-1';
|
||||||
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
||||||
|
@ -813,12 +848,28 @@ SELECT * FROM multi_extension.print_extension_changes();
|
||||||
| function worker_nextval(regclass) integer
|
| function worker_nextval(regclass) integer
|
||||||
(16 rows)
|
(16 rows)
|
||||||
|
|
||||||
|
-- Test downgrade to 10.2-1 from 10.2-2
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-2';
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-1';
|
||||||
|
-- Should be empty result since upgrade+downgrade should be a no-op
|
||||||
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
previous_object | current_object
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
-- Snapshot of state at 10.2-2
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-2';
|
||||||
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
previous_object | current_object
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
||||||
-- show running version
|
-- show running version
|
||||||
SHOW citus.version;
|
SHOW citus.version;
|
||||||
citus.version
|
citus.version
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
10.2devel
|
10.2.1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- ensure no unexpected objects were created outside pg_catalog
|
-- ensure no unexpected objects were created outside pg_catalog
|
||||||
|
|
|
@ -265,19 +265,26 @@ SELECT * FROM columnar.stripe;
|
||||||
|
|
||||||
-- alter a columnar setting
|
-- alter a columnar setting
|
||||||
SET columnar.chunk_group_row_limit = 1050;
|
SET columnar.chunk_group_row_limit = 1050;
|
||||||
DO $proc$
|
-- create columnar table
|
||||||
BEGIN
|
CREATE TABLE columnar_table (a int) USING columnar;
|
||||||
IF substring(current_Setting('server_version'), '\d+')::int >= 12 THEN
|
-- alter a columnar table that is created by that unprivileged user
|
||||||
EXECUTE $$
|
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
|
||||||
-- create columnar table
|
alter_columnar_table_set
|
||||||
CREATE TABLE columnar_table (a int) USING columnar;
|
---------------------------------------------------------------------
|
||||||
-- alter a columnar table that is created by that unprivileged user
|
|
||||||
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
|
(1 row)
|
||||||
-- and drop it
|
|
||||||
DROP TABLE columnar_table;
|
-- insert some data and read
|
||||||
$$;
|
INSERT INTO columnar_table VALUES (1), (1);
|
||||||
END IF;
|
SELECT * FROM columnar_table;
|
||||||
END$proc$;
|
a
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
1
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
-- and drop it
|
||||||
|
DROP TABLE columnar_table;
|
||||||
-- cannot modify columnar metadata table as unprivileged user
|
-- cannot modify columnar metadata table as unprivileged user
|
||||||
INSERT INTO columnar.stripe VALUES(99);
|
INSERT INTO columnar.stripe VALUES(99);
|
||||||
ERROR: permission denied for table stripe
|
ERROR: permission denied for table stripe
|
||||||
|
@ -286,6 +293,9 @@ ERROR: permission denied for table stripe
|
||||||
-- (since citus extension has a dependency to it)
|
-- (since citus extension has a dependency to it)
|
||||||
DROP TABLE columnar.chunk;
|
DROP TABLE columnar.chunk;
|
||||||
ERROR: must be owner of table chunk
|
ERROR: must be owner of table chunk
|
||||||
|
-- cannot read columnar.chunk since it could expose chunk min/max values
|
||||||
|
SELECT * FROM columnar.chunk;
|
||||||
|
ERROR: permission denied for table chunk
|
||||||
-- test whether a read-only user can read from citus_tables view
|
-- test whether a read-only user can read from citus_tables view
|
||||||
SELECT distribution_column FROM citus_tables WHERE table_name = 'test'::regclass;
|
SELECT distribution_column FROM citus_tables WHERE table_name = 'test'::regclass;
|
||||||
distribution_column
|
distribution_column
|
||||||
|
|
|
@ -1028,6 +1028,46 @@ CREATE TABLE partitioned_users_table_2009 PARTITION OF partitioned_users_table F
|
||||||
CREATE TABLE partitioned_events_table_2009 PARTITION OF partitioned_events_table FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
|
CREATE TABLE partitioned_events_table_2009 PARTITION OF partitioned_events_table FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
|
||||||
INSERT INTO partitioned_events_table SELECT * FROM events_table;
|
INSERT INTO partitioned_events_table SELECT * FROM events_table;
|
||||||
INSERT INTO partitioned_users_table_2009 SELECT * FROM users_table;
|
INSERT INTO partitioned_users_table_2009 SELECT * FROM users_table;
|
||||||
|
-- test distributed partitions are indeed colocated with the parent table
|
||||||
|
CREATE TABLE sensors(measureid integer, eventdatetime date, measure_data jsonb, PRIMARY KEY (measureid, eventdatetime, measure_data))
|
||||||
|
PARTITION BY RANGE(eventdatetime);
|
||||||
|
CREATE TABLE sensors_old PARTITION OF sensors FOR VALUES FROM ('2000-01-01') TO ('2020-01-01');
|
||||||
|
CREATE TABLE sensors_2020_01_01 PARTITION OF sensors FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
|
||||||
|
CREATE TABLE sensors_new PARTITION OF sensors DEFAULT;
|
||||||
|
SELECT create_distributed_table('sensors', 'measureid', colocate_with:='none');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(DISTINCT colocationid) FROM pg_dist_partition
|
||||||
|
WHERE logicalrelid IN ('sensors'::regclass, 'sensors_old'::regclass, 'sensors_2020_01_01'::regclass, 'sensors_new'::regclass);
|
||||||
|
count
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE TABLE local_sensors(measureid integer, eventdatetime date, measure_data jsonb, PRIMARY KEY (measureid, eventdatetime, measure_data))
|
||||||
|
PARTITION BY RANGE(eventdatetime);
|
||||||
|
CREATE TABLE local_sensors_old PARTITION OF local_sensors FOR VALUES FROM ('2000-01-01') TO ('2020-01-01');
|
||||||
|
CREATE TABLE local_sensors_2020_01_01 PARTITION OF local_sensors FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
|
||||||
|
CREATE TABLE local_sensors_new PARTITION OF local_sensors DEFAULT;
|
||||||
|
SELECT create_distributed_table('local_sensors', 'measureid', colocate_with:='sensors');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(DISTINCT colocationid) FROM pg_dist_partition
|
||||||
|
WHERE logicalrelid IN ('sensors'::regclass, 'sensors_old'::regclass, 'sensors_2020_01_01'::regclass, 'sensors_new'::regclass,
|
||||||
|
'local_sensors'::regclass, 'local_sensors_old'::regclass, 'local_sensors_2020_01_01'::regclass, 'local_sensors_new'::regclass);
|
||||||
|
count
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP TABLE sensors;
|
||||||
|
DROP TABLE local_sensors;
|
||||||
--
|
--
|
||||||
-- Complex JOINs, subqueries, UNIONs etc...
|
-- Complex JOINs, subqueries, UNIONs etc...
|
||||||
--
|
--
|
||||||
|
@ -1298,7 +1338,7 @@ INSERT INTO multi_column_partitioning VALUES(1, 1);
|
||||||
INSERT INTO multi_column_partitioning_0_0_10_0 VALUES(5, -5);
|
INSERT INTO multi_column_partitioning_0_0_10_0 VALUES(5, -5);
|
||||||
-- test INSERT to multi-column partitioned table where no suitable partition exists
|
-- test INSERT to multi-column partitioned table where no suitable partition exists
|
||||||
INSERT INTO multi_column_partitioning VALUES(10, 1);
|
INSERT INTO multi_column_partitioning VALUES(10, 1);
|
||||||
ERROR: no partition of relation "multi_column_partitioning_1660101" found for row
|
ERROR: no partition of relation "multi_column_partitioning_1660133" found for row
|
||||||
DETAIL: Partition key of the failing row contains (c1, c2) = (10, 1).
|
DETAIL: Partition key of the failing row contains (c1, c2) = (10, 1).
|
||||||
CONTEXT: while executing command on localhost:xxxxx
|
CONTEXT: while executing command on localhost:xxxxx
|
||||||
-- test with MINVALUE/MAXVALUE
|
-- test with MINVALUE/MAXVALUE
|
||||||
|
@ -1308,7 +1348,7 @@ INSERT INTO multi_column_partitioning VALUES(11, -11);
|
||||||
INSERT INTO multi_column_partitioning_10_max_20_min VALUES(19, -19);
|
INSERT INTO multi_column_partitioning_10_max_20_min VALUES(19, -19);
|
||||||
-- test INSERT to multi-column partitioned table where no suitable partition exists
|
-- test INSERT to multi-column partitioned table where no suitable partition exists
|
||||||
INSERT INTO multi_column_partitioning VALUES(20, -20);
|
INSERT INTO multi_column_partitioning VALUES(20, -20);
|
||||||
ERROR: no partition of relation "multi_column_partitioning_1660101" found for row
|
ERROR: no partition of relation "multi_column_partitioning_1660133" found for row
|
||||||
DETAIL: Partition key of the failing row contains (c1, c2) = (20, -20).
|
DETAIL: Partition key of the failing row contains (c1, c2) = (20, -20).
|
||||||
CONTEXT: while executing command on localhost:xxxxx
|
CONTEXT: while executing command on localhost:xxxxx
|
||||||
-- see data is loaded to multi-column partitioned table
|
-- see data is loaded to multi-column partitioned table
|
||||||
|
|
|
@ -374,3 +374,74 @@ select * from numrange_test natural join numrange_test2 order by nr;
|
||||||
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
DROP TABLE atest1, atest2, t1, t2, t3, numrange_test, numrange_test2;
|
||||||
|
|
||||||
set default_table_access_method to default;
|
set default_table_access_method to default;
|
||||||
|
|
||||||
|
set columnar.planner_debug_level to notice;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL columnar.stripe_row_limit = 2000;
|
||||||
|
SET LOCAL columnar.chunk_group_row_limit = 1000;
|
||||||
|
create table pushdown_test (a int, b int) using columnar;
|
||||||
|
insert into pushdown_test values (generate_series(1, 200000));
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SET columnar.max_custom_scan_paths TO 50;
|
||||||
|
SET columnar.qual_pushdown_correlation_threshold TO 0.0;
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a = 104356 or a = 76556;
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 194356 or a = 104356 or a = 76556;
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test WHERE a = 204356 or a > a*-1 + b;
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > 1000 and a < 10000) or (a > 20000 and a < 50000);
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a < 2*a) or (a > 100);
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a > random() and a <= 2000) or (a > 200000-1010);
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
SELECT sum(a) FROM pushdown_test where
|
||||||
|
(
|
||||||
|
a > random()
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(a < 200 and a not in (select a from pushdown_test)) or
|
||||||
|
(a > 1000 and a < 2000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
(a > 200000-2010);
|
||||||
|
|
||||||
|
create function stable_1(arg int) returns int language plpgsql STRICT IMMUTABLE as
|
||||||
|
$$ BEGIN RETURN 1+arg; END; $$;
|
||||||
|
|
||||||
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
SELECT sum(a) FROM pushdown_test where (a = random() and a < stable_1(a) and a < stable_1(6000));
|
||||||
|
|
||||||
|
RESET columnar.max_custom_scan_paths;
|
||||||
|
RESET columnar.qual_pushdown_correlation_threshold;
|
||||||
|
RESET columnar.planner_debug_level;
|
||||||
|
DROP TABLE pushdown_test;
|
||||||
|
|
|
@ -297,6 +297,35 @@ ALTER EXTENSION citus UPDATE TO '9.5-1';
|
||||||
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
||||||
SELECT * FROM multi_extension.print_extension_changes();
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
|
||||||
|
-- not print "HINT: " to hide current lib version
|
||||||
|
\set VERBOSITY terse
|
||||||
|
CREATE TABLE columnar_table(a INT, b INT) USING columnar;
|
||||||
|
SET citus.enable_version_checks TO ON;
|
||||||
|
|
||||||
|
-- all should throw an error due to version mismatch
|
||||||
|
VACUUM FULL columnar_table;
|
||||||
|
INSERT INTO columnar_table SELECT i FROM generate_series(1, 10) i;
|
||||||
|
VACUUM columnar_table;
|
||||||
|
TRUNCATE columnar_table;
|
||||||
|
DROP TABLE columnar_table;
|
||||||
|
CREATE INDEX ON columnar_table (a);
|
||||||
|
SELECT alter_columnar_table_set('columnar_table', compression => 'pglz');
|
||||||
|
SELECT alter_columnar_table_reset('columnar_table');
|
||||||
|
INSERT INTO columnar_table SELECT * FROM columnar_table;
|
||||||
|
|
||||||
|
SELECT 1 FROM columnar_table; -- columnar custom scan
|
||||||
|
|
||||||
|
SET columnar.enable_custom_scan TO OFF;
|
||||||
|
SELECT 1 FROM columnar_table; -- seq scan
|
||||||
|
|
||||||
|
CREATE TABLE new_columnar_table (a int) USING columnar;
|
||||||
|
|
||||||
|
-- do cleanup for the rest of the tests
|
||||||
|
SET citus.enable_version_checks TO OFF;
|
||||||
|
DROP TABLE columnar_table;
|
||||||
|
RESET columnar.enable_custom_scan;
|
||||||
|
\set VERBOSITY default
|
||||||
|
|
||||||
-- Test downgrade to 10.0-4 from 10.1-1
|
-- Test downgrade to 10.0-4 from 10.1-1
|
||||||
ALTER EXTENSION citus UPDATE TO '10.1-1';
|
ALTER EXTENSION citus UPDATE TO '10.1-1';
|
||||||
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
ALTER EXTENSION citus UPDATE TO '10.0-4';
|
||||||
|
@ -317,6 +346,16 @@ SELECT * FROM multi_extension.print_extension_changes();
|
||||||
ALTER EXTENSION citus UPDATE TO '10.2-1';
|
ALTER EXTENSION citus UPDATE TO '10.2-1';
|
||||||
SELECT * FROM multi_extension.print_extension_changes();
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
|
||||||
|
-- Test downgrade to 10.2-1 from 10.2-2
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-2';
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-1';
|
||||||
|
-- Should be empty result since upgrade+downgrade should be a no-op
|
||||||
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
|
||||||
|
-- Snapshot of state at 10.2-2
|
||||||
|
ALTER EXTENSION citus UPDATE TO '10.2-2';
|
||||||
|
SELECT * FROM multi_extension.print_extension_changes();
|
||||||
|
|
||||||
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff;
|
||||||
|
|
||||||
-- show running version
|
-- show running version
|
||||||
|
|
|
@ -162,19 +162,15 @@ SELECT * FROM columnar.stripe;
|
||||||
-- alter a columnar setting
|
-- alter a columnar setting
|
||||||
SET columnar.chunk_group_row_limit = 1050;
|
SET columnar.chunk_group_row_limit = 1050;
|
||||||
|
|
||||||
DO $proc$
|
-- create columnar table
|
||||||
BEGIN
|
CREATE TABLE columnar_table (a int) USING columnar;
|
||||||
IF substring(current_Setting('server_version'), '\d+')::int >= 12 THEN
|
-- alter a columnar table that is created by that unprivileged user
|
||||||
EXECUTE $$
|
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
|
||||||
-- create columnar table
|
-- insert some data and read
|
||||||
CREATE TABLE columnar_table (a int) USING columnar;
|
INSERT INTO columnar_table VALUES (1), (1);
|
||||||
-- alter a columnar table that is created by that unprivileged user
|
SELECT * FROM columnar_table;
|
||||||
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
|
-- and drop it
|
||||||
-- and drop it
|
DROP TABLE columnar_table;
|
||||||
DROP TABLE columnar_table;
|
|
||||||
$$;
|
|
||||||
END IF;
|
|
||||||
END$proc$;
|
|
||||||
|
|
||||||
-- cannot modify columnar metadata table as unprivileged user
|
-- cannot modify columnar metadata table as unprivileged user
|
||||||
INSERT INTO columnar.stripe VALUES(99);
|
INSERT INTO columnar.stripe VALUES(99);
|
||||||
|
@ -183,6 +179,8 @@ INSERT INTO columnar.stripe VALUES(99);
|
||||||
-- (since citus extension has a dependency to it)
|
-- (since citus extension has a dependency to it)
|
||||||
DROP TABLE columnar.chunk;
|
DROP TABLE columnar.chunk;
|
||||||
|
|
||||||
|
-- cannot read columnar.chunk since it could expose chunk min/max values
|
||||||
|
SELECT * FROM columnar.chunk;
|
||||||
|
|
||||||
-- test whether a read-only user can read from citus_tables view
|
-- test whether a read-only user can read from citus_tables view
|
||||||
SELECT distribution_column FROM citus_tables WHERE table_name = 'test'::regclass;
|
SELECT distribution_column FROM citus_tables WHERE table_name = 'test'::regclass;
|
||||||
|
|
|
@ -638,6 +638,35 @@ CREATE TABLE partitioned_events_table_2009 PARTITION OF partitioned_events_table
|
||||||
INSERT INTO partitioned_events_table SELECT * FROM events_table;
|
INSERT INTO partitioned_events_table SELECT * FROM events_table;
|
||||||
INSERT INTO partitioned_users_table_2009 SELECT * FROM users_table;
|
INSERT INTO partitioned_users_table_2009 SELECT * FROM users_table;
|
||||||
|
|
||||||
|
-- test distributed partitions are indeed colocated with the parent table
|
||||||
|
CREATE TABLE sensors(measureid integer, eventdatetime date, measure_data jsonb, PRIMARY KEY (measureid, eventdatetime, measure_data))
|
||||||
|
PARTITION BY RANGE(eventdatetime);
|
||||||
|
|
||||||
|
CREATE TABLE sensors_old PARTITION OF sensors FOR VALUES FROM ('2000-01-01') TO ('2020-01-01');
|
||||||
|
CREATE TABLE sensors_2020_01_01 PARTITION OF sensors FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
|
||||||
|
CREATE TABLE sensors_new PARTITION OF sensors DEFAULT;
|
||||||
|
|
||||||
|
SELECT create_distributed_table('sensors', 'measureid', colocate_with:='none');
|
||||||
|
|
||||||
|
SELECT count(DISTINCT colocationid) FROM pg_dist_partition
|
||||||
|
WHERE logicalrelid IN ('sensors'::regclass, 'sensors_old'::regclass, 'sensors_2020_01_01'::regclass, 'sensors_new'::regclass);
|
||||||
|
|
||||||
|
CREATE TABLE local_sensors(measureid integer, eventdatetime date, measure_data jsonb, PRIMARY KEY (measureid, eventdatetime, measure_data))
|
||||||
|
PARTITION BY RANGE(eventdatetime);
|
||||||
|
|
||||||
|
CREATE TABLE local_sensors_old PARTITION OF local_sensors FOR VALUES FROM ('2000-01-01') TO ('2020-01-01');
|
||||||
|
CREATE TABLE local_sensors_2020_01_01 PARTITION OF local_sensors FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
|
||||||
|
CREATE TABLE local_sensors_new PARTITION OF local_sensors DEFAULT;
|
||||||
|
|
||||||
|
SELECT create_distributed_table('local_sensors', 'measureid', colocate_with:='sensors');
|
||||||
|
|
||||||
|
SELECT count(DISTINCT colocationid) FROM pg_dist_partition
|
||||||
|
WHERE logicalrelid IN ('sensors'::regclass, 'sensors_old'::regclass, 'sensors_2020_01_01'::regclass, 'sensors_new'::regclass,
|
||||||
|
'local_sensors'::regclass, 'local_sensors_old'::regclass, 'local_sensors_2020_01_01'::regclass, 'local_sensors_new'::regclass);
|
||||||
|
|
||||||
|
DROP TABLE sensors;
|
||||||
|
DROP TABLE local_sensors;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Complex JOINs, subqueries, UNIONs etc...
|
-- Complex JOINs, subqueries, UNIONs etc...
|
||||||
--
|
--
|
||||||
|
|
Loading…
Reference in New Issue