diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..3f397c7d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +*.sh +fdw_rpm_with_pgspider/ +fdw_rpm_with_postgres/ diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 37ca5f7c..7542a8dd 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,8 +24,8 @@ jobs: test: needs: detect-pgversion env: - SQLITE_VERSION : "3420000" - SQLITE_YEAR: "2023" + SQLITE_VERSION : "3460000" + SQLITE_YEAR: "2024" POSTGIS_VERSION : "3.4.2" HTTP_PROXY: "" HTTPS_PROXY: "" diff --git a/GitHubActions/build_postgres.sh b/GitHubActions/build_postgres.sh index dba1c45d..8fb70f5d 100644 --- a/GitHubActions/build_postgres.sh +++ b/GitHubActions/build_postgres.sh @@ -6,7 +6,7 @@ # then builds it. # # Usage: ./build_postgres.sh pg_version [configure_options] -# pg_version is a PostgreSQL version to be installed like 16.0. +# pg_version is a PostgreSQL version to be installed like 17.0. # configure_options are a list of option for postgres server. # # Requirements @@ -36,4 +36,4 @@ fi make sudo make install -sudo chown -R $USER /usr/local/pgsql \ No newline at end of file +sudo chown -R $USER /usr/local/pgsql diff --git a/GitHubActions/build_sqlite_fdw.sh b/GitHubActions/build_sqlite_fdw.sh index d89b7bb6..05b6c839 100644 --- a/GitHubActions/build_sqlite_fdw.sh +++ b/GitHubActions/build_sqlite_fdw.sh @@ -5,7 +5,7 @@ # This script builds sqlite_fdw in PostgreSQL source tree. # # Usage: ./build_sqlite_fdw.sh pg_version mode -# pg_version is a PostgreSQL version like 16.0 to be built in. +# pg_version is a PostgreSQL version like 17.0 to be built in. # mode is flag for sqlite_fdw compiler. # # Requirements @@ -28,4 +28,4 @@ else make fi -sudo make install \ No newline at end of file +sudo make install diff --git a/GitHubActions/detect_targets.sh b/GitHubActions/detect_targets.sh index 394d27d4..981572f4 100644 --- a/GitHubActions/detect_targets.sh +++ b/GitHubActions/detect_targets.sh @@ -4,7 +4,7 @@ # # This script detects target PostgreSQL versions for sqlite_fdw testing from # directory names in ./sql directory. Detected versions will be outputed to -# the standard output as an array of string like ["15.4","16.0"]. +# the standard output as an array of string like ["16.3","17.0"]. # # Usage: ./detect_targets.sh # diff --git a/GitHubActions/execute_test.sh b/GitHubActions/execute_test.sh index 60248eba..dbbc89ec 100644 --- a/GitHubActions/execute_test.sh +++ b/GitHubActions/execute_test.sh @@ -7,7 +7,7 @@ # Otherwise, it will exit with failure. # Usage: ./execute_test.sh pg_version mode -# pg_version is a PostgreSQL version to be tested like 16.0. +# pg_version is a PostgreSQL version to be tested like 17.0. # mode is flag for sqlite_fdw compiler. # # Requiremets diff --git a/META.json b/META.json index 3fdb371d..ca39f324 100644 --- a/META.json +++ b/META.json @@ -2,7 +2,7 @@ "name": "sqlite_fdw", "abstract": "Foreign Data Wrapper for SQLite databases", "description": "PostgreSQL extension which implements a Foreign Data Wrapper (FDW) for SQLite databases.", - "version": "2.4.0", + "version": "2.5.0", "maintainer": "pgspider", "license": "postgresql", "provides": { @@ -10,7 +10,7 @@ "abstract": "Foreign Data Wrapper for SQLite databases", "file": "sqlite_fdw.c", "docfile": "README.md", - "version": "2.4.0" + "version": "2.5.0" } }, "prereqs": { diff --git a/Makefile b/Makefile index 92f0b27d..d6e210ea 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ include $(PGXS) ifndef MAJORVERSION MAJORVERSION := $(basename $(VERSION)) endif -ifeq (,$(findstring $(MAJORVERSION), 12 13 14 15 16)) -$(error PostgreSQL 12, 13, 14, 15 or 16 is required to compile this extension) +ifeq (,$(findstring $(MAJORVERSION), 13 14 15 16 17)) +$(error PostgreSQL 13, 14, 15, 16 or 17 is required to compile this extension) endif else diff --git a/README.md b/README.md index 135a8801..e552678e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ SQLite Foreign Data Wrapper for PostgreSQL ========================================== This is a foreign data wrapper (FDW) to connect [PostgreSQL](https://www.postgresql.org/) -to [SQLite](https://sqlite.org/) database file. This FDW works with PostgreSQL 12, 13, 14, 15, 16 and confirmed with SQLite 3.42.0. +to [SQLite](https://sqlite.org/) database file. This FDW works with PostgreSQL 13, 14, 15, 16, 17 and confirmed with SQLite 3.46.0. PostgreSQL + SQLite @@ -50,7 +50,7 @@ Features - `WHERE` clauses are pushdowned - Aggregate function are pushdowned - `ORDER BY` is pushdowned -- Joins (left/right/inner/cross) are pushdowned +- Joins (left/right/inner/cross/semi) are pushdowned - `CASE` expressions are pushdowned. - `LIMIT` and `OFFSET` are pushdowned when all tables in the query are foreign tables belongs to the same PostgreSQL `FOREIGN SERVER` object. - Support `GROUP BY`, `HAVING` push-down. @@ -329,7 +329,7 @@ Returns standard "version integer" as `major version * 10000 + minor version * 1 ``` sqlite_fdw_version -------------------- - 20400 + 20500 ``` Identifier case handling @@ -593,30 +593,30 @@ Test directory have structure as following: ``` +---sql -| +---12.16 +| +---13.15 | | filename1.sql | | filename2.sql | | -| +---13.12 +| +---14.12 | | filename1.sql | | filename2.sql | | ................. -| \---15.4 +| \---17.0 | filename1.sql | filename2.sql | \---expected -| +---12.16 +| +---13.15 | | filename1.out | | filename2.out | | -| +---13.12 +| +---14.12 | | filename1.out | | filename2.out | | ................. -| \---15.4 +| \---17.0 filename1.out filename2.out ``` diff --git a/connection.c b/connection.c index 2f373217..45f22729 100644 --- a/connection.c +++ b/connection.c @@ -46,7 +46,6 @@ typedef struct ConnCacheEntry Oid serverid; /* foreign server OID used to get server name */ List *stmtList; /* list stmt associated with conn */ uint32 server_hashvalue; /* hash value of foreign server OID */ - uint32 mapping_hashvalue; /* hash value of user mapping OID */ } ConnCacheEntry; /* diff --git a/deparse.c b/deparse.c index 4637609e..50e0b721 100644 --- a/deparse.c +++ b/deparse.c @@ -54,7 +54,7 @@ typedef enum { FDW_COLLATE_NONE, /* expression is of a noncollatable type */ FDW_COLLATE_SAFE, /* collation derives from a foreign Var */ - FDW_COLLATE_UNSAFE /* collation derives from something else */ + FDW_COLLATE_UNSAFE, /* collation derives from something else */ } FDWCollateState; typedef struct foreign_loc_cxt @@ -127,16 +127,28 @@ static void sqlite_deparse_relation(StringInfo buf, Relation rel); static void sqlite_deparse_target_list(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs, bool is_concat, bool check_null); static void sqlite_deparse_column_ref(StringInfo buf, int varno, int varattno, PlannerInfo *root, bool qualify_col, bool dml_context); -static void sqlite_deparse_select(List *tlist, List **retrieved_attrs, deparse_expr_cxt *context); +static void sqlite_deparse_select(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context); +static void sqlite_deparse_subquery_target_list(deparse_expr_cxt *context); static void sqlite_deparse_case_expr(CaseExpr *node, deparse_expr_cxt *context); static void sqlite_deparse_null_if_expr(NullIfExpr *node, deparse_expr_cxt *context); static void sqlite_deparse_coalesce_expr(CoalesceExpr *node, deparse_expr_cxt *context); static void sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, +#if PG_VERSION_NUM >= 170000 + List **additional_conds, +#endif List **params_list); +#if PG_VERSION_NUM >= 170000 +static void sqlite_append_where_clause(List *exprs, List *additional_conds, + deparse_expr_cxt *context); +#endif static void sqlite_deparse_range_tbl_ref(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool make_subquery, - Index ignore_rel, List **ignore_conds, List **params_list); + Index ignore_rel, List **ignore_conds, +#if PG_VERSION_NUM >= 170000 + List **additional_conds, +#endif + List **params_list); static void sqlite_deparse_from_expr(List *quals, deparse_expr_cxt *context); static void sqlite_deparse_aggref(Aggref *node, deparse_expr_cxt *context); static void sqlite_append_limit_clause(deparse_expr_cxt *context); @@ -1215,7 +1227,7 @@ sqlite_deparse_select_stmt_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo context.params_list = params_list; /* Construct SELECT clause */ - sqlite_deparse_select(tlist, retrieved_attrs, &context); + sqlite_deparse_select(tlist, is_subquery, retrieved_attrs, &context); /* * For upper relations, the WHERE clause is built from the remote @@ -1264,7 +1276,7 @@ sqlite_deparse_select_stmt_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * Deparese SELECT statment */ static void -sqlite_deparse_select(List *tlist, List **retrieved_attrs, deparse_expr_cxt *context) +sqlite_deparse_select(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context) { StringInfo buf = context->buf; PlannerInfo *root = context->root; @@ -1276,7 +1288,16 @@ sqlite_deparse_select(List *tlist, List **retrieved_attrs, deparse_expr_cxt *con */ appendStringInfoString(buf, "SELECT "); - if (IS_JOIN_REL(foreignrel) || + if (is_subquery) + { + /* + * For a relation that is deparsed as a subquery, emit expressions + * specified in the relation's reltarget. Note that since this is for + * the subquery, no need to care about *retrieved_attrs. + */ + sqlite_deparse_subquery_target_list(context); + } + else if (IS_JOIN_REL(foreignrel) || fpinfo->is_tlist_func_pushdown == true || IS_UPPER_REL(foreignrel)) { @@ -1317,6 +1338,9 @@ sqlite_deparse_from_expr(List *quals, deparse_expr_cxt *context) { StringInfo buf = context->buf; RelOptInfo *scanrel = context->scanrel; +#if PG_VERSION_NUM >= 170000 + List *additional_conds = NIL; +#endif /* For upper relations, scanrel must be either a joinrel or a baserel */ Assert(!IS_UPPER_REL(context->foreignrel) || @@ -1327,18 +1351,26 @@ sqlite_deparse_from_expr(List *quals, deparse_expr_cxt *context) appendStringInfoString(buf, " FROM "); sqlite_deparse_from_expr_for_rel(buf, context->root, scanrel, (bms_num_members(scanrel->relids) == BMS_MULTIPLE), - (Index) 0, NULL, + (Index) 0, NULL, +#if PG_VERSION_NUM >= 170000 + &additional_conds, +#endif context->params_list); +#if PG_VERSION_NUM >= 170000 + sqlite_append_where_clause(quals, additional_conds, context); + if (additional_conds != NIL) + list_free_deep(additional_conds); +#else /* Construct WHERE clause */ if (quals != NIL) { appendStringInfo(buf, " WHERE "); sqlite_append_conditions(quals, context); } +#endif } - /* * Deparse conditions from the provided list and append them to buf. * @@ -1395,7 +1427,10 @@ sqlite_get_jointype_name(JoinType jointype) case JOIN_FULL: return "FULL"; - +#if PG_VERSION_NUM >= 170000 + case JOIN_SEMI: + return "SEMI"; +#endif default: /* Shouldn't come here, but protect from buggy code. */ elog(ERROR, "unsupported join type %d", jointype); @@ -1440,6 +1475,42 @@ sqlite_deparse_explicit_target_list(List *tlist, List **retrieved_attrs, appendStringInfoString(buf, "NULL"); } +/* + * Emit expressions specified in the given relation's reltarget. + * + * This is used for deparsing the given relation as a subquery. + */ +static void +sqlite_deparse_subquery_target_list(deparse_expr_cxt *context) +{ + StringInfo buf = context->buf; + RelOptInfo *foreignrel = context->foreignrel; + bool first; + ListCell *lc; + int col = 1; + + /* Should only be called in these cases. */ + Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel)); + + first = true; + foreach(lc, foreignrel->reltarget->exprs) + { + Node *node = (Node *) lfirst(lc); + + if (!first) + appendStringInfoString(buf, ", "); + first = false; + + sqlite_deparse_expr((Expr *) node, context); + + appendStringInfo(buf, " AS %s%d", SUBQUERY_COL_ALIAS_PREFIX, col); + col++; + } + + /* Don't generate bad syntax if no expressions */ + if (first) + appendStringInfoString(buf, "NULL"); +} /* * Construct FROM clause for given relation @@ -1447,10 +1518,22 @@ sqlite_deparse_explicit_target_list(List *tlist, List **retrieved_attrs, * The function constructs ... JOIN ... ON ... for join relation. For a base * relation it just returns schema-qualified tablename, with the appropriate * alias if so requested. + * + * 'ignore_rel' is either zero or the RT index of a target relation. In the + * latter case the function constructs FROM clause of UPDATE or USING clause + * of DELETE; it deparses the join relation as if the relation never contained + * the target relation, and creates a List of conditions to be deparsed into + * the top-level WHERE clause, which is returned to *ignore_conds. + * + * 'additional_conds' is a pointer to a list of strings to be appended to + * the WHERE clause, coming from lower-level SEMI-JOINs. */ static void sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, +#if PG_VERSION_NUM >= 170000 + List **additional_conds, +#endif List **params_list) { if (IS_JOIN_REL(foreignrel)) @@ -1462,6 +1545,10 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * RelOptInfo *innerrel = fpinfo->innerrel; bool outerrel_is_target = false; bool innerrel_is_target = false; +#if PG_VERSION_NUM >= 170000 + List *additional_conds_i = NIL; + List *additional_conds_o = NIL; +#endif if (ignore_rel > 0 && bms_is_member(ignore_rel, foreignrel->relids)) { @@ -1492,13 +1579,17 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * innerrel_is_target = true; } - /* Deparse outer relation */ + /* Deparse outer relation if not the target relation. */ if (!outerrel_is_target) { initStringInfo(&join_sql_o); sqlite_deparse_range_tbl_ref(&join_sql_o, root, outerrel, fpinfo->make_outerrel_subquery, - ignore_rel, ignore_conds, params_list); + ignore_rel, ignore_conds, +#if PG_VERSION_NUM >= 170000 + &additional_conds_o, +#endif + params_list); /* * If inner relation is the target relation, skip deparsing it. @@ -1514,18 +1605,76 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * Assert(fpinfo->jointype == JOIN_INNER); Assert(fpinfo->joinclauses == NIL); appendBinaryStringInfo(buf, join_sql_o.data, join_sql_o.len); +#if PG_VERSION_NUM >= 170000 + /* Pass EXISTS conditions to upper level */ + if (additional_conds_o != NIL) + { + Assert(*additional_conds == NIL); + *additional_conds = additional_conds_o; + } +#endif return; } } - /* Deparse inner relation */ + /* Deparse inner relation if not the target relation. */ if (!innerrel_is_target) { initStringInfo(&join_sql_i); sqlite_deparse_range_tbl_ref(&join_sql_i, root, innerrel, fpinfo->make_innerrel_subquery, - ignore_rel, ignore_conds, params_list); + ignore_rel, ignore_conds, +#if PG_VERSION_NUM >= 170000 + &additional_conds_i, +#endif + params_list); +#if PG_VERSION_NUM >= 170000 + /* + * SEMI-JOIN is deparsed as the EXISTS subquery. It references + * outer and inner relations, so it should be evaluated as the + * condition in the upper-level WHERE clause. We deparse the + * condition and pass it to upper level callers as an + * additional_conds list. Upper level callers are responsible for + * inserting conditions from the list where appropriate. + */ + if (fpinfo->jointype == JOIN_SEMI) + { + deparse_expr_cxt context; + StringInfoData str; + + /* Construct deparsed condition from this SEMI-JOIN */ + initStringInfo(&str); + appendStringInfo(&str, "EXISTS (SELECT NULL FROM %s", + join_sql_i.data); + + context.buf = &str; + context.foreignrel = foreignrel; + context.scanrel = foreignrel; + context.root = root; + context.params_list = params_list; + + /* + * Append SEMI-JOIN clauses and EXISTS conditions from lower + * levels to the current EXISTS subquery + */ + sqlite_append_where_clause(fpinfo->joinclauses, additional_conds_i, &context); + /* + * EXISTS conditions, coming from lower join levels, have just + * been processed. + */ + if (additional_conds_i != NIL) + { + list_free_deep(additional_conds_i); + additional_conds_i = NIL; + } + + /* Close parentheses for EXISTS subquery */ + appendStringInfoChar(&str, ')'); + + *additional_conds = lappend(*additional_conds, str.data); + } +#endif /* * If outer relation is the target relation, skip deparsing it. * See the above note about safety. @@ -1535,6 +1684,14 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * Assert(fpinfo->jointype == JOIN_INNER); Assert(fpinfo->joinclauses == NIL); appendBinaryStringInfo(buf, join_sql_i.data, join_sql_i.len); +#if PG_VERSION_NUM >= 170000 + /* Pass EXISTS conditions to the upper call */ + if (additional_conds_i != NIL) + { + Assert(*additional_conds == NIL); + *additional_conds = additional_conds_i; + } +#endif return; } } @@ -1542,33 +1699,70 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * /* Neither of the relations is the target relation. */ Assert(!outerrel_is_target && !innerrel_is_target); +#if PG_VERSION_NUM >= 170000 /* - * For a join relation FROM clause entry is deparsed as ((outer - * relation) (inner relation) ON (joinclauses)) + * For semijoin FROM clause is deparsed as an outer relation. An inner + * relation and join clauses are converted to EXISTS condition and + * passed to the upper level. */ - appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data, - sqlite_get_jointype_name(fpinfo->jointype), join_sql_i.data); - - /* Append join clause; (TRUE) if no join clause */ - if (fpinfo->joinclauses) + if (fpinfo->jointype == JOIN_SEMI) { - deparse_expr_cxt context; + appendBinaryStringInfo(buf, join_sql_o.data, join_sql_o.len); + } + else + { +#endif + /* + * For a join relation FROM clause, entry is deparsed as + * + * ((outer relation) (inner relation) ON + * (joinclauses)) + */ + appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data, + sqlite_get_jointype_name(fpinfo->jointype), join_sql_i.data); - context.buf = buf; - context.foreignrel = foreignrel; - context.scanrel = foreignrel; - context.root = root; - context.params_list = params_list; + /* Append join clause; (TRUE) if no join clause */ + if (fpinfo->joinclauses) + { + deparse_expr_cxt context; + + context.buf = buf; + context.foreignrel = foreignrel; + context.scanrel = foreignrel; + context.root = root; + context.params_list = params_list; - appendStringInfo(buf, "("); - sqlite_append_conditions(fpinfo->joinclauses, &context); + appendStringInfo(buf, "("); + sqlite_append_conditions(fpinfo->joinclauses, &context); + appendStringInfo(buf, ")"); + } + else + appendStringInfoString(buf, "(TRUE)"); + + /* End the FROM clause entry. */ appendStringInfo(buf, ")"); +#if PG_VERSION_NUM >= 170000 + } + + /* + * Construct additional_conds to be passed to the upper caller from + * current level additional_conds and additional_conds, coming from + * inner and outer rels. + */ + if (additional_conds_o != NIL) + { + *additional_conds = list_concat(*additional_conds, + additional_conds_o); + list_free(additional_conds_o); } - else - appendStringInfoString(buf, "(TRUE)"); - /* End the FROM clause entry. */ - appendStringInfo(buf, ")"); + if (additional_conds_i != NIL) + { + *additional_conds = list_concat(*additional_conds, + additional_conds_i); + list_free(additional_conds_i); + } +#endif } else { @@ -1596,10 +1790,15 @@ sqlite_deparse_from_expr_for_rel(StringInfo buf, PlannerInfo *root, RelOptInfo * /* * Append FROM clause entry for the given relation into buf. + * Conditions from lower-level SEMI-JOINs are appended to additional_conds + * and should be added to upper level WHERE clause. */ static void sqlite_deparse_range_tbl_ref(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool make_subquery, Index ignore_rel, List **ignore_conds, +#if PG_VERSION_NUM >= 170000 + List **additional_conds, +#endif List **params_list) { SqliteFdwRelationInfo *fpinfo = (SqliteFdwRelationInfo *) foreignrel->fdw_private; @@ -1613,7 +1812,6 @@ sqlite_deparse_range_tbl_ref(StringInfo buf, PlannerInfo *root, RelOptInfo *fore if (make_subquery) { List *retrieved_attrs; - int ncols; /* * The given relation shouldn't contain the target relation, because @@ -1635,30 +1833,14 @@ sqlite_deparse_range_tbl_ref(StringInfo buf, PlannerInfo *root, RelOptInfo *fore appendStringInfo(buf, " %s%d", SUBQUERY_REL_ALIAS_PREFIX, fpinfo->relation_index); - /* - * Append the column aliases if needed. Note that the subquery emits - * expressions specified in the relation's reltarget (see - * deparseSubqueryTargetList). - */ - ncols = list_length(foreignrel->reltarget->exprs); - if (ncols > 0) - { - int i; - - appendStringInfoChar(buf, '('); - for (i = 1; i <= ncols; i++) - { - if (i > 1) - appendStringInfoString(buf, ", "); - - appendStringInfo(buf, "%s%d", SUBQUERY_COL_ALIAS_PREFIX, i); - } - appendStringInfoChar(buf, ')'); - } } else sqlite_deparse_from_expr_for_rel(buf, root, foreignrel, true, ignore_rel, - ignore_conds, params_list); + ignore_conds, +#if PG_VERSION_NUM >= 170000 + additional_conds, +#endif + params_list); } /* @@ -1900,57 +2082,43 @@ sqlite_deparse_target_list(StringInfo buf, appendStringInfoString(buf, ", '')"); } +#if PG_VERSION_NUM >= 170000 /* - * Deparse WHERE clauses in given list of RestrictInfos and append them to buf. - * - * baserel is the foreign table we're planning for. - * - * If no WHERE clause already exists in the buffer, is_first should be true. - * - * If params is not NULL, it receives a list of Params and other-relation Vars - * used in the clauses; these values must be transmitted to the remote server - * as parameter values. - * - * If params is NULL, we're generating the query for EXPLAIN purposes, - * so Params and other-relation Vars should be replaced by dummy values. + * Append WHERE clause, containing conditions from exprs and additional_conds, + * to context->buf. */ void -sqlite_append_where_clause(StringInfo buf, - PlannerInfo *root, - RelOptInfo *baserel, - List *exprs, - bool is_first, - List **params) -{ - deparse_expr_cxt context; +sqlite_append_where_clause(List *exprs, List *additional_conds, deparse_expr_cxt *context) +{ + StringInfo buf = context->buf; + bool need_and = false; ListCell *lc; - if (params) - *params = NIL; /* initialize result list to empty */ - - /* Set up context struct for recursion */ - context.root = root; - context.foreignrel = baserel; - context.buf = buf; - context.params_list = params; + if (exprs != NIL || additional_conds != NIL) + appendStringInfoString(buf, " WHERE "); - foreach(lc, exprs) + /* + * If there are some filters, append them. + */ + if (exprs != NIL) { - RestrictInfo *ri = (RestrictInfo *) lfirst(lc); + sqlite_append_conditions(exprs, context); + need_and = true; + } - /* Connect expressions with "AND" and parenthesize each condition. */ - if (is_first) - appendStringInfoString(buf, " WHERE "); - else + /* + * If there are some EXISTS conditions, coming from SEMI-JOINS, append + * them. + */ + foreach(lc, additional_conds) + { + if (need_and) appendStringInfoString(buf, " AND "); - - appendStringInfoChar(buf, '('); - sqlite_deparse_expr(ri->clause, &context); - appendStringInfoChar(buf, ')'); - - is_first = false; + appendStringInfoString(buf, (char *) lfirst(lc)); + need_and = true; } } +#endif #if PG_VERSION_NUM >= 140000 /* @@ -2367,6 +2535,9 @@ sqlite_deparse_direct_update_sql(StringInfo buf, PlannerInfo *root, bool first; ListCell *lc; ListCell *lc2; +#if PG_VERSION_NUM >= 170000 + List *additional_conds = NIL; +#endif elog(DEBUG3, "sqlite_fdw : %s\n", __func__); /* Set up context struct for recursion */ @@ -2442,15 +2613,26 @@ sqlite_deparse_direct_update_sql(StringInfo buf, PlannerInfo *root, appendStringInfo(buf, " FROM "); sqlite_deparse_from_expr_for_rel(buf, root, foreignrel, true, rtindex, - &ignore_conds, params_list); + &ignore_conds, +#if PG_VERSION_NUM >= 170000 + &additional_conds, +#endif + params_list); remote_conds = list_concat(remote_conds, ignore_conds); } +#if PG_VERSION_NUM >= 170000 + + sqlite_append_where_clause(remote_conds, additional_conds, &context); + if (additional_conds != NIL) + list_free_deep(additional_conds); +#else if (remote_conds) { appendStringInfoString(buf, " WHERE "); sqlite_append_conditions(remote_conds, &context); } +#endif } /* @@ -2502,7 +2684,9 @@ sqlite_deparse_direct_delete_sql(StringInfo buf, PlannerInfo *root, List **retrieved_attrs) { deparse_expr_cxt context; - +#if PG_VERSION_NUM >= 170000 + List *additional_conds = NIL; +#endif elog(DEBUG1, "sqlite_fdw : %s", __func__); /* Set up context struct for recursion */ @@ -2523,15 +2707,25 @@ sqlite_deparse_direct_delete_sql(StringInfo buf, PlannerInfo *root, appendStringInfo(buf, " USING "); sqlite_deparse_from_expr_for_rel(buf, root, foreignrel, true, rtindex, - &ignore_conds, params_list); + &ignore_conds, +#if PG_VERSION_NUM >= 170000 + &additional_conds, +#endif + params_list); remote_conds = list_concat(remote_conds, ignore_conds); } +#if PG_VERSION_NUM >= 170000 + sqlite_append_where_clause(remote_conds, additional_conds, &context); + if (additional_conds != NIL) + list_free_deep(additional_conds); +#else if (remote_conds) { appendStringInfoString(buf, " WHERE "); sqlite_append_conditions(remote_conds, &context); } +#endif } /* @@ -3380,7 +3574,7 @@ sqlite_deparse_coalesce_expr(CoalesceExpr *node, deparse_expr_cxt *context) * Print the representation of a parameter to be sent to the remote side. * * Note: we always label the Param's type explicitly rather than relying on - * transmitting a numeric type OID in PQexecParams(). This allows us to + * transmitting a numeric type OID in PQsendQueryParams(). This allows us to * avoid assuming that types have the same OIDs on the remote side as they * do locally --- they need only have the same names. */ @@ -3610,13 +3804,12 @@ sqlite_append_order_by_clause(List *pathkeys, bool has_final_sort, deparse_expr_ { ListCell *lcell; int nestlevel; - const char *delim = " "; StringInfo buf = context->buf; + bool gotone = false; /* Make sure any constants in the exprs are printed portably */ nestlevel = sqlite_set_transmission_modes(); - appendStringInfo(buf, " ORDER BY"); foreach(lcell, pathkeys) { PathKey *pathkey = lfirst(lcell); @@ -3647,6 +3840,28 @@ sqlite_append_order_by_clause(List *pathkeys, bool has_final_sort, deparse_expr_ em_expr = em->em_expr; +#if PG_VERSION_NUM >= 170000 + /* + * If the member is a Const expression then we needn't add it to the + * ORDER BY clause. This can happen in UNION ALL queries where the + * union child targetlist has a Const. Adding these would be + * wasteful, but also, for INT columns, an integer literal would be + * seen as an ordinal column position rather than a value to sort by. + * deparseConst() does have code to handle this, but it seems less + * effort on all accounts just to skip these for ORDER BY clauses. + */ + if (IsA(em_expr, Const)) + continue; +#endif + + if (!gotone) + { + appendStringInfoString(buf, " ORDER BY "); + gotone = true; + } + else + appendStringInfoString(buf, ", "); + /* * Lookup the operator corresponding to the strategy in the opclass. * The datatype used by the opfamily is not necessarily the same as @@ -3661,7 +3876,6 @@ sqlite_append_order_by_clause(List *pathkeys, bool has_final_sort, deparse_expr_ pathkey->pk_strategy, em->em_datatype, em->em_datatype, pathkey->pk_opfamily); - appendStringInfoString(buf, delim); sqlite_deparse_expr(em_expr, context); /* * Here we need to use the expression's actual type to discover @@ -3688,7 +3902,6 @@ sqlite_append_order_by_clause(List *pathkeys, bool has_final_sort, deparse_expr_ else if (pathkey->pk_nulls_first && pathkey->pk_strategy != BTLessStrategyNumber) elog(WARNING, "Current Sqlite Version (%d) does not support NULLS FIRST for ORDER BY DESC, degraded emitted query to ORDER BY DESC NULLS LAST (default sqlite behaviour).", sqliteVersion); } - delim = ", "; } sqlite_reset_transmission_modes(nestlevel); } diff --git a/expected/12.16/extra/aggregates.out b/expected/12.16/extra/aggregates.out deleted file mode 100644 index b87287dc..00000000 --- a/expected/12.16/extra/aggregates.out +++ /dev/null @@ -1,3995 +0,0 @@ --- --- AGGREGATES --- ---Testcase 266: -CREATE EXTENSION sqlite_fdw; ---Testcase 267: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 268: -CREATE FOREIGN TABLE onek( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 269: -CREATE FOREIGN TABLE aggtest ( - a int2, - b float4 -) SERVER sqlite_svr; ---Testcase 270: -CREATE FOREIGN TABLE student ( - name text, - age int4, - location point, - gpa float8 -) SERVER sqlite_svr; ---Testcase 271: -CREATE FOREIGN TABLE tenk1 ( - unique1 int4, - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 272: -CREATE FOREIGN TABLE INT8_TBL( - q1 int8 OPTIONS (key 'true'), - q2 int8 OPTIONS (key 'true') -) SERVER sqlite_svr; ---Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 274: -CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; ---Testcase 275: -CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 276: -CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; --- avoid bit-exact output here because operations may not be bit-exact. ---Testcase 588: -SET extra_float_digits = 0; ---Testcase 1: -SELECT avg(four) AS avg_1 FROM onek; - avg_1 -------- - 1.5 -(1 row) - ---Testcase 2: -SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100; - avg_32 ------------------- - 32.6666666666667 -(1 row) - ---Testcase 697: -CREATE FOREIGN TABLE agg_tb(v int, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 698: -INSERT INTO agg_tb(v) VALUES(1), (2), (3); ---Testcase 699: -- Pg 16+ -SELECT any_value(v) FROM agg_tb; -ERROR: function any_value(integer) does not exist -LINE 1: SELECT any_value(v) FROM agg_tb; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 700: -DELETE FROM agg_tb; ---Testcase 701: -INSERT INTO agg_tb(v) VALUES (NULL); ---Testcase 702: -- Pg 16+ -SELECT any_value(v) FROM agg_tb; -ERROR: function any_value(integer) does not exist -LINE 1: SELECT any_value(v) FROM agg_tb; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 703: -DELETE FROM agg_tb; ---Testcase 704: -INSERT INTO agg_tb(v) VALUES (NULL), (1), (2); ---Testcase 705: -- Pg 16+ -SELECT any_value(v) FROM agg_tb; -ERROR: function any_value(integer) does not exist -LINE 1: SELECT any_value(v) FROM agg_tb; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 706: -CREATE FOREIGN TABLE agg_tb2(v text) SERVER sqlite_svr; ---Testcase 707: -INSERT INTO agg_tb2(v) VALUES (array['hello', 'world']); ---Testcase 708: -- Pg 16+ -SELECT any_value(v) FROM agg_tb2; -ERROR: function any_value(text) does not exist -LINE 1: SELECT any_value(v) FROM agg_tb2; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- In 7.1, avg(float4) is computed using float8 arithmetic. ---Testcase 3: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 678: -SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; - avg_107_943 -------------- - 107.943 -(1 row) - ---Testcase 4: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 679: -SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; - avg_3_4 ---------- - 3.400 -(1 row) - ---Testcase 5: -SELECT sum(four) AS sum_1500 FROM onek; - sum_1500 ----------- - 1500 -(1 row) - ---Testcase 6: -SELECT sum(a) AS sum_198 FROM aggtest; - sum_198 ---------- - 198 -(1 row) - ---Testcase 7: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 680: -SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; - avg_431_773 -------------- - 431.773 -(1 row) - ---Testcase 8: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 681: -SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; - avg_6_8 ---------- - 6.800 -(1 row) - ---Testcase 9: -SELECT max(four) AS max_3 FROM onek; - max_3 -------- - 3 -(1 row) - ---Testcase 10: -SELECT max(a) AS max_100 FROM aggtest; - max_100 ---------- - 100 -(1 row) - ---Testcase 11: -SELECT max(aggtest.b) AS max_324_78 FROM aggtest; - max_324_78 ------------- - 324.78 -(1 row) - ---Testcase 12: -SELECT max(student.gpa) AS max_3_7 FROM student; - max_3_7 ---------- - 3.7 -(1 row) - ---Testcase 13: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 682: -SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; - stddev_pop ----------------- - 131.1070323190 -(1 row) - ---Testcase 14: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 683: -SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; - stddev_samp ----------------- - 151.3893608040 -(1 row) - ---Testcase 15: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 684: -SELECT var_pop(b)::numeric(20,10) FROM aggtest; - var_pop ------------------- - 17189.0539234823 -(1 row) - ---Testcase 16: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 685: -SELECT var_samp(b)::numeric(20,10) FROM aggtest; - var_samp ------------------- - 22918.7385646431 -(1 row) - ---Testcase 17: -SELECT stddev_pop(b::numeric) FROM aggtest; - stddev_pop ------------------- - 131.107032862199 -(1 row) - ---Testcase 18: -SELECT stddev_samp(b::numeric) FROM aggtest; - stddev_samp ------------------- - 151.389361431288 -(1 row) - ---Testcase 19: -SELECT var_pop(b::numeric) FROM aggtest; - var_pop --------------------- - 17189.054065929769 -(1 row) - ---Testcase 20: -SELECT var_samp(b::numeric) FROM aggtest; - var_samp --------------------- - 22918.738754573025 -(1 row) - --- population variance is defined for a single tuple, sample variance --- is not ---Testcase 277: -CREATE FOREIGN TABLE agg_t3(a float8, b float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 278: -DELETE FROM agg_t3; ---Testcase 279: -INSERT INTO agg_t3 values (1.0::float8, 2.0::float8); ---Testcase 280: -SELECT var_pop(a), var_samp(b) FROM agg_t3; - var_pop | var_samp ----------+---------- - 0 | -(1 row) - ---Testcase 281: -DELETE FROM agg_t3; ---Testcase 282: -INSERT INTO agg_t3 values (3.0::float8, 4.0::float8); ---Testcase 283: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - ---Testcase 284: -DELETE FROM agg_t3; ---Testcase 285: -INSERT INTO agg_t3 values ('inf'::float8, 'inf'::float8); ---Testcase 286: -SELECT var_pop(a), var_samp(b) FROM agg_t3; - var_pop | var_samp ----------+---------- - NaN | -(1 row) - ---Testcase 287: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - ---Testcase 288: -DELETE FROM agg_t3; ---Testcase 289: -INSERT INTO agg_t3 values ('nan'::float8, 'nan'::float8); ---Testcase 290: -SELECT var_pop(a), var_samp(b) FROM agg_t3; - var_pop | var_samp ----------+---------- - | -(1 row) - ---Testcase 291: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; - stddev_pop | stddev_samp -------------+------------- - | -(1 row) - ---Testcase 292: -CREATE FOREIGN TABLE agg_t4(a float4, b float4, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 293: -DELETE FROM agg_t4; ---Testcase 294: -INSERT INTO agg_t4 values (1.0::float4, 2.0::float4); ---Testcase 295: -SELECT var_pop(a), var_samp(b) FROM agg_t4; - var_pop | var_samp ----------+---------- - 0 | -(1 row) - ---Testcase 296: -DELETE FROM agg_t4; ---Testcase 297: -INSERT INTO agg_t4 values (3.0::float4, 4.0::float4); ---Testcase 298: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - ---Testcase 299: -DELETE FROM agg_t4; ---Testcase 300: -INSERT INTO agg_t4 values ('inf'::float4, 'inf'::float4); ---Testcase 301: -SELECT var_pop(a), var_samp(b) FROM agg_t4; - var_pop | var_samp ----------+---------- - NaN | -(1 row) - ---Testcase 302: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - ---Testcase 303: -DELETE FROM agg_t4; ---Testcase 304: -INSERT INTO agg_t4 values ('nan'::float4, 'nan'::float4); ---Testcase 305: -SELECT var_pop(a), var_samp(b) FROM agg_t4; - var_pop | var_samp ----------+---------- - | -(1 row) - ---Testcase 306: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; - stddev_pop | stddev_samp -------------+------------- - | -(1 row) - ---Testcase 307: -CREATE FOREIGN TABLE agg_t5(a numeric, b numeric, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 308: -DELETE FROM agg_t5; ---Testcase 309: -INSERT INTO agg_t5 values (1.0::numeric, 2.0::numeric); ---Testcase 310: -SELECT var_pop(a), var_samp(b) FROM agg_t5; - var_pop | var_samp ----------+---------- - 0 | -(1 row) - ---Testcase 311: -DELETE FROM agg_t5; ---Testcase 312: -INSERT INTO agg_t5 values (3.0::numeric, 4.0::numeric); ---Testcase 313: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - ---Testcase 597: -DELETE FROM agg_t5; ---Testcase 598: -INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); -ERROR: invalid input syntax for type numeric: "inf" -LINE 1: INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); - ^ ---Testcase 599: -SELECT var_pop(a), var_samp(b) FROM agg_t5; - var_pop | var_samp ----------+---------- - | -(1 row) - ---Testcase 600: -DELETE FROM agg_t5; ---Testcase 601: -INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); -ERROR: invalid input syntax for type numeric: "inf" -LINE 1: INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); - ^ ---Testcase 602: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; - stddev_pop | stddev_samp -------------+------------- - | -(1 row) - ---Testcase 314: -DELETE FROM agg_t5; ---Testcase 315: -INSERT INTO agg_t5 values ('nan'::numeric, 'nan'::numeric); ---Testcase 316: -SELECT var_pop(a), var_samp(b) FROM agg_t5; - var_pop | var_samp ----------+---------- - | -(1 row) - ---Testcase 317: -SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; - stddev_pop | stddev_samp -------------+------------- - | -(1 row) - --- verify correct results for null and NaN inputs ---Testcase 318: -CREATE FOREIGN TABLE agg_t8(a text OPTIONS (key 'true'), b text) SERVER sqlite_svr; ---Testcase 319: -DELETE FROM agg_t8; ---Testcase 320: -INSERT INTO agg_t8 select * from generate_series(1,3); ---Testcase 321: -select sum(null::int4) from agg_t8; - sum ------ - -(1 row) - ---Testcase 322: -select sum(null::int8) from agg_t8; - sum ------ - -(1 row) - ---Testcase 323: -select sum(null::numeric) from agg_t8; - sum ------ - -(1 row) - ---Testcase 324: -select sum(null::float8) from agg_t8; - sum ------ - -(1 row) - ---Testcase 325: -select avg(null::int4) from agg_t8; - avg ------ - -(1 row) - ---Testcase 326: -select avg(null::int8) from agg_t8; - avg ------ - -(1 row) - ---Testcase 327: -select avg(null::numeric) from agg_t8; - avg ------ - -(1 row) - ---Testcase 328: -select avg(null::float8) from agg_t8; - avg ------ - -(1 row) - ---Testcase 329: -select sum('NaN'::numeric) from agg_t8; - sum ------ - 0 -(1 row) - ---Testcase 330: -select avg('NaN'::numeric) from agg_t8; - avg ------ - 0 -(1 row) - --- verify correct results for infinite inputs ---Testcase 331: -DELETE FROM agg_t3; ---Testcase 332: -INSERT INTO agg_t3 VALUES ('1'::float8), ('infinity'::float8); ---Testcase 333: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - ---Testcase 334: -DELETE FROM agg_t3; ---Testcase 335: -INSERT INTO agg_t3 VALUES ('infinity'::float8), ('1'::float8); ---Testcase 336: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - ---Testcase 337: -DELETE FROM agg_t3; ---Testcase 338: -INSERT INTO agg_t3 VALUES ('infinity'::float8), ('infinity'::float8); ---Testcase 339: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - ---Testcase 340: -DELETE FROM agg_t3; ---Testcase 341: -INSERT INTO agg_t3 VALUES ('-infinity'::float8), ('infinity'::float8); ---Testcase 342: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - NaN | NaN | NaN -(1 row) - ---Testcase 603: -DELETE FROM agg_t3; ---Testcase 604: -INSERT INTO agg_t3 VALUES ('-infinity'::float8), ('-infinity'::float8); ---Testcase 605: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------------+-----------+--------- - -Infinity | -Infinity | NaN -(1 row) - ---Testcase 606: -DELETE FROM agg_t3; ---Testcase 607: -- Pg 14+ -INSERT INTO agg_t3 VALUES ('1'::numeric), ('infinity'::numeric); -ERROR: invalid input syntax for type numeric: "infinity" -LINE 1: INSERT INTO agg_t3 VALUES ('1'::numeric), ('infinity'::numer... - ^ ---Testcase 608: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - | | -(1 row) - ---Testcase 609: -DELETE FROM agg_t3; ---Testcase 610: -INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('1'::numeric); -ERROR: invalid input syntax for type numeric: "infinity" -LINE 1: INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('1'::numer... - ^ ---Testcase 611: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - | | -(1 row) - ---Testcase 612: -DELETE FROM agg_t3; ---Testcase 613: -INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('infinity'::numeric); -ERROR: invalid input syntax for type numeric: "infinity" -LINE 1: INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('infinity'... - ^ ---Testcase 614: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - | | -(1 row) - ---Testcase 615: -DELETE FROM agg_t3; ---Testcase 616: -INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('infinity'::numeric); -ERROR: invalid input syntax for type numeric: "-infinity" -LINE 1: INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('infinity... - ^ ---Testcase 617: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - | | -(1 row) - ---Testcase 618: -DELETE FROM agg_t3; ---Testcase 619: -INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('-infinity'::numeric); -ERROR: invalid input syntax for type numeric: "-infinity" -LINE 1: INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('-infinit... - ^ ---Testcase 620: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop ------+-----+--------- - | | -(1 row) - --- test accuracy with a large input offset ---Testcase 343: -CREATE FOREIGN TABLE agg_t6(a float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 344: -DELETE FROM agg_t6; ---Testcase 345: -INSERT INTO agg_t6 VALUES (100000003), (100000004), (100000006), (100000007); ---Testcase 346: -SELECT avg(a), var_pop(a) FROM agg_t6; - avg | var_pop ------------+--------- - 100000005 | 2.5 -(1 row) - ---Testcase 347: -DELETE FROM agg_t6; ---Testcase 348: -INSERT INTO agg_t6 VALUES (7000000000005), (7000000000007); ---Testcase 349: -SELECT avg(a), var_pop(a) FROM agg_t6; - avg | var_pop ----------------+--------- - 7000000000006 | 1 -(1 row) - --- SQL2003 binary aggregates ---Testcase 21: -SELECT regr_count(b, a) FROM aggtest; - regr_count ------------- - 4 -(1 row) - ---Testcase 22: -SELECT regr_sxx(b, a) FROM aggtest; - regr_sxx ----------- - 5099 -(1 row) - ---Testcase 23: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 686: -SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; - regr_syy ------------------- - 68756.2156939293 -(1 row) - ---Testcase 24: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 687: -SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; - regr_sxy ------------------ - 2614.5158215500 -(1 row) - ---Testcase 25: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 688: -SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; - regr_avgx | regr_avgy ------------+---------------- - 49.5 | 107.9431522731 -(1 row) - ---Testcase 26: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 689: -SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; - regr_r2 --------------- - 0.0194977982 -(1 row) - ---Testcase 27: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 690: -SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; - regr_slope | regr_intercept ---------------+---------------- - 0.5127507004 | 82.5619926012 -(1 row) - ---Testcase 28: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 691: -SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; - covar_pop | covar_samp -----------------+---------------- - 653.6289553875 | 871.5052738500 -(1 row) - ---Testcase 29: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 692: -SELECT corr(b, a)::numeric(20,10) FROM aggtest; - corr --------------- - 0.1396345165 -(1 row) - --- check single-tuple behavior ---Testcase 350: -CREATE FOREIGN TABLE agg_t7(a float8, b float8, c float8, d float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 351: -DELETE FROM agg_t7; ---Testcase 352: -INSERT INTO agg_t7 VALUES (1, 2, 3, 4); ---Testcase 353: -SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; - covar_pop | covar_samp ------------+------------ - 0 | -(1 row) - ---Testcase 354: -DELETE FROM agg_t7; ---Testcase 355: -INSERT INTO agg_t7 VALUES (1, 'inf', 3, 'inf'); ---Testcase 356: -SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; - covar_pop | covar_samp ------------+------------ - NaN | -(1 row) - ---Testcase 357: -DELETE FROM agg_t7; ---Testcase 358: -INSERT INTO agg_t7 VALUES (1, 'nan', 3, 'nan'); ---Testcase 359: -SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; - covar_pop | covar_samp ------------+------------ - | -(1 row) - --- test accum and combine functions directly ---Testcase 360: -CREATE FOREIGN TABLE regr_test (x float8, y float8, id int options (key 'true')) SERVER sqlite_svr; ---Testcase 361: -DELETE FROM regr_test; ---Testcase 362: -INSERT INTO regr_test VALUES (10,150),(20,250),(30,350),(80,540),(100,200); ---Testcase 363: -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (10,20,30,80); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+------+----------+---------- - 4 | 140 | 2900 | 1290 | 83075 | 15050 -(1 row) - ---Testcase 364: -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test; - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+------+----------+---------- - 5 | 240 | 6280 | 1490 | 95080 | 8680 -(1 row) - ---Testcase 590: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (10,20,30,80); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: count(*), sum(x), regr_sxx(y, x), sum(y), regr_syy(y, x), regr_sxy(y, x) - -> Foreign Scan on public.regr_test - Output: x, y, id - SQLite query: SELECT sqlite_fdw_float(`x`), sqlite_fdw_float(`y`) FROM main."regr_test" WHERE (sqlite_fdw_float(`x`) IN (10, 20, 30, 80)) -(5 rows) - ---Testcase 591: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test; - QUERY PLAN -------------------------------------------------------------------------------------------------- - Aggregate - Output: count(*), sum(x), regr_sxx(y, x), sum(y), regr_syy(y, x), regr_sxy(y, x) - -> Foreign Scan on public.regr_test - Output: x, y, id - SQLite query: SELECT sqlite_fdw_float(`x`), sqlite_fdw_float(`y`) FROM main."regr_test" -(5 rows) - ---Testcase 365: -CREATE FOREIGN TABLE agg_t15 (a text, b int, c int, id int options (key 'true')) SERVER sqlite_svr; ---Testcase 366: -delete from agg_t15; ---Testcase 367: -insert into agg_t15 values ('{4,140,2900}', 100); ---Testcase 368: -SELECT float8_accum(a::float8[], b) from agg_t15; - float8_accum --------------- - {5,240,6280} -(1 row) - ---Testcase 369: -delete from agg_t15; ---Testcase 370: -insert into agg_t15 values ('{4,140,2900,1290,83075,15050}', 200, 100); ---Testcase 371: -SELECT float8_regr_accum(a::float8[], b, c) from agg_t15; - float8_regr_accum ------------------------------- - {5,240,6280,1490,95080,8680} -(1 row) - ---Testcase 372: -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (10,20,30); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+-----+----------+---------- - 3 | 60 | 200 | 750 | 20000 | 2000 -(1 row) - ---Testcase 373: -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (80,100); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+-----+----------+---------- - 2 | 180 | 200 | 740 | 57800 | -3400 -(1 row) - ---Testcase 374: -CREATE FOREIGN TABLE agg_t16 (a text, b text, id int options (key 'true')) SERVER sqlite_svr; ---Testcase 375: -delete from agg_t16; ---Testcase 376: -insert into agg_t16 values ('{3,60,200}', '{0,0,0}'); ---Testcase 377: -insert into agg_t16 values ('{0,0,0}', '{2,180,200}'); ---Testcase 378: -insert into agg_t16 values ('{3,60,200}', '{2,180,200}'); ---Testcase 379: -SELECT float8_combine(a::float8[], b::float8[]) FROM agg_t16; - float8_combine ----------------- - {3,60,200} - {2,180,200} - {5,240,6280} -(3 rows) - ---Testcase 380: -delete from agg_t16; ---Testcase 381: -insert into agg_t16 values ('{3,60,200,750,20000,2000}', '{0,0,0,0,0,0}'); ---Testcase 382: -insert into agg_t16 values ('{0,0,0,0,0,0}', '{2,180,200,740,57800,-3400}'); ---Testcase 383: -insert into agg_t16 values ('{3,60,200,750,20000,2000}', '{2,180,200,740,57800,-3400}'); ---Testcase 384: -SELECT float8_regr_combine(a::float8[], b::float8[]) FROM agg_t16; - float8_regr_combine ------------------------------- - {3,60,200,750,20000,2000} - {2,180,200,740,57800,-3400} - {5,240,6280,1490,95080,8680} -(3 rows) - ---Testcase 385: -DROP FOREIGN TABLE regr_test; --- test count, distinct ---Testcase 30: -SELECT count(four) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - ---Testcase 31: -SELECT count(DISTINCT four) AS cnt_4 FROM onek; - cnt_4 -------- - 4 -(1 row) - ---Testcase 32: -select ten, count(*), sum(four) from onek -group by ten order by ten; - ten | count | sum ------+-------+----- - 0 | 100 | 100 - 1 | 100 | 200 - 2 | 100 | 100 - 3 | 100 | 200 - 4 | 100 | 100 - 5 | 100 | 200 - 6 | 100 | 100 - 7 | 100 | 200 - 8 | 100 | 100 - 9 | 100 | 200 -(10 rows) - ---Testcase 33: -select ten, count(four), sum(DISTINCT four) from onek -group by ten order by ten; - ten | count | sum ------+-------+----- - 0 | 100 | 2 - 1 | 100 | 4 - 2 | 100 | 2 - 3 | 100 | 4 - 4 | 100 | 2 - 5 | 100 | 4 - 6 | 100 | 2 - 7 | 100 | 4 - 8 | 100 | 2 - 9 | 100 | 4 -(10 rows) - --- user-defined aggregates ---Testcase 386: -CREATE AGGREGATE newavg ( - sfunc = int4_avg_accum, basetype = int4, stype = _int8, - finalfunc = int8_avg, - initcond1 = '{0,0}' -); ---Testcase 387: -CREATE AGGREGATE newsum ( - sfunc1 = int4pl, basetype = int4, stype1 = int4, - initcond1 = '0' -); ---Testcase 388: -CREATE AGGREGATE newcnt (*) ( - sfunc = int8inc, stype = int8, - initcond = '0', parallel = safe -); ---Testcase 389: -CREATE AGGREGATE newcnt ("any") ( - sfunc = int8inc_any, stype = int8, - initcond = '0' -); ---Testcase 390: -CREATE AGGREGATE oldcnt ( - sfunc = int8inc, basetype = 'ANY', stype = int8, - initcond = '0' -); ---Testcase 391: -create function sum3(int8,int8,int8) returns int8 as -'select $1 + $2 + $3' language sql strict immutable; ---Testcase 392: -create aggregate sum2(int8,int8) ( - sfunc = sum3, stype = int8, - initcond = '0' -); ---Testcase 34: -SELECT newavg(four) AS avg_1 FROM onek; - avg_1 --------------------- - 1.5000000000000000 -(1 row) - ---Testcase 35: -SELECT newsum(four) AS sum_1500 FROM onek; - sum_1500 ----------- - 1500 -(1 row) - ---Testcase 36: -SELECT newcnt(four) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - ---Testcase 37: -SELECT newcnt(*) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - ---Testcase 38: -SELECT oldcnt(*) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - ---Testcase 39: -SELECT sum2(q1,q2) FROM int8_tbl; - sum2 -------------------- - 18271560493827981 -(1 row) - --- test for outer-level aggregates --- this should work ---Testcase 40: -select ten, sum(distinct four) from onek a -group by ten -having exists (select 1 from onek b where sum(distinct a.four) = b.four); - ten | sum ------+----- - 0 | 2 - 2 | 2 - 4 | 2 - 6 | 2 - 8 | 2 -(5 rows) - --- this should fail because subquery has an agg of its own in WHERE ---Testcase 41: -select ten, sum(distinct four) from onek a -group by ten -having exists (select 1 from onek b - where sum(distinct a.four + b.four) = b.four); -ERROR: aggregate functions are not allowed in WHERE -LINE 4: where sum(distinct a.four + b.four) = b.four)... - ^ --- Test handling of sublinks within outer-level aggregates. --- Per bug report from Daniel Grace. ---Testcase 42: -select - (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1))) -from tenk1 o; - max ------- - 9999 -(1 row) - --- Test handling of Params within aggregate arguments in hashed aggregation. --- Per bug report from Jeevan Chalke. ---Testcase 393: -explain (verbose, costs off) -select s1, s2, sm -from generate_series(1, 3) s1, - lateral (select s2, sum(s1 + s2) sm - from generate_series(1, 3) s2 group by s2) ss -order by 1, 2; - QUERY PLAN ------------------------------------------------------------------- - Sort - Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) - Sort Key: s1.s1, s2.s2 - -> Nested Loop - Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) - -> Function Scan on pg_catalog.generate_series s1 - Output: s1.s1 - Function Call: generate_series(1, 3) - -> HashAggregate - Output: s2.s2, sum((s1.s1 + s2.s2)) - Group Key: s2.s2 - -> Function Scan on pg_catalog.generate_series s2 - Output: s2.s2 - Function Call: generate_series(1, 3) -(14 rows) - ---Testcase 394: -select s1, s2, sm -from generate_series(1, 3) s1, - lateral (select s2, sum(s1 + s2) sm - from generate_series(1, 3) s2 group by s2) ss -order by 1, 2; - s1 | s2 | sm -----+----+---- - 1 | 1 | 2 - 1 | 2 | 3 - 1 | 3 | 4 - 2 | 1 | 3 - 2 | 2 | 4 - 2 | 3 | 5 - 3 | 1 | 4 - 3 | 2 | 5 - 3 | 3 | 6 -(9 rows) - ---Testcase 395: -explain (verbose, costs off) -select array(select sum(x+y) s - from generate_series(1,3) y group by y order by s) - from generate_series(1,3) x; - QUERY PLAN -------------------------------------------------------------------- - Function Scan on pg_catalog.generate_series x - Output: (SubPlan 1) - Function Call: generate_series(1, 3) - SubPlan 1 - -> Sort - Output: (sum((x.x + y.y))), y.y - Sort Key: (sum((x.x + y.y))) - -> HashAggregate - Output: sum((x.x + y.y)), y.y - Group Key: y.y - -> Function Scan on pg_catalog.generate_series y - Output: y.y - Function Call: generate_series(1, 3) -(13 rows) - ---Testcase 396: -select array(select sum(x+y) s - from generate_series(1,3) y group by y order by s) - from generate_series(1,3) x; - array ---------- - {2,3,4} - {3,4,5} - {4,5,6} -(3 rows) - --- --- test for bitwise integer aggregates --- ---Testcase 397: -CREATE FOREIGN TABLE bitwise_test( - i2 INT2, - i4 INT4, - i8 INT8, - i INTEGER, - x INT2 -) SERVER sqlite_svr; --- empty case ---Testcase 43: -SELECT - BIT_AND(i2) AS "?", - BIT_OR(i4) AS "?", - BIT_XOR(i8) AS "?" -FROM bitwise_test; -ERROR: function bit_xor(bigint) does not exist -LINE 4: BIT_XOR(i8) AS "?" - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 44: -INSERT INTO bitwise_test VALUES - (1, 1, 1, 1, 1), - (3, 3, 3, null, 2), - (7, 7, 7, 3, 4); ---Testcase 45: -- bit_xor Pg 14+ -SELECT - BIT_AND(i2) AS "1", - BIT_AND(i4) AS "1", - BIT_AND(i8) AS "1", - BIT_AND(i) AS "?", - BIT_AND(x) AS "0", - BIT_OR(i2) AS "7", - BIT_OR(i4) AS "7", - BIT_OR(i8) AS "7", - BIT_OR(i) AS "?", - BIT_OR(x) AS "7", - BIT_XOR(i2) AS "5", - BIT_XOR(i4) AS "5", - BIT_XOR(i8) AS "5", - BIT_XOR(i) AS "?", - BIT_XOR(x) AS "7" -FROM bitwise_test; -ERROR: function bit_xor(smallint) does not exist -LINE 12: BIT_XOR(i2) AS "5", - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- --- test boolean aggregates --- --- first test all possible transition and final states ---Testcase 398: -CREATE FOREIGN TABLE bool_test_tmp( - b1 BOOL OPTIONS (key 'true'), - b2 BOOL OPTIONS (key 'true') -) SERVER sqlite_svr; --- boolean and transitions --- null because strict -BEGIN; ---Testcase 399: -INSERT INTO bool_test_tmp VALUES - (NULL, NULL), - (TRUE, NULL), - (FALSE, NULL), - (NULL, TRUE), - (NULL, FALSE); ---Testcase 400: -SELECT booland_statefunc(b1, b2) IS NULL as "t" FROM bool_test_tmp; - t ---- - t - t - t - t - t -(5 rows) - -ROLLBACK; --- and actual computations -BEGIN; ---Testcase 401: -INSERT INTO bool_test_tmp VALUES - (TRUE, TRUE); ---Testcase 402: -SELECT booland_statefunc(b1, b2) as "t" FROM bool_test_tmp; - t ---- - t -(1 row) - -ROLLBACK; -BEGIN; ---Testcase 403: -INSERT INTO bool_test_tmp VALUES - (TRUE, FALSE), - (FALSE, TRUE), - (FALSE, FALSE); ---Testcase 404: -SELECT NOT booland_statefunc(b1, b2) as "t" FROM bool_test_tmp; - t ---- - t - t - t -(3 rows) - -ROLLBACK; --- boolean or transitions --- null because strict -BEGIN; ---Testcase 405: -INSERT INTO bool_test_tmp VALUES - (NULL, NULL), - (TRUE, NULL), - (FALSE, NULL), - (NULL, TRUE), - (NULL, FALSE); ---Testcase 406: -SELECT boolor_statefunc(b1, b2) IS NULL as "t" FROM bool_test_tmp; - t ---- - t - t - t - t - t -(5 rows) - -ROLLBACK; --- actual computations -BEGIN; ---Testcase 407: -INSERT INTO bool_test_tmp VALUES - (TRUE, TRUE), - (TRUE, FALSE), - (FALSE, TRUE); ---Testcase 408: -SELECT boolor_statefunc(b1, b2) as "t" FROM bool_test_tmp; - t ---- - t - t - t -(3 rows) - -ROLLBACK; -BEGIN; ---Testcase 409: -INSERT INTO bool_test_tmp VALUES - (FALSE, FALSE); ---Testcase 410: -SELECT NOT boolor_statefunc(b1, b2) as "t" FROM bool_test_tmp; - t ---- - t -(1 row) - -ROLLBACK; ---Testcase 411: -CREATE FOREIGN TABLE bool_test( - b1 BOOL, - b2 BOOL, - b3 BOOL, - b4 BOOL -) SERVER sqlite_svr; --- empty case ---Testcase 46: -SELECT - BOOL_AND(b1) AS "n", - BOOL_OR(b3) AS "n" -FROM bool_test; - n | n ----+--- - | -(1 row) - ---Testcase 47: -INSERT INTO bool_test VALUES - (TRUE, null, FALSE, null), - (FALSE, TRUE, null, null), - (null, TRUE, FALSE, null); ---Testcase 48: -SELECT - BOOL_AND(b1) AS "f", - BOOL_AND(b2) AS "t", - BOOL_AND(b3) AS "f", - BOOL_AND(b4) AS "n", - BOOL_AND(NOT b2) AS "f", - BOOL_AND(NOT b3) AS "t" -FROM bool_test; - f | t | f | n | f | t ----+---+---+---+---+--- - f | t | f | | f | t -(1 row) - ---Testcase 49: -SELECT - EVERY(b1) AS "f", - EVERY(b2) AS "t", - EVERY(b3) AS "f", - EVERY(b4) AS "n", - EVERY(NOT b2) AS "f", - EVERY(NOT b3) AS "t" -FROM bool_test; - f | t | f | n | f | t ----+---+---+---+---+--- - f | t | f | | f | t -(1 row) - ---Testcase 50: -SELECT - BOOL_OR(b1) AS "t", - BOOL_OR(b2) AS "t", - BOOL_OR(b3) AS "f", - BOOL_OR(b4) AS "n", - BOOL_OR(NOT b2) AS "f", - BOOL_OR(NOT b3) AS "t" -FROM bool_test; - t | t | f | n | f | t ----+---+---+---+---+--- - t | t | f | | f | t -(1 row) - --- --- Test cases that should be optimized into indexscans instead of --- the generic aggregate implementation. --- --- Basic cases ---Testcase 51: -explain (costs off) - select min(unique1) from tenk1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 52: -select min(unique1) from tenk1; - min ------ - 0 -(1 row) - ---Testcase 53: -explain (costs off) - select max(unique1) from tenk1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 54: -select max(unique1) from tenk1; - max ------- - 9999 -(1 row) - ---Testcase 55: -explain (costs off) - select max(unique1) from tenk1 where unique1 < 42; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 56: -select max(unique1) from tenk1 where unique1 < 42; - max ------ - 41 -(1 row) - ---Testcase 57: -explain (costs off) - select max(unique1) from tenk1 where unique1 > 42; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 58: -select max(unique1) from tenk1 where unique1 > 42; - max ------- - 9999 -(1 row) - --- the planner may choose a generic aggregate here if parallel query is --- enabled, since that plan will be parallel safe and the "optimized" --- plan, which has almost identical cost, will not be. we want to test --- the optimized plan, so temporarily disable parallel query. -begin; ---Testcase 628: -set local max_parallel_workers_per_gather = 0; ---Testcase 59: -explain (costs off) - select max(unique1) from tenk1 where unique1 > 42000; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 60: -select max(unique1) from tenk1 where unique1 > 42000; - max ------ - -(1 row) - -rollback; --- multi-column index (uses tenk1_thous_tenthous) ---Testcase 61: -explain (costs off) - select max(tenthous) from tenk1 where thousand = 33; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 62: -select max(tenthous) from tenk1 where thousand = 33; - max ------- - 9033 -(1 row) - ---Testcase 63: -explain (costs off) - select min(tenthous) from tenk1 where thousand = 33; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 64: -select min(tenthous) from tenk1 where thousand = 33; - min ------ - 33 -(1 row) - --- check parameter propagation into an indexscan subquery ---Testcase 65: -explain (costs off) - select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt - from int4_tbl; - QUERY PLAN --------------------------- - Foreign Scan on int4_tbl - SubPlan 1 - -> Foreign Scan -(3 rows) - ---Testcase 66: -select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt - from int4_tbl; - f1 | gt --------------+---- - 0 | 1 - 123456 | - -123456 | 0 - 2147483647 | - -2147483647 | 0 -(5 rows) - --- check some cases that were handled incorrectly in 8.3.0 ---Testcase 67: -explain (costs off) - select distinct max(unique2) from tenk1; - QUERY PLAN ----------------------------------- - Unique - -> Sort - Sort Key: (max(unique2)) - -> Foreign Scan -(4 rows) - ---Testcase 68: -select distinct max(unique2) from tenk1; - max ------- - 9999 -(1 row) - ---Testcase 69: -explain (costs off) - select max(unique2) from tenk1 order by 1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 70: -select max(unique2) from tenk1 order by 1; - max ------- - 9999 -(1 row) - ---Testcase 71: -explain (costs off) - select max(unique2) from tenk1 order by max(unique2); - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 72: -select max(unique2) from tenk1 order by max(unique2); - max ------- - 9999 -(1 row) - ---Testcase 73: -explain (costs off) - select max(unique2) from tenk1 order by max(unique2)+1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 74: -select max(unique2) from tenk1 order by max(unique2)+1; - max ------- - 9999 -(1 row) - ---Testcase 75: -explain (costs off) - select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; - QUERY PLAN ------------------------------------------- - Sort - Sort Key: (generate_series(1, 3)) DESC - -> ProjectSet - -> Foreign Scan -(4 rows) - ---Testcase 76: -select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; - max | g -------+--- - 9999 | 3 - 9999 | 2 - 9999 | 1 -(3 rows) - --- interesting corner case: constant gets optimized into a seqscan ---Testcase 77: -explain (costs off) - select max(100) from tenk1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 78: -select max(100) from tenk1; - max ------ - 100 -(1 row) - --- try it on an inheritance tree ---Testcase 412: -create foreign table minmaxtest(f1 int) server sqlite_svr; ---Testcase 413: -create table minmaxtest1() inherits (minmaxtest); ---Testcase 414: -create table minmaxtest2() inherits (minmaxtest); ---Testcase 415: -create table minmaxtest3() inherits (minmaxtest); ---Testcase 416: -create index minmaxtest1i on minmaxtest1(f1); ---Testcase 417: -create index minmaxtest2i on minmaxtest2(f1 desc); ---Testcase 418: -create index minmaxtest3i on minmaxtest3(f1) where f1 is not null; ---Testcase 79: -insert into minmaxtest values(11), (12); ---Testcase 80: -insert into minmaxtest1 values(13), (14); ---Testcase 81: -insert into minmaxtest2 values(15), (16); ---Testcase 82: -insert into minmaxtest3 values(17), (18); ---Testcase 83: -explain (costs off) - select min(f1), max(f1) from minmaxtest; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Result - InitPlan 1 (returns $0) - -> Limit - -> Merge Append - Sort Key: minmaxtest.f1 - -> Foreign Scan on minmaxtest - -> Index Only Scan using minmaxtest1i on minmaxtest1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest3i on minmaxtest3 - InitPlan 2 (returns $1) - -> Limit - -> Merge Append - Sort Key: minmaxtest_1.f1 DESC - -> Foreign Scan on minmaxtest minmaxtest_1 - -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest1_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest2_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1 -(21 rows) - ---Testcase 84: -select min(f1), max(f1) from minmaxtest; - min | max ------+----- - 11 | 18 -(1 row) - --- DISTINCT doesn't do anything useful here, but it shouldn't fail ---Testcase 85: -explain (costs off) - select distinct min(f1), max(f1) from minmaxtest; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Unique - InitPlan 1 (returns $0) - -> Limit - -> Merge Append - Sort Key: minmaxtest.f1 - -> Foreign Scan on minmaxtest - -> Index Only Scan using minmaxtest1i on minmaxtest1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest3i on minmaxtest3 - InitPlan 2 (returns $1) - -> Limit - -> Merge Append - Sort Key: minmaxtest_1.f1 DESC - -> Foreign Scan on minmaxtest minmaxtest_1 - -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest1_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest2_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1 - -> Sort - Sort Key: ($0), ($1) - -> Result -(24 rows) - ---Testcase 86: -select distinct min(f1), max(f1) from minmaxtest; - min | max ------+----- - 11 | 18 -(1 row) - --- check for correct detection of nested-aggregate errors ---Testcase 87: -select max(min(unique1)) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select max(min(unique1)) from tenk1; - ^ ---Testcase 88: -select (select max(min(unique1)) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1; - ^ -select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) - from tenk1 a1(col1))) -from tenk1 a2(col2); -ERROR: aggregate function calls cannot be nested -LINE 1: select avg((select avg(a1.col1 order by (select avg(a2.col2)... - ^ --- --- Test removal of redundant GROUP BY columns --- ---Testcase 419: -create foreign table agg_t1 (a int OPTIONS (key 'true'), b int OPTIONS (key 'true'), c int, d int) server sqlite_svr; ---Testcase 420: -create foreign table agg_t2 (x int OPTIONS (key 'true'), y int OPTIONS (key 'true'), z int) server sqlite_svr; ---Testcase 421: -create foreign table agg_t9 (a int OPTIONS (key 'true'), b int OPTIONS (key 'true'), c int) server sqlite_svr; --- Non-primary-key columns can be removed from GROUP BY ---Testcase 89: -explain (costs off) select * from agg_t1 group by a,b,c,d; - QUERY PLAN --------------- - Foreign Scan -(1 row) - --- No removal can happen if the complete PK is not present in GROUP BY ---Testcase 90: -explain (costs off) select a,c from agg_t1 group by a,c,d; - QUERY PLAN --------------- - Foreign Scan -(1 row) - --- Test removal across multiple relations ---Testcase 91: -explain (costs off) select * -from agg_t1 inner join agg_t2 on agg_t1.a = agg_t2.x and agg_t1.b = agg_t2.y -group by agg_t1.a,agg_t1.b,agg_t1.c,agg_t1.d,agg_t2.x,agg_t2.y,agg_t2.z; - QUERY PLAN --------------- - Foreign Scan -(1 row) - --- Test case where agg_t1 can be optimized but not agg_t2 ---Testcase 92: -explain (costs off) select agg_t1.*,agg_t2.x,agg_t2.z -from agg_t1 inner join agg_t2 on agg_t1.a = agg_t2.x and agg_t1.b = agg_t2.y -group by agg_t1.a,agg_t1.b,agg_t1.c,agg_t1.d,agg_t2.x,agg_t2.z; - QUERY PLAN --------------- - Foreign Scan -(1 row) - --- Cannot optimize when PK is deferrable ---Testcase 422: -explain (costs off) select * from agg_t9 group by a,b,c; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 423: -create temp table t1c () inherits (agg_t1); --- Ensure we don't remove any columns when t1 has a child table ---Testcase 424: -explain (costs off) select * from agg_t1 group by a,b,c,d; - QUERY PLAN ------------------------------------------------------ - HashAggregate - Group Key: agg_t1.a, agg_t1.b, agg_t1.c, agg_t1.d - -> Append - -> Foreign Scan on agg_t1 - -> Seq Scan on t1c -(5 rows) - --- Okay to remove columns if we're only querying the parent. ---Testcase 425: -explain (costs off) select * from only agg_t1 group by a,b,c,d; - QUERY PLAN --------------- - Foreign Scan -(1 row) - --- Skip this test, sqlite_fdw does not support partition table ---create foreign table p_t1 ( --- a int options (key 'true'), --- b int options (key 'true'), --- c int, --- d int, ---) partition by list(a) server sqlite_svr; ---create temp table p_t1_1 partition of p_t1 for values in(1); ---create temp table p_t1_2 partition of p_t1 for values in(2); --- Ensure we can remove non-PK columns for partitioned tables. ---explain (costs off) select * from p_t1 group by a,b,c,d; ---drop table t1 cascade; ---drop table t2; ---drop table t3; ---drop table p_t1; --- --- Test GROUP BY matching of join columns that are type-coerced due to USING --- ---Testcase 426: -create foreign table t1(f1 int, f2 int) server sqlite_svr; ---Testcase 427: -create foreign table t2(f1 bigint, f2 oid) server sqlite_svr; ---Testcase 428: -select f1 from t1 left join t2 using (f1) group by f1; - f1 ----- -(0 rows) - ---Testcase 429: -select f1 from t1 left join t2 using (f1) group by t1.f1; - f1 ----- -(0 rows) - ---Testcase 430: -select t1.f1 from t1 left join t2 using (f1) group by t1.f1; - f1 ----- -(0 rows) - --- only this one should fail: ---Testcase 431: -select t1.f1 from t1 left join t2 using (f1) group by f1; -ERROR: column "t1.f1" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: select t1.f1 from t1 left join t2 using (f1) group by f1; - ^ --- check case where we have to inject nullingrels into coerced join alias -select f1, count(*) from -t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) -group by f1; - f1 | count -----+------- -(0 rows) - --- same, for a RelabelType coercion -select f2, count(*) from -t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) -group by f2; - f2 | count -----+------- -(0 rows) - ---Testcase 432: -drop foreign table t1, t2; --- --- Test planner's selection of pathkeys for ORDER BY aggregates --- --- Ensure we order by four. This suits the most aggregate functions. -explain (costs off) -select sum(two order by two),max(four order by four), min(four order by four) -from tenk1; - QUERY PLAN ------------------------------ - Aggregate - -> Foreign Scan on tenk1 -(2 rows) - --- Ensure we order by two. It's a tie between ordering by two and four but --- we tiebreak on the aggregate's position. -explain (costs off) -select - sum(two order by two), max(four order by four), - min(four order by four), max(two order by two) -from tenk1; - QUERY PLAN ------------------------------ - Aggregate - -> Foreign Scan on tenk1 -(2 rows) - --- Similar to above, but tiebreak on ordering by four -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two) -from tenk1; - QUERY PLAN ------------------------------ - Aggregate - -> Foreign Scan on tenk1 -(2 rows) - --- Ensure this one orders by ten since there are 3 aggregates that require ten --- vs two that suit two and four. -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two), - sum(ten order by ten), min(ten order by ten), max(ten order by ten) -from tenk1; - QUERY PLAN ------------------------------ - Aggregate - -> Foreign Scan on tenk1 -(2 rows) - --- Try a case involving a GROUP BY clause where the GROUP BY column is also --- part of an aggregate's ORDER BY clause. We want a sort order that works --- for the GROUP BY along with the first and the last aggregate. -explain (costs off) -select - sum(unique1 order by ten, two), sum(unique1 order by four), - sum(unique1 order by two, four) -from tenk1 -group by ten; - QUERY PLAN ------------------------------ - GroupAggregate - Group Key: ten - -> Foreign Scan on tenk1 -(3 rows) - --- Ensure that we never choose to provide presorted input to an Aggref with --- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure --- these sorts are performed individually rather than at the query level. -explain (costs off) -select - sum(unique1 order by two), sum(unique1 order by four), - sum(unique1 order by four, two), sum(unique1 order by two, random()), - sum(unique1 order by two, random(), random() + 1) -from tenk1 -group by ten; - QUERY PLAN ------------------------------ - GroupAggregate - Group Key: ten - -> Foreign Scan on tenk1 -(3 rows) - --- Ensure consecutive NULLs are properly treated as distinct from each other -select array_agg(distinct val) -from (select null as val from generate_series(1, 2)) g; - array_agg ------------ - {NULL} -(1 row) - --- Ensure no ordering is requested when enable_presorted_aggregate is off -set enable_presorted_aggregate to off; -ERROR: unrecognized configuration parameter "enable_presorted_aggregate" -explain (costs off) -select sum(two order by two) from tenk1; - QUERY PLAN ------------------------------ - Aggregate - -> Foreign Scan on tenk1 -(2 rows) - -reset enable_presorted_aggregate; -ERROR: unrecognized configuration parameter "enable_presorted_aggregate" --- --- Test combinations of DISTINCT and/or ORDER BY --- -begin; ---Testcase 93: -delete from INT8_TBL; ---Testcase 94: -insert into INT8_TBL values (1,4),(2,3),(3,1),(4,2); ---Testcase 95: -select array_agg(q1 order by q2) - from INT8_TBL; - array_agg ------------ - {3,4,2,1} -(1 row) - ---Testcase 96: -select array_agg(q1 order by q1) - from INT8_TBL; - array_agg ------------ - {1,2,3,4} -(1 row) - ---Testcase 97: -select array_agg(q1 order by q1 desc) - from INT8_TBL; - array_agg ------------ - {4,3,2,1} -(1 row) - ---Testcase 98: -select array_agg(q2 order by q1 desc) - from INT8_TBL; - array_agg ------------ - {2,1,3,4} -(1 row) - ---Testcase 99: -delete from INT4_TBL; ---Testcase 100: -insert into INT4_TBL values (1),(2),(1),(3),(null),(2); ---Testcase 101: -select array_agg(distinct f1) - from INT4_TBL; - array_agg --------------- - {1,2,3,NULL} -(1 row) - ---Testcase 102: -select array_agg(distinct f1 order by f1) - from INT4_TBL; - array_agg --------------- - {1,2,3,NULL} -(1 row) - ---Testcase 103: -select array_agg(distinct f1 order by f1 desc) - from INT4_TBL; - array_agg --------------- - {NULL,3,2,1} -(1 row) - ---Testcase 104: -select array_agg(distinct f1 order by f1 desc nulls last) - from INT4_TBL; - array_agg --------------- - {3,2,1,NULL} -(1 row) - -rollback; --- multi-arg aggs, strict/nonstrict, distinct/order by ---Testcase 433: -create type aggtype as (a integer, b integer, c text); ---Testcase 434: -create function aggf_trans(aggtype[],integer,integer,text) returns aggtype[] -as 'select array_append($1,ROW($2,$3,$4)::aggtype)' -language sql strict immutable; ---Testcase 435: -create function aggfns_trans(aggtype[],integer,integer,text) returns aggtype[] -as 'select array_append($1,ROW($2,$3,$4)::aggtype)' -language sql immutable; ---Testcase 436: -create aggregate aggfstr(integer,integer,text) ( - sfunc = aggf_trans, stype = aggtype[], - initcond = '{}' -); ---Testcase 437: -create aggregate aggfns(integer,integer,text) ( - sfunc = aggfns_trans, stype = aggtype[], sspace = 10000, - initcond = '{}' -); -begin; ---Testcase 105: -insert into multi_arg_agg values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz'); ---Testcase 106: -select aggfstr(a,b,c) from multi_arg_agg; - aggfstr ---------------------------------------- - {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 107: -select aggfns(a,b,c) from multi_arg_agg; - aggfns ------------------------------------------------ - {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 108: -select aggfstr(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; - aggfstr ---------------------------------------- - {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 109: -select aggfns(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 110: -select aggfstr(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; - aggfstr ---------------------------------------- - {"(3,1,baz)","(2,2,bar)","(1,3,foo)"} -(1 row) - ---Testcase 111: -select aggfns(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - --- test specific code paths ---Testcase 112: -select aggfns(distinct a,a,c order by c using ~<~,a) from multi_arg_agg, generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} -(1 row) - ---Testcase 113: -select aggfns(distinct a,a,c order by c using ~<~) from multi_arg_agg, generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} -(1 row) - ---Testcase 114: -select aggfns(distinct a,a,c order by a) from multi_arg_agg, generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(0,0,)","(1,1,foo)","(2,2,bar)","(3,3,baz)"} -(1 row) - ---Testcase 115: -select aggfns(distinct a,b,c order by a,c using ~<~,b) from multi_arg_agg, generate_series(1,2) i; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - --- check node I/O via view creation and usage, also deparsing logic ---Testcase 438: -create view agg_view1 as - select aggfns(a,b,c) from multi_arg_agg; ---Testcase 116: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 117: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ------------------------------------------------------------------------------ - SELECT aggfns(multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c) AS aggfns+ - FROM multi_arg_agg; -(1 row) - ---Testcase 439: -create or replace view agg_view1 as - select aggfns(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; ---Testcase 118: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 119: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef --------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c) AS aggfns+ - FROM multi_arg_agg, + - generate_series(1, 3) i(i); -(1 row) - ---Testcase 440: -create or replace view agg_view1 as - select aggfns(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; ---Testcase 120: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - ---Testcase 121: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY multi_arg_agg.b) AS aggfns+ - FROM multi_arg_agg, + - generate_series(1, 3) i(i); -(1 row) - ---Testcase 441: -create or replace view agg_view1 as - select aggfns(a,b,c order by b+1) from multi_arg_agg; ---Testcase 122: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - ---Testcase 123: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ------------------------------------------------------------------------------------------------------------- - SELECT aggfns(multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY (multi_arg_agg.b + 1)) AS aggfns+ - FROM multi_arg_agg; -(1 row) - ---Testcase 442: -create or replace view agg_view1 as - select aggfns(a,a,c order by b) from multi_arg_agg; ---Testcase 124: -select * from agg_view1; - aggfns ------------------------------------------------- - {"(3,3,baz)","(2,2,bar)","(1,1,foo)","(0,0,)"} -(1 row) - ---Testcase 125: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ------------------------------------------------------------------------------------------------------- - SELECT aggfns(multi_arg_agg.a, multi_arg_agg.a, multi_arg_agg.c ORDER BY multi_arg_agg.b) AS aggfns+ - FROM multi_arg_agg; -(1 row) - ---Testcase 443: -create or replace view agg_view1 as - select aggfns(a,b,c order by c using ~<~) from multi_arg_agg; ---Testcase 126: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(2,2,bar)","(3,1,baz)","(1,3,foo)","(0,,)"} -(1 row) - ---Testcase 127: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY multi_arg_agg.c USING ~<~ NULLS LAST) AS aggfns+ - FROM multi_arg_agg; -(1 row) - ---Testcase 444: -create or replace view agg_view1 as - select aggfns(distinct a,b,c order by a,c using ~<~,b) from multi_arg_agg, generate_series(1,2) i; ---Testcase 128: -select * from agg_view1; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - ---Testcase 129: -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY multi_arg_agg.a, multi_arg_agg.c USING ~<~ NULLS LAST, multi_arg_agg.b) AS aggfns+ - FROM multi_arg_agg, + - generate_series(1, 2) i(i); -(1 row) - ---Testcase 445: -drop view agg_view1; -rollback; --- incorrect DISTINCT usage errors ---Testcase 130: -insert into multi_arg_agg values (1,1,'foo'); ---Testcase 131: -select aggfns(distinct a,b,c order by i) from multi_arg_agg, generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by i) from multi_arg_agg,... - ^ ---Testcase 132: -select aggfns(distinct a,b,c order by a,b+1) from multi_arg_agg, generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by a,b+1) from multi_arg_... - ^ ---Testcase 133: -select aggfns(distinct a,b,c order by a,b,i,c) from multi_arg_agg, generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by a,b,i,c) from multi_ar... - ^ ---Testcase 134: -select aggfns(distinct a,a,c order by a,b) from multi_arg_agg, generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,a,c order by a,b) from multi_arg_ag... - ^ --- string_agg tests -begin; ---Testcase 135: -delete from varchar_tbl; ---Testcase 136: -insert into varchar_tbl values ('aaaa'),('bbbb'),('cccc'); ---Testcase 137: -select string_agg(f1,',') from varchar_tbl; - string_agg ----------------- - aaaa,bbbb,cccc -(1 row) - ---Testcase 138: -delete from varchar_tbl; ---Testcase 139: -insert into varchar_tbl values ('aaaa'),(null),('bbbb'),('cccc'); ---Testcase 140: -select string_agg(f1,',') from varchar_tbl; - string_agg ----------------- - aaaa,bbbb,cccc -(1 row) - ---Testcase 141: -delete from varchar_tbl; ---Testcase 142: -insert into varchar_tbl values (null),(null),('bbbb'),('cccc'); ---Testcase 143: -select string_agg(f1,'AB') from varchar_tbl; - string_agg ------------- - bbbbABcccc -(1 row) - ---Testcase 144: -delete from varchar_tbl; ---Testcase 145: -insert into varchar_tbl values (null),(null); ---Testcase 146: -select string_agg(f1,',') from varchar_tbl; - string_agg ------------- - -(1 row) - -rollback; --- check some implicit casting cases, as per bug #5564 ---Testcase 147: -select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok - string_agg ------------- - a,ab,abcd -(1 row) - ---Testcase 148: -select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select string_agg(distinct f1::text, ',' order by f1) from v... - ^ ---Testcase 149: -select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select string_agg(distinct f1, ',' order by f1::text) from v... - ^ ---Testcase 150: -select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok - string_agg ------------- - a,ab,abcd -(1 row) - --- string_agg bytea tests ---Testcase 446: -create foreign table bytea_test_table(v bytea) server sqlite_svr; ---Testcase 151: -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - -(1 row) - ---Testcase 152: -insert into bytea_test_table values(decode('ff','hex')); ---Testcase 153: -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - \xff -(1 row) - ---Testcase 154: -insert into bytea_test_table values(decode('aa','hex')); ---Testcase 155: -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - \xffaa -(1 row) - ---Testcase 156: -select string_agg(v, NULL) from bytea_test_table; - string_agg ------------- - \xffaa -(1 row) - ---Testcase 157: -select string_agg(v, decode('ee', 'hex')) from bytea_test_table; - string_agg ------------- - \xffeeaa -(1 row) - ---Testcase 447: -drop foreign table bytea_test_table; --- Test parallel string_agg and array_agg -create foreign table pagg_test (x int, y int) server sqlite_svr; -insert into pagg_test -select (case x % 4 when 1 then null else x end), x % 10 -from generate_series(1,5000) x; -set parallel_setup_cost TO 0; -set parallel_tuple_cost TO 0; -set parallel_leader_participation TO 0; -set min_parallel_table_scan_size = 0; -set bytea_output = 'escape'; -set max_parallel_workers_per_gather = 2; --- create a view as we otherwise have to repeat this query a few times. -create view v_pagg_test AS -select - y, - min(t) AS tmin,max(t) AS tmax,count(distinct t) AS tndistinct, - min(b) AS bmin,max(b) AS bmax,count(distinct b) AS bndistinct, - min(a) AS amin,max(a) AS amax,count(distinct a) AS andistinct, - min(aa) AS aamin,max(aa) AS aamax,count(distinct aa) AS aandistinct -from ( - select - y, - unnest(regexp_split_to_array(a1.t, ','))::int AS t, - unnest(regexp_split_to_array(a1.b::text, ',')) AS b, - unnest(a1.a) AS a, - unnest(a1.aa) AS aa - from ( - select - y, - string_agg(x::text, ',') AS t, - string_agg(x::text::bytea, ',') AS b, - array_agg(x) AS a, - array_agg(ARRAY[x]) AS aa - from pagg_test - group by y - ) a1 -) a2 -group by y; --- Ensure results are correct. -select * from v_pagg_test order by y; - y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ----+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- - 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 - 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 - 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 - 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 - 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 - 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 - 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 - 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 - 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 - 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 -(10 rows) - --- Ensure parallel aggregation is actually being used. -explain (costs off) select * from v_pagg_test order by y; - QUERY PLAN ---------------------------------------------------------- - GroupAggregate - Group Key: pagg_test.y - -> Sort - Sort Key: pagg_test.y - -> Result - -> ProjectSet - -> GroupAggregate - Group Key: pagg_test.y - -> Foreign Scan on pagg_test -(9 rows) - -set max_parallel_workers_per_gather = 0; --- Ensure results are the same without parallel aggregation. -select * from v_pagg_test order by y; - y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ----+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- - 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 - 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 - 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 - 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 - 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 - 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 - 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 - 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 - 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 - 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 -(10 rows) - --- Clean up -reset max_parallel_workers_per_gather; -reset bytea_output; -reset min_parallel_table_scan_size; -reset parallel_leader_participation; -reset parallel_tuple_cost; -reset parallel_setup_cost; -drop view v_pagg_test; -drop foreign table pagg_test; --- FILTER tests ---Testcase 158: -select min(unique1) filter (where unique1 > 100) from tenk1; - min ------ - 101 -(1 row) - ---Testcase 159: -select sum(1/ten) filter (where ten > 0) from tenk1; - sum ------- - 1000 -(1 row) - ---Testcase 160: -select ten, sum(distinct four) filter (where four::text ~ '123') from onek a -group by ten; - ten | sum ------+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - ---Testcase 161: -select ten, sum(distinct four) filter (where four > 10) from onek a -group by ten -having exists (select 1 from onek b where sum(distinct a.four) = b.four); - ten | sum ------+----- - 0 | - 2 | - 4 | - 6 | - 8 | -(5 rows) - ---Testcase 448: -create foreign table agg_t17(foo text, bar text) server sqlite_svr; ---Testcase 449: -insert into agg_t17 values ('a', 'b'); ---Testcase 450: -select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0') -from agg_t17; - max ------ - a -(1 row) - -create foreign table agg_t170(v int) server sqlite_svr; -insert into agg_t170(v) values (1), (2), (3); -select any_value(v) filter (where v > 2) from agg_t170; -ERROR: function any_value(integer) does not exist -LINE 1: select any_value(v) filter (where v > 2) from agg_t170; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- outer reference in FILTER (PostgreSQL extension) ---Testcase 451: -create foreign table agg_t18 (inner_c int) server sqlite_svr; ---Testcase 452: -create foreign table agg_t19 (outer_c int) server sqlite_svr; ---Testcase 453: -insert into agg_t18 values (1); ---Testcase 454: -insert into agg_t19 values (2), (3); ---Testcase 455: -select (select count(*) - from agg_t18) from agg_t19; -- inner query is aggregation query - count -------- - 1 - 1 -(2 rows) - ---Testcase 456: -select (select count(*) filter (where outer_c <> 0) - from agg_t18) from agg_t19; -- outer query is aggregation query - count -------- - 2 -(1 row) - ---Testcase 457: -select (select count(inner_c) filter (where outer_c <> 0) - from agg_t18) from agg_t19; -- inner query is aggregation query - count -------- - 1 - 1 -(2 rows) - ---Testcase 162: -select - (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)) - filter (where o.unique1 < 10)) -from tenk1 o; -- outer query is aggregation query - max ------- - 9998 -(1 row) - --- subquery in FILTER clause (PostgreSQL extension) ---Testcase 163: -select sum(unique1) FILTER (WHERE - unique1 IN (SELECT unique1 FROM onek where unique1 < 100)) FROM tenk1; - sum ------- - 4950 -(1 row) - --- exercise lots of aggregate parts with FILTER -begin; ---Testcase 164: -delete from multi_arg_agg; ---Testcase 165: -insert into multi_arg_agg values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz'); ---Testcase 166: -select aggfns(distinct a,b,c order by a,c using ~<~,b) filter (where a > 1) from multi_arg_agg, generate_series(1,2) i; - aggfns ---------------------------- - {"(2,2,bar)","(3,1,baz)"} -(1 row) - -rollback; --- check handling of bare boolean Var in FILTER ---Testcase 672: -select max(0) filter (where b1) from bool_test; - max ------ - 0 -(1 row) - ---Testcase 673: -select (select max(0) filter (where b1)) from bool_test; - max ------ - 0 -(1 row) - --- check for correct detection of nested-aggregate errors in FILTER ---Testcase 674: -select max(unique1) filter (where sum(ten) > 0) from tenk1; -ERROR: aggregate functions are not allowed in FILTER -LINE 1: select max(unique1) filter (where sum(ten) > 0) from tenk1; - ^ ---Testcase 675: -select (select max(unique1) filter (where sum(ten) > 0) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(unique1) filter (where sum(ten) > 0) from... - ^ ---Testcase 676: -select max(unique1) filter (where bool_or(ten > 0)) from tenk1; -ERROR: aggregate functions are not allowed in FILTER -LINE 1: select max(unique1) filter (where bool_or(ten > 0)) from ten... - ^ ---Testcase 677: -select (select max(unique1) filter (where bool_or(ten > 0)) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(unique1) filter (where bool_or(ten > 0)) ... - ^ --- ordered-set aggregates -begin; ---Testcase 167: -delete from FLOAT8_TBL; ---Testcase 168: -insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); ---Testcase 169: -select f1, percentile_cont(f1) within group (order by x::float8) -from generate_series(1,5) x, - FLOAT8_TBL -group by f1 order by f1; - f1 | percentile_cont -------+----------------- - 0 | 1 - 0.1 | 1.4 - 0.25 | 2 - 0.4 | 2.6 - 0.5 | 3 - 0.6 | 3.4 - 0.75 | 4 - 0.9 | 4.6 - 1 | 5 -(9 rows) - -rollback; -begin; ---Testcase 170: -delete from FLOAT8_TBL; ---Testcase 171: -insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); ---Testcase 172: -select f1, percentile_cont(f1 order by f1) within group (order by x) -- error -from generate_series(1,5) x, - FLOAT8_TBL -group by f1 order by f1; -ERROR: cannot use multiple ORDER BY clauses with WITHIN GROUP -LINE 1: select f1, percentile_cont(f1 order by f1) within group (ord... - ^ -rollback; -begin; ---Testcase 173: -delete from FLOAT8_TBL; ---Testcase 174: -insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); ---Testcase 175: -select f1, sum() within group (order by x::float8) -- error -from generate_series(1,5) x, - FLOAT8_TBL -group by f1 order by f1; -ERROR: sum is not an ordered-set aggregate, so it cannot have WITHIN GROUP -LINE 1: select f1, sum() within group (order by x::float8) - ^ -rollback; -begin; ---Testcase 176: -delete from FLOAT8_TBL; ---Testcase 177: -insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); ---Testcase 178: -select f1, percentile_cont(f1,f1) -- error -from generate_series(1,5) x, - FLOAT8_TBL -group by f1 order by f1; -ERROR: WITHIN GROUP is required for ordered-set aggregate percentile_cont -LINE 1: select f1, percentile_cont(f1,f1) - ^ -rollback; ---Testcase 179: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 693: -select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; - percentile_cont ------------------ - 53.4485001564 -(1 row) - ---Testcase 180: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 694: -select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; - percentile_cont | sum ------------------+--------- - 53.4485001564 | 431.773 -(1 row) - ---Testcase 181: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 695: -select percentile_cont(0.5) within group (order by thousand) from tenk1; - percentile_cont ------------------ - 499.5 -(1 row) - ---Testcase 182: -select percentile_disc(0.5) within group (order by thousand) from tenk1; - percentile_disc ------------------ - 499 -(1 row) - -begin; ---Testcase 183: -delete from INT4_TBL; ---Testcase 184: -insert into INT4_TBL values (1),(1),(2),(2),(3),(3),(4); ---Testcase 185: -select rank(3) within group (order by f1) from INT4_TBL; - rank ------- - 5 -(1 row) - ---Testcase 186: -select cume_dist(3) within group (order by f1) from INT4_TBL; - cume_dist ------------ - 0.875 -(1 row) - ---Testcase 187: -insert into INT4_TBL values (5); ---Testcase 458: --- Round the result to limited digits to avoid platform-specific results. ---Testcase 696: -select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; - percent_rank --------------- - 0.5000000000 -(1 row) - ---Testcase 459: -delete from INT4_TBL where f1 = 5; ---Testcase 188: -select dense_rank(3) within group (order by f1) from INT4_TBL; - dense_rank ------------- - 3 -(1 row) - -rollback; ---Testcase 189: -select percentile_disc(array[0,0.1,0.25,0.5,0.75,0.9,1]) within group (order by thousand) -from tenk1; - percentile_disc ----------------------------- - {0,99,249,499,749,899,999} -(1 row) - ---Testcase 190: -select percentile_cont(array[0,0.25,0.5,0.75,1]) within group (order by thousand) -from tenk1; - percentile_cont ------------------------------ - {0,249.75,499.5,749.25,999} -(1 row) - ---Testcase 191: -select percentile_disc(array[[null,1,0.5],[0.75,0.25,null]]) within group (order by thousand) -from tenk1; - percentile_disc ---------------------------------- - {{NULL,999,499},{749,249,NULL}} -(1 row) - ---Testcase 460: -create foreign table agg_t21 (x int) server sqlite_svr; -begin; ---Testcase 248: -insert into agg_t21 select * from generate_series(1,6); ---Testcase 249: -select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x) -from agg_t21; - percentile_cont ------------------------------------------- - {1,6,2.25,4.75,3.5,6,2.5,2.6,2.75,2.9,3} -(1 row) - -rollback; ---Testcase 192: -select ten, mode() within group (order by string4) from tenk1 group by ten; - ten | mode ------+-------- - 0 | HHHHxx - 1 | OOOOxx - 2 | VVVVxx - 3 | OOOOxx - 4 | HHHHxx - 5 | HHHHxx - 6 | OOOOxx - 7 | AAAAxx - 8 | VVVVxx - 9 | VVVVxx -(10 rows) - ---Testcase 461: -create foreign table agg_t20 (x text) server sqlite_svr; -begin; ---Testcase 462: -insert into agg_t20 values (unnest('{fred,jim,fred,jack,jill,fred,jill,jim,jim,sheila,jim,sheila}'::text[])); ---Testcase 463: -select percentile_disc(array[0.25,0.5,0.75]) within group (order by x) from agg_t20; - percentile_disc ------------------ - {fred,jill,jim} -(1 row) - -rollback; --- check collation propagates up in suitable cases: -begin; ---Testcase 464: -insert into agg_t20 values ('fred'), ('jim'); ---Testcase 465: -select pg_collation_for(percentile_disc(1) within group (order by x collate "POSIX")) from agg_t20; - pg_collation_for ------------------- - "POSIX" -(1 row) - -rollback; --- ordered-set aggs created with CREATE AGGREGATE ---Testcase 466: -create aggregate my_percentile_disc(float8 ORDER BY anyelement) ( - stype = internal, - sfunc = ordered_set_transition, - finalfunc = percentile_disc_final, - finalfunc_extra = true, - finalfunc_modify = read_write -); ---Testcase 467: -create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") ( - stype = internal, - sfunc = ordered_set_transition_multi, - finalfunc = rank_final, - finalfunc_extra = true, - hypothetical -); ---Testcase 633: -alter aggregate my_percentile_disc(float8 ORDER BY anyelement) - rename to test_percentile_disc; - ---Testcase 634: -alter aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") - rename to test_rank; -begin; ---Testcase 468: -insert into agg_t21 values (1),(1),(2),(2),(3),(3),(4); ---Testcase 469: -select test_rank(3) within group (order by x) from agg_t21; - test_rank ------------ - 5 -(1 row) - -rollback; - ---Testcase 193: -select test_percentile_disc(0.5) within group (order by thousand) from tenk1; - test_percentile_disc ----------------------- - 499 -(1 row) - --- ordered-set aggs can't use ungrouped vars in direct args: -begin; ---Testcase 470: -insert into agg_t21 select * from generate_series(1,5); ---Testcase 471: -select rank(x) within group (order by x) from agg_t21; -ERROR: column "agg_t21.x" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: select rank(x) within group (order by x) from agg_t21; - ^ -DETAIL: Direct arguments of an ordered-set aggregate must use only grouped columns. -rollback; --- outer-level agg can't use a grouped arg of a lower level, either: -begin; ---Testcase 472: -insert into agg_t21 select * from generate_series(1,5); ---Testcase 473: -select array(select percentile_disc(a) within group (order by x) - from (values (0.3),(0.7)) v(a) group by a) - from agg_t21; -ERROR: outer-level aggregate cannot contain a lower-level variable in its direct arguments -LINE 1: select array(select percentile_disc(a) within group (order b... - ^ -rollback; --- agg in the direct args is a grouping violation, too: -begin; ---Testcase 474: -insert into agg_t21 select * from generate_series(1,5); ---Testcase 475: -select rank(sum(x)) within group (order by x) from agg_t21; -ERROR: aggregate function calls cannot be nested -LINE 1: select rank(sum(x)) within group (order by x) from agg_t21; - ^ -rollback; --- hypothetical-set type unification and argument-count failures: -begin; ---Testcase 264: -insert into agg_t20 values ('fred'), ('jim'); ---Testcase 265: -select rank(3) within group (order by x) from agg_t20; -ERROR: WITHIN GROUP types text and integer cannot be matched -LINE 1: select rank(3) within group (order by x) from agg_t20; - ^ -rollback; ---Testcase 194: -select rank(3) within group (order by stringu1,stringu2) from tenk1; -ERROR: function rank(integer, name, name) does not exist -LINE 1: select rank(3) within group (order by stringu1,stringu2) fro... - ^ -HINT: To use the hypothetical-set aggregate rank, the number of hypothetical direct arguments (here 1) must match the number of ordering columns (here 2). -begin; ---Testcase 476: -insert into agg_t21 select * from generate_series(1,5); ---Testcase 477: -select rank('fred') within group (order by x) from agg_t21; -ERROR: invalid input syntax for type integer: "fred" -LINE 1: select rank('fred') within group (order by x) from agg_t21; - ^ -rollback; -begin; ---Testcase 478: -insert into agg_t20 values ('fred'), ('jim'); ---Testcase 479: -select rank('adam'::text collate "C") within group (order by x collate "POSIX") - from agg_t20; -ERROR: collation mismatch between explicit collations "C" and "POSIX" -LINE 1: ...adam'::text collate "C") within group (order by x collate "P... - ^ -rollback; --- hypothetical-set type unification successes: -begin; ---Testcase 480: -insert into agg_t20 values ('fred'), ('jim'); ---Testcase 481: -select rank('adam'::varchar) within group (order by x) from agg_t20; - rank ------- - 1 -(1 row) - -rollback; -begin; ---Testcase 482: -insert into agg_t21 select * from generate_series(1,5); ---Testcase 483: -select rank('3') within group (order by x) from agg_t21; - rank ------- - 3 -(1 row) - -rollback; --- divide by zero check -begin; ---Testcase 484: -insert into agg_t21 select * from generate_series(1,0); ---Testcase 485: -select percent_rank(0) within group (order by x) from agg_t21; - percent_rank --------------- - 0 -(1 row) - -rollback; --- deparse and multiple features: ---Testcase 486: -create view aggordview1 as -select ten, - percentile_disc(0.5) within group (order by thousand) as p50, - percentile_disc(0.5) within group (order by thousand) filter (where hundred=1) as px, - rank(5,'AZZZZ',50) within group (order by hundred, string4 desc, hundred) - from tenk1 - group by ten order by ten; ---Testcase 196: -select pg_get_viewdef('aggordview1'); - pg_get_viewdef -------------------------------------------------------------------------------------------------------------------------------- - SELECT tenk1.ten, + - percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY tenk1.thousand) AS p50, + - percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY tenk1.thousand) FILTER (WHERE (tenk1.hundred = 1)) AS px,+ - rank(5, 'AZZZZ'::name, 50) WITHIN GROUP (ORDER BY tenk1.hundred, tenk1.string4 DESC, tenk1.hundred) AS rank + - FROM tenk1 + - GROUP BY tenk1.ten + - ORDER BY tenk1.ten; -(1 row) - ---Testcase 197: -select * from aggordview1 order by ten; - ten | p50 | px | rank ------+-----+-----+------ - 0 | 490 | | 101 - 1 | 491 | 401 | 101 - 2 | 492 | | 101 - 3 | 493 | | 101 - 4 | 494 | | 101 - 5 | 495 | | 67 - 6 | 496 | | 1 - 7 | 497 | | 1 - 8 | 498 | | 1 - 9 | 499 | | 1 -(10 rows) - ---Testcase 487: -drop view aggordview1; --- variadic aggregates ---Testcase 488: -create function least_accum(anyelement, variadic anyarray) -returns anyelement language sql as - 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; ---Testcase 489: -create aggregate least_agg(variadic items anyarray) ( - stype = anyelement, sfunc = least_accum -); ---Testcase 490: -create function cleast_accum(anycompatible, variadic anycompatiblearray) -returns anycompatible language sql as - 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; -ERROR: type anycompatible does not exist ---Testcase 491: -create aggregate cleast_agg(variadic items anycompatiblearray) ( - stype = anycompatible, sfunc = cleast_accum); -ERROR: type anycompatiblearray does not exist ---Testcase 198: -select least_agg(q1,q2) from int8_tbl; - least_agg -------------------- - -4567890123456789 -(1 row) - ---Testcase 199: -select least_agg(variadic array[q1,q2]) from int8_tbl; - least_agg -------------------- - -4567890123456789 -(1 row) - ---Testcase 492: -select cleast_agg(q1,q2) from int8_tbl; -ERROR: function cleast_agg(bigint, bigint) does not exist -LINE 1: select cleast_agg(q1,q2) from int8_tbl; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 493: -select cleast_agg(4.5,f1) from int4_tbl; -ERROR: function cleast_agg(numeric, integer) does not exist -LINE 1: select cleast_agg(4.5,f1) from int4_tbl; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 494: -select cleast_agg(variadic array[4.5,f1]) from int4_tbl; -ERROR: function cleast_agg(numeric[]) does not exist -LINE 1: select cleast_agg(variadic array[4.5,f1]) from int4_tbl; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 495: -select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl; -ERROR: function cleast_agg(numeric[]) does not exist -LINE 1: select pg_typeof(cleast_agg(variadic array[4.5,f1])) from in... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- test aggregates with common transition functions share the same states ---Testcase 496: -create foreign table agg_t10(one int, id int options (key 'true')) server sqlite_svr; ---Testcase 497: -create foreign table agg_t11(one int, two int, id int options (key 'true')) server sqlite_svr; ---Testcase 498: -create foreign table agg_t12(a int, id int options (key 'true')) server sqlite_svr; -begin work; ---Testcase 499: -create type avg_state as (total bigint, count bigint); ---Testcase 500: -create or replace function avg_transfn(state avg_state, n int) returns avg_state as -$$ -declare new_state avg_state; -begin - raise notice 'avg_transfn called with %', n; - if state is null then - if n is not null then - new_state.total := n; - new_state.count := 1; - return new_state; - end if; - return null; - elsif n is not null then - state.total := state.total + n; - state.count := state.count + 1; - return state; - end if; - - return null; -end -$$ language plpgsql; ---Testcase 501: -create function avg_finalfn(state avg_state) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state.total / state.count; - end if; -end -$$ language plpgsql; ---Testcase 502: -create function sum_finalfn(state avg_state) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state.total; - end if; -end -$$ language plpgsql; ---Testcase 503: -create aggregate my_avg(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn -); ---Testcase 504: -create aggregate my_sum(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = sum_finalfn -); --- aggregate state should be shared as aggs are the same. ---Testcase 505: -delete from agg_t10; ---Testcase 506: -insert into agg_t10 values (1), (3); ---Testcase 507: -select my_avg(one),my_avg(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_avg ---------+-------- - 2 | 2 -(1 row) - --- aggregate state should be shared as transfn is the same for both aggs. ---Testcase 508: -select my_avg(one),my_sum(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- same as previous one, but with DISTINCT, which requires sorting the input. ---Testcase 509: -delete from agg_t10; ---Testcase 510: -insert into agg_t10 values (1), (3), (1); ---Testcase 511: -select my_avg(distinct one),my_sum(distinct one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- shouldn't share states due to the distinctness not matching. ---Testcase 512: -delete from agg_t10; ---Testcase 513: -insert into agg_t10 values (1), (3); ---Testcase 514: -select my_avg(distinct one),my_sum(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- shouldn't share states due to the filter clause not matching. ---Testcase 515: -select my_avg(one) filter (where one > 1),my_sum(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 3 | 4 -(1 row) - --- this should not share the state due to different input columns. ---Testcase 516: -delete from agg_t11; ---Testcase 517: -insert into agg_t11 values (1,2),(3,4); ---Testcase 518: -select my_avg(one),my_sum(two) from agg_t11; -NOTICE: avg_transfn called with 2 -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 4 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 6 -(1 row) - --- exercise cases where OSAs share state ---Testcase 519: -delete from agg_t12; ---Testcase 520: -insert into agg_t12 values (1), (3), (5), (7); ---Testcase 521: -select - percentile_cont(0.5) within group (order by a), - percentile_disc(0.5) within group (order by a) -from agg_t12; - percentile_cont | percentile_disc ------------------+----------------- - 4 | 3 -(1 row) - ---Testcase 522: -select - percentile_cont(0.25) within group (order by a), - percentile_disc(0.5) within group (order by a) -from agg_t12; - percentile_cont | percentile_disc ------------------+----------------- - 2.5 | 3 -(1 row) - --- these can't share state currently ---Testcase 523: -select - rank(4) within group (order by a), - dense_rank(4) within group (order by a) -from agg_t12; - rank | dense_rank -------+------------ - 3 | 3 -(1 row) - --- test that aggs with the same sfunc and initcond share the same agg state ---Testcase 524: -create aggregate my_sum_init(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = sum_finalfn, - initcond = '(10,0)' -); ---Testcase 525: -create aggregate my_avg_init(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn, - initcond = '(10,0)' -); ---Testcase 526: -create aggregate my_avg_init2(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn, - initcond = '(4,0)' -); --- state should be shared if INITCONDs are matching ---Testcase 527: -delete from agg_t10; ---Testcase 528: -insert into agg_t10 values (1), (3); ---Testcase 529: -select my_sum_init(one),my_avg_init(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_sum_init | my_avg_init --------------+------------- - 14 | 7 -(1 row) - --- Varying INITCONDs should cause the states not to be shared. ---Testcase 530: -select my_sum_init(one),my_avg_init2(one) from agg_t10; -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 3 - my_sum_init | my_avg_init2 --------------+-------------- - 14 | 4 -(1 row) - -rollback; --- test aggregate state sharing to ensure it works if one aggregate has a --- finalfn and the other one has none. -begin work; ---Testcase 531: -create or replace function sum_transfn(state int4, n int4) returns int4 as -$$ -declare new_state int4; -begin - raise notice 'sum_transfn called with %', n; - if state is null then - if n is not null then - new_state := n; - return new_state; - end if; - return null; - elsif n is not null then - state := state + n; - return state; - end if; - - return null; -end -$$ language plpgsql; ---Testcase 532: -create function halfsum_finalfn(state int4) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state / 2; - end if; -end -$$ language plpgsql; ---Testcase 533: -create aggregate my_sum(int4) -( - stype = int4, - sfunc = sum_transfn -); ---Testcase 534: -create aggregate my_half_sum(int4) -( - stype = int4, - sfunc = sum_transfn, - finalfunc = halfsum_finalfn -); --- Agg state should be shared even though my_sum has no finalfn ---Testcase 535: -delete from agg_t10; ---Testcase 536: -insert into agg_t10 values (1), (2), (3), (4); ---Testcase 537: -select my_sum(one),my_half_sum(one) from agg_t10; -NOTICE: sum_transfn called with 1 -NOTICE: sum_transfn called with 2 -NOTICE: sum_transfn called with 3 -NOTICE: sum_transfn called with 4 - my_sum | my_half_sum ---------+------------- - 10 | 5 -(1 row) - -rollback; --- test that the aggregate transition logic correctly handles --- transition / combine functions returning NULL --- First test the case of a normal transition function returning NULL -BEGIN; ---Testcase 538: -CREATE FUNCTION balkifnull(int8, int4) -RETURNS int8 -STRICT -LANGUAGE plpgsql AS $$ -BEGIN - IF $1 IS NULL THEN - RAISE 'erroneously called with NULL argument'; - END IF; - RETURN NULL; -END$$; ---Testcase 539: -CREATE AGGREGATE balk(int4) -( - SFUNC = balkifnull(int8, int4), - STYPE = int8, - PARALLEL = SAFE, - INITCOND = '0' -); ---Testcase 200: -SELECT balk(hundred) FROM tenk1; - balk ------- - -(1 row) - -ROLLBACK; --- Secondly test the case of a parallel aggregate combiner function --- returning NULL. For that use normal transition function, but a --- combiner function returning NULL. -BEGIN; ---Testcase 540: -CREATE FUNCTION balkifnull(int8, int8) -RETURNS int8 -PARALLEL SAFE -STRICT -LANGUAGE plpgsql AS $$ -BEGIN - IF $1 IS NULL THEN - RAISE 'erroneously called with NULL argument'; - END IF; - RETURN NULL; -END$$; ---Testcase 541: -CREATE AGGREGATE balk(int4) -( - SFUNC = int4_sum(int8, int4), - STYPE = int8, - COMBINEFUNC = balkifnull(int8, int8), - PARALLEL = SAFE, - INITCOND = '0' -); --- force use of parallelism --- Skip this test, cannot alter foreign table tenk1 --- ALTER FOREIGN TABLE tenk1 set (parallel_workers = 4); --- SET LOCAL parallel_setup_cost=0; --- SET LOCAL max_parallel_workers_per_gather=4; --- EXPLAIN (COSTS OFF) SELECT balk(hundred) FROM tenk1; --- SELECT balk(hundred) FROM tenk1; -ROLLBACK; --- test multiple usage of an aggregate whose finalfn returns a R/W datum -BEGIN; -CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray -LANGUAGE plpgsql IMMUTABLE AS $$ -BEGIN - RETURN array_fill(y[1], ARRAY[4]); -END; -$$; -CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray -LANGUAGE plpgsql STRICT IMMUTABLE AS $$ -DECLARE - res x%TYPE; -BEGIN - -- assignment is essential for this test, it expands the array to R/W - res := array_fill(x[1], ARRAY[4]); - RETURN res; -END; -$$; -CREATE AGGREGATE rwagg(anyarray) ( - STYPE = anyarray, - SFUNC = rwagg_sfunc, - FINALFUNC = rwagg_finalfunc -); -CREATE FUNCTION eatarray(x real[]) RETURNS real[] -LANGUAGE plpgsql STRICT IMMUTABLE AS $$ -BEGIN - x[1] := x[1] + 1; - RETURN x; -END; -$$; -CREATE FOREIGN TABLE float_tb(f real) SERVER sqlite_svr; -INSERT INTO float_tb(f) VALUES (1.0); -SELECT eatarray(rwagg(ARRAY[f::real])), eatarray(rwagg(ARRAY[f::real])) FROM float_tb; - eatarray | eatarray ------------+----------- - {2,1,1,1} | {2,1,1,1} -(1 row) - -ROLLBACK; --- test coverage for aggregate combine/serial/deserial functions -BEGIN; ---Testcase 635: -SET parallel_setup_cost = 0; ---Testcase 636: -SET parallel_tuple_cost = 0; ---Testcase 637: -SET min_parallel_table_scan_size = 0; ---Testcase 638: -SET max_parallel_workers_per_gather = 4; ---Testcase 639: -SET parallel_leader_participation = off; ---Testcase 640: -SET enable_indexonlyscan = off; --- variance(int4) covers numeric_poly_combine --- sum(int8) covers int8_avg_combine --- regr_count(float8, float8) covers int8inc_float8_float8 and aggregates with > 1 arg ---Testcase 542: -EXPLAIN (COSTS OFF, VERBOSE) -SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: variance(tenk1.unique1), sum((tenk1.unique1)::bigint), regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision) - -> Append - -> Foreign Scan on public.tenk1 - Output: tenk1.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_1 - Output: tenk1_1.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_2 - Output: tenk1_2.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_3 - Output: tenk1_3.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" -(15 rows) - ---Testcase 543: -SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - variance | sum | regr_count -----------------------+-----------+------------ - 8333541.588539713493 | 199980000 | 40000 -(1 row) - --- variance(int8) covers numeric_combine --- avg(numeric) covers numeric_avg_combine ---Testcase 544: -EXPLAIN (COSTS OFF, VERBOSE) -SELECT variance(unique1::int8), avg(unique1::numeric) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - QUERY PLAN ----------------------------------------------------------------------------- - Aggregate - Output: variance((tenk1.unique1)::bigint), avg((tenk1.unique1)::numeric) - -> Append - -> Foreign Scan on public.tenk1 - Output: tenk1.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_1 - Output: tenk1_1.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_2 - Output: tenk1_2.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Foreign Scan on public.tenk1 tenk1_3 - Output: tenk1_3.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" -(15 rows) - ---Testcase 545: -SELECT variance(unique1::int8), avg(unique1::numeric) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - variance | avg -----------------------+----------------------- - 8333541.588539713493 | 4999.5000000000000000 -(1 row) - -ROLLBACK; --- test coverage for dense_rank ---Testcase 546: -create foreign table agg_t13(x int, id int options (key 'true')) server sqlite_svr; ---Testcase 547: -insert into agg_t13 values (1),(1),(2),(2),(3),(3); ---Testcase 548: -SELECT dense_rank(x) WITHIN GROUP (ORDER BY x) FROM agg_t13 GROUP BY (x) ORDER BY 1; - dense_rank ------------- - 1 - 1 - 1 -(3 rows) - ---Testcase 549: -delete from agg_t13; --- Ensure that the STRICT checks for aggregates does not take NULLness --- of ORDER BY columns into account. See bug report around --- 2a505161-2727-2473-7c46-591ed108ac52@email.cz ---Testcase 550: -create foreign table agg_t14(x int, y int, id int options (key 'true')) server sqlite_svr; ---Testcase 551: -insert into agg_t14 values (1, NULL), (1, 2); ---Testcase 552: -SELECT min(x ORDER BY y) FROM agg_t14; - min ------ - 1 -(1 row) - ---Testcase 553: -SELECT min(x ORDER BY y) FROM agg_t14; - min ------ - 1 -(1 row) - --- check collation-sensitive matching between grouping expressions -begin; ---Testcase 554: -insert into agg_t20 values (unnest(array['a','b'])); ---Testcase 555: -select x||'a', case x||'a' when 'aa' then 1 else 0 end, count(*) - from agg_t20 group by x||'a' order by 1; - ?column? | case | count -----------+------+------- - aa | 1 | 1 - ba | 0 | 1 -(2 rows) - -rollback; -begin; ---Testcase 556: -insert into agg_t20 values (unnest(array['a','b'])); ---Testcase 557: -select x||'a', case when x||'a' = 'aa' then 1 else 0 end, count(*) - from agg_t20 group by x||'a' order by 1; - ?column? | case | count -----------+------+------- - aa | 1 | 1 - ba | 0 | 1 -(2 rows) - -rollback; --- Make sure that generation of HashAggregate for uniqification purposes --- does not lead to array overflow due to unexpected duplicate hash keys --- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com ---Testcase 641: -set enable_memoize to off; -ERROR: unrecognized configuration parameter "enable_memoize" ---Testcase 558: -explain (costs off) - select 1 from tenk1 - where (hundred, thousand) in (select twothousand, twothousand from onek); - QUERY PLAN -------------------------------------------------------- - Hash Join - Hash Cond: (onek.twothousand = tenk1.hundred) - -> HashAggregate - Group Key: onek.twothousand, onek.twothousand - -> Foreign Scan on onek - -> Hash - -> Foreign Scan on tenk1 -(7 rows) - ---Testcase 642: -reset enable_memoize; -ERROR: unrecognized configuration parameter "enable_memoize" --- --- Hash Aggregation Spill tests --- ---Testcase 643: -set enable_sort=false; ---Testcase 644: -set work_mem='64kB'; ---Testcase 559: -select unique1, count(*), sum(twothousand) from tenk1 -group by unique1 -having sum(fivethous) > 4975 -order by sum(twothousand); - unique1 | count | sum ----------+-------+------ - 4976 | 1 | 976 - 4977 | 1 | 977 - 4978 | 1 | 978 - 4979 | 1 | 979 - 4980 | 1 | 980 - 4981 | 1 | 981 - 4982 | 1 | 982 - 4983 | 1 | 983 - 4984 | 1 | 984 - 4985 | 1 | 985 - 4986 | 1 | 986 - 4987 | 1 | 987 - 4988 | 1 | 988 - 4989 | 1 | 989 - 4990 | 1 | 990 - 4991 | 1 | 991 - 4992 | 1 | 992 - 4993 | 1 | 993 - 4994 | 1 | 994 - 4995 | 1 | 995 - 4996 | 1 | 996 - 4997 | 1 | 997 - 4998 | 1 | 998 - 4999 | 1 | 999 - 9976 | 1 | 1976 - 9977 | 1 | 1977 - 9978 | 1 | 1978 - 9979 | 1 | 1979 - 9980 | 1 | 1980 - 9981 | 1 | 1981 - 9982 | 1 | 1982 - 9983 | 1 | 1983 - 9984 | 1 | 1984 - 9985 | 1 | 1985 - 9986 | 1 | 1986 - 9987 | 1 | 1987 - 9988 | 1 | 1988 - 9989 | 1 | 1989 - 9990 | 1 | 1990 - 9991 | 1 | 1991 - 9992 | 1 | 1992 - 9993 | 1 | 1993 - 9994 | 1 | 1994 - 9995 | 1 | 1995 - 9996 | 1 | 1996 - 9997 | 1 | 1997 - 9998 | 1 | 1998 - 9999 | 1 | 1999 -(48 rows) - ---Testcase 645: -set work_mem to default; ---Testcase 646: -set enable_sort to default; --- --- Compare results between plans using sorting and plans using hash --- aggregation. Force spilling in both cases by setting work_mem low. --- ---Testcase 647: -set work_mem='64kB'; ---Testcase 560: -create foreign table agg_data_2k(g int, id int options (key 'true')) server sqlite_svr; ---Testcase 561: -create foreign table agg_data_20k(g int, id int options (key 'true')) server sqlite_svr; ---Testcase 562: -create foreign table agg_group_1(c1 int, c2 numeric, c3 int) server sqlite_svr; ---Testcase 563: -create foreign table agg_group_2(a int, c1 numeric, c2 text, c3 int) server sqlite_svr; ---Testcase 564: -create foreign table agg_group_3(c1 numeric, c2 int4, c3 int) server sqlite_svr; ---Testcase 565: -create foreign table agg_group_4(c1 numeric, c2 text, c3 int) server sqlite_svr; ---Testcase 566: -create foreign table agg_hash_1(c1 int, c2 numeric, c3 int) server sqlite_svr; ---Testcase 567: -create foreign table agg_hash_2(a int, c1 numeric, c2 text, c3 int) server sqlite_svr; ---Testcase 568: -create foreign table agg_hash_3(c1 numeric, c2 int4, c3 int) server sqlite_svr; ---Testcase 569: -create foreign table agg_hash_4(c1 numeric, c2 text, c3 int) server sqlite_svr; ---Testcase 570: -insert into agg_data_2k select g from generate_series(0, 1999) g; ---analyze agg_data_2k; ---Testcase 571: -insert into agg_data_20k select g from generate_series(0, 19999) g; ---analyze agg_data_20k; --- Produce results with sorting. ---Testcase 648: -set enable_hashagg = false; ---Testcase 649: -set jit_above_cost = 0; ---Testcase 572: -explain (costs off) -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; - QUERY PLAN ------------------------------------- - GroupAggregate - Group Key: (g % 10000) - -> Foreign Scan on agg_data_20k -(3 rows) - ---Testcase 573: -insert into agg_group_1 -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; ---Testcase 574: -insert into agg_group_2 -select * from - (values (100), (300), (500)) as r(a), - lateral ( - select (g/2)::numeric as c1, - array_agg(g::numeric) as c2, - count(*) as c3 - from agg_data_2k - where g < r.a - group by g/2) as s; ---Testcase 650: -set jit_above_cost to default; ---Testcase 575: -insert into agg_group_3 -select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 - from agg_data_2k group by g/2; ---Testcase 576: -insert into agg_group_4 -select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 - from agg_data_2k group by g/2; --- Produce results with hash aggregation ---Testcase 651: -set enable_hashagg = true; ---Testcase 652: -set enable_sort = false; ---Testcase 653: -set jit_above_cost = 0; ---Testcase 577: -explain (costs off) -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; - QUERY PLAN ------------------------------------- - GroupAggregate - Group Key: (g % 10000) - -> Foreign Scan on agg_data_20k -(3 rows) - ---Testcase 578: -insert into agg_hash_1 -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; ---Testcase 579: -insert into agg_hash_2 -select * from - (values (100), (300), (500)) as r(a), - lateral ( - select (g/2)::numeric as c1, - array_agg(g::numeric) as c2, - count(*) as c3 - from agg_data_2k - where g < r.a - group by g/2) as s; ---Testcase 654: -set jit_above_cost to default; ---Testcase 580: -insert into agg_hash_3 -select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 - from agg_data_2k group by g/2; ---Testcase 581: -insert into agg_hash_4 -select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 - from agg_data_2k group by g/2; ---Testcase 655: -set enable_sort = true; ---Testcase 656: -set work_mem to default; --- Compare group aggregation results to hash aggregation results ---Testcase 582: -(select * from agg_hash_1 except select * from agg_group_1) - union all -(select * from agg_group_1 except select * from agg_hash_1); - c1 | c2 | c3 -----+----+---- -(0 rows) - ---Testcase 583: -(select * from agg_hash_2 except select * from agg_group_2) - union all -(select * from agg_group_2 except select * from agg_hash_2); - a | c1 | c2 | c3 ----+----+----+---- -(0 rows) - ---Testcase 584: -(select * from agg_hash_3 except select * from agg_group_3) - union all -(select * from agg_group_3 except select * from agg_hash_3); - c1 | c2 | c3 -----+----+---- -(0 rows) - ---Testcase 585: -(select * from agg_hash_4 except select * from agg_group_4) - union all -(select * from agg_group_4 except select * from agg_hash_4); - c1 | c2 | c3 -----+----+---- -(0 rows) - --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; -NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to table minmaxtest1 -drop cascades to table minmaxtest2 -drop cascades to table minmaxtest3 -NOTICE: drop cascades to table t1c ---Testcase 586: -DROP SERVER sqlite_svr CASCADE; ---Testcase 587: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/int4.out b/expected/12.16/extra/int4.out deleted file mode 100644 index 33e37dfb..00000000 --- a/expected/12.16/extra/int4.out +++ /dev/null @@ -1,649 +0,0 @@ --- --- INT4 Based on PostgreSQL tests, please don't add additional tests here, use other test files --- ---Testcase 61: -CREATE EXTENSION sqlite_fdw; ---Testcase 62: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 63: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 64: -CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; - ---Testcase 1: -INSERT INTO INT4_TBL(f1) VALUES (' 0 '); ---Testcase 2: -INSERT INTO INT4_TBL(f1) VALUES ('123456 '); ---Testcase 3: -INSERT INTO INT4_TBL(f1) VALUES (' -123456'); ---Testcase 4: -INSERT INTO INT4_TBL(f1) VALUES ('34.5'); -ERROR: invalid input syntax for type integer: "34.5" -LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('34.5'); - ^ --- largest and smallest values ---Testcase 5: -INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); ---Testcase 6: -INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --- bad input values -- should give errors ---Testcase 7: -INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); -ERROR: value "1000000000000" is out of range for type integer -LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); - ^ ---Testcase 8: -INSERT INTO INT4_TBL(f1) VALUES ('asdf'); -ERROR: invalid input syntax for type integer: "asdf" -LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('asdf'); - ^ ---Testcase 9: -INSERT INTO INT4_TBL(f1) VALUES (' '); -ERROR: invalid input syntax for type integer: " " -LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' '); - ^ ---Testcase 10: -INSERT INTO INT4_TBL(f1) VALUES (' asdf '); -ERROR: invalid input syntax for type integer: " asdf " -LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' asdf '); - ^ ---Testcase 11: -INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); -ERROR: invalid input syntax for type integer: "- 1234" -LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); - ^ ---Testcase 12: -INSERT INTO INT4_TBL(f1) VALUES ('123 5'); -ERROR: invalid input syntax for type integer: "123 5" -LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('123 5'); - ^ ---Testcase 13: -INSERT INTO INT4_TBL(f1) VALUES (''); -ERROR: invalid input syntax for type integer: "" -LINE 1: INSERT INTO INT4_TBL(f1) VALUES (''); - ^ ---Testcase 14: -SELECT '' AS five, * FROM INT4_TBL; - five | f1 -------+------------- - | 0 - | 123456 - | -123456 - | 2147483647 - | -2147483647 -(5 rows) - ---Testcase 15: -SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int2 '0'; - four | f1 -------+------------- - | 123456 - | -123456 - | 2147483647 - | -2147483647 -(4 rows) - ---Testcase 16: -SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int4 '0'; - four | f1 -------+------------- - | 123456 - | -123456 - | 2147483647 - | -2147483647 -(4 rows) - ---Testcase 17: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int2 '0'; - one | f1 ------+---- - | 0 -(1 row) - ---Testcase 18: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int4 '0'; - one | f1 ------+---- - | 0 -(1 row) - ---Testcase 19: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int2 '0'; - two | f1 ------+------------- - | -123456 - | -2147483647 -(2 rows) - ---Testcase 20: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int4 '0'; - two | f1 ------+------------- - | -123456 - | -2147483647 -(2 rows) - ---Testcase 21: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int2 '0'; - three | f1 --------+------------- - | 0 - | -123456 - | -2147483647 -(3 rows) - ---Testcase 22: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int4 '0'; - three | f1 --------+------------- - | 0 - | -123456 - | -2147483647 -(3 rows) - ---Testcase 23: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int2 '0'; - two | f1 ------+------------ - | 123456 - | 2147483647 -(2 rows) - ---Testcase 24: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int4 '0'; - two | f1 ------+------------ - | 123456 - | 2147483647 -(2 rows) - ---Testcase 25: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int2 '0'; - three | f1 --------+------------ - | 0 - | 123456 - | 2147483647 -(3 rows) - ---Testcase 26: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int4 '0'; - three | f1 --------+------------ - | 0 - | 123456 - | 2147483647 -(3 rows) - --- positive odds ---Testcase 27: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; - one | f1 ------+------------ - | 2147483647 -(1 row) - --- any evens ---Testcase 28: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; - three | f1 --------+--------- - | 0 - | 123456 - | -123456 -(3 rows) - ---Testcase 29: -SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 30: -SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i -WHERE abs(f1) < 1073741824; - five | f1 | x -------+---------+--------- - | 0 | 0 - | 123456 | 246912 - | -123456 | -246912 -(3 rows) - ---Testcase 31: -SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 32: -SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i -WHERE abs(f1) < 1073741824; - five | f1 | x -------+---------+--------- - | 0 | 0 - | 123456 | 246912 - | -123456 | -246912 -(3 rows) - ---Testcase 33: -SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 34: -SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i -WHERE f1 < 2147483646; - five | f1 | x -------+-------------+------------- - | 0 | 2 - | 123456 | 123458 - | -123456 | -123454 - | -2147483647 | -2147483645 -(4 rows) - ---Testcase 35: -SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 36: -SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i -WHERE f1 < 2147483646; - five | f1 | x -------+-------------+------------- - | 0 | 2 - | 123456 | 123458 - | -123456 | -123454 - | -2147483647 | -2147483645 -(4 rows) - ---Testcase 37: -SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 38: -SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i -WHERE f1 > -2147483647; - five | f1 | x -------+------------+------------ - | 0 | -2 - | 123456 | 123454 - | -123456 | -123458 - | 2147483647 | 2147483645 -(4 rows) - ---Testcase 39: -SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i; -ERROR: integer out of range ---Testcase 40: -SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i -WHERE f1 > -2147483647; - five | f1 | x -------+------------+------------ - | 0 | -2 - | 123456 | 123454 - | -123456 | -123458 - | 2147483647 | 2147483645 -(4 rows) - ---Testcase 41: -SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i; - five | f1 | x -------+-------------+------------- - | 0 | 0 - | 123456 | 61728 - | -123456 | -61728 - | 2147483647 | 1073741823 - | -2147483647 | -1073741823 -(5 rows) - ---Testcase 42: -SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i; - five | f1 | x -------+-------------+------------- - | 0 | 0 - | 123456 | 61728 - | -123456 | -61728 - | 2147483647 | 1073741823 - | -2147483647 | -1073741823 -(5 rows) - --- --- more complex expressions --- --- variations on unary minus parsing ---Testcase 65: -DELETE FROM INT4_TMP; ---Testcase 66: -INSERT INTO INT4_TMP VALUES (-2, 3); ---Testcase 67: -SELECT f1 + f2 as one FROM INT4_TMP; - one ------ - 1 -(1 row) - ---Testcase 68: -DELETE FROM INT4_TMP; ---Testcase 69: -INSERT INTO INT4_TMP VALUES (4, 2); ---Testcase 70: -SELECT f1 - f2 as two FROM INT4_TMP; - two ------ - 2 -(1 row) - ---Testcase 46: -DELETE FROM INT4_TMP; ---Testcase 71: -INSERT INTO INT4_TMP VALUES (2, 1); ---Testcase 72: -SELECT f1- -f2 as three FROM INT4_TMP; - three -------- - 3 -(1 row) - ---Testcase 47: -DELETE FROM INT4_TMP; ---Testcase 73: -INSERT INTO INT4_TMP VALUES (2, 2); ---Testcase 74: -SELECT f1 - -f2 as four FROM INT4_TMP; - four ------- - 4 -(1 row) - ---Testcase 75: -DELETE FROM INT4_TMP; ---Testcase 76: -INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int2, '16'::int2 / '4'::int2); ---Testcase 77: -SELECT f1 = f2 AS true FROM INT4_TMP; - true ------- - t -(1 row) - ---Testcase 78: -DELETE FROM INT4_TMP; ---Testcase 79: -INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int4, '16'::int2 / '4'::int4); ---Testcase 80: -SELECT f1 = f2 AS true FROM INT4_TMP; - true ------- - t -(1 row) - ---Testcase 81: -DELETE FROM INT4_TMP; ---Testcase 82: -INSERT INTO INT4_TMP VALUES ('2'::int4 * '2'::int2, '16'::int4 / '4'::int2); ---Testcase 83: -SELECT f1 = f2 AS true FROM INT4_TMP; - true ------- - t -(1 row) - ---Testcase 84: -DELETE FROM INT4_TMP; ---Testcase 85: -INSERT INTO INT4_TMP VALUES ('1000'::int4, '999'::int4); ---Testcase 86: -SELECT f1 < f2 AS false FROM INT4_TMP; - false -------- - f -(1 row) - ---Testcase 48: -DELETE FROM INT4_TMP; ---Testcase 87: -INSERT INTO INT4_TMP VALUES (4!); ---Testcase 88: -SELECT f1 as twenty_four FROM INT4_TMP; - twenty_four -------------- - 24 -(1 row) - ---Testcase 49: -DELETE FROM INT4_TMP; ---Testcase 89: -INSERT INTO INT4_TMP VALUES (!!3); ---Testcase 90: -SELECT f1 as six FROM INT4_TMP; - six ------ - 6 -(1 row) - ---Testcase 50: -DELETE FROM INT4_TMP; ---Testcase 91: -INSERT INTO INT4_TMP VALUES (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1); ---Testcase 92: -SELECT f1 as ten FROM INT4_TMP; - ten ------ - 10 -(1 row) - ---Testcase 51: -DELETE FROM INT4_TMP; ---Testcase 93: -INSERT INTO INT4_TMP VALUES (2 , 2); ---Testcase 94: -SELECT f1 + f1/f2 as three FROM INT4_TMP; - three -------- - 3 -(1 row) - ---Testcase 52: -DELETE FROM INT4_TMP; ---Testcase 95: -INSERT INTO INT4_TMP VALUES (2 , 2); ---Testcase 96: -SELECT (f1 + f2)/f2 as two FROM INT4_TMP; - two ------ - 2 -(1 row) - --- corner case ---Testcase 54: -DELETE FROM INT4_TMP; ---Testcase 97: -INSERT INTO INT4_TMP VALUES (-1); ---Testcase 98: -SELECT (f1<<31)::text FROM INT4_TMP; - text -------------- - -2147483648 -(1 row) - ---Testcase 56: -DELETE FROM INT4_TMP; ---Testcase 99: -INSERT INTO INT4_TMP VALUES (-1); ---Testcase 100: -SELECT ((f1<<31)+1)::text FROM INT4_TMP; - text -------------- - -2147483647 -(1 row) - --- check sane handling of INT_MIN overflow cases ---Testcase 58: -DELETE FROM INT4_TMP; ---Testcase 101: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int4); ---Testcase 102: -SELECT f1 * f2 FROM INT4_TMP; -ERROR: integer out of range ---Testcase 103: -SELECT f1 / f2 FROM INT4_TMP; -ERROR: integer out of range ---Testcase 104: -SELECT f1 % f2 FROM INT4_TMP; - ?column? ----------- - 0 -(1 row) - ---Testcase 60: -DELETE FROM INT4_TMP; ---Testcase 105: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int2); ---Testcase 106: -SELECT f1 * f2 FROM INT4_TMP; -ERROR: integer out of range ---Testcase 107: -SELECT f1 / f2 FROM INT4_TMP; -ERROR: integer out of range ---Testcase 108: -SELECT f1 % f2 FROM INT4_TMP; - ?column? ----------- - 0 -(1 row) - --- check rounding when casting from float ---Testcase 109: -CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 110: -DELETE FROM FLOAT8_TMP; ---Testcase 111: -INSERT INTO FLOAT8_TMP VALUES - (-2.5::float8), - (-1.5::float8), - (-0.5::float8), - (0.0::float8), - (0.5::float8), - (1.5::float8), - (2.5::float8); ---Testcase 112: -SELECT f1 as x, f1::int4 as int4_value FROM FLOAT8_TMP; - x | int4_value -------+------------ - -2.5 | -2 - -1.5 | -2 - -0.5 | 0 - 0 | 0 - 0.5 | 0 - 1.5 | 2 - 2.5 | 2 -(7 rows) - --- check rounding when casting from numeric ---Testcase 113: -CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 114: -DELETE FROM NUMERIC_TMP; ---Testcase 115: -INSERT INTO NUMERIC_TMP VALUES - (-2.5::numeric), - (-1.5::numeric), - (-0.5::numeric), - (0.0::numeric), - (0.5::numeric), - (1.5::numeric), - (2.5::numeric); ---Testcase 116: -SELECT f1 as x, f1::int4 as int4_value FROM NUMERIC_TMP; - x | int4_value -------+------------ - -2.5 | -3 - -1.5 | -2 - -0.5 | -1 - 0 | 0 - 0.5 | 1 - 1.5 | 2 - 2.5 | 3 -(7 rows) - --- test gcd() ---Testcase 117: -DELETE FROM INT4_TMP; ---Testcase 118: -INSERT INTO INT4_TMP VALUES - (0::int4, 0::int4), - (0::int4, 6410818::int4), - (61866666::int4, 6410818::int4), - (-61866666::int4, 6410818::int4), - ((-2147483648)::int4, 1::int4), - ((-2147483648)::int4, 2147483647::int4), - ((-2147483648)::int4, 1073741824::int4); ---Testcase 119: -SELECT f1, f2, gcd(f1, f2), gcd(f1, -f2), gcd(f2, f1), gcd(-f2, f1) FROM INT4_TMP; -ERROR: function gcd(integer, integer) does not exist -LINE 1: SELECT f1, f2, gcd(f1, f2), gcd(f1, -f2), gcd(f2, f1), gcd(-... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 120: -DELETE FROM INT4_TMP; ---Testcase 121: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 0::int4); ---Testcase 122: -SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow -ERROR: function gcd(integer, integer) does not exist -LINE 1: SELECT gcd(f1, f2) FROM INT4_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 123: -DELETE FROM INT4_TMP; ---Testcase 124: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-2147483648)::int4); ---Testcase 125: -SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow -ERROR: function gcd(integer, integer) does not exist -LINE 1: SELECT gcd(f1, f2) FROM INT4_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- test lcm() ---Testcase 126: -DELETE FROM INT4_TMP; ---Testcase 127: -INSERT INTO INT4_TMP VALUES - (0::int4, 0::int4), - (0::int4, 42::int4), - (42::int4, 42::int4), - (330::int4, 462::int4), - (-330::int4, 462::int4), - ((-2147483648)::int4, 0::int4); ---Testcase 128: -SELECT f1, f2, lcm(f1, f2), lcm(f1, -f2), lcm(f2, f1), lcm(-f2, f1) FROM INT4_TMP; -ERROR: function lcm(integer, integer) does not exist -LINE 1: SELECT f1, f2, lcm(f1, f2), lcm(f1, -f2), lcm(f2, f1), lcm(-... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 129: -DELETE FROM INT4_TMP; ---Testcase 130: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 1::int4); ---Testcase 131: -SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow -ERROR: function lcm(integer, integer) does not exist -LINE 1: SELECT lcm(f1, f2) FROM INT4_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 132: -DELETE FROM INT4_TMP; ---Testcase 133: -INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); ---Testcase 134: -SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow -ERROR: function lcm(integer, integer) does not exist -LINE 1: SELECT lcm(f1, f2) FROM INT4_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; ---Testcase 135: -DROP SERVER sqlite_svr; ---Testcase 136: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/int8.out b/expected/12.16/extra/int8.out deleted file mode 100644 index 06818382..00000000 --- a/expected/12.16/extra/int8.out +++ /dev/null @@ -1,1322 +0,0 @@ --- --- INT8 --- Test int8 64-bit integers. --- ---Testcase 140: -CREATE EXTENSION sqlite_fdw; ---Testcase 141: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 142: -CREATE FOREIGN TABLE INT8_TBL( - q1 int8 OPTIONS (key 'true'), - q2 int8 OPTIONS (key 'true') -) SERVER sqlite_svr; ---Testcase 143: -CREATE FOREIGN TABLE INT8_TMP( - q1 int8, - q2 int8, - q3 int4, - q4 int2, - q5 text, - id int options (key 'true') -) SERVER sqlite_svr; ---Testcase 1: -INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); ---Testcase 2: -INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); ---Testcase 3: -INSERT INTO INT8_TBL VALUES('4567890123456789','123'); ---Testcase 4: -INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); ---Testcase 5: -INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --- bad inputs ---Testcase 6: -INSERT INTO INT8_TBL(q1) VALUES (' '); -ERROR: invalid input syntax for type bigint: " " -LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' '); - ^ ---Testcase 7: -INSERT INTO INT8_TBL(q1) VALUES ('xxx'); -ERROR: invalid input syntax for type bigint: "xxx" -LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx'); - ^ ---Testcase 8: -INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); -ERROR: value "3908203590239580293850293850329485" is out of range for type bigint -LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938... - ^ ---Testcase 9: -INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); -ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint -LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340... - ^ ---Testcase 10: -INSERT INTO INT8_TBL(q1) VALUES ('- 123'); -ERROR: invalid input syntax for type bigint: "- 123" -LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123'); - ^ ---Testcase 11: -INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); -ERROR: invalid input syntax for type bigint: " 345 5" -LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); - ^ ---Testcase 12: -INSERT INTO INT8_TBL(q1) VALUES (''); -ERROR: invalid input syntax for type bigint: "" -LINE 1: INSERT INTO INT8_TBL(q1) VALUES (''); - ^ ---Testcase 13: -SELECT * FROM INT8_TBL; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(5 rows) - --- int8/int8 cmp ---Testcase 14: -SELECT * FROM INT8_TBL WHERE q2 = 4567890123456789; - q1 | q2 -------------------+------------------ - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(2 rows) - ---Testcase 15: -SELECT * FROM INT8_TBL WHERE q2 <> 4567890123456789; - q1 | q2 -------------------+------------------- - 123 | 456 - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 16: -SELECT * FROM INT8_TBL WHERE q2 < 4567890123456789; - q1 | q2 -------------------+------------------- - 123 | 456 - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 17: -SELECT * FROM INT8_TBL WHERE q2 > 4567890123456789; - q1 | q2 -----+---- -(0 rows) - ---Testcase 18: -SELECT * FROM INT8_TBL WHERE q2 <= 4567890123456789; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(5 rows) - ---Testcase 19: -SELECT * FROM INT8_TBL WHERE q2 >= 4567890123456789; - q1 | q2 -------------------+------------------ - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(2 rows) - --- int8/int4 cmp ---Testcase 20: -SELECT * FROM INT8_TBL WHERE q2 = 456; - q1 | q2 ------+----- - 123 | 456 -(1 row) - ---Testcase 21: -SELECT * FROM INT8_TBL WHERE q2 <> 456; - q1 | q2 -------------------+------------------- - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(4 rows) - ---Testcase 22: -SELECT * FROM INT8_TBL WHERE q2 < 456; - q1 | q2 -------------------+------------------- - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(2 rows) - ---Testcase 23: -SELECT * FROM INT8_TBL WHERE q2 > 456; - q1 | q2 -------------------+------------------ - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(2 rows) - ---Testcase 24: -SELECT * FROM INT8_TBL WHERE q2 <= 456; - q1 | q2 -------------------+------------------- - 123 | 456 - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 25: -SELECT * FROM INT8_TBL WHERE q2 >= 456; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(3 rows) - --- int4/int8 cmp ---Testcase 26: -SELECT * FROM INT8_TBL WHERE 123 = q1; - q1 | q2 ------+------------------ - 123 | 456 - 123 | 4567890123456789 -(2 rows) - ---Testcase 27: -SELECT * FROM INT8_TBL WHERE 123 <> q1; - q1 | q2 -------------------+------------------- - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 28: -SELECT * FROM INT8_TBL WHERE 123 < q1; - q1 | q2 -------------------+------------------- - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(3 rows) - ---Testcase 29: -SELECT * FROM INT8_TBL WHERE 123 > q1; - q1 | q2 -----+---- -(0 rows) - ---Testcase 30: -SELECT * FROM INT8_TBL WHERE 123 <= q1; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(5 rows) - ---Testcase 31: -SELECT * FROM INT8_TBL WHERE 123 >= q1; - q1 | q2 ------+------------------ - 123 | 456 - 123 | 4567890123456789 -(2 rows) - --- int8/int2 cmp ---Testcase 32: -SELECT * FROM INT8_TBL WHERE q2 = '456'::int2; - q1 | q2 ------+----- - 123 | 456 -(1 row) - ---Testcase 33: -SELECT * FROM INT8_TBL WHERE q2 <> '456'::int2; - q1 | q2 -------------------+------------------- - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(4 rows) - ---Testcase 34: -SELECT * FROM INT8_TBL WHERE q2 < '456'::int2; - q1 | q2 -------------------+------------------- - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(2 rows) - ---Testcase 35: -SELECT * FROM INT8_TBL WHERE q2 > '456'::int2; - q1 | q2 -------------------+------------------ - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(2 rows) - ---Testcase 36: -SELECT * FROM INT8_TBL WHERE q2 <= '456'::int2; - q1 | q2 -------------------+------------------- - 123 | 456 - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 37: -SELECT * FROM INT8_TBL WHERE q2 >= '456'::int2; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(3 rows) - --- int2/int8 cmp ---Testcase 38: -SELECT * FROM INT8_TBL WHERE '123'::int2 = q1; - q1 | q2 ------+------------------ - 123 | 456 - 123 | 4567890123456789 -(2 rows) - ---Testcase 39: -SELECT * FROM INT8_TBL WHERE '123'::int2 <> q1; - q1 | q2 -------------------+------------------- - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(3 rows) - ---Testcase 40: -SELECT * FROM INT8_TBL WHERE '123'::int2 < q1; - q1 | q2 -------------------+------------------- - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(3 rows) - ---Testcase 41: -SELECT * FROM INT8_TBL WHERE '123'::int2 > q1; - q1 | q2 -----+---- -(0 rows) - ---Testcase 42: -SELECT * FROM INT8_TBL WHERE '123'::int2 <= q1; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(5 rows) - ---Testcase 43: -SELECT * FROM INT8_TBL WHERE '123'::int2 >= q1; - q1 | q2 ------+------------------ - 123 | 456 - 123 | 4567890123456789 -(2 rows) - ---Testcase 44: -SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL; - five | plus | minus -------+------------------+------------------- - | 123 | -123 - | 123 | -123 - | 4567890123456789 | -4567890123456789 - | 4567890123456789 | -4567890123456789 - | 4567890123456789 | -4567890123456789 -(5 rows) - ---Testcase 45: -SELECT '' AS five, q1, q2, q1 + q2 AS plus FROM INT8_TBL; - five | q1 | q2 | plus -------+------------------+-------------------+------------------ - | 123 | 456 | 579 - | 123 | 4567890123456789 | 4567890123456912 - | 4567890123456789 | 123 | 4567890123456912 - | 4567890123456789 | 4567890123456789 | 9135780246913578 - | 4567890123456789 | -4567890123456789 | 0 -(5 rows) - ---Testcase 46: -SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL; - five | q1 | q2 | minus -------+------------------+-------------------+------------------- - | 123 | 456 | -333 - | 123 | 4567890123456789 | -4567890123456666 - | 4567890123456789 | 123 | 4567890123456666 - | 4567890123456789 | 4567890123456789 | 0 - | 4567890123456789 | -4567890123456789 | 9135780246913578 -(5 rows) - ---Testcase 47: -SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL; -ERROR: bigint out of range ---Testcase 48: -SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL - WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); - three | q1 | q2 | multiply --------+------------------+------------------+-------------------- - | 123 | 456 | 56088 - | 123 | 4567890123456789 | 561850485185185047 - | 4567890123456789 | 123 | 561850485185185047 -(3 rows) - ---Testcase 49: -SELECT '' AS five, q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL; - five | q1 | q2 | divide | mod -------+------------------+-------------------+----------------+----- - | 123 | 456 | 0 | 123 - | 123 | 4567890123456789 | 0 | 123 - | 4567890123456789 | 123 | 37137318076884 | 57 - | 4567890123456789 | 4567890123456789 | 1 | 0 - | 4567890123456789 | -4567890123456789 | -1 | 0 -(5 rows) - ---Testcase 50: -SELECT '' AS five, q1, float8(q1) FROM INT8_TBL; - five | q1 | float8 -------+------------------+----------------------- - | 123 | 123 - | 123 | 123 - | 4567890123456789 | 4.567890123456789e+15 - | 4567890123456789 | 4.567890123456789e+15 - | 4567890123456789 | 4.567890123456789e+15 -(5 rows) - ---Testcase 51: -SELECT '' AS five, q2, float8(q2) FROM INT8_TBL; - five | q2 | float8 -------+-------------------+------------------------ - | 456 | 456 - | 4567890123456789 | 4.567890123456789e+15 - | 123 | 123 - | 4567890123456789 | 4.567890123456789e+15 - | -4567890123456789 | -4.567890123456789e+15 -(5 rows) - ---Testcase 52: -SELECT 37 + q1 AS plus4 FROM INT8_TBL; - plus4 ------------------- - 160 - 160 - 4567890123456826 - 4567890123456826 - 4567890123456826 -(5 rows) - ---Testcase 53: -SELECT 37 - q1 AS minus4 FROM INT8_TBL; - minus4 -------------------- - -86 - -86 - -4567890123456752 - -4567890123456752 - -4567890123456752 -(5 rows) - ---Testcase 54: -SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL; - five | twice int4 -------+------------------ - | 246 - | 246 - | 9135780246913578 - | 9135780246913578 - | 9135780246913578 -(5 rows) - ---Testcase 55: -SELECT '' AS five, q1 * 2 AS "twice int4" FROM INT8_TBL; - five | twice int4 -------+------------------ - | 246 - | 246 - | 9135780246913578 - | 9135780246913578 - | 9135780246913578 -(5 rows) - --- int8 op int4 ---Testcase 56: -SELECT q1 + 42::int4 AS "8plus4", q1 - 42::int4 AS "8minus4", q1 * 42::int4 AS "8mul4", q1 / 42::int4 AS "8div4" FROM INT8_TBL; - 8plus4 | 8minus4 | 8mul4 | 8div4 -------------------+------------------+--------------------+----------------- - 165 | 81 | 5166 | 2 - 165 | 81 | 5166 | 2 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 -(5 rows) - --- int4 op int8 ---Testcase 57: -SELECT 246::int4 + q1 AS "4plus8", 246::int4 - q1 AS "4minus8", 246::int4 * q1 AS "4mul8", 246::int4 / q1 AS "4div8" FROM INT8_TBL; - 4plus8 | 4minus8 | 4mul8 | 4div8 -------------------+-------------------+---------------------+------- - 369 | 123 | 30258 | 2 - 369 | 123 | 30258 | 2 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 -(5 rows) - --- int8 op int2 ---Testcase 58: -SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "8mul2", q1 / 42::int2 AS "8div2" FROM INT8_TBL; - 8plus2 | 8minus2 | 8mul2 | 8div2 -------------------+------------------+--------------------+----------------- - 165 | 81 | 5166 | 2 - 165 | 81 | 5166 | 2 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 - 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 -(5 rows) - --- int2 op int8 ---Testcase 59: -SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL; - 2plus8 | 2minus8 | 2mul8 | 2div8 -------------------+-------------------+---------------------+------- - 369 | 123 | 30258 | 2 - 369 | 123 | 30258 | 2 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 - 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 -(5 rows) - ---Testcase 60: -SELECT q2, abs(q2) FROM INT8_TBL; - q2 | abs --------------------+------------------ - 456 | 456 - 4567890123456789 | 4567890123456789 - 123 | 123 - 4567890123456789 | 4567890123456789 - -4567890123456789 | 4567890123456789 -(5 rows) - ---Testcase 61: -SELECT min(q1), min(q2) FROM INT8_TBL; - min | min ------+------------------- - 123 | -4567890123456789 -(1 row) - ---Testcase 62: -SELECT max(q1), max(q2) FROM INT8_TBL; - max | max -------------------+------------------ - 4567890123456789 | 4567890123456789 -(1 row) - --- TO_CHAR() --- ---Testcase 63: -SELECT '' AS to_char_1, to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999') - FROM INT8_TBL; - to_char_1 | to_char | to_char ------------+------------------------+------------------------ - | 123 | 456 - | 123 | 4,567,890,123,456,789 - | 4,567,890,123,456,789 | 123 - | 4,567,890,123,456,789 | 4,567,890,123,456,789 - | 4,567,890,123,456,789 | -4,567,890,123,456,789 -(5 rows) - ---Testcase 64: -SELECT '' AS to_char_2, to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999') - FROM INT8_TBL; - to_char_2 | to_char | to_char ------------+--------------------------------+-------------------------------- - | 123.000,000 | 456.000,000 - | 123.000,000 | 4,567,890,123,456,789.000,000 - | 4,567,890,123,456,789.000,000 | 123.000,000 - | 4,567,890,123,456,789.000,000 | 4,567,890,123,456,789.000,000 - | 4,567,890,123,456,789.000,000 | -4,567,890,123,456,789.000,000 -(5 rows) - ---Testcase 65: -SELECT '' AS to_char_3, to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR') - FROM INT8_TBL; - to_char_3 | to_char | to_char ------------+--------------------+------------------------ - | <123> | <456.000> - | <123> | <4567890123456789.000> - | <4567890123456789> | <123.000> - | <4567890123456789> | <4567890123456789.000> - | <4567890123456789> | 4567890123456789.000 -(5 rows) - ---Testcase 66: -SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999') - FROM INT8_TBL; - to_char_4 | to_char | to_char ------------+-------------------+------------------- - | 123- | -456 - | 123- | -4567890123456789 - | 4567890123456789- | -123 - | 4567890123456789- | -4567890123456789 - | 4567890123456789- | +4567890123456789 -(5 rows) - ---Testcase 67: -SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL; - to_char_5 | to_char ------------+------------------- - | 456 - | 4567890123456789 - | 123 - | 4567890123456789 - | -4567890123456789 -(5 rows) - ---Testcase 68: -SELECT '' AS to_char_6, to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; - to_char_6 | to_char ------------+------------------- - | +456 - | +4567890123456789 - | +123 - | +4567890123456789 - | -4567890123456789 -(5 rows) - ---Testcase 69: -SELECT '' AS to_char_7, to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL; - to_char_7 | to_char ------------+-------------------- - | 456TH - | 4567890123456789TH - | 123RD - | 4567890123456789TH - | <4567890123456789> -(5 rows) - ---Testcase 70: -SELECT '' AS to_char_8, to_char(q2, 'SG9999999999999999th') FROM INT8_TBL; - to_char_8 | to_char ------------+--------------------- - | + 456th - | +4567890123456789th - | + 123rd - | +4567890123456789th - | -4567890123456789 -(5 rows) - ---Testcase 71: -SELECT '' AS to_char_9, to_char(q2, '0999999999999999') FROM INT8_TBL; - to_char_9 | to_char ------------+------------------- - | 0000000000000456 - | 4567890123456789 - | 0000000000000123 - | 4567890123456789 - | -4567890123456789 -(5 rows) - ---Testcase 72: -SELECT '' AS to_char_10, to_char(q2, 'S0999999999999999') FROM INT8_TBL; - to_char_10 | to_char -------------+------------------- - | +0000000000000456 - | +4567890123456789 - | +0000000000000123 - | +4567890123456789 - | -4567890123456789 -(5 rows) - ---Testcase 73: -SELECT '' AS to_char_11, to_char(q2, 'FM0999999999999999') FROM INT8_TBL; - to_char_11 | to_char -------------+------------------- - | 0000000000000456 - | 4567890123456789 - | 0000000000000123 - | 4567890123456789 - | -4567890123456789 -(5 rows) - ---Testcase 74: -SELECT '' AS to_char_12, to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL; - to_char_12 | to_char -------------+----------------------- - | 456.000 - | 4567890123456789.000 - | 123.000 - | 4567890123456789.000 - | -4567890123456789.000 -(5 rows) - ---Testcase 75: -SELECT '' AS to_char_13, to_char(q2, 'L9999999999999999.000') FROM INT8_TBL; - to_char_13 | to_char -------------+------------------------ - | 456.000 - | 4567890123456789.000 - | 123.000 - | 4567890123456789.000 - | -4567890123456789.000 -(5 rows) - ---Testcase 76: -SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL; - to_char_14 | to_char -------------+-------------------- - | 456. - | 4567890123456789. - | 123. - | 4567890123456789. - | -4567890123456789. -(5 rows) - ---Testcase 77: -SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL; - to_char_15 | to_char -------------+------------------------------------------- - | +4 5 6 . 0 0 0 - | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 - | +1 2 3 . 0 0 0 - | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 - | -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 -(5 rows) - ---Testcase 78: -SELECT '' AS to_char_16, to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; - to_char_16 | to_char -------------+----------------------------------------------------------- - | text 9999 "text between quote marks" 456 - | 45678 text 9012 9999 345 "text between quote marks" 6789 - | text 9999 "text between quote marks" 123 - | 45678 text 9012 9999 345 "text between quote marks" 6789 - | -45678 text 9012 9999 345 "text between quote marks" 6789 -(5 rows) - ---Testcase 79: -SELECT '' AS to_char_17, to_char(q2, '999999SG9999999999') FROM INT8_TBL; - to_char_17 | to_char -------------+------------------- - | + 456 - | 456789+0123456789 - | + 123 - | 456789+0123456789 - | 456789-0123456789 -(5 rows) - --- check min/max values and overflow behavior ---Testcase 80: -DELETE FROM INT8_TMP; ---Testcase 144: -INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); ---Testcase 145: -SELECT q1 FROM INT8_TMP; - q1 ----------------------- - -9223372036854775808 -(1 row) - ---Testcase 81: -DELETE FROM INT8_TMP; ---Testcase 146: -INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); -ERROR: value "-9223372036854775809" is out of range for type bigint -LINE 1: INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); - ^ ---Testcase 147: -SELECT q1 FROM INT8_TMP; - q1 ----- -(0 rows) - ---Testcase 82: -DELETE FROM INT8_TMP; ---Testcase 148: -INSERT INTO INT8_TMP VALUES ('9223372036854775807'::int8); ---Testcase 149: -SELECT q1 FROM INT8_TMP; - q1 ---------------------- - 9223372036854775807 -(1 row) - ---Testcase 83: -DELETE FROM INT8_TMP; ---Testcase 150: -INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); -ERROR: value "9223372036854775808" is out of range for type bigint -LINE 1: INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); - ^ ---Testcase 151: -SELECT q1 FROM INT8_TMP; - q1 ----- -(0 rows) - ---Testcase 84: -DELETE FROM INT8_TMP; ---Testcase 152: -INSERT INTO INT8_TMP VALUES (-('-9223372036854775807'::int8)); ---Testcase 153: -SELECT q1 FROM INT8_TMP; - q1 ---------------------- - 9223372036854775807 -(1 row) - ---Testcase 86: -DELETE FROM INT8_TMP; ---Testcase 154: -INSERT INTO INT8_TMP VALUES (-('-9223372036854775808'::int8)); -ERROR: bigint out of range ---Testcase 155: -SELECT q1 FROM INT8_TMP; - q1 ----- -(0 rows) - ---Testcase 87: -DELETE FROM INT8_TMP; ---Testcase 156: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 157: -SELECT q1 + q2 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 88: -DELETE FROM INT8_TMP; ---Testcase 158: -INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '-9223372036854775800'::int8); ---Testcase 159: -SELECT q1 + q2 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 89: -DELETE FROM INT8_TMP; ---Testcase 160: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '-9223372036854775800'::int8); ---Testcase 161: -SELECT q1-q2 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 90: -DELETE FROM INT8_TMP; ---Testcase 162: -INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 163: -SELECT q1 - q2 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 91: -DELETE FROM INT8_TMP; ---Testcase 164: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 165: -SELECT q1 * q2 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 92: -DELETE FROM INT8_TMP; ---Testcase 166: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); ---Testcase 167: -SELECT q1 / q2 FROM INT8_TMP; -ERROR: division by zero ---Testcase 93: -DELETE FROM INT8_TMP; ---Testcase 168: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); ---Testcase 169: -SELECT q1 % q2 FROM INT8_TMP; -ERROR: division by zero ---Testcase 94: -DELETE FROM INT8_TMP; ---Testcase 170: -INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); ---Testcase 171: -SELECT abs(q1) FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 95: -DELETE FROM INT8_TMP; ---Testcase 172: -INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); ---Testcase 173: -SELECT q1 + q3 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 96: -DELETE FROM INT8_TMP; ---Testcase 174: -INSERT INTO INT8_TMP(q1, q3) VALUES ('-9223372036854775800'::int8 , '100'::int4); ---Testcase 175: -SELECT q1 - q3 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 97: -DELETE FROM INT8_TMP; ---Testcase 176: -INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); ---Testcase 177: -SELECT q1 * q3 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 98: -DELETE FROM INT8_TMP; ---Testcase 178: -INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); ---Testcase 179: -SELECT q3 + q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 99: -DELETE FROM INT8_TMP; ---Testcase 180: -INSERT INTO INT8_TMP(q3, q1) VALUES ('-100'::int4 , '9223372036854775800'::int8); ---Testcase 181: -SELECT q3 - q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 100: -DELETE FROM INT8_TMP; ---Testcase 182: -INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); ---Testcase 183: -SELECT q3 * q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 101: -DELETE FROM INT8_TMP; ---Testcase 184: -INSERT INTO INT8_TMP(q1, q4) VALUES ('9223372036854775800'::int8 , '100'::int2); ---Testcase 185: -SELECT q1 + q4 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 102: -DELETE FROM INT8_TMP; ---Testcase 186: -INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775800'::int8 , '100'::int2); ---Testcase 187: -SELECT q1 - q4 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 103: -DELETE FROM INT8_TMP; ---Testcase 188: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '100'::int2); ---Testcase 189: -SELECT q1 * q4 FROM INT8_TMP; - ?column? ----------- - -(1 row) - ---Testcase 104: -DELETE FROM INT8_TMP; ---Testcase 190: -INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775808'::int8 , '0'::int2); ---Testcase 191: -SELECT q1 / q4 FROM INT8_TMP; -ERROR: division by zero ---Testcase 105: -DELETE FROM INT8_TMP; ---Testcase 192: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); ---Testcase 193: -SELECT q4 + q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 106: -DELETE FROM INT8_TMP; ---Testcase 194: -INSERT INTO INT8_TMP(q4, q1) VALUES ('-100'::int2 , '9223372036854775800'::int8); ---Testcase 195: -SELECT q4 - q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 107: -DELETE FROM INT8_TMP; ---Testcase 196: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); ---Testcase 197: -SELECT q4 * q1 FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 108: -DELETE FROM INT8_TMP; ---Testcase 198: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '0'::int8); ---Testcase 199: -SELECT q4 / q1 FROM INT8_TMP; -ERROR: division by zero ---Testcase 110: -SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 = 456; - q1 ------ - 123 -(1 row) - ---Testcase 111: -SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 <> 456; -ERROR: integer out of range ---Testcase 112: -SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 = 456; - q1 ------ - 123 -(1 row) - ---Testcase 113: -SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 <> 456; -ERROR: smallint out of range ---Testcase 200: -DELETE FROM INT8_TMP; ---Testcase 201: -INSERT INTO INT8_TMP(q5) VALUES ('42'), ('-37'); ---Testcase 202: -SELECT CAST(q5::int2 as int8) FROM INT8_TMP; - q5 ------ - 42 - -37 -(2 rows) - ---Testcase 114: -SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL; - q1 | q2 --------------+------------------------ - 123 | 456 - 123 | 4.567890123456789e+15 - 4.56789e+15 | 123 - 4.56789e+15 | 4.567890123456789e+15 - 4.56789e+15 | -4.567890123456789e+15 -(5 rows) - ---Testcase 203: -DELETE FROM INT8_TMP; ---Testcase 204: -INSERT INTO INT8_TMP(q5) VALUES ('36854775807.0'); ---Testcase 205: -SELECT CAST(q5::float4 AS int8) FROM INT8_TMP; - q5 -------------- - 36854775808 -(1 row) - ---Testcase 206: -DELETE FROM INT8_TMP; ---Testcase 207: -INSERT INTO INT8_TMP(q5) VALUES ('922337203685477580700.0'); ---Testcase 208: -SELECT CAST(q5::float8 AS int8) FROM INT8_TMP; -ERROR: bigint out of range ---Testcase 115: -SELECT CAST(q1 AS oid) FROM INT8_TBL; -ERROR: OID out of range ---Testcase 209: -SELECT oid::int8 FROM pg_class WHERE relname = 'pg_class'; - oid ------- - 1259 -(1 row) - --- bit operations ---Testcase 116: -SELECT q1, q2, q1 & q2 AS "and", q1 | q2 AS "or", q1 # q2 AS "xor", ~q1 AS "not" FROM INT8_TBL; - q1 | q2 | and | or | xor | not -------------------+-------------------+------------------+------------------+------------------+------------------- - 123 | 456 | 72 | 507 | 435 | -124 - 123 | 4567890123456789 | 17 | 4567890123456895 | 4567890123456878 | -124 - 4567890123456789 | 123 | 17 | 4567890123456895 | 4567890123456878 | -4567890123456790 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 0 | -4567890123456790 - 4567890123456789 | -4567890123456789 | 1 | -1 | -2 | -4567890123456790 -(5 rows) - ---Testcase 117: -SELECT q1, q1 << 2 AS "shl", q1 >> 3 AS "shr" FROM INT8_TBL; - q1 | shl | shr -------------------+-------------------+----------------- - 123 | 492 | 15 - 123 | 492 | 15 - 4567890123456789 | 18271560493827156 | 570986265432098 - 4567890123456789 | 18271560493827156 | 570986265432098 - 4567890123456789 | 18271560493827156 | 570986265432098 -(5 rows) - --- generate_series ---Testcase 118: -DELETE FROM INT8_TMP; ---Testcase 210: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8) q1; ---Testcase 211: -SELECT q1 FROM INT8_TMP; - q1 ------------------- - 4567890123456789 - 4567890123456790 - 4567890123456791 - 4567890123456792 - 4567890123456793 - 4567890123456794 - 4567890123456795 - 4567890123456796 - 4567890123456797 - 4567890123456798 - 4567890123456799 -(11 rows) - ---Testcase 120: -DELETE FROM INT8_TMP; ---Testcase 212: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 0) q1; -- should error -ERROR: step size cannot equal zero ---Testcase 213: -SELECT q1 FROM INT8_TMP; - q1 ----- -(0 rows) - ---Testcase 122: -DELETE FROM INT8_TMP; ---Testcase 214: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 2) q1; ---Testcase 215: -SELECT q1 FROM INT8_TMP; - q1 ------------------- - 4567890123456789 - 4567890123456791 - 4567890123456793 - 4567890123456795 - 4567890123456797 - 4567890123456799 -(6 rows) - --- corner case ---Testcase 216: -DELETE FROM INT8_TMP; ---Testcase 217: -INSERT INTO INT8_TMP VALUES (-1::int8<<63); ---Testcase 218: -SELECT q1::text FROM INT8_TMP; - q1 ----------------------- - -9223372036854775808 -(1 row) - ---Testcase 219: -DELETE FROM INT8_TMP; ---Testcase 220: -INSERT INTO INT8_TMP VALUES ((-1::int8<<63)+1); ---Testcase 221: -SELECT q1::text FROM INT8_TMP; - q1 ----------------------- - -9223372036854775807 -(1 row) - --- check sane handling of INT64_MIN overflow cases ---Testcase 125: -DELETE FROM INT8_TMP; ---Testcase 222: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int8, 888); -ERROR: bigint out of range ---Testcase 126: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int8, 888); -ERROR: bigint out of range ---Testcase 127: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int8, 888); ---Testcase 128: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; - q1 ----- - 0 -(1 row) - ---Testcase 129: -DELETE FROM INT8_TMP WHERE q2 = 888; ---Testcase 130: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int4, 888); -ERROR: bigint out of range ---Testcase 131: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int4, 888); -ERROR: bigint out of range ---Testcase 132: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int4, 888); ---Testcase 133: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; - q1 ----- - 0 -(1 row) - ---Testcase 134: -DELETE FROM INT8_TMP WHERE q2 = 888; ---Testcase 135: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int2, 888); -ERROR: bigint out of range ---Testcase 136: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int2, 888); -ERROR: bigint out of range ---Testcase 137: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int2, 888); ---Testcase 138: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; - q1 ----- - 0 -(1 row) - ---Testcase 139: -DELETE FROM INT8_TMP WHERE q2 = 888; --- check rounding when casting from float ---Testcase 223: -CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 224: -DELETE FROM FLOAT8_TMP; ---Testcase 225: -INSERT INTO FLOAT8_TMP VALUES - (-2.5::float8), - (-1.5::float8), - (-0.5::float8), - (0.0::float8), - (0.5::float8), - (1.5::float8), - (2.5::float8); ---Testcase 226: -SELECT f1 as x, f1::int8 as int8_value FROM FLOAT8_TMP; - x | int8_value -------+------------ - -2.5 | -2 - -1.5 | -2 - -0.5 | 0 - 0 | 0 - 0.5 | 0 - 1.5 | 2 - 2.5 | 2 -(7 rows) - --- check rounding when casting from numeric ---Testcase 227: -CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 228: -DELETE FROM NUMERIC_TMP; ---Testcase 229: -INSERT INTO NUMERIC_TMP VALUES - (-2.5::numeric), - (-1.5::numeric), - (-0.5::numeric), - (0.0::numeric), - (0.5::numeric), - (1.5::numeric), - (2.5::numeric); ---Testcase 230: -SELECT f1 as x, f1::int8 as int8_value FROM NUMERIC_TMP; - x | int8_value -------+------------ - -2.5 | -3 - -1.5 | -2 - -0.5 | -1 - 0 | 0 - 0.5 | 1 - 1.5 | 2 - 2.5 | 3 -(7 rows) - --- test gcd() ---Testcase 231: -DELETE FROM INT8_TMP; ---Testcase 232: -INSERT INTO INT8_TMP VALUES - (0::int8, 0::int8), - (0::int8, 29893644334::int8), - (288484263558::int8, 29893644334::int8), - (-288484263558::int8, 29893644334::int8), - ((-9223372036854775808)::int8, 1::int8), - ((-9223372036854775808)::int8, 9223372036854775807::int8), - ((-9223372036854775808)::int8, 4611686018427387904::int8); ---Testcase 233: -SELECT q1, q2, gcd(q1, q2), gcd(q1, -q2), gcd(q2, q1), gcd(-q2, q1) FROM INT8_TMP; -ERROR: function gcd(bigint, bigint) does not exist -LINE 1: SELECT q1, q2, gcd(q1, q2), gcd(q1, -q2), gcd(q2, q1), gcd(-... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 234: -DELETE FROM INT8_TMP; ---Testcase 235: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 0::int8); ---Testcase 236: -SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow -ERROR: function gcd(bigint, bigint) does not exist -LINE 1: SELECT gcd(q1, q2) FROM INT8_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 237: -DELETE FROM INT8_TMP; ---Testcase 238: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, (-9223372036854775808)::int8); ---Testcase 239: -SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow -ERROR: function gcd(bigint, bigint) does not exist -LINE 1: SELECT gcd(q1, q2) FROM INT8_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- test lcm() ---Testcase 240: -DELETE FROM INT8_TMP; ---Testcase 241: -INSERT INTO INT8_TMP VALUES - (0::int8, 0::int8), - (0::int8, 29893644334::int8), - (29893644334::int8, 29893644334::int8), - (288484263558::int8, 29893644334::int8), - (-288484263558::int8, 29893644334::int8), - ((-9223372036854775808)::int8, 0::int8); ---Testcase 242: -SELECT q1, q2, lcm(q1, q2), lcm(q1, -q2), lcm(q2, q1), lcm(-q2, q1) FROM INT8_TMP; -ERROR: function lcm(bigint, bigint) does not exist -LINE 1: SELECT q1, q2, lcm(q1, q2), lcm(q1, -q2), lcm(q2, q1), lcm(-... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 243: -DELETE FROM INT8_TMP; ---Testcase 244: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 1::int8); ---Testcase 245: -SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow -ERROR: function lcm(bigint, bigint) does not exist -LINE 1: SELECT lcm(q1, q2) FROM INT8_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 246: -DELETE FROM INT8_TMP; ---Testcase 247: -INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806)::int8); ---Testcase 248: -SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow -ERROR: function lcm(bigint, bigint) does not exist -LINE 1: SELECT lcm(q1, q2) FROM INT8_TMP; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; ---Testcase 249: -DROP SERVER sqlite_svr; ---Testcase 250: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/join.out b/expected/12.16/extra/join.out deleted file mode 100644 index b9986c19..00000000 --- a/expected/12.16/extra/join.out +++ /dev/null @@ -1,6950 +0,0 @@ --- --- JOIN --- Test JOIN clauses --- ---Testcase 360: -CREATE EXTENSION sqlite_fdw; ---Testcase 361: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 362: -CREATE FOREIGN TABLE J1_TBL ( - i integer, - j integer, - t text -) SERVER sqlite_svr; ---Testcase 363: -CREATE FOREIGN TABLE J2_TBL ( - i integer, - k integer -) SERVER sqlite_svr; ---Testcase 364: -CREATE FOREIGN TABLE tenk1 ( - unique1 int4, - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 365: -CREATE FOREIGN TABLE tenk2 ( - unique1 int4, - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 366: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 367: -CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 368: -CREATE FOREIGN TABLE INT8_TBL( - q1 int8 OPTIONS (key 'true'), - q2 int8 OPTIONS (key 'true') -) SERVER sqlite_svr; ---Testcase 369: -CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 1: -INSERT INTO J1_TBL VALUES (1, 4, 'one'); ---Testcase 2: -INSERT INTO J1_TBL VALUES (2, 3, 'two'); ---Testcase 3: -INSERT INTO J1_TBL VALUES (3, 2, 'three'); ---Testcase 4: -INSERT INTO J1_TBL VALUES (4, 1, 'four'); ---Testcase 5: -INSERT INTO J1_TBL VALUES (5, 0, 'five'); ---Testcase 6: -INSERT INTO J1_TBL VALUES (6, 6, 'six'); ---Testcase 7: -INSERT INTO J1_TBL VALUES (7, 7, 'seven'); ---Testcase 8: -INSERT INTO J1_TBL VALUES (8, 8, 'eight'); ---Testcase 9: -INSERT INTO J1_TBL VALUES (0, NULL, 'zero'); ---Testcase 10: -INSERT INTO J1_TBL VALUES (NULL, NULL, 'null'); ---Testcase 11: -INSERT INTO J1_TBL VALUES (NULL, 0, 'zero'); ---Testcase 12: -INSERT INTO J2_TBL VALUES (1, -1); ---Testcase 13: -INSERT INTO J2_TBL VALUES (2, 2); ---Testcase 14: -INSERT INTO J2_TBL VALUES (3, -3); ---Testcase 15: -INSERT INTO J2_TBL VALUES (2, 4); ---Testcase 16: -INSERT INTO J2_TBL VALUES (5, -5); ---Testcase 17: -INSERT INTO J2_TBL VALUES (5, -5); ---Testcase 18: -INSERT INTO J2_TBL VALUES (0, NULL); ---Testcase 19: -INSERT INTO J2_TBL VALUES (NULL, NULL); ---Testcase 20: -INSERT INTO J2_TBL VALUES (NULL, 0); --- useful in some tests below ---Testcase 370: -create temp table onerow(); ---Testcase 371: -insert into onerow default values; -analyze onerow; --- --- CORRELATION NAMES --- Make sure that table/column aliases are supported --- before diving into more complex join syntax. --- ---Testcase 21: -SELECT '' AS "xxx", * - FROM J1_TBL AS tx; - xxx | i | j | t ------+---+---+------- - | 1 | 4 | one - | 2 | 3 | two - | 3 | 2 | three - | 4 | 1 | four - | 5 | 0 | five - | 6 | 6 | six - | 7 | 7 | seven - | 8 | 8 | eight - | 0 | | zero - | | | null - | | 0 | zero -(11 rows) - ---Testcase 22: -SELECT '' AS "xxx", * - FROM J1_TBL tx; - xxx | i | j | t ------+---+---+------- - | 1 | 4 | one - | 2 | 3 | two - | 3 | 2 | three - | 4 | 1 | four - | 5 | 0 | five - | 6 | 6 | six - | 7 | 7 | seven - | 8 | 8 | eight - | 0 | | zero - | | | null - | | 0 | zero -(11 rows) - ---Testcase 23: -SELECT '' AS "xxx", * - FROM J1_TBL AS t1 (a, b, c); - xxx | a | b | c ------+---+---+------- - | 1 | 4 | one - | 2 | 3 | two - | 3 | 2 | three - | 4 | 1 | four - | 5 | 0 | five - | 6 | 6 | six - | 7 | 7 | seven - | 8 | 8 | eight - | 0 | | zero - | | | null - | | 0 | zero -(11 rows) - ---Testcase 24: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c); - xxx | a | b | c ------+---+---+------- - | 1 | 4 | one - | 2 | 3 | two - | 3 | 2 | three - | 4 | 1 | four - | 5 | 0 | five - | 6 | 6 | six - | 7 | 7 | seven - | 8 | 8 | eight - | 0 | | zero - | | | null - | | 0 | zero -(11 rows) - ---Testcase 25: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e); - xxx | a | b | c | d | e ------+---+---+-------+---+---- - | 1 | 4 | one | 1 | -1 - | 2 | 3 | two | 1 | -1 - | 3 | 2 | three | 1 | -1 - | 4 | 1 | four | 1 | -1 - | 5 | 0 | five | 1 | -1 - | 6 | 6 | six | 1 | -1 - | 7 | 7 | seven | 1 | -1 - | 8 | 8 | eight | 1 | -1 - | 0 | | zero | 1 | -1 - | | | null | 1 | -1 - | | 0 | zero | 1 | -1 - | 1 | 4 | one | 2 | 2 - | 2 | 3 | two | 2 | 2 - | 3 | 2 | three | 2 | 2 - | 4 | 1 | four | 2 | 2 - | 5 | 0 | five | 2 | 2 - | 6 | 6 | six | 2 | 2 - | 7 | 7 | seven | 2 | 2 - | 8 | 8 | eight | 2 | 2 - | 0 | | zero | 2 | 2 - | | | null | 2 | 2 - | | 0 | zero | 2 | 2 - | 1 | 4 | one | 3 | -3 - | 2 | 3 | two | 3 | -3 - | 3 | 2 | three | 3 | -3 - | 4 | 1 | four | 3 | -3 - | 5 | 0 | five | 3 | -3 - | 6 | 6 | six | 3 | -3 - | 7 | 7 | seven | 3 | -3 - | 8 | 8 | eight | 3 | -3 - | 0 | | zero | 3 | -3 - | | | null | 3 | -3 - | | 0 | zero | 3 | -3 - | 1 | 4 | one | 2 | 4 - | 2 | 3 | two | 2 | 4 - | 3 | 2 | three | 2 | 4 - | 4 | 1 | four | 2 | 4 - | 5 | 0 | five | 2 | 4 - | 6 | 6 | six | 2 | 4 - | 7 | 7 | seven | 2 | 4 - | 8 | 8 | eight | 2 | 4 - | 0 | | zero | 2 | 4 - | | | null | 2 | 4 - | | 0 | zero | 2 | 4 - | 1 | 4 | one | 5 | -5 - | 2 | 3 | two | 5 | -5 - | 3 | 2 | three | 5 | -5 - | 4 | 1 | four | 5 | -5 - | 5 | 0 | five | 5 | -5 - | 6 | 6 | six | 5 | -5 - | 7 | 7 | seven | 5 | -5 - | 8 | 8 | eight | 5 | -5 - | 0 | | zero | 5 | -5 - | | | null | 5 | -5 - | | 0 | zero | 5 | -5 - | 1 | 4 | one | 5 | -5 - | 2 | 3 | two | 5 | -5 - | 3 | 2 | three | 5 | -5 - | 4 | 1 | four | 5 | -5 - | 5 | 0 | five | 5 | -5 - | 6 | 6 | six | 5 | -5 - | 7 | 7 | seven | 5 | -5 - | 8 | 8 | eight | 5 | -5 - | 0 | | zero | 5 | -5 - | | | null | 5 | -5 - | | 0 | zero | 5 | -5 - | 1 | 4 | one | 0 | - | 2 | 3 | two | 0 | - | 3 | 2 | three | 0 | - | 4 | 1 | four | 0 | - | 5 | 0 | five | 0 | - | 6 | 6 | six | 0 | - | 7 | 7 | seven | 0 | - | 8 | 8 | eight | 0 | - | 0 | | zero | 0 | - | | | null | 0 | - | | 0 | zero | 0 | - | 1 | 4 | one | | - | 2 | 3 | two | | - | 3 | 2 | three | | - | 4 | 1 | four | | - | 5 | 0 | five | | - | 6 | 6 | six | | - | 7 | 7 | seven | | - | 8 | 8 | eight | | - | 0 | | zero | | - | | | null | | - | | 0 | zero | | - | 1 | 4 | one | | 0 - | 2 | 3 | two | | 0 - | 3 | 2 | three | | 0 - | 4 | 1 | four | | 0 - | 5 | 0 | five | | 0 - | 6 | 6 | six | | 0 - | 7 | 7 | seven | | 0 - | 8 | 8 | eight | | 0 - | 0 | | zero | | 0 - | | | null | | 0 - | | 0 | zero | | 0 -(99 rows) - ---Testcase 26: -SELECT '' AS "xxx", t1.a, t2.e - FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e) - WHERE t1.a = t2.d; - xxx | a | e ------+---+---- - | 0 | - | 1 | -1 - | 2 | 2 - | 2 | 4 - | 3 | -3 - | 5 | -5 - | 5 | -5 -(7 rows) - --- --- CROSS JOIN --- Qualifications are not allowed on cross joins, --- which degenerate into a standard unqualified inner join. --- ---Testcase 27: -SELECT '' AS "xxx", * - FROM J1_TBL CROSS JOIN J2_TBL; - xxx | i | j | t | i | k ------+---+---+-------+---+---- - | 1 | 4 | one | 1 | -1 - | 2 | 3 | two | 1 | -1 - | 3 | 2 | three | 1 | -1 - | 4 | 1 | four | 1 | -1 - | 5 | 0 | five | 1 | -1 - | 6 | 6 | six | 1 | -1 - | 7 | 7 | seven | 1 | -1 - | 8 | 8 | eight | 1 | -1 - | 0 | | zero | 1 | -1 - | | | null | 1 | -1 - | | 0 | zero | 1 | -1 - | 1 | 4 | one | 2 | 2 - | 2 | 3 | two | 2 | 2 - | 3 | 2 | three | 2 | 2 - | 4 | 1 | four | 2 | 2 - | 5 | 0 | five | 2 | 2 - | 6 | 6 | six | 2 | 2 - | 7 | 7 | seven | 2 | 2 - | 8 | 8 | eight | 2 | 2 - | 0 | | zero | 2 | 2 - | | | null | 2 | 2 - | | 0 | zero | 2 | 2 - | 1 | 4 | one | 3 | -3 - | 2 | 3 | two | 3 | -3 - | 3 | 2 | three | 3 | -3 - | 4 | 1 | four | 3 | -3 - | 5 | 0 | five | 3 | -3 - | 6 | 6 | six | 3 | -3 - | 7 | 7 | seven | 3 | -3 - | 8 | 8 | eight | 3 | -3 - | 0 | | zero | 3 | -3 - | | | null | 3 | -3 - | | 0 | zero | 3 | -3 - | 1 | 4 | one | 2 | 4 - | 2 | 3 | two | 2 | 4 - | 3 | 2 | three | 2 | 4 - | 4 | 1 | four | 2 | 4 - | 5 | 0 | five | 2 | 4 - | 6 | 6 | six | 2 | 4 - | 7 | 7 | seven | 2 | 4 - | 8 | 8 | eight | 2 | 4 - | 0 | | zero | 2 | 4 - | | | null | 2 | 4 - | | 0 | zero | 2 | 4 - | 1 | 4 | one | 5 | -5 - | 2 | 3 | two | 5 | -5 - | 3 | 2 | three | 5 | -5 - | 4 | 1 | four | 5 | -5 - | 5 | 0 | five | 5 | -5 - | 6 | 6 | six | 5 | -5 - | 7 | 7 | seven | 5 | -5 - | 8 | 8 | eight | 5 | -5 - | 0 | | zero | 5 | -5 - | | | null | 5 | -5 - | | 0 | zero | 5 | -5 - | 1 | 4 | one | 5 | -5 - | 2 | 3 | two | 5 | -5 - | 3 | 2 | three | 5 | -5 - | 4 | 1 | four | 5 | -5 - | 5 | 0 | five | 5 | -5 - | 6 | 6 | six | 5 | -5 - | 7 | 7 | seven | 5 | -5 - | 8 | 8 | eight | 5 | -5 - | 0 | | zero | 5 | -5 - | | | null | 5 | -5 - | | 0 | zero | 5 | -5 - | 1 | 4 | one | 0 | - | 2 | 3 | two | 0 | - | 3 | 2 | three | 0 | - | 4 | 1 | four | 0 | - | 5 | 0 | five | 0 | - | 6 | 6 | six | 0 | - | 7 | 7 | seven | 0 | - | 8 | 8 | eight | 0 | - | 0 | | zero | 0 | - | | | null | 0 | - | | 0 | zero | 0 | - | 1 | 4 | one | | - | 2 | 3 | two | | - | 3 | 2 | three | | - | 4 | 1 | four | | - | 5 | 0 | five | | - | 6 | 6 | six | | - | 7 | 7 | seven | | - | 8 | 8 | eight | | - | 0 | | zero | | - | | | null | | - | | 0 | zero | | - | 1 | 4 | one | | 0 - | 2 | 3 | two | | 0 - | 3 | 2 | three | | 0 - | 4 | 1 | four | | 0 - | 5 | 0 | five | | 0 - | 6 | 6 | six | | 0 - | 7 | 7 | seven | | 0 - | 8 | 8 | eight | | 0 - | 0 | | zero | | 0 - | | | null | | 0 - | | 0 | zero | | 0 -(99 rows) - --- ambiguous column ---Testcase 28: -SELECT '' AS "xxx", i, k, t - FROM J1_TBL CROSS JOIN J2_TBL; -ERROR: column reference "i" is ambiguous -LINE 1: SELECT '' AS "xxx", i, k, t - ^ --- resolve previous ambiguity by specifying the table name ---Testcase 29: -SELECT '' AS "xxx", t1.i, k, t - FROM J1_TBL t1 CROSS JOIN J2_TBL t2; - xxx | i | k | t ------+---+----+------- - | 1 | -1 | one - | 2 | -1 | two - | 3 | -1 | three - | 4 | -1 | four - | 5 | -1 | five - | 6 | -1 | six - | 7 | -1 | seven - | 8 | -1 | eight - | 0 | -1 | zero - | | -1 | null - | | -1 | zero - | 1 | 2 | one - | 2 | 2 | two - | 3 | 2 | three - | 4 | 2 | four - | 5 | 2 | five - | 6 | 2 | six - | 7 | 2 | seven - | 8 | 2 | eight - | 0 | 2 | zero - | | 2 | null - | | 2 | zero - | 1 | -3 | one - | 2 | -3 | two - | 3 | -3 | three - | 4 | -3 | four - | 5 | -3 | five - | 6 | -3 | six - | 7 | -3 | seven - | 8 | -3 | eight - | 0 | -3 | zero - | | -3 | null - | | -3 | zero - | 1 | 4 | one - | 2 | 4 | two - | 3 | 4 | three - | 4 | 4 | four - | 5 | 4 | five - | 6 | 4 | six - | 7 | 4 | seven - | 8 | 4 | eight - | 0 | 4 | zero - | | 4 | null - | | 4 | zero - | 1 | -5 | one - | 2 | -5 | two - | 3 | -5 | three - | 4 | -5 | four - | 5 | -5 | five - | 6 | -5 | six - | 7 | -5 | seven - | 8 | -5 | eight - | 0 | -5 | zero - | | -5 | null - | | -5 | zero - | 1 | -5 | one - | 2 | -5 | two - | 3 | -5 | three - | 4 | -5 | four - | 5 | -5 | five - | 6 | -5 | six - | 7 | -5 | seven - | 8 | -5 | eight - | 0 | -5 | zero - | | -5 | null - | | -5 | zero - | 1 | | one - | 2 | | two - | 3 | | three - | 4 | | four - | 5 | | five - | 6 | | six - | 7 | | seven - | 8 | | eight - | 0 | | zero - | | | null - | | | zero - | 1 | | one - | 2 | | two - | 3 | | three - | 4 | | four - | 5 | | five - | 6 | | six - | 7 | | seven - | 8 | | eight - | 0 | | zero - | | | null - | | | zero - | 1 | 0 | one - | 2 | 0 | two - | 3 | 0 | three - | 4 | 0 | four - | 5 | 0 | five - | 6 | 0 | six - | 7 | 0 | seven - | 8 | 0 | eight - | 0 | 0 | zero - | | 0 | null - | | 0 | zero -(99 rows) - ---Testcase 30: -SELECT '' AS "xxx", ii, tt, kk - FROM (J1_TBL CROSS JOIN J2_TBL) - AS tx (ii, jj, tt, ii2, kk); - xxx | ii | tt | kk ------+----+-------+---- - | 1 | one | -1 - | 2 | two | -1 - | 3 | three | -1 - | 4 | four | -1 - | 5 | five | -1 - | 6 | six | -1 - | 7 | seven | -1 - | 8 | eight | -1 - | 0 | zero | -1 - | | null | -1 - | | zero | -1 - | 1 | one | 2 - | 2 | two | 2 - | 3 | three | 2 - | 4 | four | 2 - | 5 | five | 2 - | 6 | six | 2 - | 7 | seven | 2 - | 8 | eight | 2 - | 0 | zero | 2 - | | null | 2 - | | zero | 2 - | 1 | one | -3 - | 2 | two | -3 - | 3 | three | -3 - | 4 | four | -3 - | 5 | five | -3 - | 6 | six | -3 - | 7 | seven | -3 - | 8 | eight | -3 - | 0 | zero | -3 - | | null | -3 - | | zero | -3 - | 1 | one | 4 - | 2 | two | 4 - | 3 | three | 4 - | 4 | four | 4 - | 5 | five | 4 - | 6 | six | 4 - | 7 | seven | 4 - | 8 | eight | 4 - | 0 | zero | 4 - | | null | 4 - | | zero | 4 - | 1 | one | -5 - | 2 | two | -5 - | 3 | three | -5 - | 4 | four | -5 - | 5 | five | -5 - | 6 | six | -5 - | 7 | seven | -5 - | 8 | eight | -5 - | 0 | zero | -5 - | | null | -5 - | | zero | -5 - | 1 | one | -5 - | 2 | two | -5 - | 3 | three | -5 - | 4 | four | -5 - | 5 | five | -5 - | 6 | six | -5 - | 7 | seven | -5 - | 8 | eight | -5 - | 0 | zero | -5 - | | null | -5 - | | zero | -5 - | 1 | one | - | 2 | two | - | 3 | three | - | 4 | four | - | 5 | five | - | 6 | six | - | 7 | seven | - | 8 | eight | - | 0 | zero | - | | null | - | | zero | - | 1 | one | - | 2 | two | - | 3 | three | - | 4 | four | - | 5 | five | - | 6 | six | - | 7 | seven | - | 8 | eight | - | 0 | zero | - | | null | - | | zero | - | 1 | one | 0 - | 2 | two | 0 - | 3 | three | 0 - | 4 | four | 0 - | 5 | five | 0 - | 6 | six | 0 - | 7 | seven | 0 - | 8 | eight | 0 - | 0 | zero | 0 - | | null | 0 - | | zero | 0 -(99 rows) - ---Testcase 31: -SELECT '' AS "xxx", tx.ii, tx.jj, tx.kk - FROM (J1_TBL t1 (a, b, c) CROSS JOIN J2_TBL t2 (d, e)) - AS tx (ii, jj, tt, ii2, kk); - xxx | ii | jj | kk ------+----+----+---- - | 1 | 4 | -1 - | 2 | 3 | -1 - | 3 | 2 | -1 - | 4 | 1 | -1 - | 5 | 0 | -1 - | 6 | 6 | -1 - | 7 | 7 | -1 - | 8 | 8 | -1 - | 0 | | -1 - | | | -1 - | | 0 | -1 - | 1 | 4 | 2 - | 2 | 3 | 2 - | 3 | 2 | 2 - | 4 | 1 | 2 - | 5 | 0 | 2 - | 6 | 6 | 2 - | 7 | 7 | 2 - | 8 | 8 | 2 - | 0 | | 2 - | | | 2 - | | 0 | 2 - | 1 | 4 | -3 - | 2 | 3 | -3 - | 3 | 2 | -3 - | 4 | 1 | -3 - | 5 | 0 | -3 - | 6 | 6 | -3 - | 7 | 7 | -3 - | 8 | 8 | -3 - | 0 | | -3 - | | | -3 - | | 0 | -3 - | 1 | 4 | 4 - | 2 | 3 | 4 - | 3 | 2 | 4 - | 4 | 1 | 4 - | 5 | 0 | 4 - | 6 | 6 | 4 - | 7 | 7 | 4 - | 8 | 8 | 4 - | 0 | | 4 - | | | 4 - | | 0 | 4 - | 1 | 4 | -5 - | 2 | 3 | -5 - | 3 | 2 | -5 - | 4 | 1 | -5 - | 5 | 0 | -5 - | 6 | 6 | -5 - | 7 | 7 | -5 - | 8 | 8 | -5 - | 0 | | -5 - | | | -5 - | | 0 | -5 - | 1 | 4 | -5 - | 2 | 3 | -5 - | 3 | 2 | -5 - | 4 | 1 | -5 - | 5 | 0 | -5 - | 6 | 6 | -5 - | 7 | 7 | -5 - | 8 | 8 | -5 - | 0 | | -5 - | | | -5 - | | 0 | -5 - | 1 | 4 | - | 2 | 3 | - | 3 | 2 | - | 4 | 1 | - | 5 | 0 | - | 6 | 6 | - | 7 | 7 | - | 8 | 8 | - | 0 | | - | | | - | | 0 | - | 1 | 4 | - | 2 | 3 | - | 3 | 2 | - | 4 | 1 | - | 5 | 0 | - | 6 | 6 | - | 7 | 7 | - | 8 | 8 | - | 0 | | - | | | - | | 0 | - | 1 | 4 | 0 - | 2 | 3 | 0 - | 3 | 2 | 0 - | 4 | 1 | 0 - | 5 | 0 | 0 - | 6 | 6 | 0 - | 7 | 7 | 0 - | 8 | 8 | 0 - | 0 | | 0 - | | | 0 - | | 0 | 0 -(99 rows) - ---Testcase 32: -SELECT '' AS "xxx", * - FROM J1_TBL CROSS JOIN J2_TBL a CROSS JOIN J2_TBL b; - xxx | i | j | t | i | k | i | k ------+---+---+-------+---+----+---+---- - | 1 | 4 | one | 1 | -1 | 1 | -1 - | 1 | 4 | one | 1 | -1 | 2 | 2 - | 1 | 4 | one | 1 | -1 | 3 | -3 - | 1 | 4 | one | 1 | -1 | 2 | 4 - | 1 | 4 | one | 1 | -1 | 5 | -5 - | 1 | 4 | one | 1 | -1 | 5 | -5 - | 1 | 4 | one | 1 | -1 | 0 | - | 1 | 4 | one | 1 | -1 | | - | 1 | 4 | one | 1 | -1 | | 0 - | 2 | 3 | two | 1 | -1 | 1 | -1 - | 2 | 3 | two | 1 | -1 | 2 | 2 - | 2 | 3 | two | 1 | -1 | 3 | -3 - | 2 | 3 | two | 1 | -1 | 2 | 4 - | 2 | 3 | two | 1 | -1 | 5 | -5 - | 2 | 3 | two | 1 | -1 | 5 | -5 - | 2 | 3 | two | 1 | -1 | 0 | - | 2 | 3 | two | 1 | -1 | | - | 2 | 3 | two | 1 | -1 | | 0 - | 3 | 2 | three | 1 | -1 | 1 | -1 - | 3 | 2 | three | 1 | -1 | 2 | 2 - | 3 | 2 | three | 1 | -1 | 3 | -3 - | 3 | 2 | three | 1 | -1 | 2 | 4 - | 3 | 2 | three | 1 | -1 | 5 | -5 - | 3 | 2 | three | 1 | -1 | 5 | -5 - | 3 | 2 | three | 1 | -1 | 0 | - | 3 | 2 | three | 1 | -1 | | - | 3 | 2 | three | 1 | -1 | | 0 - | 4 | 1 | four | 1 | -1 | 1 | -1 - | 4 | 1 | four | 1 | -1 | 2 | 2 - | 4 | 1 | four | 1 | -1 | 3 | -3 - | 4 | 1 | four | 1 | -1 | 2 | 4 - | 4 | 1 | four | 1 | -1 | 5 | -5 - | 4 | 1 | four | 1 | -1 | 5 | -5 - | 4 | 1 | four | 1 | -1 | 0 | - | 4 | 1 | four | 1 | -1 | | - | 4 | 1 | four | 1 | -1 | | 0 - | 5 | 0 | five | 1 | -1 | 1 | -1 - | 5 | 0 | five | 1 | -1 | 2 | 2 - | 5 | 0 | five | 1 | -1 | 3 | -3 - | 5 | 0 | five | 1 | -1 | 2 | 4 - | 5 | 0 | five | 1 | -1 | 5 | -5 - | 5 | 0 | five | 1 | -1 | 5 | -5 - | 5 | 0 | five | 1 | -1 | 0 | - | 5 | 0 | five | 1 | -1 | | - | 5 | 0 | five | 1 | -1 | | 0 - | 6 | 6 | six | 1 | -1 | 1 | -1 - | 6 | 6 | six | 1 | -1 | 2 | 2 - | 6 | 6 | six | 1 | -1 | 3 | -3 - | 6 | 6 | six | 1 | -1 | 2 | 4 - | 6 | 6 | six | 1 | -1 | 5 | -5 - | 6 | 6 | six | 1 | -1 | 5 | -5 - | 6 | 6 | six | 1 | -1 | 0 | - | 6 | 6 | six | 1 | -1 | | - | 6 | 6 | six | 1 | -1 | | 0 - | 7 | 7 | seven | 1 | -1 | 1 | -1 - | 7 | 7 | seven | 1 | -1 | 2 | 2 - | 7 | 7 | seven | 1 | -1 | 3 | -3 - | 7 | 7 | seven | 1 | -1 | 2 | 4 - | 7 | 7 | seven | 1 | -1 | 5 | -5 - | 7 | 7 | seven | 1 | -1 | 5 | -5 - | 7 | 7 | seven | 1 | -1 | 0 | - | 7 | 7 | seven | 1 | -1 | | - | 7 | 7 | seven | 1 | -1 | | 0 - | 8 | 8 | eight | 1 | -1 | 1 | -1 - | 8 | 8 | eight | 1 | -1 | 2 | 2 - | 8 | 8 | eight | 1 | -1 | 3 | -3 - | 8 | 8 | eight | 1 | -1 | 2 | 4 - | 8 | 8 | eight | 1 | -1 | 5 | -5 - | 8 | 8 | eight | 1 | -1 | 5 | -5 - | 8 | 8 | eight | 1 | -1 | 0 | - | 8 | 8 | eight | 1 | -1 | | - | 8 | 8 | eight | 1 | -1 | | 0 - | 0 | | zero | 1 | -1 | 1 | -1 - | 0 | | zero | 1 | -1 | 2 | 2 - | 0 | | zero | 1 | -1 | 3 | -3 - | 0 | | zero | 1 | -1 | 2 | 4 - | 0 | | zero | 1 | -1 | 5 | -5 - | 0 | | zero | 1 | -1 | 5 | -5 - | 0 | | zero | 1 | -1 | 0 | - | 0 | | zero | 1 | -1 | | - | 0 | | zero | 1 | -1 | | 0 - | | | null | 1 | -1 | 1 | -1 - | | | null | 1 | -1 | 2 | 2 - | | | null | 1 | -1 | 3 | -3 - | | | null | 1 | -1 | 2 | 4 - | | | null | 1 | -1 | 5 | -5 - | | | null | 1 | -1 | 5 | -5 - | | | null | 1 | -1 | 0 | - | | | null | 1 | -1 | | - | | | null | 1 | -1 | | 0 - | | 0 | zero | 1 | -1 | 1 | -1 - | | 0 | zero | 1 | -1 | 2 | 2 - | | 0 | zero | 1 | -1 | 3 | -3 - | | 0 | zero | 1 | -1 | 2 | 4 - | | 0 | zero | 1 | -1 | 5 | -5 - | | 0 | zero | 1 | -1 | 5 | -5 - | | 0 | zero | 1 | -1 | 0 | - | | 0 | zero | 1 | -1 | | - | | 0 | zero | 1 | -1 | | 0 - | 1 | 4 | one | 2 | 2 | 1 | -1 - | 1 | 4 | one | 2 | 2 | 2 | 2 - | 1 | 4 | one | 2 | 2 | 3 | -3 - | 1 | 4 | one | 2 | 2 | 2 | 4 - | 1 | 4 | one | 2 | 2 | 5 | -5 - | 1 | 4 | one | 2 | 2 | 5 | -5 - | 1 | 4 | one | 2 | 2 | 0 | - | 1 | 4 | one | 2 | 2 | | - | 1 | 4 | one | 2 | 2 | | 0 - | 2 | 3 | two | 2 | 2 | 1 | -1 - | 2 | 3 | two | 2 | 2 | 2 | 2 - | 2 | 3 | two | 2 | 2 | 3 | -3 - | 2 | 3 | two | 2 | 2 | 2 | 4 - | 2 | 3 | two | 2 | 2 | 5 | -5 - | 2 | 3 | two | 2 | 2 | 5 | -5 - | 2 | 3 | two | 2 | 2 | 0 | - | 2 | 3 | two | 2 | 2 | | - | 2 | 3 | two | 2 | 2 | | 0 - | 3 | 2 | three | 2 | 2 | 1 | -1 - | 3 | 2 | three | 2 | 2 | 2 | 2 - | 3 | 2 | three | 2 | 2 | 3 | -3 - | 3 | 2 | three | 2 | 2 | 2 | 4 - | 3 | 2 | three | 2 | 2 | 5 | -5 - | 3 | 2 | three | 2 | 2 | 5 | -5 - | 3 | 2 | three | 2 | 2 | 0 | - | 3 | 2 | three | 2 | 2 | | - | 3 | 2 | three | 2 | 2 | | 0 - | 4 | 1 | four | 2 | 2 | 1 | -1 - | 4 | 1 | four | 2 | 2 | 2 | 2 - | 4 | 1 | four | 2 | 2 | 3 | -3 - | 4 | 1 | four | 2 | 2 | 2 | 4 - | 4 | 1 | four | 2 | 2 | 5 | -5 - | 4 | 1 | four | 2 | 2 | 5 | -5 - | 4 | 1 | four | 2 | 2 | 0 | - | 4 | 1 | four | 2 | 2 | | - | 4 | 1 | four | 2 | 2 | | 0 - | 5 | 0 | five | 2 | 2 | 1 | -1 - | 5 | 0 | five | 2 | 2 | 2 | 2 - | 5 | 0 | five | 2 | 2 | 3 | -3 - | 5 | 0 | five | 2 | 2 | 2 | 4 - | 5 | 0 | five | 2 | 2 | 5 | -5 - | 5 | 0 | five | 2 | 2 | 5 | -5 - | 5 | 0 | five | 2 | 2 | 0 | - | 5 | 0 | five | 2 | 2 | | - | 5 | 0 | five | 2 | 2 | | 0 - | 6 | 6 | six | 2 | 2 | 1 | -1 - | 6 | 6 | six | 2 | 2 | 2 | 2 - | 6 | 6 | six | 2 | 2 | 3 | -3 - | 6 | 6 | six | 2 | 2 | 2 | 4 - | 6 | 6 | six | 2 | 2 | 5 | -5 - | 6 | 6 | six | 2 | 2 | 5 | -5 - | 6 | 6 | six | 2 | 2 | 0 | - | 6 | 6 | six | 2 | 2 | | - | 6 | 6 | six | 2 | 2 | | 0 - | 7 | 7 | seven | 2 | 2 | 1 | -1 - | 7 | 7 | seven | 2 | 2 | 2 | 2 - | 7 | 7 | seven | 2 | 2 | 3 | -3 - | 7 | 7 | seven | 2 | 2 | 2 | 4 - | 7 | 7 | seven | 2 | 2 | 5 | -5 - | 7 | 7 | seven | 2 | 2 | 5 | -5 - | 7 | 7 | seven | 2 | 2 | 0 | - | 7 | 7 | seven | 2 | 2 | | - | 7 | 7 | seven | 2 | 2 | | 0 - | 8 | 8 | eight | 2 | 2 | 1 | -1 - | 8 | 8 | eight | 2 | 2 | 2 | 2 - | 8 | 8 | eight | 2 | 2 | 3 | -3 - | 8 | 8 | eight | 2 | 2 | 2 | 4 - | 8 | 8 | eight | 2 | 2 | 5 | -5 - | 8 | 8 | eight | 2 | 2 | 5 | -5 - | 8 | 8 | eight | 2 | 2 | 0 | - | 8 | 8 | eight | 2 | 2 | | - | 8 | 8 | eight | 2 | 2 | | 0 - | 0 | | zero | 2 | 2 | 1 | -1 - | 0 | | zero | 2 | 2 | 2 | 2 - | 0 | | zero | 2 | 2 | 3 | -3 - | 0 | | zero | 2 | 2 | 2 | 4 - | 0 | | zero | 2 | 2 | 5 | -5 - | 0 | | zero | 2 | 2 | 5 | -5 - | 0 | | zero | 2 | 2 | 0 | - | 0 | | zero | 2 | 2 | | - | 0 | | zero | 2 | 2 | | 0 - | | | null | 2 | 2 | 1 | -1 - | | | null | 2 | 2 | 2 | 2 - | | | null | 2 | 2 | 3 | -3 - | | | null | 2 | 2 | 2 | 4 - | | | null | 2 | 2 | 5 | -5 - | | | null | 2 | 2 | 5 | -5 - | | | null | 2 | 2 | 0 | - | | | null | 2 | 2 | | - | | | null | 2 | 2 | | 0 - | | 0 | zero | 2 | 2 | 1 | -1 - | | 0 | zero | 2 | 2 | 2 | 2 - | | 0 | zero | 2 | 2 | 3 | -3 - | | 0 | zero | 2 | 2 | 2 | 4 - | | 0 | zero | 2 | 2 | 5 | -5 - | | 0 | zero | 2 | 2 | 5 | -5 - | | 0 | zero | 2 | 2 | 0 | - | | 0 | zero | 2 | 2 | | - | | 0 | zero | 2 | 2 | | 0 - | 1 | 4 | one | 3 | -3 | 1 | -1 - | 1 | 4 | one | 3 | -3 | 2 | 2 - | 1 | 4 | one | 3 | -3 | 3 | -3 - | 1 | 4 | one | 3 | -3 | 2 | 4 - | 1 | 4 | one | 3 | -3 | 5 | -5 - | 1 | 4 | one | 3 | -3 | 5 | -5 - | 1 | 4 | one | 3 | -3 | 0 | - | 1 | 4 | one | 3 | -3 | | - | 1 | 4 | one | 3 | -3 | | 0 - | 2 | 3 | two | 3 | -3 | 1 | -1 - | 2 | 3 | two | 3 | -3 | 2 | 2 - | 2 | 3 | two | 3 | -3 | 3 | -3 - | 2 | 3 | two | 3 | -3 | 2 | 4 - | 2 | 3 | two | 3 | -3 | 5 | -5 - | 2 | 3 | two | 3 | -3 | 5 | -5 - | 2 | 3 | two | 3 | -3 | 0 | - | 2 | 3 | two | 3 | -3 | | - | 2 | 3 | two | 3 | -3 | | 0 - | 3 | 2 | three | 3 | -3 | 1 | -1 - | 3 | 2 | three | 3 | -3 | 2 | 2 - | 3 | 2 | three | 3 | -3 | 3 | -3 - | 3 | 2 | three | 3 | -3 | 2 | 4 - | 3 | 2 | three | 3 | -3 | 5 | -5 - | 3 | 2 | three | 3 | -3 | 5 | -5 - | 3 | 2 | three | 3 | -3 | 0 | - | 3 | 2 | three | 3 | -3 | | - | 3 | 2 | three | 3 | -3 | | 0 - | 4 | 1 | four | 3 | -3 | 1 | -1 - | 4 | 1 | four | 3 | -3 | 2 | 2 - | 4 | 1 | four | 3 | -3 | 3 | -3 - | 4 | 1 | four | 3 | -3 | 2 | 4 - | 4 | 1 | four | 3 | -3 | 5 | -5 - | 4 | 1 | four | 3 | -3 | 5 | -5 - | 4 | 1 | four | 3 | -3 | 0 | - | 4 | 1 | four | 3 | -3 | | - | 4 | 1 | four | 3 | -3 | | 0 - | 5 | 0 | five | 3 | -3 | 1 | -1 - | 5 | 0 | five | 3 | -3 | 2 | 2 - | 5 | 0 | five | 3 | -3 | 3 | -3 - | 5 | 0 | five | 3 | -3 | 2 | 4 - | 5 | 0 | five | 3 | -3 | 5 | -5 - | 5 | 0 | five | 3 | -3 | 5 | -5 - | 5 | 0 | five | 3 | -3 | 0 | - | 5 | 0 | five | 3 | -3 | | - | 5 | 0 | five | 3 | -3 | | 0 - | 6 | 6 | six | 3 | -3 | 1 | -1 - | 6 | 6 | six | 3 | -3 | 2 | 2 - | 6 | 6 | six | 3 | -3 | 3 | -3 - | 6 | 6 | six | 3 | -3 | 2 | 4 - | 6 | 6 | six | 3 | -3 | 5 | -5 - | 6 | 6 | six | 3 | -3 | 5 | -5 - | 6 | 6 | six | 3 | -3 | 0 | - | 6 | 6 | six | 3 | -3 | | - | 6 | 6 | six | 3 | -3 | | 0 - | 7 | 7 | seven | 3 | -3 | 1 | -1 - | 7 | 7 | seven | 3 | -3 | 2 | 2 - | 7 | 7 | seven | 3 | -3 | 3 | -3 - | 7 | 7 | seven | 3 | -3 | 2 | 4 - | 7 | 7 | seven | 3 | -3 | 5 | -5 - | 7 | 7 | seven | 3 | -3 | 5 | -5 - | 7 | 7 | seven | 3 | -3 | 0 | - | 7 | 7 | seven | 3 | -3 | | - | 7 | 7 | seven | 3 | -3 | | 0 - | 8 | 8 | eight | 3 | -3 | 1 | -1 - | 8 | 8 | eight | 3 | -3 | 2 | 2 - | 8 | 8 | eight | 3 | -3 | 3 | -3 - | 8 | 8 | eight | 3 | -3 | 2 | 4 - | 8 | 8 | eight | 3 | -3 | 5 | -5 - | 8 | 8 | eight | 3 | -3 | 5 | -5 - | 8 | 8 | eight | 3 | -3 | 0 | - | 8 | 8 | eight | 3 | -3 | | - | 8 | 8 | eight | 3 | -3 | | 0 - | 0 | | zero | 3 | -3 | 1 | -1 - | 0 | | zero | 3 | -3 | 2 | 2 - | 0 | | zero | 3 | -3 | 3 | -3 - | 0 | | zero | 3 | -3 | 2 | 4 - | 0 | | zero | 3 | -3 | 5 | -5 - | 0 | | zero | 3 | -3 | 5 | -5 - | 0 | | zero | 3 | -3 | 0 | - | 0 | | zero | 3 | -3 | | - | 0 | | zero | 3 | -3 | | 0 - | | | null | 3 | -3 | 1 | -1 - | | | null | 3 | -3 | 2 | 2 - | | | null | 3 | -3 | 3 | -3 - | | | null | 3 | -3 | 2 | 4 - | | | null | 3 | -3 | 5 | -5 - | | | null | 3 | -3 | 5 | -5 - | | | null | 3 | -3 | 0 | - | | | null | 3 | -3 | | - | | | null | 3 | -3 | | 0 - | | 0 | zero | 3 | -3 | 1 | -1 - | | 0 | zero | 3 | -3 | 2 | 2 - | | 0 | zero | 3 | -3 | 3 | -3 - | | 0 | zero | 3 | -3 | 2 | 4 - | | 0 | zero | 3 | -3 | 5 | -5 - | | 0 | zero | 3 | -3 | 5 | -5 - | | 0 | zero | 3 | -3 | 0 | - | | 0 | zero | 3 | -3 | | - | | 0 | zero | 3 | -3 | | 0 - | 1 | 4 | one | 2 | 4 | 1 | -1 - | 1 | 4 | one | 2 | 4 | 2 | 2 - | 1 | 4 | one | 2 | 4 | 3 | -3 - | 1 | 4 | one | 2 | 4 | 2 | 4 - | 1 | 4 | one | 2 | 4 | 5 | -5 - | 1 | 4 | one | 2 | 4 | 5 | -5 - | 1 | 4 | one | 2 | 4 | 0 | - | 1 | 4 | one | 2 | 4 | | - | 1 | 4 | one | 2 | 4 | | 0 - | 2 | 3 | two | 2 | 4 | 1 | -1 - | 2 | 3 | two | 2 | 4 | 2 | 2 - | 2 | 3 | two | 2 | 4 | 3 | -3 - | 2 | 3 | two | 2 | 4 | 2 | 4 - | 2 | 3 | two | 2 | 4 | 5 | -5 - | 2 | 3 | two | 2 | 4 | 5 | -5 - | 2 | 3 | two | 2 | 4 | 0 | - | 2 | 3 | two | 2 | 4 | | - | 2 | 3 | two | 2 | 4 | | 0 - | 3 | 2 | three | 2 | 4 | 1 | -1 - | 3 | 2 | three | 2 | 4 | 2 | 2 - | 3 | 2 | three | 2 | 4 | 3 | -3 - | 3 | 2 | three | 2 | 4 | 2 | 4 - | 3 | 2 | three | 2 | 4 | 5 | -5 - | 3 | 2 | three | 2 | 4 | 5 | -5 - | 3 | 2 | three | 2 | 4 | 0 | - | 3 | 2 | three | 2 | 4 | | - | 3 | 2 | three | 2 | 4 | | 0 - | 4 | 1 | four | 2 | 4 | 1 | -1 - | 4 | 1 | four | 2 | 4 | 2 | 2 - | 4 | 1 | four | 2 | 4 | 3 | -3 - | 4 | 1 | four | 2 | 4 | 2 | 4 - | 4 | 1 | four | 2 | 4 | 5 | -5 - | 4 | 1 | four | 2 | 4 | 5 | -5 - | 4 | 1 | four | 2 | 4 | 0 | - | 4 | 1 | four | 2 | 4 | | - | 4 | 1 | four | 2 | 4 | | 0 - | 5 | 0 | five | 2 | 4 | 1 | -1 - | 5 | 0 | five | 2 | 4 | 2 | 2 - | 5 | 0 | five | 2 | 4 | 3 | -3 - | 5 | 0 | five | 2 | 4 | 2 | 4 - | 5 | 0 | five | 2 | 4 | 5 | -5 - | 5 | 0 | five | 2 | 4 | 5 | -5 - | 5 | 0 | five | 2 | 4 | 0 | - | 5 | 0 | five | 2 | 4 | | - | 5 | 0 | five | 2 | 4 | | 0 - | 6 | 6 | six | 2 | 4 | 1 | -1 - | 6 | 6 | six | 2 | 4 | 2 | 2 - | 6 | 6 | six | 2 | 4 | 3 | -3 - | 6 | 6 | six | 2 | 4 | 2 | 4 - | 6 | 6 | six | 2 | 4 | 5 | -5 - | 6 | 6 | six | 2 | 4 | 5 | -5 - | 6 | 6 | six | 2 | 4 | 0 | - | 6 | 6 | six | 2 | 4 | | - | 6 | 6 | six | 2 | 4 | | 0 - | 7 | 7 | seven | 2 | 4 | 1 | -1 - | 7 | 7 | seven | 2 | 4 | 2 | 2 - | 7 | 7 | seven | 2 | 4 | 3 | -3 - | 7 | 7 | seven | 2 | 4 | 2 | 4 - | 7 | 7 | seven | 2 | 4 | 5 | -5 - | 7 | 7 | seven | 2 | 4 | 5 | -5 - | 7 | 7 | seven | 2 | 4 | 0 | - | 7 | 7 | seven | 2 | 4 | | - | 7 | 7 | seven | 2 | 4 | | 0 - | 8 | 8 | eight | 2 | 4 | 1 | -1 - | 8 | 8 | eight | 2 | 4 | 2 | 2 - | 8 | 8 | eight | 2 | 4 | 3 | -3 - | 8 | 8 | eight | 2 | 4 | 2 | 4 - | 8 | 8 | eight | 2 | 4 | 5 | -5 - | 8 | 8 | eight | 2 | 4 | 5 | -5 - | 8 | 8 | eight | 2 | 4 | 0 | - | 8 | 8 | eight | 2 | 4 | | - | 8 | 8 | eight | 2 | 4 | | 0 - | 0 | | zero | 2 | 4 | 1 | -1 - | 0 | | zero | 2 | 4 | 2 | 2 - | 0 | | zero | 2 | 4 | 3 | -3 - | 0 | | zero | 2 | 4 | 2 | 4 - | 0 | | zero | 2 | 4 | 5 | -5 - | 0 | | zero | 2 | 4 | 5 | -5 - | 0 | | zero | 2 | 4 | 0 | - | 0 | | zero | 2 | 4 | | - | 0 | | zero | 2 | 4 | | 0 - | | | null | 2 | 4 | 1 | -1 - | | | null | 2 | 4 | 2 | 2 - | | | null | 2 | 4 | 3 | -3 - | | | null | 2 | 4 | 2 | 4 - | | | null | 2 | 4 | 5 | -5 - | | | null | 2 | 4 | 5 | -5 - | | | null | 2 | 4 | 0 | - | | | null | 2 | 4 | | - | | | null | 2 | 4 | | 0 - | | 0 | zero | 2 | 4 | 1 | -1 - | | 0 | zero | 2 | 4 | 2 | 2 - | | 0 | zero | 2 | 4 | 3 | -3 - | | 0 | zero | 2 | 4 | 2 | 4 - | | 0 | zero | 2 | 4 | 5 | -5 - | | 0 | zero | 2 | 4 | 5 | -5 - | | 0 | zero | 2 | 4 | 0 | - | | 0 | zero | 2 | 4 | | - | | 0 | zero | 2 | 4 | | 0 - | 1 | 4 | one | 5 | -5 | 1 | -1 - | 1 | 4 | one | 5 | -5 | 2 | 2 - | 1 | 4 | one | 5 | -5 | 3 | -3 - | 1 | 4 | one | 5 | -5 | 2 | 4 - | 1 | 4 | one | 5 | -5 | 5 | -5 - | 1 | 4 | one | 5 | -5 | 5 | -5 - | 1 | 4 | one | 5 | -5 | 0 | - | 1 | 4 | one | 5 | -5 | | - | 1 | 4 | one | 5 | -5 | | 0 - | 2 | 3 | two | 5 | -5 | 1 | -1 - | 2 | 3 | two | 5 | -5 | 2 | 2 - | 2 | 3 | two | 5 | -5 | 3 | -3 - | 2 | 3 | two | 5 | -5 | 2 | 4 - | 2 | 3 | two | 5 | -5 | 5 | -5 - | 2 | 3 | two | 5 | -5 | 5 | -5 - | 2 | 3 | two | 5 | -5 | 0 | - | 2 | 3 | two | 5 | -5 | | - | 2 | 3 | two | 5 | -5 | | 0 - | 3 | 2 | three | 5 | -5 | 1 | -1 - | 3 | 2 | three | 5 | -5 | 2 | 2 - | 3 | 2 | three | 5 | -5 | 3 | -3 - | 3 | 2 | three | 5 | -5 | 2 | 4 - | 3 | 2 | three | 5 | -5 | 5 | -5 - | 3 | 2 | three | 5 | -5 | 5 | -5 - | 3 | 2 | three | 5 | -5 | 0 | - | 3 | 2 | three | 5 | -5 | | - | 3 | 2 | three | 5 | -5 | | 0 - | 4 | 1 | four | 5 | -5 | 1 | -1 - | 4 | 1 | four | 5 | -5 | 2 | 2 - | 4 | 1 | four | 5 | -5 | 3 | -3 - | 4 | 1 | four | 5 | -5 | 2 | 4 - | 4 | 1 | four | 5 | -5 | 5 | -5 - | 4 | 1 | four | 5 | -5 | 5 | -5 - | 4 | 1 | four | 5 | -5 | 0 | - | 4 | 1 | four | 5 | -5 | | - | 4 | 1 | four | 5 | -5 | | 0 - | 5 | 0 | five | 5 | -5 | 1 | -1 - | 5 | 0 | five | 5 | -5 | 2 | 2 - | 5 | 0 | five | 5 | -5 | 3 | -3 - | 5 | 0 | five | 5 | -5 | 2 | 4 - | 5 | 0 | five | 5 | -5 | 5 | -5 - | 5 | 0 | five | 5 | -5 | 5 | -5 - | 5 | 0 | five | 5 | -5 | 0 | - | 5 | 0 | five | 5 | -5 | | - | 5 | 0 | five | 5 | -5 | | 0 - | 6 | 6 | six | 5 | -5 | 1 | -1 - | 6 | 6 | six | 5 | -5 | 2 | 2 - | 6 | 6 | six | 5 | -5 | 3 | -3 - | 6 | 6 | six | 5 | -5 | 2 | 4 - | 6 | 6 | six | 5 | -5 | 5 | -5 - | 6 | 6 | six | 5 | -5 | 5 | -5 - | 6 | 6 | six | 5 | -5 | 0 | - | 6 | 6 | six | 5 | -5 | | - | 6 | 6 | six | 5 | -5 | | 0 - | 7 | 7 | seven | 5 | -5 | 1 | -1 - | 7 | 7 | seven | 5 | -5 | 2 | 2 - | 7 | 7 | seven | 5 | -5 | 3 | -3 - | 7 | 7 | seven | 5 | -5 | 2 | 4 - | 7 | 7 | seven | 5 | -5 | 5 | -5 - | 7 | 7 | seven | 5 | -5 | 5 | -5 - | 7 | 7 | seven | 5 | -5 | 0 | - | 7 | 7 | seven | 5 | -5 | | - | 7 | 7 | seven | 5 | -5 | | 0 - | 8 | 8 | eight | 5 | -5 | 1 | -1 - | 8 | 8 | eight | 5 | -5 | 2 | 2 - | 8 | 8 | eight | 5 | -5 | 3 | -3 - | 8 | 8 | eight | 5 | -5 | 2 | 4 - | 8 | 8 | eight | 5 | -5 | 5 | -5 - | 8 | 8 | eight | 5 | -5 | 5 | -5 - | 8 | 8 | eight | 5 | -5 | 0 | - | 8 | 8 | eight | 5 | -5 | | - | 8 | 8 | eight | 5 | -5 | | 0 - | 0 | | zero | 5 | -5 | 1 | -1 - | 0 | | zero | 5 | -5 | 2 | 2 - | 0 | | zero | 5 | -5 | 3 | -3 - | 0 | | zero | 5 | -5 | 2 | 4 - | 0 | | zero | 5 | -5 | 5 | -5 - | 0 | | zero | 5 | -5 | 5 | -5 - | 0 | | zero | 5 | -5 | 0 | - | 0 | | zero | 5 | -5 | | - | 0 | | zero | 5 | -5 | | 0 - | | | null | 5 | -5 | 1 | -1 - | | | null | 5 | -5 | 2 | 2 - | | | null | 5 | -5 | 3 | -3 - | | | null | 5 | -5 | 2 | 4 - | | | null | 5 | -5 | 5 | -5 - | | | null | 5 | -5 | 5 | -5 - | | | null | 5 | -5 | 0 | - | | | null | 5 | -5 | | - | | | null | 5 | -5 | | 0 - | | 0 | zero | 5 | -5 | 1 | -1 - | | 0 | zero | 5 | -5 | 2 | 2 - | | 0 | zero | 5 | -5 | 3 | -3 - | | 0 | zero | 5 | -5 | 2 | 4 - | | 0 | zero | 5 | -5 | 5 | -5 - | | 0 | zero | 5 | -5 | 5 | -5 - | | 0 | zero | 5 | -5 | 0 | - | | 0 | zero | 5 | -5 | | - | | 0 | zero | 5 | -5 | | 0 - | 1 | 4 | one | 5 | -5 | 1 | -1 - | 1 | 4 | one | 5 | -5 | 2 | 2 - | 1 | 4 | one | 5 | -5 | 3 | -3 - | 1 | 4 | one | 5 | -5 | 2 | 4 - | 1 | 4 | one | 5 | -5 | 5 | -5 - | 1 | 4 | one | 5 | -5 | 5 | -5 - | 1 | 4 | one | 5 | -5 | 0 | - | 1 | 4 | one | 5 | -5 | | - | 1 | 4 | one | 5 | -5 | | 0 - | 2 | 3 | two | 5 | -5 | 1 | -1 - | 2 | 3 | two | 5 | -5 | 2 | 2 - | 2 | 3 | two | 5 | -5 | 3 | -3 - | 2 | 3 | two | 5 | -5 | 2 | 4 - | 2 | 3 | two | 5 | -5 | 5 | -5 - | 2 | 3 | two | 5 | -5 | 5 | -5 - | 2 | 3 | two | 5 | -5 | 0 | - | 2 | 3 | two | 5 | -5 | | - | 2 | 3 | two | 5 | -5 | | 0 - | 3 | 2 | three | 5 | -5 | 1 | -1 - | 3 | 2 | three | 5 | -5 | 2 | 2 - | 3 | 2 | three | 5 | -5 | 3 | -3 - | 3 | 2 | three | 5 | -5 | 2 | 4 - | 3 | 2 | three | 5 | -5 | 5 | -5 - | 3 | 2 | three | 5 | -5 | 5 | -5 - | 3 | 2 | three | 5 | -5 | 0 | - | 3 | 2 | three | 5 | -5 | | - | 3 | 2 | three | 5 | -5 | | 0 - | 4 | 1 | four | 5 | -5 | 1 | -1 - | 4 | 1 | four | 5 | -5 | 2 | 2 - | 4 | 1 | four | 5 | -5 | 3 | -3 - | 4 | 1 | four | 5 | -5 | 2 | 4 - | 4 | 1 | four | 5 | -5 | 5 | -5 - | 4 | 1 | four | 5 | -5 | 5 | -5 - | 4 | 1 | four | 5 | -5 | 0 | - | 4 | 1 | four | 5 | -5 | | - | 4 | 1 | four | 5 | -5 | | 0 - | 5 | 0 | five | 5 | -5 | 1 | -1 - | 5 | 0 | five | 5 | -5 | 2 | 2 - | 5 | 0 | five | 5 | -5 | 3 | -3 - | 5 | 0 | five | 5 | -5 | 2 | 4 - | 5 | 0 | five | 5 | -5 | 5 | -5 - | 5 | 0 | five | 5 | -5 | 5 | -5 - | 5 | 0 | five | 5 | -5 | 0 | - | 5 | 0 | five | 5 | -5 | | - | 5 | 0 | five | 5 | -5 | | 0 - | 6 | 6 | six | 5 | -5 | 1 | -1 - | 6 | 6 | six | 5 | -5 | 2 | 2 - | 6 | 6 | six | 5 | -5 | 3 | -3 - | 6 | 6 | six | 5 | -5 | 2 | 4 - | 6 | 6 | six | 5 | -5 | 5 | -5 - | 6 | 6 | six | 5 | -5 | 5 | -5 - | 6 | 6 | six | 5 | -5 | 0 | - | 6 | 6 | six | 5 | -5 | | - | 6 | 6 | six | 5 | -5 | | 0 - | 7 | 7 | seven | 5 | -5 | 1 | -1 - | 7 | 7 | seven | 5 | -5 | 2 | 2 - | 7 | 7 | seven | 5 | -5 | 3 | -3 - | 7 | 7 | seven | 5 | -5 | 2 | 4 - | 7 | 7 | seven | 5 | -5 | 5 | -5 - | 7 | 7 | seven | 5 | -5 | 5 | -5 - | 7 | 7 | seven | 5 | -5 | 0 | - | 7 | 7 | seven | 5 | -5 | | - | 7 | 7 | seven | 5 | -5 | | 0 - | 8 | 8 | eight | 5 | -5 | 1 | -1 - | 8 | 8 | eight | 5 | -5 | 2 | 2 - | 8 | 8 | eight | 5 | -5 | 3 | -3 - | 8 | 8 | eight | 5 | -5 | 2 | 4 - | 8 | 8 | eight | 5 | -5 | 5 | -5 - | 8 | 8 | eight | 5 | -5 | 5 | -5 - | 8 | 8 | eight | 5 | -5 | 0 | - | 8 | 8 | eight | 5 | -5 | | - | 8 | 8 | eight | 5 | -5 | | 0 - | 0 | | zero | 5 | -5 | 1 | -1 - | 0 | | zero | 5 | -5 | 2 | 2 - | 0 | | zero | 5 | -5 | 3 | -3 - | 0 | | zero | 5 | -5 | 2 | 4 - | 0 | | zero | 5 | -5 | 5 | -5 - | 0 | | zero | 5 | -5 | 5 | -5 - | 0 | | zero | 5 | -5 | 0 | - | 0 | | zero | 5 | -5 | | - | 0 | | zero | 5 | -5 | | 0 - | | | null | 5 | -5 | 1 | -1 - | | | null | 5 | -5 | 2 | 2 - | | | null | 5 | -5 | 3 | -3 - | | | null | 5 | -5 | 2 | 4 - | | | null | 5 | -5 | 5 | -5 - | | | null | 5 | -5 | 5 | -5 - | | | null | 5 | -5 | 0 | - | | | null | 5 | -5 | | - | | | null | 5 | -5 | | 0 - | | 0 | zero | 5 | -5 | 1 | -1 - | | 0 | zero | 5 | -5 | 2 | 2 - | | 0 | zero | 5 | -5 | 3 | -3 - | | 0 | zero | 5 | -5 | 2 | 4 - | | 0 | zero | 5 | -5 | 5 | -5 - | | 0 | zero | 5 | -5 | 5 | -5 - | | 0 | zero | 5 | -5 | 0 | - | | 0 | zero | 5 | -5 | | - | | 0 | zero | 5 | -5 | | 0 - | 1 | 4 | one | 0 | | 1 | -1 - | 1 | 4 | one | 0 | | 2 | 2 - | 1 | 4 | one | 0 | | 3 | -3 - | 1 | 4 | one | 0 | | 2 | 4 - | 1 | 4 | one | 0 | | 5 | -5 - | 1 | 4 | one | 0 | | 5 | -5 - | 1 | 4 | one | 0 | | 0 | - | 1 | 4 | one | 0 | | | - | 1 | 4 | one | 0 | | | 0 - | 2 | 3 | two | 0 | | 1 | -1 - | 2 | 3 | two | 0 | | 2 | 2 - | 2 | 3 | two | 0 | | 3 | -3 - | 2 | 3 | two | 0 | | 2 | 4 - | 2 | 3 | two | 0 | | 5 | -5 - | 2 | 3 | two | 0 | | 5 | -5 - | 2 | 3 | two | 0 | | 0 | - | 2 | 3 | two | 0 | | | - | 2 | 3 | two | 0 | | | 0 - | 3 | 2 | three | 0 | | 1 | -1 - | 3 | 2 | three | 0 | | 2 | 2 - | 3 | 2 | three | 0 | | 3 | -3 - | 3 | 2 | three | 0 | | 2 | 4 - | 3 | 2 | three | 0 | | 5 | -5 - | 3 | 2 | three | 0 | | 5 | -5 - | 3 | 2 | three | 0 | | 0 | - | 3 | 2 | three | 0 | | | - | 3 | 2 | three | 0 | | | 0 - | 4 | 1 | four | 0 | | 1 | -1 - | 4 | 1 | four | 0 | | 2 | 2 - | 4 | 1 | four | 0 | | 3 | -3 - | 4 | 1 | four | 0 | | 2 | 4 - | 4 | 1 | four | 0 | | 5 | -5 - | 4 | 1 | four | 0 | | 5 | -5 - | 4 | 1 | four | 0 | | 0 | - | 4 | 1 | four | 0 | | | - | 4 | 1 | four | 0 | | | 0 - | 5 | 0 | five | 0 | | 1 | -1 - | 5 | 0 | five | 0 | | 2 | 2 - | 5 | 0 | five | 0 | | 3 | -3 - | 5 | 0 | five | 0 | | 2 | 4 - | 5 | 0 | five | 0 | | 5 | -5 - | 5 | 0 | five | 0 | | 5 | -5 - | 5 | 0 | five | 0 | | 0 | - | 5 | 0 | five | 0 | | | - | 5 | 0 | five | 0 | | | 0 - | 6 | 6 | six | 0 | | 1 | -1 - | 6 | 6 | six | 0 | | 2 | 2 - | 6 | 6 | six | 0 | | 3 | -3 - | 6 | 6 | six | 0 | | 2 | 4 - | 6 | 6 | six | 0 | | 5 | -5 - | 6 | 6 | six | 0 | | 5 | -5 - | 6 | 6 | six | 0 | | 0 | - | 6 | 6 | six | 0 | | | - | 6 | 6 | six | 0 | | | 0 - | 7 | 7 | seven | 0 | | 1 | -1 - | 7 | 7 | seven | 0 | | 2 | 2 - | 7 | 7 | seven | 0 | | 3 | -3 - | 7 | 7 | seven | 0 | | 2 | 4 - | 7 | 7 | seven | 0 | | 5 | -5 - | 7 | 7 | seven | 0 | | 5 | -5 - | 7 | 7 | seven | 0 | | 0 | - | 7 | 7 | seven | 0 | | | - | 7 | 7 | seven | 0 | | | 0 - | 8 | 8 | eight | 0 | | 1 | -1 - | 8 | 8 | eight | 0 | | 2 | 2 - | 8 | 8 | eight | 0 | | 3 | -3 - | 8 | 8 | eight | 0 | | 2 | 4 - | 8 | 8 | eight | 0 | | 5 | -5 - | 8 | 8 | eight | 0 | | 5 | -5 - | 8 | 8 | eight | 0 | | 0 | - | 8 | 8 | eight | 0 | | | - | 8 | 8 | eight | 0 | | | 0 - | 0 | | zero | 0 | | 1 | -1 - | 0 | | zero | 0 | | 2 | 2 - | 0 | | zero | 0 | | 3 | -3 - | 0 | | zero | 0 | | 2 | 4 - | 0 | | zero | 0 | | 5 | -5 - | 0 | | zero | 0 | | 5 | -5 - | 0 | | zero | 0 | | 0 | - | 0 | | zero | 0 | | | - | 0 | | zero | 0 | | | 0 - | | | null | 0 | | 1 | -1 - | | | null | 0 | | 2 | 2 - | | | null | 0 | | 3 | -3 - | | | null | 0 | | 2 | 4 - | | | null | 0 | | 5 | -5 - | | | null | 0 | | 5 | -5 - | | | null | 0 | | 0 | - | | | null | 0 | | | - | | | null | 0 | | | 0 - | | 0 | zero | 0 | | 1 | -1 - | | 0 | zero | 0 | | 2 | 2 - | | 0 | zero | 0 | | 3 | -3 - | | 0 | zero | 0 | | 2 | 4 - | | 0 | zero | 0 | | 5 | -5 - | | 0 | zero | 0 | | 5 | -5 - | | 0 | zero | 0 | | 0 | - | | 0 | zero | 0 | | | - | | 0 | zero | 0 | | | 0 - | 1 | 4 | one | | | 1 | -1 - | 1 | 4 | one | | | 2 | 2 - | 1 | 4 | one | | | 3 | -3 - | 1 | 4 | one | | | 2 | 4 - | 1 | 4 | one | | | 5 | -5 - | 1 | 4 | one | | | 5 | -5 - | 1 | 4 | one | | | 0 | - | 1 | 4 | one | | | | - | 1 | 4 | one | | | | 0 - | 2 | 3 | two | | | 1 | -1 - | 2 | 3 | two | | | 2 | 2 - | 2 | 3 | two | | | 3 | -3 - | 2 | 3 | two | | | 2 | 4 - | 2 | 3 | two | | | 5 | -5 - | 2 | 3 | two | | | 5 | -5 - | 2 | 3 | two | | | 0 | - | 2 | 3 | two | | | | - | 2 | 3 | two | | | | 0 - | 3 | 2 | three | | | 1 | -1 - | 3 | 2 | three | | | 2 | 2 - | 3 | 2 | three | | | 3 | -3 - | 3 | 2 | three | | | 2 | 4 - | 3 | 2 | three | | | 5 | -5 - | 3 | 2 | three | | | 5 | -5 - | 3 | 2 | three | | | 0 | - | 3 | 2 | three | | | | - | 3 | 2 | three | | | | 0 - | 4 | 1 | four | | | 1 | -1 - | 4 | 1 | four | | | 2 | 2 - | 4 | 1 | four | | | 3 | -3 - | 4 | 1 | four | | | 2 | 4 - | 4 | 1 | four | | | 5 | -5 - | 4 | 1 | four | | | 5 | -5 - | 4 | 1 | four | | | 0 | - | 4 | 1 | four | | | | - | 4 | 1 | four | | | | 0 - | 5 | 0 | five | | | 1 | -1 - | 5 | 0 | five | | | 2 | 2 - | 5 | 0 | five | | | 3 | -3 - | 5 | 0 | five | | | 2 | 4 - | 5 | 0 | five | | | 5 | -5 - | 5 | 0 | five | | | 5 | -5 - | 5 | 0 | five | | | 0 | - | 5 | 0 | five | | | | - | 5 | 0 | five | | | | 0 - | 6 | 6 | six | | | 1 | -1 - | 6 | 6 | six | | | 2 | 2 - | 6 | 6 | six | | | 3 | -3 - | 6 | 6 | six | | | 2 | 4 - | 6 | 6 | six | | | 5 | -5 - | 6 | 6 | six | | | 5 | -5 - | 6 | 6 | six | | | 0 | - | 6 | 6 | six | | | | - | 6 | 6 | six | | | | 0 - | 7 | 7 | seven | | | 1 | -1 - | 7 | 7 | seven | | | 2 | 2 - | 7 | 7 | seven | | | 3 | -3 - | 7 | 7 | seven | | | 2 | 4 - | 7 | 7 | seven | | | 5 | -5 - | 7 | 7 | seven | | | 5 | -5 - | 7 | 7 | seven | | | 0 | - | 7 | 7 | seven | | | | - | 7 | 7 | seven | | | | 0 - | 8 | 8 | eight | | | 1 | -1 - | 8 | 8 | eight | | | 2 | 2 - | 8 | 8 | eight | | | 3 | -3 - | 8 | 8 | eight | | | 2 | 4 - | 8 | 8 | eight | | | 5 | -5 - | 8 | 8 | eight | | | 5 | -5 - | 8 | 8 | eight | | | 0 | - | 8 | 8 | eight | | | | - | 8 | 8 | eight | | | | 0 - | 0 | | zero | | | 1 | -1 - | 0 | | zero | | | 2 | 2 - | 0 | | zero | | | 3 | -3 - | 0 | | zero | | | 2 | 4 - | 0 | | zero | | | 5 | -5 - | 0 | | zero | | | 5 | -5 - | 0 | | zero | | | 0 | - | 0 | | zero | | | | - | 0 | | zero | | | | 0 - | | | null | | | 1 | -1 - | | | null | | | 2 | 2 - | | | null | | | 3 | -3 - | | | null | | | 2 | 4 - | | | null | | | 5 | -5 - | | | null | | | 5 | -5 - | | | null | | | 0 | - | | | null | | | | - | | | null | | | | 0 - | | 0 | zero | | | 1 | -1 - | | 0 | zero | | | 2 | 2 - | | 0 | zero | | | 3 | -3 - | | 0 | zero | | | 2 | 4 - | | 0 | zero | | | 5 | -5 - | | 0 | zero | | | 5 | -5 - | | 0 | zero | | | 0 | - | | 0 | zero | | | | - | | 0 | zero | | | | 0 - | 1 | 4 | one | | 0 | 1 | -1 - | 1 | 4 | one | | 0 | 2 | 2 - | 1 | 4 | one | | 0 | 3 | -3 - | 1 | 4 | one | | 0 | 2 | 4 - | 1 | 4 | one | | 0 | 5 | -5 - | 1 | 4 | one | | 0 | 5 | -5 - | 1 | 4 | one | | 0 | 0 | - | 1 | 4 | one | | 0 | | - | 1 | 4 | one | | 0 | | 0 - | 2 | 3 | two | | 0 | 1 | -1 - | 2 | 3 | two | | 0 | 2 | 2 - | 2 | 3 | two | | 0 | 3 | -3 - | 2 | 3 | two | | 0 | 2 | 4 - | 2 | 3 | two | | 0 | 5 | -5 - | 2 | 3 | two | | 0 | 5 | -5 - | 2 | 3 | two | | 0 | 0 | - | 2 | 3 | two | | 0 | | - | 2 | 3 | two | | 0 | | 0 - | 3 | 2 | three | | 0 | 1 | -1 - | 3 | 2 | three | | 0 | 2 | 2 - | 3 | 2 | three | | 0 | 3 | -3 - | 3 | 2 | three | | 0 | 2 | 4 - | 3 | 2 | three | | 0 | 5 | -5 - | 3 | 2 | three | | 0 | 5 | -5 - | 3 | 2 | three | | 0 | 0 | - | 3 | 2 | three | | 0 | | - | 3 | 2 | three | | 0 | | 0 - | 4 | 1 | four | | 0 | 1 | -1 - | 4 | 1 | four | | 0 | 2 | 2 - | 4 | 1 | four | | 0 | 3 | -3 - | 4 | 1 | four | | 0 | 2 | 4 - | 4 | 1 | four | | 0 | 5 | -5 - | 4 | 1 | four | | 0 | 5 | -5 - | 4 | 1 | four | | 0 | 0 | - | 4 | 1 | four | | 0 | | - | 4 | 1 | four | | 0 | | 0 - | 5 | 0 | five | | 0 | 1 | -1 - | 5 | 0 | five | | 0 | 2 | 2 - | 5 | 0 | five | | 0 | 3 | -3 - | 5 | 0 | five | | 0 | 2 | 4 - | 5 | 0 | five | | 0 | 5 | -5 - | 5 | 0 | five | | 0 | 5 | -5 - | 5 | 0 | five | | 0 | 0 | - | 5 | 0 | five | | 0 | | - | 5 | 0 | five | | 0 | | 0 - | 6 | 6 | six | | 0 | 1 | -1 - | 6 | 6 | six | | 0 | 2 | 2 - | 6 | 6 | six | | 0 | 3 | -3 - | 6 | 6 | six | | 0 | 2 | 4 - | 6 | 6 | six | | 0 | 5 | -5 - | 6 | 6 | six | | 0 | 5 | -5 - | 6 | 6 | six | | 0 | 0 | - | 6 | 6 | six | | 0 | | - | 6 | 6 | six | | 0 | | 0 - | 7 | 7 | seven | | 0 | 1 | -1 - | 7 | 7 | seven | | 0 | 2 | 2 - | 7 | 7 | seven | | 0 | 3 | -3 - | 7 | 7 | seven | | 0 | 2 | 4 - | 7 | 7 | seven | | 0 | 5 | -5 - | 7 | 7 | seven | | 0 | 5 | -5 - | 7 | 7 | seven | | 0 | 0 | - | 7 | 7 | seven | | 0 | | - | 7 | 7 | seven | | 0 | | 0 - | 8 | 8 | eight | | 0 | 1 | -1 - | 8 | 8 | eight | | 0 | 2 | 2 - | 8 | 8 | eight | | 0 | 3 | -3 - | 8 | 8 | eight | | 0 | 2 | 4 - | 8 | 8 | eight | | 0 | 5 | -5 - | 8 | 8 | eight | | 0 | 5 | -5 - | 8 | 8 | eight | | 0 | 0 | - | 8 | 8 | eight | | 0 | | - | 8 | 8 | eight | | 0 | | 0 - | 0 | | zero | | 0 | 1 | -1 - | 0 | | zero | | 0 | 2 | 2 - | 0 | | zero | | 0 | 3 | -3 - | 0 | | zero | | 0 | 2 | 4 - | 0 | | zero | | 0 | 5 | -5 - | 0 | | zero | | 0 | 5 | -5 - | 0 | | zero | | 0 | 0 | - | 0 | | zero | | 0 | | - | 0 | | zero | | 0 | | 0 - | | | null | | 0 | 1 | -1 - | | | null | | 0 | 2 | 2 - | | | null | | 0 | 3 | -3 - | | | null | | 0 | 2 | 4 - | | | null | | 0 | 5 | -5 - | | | null | | 0 | 5 | -5 - | | | null | | 0 | 0 | - | | | null | | 0 | | - | | | null | | 0 | | 0 - | | 0 | zero | | 0 | 1 | -1 - | | 0 | zero | | 0 | 2 | 2 - | | 0 | zero | | 0 | 3 | -3 - | | 0 | zero | | 0 | 2 | 4 - | | 0 | zero | | 0 | 5 | -5 - | | 0 | zero | | 0 | 5 | -5 - | | 0 | zero | | 0 | 0 | - | | 0 | zero | | 0 | | - | | 0 | zero | | 0 | | 0 -(891 rows) - --- --- --- Inner joins (equi-joins) --- --- --- --- Inner joins (equi-joins) with USING clause --- The USING syntax changes the shape of the resulting table --- by including a column in the USING clause only once in the result. --- --- Inner equi-join on specified column ---Testcase 33: -SELECT '' AS "xxx", * - FROM J1_TBL INNER JOIN J2_TBL USING (i); - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - --- Same as above, slightly different syntax ---Testcase 34: -SELECT '' AS "xxx", * - FROM J1_TBL JOIN J2_TBL USING (i); - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - ---Testcase 35: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a) - ORDER BY a, d; - xxx | a | b | c | d ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - ---Testcase 36: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, b) USING (b) - ORDER BY b, t1.a; - xxx | b | a | c | a ------+---+---+-------+--- - | 0 | 5 | five | - | 0 | | zero | - | 2 | 3 | three | 2 - | 4 | 1 | one | 2 -(4 rows) - --- --- NATURAL JOIN --- Inner equi-join on all columns with the same name --- ---Testcase 37: -SELECT '' AS "xxx", * - FROM J1_TBL NATURAL JOIN J2_TBL; - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - ---Testcase 38: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (a, d); - xxx | a | b | c | d ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - ---Testcase 39: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (d, a); - xxx | a | b | c | d ------+---+---+------+--- - | 0 | | zero | - | 2 | 3 | two | 2 - | 4 | 1 | four | 2 -(3 rows) - --- mismatch number of columns --- currently, Postgres will fill in with underlying names ---Testcase 40: -SELECT '' AS "xxx", * - FROM J1_TBL t1 (a, b) NATURAL JOIN J2_TBL t2 (a); - xxx | a | b | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 -(7 rows) - --- --- Inner joins (equi-joins) --- ---Testcase 41: -SELECT '' AS "xxx", * - FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i); - xxx | i | j | t | i | k ------+---+---+-------+---+---- - | 0 | | zero | 0 | - | 1 | 4 | one | 1 | -1 - | 2 | 3 | two | 2 | 2 - | 2 | 3 | two | 2 | 4 - | 3 | 2 | three | 3 | -3 - | 5 | 0 | five | 5 | -5 - | 5 | 0 | five | 5 | -5 -(7 rows) - ---Testcase 42: -SELECT '' AS "xxx", * - FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k); - xxx | i | j | t | i | k ------+---+---+------+---+--- - | 0 | | zero | | 0 - | 2 | 3 | two | 2 | 2 - | 4 | 1 | four | 2 | 4 -(3 rows) - --- --- Non-equi-joins --- ---Testcase 43: -SELECT '' AS "xxx", * - FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k); - xxx | i | j | t | i | k ------+---+---+-------+---+--- - | 1 | 4 | one | 2 | 2 - | 1 | 4 | one | 2 | 4 - | 2 | 3 | two | 2 | 2 - | 2 | 3 | two | 2 | 4 - | 3 | 2 | three | 2 | 4 - | 4 | 1 | four | 2 | 4 - | 0 | | zero | 2 | 2 - | 0 | | zero | 2 | 4 - | 0 | | zero | | 0 -(9 rows) - --- --- Outer joins --- Note that OUTER is a noise word --- ---Testcase 44: -SELECT '' AS "xxx", * - FROM J1_TBL LEFT OUTER JOIN J2_TBL USING (i) - ORDER BY i, k, t; - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 4 | 1 | four | - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | 6 | 6 | six | - | 7 | 7 | seven | - | 8 | 8 | eight | - | | | null | - | | 0 | zero | -(13 rows) - ---Testcase 45: -SELECT '' AS "xxx", * - FROM J1_TBL LEFT JOIN J2_TBL USING (i) - ORDER BY i, k, t; - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 4 | 1 | four | - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | 6 | 6 | six | - | 7 | 7 | seven | - | 8 | 8 | eight | - | | | null | - | | 0 | zero | -(13 rows) - ---Testcase 46: -SELECT '' AS "xxx", * - FROM J1_TBL RIGHT OUTER JOIN J2_TBL USING (i); - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | | | | - | | | | 0 -(9 rows) - ---Testcase 47: -SELECT '' AS "xxx", * - FROM J1_TBL RIGHT JOIN J2_TBL USING (i); - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | | | | - | | | | 0 -(9 rows) - ---Testcase 48: -SELECT '' AS "xxx", * - FROM J1_TBL FULL OUTER JOIN J2_TBL USING (i) - ORDER BY i, k, t; - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 4 | 1 | four | - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | 6 | 6 | six | - | 7 | 7 | seven | - | 8 | 8 | eight | - | | | | 0 - | | | null | - | | 0 | zero | - | | | | -(15 rows) - ---Testcase 49: -SELECT '' AS "xxx", * - FROM J1_TBL FULL JOIN J2_TBL USING (i) - ORDER BY i, k, t; - xxx | i | j | t | k ------+---+---+-------+---- - | 0 | | zero | - | 1 | 4 | one | -1 - | 2 | 3 | two | 2 - | 2 | 3 | two | 4 - | 3 | 2 | three | -3 - | 4 | 1 | four | - | 5 | 0 | five | -5 - | 5 | 0 | five | -5 - | 6 | 6 | six | - | 7 | 7 | seven | - | 8 | 8 | eight | - | | | | 0 - | | | null | - | | 0 | zero | - | | | | -(15 rows) - ---Testcase 50: -SELECT '' AS "xxx", * - FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1); - xxx | i | j | t | k ------+---+---+---+--- -(0 rows) - ---Testcase 51: -SELECT '' AS "xxx", * - FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (i = 1); - xxx | i | j | t | k ------+---+---+-----+---- - | 1 | 4 | one | -1 -(1 row) - --- --- semijoin selectivity for <> --- ---Testcase 52: -explain (costs off) -select * from int4_tbl i4, tenk1 a -where exists(select * from tenk1 b - where a.twothousand = b.twothousand and a.fivethous <> b.fivethous) - and i4.f1 = a.tenthous; - QUERY PLAN ----------------------------------------------- - Hash Semi Join - Hash Cond: (a.twothousand = b.twothousand) - Join Filter: (a.fivethous <> b.fivethous) - -> Foreign Scan - -> Hash - -> Foreign Scan on tenk1 b -(6 rows) - --- --- More complicated constructs --- --- --- Multiway full join --- ---Testcase 372: -CREATE FOREIGN TABLE t11 (name TEXT, n INTEGER) SERVER sqlite_svr; ---Testcase 373: -CREATE FOREIGN TABLE t21 (name TEXT, n INTEGER) SERVER sqlite_svr; ---Testcase 374: -CREATE FOREIGN TABLE t31 (name TEXT, n INTEGER) SERVER sqlite_svr; ---Testcase 53: -INSERT INTO t11 VALUES ( 'bb', 11 ); ---Testcase 54: -INSERT INTO t21 VALUES ( 'bb', 12 ); ---Testcase 55: -INSERT INTO t21 VALUES ( 'cc', 22 ); ---Testcase 56: -INSERT INTO t21 VALUES ( 'ee', 42 ); ---Testcase 57: -INSERT INTO t31 VALUES ( 'bb', 13 ); ---Testcase 58: -INSERT INTO t31 VALUES ( 'cc', 23 ); ---Testcase 59: -INSERT INTO t31 VALUES ( 'dd', 33 ); ---Testcase 60: -SELECT * FROM t11 FULL JOIN t21 USING (name) FULL JOIN t31 USING (name); - name | n | n | n -------+----+----+---- - bb | 11 | 12 | 13 - cc | | 22 | 23 - dd | | | 33 - ee | | 42 | -(4 rows) - --- --- Test interactions of join syntax and subqueries --- --- Basic cases (we expect planner to pull up the subquery here) ---Testcase 61: -SELECT * FROM -(SELECT * FROM t21) as s2 -INNER JOIN -(SELECT * FROM t31) s3 -USING (name); - name | n | n -------+----+---- - bb | 12 | 13 - cc | 22 | 23 -(2 rows) - ---Testcase 62: -SELECT * FROM -(SELECT * FROM t21) as s2 -LEFT JOIN -(SELECT * FROM t31) s3 -USING (name); - name | n | n -------+----+---- - bb | 12 | 13 - cc | 22 | 23 - ee | 42 | -(3 rows) - ---Testcase 63: -SELECT * FROM -(SELECT * FROM t21) as s2 -FULL JOIN -(SELECT * FROM t31) s3 -USING (name); - name | n | n -------+----+---- - bb | 12 | 13 - cc | 22 | 23 - dd | | 33 - ee | 42 | -(4 rows) - --- Cases with non-nullable expressions in subquery results; --- make sure these go to null as expected ---Testcase 64: -SELECT * FROM -(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 -NATURAL INNER JOIN -(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; - name | s2_n | s2_2 | s3_n | s3_2 -------+------+------+------+------ - bb | 12 | 2 | 13 | 3 - cc | 22 | 2 | 23 | 3 -(2 rows) - ---Testcase 65: -SELECT * FROM -(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 -NATURAL LEFT JOIN -(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; - name | s2_n | s2_2 | s3_n | s3_2 -------+------+------+------+------ - bb | 12 | 2 | 13 | 3 - cc | 22 | 2 | 23 | 3 - ee | 42 | 2 | | -(3 rows) - ---Testcase 66: -SELECT * FROM -(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 -NATURAL FULL JOIN -(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; - name | s2_n | s2_2 | s3_n | s3_2 -------+------+------+------+------ - bb | 12 | 2 | 13 | 3 - cc | 22 | 2 | 23 | 3 - dd | | | 33 | 3 - ee | 42 | 2 | | -(4 rows) - ---Testcase 67: -SELECT * FROM -(SELECT name, n as s1_n, 1 as s1_1 FROM t11) as s1 -NATURAL INNER JOIN -(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 -NATURAL INNER JOIN -(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; - name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 -------+------+------+------+------+------+------ - bb | 11 | 1 | 12 | 2 | 13 | 3 -(1 row) - ---Testcase 68: -SELECT * FROM -(SELECT name, n as s1_n, 1 as s1_1 FROM t11) as s1 -NATURAL FULL JOIN -(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 -NATURAL FULL JOIN -(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; - name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 -------+------+------+------+------+------+------ - bb | 11 | 1 | 12 | 2 | 13 | 3 - cc | | | 22 | 2 | 23 | 3 - dd | | | | | 33 | 3 - ee | | | 42 | 2 | | -(4 rows) - ---Testcase 69: -SELECT * FROM -(SELECT name, n as s1_n FROM t11) as s1 -NATURAL FULL JOIN - (SELECT * FROM - (SELECT name, n as s2_n FROM t21) as s2 - NATURAL FULL JOIN - (SELECT name, n as s3_n FROM t31) as s3 - ) ss2; - name | s1_n | s2_n | s3_n -------+------+------+------ - bb | 11 | 12 | 13 - cc | | 22 | 23 - dd | | | 33 - ee | | 42 | -(4 rows) - ---Testcase 70: -SELECT * FROM -(SELECT name, n as s1_n FROM t11) as s1 -NATURAL FULL JOIN - (SELECT * FROM - (SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 - NATURAL FULL JOIN - (SELECT name, n as s3_n FROM t31) as s3 - ) ss2; - name | s1_n | s2_n | s2_2 | s3_n -------+------+------+------+------ - bb | 11 | 12 | 2 | 13 - cc | | 22 | 2 | 23 - dd | | | | 33 - ee | | 42 | 2 | -(4 rows) - --- Constants as join keys can also be problematic ---Testcase 375: -SELECT * FROM - (SELECT name, n as s1_n FROM t11) as s1 -FULL JOIN - (SELECT name, 2 as s2_n FROM t21) as s2 -ON (s1_n = s2_n); - name | s1_n | name | s2_n -------+------+------+------ - | | bb | 2 - | | cc | 2 - | | ee | 2 - bb | 11 | | -(4 rows) - --- Test for propagation of nullability constraints into sub-joins ---Testcase 376: -create foreign table x (x1 int, x2 int) server sqlite_svr; ---Testcase 71: -insert into x values (1,11); ---Testcase 72: -insert into x values (2,22); ---Testcase 73: -insert into x values (3,null); ---Testcase 74: -insert into x values (4,44); ---Testcase 75: -insert into x values (5,null); ---Testcase 377: -create foreign table y (y1 int, y2 int) server sqlite_svr; ---Testcase 76: -insert into y values (1,111); ---Testcase 77: -insert into y values (2,222); ---Testcase 78: -insert into y values (3,333); ---Testcase 79: -insert into y values (4,null); ---Testcase 80: -select * from x; - x1 | x2 -----+---- - 1 | 11 - 2 | 22 - 3 | - 4 | 44 - 5 | -(5 rows) - ---Testcase 81: -select * from y; - y1 | y2 -----+----- - 1 | 111 - 2 | 222 - 3 | 333 - 4 | -(4 rows) - ---Testcase 82: -select * from x left join y on (x1 = y1 and x2 is not null); - x1 | x2 | y1 | y2 -----+----+----+----- - 1 | 11 | 1 | 111 - 2 | 22 | 2 | 222 - 3 | | | - 4 | 44 | 4 | - 5 | | | -(5 rows) - ---Testcase 83: -select * from x left join y on (x1 = y1 and y2 is not null); - x1 | x2 | y1 | y2 -----+----+----+----- - 1 | 11 | 1 | 111 - 2 | 22 | 2 | 222 - 3 | | 3 | 333 - 4 | 44 | | - 5 | | | -(5 rows) - ---Testcase 84: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 3 | | 3 | 333 | 3 | - 4 | 44 | 4 | | 4 | 44 - 5 | | | | 5 | -(5 rows) - ---Testcase 85: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1 and x2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 3 | | 3 | 333 | | - 4 | 44 | 4 | | 4 | 44 - 5 | | | | | -(5 rows) - ---Testcase 86: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1 and y2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 3 | | 3 | 333 | 3 | - 4 | 44 | 4 | | | - 5 | | | | | -(5 rows) - ---Testcase 87: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1 and xx2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 3 | | 3 | 333 | | - 4 | 44 | 4 | | 4 | 44 - 5 | | | | | -(5 rows) - --- these should NOT give the same answers as above ---Testcase 88: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1) where (x2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 4 | 44 | 4 | | 4 | 44 -(3 rows) - ---Testcase 89: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1) where (y2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 3 | | 3 | 333 | 3 | -(3 rows) - ---Testcase 90: -select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) -on (x1 = xx1) where (xx2 is not null); - x1 | x2 | y1 | y2 | xx1 | xx2 -----+----+----+-----+-----+----- - 1 | 11 | 1 | 111 | 1 | 11 - 2 | 22 | 2 | 222 | 2 | 22 - 4 | 44 | 4 | | 4 | 44 -(3 rows) - --- --- regression test: check for bug with propagation of implied equality --- to outside an IN --- ---Testcase 91: -select count(*) from tenk1 a where unique1 in - (select unique1 from tenk1 b join tenk1 c using (unique1) - where b.unique2 = 42); - count -------- - 1 -(1 row) - --- --- regression test: check for failure to generate a plan with multiple --- degenerate IN clauses --- ---Testcase 92: -select count(*) from tenk1 x where - x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and - x.unique1 = 0 and - x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); - count -------- - 1 -(1 row) - --- try that with GEQO too -begin; -set geqo = on; -set geqo_threshold = 2; ---Testcase 93: -select count(*) from tenk1 x where - x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and - x.unique1 = 0 and - x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); - count -------- - 1 -(1 row) - -rollback; --- --- regression test: be sure we cope with proven-dummy append rels --- ---Testcase 378: -create table b (aa int, bb int); ---Testcase 379: -explain (costs off) -select aa, bb, unique1, unique1 - from tenk1 right join b on aa = unique1 - where bb < bb and bb is null; - QUERY PLAN ----------------------------------------------------- - Hash Right Join - Hash Cond: (tenk1.unique1 = b.aa) - -> Foreign Scan on tenk1 - -> Hash - -> Seq Scan on b - Filter: ((bb IS NULL) AND (bb < bb)) -(6 rows) - ---Testcase 380: -select aa, bb, unique1, unique1 - from tenk1 right join b on aa = unique1 - where bb < bb and bb is null; - aa | bb | unique1 | unique1 -----+----+---------+--------- -(0 rows) - --- --- regression test: check handling of empty-FROM subquery underneath outer join --- ---Testcase 94: -explain (costs off) -select * from int8_tbl i1 left join (int8_tbl i2 join - (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 -order by 1, 2; - QUERY PLAN ------------------------------------------ - Nested Loop Left Join - Join Filter: (i1.q2 = i2.q2) - -> Foreign Scan on int8_tbl i1 - -> Materialize - -> Foreign Scan on int8_tbl i2 -(5 rows) - ---Testcase 95: -select * from int8_tbl i1 left join (int8_tbl i2 join - (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 -order by 1, 2; - q1 | q2 | q1 | q2 | x -------------------+-------------------+-----+------------------+----- - 123 | 456 | 123 | 456 | 123 - 123 | 4567890123456789 | 123 | 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 | | | - 4567890123456789 | 123 | | | - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 123 -(5 rows) - --- --- regression test: check a case where join_clause_is_movable_into() gives --- an imprecise result, causing an assertion failure --- ---Testcase 96: -select count(*) -from - (select t31.tenthous as x1, coalesce(t11.stringu1, t21.stringu1) as x2 - from tenk1 t11 - left join tenk1 t21 on t11.unique1 = t21.unique1 - join tenk1 t31 on t11.unique2 = t31.unique2) ss, - tenk1 t4, - tenk1 t5 -where t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1; - count -------- - 1000 -(1 row) - --- --- regression test: check a case where we formerly missed including an EC --- enforcement clause because it was expected to be handled at scan level --- ---Testcase 97: -explain (costs off) -select a.f1, b.f1, t.thousand, t.tenthous from - tenk1 t, - (select sum(f1)+1 as f1 from int4_tbl i4a) a, - (select sum(f1) as f1 from int4_tbl i4b) b -where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; - QUERY PLAN ------------------------------------------------------------------------------ - Hash Join - Hash Cond: (t.thousand = (sum(i4b.f1))) - Join Filter: (((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999) = t.tenthous) - -> Hash Join - Hash Cond: (t.thousand = ((sum(i4a.f1) + 1))) - -> Foreign Scan on tenk1 t - -> Hash - -> Foreign Scan - -> Hash - -> Foreign Scan -(10 rows) - ---Testcase 98: -select a.f1, b.f1, t.thousand, t.tenthous from - tenk1 t, - (select sum(f1)+1 as f1 from int4_tbl i4a) a, - (select sum(f1) as f1 from int4_tbl i4b) b -where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; - f1 | f1 | thousand | tenthous -----+----+----------+---------- -(0 rows) - --- --- check a case where we formerly got confused by conflicting sort orders --- in redundant merge join path keys --- PS: Used ORDER BY to force SQLite and PG12 always order in the same way (NULLS FIRST/LAST default value for PG and Sqlite are different) --- ---Testcase 99: -explain (costs off) -select * from - j1_tbl full join - (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl - on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k ORDER BY j1_tbl.i, j2_tbl.k; - QUERY PLAN ----------------------------------------------------------------------- - Sort - Sort Key: j1_tbl.i, j2_tbl.k - -> Hash Full Join - Hash Cond: ((j1_tbl.i = j2_tbl.i) AND (j1_tbl.i = j2_tbl.k)) - -> Foreign Scan on j1_tbl - -> Hash - -> Foreign Scan on j2_tbl -(7 rows) - ---Testcase 100: -select * from - j1_tbl full join - (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl - on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k ORDER BY j1_tbl.i, j2_tbl.k; - i | j | t | i | k ----+---+-------+---+---- - 0 | | zero | | - 1 | 4 | one | | - 2 | 3 | two | 2 | 2 - 3 | 2 | three | | - 4 | 1 | four | | - 5 | 0 | five | | - 6 | 6 | six | | - 7 | 7 | seven | | - 8 | 8 | eight | | - | | | 5 | -5 - | | | 5 | -5 - | | | 3 | -3 - | | | 1 | -1 - | | | | 0 - | | | 2 | 4 - | | | | - | | | 0 | - | 0 | zero | | - | | null | | -(19 rows) - --- --- a different check for handling of redundant sort keys in merge joins --- ---Testcase 101: -explain (costs off) -select count(*) from - (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x - left join - (select * from tenk1 y order by y.unique2) y - on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; - QUERY PLAN ----------------------------------------------------------------------------------- - Aggregate - -> Merge Left Join - Merge Cond: (x.thousand = y.unique2) - Join Filter: ((x.twothousand = y.hundred) AND (x.fivethous = y.unique2)) - -> Foreign Scan on tenk1 x - -> Materialize - -> Foreign Scan on tenk1 y -(7 rows) - ---Testcase 102: -select count(*) from - (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x - left join - (select * from tenk1 y order by y.unique2) y - on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; - count -------- - 10000 -(1 row) - --- --- Clean up --- ---Testcase 381: -DROP FOREIGN TABLE t11; ---Testcase 382: -DROP FOREIGN TABLE t21; ---Testcase 383: -DROP FOREIGN TABLE t31; ---Testcase 384: -DROP FOREIGN TABLE J1_TBL; ---Testcase 385: -DROP FOREIGN TABLE J2_TBL; --- Both DELETE and UPDATE allow the specification of additional tables --- to "join" against to determine which rows should be modified. ---Testcase 386: -CREATE FOREIGN TABLE t12 (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; ---Testcase 387: -CREATE FOREIGN TABLE t22 (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; ---Testcase 388: -CREATE FOREIGN TABLE t32 (x int OPTIONS (key 'true'), y int) SERVER sqlite_svr; ---Testcase 103: -INSERT INTO t12 VALUES (5, 10); ---Testcase 104: -INSERT INTO t12 VALUES (15, 20); ---Testcase 105: -INSERT INTO t12 VALUES (100, 100); ---Testcase 106: -INSERT INTO t12 VALUES (200, 1000); ---Testcase 107: -INSERT INTO t22 VALUES (200, 2000); ---Testcase 108: -INSERT INTO t32 VALUES (5, 20); ---Testcase 109: -INSERT INTO t32 VALUES (6, 7); ---Testcase 110: -INSERT INTO t32 VALUES (7, 8); ---Testcase 111: -INSERT INTO t32 VALUES (500, 100); ---Testcase 112: -DELETE FROM t32 USING t12 table1 WHERE t32.x = table1.a; ---Testcase 113: -SELECT * FROM t32; - x | y ------+----- - 6 | 7 - 7 | 8 - 500 | 100 -(3 rows) - ---Testcase 114: -DELETE FROM t32 USING t12 JOIN t22 USING (a) WHERE t32.x > t12.a; ---Testcase 115: -SELECT * FROM t32; - x | y ----+--- - 6 | 7 - 7 | 8 -(2 rows) - ---Testcase 116: -DELETE FROM t32 USING t32 t3_other WHERE t32.x = t3_other.x AND t32.y = t3_other.y; ---Testcase 117: -SELECT * FROM t32; - x | y ----+--- -(0 rows) - --- Test join against inheritance tree ---Testcase 389: -create temp table t2a () inherits (t22); ---Testcase 118: -insert into t2a values (200, 2001); ---Testcase 119: -select * from t12 left join t22 on (t12.a = t22.a); - a | b | a | b ------+------+-----+------ - 5 | 10 | | - 15 | 20 | | - 100 | 100 | | - 200 | 1000 | 200 | 2000 - 200 | 1000 | 200 | 2001 -(5 rows) - --- Test matching of column name with wrong alias ---Testcase 120: -select t12.x from t12 join t32 on (t12.a = t32.x); -ERROR: column t12.x does not exist -LINE 1: select t12.x from t12 join t32 on (t12.a = t32.x); - ^ -HINT: Perhaps you meant to reference the column "t32.x". -drop table t2a; --- --- regression test for 8.1 merge right join bug --- ---Testcase 390: -CREATE FOREIGN TABLE tt1 ( tt1_id int4, joincol int4 ) SERVER sqlite_svr; ---Testcase 121: -INSERT INTO tt1 VALUES (1, 11); ---Testcase 122: -INSERT INTO tt1 VALUES (2, NULL); ---Testcase 391: -CREATE FOREIGN TABLE tt2 ( tt2_id int4, joincol int4 ) SERVER sqlite_svr; ---Testcase 123: -INSERT INTO tt2 VALUES (21, 11); ---Testcase 124: -INSERT INTO tt2 VALUES (22, 11); -set enable_hashjoin to off; -set enable_nestloop to off; --- these should give the same results ---Testcase 125: -select tt1.*, tt2.* from tt1 left join tt2 on tt1.joincol = tt2.joincol; - tt1_id | joincol | tt2_id | joincol ---------+---------+--------+--------- - 1 | 11 | 21 | 11 - 1 | 11 | 22 | 11 - 2 | | | -(3 rows) - ---Testcase 126: -select tt1.*, tt2.* from tt2 right join tt1 on tt1.joincol = tt2.joincol; - tt1_id | joincol | tt2_id | joincol ---------+---------+--------+--------- - 1 | 11 | 21 | 11 - 1 | 11 | 22 | 11 - 2 | | | -(3 rows) - -reset enable_hashjoin; -reset enable_nestloop; --- --- regression test for bug #13908 (hash join with skew tuples & nbatch increase) --- -set work_mem to '64kB'; -set enable_mergejoin to off; ---Testcase 127: -explain (costs off) -select count(*) from tenk1 a, tenk1 b - where a.hundred = b.thousand and (b.fivethous % 10) < 10; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 128: -select count(*) from tenk1 a, tenk1 b - where a.hundred = b.thousand and (b.fivethous % 10) < 10; - count --------- - 100000 -(1 row) - -reset work_mem; -reset enable_mergejoin; --- --- regression test for 8.2 bug with improper re-ordering of left joins --- ---Testcase 392: -create foreign table tt3(f1 int, f2 text) server sqlite_svr; ---Testcase 129: -insert into tt3 select x, repeat('xyzzy', 100) from generate_series(1,10000) x; ---Testcase 393: -create foreign table tt4(f1 int) server sqlite_svr; ---Testcase 130: -insert into tt4 values (0),(1),(9999); ---Testcase 131: -SELECT a.f1 -FROM tt4 a -LEFT JOIN ( - SELECT b.f1 - FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) - WHERE c.f1 IS NULL -) AS d ON (a.f1 = d.f1) -WHERE d.f1 IS NULL; - f1 ------- - 0 - 1 - 9999 -(3 rows) - --- --- regression test for proper handling of outer joins within antijoins --- ---Testcase 394: -create foreign table tt4x(c1 int, c2 int, c3 int) server sqlite_svr; ---Testcase 132: -explain (costs off) -select * from tt4x t1 -where not exists ( - select 1 from tt4x t2 - left join tt4x t3 on t2.c3 = t3.c1 - left join ( select t5.c1 as c1 - from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1 - ) a1 on t3.c2 = a1.c1 - where t1.c1 = t2.c2 -); - QUERY PLAN -------------------------------------------------------------- - Hash Anti Join - Hash Cond: (t1.c1 = t2.c2) - -> Foreign Scan on tt4x t1 - -> Hash - -> Merge Right Join - Merge Cond: (t5.c1 = t3.c2) - -> Merge Join - Merge Cond: (t4.c2 = t5.c1) - -> Sort - Sort Key: t4.c2 - -> Foreign Scan on tt4x t4 - -> Sort - Sort Key: t5.c1 - -> Foreign Scan on tt4x t5 - -> Sort - Sort Key: t3.c2 - -> Merge Left Join - Merge Cond: (t2.c3 = t3.c1) - -> Sort - Sort Key: t2.c3 - -> Foreign Scan on tt4x t2 - -> Sort - Sort Key: t3.c1 - -> Foreign Scan on tt4x t3 -(24 rows) - --- --- regression test for problems of the sort depicted in bug #3494 --- ---Testcase 395: -create foreign table tt5(f1 int, f2 int) server sqlite_svr; ---Testcase 396: -create foreign table tt6(f1 int, f2 int) server sqlite_svr; ---Testcase 133: -insert into tt5 values(1, 10); ---Testcase 134: -insert into tt5 values(1, 11); ---Testcase 135: -insert into tt6 values(1, 9); ---Testcase 136: -insert into tt6 values(1, 2); ---Testcase 137: -insert into tt6 values(2, 9); ---Testcase 138: -select * from tt5,tt6 where tt5.f1 = tt6.f1 and tt5.f1 = tt5.f2 - tt6.f2; - f1 | f2 | f1 | f2 -----+----+----+---- - 1 | 10 | 1 | 9 -(1 row) - --- --- regression test for problems of the sort depicted in bug #3588 --- ---Testcase 397: -create foreign table xx (pkxx int) server sqlite_svr; ---Testcase 398: -create foreign table yy (pkyy int, pkxx int) server sqlite_svr; ---Testcase 139: -insert into xx values (1); ---Testcase 140: -insert into xx values (2); ---Testcase 141: -insert into xx values (3); ---Testcase 142: -insert into yy values (101, 1); ---Testcase 143: -insert into yy values (201, 2); ---Testcase 144: -insert into yy values (301, NULL); ---Testcase 145: -select yy.pkyy as yy_pkyy, yy.pkxx as yy_pkxx, yya.pkyy as yya_pkyy, - xxa.pkxx as xxa_pkxx, xxb.pkxx as xxb_pkxx -from yy - left join (SELECT * FROM yy where pkyy = 101) as yya ON yy.pkyy = yya.pkyy - left join xx xxa on yya.pkxx = xxa.pkxx - left join xx xxb on coalesce (xxa.pkxx, 1) = xxb.pkxx; - yy_pkyy | yy_pkxx | yya_pkyy | xxa_pkxx | xxb_pkxx ----------+---------+----------+----------+---------- - 101 | 1 | 101 | 1 | 1 - 201 | 2 | | | 1 - 301 | | | | 1 -(3 rows) - --- --- regression test for improper pushing of constants across outer-join clauses --- (as seen in early 8.2.x releases) --- ---Testcase 399: -create foreign table zt1 (f1 int OPTIONS(key 'true')) server sqlite_svr; ---Testcase 400: -create foreign table zt2 (f2 int OPTIONS(key 'true')) server sqlite_svr; ---Testcase 401: -create foreign table zt3 (f3 int OPTIONS(key 'true')) server sqlite_svr; ---Testcase 146: -insert into zt1 values(53); ---Testcase 147: -insert into zt2 values(53); ---Testcase 148: -select * from - zt2 left join zt3 on (f2 = f3) - left join zt1 on (f3 = f1) -where f2 = 53; - f2 | f3 | f1 -----+----+---- - 53 | | -(1 row) - ---Testcase 402: -create temp view zv1 as select *,'dummy'::text AS junk from zt1; ---Testcase 149: -select * from - zt2 left join zt3 on (f2 = f3) - left join zv1 on (f3 = f1) -where f2 = 53; - f2 | f3 | f1 | junk -----+----+----+------ - 53 | | | -(1 row) - -drop view zv1; --- --- regression test for improper extraction of OR indexqual conditions --- (as seen in early 8.3.x releases) --- ---Testcase 150: -select a.unique2, a.ten, b.tenthous, b.unique2, b.hundred -from tenk1 a left join tenk1 b on a.unique2 = b.tenthous -where a.unique1 = 42 and - ((b.unique2 is null and a.ten = 2) or b.hundred = 3); - unique2 | ten | tenthous | unique2 | hundred ----------+-----+----------+---------+--------- -(0 rows) - --- --- test proper positioning of one-time quals in EXISTS (8.4devel bug) --- ---Testcase 151: -prepare foo(bool) as - select count(*) from tenk1 a left join tenk1 b - on (a.unique2 = b.unique1 and exists - (select 1 from tenk1 c where c.thousand = b.unique2 and $1)); ---Testcase 152: -execute foo(true); - count -------- - 10000 -(1 row) - ---Testcase 153: -execute foo(false); - count -------- - 10000 -(1 row) - --- --- test for sane behavior with noncanonical merge clauses, per bug #4926 --- -begin; -set enable_mergejoin = 1; -set enable_hashjoin = 0; -set enable_nestloop = 0; ---Testcase 403: -create foreign table a1 (i integer) server sqlite_svr; ---Testcase 404: -create foreign table b1 (x integer, y integer) server sqlite_svr; ---Testcase 154: -select * from a1 left join b1 on i = x and i = y and x = i; - i | x | y ----+---+--- -(0 rows) - -rollback; --- skip this test, sqlite fdw does not support customized type --- test handling of merge clauses using record_ops --- ---begin; ---create type mycomptype as (id int, v bigint); ---create foreign table tidv (idv mycomptype) server sqlite_svr; ---create index on tidv (idv); ---explain (costs off) ---select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; ---set enable_mergejoin = 0; ---explain (costs off) ---select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; ---rollback; --- --- test NULL behavior of whole-row Vars, per bug #5025 --- ---Testcase 155: -select t1.q2, count(t2.*) -from int8_tbl t1 left join int8_tbl t2 on (t1.q2 = t2.q1) -group by t1.q2 order by 1; - q2 | count --------------------+------- - -4567890123456789 | 0 - 123 | 2 - 456 | 0 - 4567890123456789 | 6 -(4 rows) - ---Testcase 156: -select t1.q2, count(t2.*) -from int8_tbl t1 left join (select * from int8_tbl) t2 on (t1.q2 = t2.q1) -group by t1.q2 order by 1; - q2 | count --------------------+------- - -4567890123456789 | 0 - 123 | 2 - 456 | 0 - 4567890123456789 | 6 -(4 rows) - ---Testcase 157: -select t1.q2, count(t2.*) -from int8_tbl t1 left join (select * from int8_tbl offset 0) t2 on (t1.q2 = t2.q1) -group by t1.q2 order by 1; - q2 | count --------------------+------- - -4567890123456789 | 0 - 123 | 2 - 456 | 0 - 4567890123456789 | 6 -(4 rows) - ---Testcase 158: -select t1.q2, count(t2.*) -from int8_tbl t1 left join - (select q1, case when q2=1 then 1 else q2 end as q2 from int8_tbl) t2 - on (t1.q2 = t2.q1) -group by t1.q2 order by 1; - q2 | count --------------------+------- - -4567890123456789 | 0 - 123 | 2 - 456 | 0 - 4567890123456789 | 6 -(4 rows) - --- --- test incorrect failure to NULL pulled-up subexpressions --- -begin; ---Testcase 405: -create foreign table a2 ( - code char OPTIONS (key 'true') -) server sqlite_svr; ---Testcase 406: -create foreign table b2 ( - a char OPTIONS (key 'true'), - num integer OPTIONS (key 'true') -) server sqlite_svr; ---Testcase 407: -create foreign table c2 ( - name char OPTIONS (key 'true'), - a char -) server sqlite_svr; ---Testcase 159: -insert into a2 (code) values ('p'); ---Testcase 160: -insert into a2 (code) values ('q'); ---Testcase 161: -insert into b2 (a, num) values ('p', 1); ---Testcase 162: -insert into b2 (a, num) values ('p', 2); ---Testcase 163: -insert into c2 (name, a) values ('A', 'p'); ---Testcase 164: -insert into c2 (name, a) values ('B', 'q'); ---Testcase 165: -insert into c2 (name, a) values ('C', null); ---Testcase 166: -select c2.name, ss.code, ss.b_cnt, ss.const -from c2 left join - (select a2.code, coalesce(b_grp.cnt, 0) as b_cnt, -1 as const - from a2 left join - (select count(1) as cnt, b2.a from b2 group by b2.a) as b_grp - on a2.code = b_grp.a - ) as ss - on (c2.a = ss.code) -order by c2.name; - name | code | b_cnt | const -------+------+-------+------- - A | p | 2 | -1 - B | q | 0 | -1 - C | | | -(3 rows) - -rollback; --- --- test incorrect handling of placeholders that only appear in targetlists, --- per bug #6154 --- ---Testcase 408: -create foreign table sub_tbl (key1 int, key3 int, key5 int, key6 int, value1 int, id int options (key 'true')) server sqlite_svr; ---Testcase 409: -insert into sub_tbl values (1, 1, 1, 2, 42); ---Testcase 410: -SELECT * FROM -( SELECT key1 from sub_tbl) sub1 -LEFT JOIN -( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM - ( SELECT key3 from sub_tbl) sub3 - LEFT JOIN - ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM - ( SELECT key5 from sub_tbl) sub5 - LEFT JOIN - ( SELECT key6, value1 from sub_tbl ) sub6 - ON sub5.key5 = sub6.key6 - ) sub4 - ON sub4.key5 = sub3.key3 -) sub2 -ON sub1.key1 = sub2.key3; - key1 | key3 | value2 | value3 -------+------+--------+-------- - 1 | 1 | 1 | 1 -(1 row) - --- test the path using join aliases, too ---Testcase 411: -SELECT * FROM -( SELECT key1 from sub_tbl ) sub1 -LEFT JOIN -( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM - ( SELECT key3 from sub_tbl ) sub3 - LEFT JOIN - ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM - ( SELECT key5 from sub_tbl ) sub5 - LEFT JOIN - ( SELECT key6, value1 from sub_tbl) sub6 - ON sub5.key5 = sub6.key6 - ) sub4 - ON sub4.key5 = sub3.key3 -) sub2 -ON sub1.key1 = sub2.key3; - key1 | key3 | value2 | value3 -------+------+--------+-------- - 1 | 1 | 1 | 1 -(1 row) - --- --- test case where a PlaceHolderVar is used as a nestloop parameter --- ---Testcase 167: -EXPLAIN (COSTS OFF) -SELECT qq, unique1 - FROM - ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 - FULL OUTER JOIN - ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 - USING (qq) - INNER JOIN tenk1 c ON qq = unique2; - QUERY PLAN -------------------------------------------------------------------------------------------------------- - Merge Join - Merge Cond: (c.unique2 = (COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))) - -> Sort - Sort Key: c.unique2 - -> Foreign Scan on tenk1 c - -> Sort - Sort Key: (COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint)))) - -> Merge Full Join - Merge Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint))) - -> Sort - Sort Key: (COALESCE(a.q1, '0'::bigint)) - -> Foreign Scan on int8_tbl a - -> Sort - Sort Key: (COALESCE(b.q2, '-1'::bigint)) - -> Foreign Scan on int8_tbl b -(15 rows) - ---Testcase 168: -SELECT qq, unique1 - FROM - ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 - FULL OUTER JOIN - ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 - USING (qq) - INNER JOIN tenk1 c ON qq = unique2; - qq | unique1 ------+--------- - 123 | 4596 - 123 | 4596 - 456 | 7318 -(3 rows) - --- --- nested nestloops can require nested PlaceHolderVars --- ---Testcase 412: -create foreign table nt1 ( - id int OPTIONS (key 'true'), - a1 boolean, - a2 boolean -) server sqlite_svr; ---Testcase 413: -create foreign table nt2 ( - id int OPTIONS (key 'true'), - nt1_id int, - b1 boolean, - b2 boolean -) server sqlite_svr; ---Testcase 414: -create foreign table nt3 ( - id int OPTIONS (key 'true'), - nt2_id int, - c1 boolean -) server sqlite_svr; ---Testcase 169: -insert into nt1 values (1,true,true); ---Testcase 170: -insert into nt1 values (2,true,false); ---Testcase 171: -insert into nt1 values (3,false,false); ---Testcase 172: -insert into nt2 values (1,1,true,true); ---Testcase 173: -insert into nt2 values (2,2,true,false); ---Testcase 174: -insert into nt2 values (3,3,false,false); ---Testcase 175: -insert into nt3 values (1,1,true); ---Testcase 176: -insert into nt3 values (2,2,false); ---Testcase 177: -insert into nt3 values (3,3,true); ---Testcase 178: -explain (costs off) -select nt3.id -from nt3 as nt3 - left join - (select nt2.*, (nt2.b1 and ss1.a3) AS b3 - from nt2 as nt2 - left join - (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 - on ss1.id = nt2.nt1_id - ) as ss2 - on ss2.id = nt3.nt2_id -where nt3.id = 1 and ss2.b3; - QUERY PLAN ----------------------------------------------------- - Hash Join - Hash Cond: (nt1.id = nt2.nt1_id) - Join Filter: (nt2.b1 AND ((nt1.id IS NOT NULL))) - -> Foreign Scan on nt1 - -> Hash - -> Foreign Scan -(6 rows) - ---Testcase 179: -select nt3.id -from nt3 as nt3 - left join - (select nt2.*, (nt2.b1 and ss1.a3) AS b3 - from nt2 as nt2 - left join - (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 - on ss1.id = nt2.nt1_id - ) as ss2 - on ss2.id = nt3.nt2_id -where nt3.id = 1 and ss2.b3; - id ----- - 1 -(1 row) - --- --- test case where a PlaceHolderVar is propagated into a subquery --- ---Testcase 180: -explain (costs off) -select * from - int8_tbl t1 left join - (select q1 as x, 42 as y from int8_tbl t2) ss - on t1.q2 = ss.x -where - 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) -order by 1,2; - QUERY PLAN ------------------------------------------------------ - Sort - Sort Key: t1.q1, t1.q2 - -> Hash Right Join - Hash Cond: (t2.q1 = t1.q2) - Filter: (1 = (SubPlan 1)) - -> Foreign Scan on int8_tbl t2 - -> Hash - -> Foreign Scan on int8_tbl t1 - SubPlan 1 - -> Result - One-Time Filter: ((42) IS NOT NULL) - -> Foreign Scan on int8_tbl t3 -(12 rows) - ---Testcase 181: -select * from - int8_tbl t1 left join - (select q1 as x, 42 as y from int8_tbl t2) ss - on t1.q2 = ss.x -where - 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) -order by 1,2; - q1 | q2 | x | y -------------------+------------------+------------------+---- - 123 | 4567890123456789 | 4567890123456789 | 42 - 123 | 4567890123456789 | 4567890123456789 | 42 - 123 | 4567890123456789 | 4567890123456789 | 42 - 4567890123456789 | 123 | 123 | 42 - 4567890123456789 | 123 | 123 | 42 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 -(8 rows) - --- --- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE --- ---Testcase 182: -select * from int4_tbl a full join int4_tbl b on true; - f1 | f1 --------------+------------- - 0 | 0 - 0 | 123456 - 0 | -123456 - 0 | 2147483647 - 0 | -2147483647 - 123456 | 0 - 123456 | 123456 - 123456 | -123456 - 123456 | 2147483647 - 123456 | -2147483647 - -123456 | 0 - -123456 | 123456 - -123456 | -123456 - -123456 | 2147483647 - -123456 | -2147483647 - 2147483647 | 0 - 2147483647 | 123456 - 2147483647 | -123456 - 2147483647 | 2147483647 - 2147483647 | -2147483647 - -2147483647 | 0 - -2147483647 | 123456 - -2147483647 | -123456 - -2147483647 | 2147483647 - -2147483647 | -2147483647 -(25 rows) - ---Testcase 183: -select * from int4_tbl a full join int4_tbl b on false; - f1 | f1 --------------+------------- - | 0 - | 123456 - | -123456 - | 2147483647 - | -2147483647 - 0 | - 123456 | - -123456 | - 2147483647 | - -2147483647 | -(10 rows) - --- --- test for ability to use a cartesian join when necessary --- ---Testcase 415: -create foreign table q1(i int) server sqlite_svr; ---Testcase 416: -insert into q1 values (1); ---Testcase 417: -create foreign table q2(i int) server sqlite_svr; ---Testcase 418: -insert into q2 values (0); ---Testcase 184: -explain (costs off) -select * from - tenk1 join int4_tbl on f1 = twothousand, - q1, q2 -where q1.i = thousand or q2.i = thousand; - QUERY PLAN ------------------------------------------------- - Hash Join - Hash Cond: (tenk1.twothousand = int4_tbl.f1) - -> Foreign Scan - -> Hash - -> Foreign Scan on int4_tbl -(5 rows) - ---Testcase 185: -explain (costs off) -select * from - tenk1 join int4_tbl on f1 = twothousand, - q1, q2 -where thousand = (q1.i + q2.i); - QUERY PLAN --------------------------------------------------- - Merge Join - Merge Cond: (tenk1.thousand = ((q1.i + q2.i))) - -> Sort - Sort Key: tenk1.thousand - -> Foreign Scan - -> Materialize - -> Sort - Sort Key: ((q1.i + q2.i)) - -> Nested Loop - -> Foreign Scan on q1 - -> Materialize - -> Foreign Scan on q2 -(12 rows) - --- --- test ability to generate a suitable plan for a star-schema query --- ---Testcase 186: -explain (costs off) -select * from - tenk1, int8_tbl a, int8_tbl b -where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2; - QUERY PLAN ----------------------------------------- - Hash Join - Hash Cond: (tenk1.tenthous = b.q1) - -> Foreign Scan - -> Hash - -> Foreign Scan on int8_tbl b -(5 rows) - --- --- test a corner case in which we shouldn't apply the star-schema optimization --- ---Testcase 187: -explain (costs off) -select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from - tenk1 t1 - inner join int4_tbl i1 - left join (select v1.x2, v2.y1, 11 AS d1 - from (select 1,0 from onerow) v1(x1,x2) - left join (select 3,1 from onerow) v2(y1,y2) - on v1.x1 = v2.y2) subq1 - on (i1.f1 = subq1.x2) - on (t1.unique2 = subq1.d1) - left join tenk1 t2 - on (subq1.y1 = t2.unique1) -where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; - QUERY PLAN ------------------------------------------------------ - Hash Join - Hash Cond: (t2.unique1 = (3)) - Join Filter: (t1.stringu1 > t2.stringu2) - -> Foreign Scan - -> Hash - -> Nested Loop - Join Filter: ((11) = t1.unique2) - -> Nested Loop - -> Seq Scan on onerow - -> Seq Scan on onerow onerow_1 - -> Foreign Scan on tenk1 t1 -(11 rows) - ---Testcase 188: -select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from - tenk1 t1 - inner join int4_tbl i1 - left join (select v1.x2, v2.y1, 11 AS d1 - from (select 1,0 from onerow) v1(x1,x2) - left join (select 3,1 from onerow) v2(y1,y2) - on v1.x1 = v2.y2) subq1 - on (i1.f1 = subq1.x2) - on (t1.unique2 = subq1.d1) - left join tenk1 t2 - on (subq1.y1 = t2.unique1) -where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; - unique2 | stringu1 | unique1 | stringu2 ----------+----------+---------+---------- - 11 | WFAAAA | 3 | LKIAAA -(1 row) - --- variant that isn't quite a star-schema case ---Testcase 189: -select ss1.d1 from - tenk1 as t1 - inner join tenk1 as t2 - on t1.tenthous = t2.ten - inner join - int8_tbl as i8 - left join int4_tbl as i4 - inner join (select 64::information_schema.cardinal_number as d1 - from tenk1 t3, - lateral (select abs(t3.unique1) + random()) ss0(x) - where t3.fivethous < 0) as ss1 - on i4.f1 = ss1.d1 - on i8.q1 = i4.f1 - on t1.tenthous = ss1.d1 -where t1.unique1 < i4.f1; - d1 ----- -(0 rows) - --- this variant is foldable by the remove-useless-RESULT-RTEs code ---Testcase 419: -explain (costs off) -select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from - tenk1 t1 - inner join int4_tbl i1 - left join (select v1.x2, v2.y1, 11 AS d1 - from (values(1,0)) v1(x1,x2) - left join (values(3,1)) v2(y1,y2) - on v1.x1 = v2.y2) subq1 - on (i1.f1 = subq1.x2) - on (t1.unique2 = subq1.d1) - left join tenk1 t2 - on (subq1.y1 = t2.unique1) -where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; - QUERY PLAN ------------------------------------------------------ - Hash Join - Hash Cond: (t2.unique1 = (3)) - Join Filter: (t1.stringu1 > t2.stringu2) - -> Foreign Scan on tenk1 t2 - -> Hash - -> Hash Join - Hash Cond: (t1.unique2 = (11)) - -> Foreign Scan on tenk1 t1 - -> Hash - -> Foreign Scan on int4_tbl i1 -(10 rows) - ---Testcase 420: -select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from - tenk1 t1 - inner join int4_tbl i1 - left join (select v1.x2, v2.y1, 11 AS d1 - from (values(1,0)) v1(x1,x2) - left join (values(3,1)) v2(y1,y2) - on v1.x1 = v2.y2) subq1 - on (i1.f1 = subq1.x2) - on (t1.unique2 = subq1.d1) - left join tenk1 t2 - on (subq1.y1 = t2.unique1) -where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; - unique2 | stringu1 | unique1 | stringu2 ----------+----------+---------+---------- - 11 | WFAAAA | 3 | LKIAAA -(1 row) - --- Here's a variant that we can't fold too aggressively, though, --- or we end up with noplace to evaluate the lateral PHV ---Testcase 421: -explain (verbose, costs off) -select * from - (select key1 as x from sub_tbl) ss1 left join (select key6 as y from sub_tbl) ss2 on (true), - lateral (select ss2.y as z limit 1) ss3; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - Nested Loop - Output: sub_tbl.key1, sub_tbl_1.key6, (sub_tbl_1.key6) - -> Nested Loop Left Join - Output: sub_tbl.key1, sub_tbl_1.key6 - -> Foreign Scan on public.sub_tbl - Output: sub_tbl.key1, sub_tbl.key3, sub_tbl.key5, sub_tbl.key6, sub_tbl.value1, sub_tbl.id - SQLite query: SELECT `key1` FROM main."sub_tbl" - -> Materialize - Output: sub_tbl_1.key6 - -> Foreign Scan on public.sub_tbl sub_tbl_1 - Output: sub_tbl_1.key6 - SQLite query: SELECT `key6` FROM main."sub_tbl" - -> Limit - Output: (sub_tbl_1.key6) - -> Result - Output: sub_tbl_1.key6 -(16 rows) - ---Testcase 422: -select * from - (select key1 as x from sub_tbl as x) ss1 left join (select key6 as y from sub_tbl) ss2 on (true), - lateral (select ss2.y as z limit 1) ss3; - x | y | z ----+---+--- - 1 | 2 | 2 -(1 row) - - --- --- test inlining of immutable functions --- ---Testcase 423: -create function f_immutable_int4(i integer) returns integer as -$$ begin return i; end; $$ language plpgsql immutable; --- check optimization of function scan with join ---Testcase 424: -explain (costs off) -select unique1 from tenk1, (select * from f_immutable_int4(1) x) x -where x = unique1; - QUERY PLAN ------------------------------------- - Hash Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 425: -explain (verbose, costs off) -select unique1, x.* -from tenk1, (select *, random() from f_immutable_int4(1) x) x -where x = unique1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Join - Output: tenk1.unique1, x.x, (random()) - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on public.tenk1 - Output: tenk1.unique1, tenk1.unique2, tenk1.two, tenk1.four, tenk1.ten, tenk1.twenty, tenk1.hundred, tenk1.thousand, tenk1.twothousand, tenk1.fivethous, tenk1.tenthous, tenk1.odd, tenk1.even, tenk1.stringu1, tenk1.stringu2, tenk1.string4 - SQLite query: SELECT `unique1` FROM main."tenk1" - -> Hash - Output: x.x, (random()) - -> Function Scan on x - Output: x.x, random() - Function Call: 1 -(11 rows) - ---Testcase 426: -explain (costs off) -select unique1 from tenk1, f_immutable_int4(1) x where x = unique1; - QUERY PLAN ------------------------------------- - Hash Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 427: -explain (costs off) -select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1; - QUERY PLAN ------------------------------------- - Hash Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 428: -explain (costs off) -select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x; - QUERY PLAN ------------------------------------- - Hash Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 429: -explain (costs off) -select unique1, x from tenk1 left join f_immutable_int4(1) x on unique1 = x; - QUERY PLAN ------------------------------------- - Hash Left Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 430: -explain (costs off) -select unique1, x from tenk1 right join f_immutable_int4(1) x on unique1 = x; - QUERY PLAN ------------------------------------- - Hash Right Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - ---Testcase 431: -explain (costs off) -select unique1, x from tenk1 full join f_immutable_int4(1) x on unique1 = x; - QUERY PLAN ------------------------------------- - Hash Full Join - Hash Cond: (tenk1.unique1 = x.x) - -> Foreign Scan on tenk1 - -> Hash - -> Function Scan on x -(5 rows) - --- check that pullup of a const function allows further const-folding ---Testcase 432: -explain (costs off) -select unique1 from tenk1, f_immutable_int4(1) x where x = 42; - QUERY PLAN ------------------------------ - Nested Loop - -> Function Scan on x - Filter: (x = 42) - -> Foreign Scan on tenk1 -(4 rows) - --- test inlining of immutable functions with PlaceHolderVars ---Testcase 433: -explain (costs off) -select nt3.id -from nt3 as nt3 - left join - (select nt2.*, (nt2.b1 or i4 = 42) AS b3 - from nt2 as nt2 - left join - f_immutable_int4(0) i4 - on i4 = nt2.nt1_id - ) as ss2 - on ss2.id = nt3.nt2_id -where nt3.id = 1 and ss2.b3; - QUERY PLAN ------------------------------------------ - Hash Right Join - Hash Cond: (nt2.id = nt3.nt2_id) - Filter: ((nt2.b1 OR (i4.i4 = 42))) - -> Hash Left Join - Hash Cond: (nt2.nt1_id = i4.i4) - -> Foreign Scan on nt2 - -> Hash - -> Function Scan on i4 - -> Hash - -> Foreign Scan on nt3 -(10 rows) - ---Testcase 434: -drop function f_immutable_int4(int); --- test inlining when function returns composite ---Testcase 435: -create function mki8(bigint, bigint) returns int8_tbl as -$$select row($1,$2)::int8_tbl$$ language sql; ---Testcase 436: -create function mki4(int) returns int4_tbl as -$$select row($1)::int4_tbl$$ language sql; ---Testcase 437: -explain (verbose, costs off) -select * from mki8(1,2); - QUERY PLAN ------------------------------------- - Function Scan on mki8 - Output: q1, q2 - Function Call: '(1,2)'::int8_tbl -(3 rows) - ---Testcase 438: -select * from mki8(1,2); - q1 | q2 -----+---- - 1 | 2 -(1 row) - ---Testcase 439: -explain (verbose, costs off) -select * from mki4(42); - QUERY PLAN ------------------------------------ - Function Scan on mki4 - Output: f1 - Function Call: '(42)'::int4_tbl -(3 rows) - ---Testcase 440: -select * from mki4(42); - f1 ----- - 42 -(1 row) - ---Testcase 441: -drop function mki8(bigint, bigint); ---Testcase 442: -drop function mki4(int); --- --- test extraction of restriction OR clauses from join OR clause --- (we used to only do this for indexable clauses) --- ---Testcase 190: -explain (costs off) -select * from tenk1 a join tenk1 b on - (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.hundred = 4); - QUERY PLAN -------------------------------------------------------------------------------------------------- - Nested Loop - Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.hundred = 4))) - -> Foreign Scan on tenk1 a - -> Materialize - -> Foreign Scan on tenk1 b -(5 rows) - ---Testcase 191: -explain (costs off) -select * from tenk1 a join tenk1 b on - (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.ten = 4); - QUERY PLAN ---------------------------------------------------------------------------------------------- - Nested Loop - Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.ten = 4))) - -> Foreign Scan on tenk1 a - -> Materialize - -> Foreign Scan on tenk1 b -(5 rows) - ---Testcase 192: -explain (costs off) -select * from tenk1 a join tenk1 b on - (a.unique1 = 1 and b.unique1 = 2) or - ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Nested Loop - Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4))) - -> Foreign Scan on tenk1 a - -> Materialize - -> Foreign Scan on tenk1 b -(5 rows) - --- --- test placement of movable quals in a parameterized join tree --- ---Testcase 193: -explain (costs off) -select * from tenk1 t1 left join - (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) - on t1.hundred = t2.hundred and t1.ten = t3.ten -where t1.unique1 = 1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 194: -explain (costs off) -select * from tenk1 t1 left join - (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) - on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten -where t1.unique1 = 1; - QUERY PLAN ---------------------------------------------- - Hash Right Join - Hash Cond: (t2.hundred = t1.hundred) - Join Filter: ((t1.ten + t2.ten) = t3.ten) - -> Foreign Scan - -> Hash - -> Foreign Scan on tenk1 t1 -(6 rows) - ---Testcase 195: -explain (costs off) -select count(*) from - tenk1 a join tenk1 b on a.unique1 = b.unique2 - left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand - join int4_tbl on b.thousand = f1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 196: -select count(*) from - tenk1 a join tenk1 b on a.unique1 = b.unique2 - left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand - join int4_tbl on b.thousand = f1; - count -------- - 10 -(1 row) - ---Testcase 197: -explain (costs off) -select b.unique1 from - tenk1 a join tenk1 b on a.unique1 = b.unique2 - left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand - join int4_tbl i1 on b.thousand = f1 - right join int4_tbl i2 on i2.f1 = b.tenthous - order by 1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 198: -select b.unique1 from - tenk1 a join tenk1 b on a.unique1 = b.unique2 - left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand - join int4_tbl i1 on b.thousand = f1 - right join int4_tbl i2 on i2.f1 = b.tenthous - order by 1; - unique1 ---------- - 0 - - - - -(5 rows) - ---Testcase 199: -explain (costs off) -select * from -( - select unique1, q1, coalesce(unique1, -1) + q1 as fault - from int8_tbl left join tenk1 on (q2 = unique2) -) ss -where fault = 122 -order by fault; - QUERY PLAN --------------------------------------------------------------------------- - Merge Left Join - Merge Cond: (int8_tbl.q2 = tenk1.unique2) - Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122) - -> Sort - Sort Key: int8_tbl.q2 - -> Foreign Scan on int8_tbl - -> Sort - Sort Key: tenk1.unique2 - -> Foreign Scan on tenk1 -(9 rows) - ---Testcase 200: -select * from -( - select unique1, q1, coalesce(unique1, -1) + q1 as fault - from int8_tbl left join tenk1 on (q2 = unique2) -) ss -where fault = 122 -order by fault; - unique1 | q1 | fault ----------+-----+------- - | 123 | 122 -(1 row) - ---Testcase 201: -explain (costs off) -select * from -(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) -left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x -left join unnest(v1ys) as u1(u1y) on u1y = v2y; - QUERY PLAN -------------------------------------------------------------- - Nested Loop Left Join - -> Values Scan on "*VALUES*" - -> Hash Right Join - Hash Cond: (u1.u1y = "*VALUES*_1".column2) - Filter: ("*VALUES*_1".column1 = "*VALUES*".column1) - -> Function Scan on unnest u1 - -> Hash - -> Values Scan on "*VALUES*_1" -(8 rows) - ---Testcase 202: -select * from -(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) -left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x -left join unnest(v1ys) as u1(u1y) on u1y = v2y; - v1x | v1ys | v2x | v2y | u1y ------+---------+-----+-----+----- - 1 | {10,20} | 1 | 10 | 10 - 2 | {20,30} | 2 | 20 | 20 -(2 rows) - --- --- test handling of potential equivalence clauses above outer joins --- ---Testcase 203: -explain (costs off) -select q1, unique2, thousand, hundred - from int8_tbl a left join tenk1 b on q1 = unique2 - where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); - QUERY PLAN --------------------------------------------------------------------------------------- - Merge Right Join - Merge Cond: (b.unique2 = a.q1) - Filter: ((COALESCE(b.thousand, 123) = a.q1) AND (a.q1 = COALESCE(b.hundred, 123))) - -> Sort - Sort Key: b.unique2 - -> Foreign Scan on tenk1 b - -> Sort - Sort Key: a.q1 - -> Foreign Scan on int8_tbl a -(9 rows) - ---Testcase 204: -select q1, unique2, thousand, hundred - from int8_tbl a left join tenk1 b on q1 = unique2 - where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); - q1 | unique2 | thousand | hundred -----+---------+----------+--------- -(0 rows) - ---Testcase 205: -explain (costs off) -select f1, unique2, case when unique2 is null then f1 else 0 end - from int4_tbl a left join tenk1 b on f1 = unique2 - where (case when unique2 is null then f1 else 0 end) = 0; - QUERY PLAN --------------------------------------------------------------------- - Merge Left Join - Merge Cond: (a.f1 = b.unique2) - Filter: (CASE WHEN (b.unique2 IS NULL) THEN a.f1 ELSE 0 END = 0) - -> Sort - Sort Key: a.f1 - -> Foreign Scan on int4_tbl a - -> Sort - Sort Key: b.unique2 - -> Foreign Scan on tenk1 b -(9 rows) - ---Testcase 206: -select f1, unique2, case when unique2 is null then f1 else 0 end - from int4_tbl a left join tenk1 b on f1 = unique2 - where (case when unique2 is null then f1 else 0 end) = 0; - f1 | unique2 | case -----+---------+------ - 0 | 0 | 0 -(1 row) - --- --- another case with equivalence clauses above outer joins (bug #8591) --- ---Testcase 207: -explain (costs off) -select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) - from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) - where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; - QUERY PLAN -------------------------------------------------------------------- - Hash Left Join - Hash Cond: (COALESCE(b.twothousand, a.twothousand) = c.unique2) - -> Merge Left Join - Merge Cond: (a.unique1 = b.thousand) - Filter: (COALESCE(b.twothousand, a.twothousand) = 44) - -> Sort - Sort Key: a.unique1 - -> Foreign Scan on tenk1 a - -> Sort - Sort Key: b.thousand - -> Foreign Scan on tenk1 b - -> Hash - -> Foreign Scan on tenk1 c -(13 rows) - ---Testcase 208: -select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) - from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) - where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; - unique1 | unique1 | unique1 | coalesce ----------+---------+---------+---------- -(0 rows) - --- --- check handling of join aliases when flattening multiple levels of subquery --- ---Testcase 209: -explain (verbose, costs off) -select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from - (values (0),(1)) foo1(join_key) -left join - (select join_key, bug_field from - (select ss1.join_key, ss1.bug_field from - (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 - ) foo2 - left join - (select unique2 as join_key from tenk1 i2) ss2 - using (join_key) - ) foo3 -using (join_key); - QUERY PLAN ----------------------------------------------------------------------- - Merge Right Join - Output: "*VALUES*".column1, i1.f1, (666) - Merge Cond: (i1.f1 = "*VALUES*".column1) - -> Merge Left Join - Output: i1.f1, 666 - Merge Cond: (i1.f1 = i2.unique2) - -> Sort - Output: i1.f1 - Sort Key: i1.f1 - -> Foreign Scan on public.int4_tbl i1 - Output: i1.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Sort - Output: i2.unique2 - Sort Key: i2.unique2 - -> Foreign Scan on public.tenk1 i2 - Output: i2.unique2 - SQLite query: SELECT `unique2` FROM main."tenk1" - -> Sort - Output: "*VALUES*".column1 - Sort Key: "*VALUES*".column1 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1 -(23 rows) - ---Testcase 210: -select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from - (values (0),(1)) foo1(join_key) -left join - (select join_key, bug_field from - (select ss1.join_key, ss1.bug_field from - (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 - ) foo2 - left join - (select unique2 as join_key from tenk1 i2) ss2 - using (join_key) - ) foo3 -using (join_key); - foo1_id | foo3_id | bug_field ----------+---------+----------- - 0 | 0 | 666 - 1 | | -(2 rows) - --- --- test successful handling of nested outer joins with degenerate join quals --- ---Testcase 443: -create foreign table text_tbl(f1 text) server sqlite_svr; ---Testcase 211: -explain (verbose, costs off) -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - QUERY PLAN --------------------------------------------------------------------------------------------------------------- - Merge Right Join - Output: t1.f1 - Merge Cond: (i4.f1 = i8.q2) - -> Sort - Output: i4.f1 - Sort Key: i4.f1 - -> Foreign Scan on public.int4_tbl i4 - Output: i4.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Materialize - Output: t1.f1, i8.q2 - -> Sort - Output: t1.f1, i8.q2 - Sort Key: i8.q2 - -> Nested Loop Left Join - Output: t1.f1, i8.q2 - Join Filter: (t1.f1 = '***'::text) - -> Foreign Scan on public.text_tbl t1 - Output: t1.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" - -> Materialize - Output: i8.q2 - -> Merge Left Join - Output: i8.q2 - Merge Cond: (i8b1.q2 = (NULL::integer)) - -> Sort - Output: i8b1.q2 - Sort Key: i8b1.q2 - -> Foreign Scan on public.int8_tbl i8b1 - Output: i8b1.q2 - SQLite query: SELECT `q2` FROM main."int8_tbl" - -> Sort - Output: i8.q2, (NULL::integer) - Sort Key: (NULL::integer) - -> Merge Join - Output: i8.q2, (NULL::integer) - Merge Cond: (i8.q1 = i8b2.q1) - -> Sort - Output: i8.q1, i8.q2 - Sort Key: i8.q1 - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Sort - Output: i8b2.q1, (NULL::integer) - Sort Key: i8b2.q1 - -> Foreign Scan on public.int8_tbl i8b2 - Output: i8b2.q1, NULL::integer - SQLite query: SELECT `q1` FROM main."int8_tbl" -(49 rows) - ---Testcase 212: -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - f1 -------------------- - doh! - hi de ho neighbor -(2 rows) - ---Testcase 213: -explain (verbose, costs off) -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - Hash Left Join - Output: t1.f1 - Hash Cond: (i8.q2 = i4.f1) - -> Nested Loop Left Join - Output: t1.f1, i8.q2 - Join Filter: (t1.f1 = '***'::text) - -> Foreign Scan on public.text_tbl t1 - Output: t1.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" - -> Materialize - Output: i8.q2 - -> Merge Left Join - Output: i8.q2 - Merge Cond: (i8b1.q2 = (NULL::integer)) - -> Sort - Output: i8b1.q2 - Sort Key: i8b1.q2 - -> Foreign Scan on public.int8_tbl i8b1 - Output: i8b1.q2 - SQLite query: SELECT `q2` FROM main."int8_tbl" - -> Materialize - Output: i8.q2, (NULL::integer) - -> Sort - Output: i8.q2, (NULL::integer) - Sort Key: (NULL::integer) - -> Merge Left Join - Output: i8.q2, (NULL::integer) - Merge Cond: (i8.q1 = i8b2.q1) - -> Sort - Output: i8.q1, i8.q2 - Sort Key: i8.q1 - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Materialize - Output: i8b2.q1, (NULL::integer) - -> Sort - Output: i8b2.q1, (NULL::integer) - Sort Key: i8b2.q1 - -> Nested Loop - Output: i8b2.q1, NULL::integer - -> Foreign Scan on public.int4_tbl i4b2 - Output: i4b2.f1 - SQLite query: SELECT NULL FROM main."int4_tbl" - -> Materialize - Output: i8b2.q1 - -> Foreign Scan on public.int8_tbl i8b2 - Output: i8b2.q1 - SQLite query: SELECT `q1` FROM main."int8_tbl" - -> Hash - Output: i4.f1 - -> Foreign Scan on public.int4_tbl i4 - Output: i4.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" -(54 rows) - ---Testcase 214: -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - f1 -------------------- - doh! - hi de ho neighbor -(2 rows) - ---Testcase 215: -explain (verbose, costs off) -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 - where q1 = f1) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Merge Right Join - Output: t1.f1 - Merge Cond: (i4.f1 = i8.q2) - -> Sort - Output: i4.f1 - Sort Key: i4.f1 - -> Foreign Scan on public.int4_tbl i4 - Output: i4.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Materialize - Output: t1.f1, i8.q2 - -> Sort - Output: t1.f1, i8.q2 - Sort Key: i8.q2 - -> Nested Loop Left Join - Output: t1.f1, i8.q2 - Join Filter: (t1.f1 = '***'::text) - -> Foreign Scan on public.text_tbl t1 - Output: t1.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" - -> Materialize - Output: i8.q2 - -> Merge Left Join - Output: i8.q2 - Merge Cond: (i8b1.q2 = (NULL::integer)) - -> Sort - Output: i8b1.q2 - Sort Key: i8b1.q2 - -> Foreign Scan on public.int8_tbl i8b1 - Output: i8b1.q2 - SQLite query: SELECT `q2` FROM main."int8_tbl" - -> Materialize - Output: i8.q2, (NULL::integer) - -> Sort - Output: i8.q2, (NULL::integer) - Sort Key: (NULL::integer) - -> Merge Left Join - Output: i8.q2, (NULL::integer) - Merge Cond: (i8.q1 = i8b2.q1) - -> Sort - Output: i8.q1, i8.q2 - Sort Key: i8.q1 - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Materialize - Output: i8b2.q1, (NULL::integer) - -> Merge Join - Output: i8b2.q1, NULL::integer - Merge Cond: (i8b2.q1 = i4b2.f1) - -> Sort - Output: i8b2.q1 - Sort Key: i8b2.q1 - -> Foreign Scan on public.int8_tbl i8b2 - Output: i8b2.q1 - SQLite query: SELECT `q1` FROM main."int8_tbl" - -> Sort - Output: i4b2.f1 - Sort Key: i4b2.f1 - -> Foreign Scan on public.int4_tbl i4b2 - Output: i4b2.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" -(62 rows) - ---Testcase 216: -select t1.* from - text_tbl t1 - left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 - left join int8_tbl i8 - left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 - where q1 = f1) b2 - on (i8.q1 = b2.q1) - on (b2.d2 = b1.q2) - on (t1.f1 = b1.d1) - left join int4_tbl i4 - on (i8.q2 = i4.f1); - f1 -------------------- - doh! - hi de ho neighbor -(2 rows) - ---Testcase 217: -explain (verbose, costs off) -select * from - text_tbl t1 - inner join int8_tbl i8 - on i8.q2 = 456 - right join text_tbl t2 - on t1.f1 = 'doh!' - left join int4_tbl i4 - on i8.q1 = i4.f1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join - Output: t1.f1, i8.q1, i8.q2, t2.f1, i4.f1 - -> Foreign Scan on public.text_tbl t2 - Output: t2.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" - -> Materialize - Output: i8.q1, i8.q2, i4.f1, t1.f1 - -> Nested Loop - Output: i8.q1, i8.q2, i4.f1, t1.f1 - -> Foreign Scan - Output: i8.q1, i8.q2, i4.f1 - SQLite query: SELECT r2.`q1`, r2.`q2`, r6.`f1` FROM (main."int8_tbl" r2 LEFT JOIN main."int4_tbl" r6 ON (((r2.`q1` = r6.`f1`)))) WHERE ((r2.`q2` = 456)) - -> Materialize - Output: t1.f1 - -> Foreign Scan on public.text_tbl t1 - Output: t1.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'doh!')) -(17 rows) - ---Testcase 218: -select * from - text_tbl t1 - inner join int8_tbl i8 - on i8.q2 = 456 - right join text_tbl t2 - on t1.f1 = 'doh!' - left join int4_tbl i4 - on i8.q1 = i4.f1; - f1 | q1 | q2 | f1 | f1 -------+-----+-----+-------------------+---- - doh! | 123 | 456 | doh! | - doh! | 123 | 456 | hi de ho neighbor | -(2 rows) - --- --- test for appropriate join order in the presence of lateral references --- ---Testcase 219: -explain (verbose, costs off) -select * from - text_tbl t1 - left join int8_tbl i8 - on i8.q2 = 123, - lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss -where t1.f1 = ss.f1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 - Join Filter: (t1.f1 = t2.f1) - -> Foreign Scan - Output: t1.f1, i8.q1, i8.q2 - SQLite query: SELECT r1.`f1`, r2.`q1`, r2.`q2` FROM (main."text_tbl" r1 LEFT JOIN main."int8_tbl" r2 ON (((r2.`q2` = 123)))) - -> Foreign Scan on public.text_tbl t2 - Output: i8.q1, t2.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" LIMIT 1 -(9 rows) - ---Testcase 220: -select * from - text_tbl t1 - left join int8_tbl i8 - on i8.q2 = 123, - lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss -where t1.f1 = ss.f1; - f1 | q1 | q2 | q1 | f1 -------+------------------+-----+------------------+------ - doh! | 4567890123456789 | 123 | 4567890123456789 | doh! -(1 row) - ---Testcase 221: -explain (verbose, costs off) -select * from - text_tbl t1 - left join int8_tbl i8 - on i8.q2 = 123, - lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, - lateral (select ss1.* from text_tbl t3 limit 1) as ss2 -where t1.f1 = ss2.f1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1, ((i8.q1)), (t2.f1) - Join Filter: (t1.f1 = (t2.f1)) - -> Nested Loop - Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 - -> Foreign Scan - Output: t1.f1, i8.q1, i8.q2 - SQLite query: SELECT r1.`f1`, r2.`q1`, r2.`q2` FROM (main."text_tbl" r1 LEFT JOIN main."int8_tbl" r2 ON (((r2.`q2` = 123)))) - -> Foreign Scan on public.text_tbl t2 - Output: i8.q1, t2.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" LIMIT 1 - -> Foreign Scan on public.text_tbl t3 - Output: (i8.q1), t2.f1 - SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 -(14 rows) - ---Testcase 222: -select * from - text_tbl t1 - left join int8_tbl i8 - on i8.q2 = 123, - lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, - lateral (select ss1.* from text_tbl t3 limit 1) as ss2 -where t1.f1 = ss2.f1; - f1 | q1 | q2 | q1 | f1 | q1 | f1 -------+------------------+-----+------------------+------+------------------+------ - doh! | 4567890123456789 | 123 | 4567890123456789 | doh! | 4567890123456789 | doh! -(1 row) - ---Testcase 223: -explain (verbose, costs off) -select 1 from - text_tbl as tt1 - inner join text_tbl as tt2 on (tt1.f1 = 'foo') - left join text_tbl as tt3 on (tt3.f1 = 'foo') - left join text_tbl as tt4 on (tt3.f1 = tt4.f1), - lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 -where tt1.f1 = ss1.c0; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Nested Loop - Output: 1 - -> Nested Loop Left Join - Output: tt1.f1, tt4.f1 - -> Foreign Scan - Output: tt1.f1 - SQLite query: SELECT r1.`f1` FROM (main."text_tbl" r1 INNER JOIN main."text_tbl" r2 ON (((r1.`f1` = 'foo')))) - -> Hash Left Join - Output: tt4.f1 - Hash Cond: (tt3.f1 = tt4.f1) - -> Foreign Scan on public.text_tbl tt3 - Output: tt3.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'foo')) - -> Hash - Output: tt4.f1 - -> Foreign Scan on public.text_tbl tt4 - Output: tt4.f1 - SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'foo')) - -> Subquery Scan on ss1 - Output: ss1.c0 - Filter: (ss1.c0 = 'foo'::text) - -> Foreign Scan on public.text_tbl tt5 - Output: tt4.f1 - SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 -(24 rows) - ---Testcase 224: -select 1 from - text_tbl as tt1 - inner join text_tbl as tt2 on (tt1.f1 = 'foo') - left join text_tbl as tt3 on (tt3.f1 = 'foo') - left join text_tbl as tt4 on (tt3.f1 = tt4.f1), - lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 -where tt1.f1 = ss1.c0; - ?column? ----------- -(0 rows) - --- --- check a case in which a PlaceHolderVar forces join order --- ---Testcase 225: -explain (verbose, costs off) -select ss2.* from - int4_tbl i41 - left join int8_tbl i8 - join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 - from int4_tbl i42, int4_tbl i43) ss1 - on i8.q1 = ss1.c2 - on i41.f1 = ss1.c1, - lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 -where ss1.c2 = 0; - QUERY PLAN ---------------------------------------------------------------------------------------------------- - Nested Loop - Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42)) - -> Nested Loop - Output: i41.f1, i42.f1, i8.q1, i8.q2, i43.f1, 42 - -> Nested Loop - Output: i41.f1, i42.f1, i8.q1, i8.q2 - -> Merge Join - Output: i41.f1, i42.f1 - Merge Cond: (i41.f1 = i42.f1) - -> Sort - Output: i41.f1 - Sort Key: i41.f1 - -> Foreign Scan on public.int4_tbl i41 - Output: i41.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Sort - Output: i42.f1 - Sort Key: i42.f1 - -> Foreign Scan on public.int4_tbl i42 - Output: i42.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Materialize - Output: i8.q1, i8.q2 - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((`q1` = 0)) - -> Materialize - Output: i43.f1 - -> Foreign Scan on public.int4_tbl i43 - Output: i43.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" WHERE ((`f1` = 0)) - -> Foreign Scan on public.text_tbl - Output: i41.f1, i8.q1, i8.q2, i42.f1, i43.f1, (42) - SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 -(34 rows) - ---Testcase 226: -select ss2.* from - int4_tbl i41 - left join int8_tbl i8 - join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 - from int4_tbl i42, int4_tbl i43) ss1 - on i8.q1 = ss1.c2 - on i41.f1 = ss1.c1, - lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 -where ss1.c2 = 0; - f1 | q1 | q2 | c1 | c2 | c3 -----+----+----+----+----+---- -(0 rows) - --- --- test successful handling of full join underneath left join (bug #14105) --- ---Testcase 227: -explain (costs off) -select * from - (select 1 as id) as xx - left join - (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) - on (xx.id = coalesce(yy.id)); - QUERY PLAN ---------------------------------------- - Nested Loop Left Join - -> Result - -> Hash Full Join - Hash Cond: (a1.unique1 = (1)) - Filter: (1 = COALESCE((1))) - -> Foreign Scan on tenk1 a1 - -> Hash - -> Result -(8 rows) - ---Testcase 228: -select * from - (select 1 as id) as xx - left join - (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) - on (xx.id = coalesce(yy.id)); - id | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | id -----+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---- - 1 | 1 | 2838 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | BAAAAA | EFEAAA | OOOOxx | 1 -(1 row) - --- --- test ability to push constants through outer join clauses --- ---Testcase 229: -explain (costs off) - select * from int4_tbl a left join tenk1 b on f1 = unique2 where f1 = 0; - QUERY PLAN -------------------------------------- - Hash Left Join - Hash Cond: (a.f1 = b.unique2) - -> Foreign Scan on int4_tbl a - -> Hash - -> Foreign Scan on tenk1 b -(5 rows) - ---Testcase 230: -explain (costs off) - select * from tenk1 a full join tenk1 b using(unique2) where unique2 = 42; - QUERY PLAN ---------------------------------------- - Merge Full Join - Merge Cond: (a.unique2 = b.unique2) - -> Sort - Sort Key: a.unique2 - -> Foreign Scan on tenk1 a - -> Sort - Sort Key: b.unique2 - -> Foreign Scan on tenk1 b -(8 rows) - --- --- test that quals attached to an outer join have correct semantics, --- specifically that they don't re-use expressions computed below the join; --- we force a mergejoin so that coalesce(b.q1, 1) appears as a join input --- -set enable_hashjoin to off; -set enable_nestloop to off; ---Testcase 231: -explain (verbose, costs off) - select a.q2, b.q1 - from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) - where coalesce(b.q1, 1) > 0; - QUERY PLAN --------------------------------------------------------------- - Merge Left Join - Output: a.q2, b.q1 - Merge Cond: (a.q2 = (COALESCE(b.q1, '1'::bigint))) - Filter: (COALESCE(b.q1, '1'::bigint) > 0) - -> Sort - Output: a.q2 - Sort Key: a.q2 - -> Foreign Scan on public.int8_tbl a - Output: a.q2 - SQLite query: SELECT `q2` FROM main."int8_tbl" - -> Sort - Output: b.q1, (COALESCE(b.q1, '1'::bigint)) - Sort Key: (COALESCE(b.q1, '1'::bigint)) - -> Foreign Scan on public.int8_tbl b - Output: b.q1, COALESCE(b.q1, '1'::bigint) - SQLite query: SELECT `q1` FROM main."int8_tbl" -(16 rows) - ---Testcase 232: -select a.q2, b.q1 - from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) - where coalesce(b.q1, 1) > 0; - q2 | q1 --------------------+------------------ - -4567890123456789 | - 123 | 123 - 123 | 123 - 456 | - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(10 rows) - -reset enable_hashjoin; -reset enable_nestloop; --- --- test join removal --- -begin; ---Testcase 444: -CREATE FOREIGN TABLE a3 (id int OPTIONS (key 'true'), b_id int) SERVER sqlite_svr; ---Testcase 445: -CREATE FOREIGN TABLE b3 (id int OPTIONS (key 'true'), c_id int) SERVER sqlite_svr; ---Testcase 446: -CREATE FOREIGN TABLE c3 (id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 447: -CREATE FOREIGN TABLE d3 (a int, b int) SERVER sqlite_svr; ---Testcase 233: -INSERT INTO a3 VALUES (0, 0), (1, NULL); ---Testcase 234: -INSERT INTO b3 VALUES (0, 0), (1, NULL); ---Testcase 235: -INSERT INTO c3 VALUES (0), (1); ---Testcase 236: -INSERT INTO d3 VALUES (1,3), (2,2), (3,1); --- all three cases should be optimizable into a3 simple seqscan ---Testcase 237: -explain (costs off) SELECT a3.* FROM a3 LEFT JOIN b3 ON a3.b_id = b3.id; - QUERY PLAN ---------------------------------- - Merge Left Join - Merge Cond: (a3.b_id = b3.id) - -> Sort - Sort Key: a3.b_id - -> Foreign Scan on a3 - -> Sort - Sort Key: b3.id - -> Foreign Scan on b3 -(8 rows) - ---Testcase 238: -explain (costs off) SELECT b3.* FROM b3 LEFT JOIN c3 ON b3.c_id = c3.id; - QUERY PLAN ---------------------------------- - Merge Left Join - Merge Cond: (b3.c_id = c3.id) - -> Sort - Sort Key: b3.c_id - -> Foreign Scan on b3 - -> Sort - Sort Key: c3.id - -> Foreign Scan on c3 -(8 rows) - ---Testcase 239: -explain (costs off) - SELECT a3.* FROM a3 LEFT JOIN (b3 left join c3 on b3.c_id = c3.id) - ON (a3.b_id = b3.id); - QUERY PLAN ---------------------------------------------- - Merge Right Join - Merge Cond: (c3.id = b3.c_id) - -> Sort - Sort Key: c3.id - -> Foreign Scan on c3 - -> Sort - Sort Key: b3.c_id - -> Merge Left Join - Merge Cond: (a3.b_id = b3.id) - -> Sort - Sort Key: a3.b_id - -> Foreign Scan on a3 - -> Sort - Sort Key: b3.id - -> Foreign Scan on b3 -(15 rows) - --- check optimization of outer join within another special join ---Testcase 240: -explain (costs off) -select id from a3 where id in ( - select b3.id from b3 left join c3 on b3.id = c3.id -); - QUERY PLAN --------------------------------------------------- - Hash Join - Hash Cond: (a3.id = b3.id) - -> Foreign Scan on a3 - -> Hash - -> HashAggregate - Group Key: b3.id - -> Merge Left Join - Merge Cond: (b3.id = c3.id) - -> Sort - Sort Key: b3.id - -> Foreign Scan on b3 - -> Sort - Sort Key: c3.id - -> Foreign Scan on c3 -(14 rows) - --- check that join removal works for a left join when joining a subquery --- that is guaranteed to be unique by its GROUP BY clause ---Testcase 241: -explain (costs off) -select d3.* from d3 left join (select * from b3 group by b3.id, b3.c_id) s - on d3.a = s.id and d3.b = s.c_id; - QUERY PLAN --------------------- - Foreign Scan on d3 -(1 row) - --- similarly, but keying off a DISTINCT clause ---Testcase 242: -explain (costs off) -select d3.* from d3 left join (select distinct * from b3) s - on d3.a = s.id and d3.b = s.c_id; - QUERY PLAN --------------------- - Foreign Scan on d3 -(1 row) - --- join removal is not possible when the GROUP BY contains a column that is --- not in the join condition. (Note: as of 9.6, we notice that b3.id is a --- primary key and so drop b3.c_id from the GROUP BY of the resulting plan; --- but this happens too late for join removal in the outer plan level.) ---Testcase 243: -explain (costs off) -select d3.* from d3 left join (select * from b3 group by b3.id, b3.c_id) s - on d3.a = s.id; - QUERY PLAN --------------------------------- - Hash Left Join - Hash Cond: (d3.a = s.id) - -> Foreign Scan on d3 - -> Hash - -> Subquery Scan on s - -> Foreign Scan -(6 rows) - --- similarly, but keying off a DISTINCT clause ---Testcase 244: -explain (costs off) -select d3.* from d3 left join (select distinct * from b3) s - on d3.a = s.id; - QUERY PLAN --------------------------------------------- - Hash Left Join - Hash Cond: (d3.a = s.id) - -> Foreign Scan on d3 - -> Hash - -> Subquery Scan on s - -> Unique - -> Foreign Scan on b3 -(7 rows) - --- check join removal works when uniqueness of the join condition is enforced --- by a UNION ---Testcase 245: -explain (costs off) -select d3.* from d3 left join (select id from a3 union select id from b3) s - on d3.a = s.id; - QUERY PLAN --------------------- - Foreign Scan on d3 -(1 row) - --- check join removal with a cross-type comparison operator ---Testcase 246: -explain (costs off) -select i8.* from int8_tbl i8 left join (select f1 from int4_tbl group by f1) i4 - on i8.q1 = i4.f1; - QUERY PLAN ------------------------------ - Foreign Scan on int8_tbl i8 -(1 row) - --- check join removal with lateral references ---Testcase 247: -explain (costs off) -select 1 from (select a3.id FROM a3 left join b3 on a3.b_id = b3.id) q, - lateral generate_series(1, q.id) gs(i) where q.id = gs.i; - QUERY PLAN -------------------------------------------------------- - Merge Right Join - Merge Cond: (b3.id = a3.b_id) - -> Sort - Sort Key: b3.id - -> Foreign Scan on b3 - -> Sort - Sort Key: a3.b_id - -> Nested Loop - -> Foreign Scan on a3 - -> Function Scan on generate_series gs - Filter: (a3.id = i) -(11 rows) - -rollback; ---Testcase 448: -create foreign table parent (k int options (key 'true'), pd int) server sqlite_svr; ---Testcase 449: -create foreign table child (k int options (key 'true'), cd int) server sqlite_svr; ---Testcase 248: -insert into parent values (1, 10), (2, 20), (3, 30); ---Testcase 249: -insert into child values (1, 100), (4, 400); --- this case is optimizable ---Testcase 250: -select p.* from parent p left join child c on (p.k = c.k); - k | pd ----+---- - 1 | 10 - 2 | 20 - 3 | 30 -(3 rows) - ---Testcase 251: -explain (costs off) - select p.* from parent p left join child c on (p.k = c.k); - QUERY PLAN --------------------------------------- - Merge Left Join - Merge Cond: (p.k = c.k) - -> Sort - Sort Key: p.k - -> Foreign Scan on parent p - -> Sort - Sort Key: c.k - -> Foreign Scan on child c -(8 rows) - --- this case is not ---Testcase 252: -select p.*, linked from parent p - left join (select c.*, true as linked from child c) as ss - on (p.k = ss.k); - k | pd | linked ----+----+-------- - 1 | 10 | t - 2 | 20 | - 3 | 30 | -(3 rows) - ---Testcase 253: -explain (costs off) - select p.*, linked from parent p - left join (select c.*, true as linked from child c) as ss - on (p.k = ss.k); - QUERY PLAN --------------------------------------- - Merge Left Join - Merge Cond: (p.k = c.k) - -> Sort - Sort Key: p.k - -> Foreign Scan on parent p - -> Sort - Sort Key: c.k - -> Foreign Scan on child c -(8 rows) - --- check for a 9.0rc1 bug: join removal breaks pseudoconstant qual handling ---Testcase 254: -select p.* from - parent p left join child c on (p.k = c.k) - where p.k = 1 and p.k = 2; - k | pd ----+---- -(0 rows) - ---Testcase 255: -explain (costs off) -select p.* from - parent p left join child c on (p.k = c.k) - where p.k = 1 and p.k = 2; - QUERY PLAN --------------------------- - Result - One-Time Filter: false -(2 rows) - ---Testcase 256: -select p.* from - (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k - where p.k = 1 and p.k = 2; - k | pd ----+---- -(0 rows) - ---Testcase 257: -explain (costs off) -select p.* from - (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k - where p.k = 1 and p.k = 2; - QUERY PLAN --------------------------- - Result - One-Time Filter: false -(2 rows) - --- bug 5255: this is not optimizable by join removal -begin; ---Testcase 450: -CREATE FOREIGN TABLE a4 (id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 451: -CREATE FOREIGN TABLE b4 (id int OPTIONS (key 'true'), a_id int) SERVER sqlite_svr; ---Testcase 258: -INSERT INTO a4 VALUES (0), (1); ---Testcase 259: -INSERT INTO b4 VALUES (0, 0), (1, NULL); ---Testcase 260: -SELECT * FROM b4 LEFT JOIN a4 ON (b4.a_id = a4.id) WHERE (a4.id IS NULL OR a4.id > 0); - id | a_id | id -----+------+---- - 1 | | -(1 row) - ---Testcase 261: -SELECT b4.* FROM b4 LEFT JOIN a4 ON (b4.a_id = a4.id) WHERE (a4.id IS NULL OR a4.id > 0); - id | a_id -----+------ - 1 | -(1 row) - -rollback; --- another join removal bug: this is not optimizable, either -begin; ---Testcase 452: -create foreign table innertab (id int8 options (key 'true'), dat1 int8) server sqlite_svr; ---Testcase 262: -insert into innertab values(123, 42); ---Testcase 263: -SELECT * FROM - (SELECT 1 AS x) ss1 - LEFT JOIN - (SELECT q1, q2, COALESCE(dat1, q1) AS y - FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss2 - ON true; - x | q1 | q2 | y ----+------------------+-------------------+------------------ - 1 | 4567890123456789 | -4567890123456789 | 4567890123456789 - 1 | 4567890123456789 | 123 | 42 - 1 | 123 | 456 | 123 - 1 | 123 | 4567890123456789 | 123 - 1 | 4567890123456789 | 4567890123456789 | 4567890123456789 -(5 rows) - -rollback; --- another join removal bug: we must clean up correctly when removing a PHV -begin; ---Testcase 453: -create foreign table uniquetbl (f1 text) server sqlite_svr; ---Testcase 264: -explain (costs off) -select t1.* from - uniquetbl as t1 - left join (select *, '***'::text as d1 from uniquetbl) t2 - on t1.f1 = t2.f1 - left join uniquetbl t3 - on t2.d1 = t3.f1; - QUERY PLAN ---------------------------------------------------- - Merge Right Join - Merge Cond: (t3.f1 = ('***'::text)) - -> Sort - Sort Key: t3.f1 - -> Foreign Scan on uniquetbl t3 - -> Sort - Sort Key: ('***'::text) - -> Hash Left Join - Hash Cond: (t1.f1 = uniquetbl.f1) - -> Foreign Scan on uniquetbl t1 - -> Hash - -> Foreign Scan on uniquetbl -(12 rows) - ---Testcase 265: -explain (costs off) -select t0.* -from - text_tbl t0 - left join - (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, - t1.stringu2 - from tenk1 t1 - join int4_tbl i4 ON i4.f1 = t1.unique2 - left join uniquetbl u1 ON u1.f1 = t1.string4) ss - on t0.f1 = ss.case1 -where ss.stringu2 !~* ss.case1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - Merge Join - Merge Cond: (i4.f1 = t1.unique2) - -> Sort - Sort Key: i4.f1 - -> Foreign Scan on int4_tbl i4 - -> Sort - Sort Key: t1.unique2 - -> Merge Right Join - Merge Cond: (u1.f1 = t1.string4) - -> Sort - Sort Key: u1.f1 COLLATE "C" - -> Foreign Scan on uniquetbl u1 - -> Sort - Sort Key: t1.string4 - -> Merge Join - Merge Cond: ((CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) = t0.f1) - -> Sort - Sort Key: (CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) - -> Foreign Scan on tenk1 t1 - Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) - -> Sort - Sort Key: t0.f1 - -> Foreign Scan on text_tbl t0 -(23 rows) - ---Testcase 266: -select t0.* -from - text_tbl t0 - left join - (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, - t1.stringu2 - from tenk1 t1 - join int4_tbl i4 ON i4.f1 = t1.unique2 - left join uniquetbl u1 ON u1.f1 = t1.string4) ss - on t0.f1 = ss.case1 -where ss.stringu2 !~* ss.case1; - f1 ------- - doh! -(1 row) - -rollback; --- bug #8444: we've historically allowed duplicate aliases within aliased JOINs ---Testcase 267: -select * from - int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error -ERROR: column reference "f1" is ambiguous -LINE 2: ..._tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; - ^ ---Testcase 268: -select * from - int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; -- error -ERROR: invalid reference to FROM-clause entry for table "y" -LINE 2: ...bl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; - ^ -HINT: There is an entry for table "y", but it cannot be referenced from this part of the query. ---Testcase 269: -select * from - int8_tbl x join (int4_tbl x cross join int4_tbl y(ff)) j on q1 = f1; -- ok - q1 | q2 | f1 | ff -----+----+----+---- -(0 rows) - --- --- Test hints given on incorrect column references are useful --- ---Testcase 270: -select t1.uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion -ERROR: column t1.uunique1 does not exist -LINE 1: select t1.uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t1.unique1". ---Testcase 271: -select t2.uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion -ERROR: column t2.uunique1 does not exist -LINE 1: select t2.uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t2.unique1". ---Testcase 272: -select uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once -ERROR: column "uunique1" does not exist -LINE 1: select uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1". --- --- Take care to reference the correct RTE --- ---Testcase 454: -select atts.relid::regclass, s.* from pg_stats s join - pg_attribute a on s.attname = a.attname and s.tablename = - a.attrelid::regclass::text join (select unnest(indkey) attnum, - indexrelid from pg_index i) atts on atts.attnum = a.attnum where - schemaname != 'pg_catalog'; -ERROR: column atts.relid does not exist -LINE 1: select atts.relid::regclass, s.* from pg_stats s join - ^ --- --- Test LATERAL --- ---Testcase 273: -select unique2, x.* -from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; - unique2 | f1 ----------+---- - 9998 | 0 -(1 row) - ---Testcase 274: -explain (costs off) - select unique2, x.* - from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; - QUERY PLAN ----------------------------------------- - Merge Join - Merge Cond: (a.unique1 = b.f1) - -> Sort - Sort Key: a.unique1 - -> Foreign Scan on tenk1 a - -> Sort - Sort Key: b.f1 - -> Foreign Scan on int4_tbl b -(8 rows) - ---Testcase 275: -select unique2, x.* -from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; - unique2 | f1 ----------+---- - 9998 | 0 -(1 row) - ---Testcase 276: -explain (costs off) - select unique2, x.* - from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; - QUERY PLAN ----------------------------------------- - Merge Join - Merge Cond: (tenk1.unique1 = x.f1) - -> Sort - Sort Key: tenk1.unique1 - -> Foreign Scan on tenk1 - -> Sort - Sort Key: x.f1 - -> Foreign Scan on int4_tbl x -(8 rows) - ---Testcase 277: -explain (costs off) - select unique2, x.* - from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss; - QUERY PLAN ----------------------------------------- - Merge Join - Merge Cond: (tenk1.unique1 = x.f1) - -> Sort - Sort Key: tenk1.unique1 - -> Foreign Scan on tenk1 - -> Sort - Sort Key: x.f1 - -> Foreign Scan on int4_tbl x -(8 rows) - ---Testcase 278: -select unique2, x.* -from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; - unique2 | f1 ----------+------------- - | -2147483647 - | -123456 - 9998 | 0 - | 123456 - | 2147483647 -(5 rows) - ---Testcase 279: -explain (costs off) - select unique2, x.* - from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; - QUERY PLAN ----------------------------------------- - Merge Right Join - Merge Cond: (tenk1.unique1 = x.f1) - -> Sort - Sort Key: tenk1.unique1 - -> Foreign Scan on tenk1 - -> Sort - Sort Key: x.f1 - -> Foreign Scan on int4_tbl x -(8 rows) - --- check scoping of lateral versus parent references --- the first of these should return int8_tbl.q2, the second int8_tbl.q1 ---Testcase 280: -select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl; - q1 | q2 | r -------------------+-------------------+------------------- - 123 | 456 | 456 - 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | -4567890123456789 -(5 rows) - ---Testcase 281: -select *, (select r from (select q1 as q2) x, lateral (select q2 as r) y) from int8_tbl; - q1 | q2 | r -------------------+-------------------+------------------ - 123 | 456 | 123 - 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 -(5 rows) - --- lateral with function in FROM ---Testcase 282: -select count(*) from tenk1 a, lateral generate_series(1,two) g; - count -------- - 5000 -(1 row) - ---Testcase 283: -explain (costs off) - select count(*) from tenk1 a, lateral generate_series(1,two) g; - QUERY PLAN ------------------------------------------------- - Aggregate - -> Nested Loop - -> Foreign Scan on tenk1 a - -> Function Scan on generate_series g -(4 rows) - ---Testcase 284: -explain (costs off) - select count(*) from tenk1 a cross join lateral generate_series(1,two) g; - QUERY PLAN ------------------------------------------------- - Aggregate - -> Nested Loop - -> Foreign Scan on tenk1 a - -> Function Scan on generate_series g -(4 rows) - --- don't need the explicit LATERAL keyword for functions ---Testcase 285: -explain (costs off) - select count(*) from tenk1 a, generate_series(1,two) g; - QUERY PLAN ------------------------------------------------- - Aggregate - -> Nested Loop - -> Foreign Scan on tenk1 a - -> Function Scan on generate_series g -(4 rows) - --- lateral with UNION ALL subselect ---Testcase 286: -explain (costs off) - select * from generate_series(100,200) g, - lateral (select * from int8_tbl a where g = q1 union all - select * from int8_tbl b where g = q2) ss; - QUERY PLAN ------------------------------------------- - Nested Loop - -> Function Scan on generate_series g - -> Append - -> Foreign Scan on int8_tbl a - -> Foreign Scan on int8_tbl b -(5 rows) - ---Testcase 287: -select * from generate_series(100,200) g, - lateral (select * from int8_tbl a where g = q1 union all - select * from int8_tbl b where g = q2) ss; - g | q1 | q2 ------+------------------+------------------ - 123 | 123 | 456 - 123 | 123 | 4567890123456789 - 123 | 4567890123456789 | 123 -(3 rows) - --- lateral with VALUES ---Testcase 288: -explain (costs off) - select count(*) from tenk1 a, - tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 289: -select count(*) from tenk1 a, - tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; - count -------- - 10000 -(1 row) - --- lateral with VALUES, no flattening possible ---Testcase 290: -explain (costs off) - select count(*) from tenk1 a, - tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; - QUERY PLAN ------------------------------------------------------- - Aggregate - -> Merge Join - Merge Cond: (b.unique2 = "*VALUES*".column1) - -> Sort - Sort Key: b.unique2 - -> Foreign Scan on tenk1 b - -> Sort - Sort Key: "*VALUES*".column1 - -> Nested Loop - -> Foreign Scan on tenk1 a - -> Values Scan on "*VALUES*" -(11 rows) - ---Testcase 291: -select count(*) from tenk1 a, - tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; - count -------- - 10000 -(1 row) - --- lateral injecting a strange outer join condition ---Testcase 292: -explain (costs off) - select * from int8_tbl a, - int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) - on x.q2 = ss.z - order by a.q1, a.q2, x.q1, x.q2, ss.z; - QUERY PLAN ----------------------------------------------------- - Sort - Sort Key: a.q1, a.q2, x.q1, x.q2, (a.q1) - -> Nested Loop - -> Foreign Scan on int8_tbl a - -> Merge Left Join - Merge Cond: (x.q2 = (a.q1)) - -> Sort - Sort Key: x.q2 - -> Foreign Scan on int8_tbl x - -> Sort - Sort Key: (a.q1) - -> Foreign Scan on int4_tbl y -(12 rows) - ---Testcase 293: -select * from int8_tbl a, - int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) - on x.q2 = ss.z - order by a.q1, a.q2, x.q1, x.q2, ss.z; - q1 | q2 | q1 | q2 | z -------------------+-------------------+------------------+-------------------+------------------ - 123 | 456 | 123 | 456 | - 123 | 456 | 123 | 4567890123456789 | - 123 | 456 | 4567890123456789 | -4567890123456789 | - 123 | 456 | 4567890123456789 | 123 | 123 - 123 | 456 | 4567890123456789 | 123 | 123 - 123 | 456 | 4567890123456789 | 123 | 123 - 123 | 456 | 4567890123456789 | 123 | 123 - 123 | 456 | 4567890123456789 | 123 | 123 - 123 | 456 | 4567890123456789 | 4567890123456789 | - 123 | 4567890123456789 | 123 | 456 | - 123 | 4567890123456789 | 123 | 4567890123456789 | - 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | - 4567890123456789 | -4567890123456789 | 123 | 456 | - 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 | - 4567890123456789 | -4567890123456789 | 4567890123456789 | 123 | - 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 456 | - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 4567890123456789 | -4567890123456789 | - 4567890123456789 | 123 | 4567890123456789 | 123 | - 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 123 | 456 | - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 -(57 rows) - --- lateral reference to a join alias variable ---Testcase 294: -select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, - lateral (select x) ss2(y); - x | f1 | y ----+----+--- - 0 | 0 | 0 -(1 row) - ---Testcase 295: -select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, - lateral (values(x)) ss2(y); - x | f1 | y --------------+-------------+------------- - -2147483647 | -2147483647 | -2147483647 - -123456 | -123456 | -123456 - 0 | 0 | 0 - 123456 | 123456 | 123456 - 2147483647 | 2147483647 | 2147483647 -(5 rows) - ---Testcase 296: -select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j, - lateral (select x) ss2(y); - x | f1 | y ----+----+--- - 0 | 0 | 0 -(1 row) - --- lateral references requiring pullup ---Testcase 297: -select * from (values(1)) x(lb), - lateral generate_series(lb,4) x4; - lb | x4 -----+---- - 1 | 1 - 1 | 2 - 1 | 3 - 1 | 4 -(4 rows) - ---Testcase 298: -select * from (select f1/1000000000 from int4_tbl) x(lb), - lateral generate_series(lb,4) x4; - lb | x4 -----+---- - 0 | 0 - 0 | 1 - 0 | 2 - 0 | 3 - 0 | 4 - 0 | 0 - 0 | 1 - 0 | 2 - 0 | 3 - 0 | 4 - 0 | 0 - 0 | 1 - 0 | 2 - 0 | 3 - 0 | 4 - 2 | 2 - 2 | 3 - 2 | 4 - -2 | -2 - -2 | -1 - -2 | 0 - -2 | 1 - -2 | 2 - -2 | 3 - -2 | 4 -(25 rows) - ---Testcase 299: -select * from (values(1)) x(lb), - lateral (values(lb)) y(lbcopy); - lb | lbcopy -----+-------- - 1 | 1 -(1 row) - ---Testcase 300: -select * from (values(1)) x(lb), - lateral (select lb from int4_tbl) y(lbcopy); - lb | lbcopy -----+-------- - 1 | 1 - 1 | 1 - 1 | 1 - 1 | 1 - 1 | 1 -(5 rows) - ---Testcase 301: -select * from - int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, - lateral (values(x.q1,y.q1,y.q2)) v(xq1,yq1,yq2); - q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 -------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- - 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | - 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 123 | 456 | | | 123 | | - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 -(10 rows) - ---Testcase 302: -select * from - int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, - lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); - q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 -------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- - 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | - 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 - 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 123 | 456 | | | 123 | | - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 -(10 rows) - ---Testcase 303: -select x.* from - int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, - lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); - q1 | q2 -------------------+------------------- - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 123 - 123 | 456 - 123 | 4567890123456789 - 123 | 4567890123456789 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 -(10 rows) - ---Testcase 304: -select v.* from - (int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1) - left join int4_tbl z on z.f1 = x.q2, - lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); - vx | vy --------------------+------------------- - 4567890123456789 | - -4567890123456789 | - 4567890123456789 | 123 - 123 | 456 - 4567890123456789 | 123 - 123 | 4567890123456789 - 123 | - 456 | - 123 | 4567890123456789 - 4567890123456789 | 123 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(20 rows) - ---Testcase 305: -select v.* from - (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) - left join int4_tbl z on z.f1 = x.q2, - lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); - vx | vy --------------------+------------------- - 4567890123456789 | - -4567890123456789 | - 4567890123456789 | 123 - 123 | 456 - 4567890123456789 | 123 - 123 | 4567890123456789 - 123 | - 456 | - 123 | 4567890123456789 - 4567890123456789 | 123 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(20 rows) - ---Testcase 307: -select v.* from - (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) - left join int4_tbl z on z.f1 = x.q2, - lateral (select x.q1,y.q1 from onerow union all select x.q2,y.q2 from onerow) v(vx,vy); - vx | vy --------------------+------------------- - 4567890123456789 | - -4567890123456789 | - 4567890123456789 | 123 - 123 | 456 - 4567890123456789 | 123 - 123 | 4567890123456789 - 123 | - 456 | - 123 | 4567890123456789 - 4567890123456789 | 123 - 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(20 rows) - --- Error when using sub-query with multi instances of table, this issue is fixed on PostgreSQL-12 ---Testcase 455: -explain (verbose, costs off) -select * from - int8_tbl a left join - lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; - QUERY PLAN ---------------------------------------------------------------------------------- - Nested Loop Left Join - Output: a.q1, a.q2, b.q1, b.q2, (a.q2) - -> Foreign Scan on public.int8_tbl a - Output: a.q1, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Foreign Scan on public.int8_tbl b - Output: b.q1, b.q2, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((? = `q1`)) -(8 rows) - ---Testcase 456: -select * from - int8_tbl a left join - lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; - q1 | q2 | q1 | q2 | x -------------------+-------------------+------------------+-------------------+------------------ - 123 | 456 | | | - 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 456 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | | | -(10 rows) - ---Testcase 457: -explain (verbose, costs off) -select * from - int8_tbl a left join - lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; - QUERY PLAN ---------------------------------------------------------------------------------- - Nested Loop Left Join - Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, '42'::bigint)) - -> Foreign Scan on public.int8_tbl a - Output: a.q1, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Foreign Scan on public.int8_tbl b - Output: b.q1, b.q2, COALESCE(a.q2, '42'::bigint) - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((? = `q1`)) -(8 rows) - ---Testcase 458: -select * from - int8_tbl a left join - lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; - q1 | q2 | q1 | q2 | x -------------------+-------------------+------------------+-------------------+------------------ - 123 | 456 | | | - 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 | 456 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | | | -(10 rows) - --- lateral can result in join conditions appearing below their --- real semantic level ---Testcase 308: -explain (verbose, costs off) -select * from int4_tbl i left join - lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; - QUERY PLAN --------------------------------------------------------------- - Merge Left Join - Output: i.f1, j.f1 - Merge Cond: (i.f1 = j.f1) - -> Sort - Output: i.f1 - Sort Key: i.f1 - -> Foreign Scan on public.int4_tbl i - Output: i.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Sort - Output: j.f1 - Sort Key: j.f1 - -> Foreign Scan on public.int2_tbl j - Output: j.f1 - SQLite query: SELECT `f1` FROM main."int2_tbl" -(15 rows) - ---Testcase 309: -select * from int4_tbl i left join - lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; - f1 | f1 --------------+---- - -2147483647 | - -123456 | - 0 | 0 - 123456 | - 2147483647 | -(5 rows) - ---Testcase 310: -explain (verbose, costs off) -select * from int4_tbl i left join - lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; - QUERY PLAN ---------------------------------------------------------------------------- - Nested Loop Left Join - Output: i.f1, (COALESCE(i.*)) - -> Foreign Scan on public.int4_tbl i - Output: i.f1, i.* - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Foreign Scan on public.int2_tbl j - Output: j.f1, COALESCE(i.*) - SQLite query: SELECT `f1` FROM main."int2_tbl" WHERE ((? = `f1`)) -(8 rows) - ---Testcase 311: -select * from int4_tbl i left join - lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; - f1 | coalesce --------------+---------- - 0 | (0) - 123456 | - -123456 | - 2147483647 | - -2147483647 | -(5 rows) - ---Testcase 312: -explain (verbose, costs off) -select * from int4_tbl a, - lateral ( - select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) - ) ss; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: a.f1, b.f1, c.q1, c.q2 - -> Foreign Scan on public.int4_tbl a - Output: a.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Foreign Scan - Output: b.f1, c.q1, c.q2 - SQLite query: SELECT r1.`f1`, r2.`q1`, r2.`q2` FROM (main."int4_tbl" r1 LEFT JOIN main."int8_tbl" r2 ON (((r1.`f1` = r2.`q1`)) AND ((? = r2.`q2`)))) -(8 rows) - ---Testcase 313: -select * from int4_tbl a, - lateral ( - select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) - ) ss; - f1 | f1 | q1 | q2 --------------+-------------+----+---- - 0 | 0 | | - 0 | 123456 | | - 0 | -123456 | | - 0 | 2147483647 | | - 0 | -2147483647 | | - 123456 | 0 | | - 123456 | 123456 | | - 123456 | -123456 | | - 123456 | 2147483647 | | - 123456 | -2147483647 | | - -123456 | 0 | | - -123456 | 123456 | | - -123456 | -123456 | | - -123456 | 2147483647 | | - -123456 | -2147483647 | | - 2147483647 | 0 | | - 2147483647 | 123456 | | - 2147483647 | -123456 | | - 2147483647 | 2147483647 | | - 2147483647 | -2147483647 | | - -2147483647 | 0 | | - -2147483647 | 123456 | | - -2147483647 | -123456 | | - -2147483647 | 2147483647 | | - -2147483647 | -2147483647 | | -(25 rows) - --- lateral reference in a PlaceHolderVar evaluated at join level --- Error when using sub-query with multi instances of table, this issue is fixed on PostgreSQL-12 ---Testcase 459: -explain (verbose, costs off) -select * from - int8_tbl a left join lateral - (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from - int8_tbl b cross join int8_tbl c) ss - on a.q2 = ss.bq1; - QUERY PLAN ---------------------------------------------------------------------------------- - Nested Loop Left Join - Output: a.q1, a.q2, b.q1, c.q1, (LEAST(a.q1, b.q1, c.q1)) - -> Foreign Scan on public.int8_tbl a - Output: a.q1, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Nested Loop - Output: b.q1, c.q1, LEAST(a.q1, b.q1, c.q1) - -> Foreign Scan on public.int8_tbl b - Output: b.q1, b.q2 - SQLite query: SELECT `q1` FROM main."int8_tbl" WHERE ((? = `q1`)) - -> Materialize - Output: c.q1 - -> Foreign Scan on public.int8_tbl c - Output: c.q1 - SQLite query: SELECT `q1` FROM main."int8_tbl" -(15 rows) - ---Testcase 460: -select * from - int8_tbl a left join lateral - (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from - int8_tbl b cross join int8_tbl c) ss - on a.q2 = ss.bq1; - q1 | q2 | bq1 | cq1 | least -------------------+-------------------+------------------+------------------+------------------ - 123 | 456 | | | - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 123 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 123 | 123 - 4567890123456789 | 123 | 123 | 123 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 123 | 123 - 4567890123456789 | 123 | 123 | 123 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 123 | 123 | 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | | | -(42 rows) - --- case requiring nested PlaceHolderVars ---Testcase 461: -explain (verbose, costs off) -select * from - int8_tbl c left join ( - int8_tbl a left join (select q1, coalesce(q2,42) as x from int8_tbl b) ss1 - on a.q2 = ss1.q1 - cross join - lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 - ) on c.q2 = ss2.q1, - lateral (select ss2.y offset 0) ss3; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)), ((COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))) - -> Hash Right Join - Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) - Hash Cond: (d.q1 = c.q2) - -> Nested Loop - Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) - -> Merge Left Join - Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)) - Merge Cond: (a.q2 = b.q1) - -> Sort - Output: a.q1, a.q2 - Sort Key: a.q2 - -> Foreign Scan on public.int8_tbl a - Output: a.q1, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Sort - Output: b.q1, (COALESCE(b.q2, '42'::bigint)) - Sort Key: b.q1 - -> Foreign Scan on public.int8_tbl b - Output: b.q1, COALESCE(b.q2, '42'::bigint) - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Foreign Scan on public.int8_tbl d - Output: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2) - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Hash - Output: c.q1, c.q2 - -> Foreign Scan on public.int8_tbl c - Output: c.q1, c.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Result - Output: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) -(32 rows) - --- case that breaks the old ph_may_need optimization ---Testcase 462: -explain (verbose, costs off) -select c.*,a.*,ss1.q1,ss2.q1,ss3.* from - int8_tbl c left join ( - int8_tbl a left join - (select q1, coalesce(q2,f1) as x from int8_tbl b, int4_tbl b2 - where q1 < f1) ss1 - on a.q2 = ss1.q1 - cross join - lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 - ) on c.q2 = ss2.q1, - lateral (select * from int4_tbl i where ss2.y > f1) ss3; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, i.f1 - Join Filter: ((COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) > i.f1) - -> Hash Right Join - Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) - Hash Cond: (d.q1 = c.q2) - -> Nested Loop - Output: a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) - -> Merge Left Join - Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) - Merge Cond: (a.q2 = b.q1) - -> Sort - Output: a.q1, a.q2 - Sort Key: a.q2 - -> Foreign Scan on public.int8_tbl a - Output: a.q1, a.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Materialize - Output: b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) - -> Sort - Output: b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) - Sort Key: b.q1 - -> Foreign Scan - Output: b.q1, COALESCE(b.q2, (b2.f1)::bigint) - SQLite query: SELECT r9.`q1`, r9.`q2`, r10.`f1` FROM (main."int8_tbl" r9 INNER JOIN main."int4_tbl" r10 ON (((r9.`q1` < r10.`f1`)))) - -> Foreign Scan on public.int8_tbl d - Output: d.q1, COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2) - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Hash - Output: c.q1, c.q2 - -> Foreign Scan on public.int8_tbl c - Output: c.q1, c.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Materialize - Output: i.f1 - -> Foreign Scan on public.int4_tbl i - Output: i.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" -(38 rows) - --- check processing of postponed quals (bug #9041) ---Testcase 463: -delete from sub_tbl; ---Testcase 464: -insert into sub_tbl values (1, 2, 3, 4, 5); ---Testcase 465: -explain (verbose, costs off) -select * from - (select key1 as x from sub_tbl offset 0) x cross join (select key3 as y from sub_tbl offset 0) y - left join lateral ( - select * from (select key5 as z from sub_tbl offset 0) z where z.z = x.x - ) zz on zz.z = y.y; - QUERY PLAN ---------------------------------------------------------------------------------------- - Merge Left Join - Output: sub_tbl.key1, sub_tbl_1.key3, sub_tbl_2.key5 - Merge Cond: ((sub_tbl.key1 = sub_tbl_2.key5) AND (sub_tbl_1.key3 = sub_tbl_2.key5)) - -> Sort - Output: sub_tbl.key1, sub_tbl_1.key3 - Sort Key: sub_tbl.key1, sub_tbl_1.key3 - -> Nested Loop - Output: sub_tbl.key1, sub_tbl_1.key3 - -> Foreign Scan on public.sub_tbl - Output: sub_tbl.key1 - SQLite query: SELECT `key1` FROM main."sub_tbl" - -> Materialize - Output: sub_tbl_1.key3 - -> Foreign Scan on public.sub_tbl sub_tbl_1 - Output: sub_tbl_1.key3 - SQLite query: SELECT `key3` FROM main."sub_tbl" - -> Sort - Output: sub_tbl_2.key5 - Sort Key: sub_tbl_2.key5 - -> Foreign Scan on public.sub_tbl sub_tbl_2 - Output: sub_tbl_2.key5 - SQLite query: SELECT `key5` FROM main."sub_tbl" -(22 rows) - --- check dummy rels with lateral references (bug #15694) ---Testcase 466: -explain (verbose, costs off) -select * from int8_tbl i8 left join lateral - (select *, i8.q2 from int4_tbl where false) ss on true; - QUERY PLAN --------------------------------------------------------------- - Nested Loop Left Join - Output: i8.q1, i8.q2, f1, (i8.q2) - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Result - Output: f1, i8.q2 - One-Time Filter: false -(8 rows) - ---Testcase 467: -explain (verbose, costs off) -select * from int8_tbl i8 left join lateral - (select *, i8.q2 from int4_tbl i1, int4_tbl i2 where false) ss on true; - QUERY PLAN --------------------------------------------------------------- - Nested Loop Left Join - Output: i8.q1, i8.q2, f1, f1, (i8.q2) - -> Foreign Scan on public.int8_tbl i8 - Output: i8.q1, i8.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Result - Output: f1, f1, i8.q2 - One-Time Filter: false -(8 rows) - --- check handling of nested appendrels inside LATERAL ---Testcase 468: -select * from - ((select key3 as v from sub_tbl) union all (select key5 as v from sub_tbl)) as q1 - cross join lateral - ((select * from - ((select key6 as v from sub_tbl) union all (select value1 as v from sub_tbl)) as q3) - union all - (select q1.v) - ) as q2; - v | v ----+--- - 2 | 4 - 2 | 5 - 2 | 2 - 3 | 4 - 3 | 5 - 3 | 3 -(6 rows) - --- check we don't try to do a unique-ified semijoin with LATERAL ---Testcase 314: -explain (verbose, costs off) -select * from - (values (0,9998), (1,1000)) v(id,x), - lateral (select f1 from int4_tbl - where f1 = any (select unique1 from tenk1 - where unique2 = v.x offset 0)) ss; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Nested Loop - Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2 - -> Hash Semi Join - Output: int4_tbl.f1 - Hash Cond: (int4_tbl.f1 = tenk1.unique1) - -> Foreign Scan on public.int4_tbl - Output: int4_tbl.f1 - SQLite query: SELECT `f1` FROM main."int4_tbl" - -> Hash - Output: tenk1.unique1 - -> Foreign Scan on public.tenk1 - Output: tenk1.unique1 - SQLite query: SELECT `unique1` FROM main."tenk1" WHERE ((`unique2` = ?)) -(15 rows) - ---Testcase 315: -select * from - (values (0,9998), (1,1000)) v(id,x), - lateral (select f1 from int4_tbl - where f1 = any (select unique1 from tenk1 - where unique2 = v.x offset 0)) ss; - id | x | f1 -----+------+---- - 0 | 9998 | 0 -(1 row) - --- check proper extParam/allParam handling (this isn't exactly a LATERAL issue, --- but we can make the test case much more compact with LATERAL) ---Testcase 316: -explain (verbose, costs off) -select * from (values (0), (1)) v(id), -lateral (select * from int8_tbl t1, - lateral (select * from - (select * from int8_tbl t2 - where q1 = any (select q2 from int8_tbl t3 - where q2 = (select greatest(t1.q1,t2.q2)) - and (select v.id=0)) offset 0) ss2) ss - where t1.q1 = ss.q2) ss0; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - Nested Loop - Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2 - -> Foreign Scan on public.int8_tbl t1 - Output: t1.q1, t1.q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - -> Nested Loop - Output: "*VALUES*".column1, ss2.q1, ss2.q2 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1 - -> Subquery Scan on ss2 - Output: ss2.q1, ss2.q2 - Filter: (t1.q1 = ss2.q2) - -> Foreign Scan on public.int8_tbl t2 - Output: t2.q1, t2.q2 - Filter: (SubPlan 3) - SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" - SubPlan 3 - -> Result - Output: t3.q2 - One-Time Filter: $4 - InitPlan 1 (returns $2) - -> Result - Output: GREATEST($0, t2.q2) - InitPlan 2 (returns $4) - -> Result - Output: ($3 = 0) - -> Foreign Scan on public.int8_tbl t3 - Output: t3.q1, t3.q2 - SQLite query: SELECT `q2` FROM main."int8_tbl" WHERE ((`q2` = ?)) -(29 rows) - ---Testcase 317: -select * from (values (0), (1)) v(id), -lateral (select * from int8_tbl t1, - lateral (select * from - (select * from int8_tbl t2 - where q1 = any (select q2 from int8_tbl t3 - where q2 = (select greatest(t1.q1,t2.q2)) - and (select v.id=0)) offset 0) ss2) ss - where t1.q1 = ss.q2) ss0; - id | q1 | q2 | q1 | q2 -----+------------------+-------------------+------------------+------------------ - 0 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 - 0 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 - 0 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 -(3 rows) - --- test some error cases where LATERAL should have been used but wasn't ---Testcase 318: -select f1,g from int4_tbl a, (select f1 as g) ss; -ERROR: column "f1" does not exist -LINE 1: select f1,g from int4_tbl a, (select f1 as g) ss; - ^ -HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. ---Testcase 319: -select f1,g from int4_tbl a, (select a.f1 as g) ss; -ERROR: invalid reference to FROM-clause entry for table "a" -LINE 1: select f1,g from int4_tbl a, (select a.f1 as g) ss; - ^ -HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. ---Testcase 320: -select f1,g from int4_tbl a cross join (select f1 as g) ss; -ERROR: column "f1" does not exist -LINE 1: select f1,g from int4_tbl a cross join (select f1 as g) ss; - ^ -HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. ---Testcase 321: -select f1,g from int4_tbl a cross join (select a.f1 as g) ss; -ERROR: invalid reference to FROM-clause entry for table "a" -LINE 1: select f1,g from int4_tbl a cross join (select a.f1 as g) ss... - ^ -HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. --- SQL:2008 says the left table is in scope but illegal to access here ---Testcase 322: -select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true; -ERROR: invalid reference to FROM-clause entry for table "a" -LINE 1: ... int4_tbl a right join lateral generate_series(0, a.f1) g on... - ^ -DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. ---Testcase 323: -select f1,g from int4_tbl a full join lateral generate_series(0, a.f1) g on true; -ERROR: invalid reference to FROM-clause entry for table "a" -LINE 1: ...m int4_tbl a full join lateral generate_series(0, a.f1) g on... - ^ -DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. --- check we complain about ambiguous table references ---Testcase 324: -select * from - int8_tbl x cross join (int4_tbl x cross join lateral (select x.f1) ss); -ERROR: table reference "x" is ambiguous -LINE 2: ...cross join (int4_tbl x cross join lateral (select x.f1) ss); - ^ --- LATERAL can be used to put an aggregate into the FROM clause of its query ---Testcase 325: -select 1 from tenk1 a, lateral (select max(a.unique1) from int4_tbl b) ss; -ERROR: aggregate functions are not allowed in FROM clause of their own query level -LINE 1: select 1 from tenk1 a, lateral (select max(a.unique1) from i... - ^ --- check behavior of LATERAL in UPDATE/DELETE ---Testcase 469: -create temp table xx1 as select f1 as x1, -f1 as x2 from int4_tbl; --- error, can't do this: ---Testcase 326: -update xx1 set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; -ERROR: column "x1" does not exist -LINE 1: ... set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; - ^ -HINT: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. ---Testcase 327: -update xx1 set x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss; -ERROR: invalid reference to FROM-clause entry for table "xx1" -LINE 1: ...t x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss... - ^ -HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. --- can't do it even with LATERAL: ---Testcase 328: -update xx1 set x2 = f1 from lateral (select * from int4_tbl where f1 = x1) ss; -ERROR: invalid reference to FROM-clause entry for table "xx1" -LINE 1: ...= f1 from lateral (select * from int4_tbl where f1 = x1) ss; - ^ -HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. --- we might in future allow something like this, but for now it's an error: ---Testcase 329: -update xx1 set x2 = f1 from xx1, lateral (select * from int4_tbl where f1 = x1) ss; -ERROR: table name "xx1" specified more than once --- also errors: ---Testcase 330: -delete from xx1 using (select * from int4_tbl where f1 = x1) ss; -ERROR: column "x1" does not exist -LINE 1: ...te from xx1 using (select * from int4_tbl where f1 = x1) ss; - ^ -HINT: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. ---Testcase 331: -delete from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss; -ERROR: invalid reference to FROM-clause entry for table "xx1" -LINE 1: ...from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss... - ^ -HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. ---Testcase 332: -delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss; -ERROR: invalid reference to FROM-clause entry for table "xx1" -LINE 1: ...xx1 using lateral (select * from int4_tbl where f1 = x1) ss; - ^ -HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. --- Skip this test, sqlite fdw does not support to create partition table --- test LATERAL reference propagation down a multi-level inheritance hierarchy --- produced for a multi-level partitioned table hierarchy. --- ---create table join_pt1 (a int, b int, c varchar) partition by range(a); ---create table join_pt1p1 partition of join_pt1 for values from (0) to (100) partition by range(b); ---create table join_pt1p2 partition of join_pt1 for values from (100) to (200); ---create table join_pt1p1p1 partition of join_pt1p1 for values from (0) to (100); ---insert into join_pt1 values (1, 1, 'x'), (101, 101, 'y'); ---create table join_ut1 (a int, b int, c varchar); ---insert into join_ut1 values (101, 101, 'y'), (2, 2, 'z'); ---explain (verbose, costs off) ---select t1.b, ss.phv from join_ut1 t1 left join lateral --- (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv --- from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss --- on t1.a = ss.t2a order by t1.a; ---select t1.b, ss.phv from join_ut1 t1 left join lateral --- (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv --- from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss --- on t1.a = ss.t2a order by t1.a; ---drop table join_pt1; ---drop table join_ut1; --- --- test that foreign key join estimation performs sanely for outer joins --- -begin; ---Testcase 470: -create foreign table fkest (a int options (key 'true'), b int options (key 'true'), c int) server sqlite_svr; ---Testcase 471: -create foreign table fkest1 (a int options (key 'true'), b int options (key 'true')) server sqlite_svr; ---Testcase 333: -insert into fkest select x/10, x%10, x from generate_series(1,1000) x; ---Testcase 334: -insert into fkest1 select x/10, x%10 from generate_series(1,1000) x; ---alter table fkest1 --- add constraint fkest1_a_b_fkey foreign key (a,b) references fkest; ---analyze fkest; ---analyze fkest1; ---Testcase 335: -explain (costs off) -select * -from fkest f - left join fkest1 f1 on f.a = f1.a and f.b = f1.b - left join fkest1 f2 on f.a = f2.a and f.b = f2.b - left join fkest1 f3 on f.a = f3.a and f.b = f3.b -where f.c = 1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - -rollback; --- --- test planner's ability to mark joins as unique --- ---Testcase 472: -create foreign table j11 (id int options (key 'true')) server sqlite_svr; ---Testcase 473: -create foreign table j21 (id int options (key 'true')) server sqlite_svr; ---Testcase 474: -create foreign table j31 (id int) server sqlite_svr; ---Testcase 336: -insert into j11 values(1),(2),(3); ---Testcase 337: -insert into j21 values(1),(2),(3); ---Testcase 338: -insert into j31 values(1),(1); --- ensure join is properly marked as unique ---Testcase 339: -explain (verbose, costs off) -select * from j11 inner join j21 on j11.id = j21.id; - QUERY PLAN ---------------------------------------------------------- - Merge Join - Output: j11.id, j21.id - Merge Cond: (j11.id = j21.id) - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Sort - Output: j21.id - Sort Key: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" -(15 rows) - --- ensure join is not unique when not an equi-join ---Testcase 340: -explain (verbose, costs off) -select * from j11 inner join j21 on j11.id > j21.id; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: j11.id, j21.id - SQLite query: SELECT r1.`id`, r2.`id` FROM (main."j11" r1 INNER JOIN main."j21" r2 ON (((r1.`id` > r2.`id`)))) -(3 rows) - --- ensure non-unique rel is not chosen as inner ---Testcase 341: -explain (verbose, costs off) -select * from j11 inner join j31 on j11.id = j31.id; - QUERY PLAN ---------------------------------------------------------- - Merge Join - Output: j11.id, j31.id - Merge Cond: (j11.id = j31.id) - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Sort - Output: j31.id - Sort Key: j31.id - -> Foreign Scan on public.j31 - Output: j31.id - SQLite query: SELECT `id` FROM main."j31" -(15 rows) - --- ensure left join is marked as unique ---Testcase 342: -explain (verbose, costs off) -select * from j11 left join j21 on j11.id = j21.id; - QUERY PLAN ---------------------------------------------------------- - Merge Left Join - Output: j11.id, j21.id - Merge Cond: (j11.id = j21.id) - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Sort - Output: j21.id - Sort Key: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" -(15 rows) - --- ensure right join is marked as unique ---Testcase 343: -explain (verbose, costs off) -select * from j11 right join j21 on j11.id = j21.id; - QUERY PLAN ---------------------------------------------------------- - Merge Left Join - Output: j11.id, j21.id - Merge Cond: (j21.id = j11.id) - -> Sort - Output: j21.id - Sort Key: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" -(15 rows) - --- ensure full join is marked as unique ---Testcase 344: -explain (verbose, costs off) -select * from j11 full join j21 on j11.id = j21.id; - QUERY PLAN ---------------------------------------------------------- - Merge Full Join - Output: j11.id, j21.id - Merge Cond: (j11.id = j21.id) - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Sort - Output: j21.id - Sort Key: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" -(15 rows) - --- a clauseless (cross) join can't be unique ---Testcase 345: -explain (verbose, costs off) -select * from j11 cross join j21; - QUERY PLAN ---------------------------------------------------------- - Nested Loop - Output: j11.id, j21.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Materialize - Output: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" -(10 rows) - --- ensure a natural join is marked as unique ---Testcase 346: -explain (verbose, costs off) -select * from j11 natural join j21; - QUERY PLAN ---------------------------------------------------------- - Merge Join - Output: j11.id - Merge Cond: (j11.id = j21.id) - -> Sort - Output: j11.id - Sort Key: j11.id - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Sort - Output: j21.id - Sort Key: j21.id - -> Foreign Scan on public.j21 - Output: j21.id - SQLite query: SELECT `id` FROM main."j21" -(15 rows) - --- ensure a distinct clause allows the inner to become unique ---Testcase 347: -explain (verbose, costs off) -select * from j11 -inner join (select distinct id from j31) j31 on j11.id = j31.id; - QUERY PLAN --------------------------------------------------------------------------------------------- - Hash Join - Output: j11.id, j31.id - Inner Unique: true - Hash Cond: (j11.id = j31.id) - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Hash - Output: j31.id - -> Unique - Output: j31.id - -> Foreign Scan on public.j31 - Output: j31.id - SQLite query: SELECT `id` FROM main."j31" ORDER BY `id` ASC NULLS LAST -(14 rows) - --- ensure group by clause allows the inner to become unique ---Testcase 348: -explain (verbose, costs off) -select * from j11 -inner join (select id from j31 group by id) j31 on j11.id = j31.id; - QUERY PLAN --------------------------------------------------------------------- - Hash Join - Output: j11.id, j31.id - Inner Unique: true - Hash Cond: (j11.id = j31.id) - -> Foreign Scan on public.j11 - Output: j11.id - SQLite query: SELECT `id` FROM main."j11" - -> Hash - Output: j31.id - -> Foreign Scan - Output: j31.id - SQLite query: SELECT `id` FROM main."j31" GROUP BY 1 -(12 rows) - ---drop table j1; ---drop table j2; ---drop table j3; --- test more complex permutations of unique joins ---Testcase 475: -create foreign table j12 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; ---Testcase 476: -create foreign table j22 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; ---Testcase 477: -create foreign table j32 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; ---Testcase 349: -insert into j12 values(1,1),(1,2); ---Testcase 350: -insert into j22 values(1,1); ---Testcase 351: -insert into j32 values(1,1); ---analyze j1; ---analyze j2; ---analyze j3; --- ensure there's no unique join when not all columns which are part of the --- unique index are seen in the join clause ---Testcase 352: -explain (verbose, costs off) -select * from j12 -inner join j22 on j12.id1 = j22.id1; - QUERY PLAN ------------------------------------------------------------------ - Merge Join - Output: j12.id1, j12.id2, j22.id1, j22.id2 - Merge Cond: (j12.id1 = j22.id1) - -> Sort - Output: j12.id1, j12.id2 - Sort Key: j12.id1 - -> Foreign Scan on public.j12 - Output: j12.id1, j12.id2 - SQLite query: SELECT `id1`, `id2` FROM main."j12" - -> Sort - Output: j22.id1, j22.id2 - Sort Key: j22.id1 - -> Foreign Scan on public.j22 - Output: j22.id1, j22.id2 - SQLite query: SELECT `id1`, `id2` FROM main."j22" -(15 rows) - --- ensure proper unique detection with multiple join quals ---Testcase 353: -explain (verbose, costs off) -select * from j12 -inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2; - QUERY PLAN ------------------------------------------------------------------ - Merge Join - Output: j12.id1, j12.id2, j22.id1, j22.id2 - Merge Cond: ((j12.id1 = j22.id1) AND (j12.id2 = j22.id2)) - -> Sort - Output: j12.id1, j12.id2 - Sort Key: j12.id1, j12.id2 - -> Foreign Scan on public.j12 - Output: j12.id1, j12.id2 - SQLite query: SELECT `id1`, `id2` FROM main."j12" - -> Sort - Output: j22.id1, j22.id2 - Sort Key: j22.id1, j22.id2 - -> Foreign Scan on public.j22 - Output: j22.id1, j22.id2 - SQLite query: SELECT `id1`, `id2` FROM main."j22" -(15 rows) - --- ensure we don't detect the join to be unique when quals are not part of the --- join condition ---Testcase 354: -explain (verbose, costs off) -select * from j12 -inner join j22 on j12.id1 = j22.id1 where j12.id2 = 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: j12.id1, j12.id2, j22.id1, j22.id2 - SQLite query: SELECT r1.`id1`, r1.`id2`, r2.`id1`, r2.`id2` FROM (main."j12" r1 INNER JOIN main."j22" r2 ON (((r1.`id1` = r2.`id1`)) AND ((r1.`id2` = 1)))) -(3 rows) - --- as above, but for left joins. ---Testcase 355: -explain (verbose, costs off) -select * from j12 -left join j22 on j12.id1 = j22.id1 where j12.id2 = 1; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: j12.id1, j12.id2, j22.id1, j22.id2 - SQLite query: SELECT r1.`id1`, r1.`id2`, r2.`id1`, r2.`id2` FROM (main."j12" r1 LEFT JOIN main."j22" r2 ON (((r1.`id1` = r2.`id1`)))) WHERE ((r1.`id2` = 1)) -(3 rows) - --- validate logic in merge joins which skips mark and restore. --- it should only do this if all quals which were used to detect the unique --- are present as join quals, and not plain quals. -set enable_nestloop to 0; -set enable_hashjoin to 0; -set enable_sort to 0; --- skip, cannot create index on foreign table --- create indexes that will be preferred over the PKs to perform the join ---create index j1_id1_idx on j1 (id1) where id1 % 1000 = 1; ---create index j2_id1_idx on j2 (id1) where id1 % 1000 = 1; --- need an additional row in j2, if we want j2_id1_idx to be preferred ---Testcase 478: -insert into j22 values(1,2); ---analyze j2; ---Testcase 356: -explain (costs off) select * from j12 j12 -inner join j12 j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 357: -select * from j12 j12 -inner join j12 j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1; - id1 | id2 | id1 | id2 ------+-----+-----+----- - 1 | 1 | 1 | 1 - 1 | 2 | 1 | 2 -(2 rows) - --- Exercise array keys mark/restore B-Tree code ---Testcase 479: -explain (costs off) select * from j12 -inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 = any (array[1]); - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 480: -select * from j12 -inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 = any (array[1]); - id1 | id2 | id1 | id2 ------+-----+-----+----- - 1 | 1 | 1 | 1 - 1 | 2 | 1 | 2 -(2 rows) - --- Exercise array keys "find extreme element" B-Tree code ---Testcase 481: -explain (costs off) select * from j12 -inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 >= any (array[1,5]); - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 482: -select * from j12 -inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 -where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 >= any (array[1,5]); - id1 | id2 | id1 | id2 ------+-----+-----+----- - 1 | 1 | 1 | 1 - 1 | 2 | 1 | 2 -(2 rows) - -reset enable_nestloop; -reset enable_hashjoin; -reset enable_sort; ---drop table j1; ---drop table j2; ---drop table j3; --- check that semijoin inner is not seen as unique for a portion of the outerrel ---Testcase 483: -CREATE FOREIGN TABLE onek ( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 358: -explain (verbose, costs off) -select t1.unique1, t2.hundred -from onek t1, tenk1 t2 -where exists (select 1 from tenk1 t3 - where t3.thousand = t1.unique1 and t3.tenthous = t2.hundred) - and t1.unique1 < 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Join - Output: t1.unique1, t2.hundred - Hash Cond: (t2.hundred = t3.tenthous) - -> Foreign Scan on public.tenk1 t2 - Output: t2.unique1, t2.unique2, t2.two, t2.four, t2.ten, t2.twenty, t2.hundred, t2.thousand, t2.twothousand, t2.fivethous, t2.tenthous, t2.odd, t2.even, t2.stringu1, t2.stringu2, t2.string4 - SQLite query: SELECT `hundred` FROM main."tenk1" - -> Hash - Output: t1.unique1, t3.tenthous - -> Hash Join - Output: t1.unique1, t3.tenthous - Hash Cond: (t1.unique1 = t3.thousand) - -> Foreign Scan on public.onek t1 - Output: t1.unique1, t1.unique2, t1.two, t1.four, t1.ten, t1.twenty, t1.hundred, t1.thousand, t1.twothousand, t1.fivethous, t1.tenthous, t1.odd, t1.even, t1.stringu1, t1.stringu2, t1.string4 - SQLite query: SELECT `unique1` FROM main."onek" WHERE ((`unique1` < 1)) - -> Hash - Output: t3.thousand, t3.tenthous - -> HashAggregate - Output: t3.thousand, t3.tenthous - Group Key: t3.thousand, t3.tenthous - -> Foreign Scan on public.tenk1 t3 - Output: t3.thousand, t3.tenthous - SQLite query: SELECT `thousand`, `tenthous` FROM main."tenk1" -(22 rows) - --- ... unless it actually is unique ---Testcase 484: -create table j3 as select unique1, tenthous from onek; -vacuum analyze j3; ---Testcase 485: -create unique index on j3(unique1, tenthous); ---Testcase 359: -explain (verbose, costs off) -select t1.unique1, t2.hundred -from onek t1, tenk1 t2 -where exists (select 1 from j3 - where j3.unique1 = t1.unique1 and j3.tenthous = t2.hundred) - and t1.unique1 < 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Join - Output: t1.unique1, t2.hundred - Hash Cond: (t2.hundred = j3.tenthous) - -> Foreign Scan on public.tenk1 t2 - Output: t2.unique1, t2.unique2, t2.two, t2.four, t2.ten, t2.twenty, t2.hundred, t2.thousand, t2.twothousand, t2.fivethous, t2.tenthous, t2.odd, t2.even, t2.stringu1, t2.stringu2, t2.string4 - SQLite query: SELECT `hundred` FROM main."tenk1" - -> Hash - Output: t1.unique1, j3.tenthous - -> Hash Join - Output: t1.unique1, j3.tenthous - Hash Cond: (t1.unique1 = j3.unique1) - -> Foreign Scan on public.onek t1 - Output: t1.unique1, t1.unique2, t1.two, t1.four, t1.ten, t1.twenty, t1.hundred, t1.thousand, t1.twothousand, t1.fivethous, t1.tenthous, t1.odd, t1.even, t1.stringu1, t1.stringu2, t1.string4 - SQLite query: SELECT `unique1` FROM main."onek" WHERE ((`unique1` < 1)) - -> Hash - Output: j3.unique1, j3.tenthous - -> Seq Scan on public.j3 - Output: j3.unique1, j3.tenthous -(18 rows) - ---Testcase 486: -drop table j3; -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; ---Testcase 487: -DROP SERVER sqlite_svr; ---Testcase 488: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/limit.out b/expected/12.16/extra/limit.out deleted file mode 100644 index 27323d02..00000000 --- a/expected/12.16/extra/limit.out +++ /dev/null @@ -1,980 +0,0 @@ --- --- LIMIT --- Check the LIMIT/OFFSET feature of SELECT --- ---Testcase 27: -CREATE EXTENSION sqlite_fdw; ---Testcase 28: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 29: -CREATE FOREIGN TABLE onek( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 30: -CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; ---Testcase 31: -CREATE FOREIGN TABLE INT8_TMP( - q1 int8, - q2 int8, - q3 int4, - q4 int2, - q5 text, - id int options (key 'true') -) SERVER sqlite_svr; ---Testcase 32: -CREATE FOREIGN TABLE tenk1 ( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; ---Testcase 88: -CREATE TABLE parent_table ( - unique1 int4 PRIMARY KEY, - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -); ---Testcase 89: -CREATE FOREIGN table inherited_table () -INHERITS (parent_table) -SERVER sqlite_svr options (table 'tenk1'); ---Testcase 1: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 50 - ORDER BY unique1 LIMIT 2; - two | unique1 | unique2 | stringu1 ------+---------+---------+---------- - | 51 | 76 | ZBAAAA - | 52 | 985 | ACAAAA -(2 rows) - ---Testcase 2: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 60 - ORDER BY unique1 LIMIT 5; - five | unique1 | unique2 | stringu1 -------+---------+---------+---------- - | 61 | 560 | JCAAAA - | 62 | 633 | KCAAAA - | 63 | 296 | LCAAAA - | 64 | 479 | MCAAAA - | 65 | 64 | NCAAAA -(5 rows) - ---Testcase 3: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 60 AND unique1 < 63 - ORDER BY unique1 LIMIT 5; - two | unique1 | unique2 | stringu1 ------+---------+---------+---------- - | 61 | 560 | JCAAAA - | 62 | 633 | KCAAAA -(2 rows) - ---Testcase 4: -SELECT ''::text AS three, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 100 - ORDER BY unique1 LIMIT 3 OFFSET 20; - three | unique1 | unique2 | stringu1 --------+---------+---------+---------- - | 121 | 700 | REAAAA - | 122 | 519 | SEAAAA - | 123 | 777 | TEAAAA -(3 rows) - ---Testcase 5: -SELECT ''::text AS zero, unique1, unique2, stringu1 - FROM onek WHERE unique1 < 50 - ORDER BY unique1 DESC LIMIT 8 OFFSET 99; - zero | unique1 | unique2 | stringu1 -------+---------+---------+---------- -(0 rows) - ---Testcase 6: -SELECT ''::text AS eleven, unique1, unique2, stringu1 - FROM onek WHERE unique1 < 50 - ORDER BY unique1 DESC LIMIT 20 OFFSET 39; - eleven | unique1 | unique2 | stringu1 ---------+---------+---------+---------- - | 10 | 520 | KAAAAA - | 9 | 49 | JAAAAA - | 8 | 653 | IAAAAA - | 7 | 647 | HAAAAA - | 6 | 978 | GAAAAA - | 5 | 541 | FAAAAA - | 4 | 833 | EAAAAA - | 3 | 431 | DAAAAA - | 2 | 326 | CAAAAA - | 1 | 214 | BAAAAA - | 0 | 998 | AAAAAA -(11 rows) - ---Testcase 7: -SELECT ''::text AS ten, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 OFFSET 990; - ten | unique1 | unique2 | stringu1 ------+---------+---------+---------- - | 990 | 369 | CMAAAA - | 991 | 426 | DMAAAA - | 992 | 363 | EMAAAA - | 993 | 661 | FMAAAA - | 994 | 695 | GMAAAA - | 995 | 144 | HMAAAA - | 996 | 258 | IMAAAA - | 997 | 21 | JMAAAA - | 998 | 549 | KMAAAA - | 999 | 152 | LMAAAA -(10 rows) - ---Testcase 8: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 OFFSET 990 LIMIT 5; - five | unique1 | unique2 | stringu1 -------+---------+---------+---------- - | 990 | 369 | CMAAAA - | 991 | 426 | DMAAAA - | 992 | 363 | EMAAAA - | 993 | 661 | FMAAAA - | 994 | 695 | GMAAAA -(5 rows) - ---Testcase 9: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 LIMIT 5 OFFSET 900; - five | unique1 | unique2 | stringu1 -------+---------+---------+---------- - | 900 | 913 | QIAAAA - | 901 | 931 | RIAAAA - | 902 | 702 | SIAAAA - | 903 | 641 | TIAAAA - | 904 | 793 | UIAAAA -(5 rows) - --- Test null limit and offset. The planner would discard a simple null --- constant, so to ensure executor is exercised, do this: ---Testcase 10: -select * from int8_tbl limit (case when random() < 0.5 then null::bigint end); - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(5 rows) - ---Testcase 11: -select * from int8_tbl offset (case when random() < 0.5 then null::bigint end); - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(5 rows) - --- Test assorted cases involving backwards fetch from a LIMIT plan node -begin; -declare c1 scroll cursor for select * from int8_tbl order by q1 limit 10; ---Testcase 12: -fetch all in c1; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(5 rows) - ---Testcase 13: -fetch 1 in c1; - q1 | q2 -----+---- -(0 rows) - ---Testcase 14: -fetch backward 1 in c1; - q1 | q2 -------------------+------------------ - 4567890123456789 | 4567890123456789 -(1 row) - ---Testcase 33: -fetch backward all in c1; - q1 | q2 -------------------+------------------- - 4567890123456789 | 123 - 4567890123456789 | -4567890123456789 - 123 | 4567890123456789 - 123 | 456 -(4 rows) - ---Testcase 34: -fetch backward 1 in c1; - q1 | q2 -----+---- -(0 rows) - ---Testcase 35: -fetch all in c1; - q1 | q2 -------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | -4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 -(5 rows) - -declare c2 scroll cursor for select * from int8_tbl limit 3; ---Testcase 36: -fetch all in c2; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 -(3 rows) - ---Testcase 37: -fetch 1 in c2; - q1 | q2 -----+---- -(0 rows) - ---Testcase 38: -fetch backward 1 in c2; - q1 | q2 -------------------+----- - 4567890123456789 | 123 -(1 row) - ---Testcase 39: -fetch backward all in c2; - q1 | q2 ------+------------------ - 123 | 4567890123456789 - 123 | 456 -(2 rows) - ---Testcase 40: -fetch backward 1 in c2; - q1 | q2 -----+---- -(0 rows) - ---Testcase 41: -fetch all in c2; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 -(3 rows) - -declare c3 scroll cursor for select * from int8_tbl offset 3; ---Testcase 42: -fetch all in c3; - q1 | q2 -------------------+------------------- - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(2 rows) - ---Testcase 43: -fetch 1 in c3; - q1 | q2 -----+---- -(0 rows) - ---Testcase 44: -fetch backward 1 in c3; - q1 | q2 -------------------+------------------- - 4567890123456789 | -4567890123456789 -(1 row) - ---Testcase 45: -fetch backward all in c3; - q1 | q2 -------------------+------------------ - 4567890123456789 | 4567890123456789 -(1 row) - ---Testcase 46: -fetch backward 1 in c3; - q1 | q2 -----+---- -(0 rows) - ---Testcase 47: -fetch all in c3; - q1 | q2 -------------------+------------------- - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 -(2 rows) - -declare c4 scroll cursor for select * from int8_tbl offset 10; ---Testcase 48: -fetch all in c4; - q1 | q2 -----+---- -(0 rows) - ---Testcase 49: -fetch 1 in c4; - q1 | q2 -----+---- -(0 rows) - ---Testcase 50: -fetch backward 1 in c4; - q1 | q2 -----+---- -(0 rows) - ---Testcase 51: -fetch backward all in c4; - q1 | q2 -----+---- -(0 rows) - ---Testcase 52: -fetch backward 1 in c4; - q1 | q2 -----+---- -(0 rows) - ---Testcase 53: -fetch all in c4; - q1 | q2 -----+---- -(0 rows) - -declare c5 scroll cursor for select * from int8_tbl order by q1 fetch first 2 rows with ties; -ERROR: syntax error at or near "with" -LINE 1: ...ct * from int8_tbl order by q1 fetch first 2 rows with ties; - ^ ---Testcase 54: -fetch all in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 55: -fetch 1 in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 56: -fetch backward 1 in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 57: -fetch backward 1 in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 58: -fetch all in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 59: -fetch backward all in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 60: -fetch all in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block ---Testcase 61: -fetch backward all in c5; -ERROR: current transaction is aborted, commands ignored until end of transaction block -rollback; --- Stress test for variable LIMIT in conjunction with bounded-heap sorting ---Testcase 62: -DELETE FROM INT8_TMP; ---Testcase 63: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series(1,10) q1; ---Testcase 64: -SELECT - (SELECT s.q1 - FROM (VALUES (1)) AS x, - (SELECT q1 FROM INT8_TMP as n - ORDER BY q1 LIMIT 1 OFFSET s.q1-1) AS y) AS z - FROM INT8_TMP AS s; - z ----- - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 -(10 rows) - --- --- Test behavior of volatile and set-returning functions in conjunction --- with ORDER BY and LIMIT. --- ---Testcase 65: -create temp sequence testseq; ---Testcase 15: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass) - SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST LIMIT 10 -(3 rows) - ---Testcase 16: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10; - unique1 | unique2 | nextval ----------+---------+--------- - 8800 | 0 | 1 - 1891 | 1 | 2 - 3420 | 2 | 3 - 9850 | 3 | 4 - 7164 | 4 | 5 - 8009 | 5 | 6 - 5057 | 6 | 7 - 6701 | 7 | 8 - 4321 | 8 | 9 - 3043 | 9 | 10 -(10 rows) - ---Testcase 90: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10 offset 5; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass) - SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST LIMIT 10 OFFSET 5 -(3 rows) - ---Testcase 91: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10 offset 5; - unique1 | unique2 | nextval ----------+---------+--------- - 8009 | 5 | 11 - 5057 | 6 | 12 - 6701 | 7 | 13 - 4321 | 8 | 14 - 3043 | 9 | 15 - 1314 | 10 | 16 - 1504 | 11 | 17 - 5222 | 12 | 18 - 6243 | 13 | 19 - 5471 | 14 | 20 -(10 rows) - ---Testcase 17: -select currval('testseq'); - currval ---------- - 20 -(1 row) - ---Testcase 92: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass) - SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` DESC NULLS FIRST LIMIT 10 -(3 rows) - ---Testcase 93: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10; - unique1 | unique2 | nextval ----------+---------+--------- - 2968 | 9999 | 21 - 0 | 9998 | 22 - 2992 | 9997 | 23 - 1783 | 9996 | 24 - 5780 | 9995 | 25 - 429 | 9994 | 26 - 6093 | 9993 | 27 - 6587 | 9992 | 28 - 4093 | 9991 | 29 - 4773 | 9990 | 30 -(10 rows) - ---Testcase 94: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10 offset 5; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass) - SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` DESC NULLS FIRST LIMIT 10 OFFSET 5 -(3 rows) - ---Testcase 95: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10 offset 5; - unique1 | unique2 | nextval ----------+---------+--------- - 429 | 9994 | 31 - 6093 | 9993 | 32 - 6587 | 9992 | 33 - 4093 | 9991 | 34 - 4773 | 9990 | 35 - 8592 | 9989 | 36 - 858 | 9988 | 37 - 9194 | 9987 | 38 - 1384 | 9986 | 39 - 2406 | 9985 | 40 -(10 rows) - ---Testcase 96: -select currval('testseq'); - currval ---------- - 40 -(1 row) - ---Testcase 18: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass), tenthous - SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 -(3 rows) - ---Testcase 19: -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10; - unique1 | unique2 | nextval ----------+---------+--------- - 0 | 9998 | 41 - 1 | 2838 | 42 - 2 | 2716 | 43 - 3 | 5679 | 44 - 4 | 1621 | 45 - 5 | 5557 | 46 - 6 | 2855 | 47 - 7 | 8518 | 48 - 8 | 5435 | 49 - 9 | 4463 | 50 -(10 rows) - ---Testcase 97: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10 offset 5; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.tenk1 - Output: unique1, unique2, nextval('testseq'::regclass), tenthous - SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 OFFSET 5 -(3 rows) - ---Testcase 98: -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10 offset 5; - unique1 | unique2 | nextval ----------+---------+--------- - 5 | 5557 | 51 - 6 | 2855 | 52 - 7 | 8518 | 53 - 8 | 5435 | 54 - 9 | 4463 | 55 - 10 | 8788 | 56 - 11 | 8396 | 57 - 12 | 6605 | 58 - 13 | 5696 | 59 - 14 | 4341 | 60 -(10 rows) - ---Testcase 20: -select currval('testseq'); - currval ---------- - 60 -(1 row) - --- test for limit and offset when querying table and foreign table inherited ---Testcase 99: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: parent_table.unique1, parent_table.unique2, (nextval('testseq'::regclass)), parent_table.tenthous - -> Result - Output: parent_table.unique1, parent_table.unique2, nextval('testseq'::regclass), parent_table.tenthous - -> Merge Append - Sort Key: parent_table.tenthous - -> Sort - Output: parent_table.unique1, parent_table.unique2, parent_table.tenthous - Sort Key: parent_table.tenthous - -> Seq Scan on public.parent_table - Output: parent_table.unique1, parent_table.unique2, parent_table.tenthous - -> Foreign Scan on public.inherited_table - Output: inherited_table.unique1, inherited_table.unique2, inherited_table.tenthous - SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 -(14 rows) - ---Testcase 100: -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10; - unique1 | unique2 | nextval ----------+---------+--------- - 0 | 9998 | 61 - 1 | 2838 | 62 - 2 | 2716 | 63 - 3 | 5679 | 64 - 4 | 1621 | 65 - 5 | 5557 | 66 - 6 | 2855 | 67 - 7 | 8518 | 68 - 8 | 5435 | 69 - 9 | 4463 | 70 -(10 rows) - --- when querying regular tables with inherited tables, only limit is pushed-down when no offset is specified ---Testcase 101: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10 offset 5; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: parent_table.unique1, parent_table.unique2, (nextval('testseq'::regclass)), parent_table.tenthous - -> Result - Output: parent_table.unique1, parent_table.unique2, nextval('testseq'::regclass), parent_table.tenthous - -> Merge Append - Sort Key: parent_table.tenthous - -> Sort - Output: parent_table.unique1, parent_table.unique2, parent_table.tenthous - Sort Key: parent_table.tenthous - -> Seq Scan on public.parent_table - Output: parent_table.unique1, parent_table.unique2, parent_table.tenthous - -> Foreign Scan on public.inherited_table - Output: inherited_table.unique1, inherited_table.unique2, inherited_table.tenthous - SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST -(14 rows) - ---Testcase 102: -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10 offset 5; - unique1 | unique2 | nextval ----------+---------+--------- - 5 | 5557 | 76 - 6 | 2855 | 77 - 7 | 8518 | 78 - 8 | 5435 | 79 - 9 | 4463 | 80 - 10 | 8788 | 81 - 11 | 8396 | 82 - 12 | 6605 | 83 - 13 | 5696 | 84 - 14 | 4341 | 85 -(10 rows) - ---Testcase 103: -select currval('testseq'); - currval ---------- - 85 -(1 row) - ---Testcase 21: -explain (verbose, costs off) -select unique1, unique2, generate_series(1,10) - from tenk1 order by unique2 limit 7; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: unique1, unique2, (generate_series(1, 10)) - -> ProjectSet - Output: unique1, unique2, generate_series(1, 10) - -> Foreign Scan on public.tenk1 - Output: unique1, unique2, two, four, ten, twenty, hundred, thousand, twothousand, fivethous, tenthous, odd, even, stringu1, stringu2, string4 - SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST -(7 rows) - ---Testcase 22: -select unique1, unique2, generate_series(1,10) - from tenk1 order by unique2 limit 7; - unique1 | unique2 | generate_series ----------+---------+----------------- - 8800 | 0 | 1 - 8800 | 0 | 2 - 8800 | 0 | 3 - 8800 | 0 | 4 - 8800 | 0 | 5 - 8800 | 0 | 6 - 8800 | 0 | 7 -(7 rows) - ---Testcase 23: -explain (verbose, costs off) -select unique1, unique2, generate_series(1,10) - from tenk1 order by tenthous limit 7; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: unique1, unique2, (generate_series(1, 10)), tenthous - -> ProjectSet - Output: unique1, unique2, generate_series(1, 10), tenthous - -> Foreign Scan on public.tenk1 - Output: unique1, unique2, two, four, ten, twenty, hundred, thousand, twothousand, fivethous, tenthous, odd, even, stringu1, stringu2, string4 - SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST -(7 rows) - ---Testcase 24: -select unique1, unique2, generate_series(1,10) - from tenk1 order by tenthous limit 7; - unique1 | unique2 | generate_series ----------+---------+----------------- - 0 | 9998 | 1 - 0 | 9998 | 2 - 0 | 9998 | 3 - 0 | 9998 | 4 - 0 | 9998 | 5 - 0 | 9998 | 6 - 0 | 9998 | 7 -(7 rows) - --- use of random() is to keep planner from folding the expressions together ---Testcase 66: -DELETE FROM INT8_TMP; ---Testcase 67: -INSERT INTO INT8_TMP VALUES (generate_series(0,2), generate_series((random()*.1)::int,2)); ---Testcase 68: -explain (verbose, costs off) -select q1, q2 from int8_tmp; - QUERY PLAN --------------------------------------------------------- - Foreign Scan on public.int8_tmp - Output: q1, q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tmp" -(3 rows) - ---Testcase 69: -select q1, q2 from int8_tmp; - q1 | q2 -----+---- - 0 | 0 - 1 | 1 - 2 | 2 -(3 rows) - ---Testcase 70: -explain (verbose, costs off) -select q1, q2 from int8_tmp order by q2 desc; - QUERY PLAN ---------------------------------------------------------------------------------------- - Foreign Scan on public.int8_tmp - Output: q1, q2 - SQLite query: SELECT `q1`, `q2` FROM main."int8_tmp" ORDER BY `q2` DESC NULLS FIRST -(3 rows) - ---Testcase 71: -select q1, q2 from int8_tmp order by q2 desc; - q1 | q2 -----+---- - 2 | 2 - 1 | 1 - 0 | 0 -(3 rows) - --- test for failure to set all aggregates' aggtranstype ---Testcase 25: -explain (verbose, costs off) -select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 - from tenk1 group by thousand order by thousand limit 3; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (sum(tenthous)), ((((sum(tenthous)))::double precision + (random() * '0'::double precision))), thousand - -> Foreign Scan - Output: (sum(tenthous)), (((sum(tenthous)))::double precision + (random() * '0'::double precision)), thousand - SQLite query: SELECT sum(`tenthous`), `thousand` FROM main."tenk1" GROUP BY 2 ORDER BY `thousand` ASC NULLS LAST -(5 rows) - ---Testcase 26: -select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 - from tenk1 group by thousand order by thousand limit 3; - s1 | s2 --------+------- - 45000 | 45000 - 45010 | 45010 - 45020 | 45020 -(3 rows) - --- --- FETCH FIRST --- Check the WITH TIES clause --- ---Testcase 72: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 2 ROW WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 3: ORDER BY thousand FETCH FIRST 2 ROW WITH TIES; - ^ ---Testcase 73: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 3: ORDER BY thousand FETCH FIRST ROWS WITH TIES; - ^ ---Testcase 74: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 3: ORDER BY thousand FETCH FIRST 1 ROW WITH TIES; - ^ ---Testcase 75: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 2 ROW ONLY; - thousand ----------- - 0 - 0 -(2 rows) - --- should fail ---Testcase 76: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 50 - FETCH FIRST 2 ROW WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 3: FETCH FIRST 2 ROW WITH TIES; - ^ --- test ruleutils ---Testcase 77: -CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; -ERROR: syntax error at or near "WITH" -LINE 2: ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; - ^ ---Testcase 78: -\d+ limit_thousand_v_1 ---Testcase 79: -CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY; ---Testcase 80: -\d+ limit_thousand_v_2 - View "public.limit_thousand_v_2" - Column | Type | Collation | Nullable | Default | Storage | Description -----------+---------+-----------+----------+---------+---------+------------- - thousand | integer | | | | plain | -View definition: - SELECT onek.thousand - FROM onek - WHERE onek.thousand < 995 - ORDER BY onek.thousand - OFFSET 10 - LIMIT 5; - ---Testcase 81: -CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS WITH TIES; -- fails -ERROR: syntax error at or near "WITH" -LINE 2: ORDER BY thousand FETCH FIRST NULL ROWS WITH TIES; - ^ ---Testcase 82: -CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 2: ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; - ^ ---Testcase 83: -\d+ limit_thousand_v_3 ---Testcase 84: -CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS ONLY; ---Testcase 85: -\d+ limit_thousand_v_4 - View "public.limit_thousand_v_4" - Column | Type | Collation | Nullable | Default | Storage | Description -----------+---------+-----------+----------+---------+---------+------------- - thousand | integer | | | | plain | -View definition: - SELECT onek.thousand - FROM onek - WHERE onek.thousand < 995 - ORDER BY onek.thousand - LIMIT ALL; - --- leave these views --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view limit_thousand_v_2 -drop cascades to view limit_thousand_v_4 ---Testcase 86: -DROP SERVER sqlite_svr; ---Testcase 87: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/numeric.out b/expected/12.16/extra/numeric.out deleted file mode 100644 index ba879d51..00000000 --- a/expected/12.16/extra/numeric.out +++ /dev/null @@ -1,3810 +0,0 @@ --- --- NUMERIC --- ---Testcase 567: -CREATE EXTENSION sqlite_fdw; ---Testcase 568: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 569: -CREATE FOREIGN TABLE num_data (id int4 OPTIONS (key 'true'), val numeric(210,10)) SERVER sqlite_svr; ---Testcase 570: -CREATE FOREIGN TABLE num_exp_add (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 571: -CREATE FOREIGN TABLE num_exp_sub (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 572: -CREATE FOREIGN TABLE num_exp_div (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 573: -CREATE FOREIGN TABLE num_exp_mul (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 574: -CREATE FOREIGN TABLE num_exp_sqrt (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 575: -CREATE FOREIGN TABLE num_exp_ln (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 576: -CREATE FOREIGN TABLE num_exp_log10 (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 577: -CREATE FOREIGN TABLE num_exp_power_10_ln (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; ---Testcase 578: -CREATE FOREIGN TABLE num_result (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), result numeric(210,10)) SERVER sqlite_svr; --- ****************************** --- * The following EXPECTED results are computed by bc(1) --- * with a scale of 200 --- ****************************** -BEGIN TRANSACTION; ---Testcase 1: -INSERT INTO num_exp_add VALUES (0,0,'0'); ---Testcase 2: -INSERT INTO num_exp_sub VALUES (0,0,'0'); ---Testcase 3: -INSERT INTO num_exp_mul VALUES (0,0,'0'); ---Testcase 4: -INSERT INTO num_exp_div VALUES (0,0,'NaN'); ---Testcase 5: -INSERT INTO num_exp_add VALUES (0,1,'0'); ---Testcase 6: -INSERT INTO num_exp_sub VALUES (0,1,'0'); ---Testcase 7: -INSERT INTO num_exp_mul VALUES (0,1,'0'); ---Testcase 8: -INSERT INTO num_exp_div VALUES (0,1,'NaN'); ---Testcase 9: -INSERT INTO num_exp_add VALUES (0,2,'-34338492.215397047'); ---Testcase 10: -INSERT INTO num_exp_sub VALUES (0,2,'34338492.215397047'); ---Testcase 11: -INSERT INTO num_exp_mul VALUES (0,2,'0'); ---Testcase 12: -INSERT INTO num_exp_div VALUES (0,2,'0'); ---Testcase 13: -INSERT INTO num_exp_add VALUES (0,3,'4.31'); ---Testcase 14: -INSERT INTO num_exp_sub VALUES (0,3,'-4.31'); ---Testcase 15: -INSERT INTO num_exp_mul VALUES (0,3,'0'); ---Testcase 16: -INSERT INTO num_exp_div VALUES (0,3,'0'); ---Testcase 17: -INSERT INTO num_exp_add VALUES (0,4,'7799461.4119'); ---Testcase 18: -INSERT INTO num_exp_sub VALUES (0,4,'-7799461.4119'); ---Testcase 19: -INSERT INTO num_exp_mul VALUES (0,4,'0'); ---Testcase 20: -INSERT INTO num_exp_div VALUES (0,4,'0'); ---Testcase 21: -INSERT INTO num_exp_add VALUES (0,5,'16397.038491'); ---Testcase 22: -INSERT INTO num_exp_sub VALUES (0,5,'-16397.038491'); ---Testcase 23: -INSERT INTO num_exp_mul VALUES (0,5,'0'); ---Testcase 24: -INSERT INTO num_exp_div VALUES (0,5,'0'); ---Testcase 25: -INSERT INTO num_exp_add VALUES (0,6,'93901.57763026'); ---Testcase 26: -INSERT INTO num_exp_sub VALUES (0,6,'-93901.57763026'); ---Testcase 27: -INSERT INTO num_exp_mul VALUES (0,6,'0'); ---Testcase 28: -INSERT INTO num_exp_div VALUES (0,6,'0'); ---Testcase 29: -INSERT INTO num_exp_add VALUES (0,7,'-83028485'); ---Testcase 30: -INSERT INTO num_exp_sub VALUES (0,7,'83028485'); ---Testcase 31: -INSERT INTO num_exp_mul VALUES (0,7,'0'); ---Testcase 32: -INSERT INTO num_exp_div VALUES (0,7,'0'); ---Testcase 33: -INSERT INTO num_exp_add VALUES (0,8,'74881'); ---Testcase 34: -INSERT INTO num_exp_sub VALUES (0,8,'-74881'); ---Testcase 35: -INSERT INTO num_exp_mul VALUES (0,8,'0'); ---Testcase 36: -INSERT INTO num_exp_div VALUES (0,8,'0'); ---Testcase 37: -INSERT INTO num_exp_add VALUES (0,9,'-24926804.045047420'); ---Testcase 38: -INSERT INTO num_exp_sub VALUES (0,9,'24926804.045047420'); ---Testcase 39: -INSERT INTO num_exp_mul VALUES (0,9,'0'); ---Testcase 40: -INSERT INTO num_exp_div VALUES (0,9,'0'); ---Testcase 41: -INSERT INTO num_exp_add VALUES (1,0,'0'); ---Testcase 42: -INSERT INTO num_exp_sub VALUES (1,0,'0'); ---Testcase 43: -INSERT INTO num_exp_mul VALUES (1,0,'0'); ---Testcase 44: -INSERT INTO num_exp_div VALUES (1,0,'NaN'); ---Testcase 45: -INSERT INTO num_exp_add VALUES (1,1,'0'); ---Testcase 46: -INSERT INTO num_exp_sub VALUES (1,1,'0'); ---Testcase 47: -INSERT INTO num_exp_mul VALUES (1,1,'0'); ---Testcase 48: -INSERT INTO num_exp_div VALUES (1,1,'NaN'); ---Testcase 49: -INSERT INTO num_exp_add VALUES (1,2,'-34338492.215397047'); ---Testcase 50: -INSERT INTO num_exp_sub VALUES (1,2,'34338492.215397047'); ---Testcase 51: -INSERT INTO num_exp_mul VALUES (1,2,'0'); ---Testcase 52: -INSERT INTO num_exp_div VALUES (1,2,'0'); ---Testcase 53: -INSERT INTO num_exp_add VALUES (1,3,'4.31'); ---Testcase 54: -INSERT INTO num_exp_sub VALUES (1,3,'-4.31'); ---Testcase 55: -INSERT INTO num_exp_mul VALUES (1,3,'0'); ---Testcase 56: -INSERT INTO num_exp_div VALUES (1,3,'0'); ---Testcase 57: -INSERT INTO num_exp_add VALUES (1,4,'7799461.4119'); ---Testcase 58: -INSERT INTO num_exp_sub VALUES (1,4,'-7799461.4119'); ---Testcase 59: -INSERT INTO num_exp_mul VALUES (1,4,'0'); ---Testcase 60: -INSERT INTO num_exp_div VALUES (1,4,'0'); ---Testcase 61: -INSERT INTO num_exp_add VALUES (1,5,'16397.038491'); ---Testcase 62: -INSERT INTO num_exp_sub VALUES (1,5,'-16397.038491'); ---Testcase 63: -INSERT INTO num_exp_mul VALUES (1,5,'0'); ---Testcase 64: -INSERT INTO num_exp_div VALUES (1,5,'0'); ---Testcase 65: -INSERT INTO num_exp_add VALUES (1,6,'93901.57763026'); ---Testcase 66: -INSERT INTO num_exp_sub VALUES (1,6,'-93901.57763026'); ---Testcase 67: -INSERT INTO num_exp_mul VALUES (1,6,'0'); ---Testcase 68: -INSERT INTO num_exp_div VALUES (1,6,'0'); ---Testcase 69: -INSERT INTO num_exp_add VALUES (1,7,'-83028485'); ---Testcase 70: -INSERT INTO num_exp_sub VALUES (1,7,'83028485'); ---Testcase 71: -INSERT INTO num_exp_mul VALUES (1,7,'0'); ---Testcase 72: -INSERT INTO num_exp_div VALUES (1,7,'0'); ---Testcase 73: -INSERT INTO num_exp_add VALUES (1,8,'74881'); ---Testcase 74: -INSERT INTO num_exp_sub VALUES (1,8,'-74881'); ---Testcase 75: -INSERT INTO num_exp_mul VALUES (1,8,'0'); ---Testcase 76: -INSERT INTO num_exp_div VALUES (1,8,'0'); ---Testcase 77: -INSERT INTO num_exp_add VALUES (1,9,'-24926804.045047420'); ---Testcase 78: -INSERT INTO num_exp_sub VALUES (1,9,'24926804.045047420'); ---Testcase 79: -INSERT INTO num_exp_mul VALUES (1,9,'0'); ---Testcase 80: -INSERT INTO num_exp_div VALUES (1,9,'0'); ---Testcase 81: -INSERT INTO num_exp_add VALUES (2,0,'-34338492.215397047'); ---Testcase 82: -INSERT INTO num_exp_sub VALUES (2,0,'-34338492.215397047'); ---Testcase 83: -INSERT INTO num_exp_mul VALUES (2,0,'0'); ---Testcase 84: -INSERT INTO num_exp_div VALUES (2,0,'NaN'); ---Testcase 85: -INSERT INTO num_exp_add VALUES (2,1,'-34338492.215397047'); ---Testcase 86: -INSERT INTO num_exp_sub VALUES (2,1,'-34338492.215397047'); ---Testcase 87: -INSERT INTO num_exp_mul VALUES (2,1,'0'); ---Testcase 88: -INSERT INTO num_exp_div VALUES (2,1,'NaN'); ---Testcase 89: -INSERT INTO num_exp_add VALUES (2,2,'-68676984.430794094'); ---Testcase 90: -INSERT INTO num_exp_sub VALUES (2,2,'0'); ---Testcase 91: -INSERT INTO num_exp_mul VALUES (2,2,'1179132047626883.596862135856320209'); ---Testcase 92: -INSERT INTO num_exp_div VALUES (2,2,'1.00000000000000000000'); ---Testcase 93: -INSERT INTO num_exp_add VALUES (2,3,'-34338487.905397047'); ---Testcase 94: -INSERT INTO num_exp_sub VALUES (2,3,'-34338496.525397047'); ---Testcase 95: -INSERT INTO num_exp_mul VALUES (2,3,'-147998901.44836127257'); ---Testcase 96: -INSERT INTO num_exp_div VALUES (2,3,'-7967167.56737750510440835266'); ---Testcase 97: -INSERT INTO num_exp_add VALUES (2,4,'-26539030.803497047'); ---Testcase 98: -INSERT INTO num_exp_sub VALUES (2,4,'-42137953.627297047'); ---Testcase 99: -INSERT INTO num_exp_mul VALUES (2,4,'-267821744976817.8111137106593'); ---Testcase 100: -INSERT INTO num_exp_div VALUES (2,4,'-4.40267480046830116685'); ---Testcase 101: -INSERT INTO num_exp_add VALUES (2,5,'-34322095.176906047'); ---Testcase 102: -INSERT INTO num_exp_sub VALUES (2,5,'-34354889.253888047'); ---Testcase 103: -INSERT INTO num_exp_mul VALUES (2,5,'-563049578578.769242506736077'); ---Testcase 104: -INSERT INTO num_exp_div VALUES (2,5,'-2094.18866914563535496429'); ---Testcase 105: -INSERT INTO num_exp_add VALUES (2,6,'-34244590.637766787'); ---Testcase 106: -INSERT INTO num_exp_sub VALUES (2,6,'-34432393.793027307'); ---Testcase 107: -INSERT INTO num_exp_mul VALUES (2,6,'-3224438592470.18449811926184222'); ---Testcase 108: -INSERT INTO num_exp_div VALUES (2,6,'-365.68599891479766440940'); ---Testcase 109: -INSERT INTO num_exp_add VALUES (2,7,'-117366977.215397047'); ---Testcase 110: -INSERT INTO num_exp_sub VALUES (2,7,'48689992.784602953'); ---Testcase 111: -INSERT INTO num_exp_mul VALUES (2,7,'2851072985828710.485883795'); ---Testcase 112: -INSERT INTO num_exp_div VALUES (2,7,'.41357483778485235518'); ---Testcase 113: -INSERT INTO num_exp_add VALUES (2,8,'-34263611.215397047'); ---Testcase 114: -INSERT INTO num_exp_sub VALUES (2,8,'-34413373.215397047'); ---Testcase 115: -INSERT INTO num_exp_mul VALUES (2,8,'-2571300635581.146276407'); ---Testcase 116: -INSERT INTO num_exp_div VALUES (2,8,'-458.57416721727870888476'); ---Testcase 117: -INSERT INTO num_exp_add VALUES (2,9,'-59265296.260444467'); ---Testcase 118: -INSERT INTO num_exp_sub VALUES (2,9,'-9411688.170349627'); ---Testcase 119: -INSERT INTO num_exp_mul VALUES (2,9,'855948866655588.453741509242968740'); ---Testcase 120: -INSERT INTO num_exp_div VALUES (2,9,'1.37757299946438931811'); ---Testcase 121: -INSERT INTO num_exp_add VALUES (3,0,'4.31'); ---Testcase 122: -INSERT INTO num_exp_sub VALUES (3,0,'4.31'); ---Testcase 123: -INSERT INTO num_exp_mul VALUES (3,0,'0'); ---Testcase 124: -INSERT INTO num_exp_div VALUES (3,0,'NaN'); ---Testcase 125: -INSERT INTO num_exp_add VALUES (3,1,'4.31'); ---Testcase 126: -INSERT INTO num_exp_sub VALUES (3,1,'4.31'); ---Testcase 127: -INSERT INTO num_exp_mul VALUES (3,1,'0'); ---Testcase 128: -INSERT INTO num_exp_div VALUES (3,1,'NaN'); ---Testcase 129: -INSERT INTO num_exp_add VALUES (3,2,'-34338487.905397047'); ---Testcase 130: -INSERT INTO num_exp_sub VALUES (3,2,'34338496.525397047'); ---Testcase 131: -INSERT INTO num_exp_mul VALUES (3,2,'-147998901.44836127257'); ---Testcase 132: -INSERT INTO num_exp_div VALUES (3,2,'-.00000012551512084352'); ---Testcase 133: -INSERT INTO num_exp_add VALUES (3,3,'8.62'); ---Testcase 134: -INSERT INTO num_exp_sub VALUES (3,3,'0'); ---Testcase 135: -INSERT INTO num_exp_mul VALUES (3,3,'18.5761'); ---Testcase 136: -INSERT INTO num_exp_div VALUES (3,3,'1.00000000000000000000'); ---Testcase 137: -INSERT INTO num_exp_add VALUES (3,4,'7799465.7219'); ---Testcase 138: -INSERT INTO num_exp_sub VALUES (3,4,'-7799457.1019'); ---Testcase 139: -INSERT INTO num_exp_mul VALUES (3,4,'33615678.685289'); ---Testcase 140: -INSERT INTO num_exp_div VALUES (3,4,'.00000055260225961552'); ---Testcase 141: -INSERT INTO num_exp_add VALUES (3,5,'16401.348491'); ---Testcase 142: -INSERT INTO num_exp_sub VALUES (3,5,'-16392.728491'); ---Testcase 143: -INSERT INTO num_exp_mul VALUES (3,5,'70671.23589621'); ---Testcase 144: -INSERT INTO num_exp_div VALUES (3,5,'.00026285234387695504'); ---Testcase 145: -INSERT INTO num_exp_add VALUES (3,6,'93905.88763026'); ---Testcase 146: -INSERT INTO num_exp_sub VALUES (3,6,'-93897.26763026'); ---Testcase 147: -INSERT INTO num_exp_mul VALUES (3,6,'404715.7995864206'); ---Testcase 148: -INSERT INTO num_exp_div VALUES (3,6,'.00004589912234457595'); ---Testcase 149: -INSERT INTO num_exp_add VALUES (3,7,'-83028480.69'); ---Testcase 150: -INSERT INTO num_exp_sub VALUES (3,7,'83028489.31'); ---Testcase 151: -INSERT INTO num_exp_mul VALUES (3,7,'-357852770.35'); ---Testcase 152: -INSERT INTO num_exp_div VALUES (3,7,'-.00000005190989574240'); ---Testcase 153: -INSERT INTO num_exp_add VALUES (3,8,'74885.31'); ---Testcase 154: -INSERT INTO num_exp_sub VALUES (3,8,'-74876.69'); ---Testcase 155: -INSERT INTO num_exp_mul VALUES (3,8,'322737.11'); ---Testcase 156: -INSERT INTO num_exp_div VALUES (3,8,'.00005755799201399553'); ---Testcase 157: -INSERT INTO num_exp_add VALUES (3,9,'-24926799.735047420'); ---Testcase 158: -INSERT INTO num_exp_sub VALUES (3,9,'24926808.355047420'); ---Testcase 159: -INSERT INTO num_exp_mul VALUES (3,9,'-107434525.43415438020'); ---Testcase 160: -INSERT INTO num_exp_div VALUES (3,9,'-.00000017290624149854'); ---Testcase 161: -INSERT INTO num_exp_add VALUES (4,0,'7799461.4119'); ---Testcase 162: -INSERT INTO num_exp_sub VALUES (4,0,'7799461.4119'); ---Testcase 163: -INSERT INTO num_exp_mul VALUES (4,0,'0'); ---Testcase 164: -INSERT INTO num_exp_div VALUES (4,0,'NaN'); ---Testcase 165: -INSERT INTO num_exp_add VALUES (4,1,'7799461.4119'); ---Testcase 166: -INSERT INTO num_exp_sub VALUES (4,1,'7799461.4119'); ---Testcase 167: -INSERT INTO num_exp_mul VALUES (4,1,'0'); ---Testcase 168: -INSERT INTO num_exp_div VALUES (4,1,'NaN'); ---Testcase 169: -INSERT INTO num_exp_add VALUES (4,2,'-26539030.803497047'); ---Testcase 170: -INSERT INTO num_exp_sub VALUES (4,2,'42137953.627297047'); ---Testcase 171: -INSERT INTO num_exp_mul VALUES (4,2,'-267821744976817.8111137106593'); ---Testcase 172: -INSERT INTO num_exp_div VALUES (4,2,'-.22713465002993920385'); ---Testcase 173: -INSERT INTO num_exp_add VALUES (4,3,'7799465.7219'); ---Testcase 174: -INSERT INTO num_exp_sub VALUES (4,3,'7799457.1019'); ---Testcase 175: -INSERT INTO num_exp_mul VALUES (4,3,'33615678.685289'); ---Testcase 176: -INSERT INTO num_exp_div VALUES (4,3,'1809619.81714617169373549883'); ---Testcase 177: -INSERT INTO num_exp_add VALUES (4,4,'15598922.8238'); ---Testcase 178: -INSERT INTO num_exp_sub VALUES (4,4,'0'); ---Testcase 179: -INSERT INTO num_exp_mul VALUES (4,4,'60831598315717.14146161'); ---Testcase 180: -INSERT INTO num_exp_div VALUES (4,4,'1.00000000000000000000'); ---Testcase 181: -INSERT INTO num_exp_add VALUES (4,5,'7815858.450391'); ---Testcase 182: -INSERT INTO num_exp_sub VALUES (4,5,'7783064.373409'); ---Testcase 183: -INSERT INTO num_exp_mul VALUES (4,5,'127888068979.9935054429'); ---Testcase 184: -INSERT INTO num_exp_div VALUES (4,5,'475.66281046305802686061'); ---Testcase 185: -INSERT INTO num_exp_add VALUES (4,6,'7893362.98953026'); ---Testcase 186: -INSERT INTO num_exp_sub VALUES (4,6,'7705559.83426974'); ---Testcase 187: -INSERT INTO num_exp_mul VALUES (4,6,'732381731243.745115764094'); ---Testcase 188: -INSERT INTO num_exp_div VALUES (4,6,'83.05996138436129499606'); ---Testcase 189: -INSERT INTO num_exp_add VALUES (4,7,'-75229023.5881'); ---Testcase 190: -INSERT INTO num_exp_sub VALUES (4,7,'90827946.4119'); ---Testcase 191: -INSERT INTO num_exp_mul VALUES (4,7,'-647577464846017.9715'); ---Testcase 192: -INSERT INTO num_exp_div VALUES (4,7,'-.09393717604145131637'); ---Testcase 193: -INSERT INTO num_exp_add VALUES (4,8,'7874342.4119'); ---Testcase 194: -INSERT INTO num_exp_sub VALUES (4,8,'7724580.4119'); ---Testcase 195: -INSERT INTO num_exp_mul VALUES (4,8,'584031469984.4839'); ---Testcase 196: -INSERT INTO num_exp_div VALUES (4,8,'104.15808298366741897143'); ---Testcase 197: -INSERT INTO num_exp_add VALUES (4,9,'-17127342.633147420'); ---Testcase 198: -INSERT INTO num_exp_sub VALUES (4,9,'32726265.456947420'); ---Testcase 199: -INSERT INTO num_exp_mul VALUES (4,9,'-194415646271340.1815956522980'); ---Testcase 200: -INSERT INTO num_exp_div VALUES (4,9,'-.31289456112403769409'); ---Testcase 201: -INSERT INTO num_exp_add VALUES (5,0,'16397.038491'); ---Testcase 202: -INSERT INTO num_exp_sub VALUES (5,0,'16397.038491'); ---Testcase 203: -INSERT INTO num_exp_mul VALUES (5,0,'0'); ---Testcase 204: -INSERT INTO num_exp_div VALUES (5,0,'NaN'); ---Testcase 205: -INSERT INTO num_exp_add VALUES (5,1,'16397.038491'); ---Testcase 206: -INSERT INTO num_exp_sub VALUES (5,1,'16397.038491'); ---Testcase 207: -INSERT INTO num_exp_mul VALUES (5,1,'0'); ---Testcase 208: -INSERT INTO num_exp_div VALUES (5,1,'NaN'); ---Testcase 209: -INSERT INTO num_exp_add VALUES (5,2,'-34322095.176906047'); ---Testcase 210: -INSERT INTO num_exp_sub VALUES (5,2,'34354889.253888047'); ---Testcase 211: -INSERT INTO num_exp_mul VALUES (5,2,'-563049578578.769242506736077'); ---Testcase 212: -INSERT INTO num_exp_div VALUES (5,2,'-.00047751189505192446'); ---Testcase 213: -INSERT INTO num_exp_add VALUES (5,3,'16401.348491'); ---Testcase 214: -INSERT INTO num_exp_sub VALUES (5,3,'16392.728491'); ---Testcase 215: -INSERT INTO num_exp_mul VALUES (5,3,'70671.23589621'); ---Testcase 216: -INSERT INTO num_exp_div VALUES (5,3,'3804.41728329466357308584'); ---Testcase 217: -INSERT INTO num_exp_add VALUES (5,4,'7815858.450391'); ---Testcase 218: -INSERT INTO num_exp_sub VALUES (5,4,'-7783064.373409'); ---Testcase 219: -INSERT INTO num_exp_mul VALUES (5,4,'127888068979.9935054429'); ---Testcase 220: -INSERT INTO num_exp_div VALUES (5,4,'.00210232958726897192'); ---Testcase 221: -INSERT INTO num_exp_add VALUES (5,5,'32794.076982'); ---Testcase 222: -INSERT INTO num_exp_sub VALUES (5,5,'0'); ---Testcase 223: -INSERT INTO num_exp_mul VALUES (5,5,'268862871.275335557081'); ---Testcase 224: -INSERT INTO num_exp_div VALUES (5,5,'1.00000000000000000000'); ---Testcase 225: -INSERT INTO num_exp_add VALUES (5,6,'110298.61612126'); ---Testcase 226: -INSERT INTO num_exp_sub VALUES (5,6,'-77504.53913926'); ---Testcase 227: -INSERT INTO num_exp_mul VALUES (5,6,'1539707782.76899778633766'); ---Testcase 228: -INSERT INTO num_exp_div VALUES (5,6,'.17461941433576102689'); ---Testcase 229: -INSERT INTO num_exp_add VALUES (5,7,'-83012087.961509'); ---Testcase 230: -INSERT INTO num_exp_sub VALUES (5,7,'83044882.038491'); ---Testcase 231: -INSERT INTO num_exp_mul VALUES (5,7,'-1361421264394.416135'); ---Testcase 232: -INSERT INTO num_exp_div VALUES (5,7,'-.00019748690453643710'); ---Testcase 233: -INSERT INTO num_exp_add VALUES (5,8,'91278.038491'); ---Testcase 234: -INSERT INTO num_exp_sub VALUES (5,8,'-58483.961509'); ---Testcase 235: -INSERT INTO num_exp_mul VALUES (5,8,'1227826639.244571'); ---Testcase 236: -INSERT INTO num_exp_div VALUES (5,8,'.21897461960978085228'); ---Testcase 237: -INSERT INTO num_exp_add VALUES (5,9,'-24910407.006556420'); ---Testcase 238: -INSERT INTO num_exp_sub VALUES (5,9,'24943201.083538420'); ---Testcase 239: -INSERT INTO num_exp_mul VALUES (5,9,'-408725765384.257043660243220'); ---Testcase 240: -INSERT INTO num_exp_div VALUES (5,9,'-.00065780749354660427'); ---Testcase 241: -INSERT INTO num_exp_add VALUES (6,0,'93901.57763026'); ---Testcase 242: -INSERT INTO num_exp_sub VALUES (6,0,'93901.57763026'); ---Testcase 243: -INSERT INTO num_exp_mul VALUES (6,0,'0'); ---Testcase 244: -INSERT INTO num_exp_div VALUES (6,0,'NaN'); ---Testcase 245: -INSERT INTO num_exp_add VALUES (6,1,'93901.57763026'); ---Testcase 246: -INSERT INTO num_exp_sub VALUES (6,1,'93901.57763026'); ---Testcase 247: -INSERT INTO num_exp_mul VALUES (6,1,'0'); ---Testcase 248: -INSERT INTO num_exp_div VALUES (6,1,'NaN'); ---Testcase 249: -INSERT INTO num_exp_add VALUES (6,2,'-34244590.637766787'); ---Testcase 250: -INSERT INTO num_exp_sub VALUES (6,2,'34432393.793027307'); ---Testcase 251: -INSERT INTO num_exp_mul VALUES (6,2,'-3224438592470.18449811926184222'); ---Testcase 252: -INSERT INTO num_exp_div VALUES (6,2,'-.00273458651128995823'); ---Testcase 253: -INSERT INTO num_exp_add VALUES (6,3,'93905.88763026'); ---Testcase 254: -INSERT INTO num_exp_sub VALUES (6,3,'93897.26763026'); ---Testcase 255: -INSERT INTO num_exp_mul VALUES (6,3,'404715.7995864206'); ---Testcase 256: -INSERT INTO num_exp_div VALUES (6,3,'21786.90896293735498839907'); ---Testcase 257: -INSERT INTO num_exp_add VALUES (6,4,'7893362.98953026'); ---Testcase 258: -INSERT INTO num_exp_sub VALUES (6,4,'-7705559.83426974'); ---Testcase 259: -INSERT INTO num_exp_mul VALUES (6,4,'732381731243.745115764094'); ---Testcase 260: -INSERT INTO num_exp_div VALUES (6,4,'.01203949512295682469'); ---Testcase 261: -INSERT INTO num_exp_add VALUES (6,5,'110298.61612126'); ---Testcase 262: -INSERT INTO num_exp_sub VALUES (6,5,'77504.53913926'); ---Testcase 263: -INSERT INTO num_exp_mul VALUES (6,5,'1539707782.76899778633766'); ---Testcase 264: -INSERT INTO num_exp_div VALUES (6,5,'5.72674008674192359679'); ---Testcase 265: -INSERT INTO num_exp_add VALUES (6,6,'187803.15526052'); ---Testcase 266: -INSERT INTO num_exp_sub VALUES (6,6,'0'); ---Testcase 267: -INSERT INTO num_exp_mul VALUES (6,6,'8817506281.4517452372676676'); ---Testcase 268: -INSERT INTO num_exp_div VALUES (6,6,'1.00000000000000000000'); ---Testcase 269: -INSERT INTO num_exp_add VALUES (6,7,'-82934583.42236974'); ---Testcase 270: -INSERT INTO num_exp_sub VALUES (6,7,'83122386.57763026'); ---Testcase 271: -INSERT INTO num_exp_mul VALUES (6,7,'-7796505729750.37795610'); ---Testcase 272: -INSERT INTO num_exp_div VALUES (6,7,'-.00113095617281538980'); ---Testcase 273: -INSERT INTO num_exp_add VALUES (6,8,'168782.57763026'); ---Testcase 274: -INSERT INTO num_exp_sub VALUES (6,8,'19020.57763026'); ---Testcase 275: -INSERT INTO num_exp_mul VALUES (6,8,'7031444034.53149906'); ---Testcase 276: -INSERT INTO num_exp_div VALUES (6,8,'1.25401073209839612184'); ---Testcase 277: -INSERT INTO num_exp_add VALUES (6,9,'-24832902.467417160'); ---Testcase 278: -INSERT INTO num_exp_sub VALUES (6,9,'25020705.622677680'); ---Testcase 279: -INSERT INTO num_exp_mul VALUES (6,9,'-2340666225110.29929521292692920'); ---Testcase 280: -INSERT INTO num_exp_div VALUES (6,9,'-.00376709254265256789'); ---Testcase 281: -INSERT INTO num_exp_add VALUES (7,0,'-83028485'); ---Testcase 282: -INSERT INTO num_exp_sub VALUES (7,0,'-83028485'); ---Testcase 283: -INSERT INTO num_exp_mul VALUES (7,0,'0'); ---Testcase 284: -INSERT INTO num_exp_div VALUES (7,0,'NaN'); ---Testcase 285: -INSERT INTO num_exp_add VALUES (7,1,'-83028485'); ---Testcase 286: -INSERT INTO num_exp_sub VALUES (7,1,'-83028485'); ---Testcase 287: -INSERT INTO num_exp_mul VALUES (7,1,'0'); ---Testcase 288: -INSERT INTO num_exp_div VALUES (7,1,'NaN'); ---Testcase 289: -INSERT INTO num_exp_add VALUES (7,2,'-117366977.215397047'); ---Testcase 290: -INSERT INTO num_exp_sub VALUES (7,2,'-48689992.784602953'); ---Testcase 291: -INSERT INTO num_exp_mul VALUES (7,2,'2851072985828710.485883795'); ---Testcase 292: -INSERT INTO num_exp_div VALUES (7,2,'2.41794207151503385700'); ---Testcase 293: -INSERT INTO num_exp_add VALUES (7,3,'-83028480.69'); ---Testcase 294: -INSERT INTO num_exp_sub VALUES (7,3,'-83028489.31'); ---Testcase 295: -INSERT INTO num_exp_mul VALUES (7,3,'-357852770.35'); ---Testcase 296: -INSERT INTO num_exp_div VALUES (7,3,'-19264149.65197215777262180974'); ---Testcase 297: -INSERT INTO num_exp_add VALUES (7,4,'-75229023.5881'); ---Testcase 298: -INSERT INTO num_exp_sub VALUES (7,4,'-90827946.4119'); ---Testcase 299: -INSERT INTO num_exp_mul VALUES (7,4,'-647577464846017.9715'); ---Testcase 300: -INSERT INTO num_exp_div VALUES (7,4,'-10.64541262725136247686'); ---Testcase 301: -INSERT INTO num_exp_add VALUES (7,5,'-83012087.961509'); ---Testcase 302: -INSERT INTO num_exp_sub VALUES (7,5,'-83044882.038491'); ---Testcase 303: -INSERT INTO num_exp_mul VALUES (7,5,'-1361421264394.416135'); ---Testcase 304: -INSERT INTO num_exp_div VALUES (7,5,'-5063.62688881730941836574'); ---Testcase 305: -INSERT INTO num_exp_add VALUES (7,6,'-82934583.42236974'); ---Testcase 306: -INSERT INTO num_exp_sub VALUES (7,6,'-83122386.57763026'); ---Testcase 307: -INSERT INTO num_exp_mul VALUES (7,6,'-7796505729750.37795610'); ---Testcase 308: -INSERT INTO num_exp_div VALUES (7,6,'-884.20756174009028770294'); ---Testcase 309: -INSERT INTO num_exp_add VALUES (7,7,'-166056970'); ---Testcase 310: -INSERT INTO num_exp_sub VALUES (7,7,'0'); ---Testcase 311: -INSERT INTO num_exp_mul VALUES (7,7,'6893729321395225'); ---Testcase 312: -INSERT INTO num_exp_div VALUES (7,7,'1.00000000000000000000'); ---Testcase 313: -INSERT INTO num_exp_add VALUES (7,8,'-82953604'); ---Testcase 314: -INSERT INTO num_exp_sub VALUES (7,8,'-83103366'); ---Testcase 315: -INSERT INTO num_exp_mul VALUES (7,8,'-6217255985285'); ---Testcase 316: -INSERT INTO num_exp_div VALUES (7,8,'-1108.80577182462841041118'); ---Testcase 317: -INSERT INTO num_exp_add VALUES (7,9,'-107955289.045047420'); ---Testcase 318: -INSERT INTO num_exp_sub VALUES (7,9,'-58101680.954952580'); ---Testcase 319: -INSERT INTO num_exp_mul VALUES (7,9,'2069634775752159.035758700'); ---Testcase 320: -INSERT INTO num_exp_div VALUES (7,9,'3.33089171198810413382'); ---Testcase 321: -INSERT INTO num_exp_add VALUES (8,0,'74881'); ---Testcase 322: -INSERT INTO num_exp_sub VALUES (8,0,'74881'); ---Testcase 323: -INSERT INTO num_exp_mul VALUES (8,0,'0'); ---Testcase 324: -INSERT INTO num_exp_div VALUES (8,0,'NaN'); ---Testcase 325: -INSERT INTO num_exp_add VALUES (8,1,'74881'); ---Testcase 326: -INSERT INTO num_exp_sub VALUES (8,1,'74881'); ---Testcase 327: -INSERT INTO num_exp_mul VALUES (8,1,'0'); ---Testcase 328: -INSERT INTO num_exp_div VALUES (8,1,'NaN'); ---Testcase 329: -INSERT INTO num_exp_add VALUES (8,2,'-34263611.215397047'); ---Testcase 330: -INSERT INTO num_exp_sub VALUES (8,2,'34413373.215397047'); ---Testcase 331: -INSERT INTO num_exp_mul VALUES (8,2,'-2571300635581.146276407'); ---Testcase 332: -INSERT INTO num_exp_div VALUES (8,2,'-.00218067233500788615'); ---Testcase 333: -INSERT INTO num_exp_add VALUES (8,3,'74885.31'); ---Testcase 334: -INSERT INTO num_exp_sub VALUES (8,3,'74876.69'); ---Testcase 335: -INSERT INTO num_exp_mul VALUES (8,3,'322737.11'); ---Testcase 336: -INSERT INTO num_exp_div VALUES (8,3,'17373.78190255220417633410'); ---Testcase 337: -INSERT INTO num_exp_add VALUES (8,4,'7874342.4119'); ---Testcase 338: -INSERT INTO num_exp_sub VALUES (8,4,'-7724580.4119'); ---Testcase 339: -INSERT INTO num_exp_mul VALUES (8,4,'584031469984.4839'); ---Testcase 340: -INSERT INTO num_exp_div VALUES (8,4,'.00960079113741758956'); ---Testcase 341: -INSERT INTO num_exp_add VALUES (8,5,'91278.038491'); ---Testcase 342: -INSERT INTO num_exp_sub VALUES (8,5,'58483.961509'); ---Testcase 343: -INSERT INTO num_exp_mul VALUES (8,5,'1227826639.244571'); ---Testcase 344: -INSERT INTO num_exp_div VALUES (8,5,'4.56673929509287019456'); ---Testcase 345: -INSERT INTO num_exp_add VALUES (8,6,'168782.57763026'); ---Testcase 346: -INSERT INTO num_exp_sub VALUES (8,6,'-19020.57763026'); ---Testcase 347: -INSERT INTO num_exp_mul VALUES (8,6,'7031444034.53149906'); ---Testcase 348: -INSERT INTO num_exp_div VALUES (8,6,'.79744134113322314424'); ---Testcase 349: -INSERT INTO num_exp_add VALUES (8,7,'-82953604'); ---Testcase 350: -INSERT INTO num_exp_sub VALUES (8,7,'83103366'); ---Testcase 351: -INSERT INTO num_exp_mul VALUES (8,7,'-6217255985285'); ---Testcase 352: -INSERT INTO num_exp_div VALUES (8,7,'-.00090187120721280172'); ---Testcase 353: -INSERT INTO num_exp_add VALUES (8,8,'149762'); ---Testcase 354: -INSERT INTO num_exp_sub VALUES (8,8,'0'); ---Testcase 355: -INSERT INTO num_exp_mul VALUES (8,8,'5607164161'); ---Testcase 356: -INSERT INTO num_exp_div VALUES (8,8,'1.00000000000000000000'); ---Testcase 357: -INSERT INTO num_exp_add VALUES (8,9,'-24851923.045047420'); ---Testcase 358: -INSERT INTO num_exp_sub VALUES (8,9,'25001685.045047420'); ---Testcase 359: -INSERT INTO num_exp_mul VALUES (8,9,'-1866544013697.195857020'); ---Testcase 360: -INSERT INTO num_exp_div VALUES (8,9,'-.00300403532938582735'); ---Testcase 361: -INSERT INTO num_exp_add VALUES (9,0,'-24926804.045047420'); ---Testcase 362: -INSERT INTO num_exp_sub VALUES (9,0,'-24926804.045047420'); ---Testcase 363: -INSERT INTO num_exp_mul VALUES (9,0,'0'); ---Testcase 364: -INSERT INTO num_exp_div VALUES (9,0,'NaN'); ---Testcase 365: -INSERT INTO num_exp_add VALUES (9,1,'-24926804.045047420'); ---Testcase 366: -INSERT INTO num_exp_sub VALUES (9,1,'-24926804.045047420'); ---Testcase 367: -INSERT INTO num_exp_mul VALUES (9,1,'0'); ---Testcase 368: -INSERT INTO num_exp_div VALUES (9,1,'NaN'); ---Testcase 369: -INSERT INTO num_exp_add VALUES (9,2,'-59265296.260444467'); ---Testcase 370: -INSERT INTO num_exp_sub VALUES (9,2,'9411688.170349627'); ---Testcase 371: -INSERT INTO num_exp_mul VALUES (9,2,'855948866655588.453741509242968740'); ---Testcase 372: -INSERT INTO num_exp_div VALUES (9,2,'.72591434384152961526'); ---Testcase 373: -INSERT INTO num_exp_add VALUES (9,3,'-24926799.735047420'); ---Testcase 374: -INSERT INTO num_exp_sub VALUES (9,3,'-24926808.355047420'); ---Testcase 375: -INSERT INTO num_exp_mul VALUES (9,3,'-107434525.43415438020'); ---Testcase 376: -INSERT INTO num_exp_div VALUES (9,3,'-5783481.21694835730858468677'); ---Testcase 377: -INSERT INTO num_exp_add VALUES (9,4,'-17127342.633147420'); ---Testcase 378: -INSERT INTO num_exp_sub VALUES (9,4,'-32726265.456947420'); ---Testcase 379: -INSERT INTO num_exp_mul VALUES (9,4,'-194415646271340.1815956522980'); ---Testcase 380: -INSERT INTO num_exp_div VALUES (9,4,'-3.19596478892958416484'); ---Testcase 381: -INSERT INTO num_exp_add VALUES (9,5,'-24910407.006556420'); ---Testcase 382: -INSERT INTO num_exp_sub VALUES (9,5,'-24943201.083538420'); ---Testcase 383: -INSERT INTO num_exp_mul VALUES (9,5,'-408725765384.257043660243220'); ---Testcase 384: -INSERT INTO num_exp_div VALUES (9,5,'-1520.20159364322004505807'); ---Testcase 385: -INSERT INTO num_exp_add VALUES (9,6,'-24832902.467417160'); ---Testcase 386: -INSERT INTO num_exp_sub VALUES (9,6,'-25020705.622677680'); ---Testcase 387: -INSERT INTO num_exp_mul VALUES (9,6,'-2340666225110.29929521292692920'); ---Testcase 388: -INSERT INTO num_exp_div VALUES (9,6,'-265.45671195426965751280'); ---Testcase 389: -INSERT INTO num_exp_add VALUES (9,7,'-107955289.045047420'); ---Testcase 390: -INSERT INTO num_exp_sub VALUES (9,7,'58101680.954952580'); ---Testcase 391: -INSERT INTO num_exp_mul VALUES (9,7,'2069634775752159.035758700'); ---Testcase 392: -INSERT INTO num_exp_div VALUES (9,7,'.30021990699995814689'); ---Testcase 393: -INSERT INTO num_exp_add VALUES (9,8,'-24851923.045047420'); ---Testcase 394: -INSERT INTO num_exp_sub VALUES (9,8,'-25001685.045047420'); ---Testcase 395: -INSERT INTO num_exp_mul VALUES (9,8,'-1866544013697.195857020'); ---Testcase 396: -INSERT INTO num_exp_div VALUES (9,8,'-332.88556569820675471748'); ---Testcase 397: -INSERT INTO num_exp_add VALUES (9,9,'-49853608.090094840'); ---Testcase 398: -INSERT INTO num_exp_sub VALUES (9,9,'0'); ---Testcase 399: -INSERT INTO num_exp_mul VALUES (9,9,'621345559900192.420120630048656400'); ---Testcase 400: -INSERT INTO num_exp_div VALUES (9,9,'1.00000000000000000000'); -COMMIT TRANSACTION; -BEGIN TRANSACTION; ---Testcase 401: -INSERT INTO num_exp_sqrt VALUES (0,'0'); ---Testcase 402: -INSERT INTO num_exp_sqrt VALUES (1,'0'); ---Testcase 403: -INSERT INTO num_exp_sqrt VALUES (2,'5859.90547836712524903505'); ---Testcase 404: -INSERT INTO num_exp_sqrt VALUES (3,'2.07605394920266944396'); ---Testcase 405: -INSERT INTO num_exp_sqrt VALUES (4,'2792.75158435189147418923'); ---Testcase 406: -INSERT INTO num_exp_sqrt VALUES (5,'128.05092147657509145473'); ---Testcase 407: -INSERT INTO num_exp_sqrt VALUES (6,'306.43364311096782703406'); ---Testcase 408: -INSERT INTO num_exp_sqrt VALUES (7,'9111.99676251039939975230'); ---Testcase 409: -INSERT INTO num_exp_sqrt VALUES (8,'273.64392922189960397542'); ---Testcase 410: -INSERT INTO num_exp_sqrt VALUES (9,'4992.67503899937593364766'); -COMMIT TRANSACTION; -BEGIN TRANSACTION; ---Testcase 411: -INSERT INTO num_exp_ln VALUES (0,'NaN'); ---Testcase 412: -INSERT INTO num_exp_ln VALUES (1,'NaN'); ---Testcase 413: -INSERT INTO num_exp_ln VALUES (2,'17.35177750493897715514'); ---Testcase 414: -INSERT INTO num_exp_ln VALUES (3,'1.46093790411565641971'); ---Testcase 415: -INSERT INTO num_exp_ln VALUES (4,'15.86956523951936572464'); ---Testcase 416: -INSERT INTO num_exp_ln VALUES (5,'9.70485601768871834038'); ---Testcase 417: -INSERT INTO num_exp_ln VALUES (6,'11.45000246622944403127'); ---Testcase 418: -INSERT INTO num_exp_ln VALUES (7,'18.23469429965478772991'); ---Testcase 419: -INSERT INTO num_exp_ln VALUES (8,'11.22365546576315513668'); ---Testcase 420: -INSERT INTO num_exp_ln VALUES (9,'17.03145425013166006962'); -COMMIT TRANSACTION; -BEGIN TRANSACTION; ---Testcase 421: -INSERT INTO num_exp_log10 VALUES (0,'NaN'); ---Testcase 422: -INSERT INTO num_exp_log10 VALUES (1,'NaN'); ---Testcase 423: -INSERT INTO num_exp_log10 VALUES (2,'7.53578122160797276459'); ---Testcase 424: -INSERT INTO num_exp_log10 VALUES (3,'.63447727016073160075'); ---Testcase 425: -INSERT INTO num_exp_log10 VALUES (4,'6.89206461372691743345'); ---Testcase 426: -INSERT INTO num_exp_log10 VALUES (5,'4.21476541614777768626'); ---Testcase 427: -INSERT INTO num_exp_log10 VALUES (6,'4.97267288886207207671'); ---Testcase 428: -INSERT INTO num_exp_log10 VALUES (7,'7.91922711353275546914'); ---Testcase 429: -INSERT INTO num_exp_log10 VALUES (8,'4.87437163556421004138'); ---Testcase 430: -INSERT INTO num_exp_log10 VALUES (9,'7.39666659961986567059'); -COMMIT TRANSACTION; -BEGIN TRANSACTION; ---Testcase 431: -INSERT INTO num_exp_power_10_ln VALUES (0,'NaN'); ---Testcase 432: -INSERT INTO num_exp_power_10_ln VALUES (1,'NaN'); ---Testcase 433: -INSERT INTO num_exp_power_10_ln VALUES (2,'224790267919917955.13261618583642653184'); ---Testcase 434: -INSERT INTO num_exp_power_10_ln VALUES (3,'28.90266599445155957393'); ---Testcase 435: -INSERT INTO num_exp_power_10_ln VALUES (4,'7405685069594999.07733999469386277636'); ---Testcase 436: -INSERT INTO num_exp_power_10_ln VALUES (5,'5068226527.32127265408584640098'); ---Testcase 437: -INSERT INTO num_exp_power_10_ln VALUES (6,'281839893606.99372343357047819067'); ---Testcase 438: -INSERT INTO num_exp_power_10_ln VALUES (7,'1716699575118597095.42330819910640247627'); ---Testcase 439: -INSERT INTO num_exp_power_10_ln VALUES (8,'167361463828.07491320069016125952'); ---Testcase 440: -INSERT INTO num_exp_power_10_ln VALUES (9,'107511333880052007.04141124673540337457'); -COMMIT TRANSACTION; -BEGIN TRANSACTION; ---Testcase 441: -INSERT INTO num_data VALUES (0, '0'); ---Testcase 442: -INSERT INTO num_data VALUES (1, '0'); ---Testcase 443: -INSERT INTO num_data VALUES (2, '-34338492.215397047'); ---Testcase 444: -INSERT INTO num_data VALUES (3, '4.31'); ---Testcase 445: -INSERT INTO num_data VALUES (4, '7799461.4119'); ---Testcase 446: -INSERT INTO num_data VALUES (5, '16397.038491'); ---Testcase 447: -INSERT INTO num_data VALUES (6, '93901.57763026'); ---Testcase 448: -INSERT INTO num_data VALUES (7, '-83028485'); ---Testcase 449: -INSERT INTO num_data VALUES (8, '74881'); ---Testcase 450: -INSERT INTO num_data VALUES (9, '-24926804.045047420'); -COMMIT TRANSACTION; --- ****************************** --- * Create indices for faster checks --- ****************************** --- Skip these setting, creating foreign table with primary key already covered. ---CREATE UNIQUE INDEX num_exp_add_idx ON num_exp_add (id1, id2); ---CREATE UNIQUE INDEX num_exp_sub_idx ON num_exp_sub (id1, id2); ---CREATE UNIQUE INDEX num_exp_div_idx ON num_exp_div (id1, id2); ---CREATE UNIQUE INDEX num_exp_mul_idx ON num_exp_mul (id1, id2); ---CREATE UNIQUE INDEX num_exp_sqrt_idx ON num_exp_sqrt (id); ---CREATE UNIQUE INDEX num_exp_ln_idx ON num_exp_ln (id); ---CREATE UNIQUE INDEX num_exp_log10_idx ON num_exp_log10 (id); ---CREATE UNIQUE INDEX num_exp_power_10_ln_idx ON num_exp_power_10_ln (id); ---VACUUM ANALYZE num_exp_add; ---VACUUM ANALYZE num_exp_sub; ---VACUUM ANALYZE num_exp_div; ---VACUUM ANALYZE num_exp_mul; ---VACUUM ANALYZE num_exp_sqrt; ---VACUUM ANALYZE num_exp_ln; ---VACUUM ANALYZE num_exp_log10; ---VACUUM ANALYZE num_exp_power_10_ln; --- ****************************** --- * Now check the behaviour of the NUMERIC type --- ****************************** --- ****************************** --- * Addition check --- ****************************** ---Testcase 451: -DELETE FROM num_result; ---Testcase 452: -INSERT INTO num_result SELECT t1.id, t2.id, t1.val + t2.val - FROM num_data t1, num_data t2; ---Testcase 453: -SELECT t1.id1, t1.id2, t1.result, t2.expected - FROM num_result t1, num_exp_add t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != t2.expected; - id1 | id2 | result | expected ------+-----+----------------------+---------------------- - 2 | 3 | -34338487.9053970400 | -34338487.9053970500 - 2 | 5 | -34322095.1769060400 | -34322095.1769060500 - 2 | 9 | -59265296.2604444600 | -59265296.2604444700 - 3 | 2 | -34338487.9053970400 | -34338487.9053970500 - 5 | 2 | -34322095.1769060400 | -34322095.1769060500 - 9 | 2 | -59265296.2604444600 | -59265296.2604444700 -(6 rows) - ---Testcase 454: -DELETE FROM num_result; ---Testcase 455: -INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val + t2.val, 10) - FROM num_data t1, num_data t2; ---Testcase 456: -SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 10) as expected - FROM num_result t1, num_exp_add t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != round(t2.expected, 10); - id1 | id2 | result | expected ------+-----+----------------------+---------------------- - 2 | 3 | -34338487.9053970400 | -34338487.9053970500 - 2 | 5 | -34322095.1769060400 | -34322095.1769060500 - 2 | 9 | -59265296.2604444600 | -59265296.2604444700 - 3 | 2 | -34338487.9053970400 | -34338487.9053970500 - 5 | 2 | -34322095.1769060400 | -34322095.1769060500 - 9 | 2 | -59265296.2604444600 | -59265296.2604444700 -(6 rows) - --- ****************************** --- * Subtraction check --- ****************************** ---Testcase 457: -DELETE FROM num_result; ---Testcase 458: -INSERT INTO num_result SELECT t1.id, t2.id, t1.val - t2.val - FROM num_data t1, num_data t2; ---Testcase 459: -SELECT t1.id1, t1.id2, t1.result, t2.expected - FROM num_result t1, num_exp_sub t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != t2.expected; - id1 | id2 | result | expected ------+-----+---------------------+--------------------- - 2 | 9 | -9411688.1703496260 | -9411688.1703496280 - 9 | 2 | 9411688.1703496260 | 9411688.1703496280 -(2 rows) - ---Testcase 460: -DELETE FROM num_result; ---Testcase 461: -INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val - t2.val, 40) - FROM num_data t1, num_data t2; ---Testcase 462: -SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 40) - FROM num_result t1, num_exp_sub t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != round(t2.expected, 40); - id1 | id2 | result | round ------+-----+---------------------+--------------------------------------------------- - 2 | 9 | -9411688.1703496260 | -9411688.1703496280000000000000000000000000000000 - 9 | 2 | 9411688.1703496260 | 9411688.1703496280000000000000000000000000000000 -(2 rows) - --- ****************************** --- * Multiply check --- ****************************** ---Testcase 463: -DELETE FROM num_result; ---Testcase 464: -INSERT INTO num_result SELECT t1.id, t2.id, t1.val * t2.val - FROM num_data t1, num_data t2; ---Testcase 465: -SELECT t1.id1, t1.id2, t1.result, t2.expected - FROM num_result t1, num_exp_mul t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != t2.expected; - id1 | id2 | result | expected ------+-----+-----------------------------+----------------------------- - 2 | 4 | -267821744976817.7800000000 | -267821744976817.8000000000 - 2 | 5 | -563049578578.7692000000 | -563049578578.7693000000 - 2 | 6 | -3224438592470.1840000000 | -3224438592470.1846000000 - 2 | 8 | -2571300635581.1460000000 | -2571300635581.1465000000 - 2 | 9 | 855948866655588.4000000000 | 855948866655588.5000000000 - 4 | 2 | -267821744976817.7800000000 | -267821744976817.8000000000 - 5 | 2 | -563049578578.7692000000 | -563049578578.7693000000 - 6 | 2 | -3224438592470.1840000000 | -3224438592470.1846000000 - 8 | 2 | -2571300635581.1460000000 | -2571300635581.1465000000 - 9 | 2 | 855948866655588.4000000000 | 855948866655588.5000000000 -(10 rows) - ---Testcase 466: -DELETE FROM num_result; ---Testcase 467: -INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val * t2.val, 30) - FROM num_data t1, num_data t2; ---Testcase 468: -SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 30) as expected - FROM num_result t1, num_exp_mul t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != round(t2.expected, 30); - id1 | id2 | result | expected ------+-----+-----------------------------+------------------------------------------------- - 2 | 4 | -267821744976817.7800000000 | -267821744976817.800000000000000000000000000000 - 2 | 5 | -563049578578.7692000000 | -563049578578.769300000000000000000000000000 - 2 | 6 | -3224438592470.1840000000 | -3224438592470.184600000000000000000000000000 - 2 | 8 | -2571300635581.1460000000 | -2571300635581.146500000000000000000000000000 - 2 | 9 | 855948866655588.4000000000 | 855948866655588.500000000000000000000000000000 - 4 | 2 | -267821744976817.7800000000 | -267821744976817.800000000000000000000000000000 - 5 | 2 | -563049578578.7692000000 | -563049578578.769300000000000000000000000000 - 6 | 2 | -3224438592470.1840000000 | -3224438592470.184600000000000000000000000000 - 8 | 2 | -2571300635581.1460000000 | -2571300635581.146500000000000000000000000000 - 9 | 2 | 855948866655588.4000000000 | 855948866655588.500000000000000000000000000000 -(10 rows) - --- ****************************** --- * Division check --- ****************************** ---Testcase 469: -DELETE FROM num_result; ---Testcase 470: -INSERT INTO num_result SELECT t1.id, t2.id, t1.val / t2.val - FROM num_data t1, num_data t2 - WHERE t2.val != '0.0'; ---Testcase 471: -SELECT t1.id1, t1.id2, t1.result, t2.expected - FROM num_result t1, num_exp_div t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != t2.expected; - id1 | id2 | result | expected ------+-----+--------+---------- -(0 rows) - ---Testcase 472: -DELETE FROM num_result; ---Testcase 473: -INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val / t2.val, 80) - FROM num_data t1, num_data t2 - WHERE t2.val != '0.0'; ---Testcase 474: -SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 80) as expected - FROM num_result t1, num_exp_div t2 - WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 - AND t1.result != round(t2.expected, 80); - id1 | id2 | result | expected ------+-----+--------+---------- -(0 rows) - --- ****************************** --- * Square root check --- ****************************** ---Testcase 475: -DELETE FROM num_result; ---Testcase 476: -INSERT INTO num_result SELECT id, 0, SQRT(ABS(val)) - FROM num_data; ---Testcase 477: -SELECT t1.id1, t1.result, t2.expected - FROM num_result t1, num_exp_sqrt t2 - WHERE t1.id1 = t2.id - AND t1.result != t2.expected; - id1 | result | expected ------+--------+---------- -(0 rows) - --- ****************************** --- * Natural logarithm check --- ****************************** ---Testcase 478: -DELETE FROM num_result; ---Testcase 479: -INSERT INTO num_result SELECT id, 0, LN(ABS(val)) - FROM num_data - WHERE val != '0.0'; ---Testcase 480: -SELECT t1.id1, t1.result, t2.expected - FROM num_result t1, num_exp_ln t2 - WHERE t1.id1 = t2.id - AND t1.result != t2.expected; - id1 | result | expected ------+--------+---------- -(0 rows) - --- ****************************** --- * Logarithm base 10 check --- ****************************** ---Testcase 481: -DELETE FROM num_result; ---Testcase 482: -INSERT INTO num_result SELECT id, 0, LOG(numeric '10', ABS(val)) - FROM num_data - WHERE val != '0.0'; ---Testcase 483: -SELECT t1.id1, t1.result, t2.expected - FROM num_result t1, num_exp_log10 t2 - WHERE t1.id1 = t2.id - AND t1.result != t2.expected; - id1 | result | expected ------+--------+---------- -(0 rows) - --- ****************************** --- * POWER(10, LN(value)) check --- ****************************** ---Testcase 484: -DELETE FROM num_result; ---Testcase 485: -INSERT INTO num_result SELECT id, 0, POWER(numeric '10', LN(ABS(round(val,200)))) - FROM num_data - WHERE val != '0.0'; ---Testcase 486: -SELECT t1.id1, t1.result, t2.expected - FROM num_result t1, num_exp_power_10_ln t2 - WHERE t1.id1 = t2.id - AND t1.result != t2.expected; - id1 | result | expected ------+-------------------------------+------------------------------- - 2 | 224790267919917920.0000000000 | 224790267919917950.0000000000 -(1 row) - --- ****************************** --- * miscellaneous checks for things that have been broken in the past... --- ****************************** --- numeric AVG used to fail on some platforms ---Testcase 487: -SELECT AVG(val) FROM num_data; - avg ---------------------- - -13430913.592242321 -(1 row) - ---Testcase 488: -SELECT STDDEV(val) FROM num_data; - stddev -------------------------------- - 27791203.28758835313087634596 -(1 row) - ---Testcase 489: -SELECT VARIANCE(val) FROM num_data; - variance --------------------------------------- - 772350980172061.68729880105331209139 -(1 row) - --- Check for appropriate rounding and overflow ---Testcase 579: -CREATE FOREIGN TABLE fract_only (id int, val numeric(4,4)) SERVER sqlite_svr; ---Testcase 490: -INSERT INTO fract_only VALUES (1, '0.0'); ---Testcase 491: -INSERT INTO fract_only VALUES (2, '0.1'); ---Testcase 492: -INSERT INTO fract_only VALUES (3, '1.0'); -- should fail -ERROR: numeric field overflow -DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. ---Testcase 493: -INSERT INTO fract_only VALUES (4, '-0.9999'); ---Testcase 494: -INSERT INTO fract_only VALUES (5, '0.99994'); ---Testcase 495: -INSERT INTO fract_only VALUES (6, '0.99995'); -- should fail -ERROR: numeric field overflow -DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. ---Testcase 496: -INSERT INTO fract_only VALUES (7, '0.00001'); ---Testcase 497: -INSERT INTO fract_only VALUES (8, '0.00017'); ---Testcase 498: -SELECT * FROM fract_only; - id | val -----+--------- - 1 | 0.0000 - 2 | 0.1000 - 4 | -0.9999 - 5 | 0.9999 - 7 | 0.0000 - 8 | 0.0002 -(6 rows) - ---Testcase 580: -DROP FOREIGN TABLE fract_only; --- Check inf/nan conversion behavior ---Testcase 581: -CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, f2 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 582: -DELETE FROM FLOAT8_TMP; ---Testcase 583: -INSERT INTO FLOAT8_TMP VALUES ('NaN'); ---Testcase 584: -SELECT f1::numeric FROM FLOAT8_TMP; - f1 ----- - -(1 row) - ---Testcase 585: -DELETE FROM FLOAT8_TMP; ---Testcase 586: -INSERT INTO FLOAT8_TMP VALUES ('Infinity'); ---Testcase 587: -SELECT f1::numeric FROM FLOAT8_TMP; -ERROR: cannot convert infinity to numeric ---Testcase 588: -DELETE FROM FLOAT8_TMP; ---Testcase 589: -INSERT INTO FLOAT8_TMP VALUES ('-Infinity'); ---Testcase 590: -SELECT f1::numeric FROM FLOAT8_TMP; -ERROR: cannot convert infinity to numeric ---Testcase 591: -CREATE FOREIGN TABLE FLOAT4_TMP(f1 float4, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 592: -DELETE FROM FLOAT4_TMP; ---Testcase 593: -INSERT INTO FLOAT4_TMP VALUES ('NaN'); ---Testcase 594: -SELECT f1::numeric FROM FLOAT4_TMP; - f1 ----- - -(1 row) - ---Testcase 595: -DELETE FROM FLOAT4_TMP; ---Testcase 596: -INSERT INTO FLOAT4_TMP VALUES ('Infinity'); ---Testcase 597: -SELECT f1::numeric FROM FLOAT4_TMP; -ERROR: cannot convert infinity to numeric ---Testcase 598: -DELETE FROM FLOAT4_TMP; ---Testcase 599: -INSERT INTO FLOAT4_TMP VALUES ('-Infinity'); ---Testcase 600: -SELECT f1::numeric FROM FLOAT4_TMP; -ERROR: cannot convert infinity to numeric --- Simple check that ceil(), floor(), and round() work correctly ---Testcase 601: -CREATE FOREIGN TABLE ceil_floor_round (a numeric OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 499: -INSERT INTO ceil_floor_round VALUES ('-5.5'); ---Testcase 500: -INSERT INTO ceil_floor_round VALUES ('-5.499999'); ---Testcase 501: -INSERT INTO ceil_floor_round VALUES ('9.5'); ---Testcase 502: -INSERT INTO ceil_floor_round VALUES ('9.4999999'); ---Testcase 503: -INSERT INTO ceil_floor_round VALUES ('0.0'); ---Testcase 504: -INSERT INTO ceil_floor_round VALUES ('0.0000001'); ---Testcase 505: -INSERT INTO ceil_floor_round VALUES ('-0.000001'); ---Testcase 506: -SELECT a, ceil(a), ceiling(a), floor(a), round(a) FROM ceil_floor_round ORDER BY a; - a | ceil | ceiling | floor | round ------------+------+---------+-------+------- - -5.5 | -5 | -5 | -6 | -6 - -5.499999 | -5 | -5 | -6 | -5 - -0.000001 | 0 | 0 | -1 | 0 - 0 | 0 | 0 | 0 | 0 - 0.0000001 | 1 | 1 | 0 | 0 - 9.4999999 | 10 | 10 | 9 | 9 - 9.5 | 10 | 10 | 9 | 10 -(7 rows) - --- Check rounding, it should round ties away from zero. ---Testcase 602: -CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 603: -DELETE FROM INT4_TMP; ---Testcase 604: -INSERT INTO INT4_TMP SELECT a FROM generate_series(-5,5) a; ---Testcase 605: -SELECT f1 as pow, - round((-2.5 * 10 ^ f1)::numeric, -f1), - round((-1.5 * 10 ^ f1)::numeric, -f1), - round((-0.5 * 10 ^ f1)::numeric, -f1), - round((0.5 * 10 ^ f1)::numeric, -f1), - round((1.5 * 10 ^ f1)::numeric, -f1), - round((2.5 * 10 ^ f1)::numeric, -f1) -FROM INT4_TMP; - pow | round | round | round | round | round | round ------+----------+----------+----------+---------+---------+--------- - -5 | -0.00003 | -0.00002 | -0.00001 | 0.00001 | 0.00002 | 0.00003 - -4 | -0.0003 | -0.0002 | -0.0001 | 0.0001 | 0.0002 | 0.0003 - -3 | -0.003 | -0.002 | -0.001 | 0.001 | 0.002 | 0.003 - -2 | -0.03 | -0.02 | -0.01 | 0.01 | 0.02 | 0.03 - -1 | -0.3 | -0.2 | -0.1 | 0.1 | 0.2 | 0.3 - 0 | -3 | -2 | -1 | 1 | 2 | 3 - 1 | -30 | -20 | -10 | 10 | 20 | 30 - 2 | -300 | -200 | -100 | 100 | 200 | 300 - 3 | -3000 | -2000 | -1000 | 1000 | 2000 | 3000 - 4 | -30000 | -20000 | -10000 | 10000 | 20000 | 30000 - 5 | -300000 | -200000 | -100000 | 100000 | 200000 | 300000 -(11 rows) - --- Testing for width_bucket(). For convenience, we test both the --- numeric and float8 versions of the function in this file. --- errors ---Testcase 606: -CREATE FOREIGN TABLE width_bucket_tbl ( - id1 numeric, - id2 numeric, - id3 numeric, - id4 int, - id int OPTIONS (key 'true') -) SERVER sqlite_svr; ---Testcase 607: -DELETE FROM width_bucket_tbl; ---Testcase 608: -INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, 0); ---Testcase 609: -SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; -ERROR: count must be greater than zero ---Testcase 610: -DELETE FROM width_bucket_tbl; ---Testcase 611: -INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, -5); ---Testcase 612: -SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; -ERROR: count must be greater than zero ---Testcase 613: -DELETE FROM width_bucket_tbl; ---Testcase 614: -INSERT INTO width_bucket_tbl VALUES (3.5, 3.0, 3.0, 888); ---Testcase 615: -SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; -ERROR: lower bound cannot equal upper bound ---Testcase 616: -DELETE FROM width_bucket_tbl; ---Testcase 617: -INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, 0); ---Testcase 618: -SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; -ERROR: count must be greater than zero ---Testcase 619: -DELETE FROM width_bucket_tbl; ---Testcase 620: -INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, -5); ---Testcase 621: -SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; -ERROR: count must be greater than zero ---Testcase 622: -DELETE FROM width_bucket_tbl; ---Testcase 623: -INSERT INTO width_bucket_tbl VALUES (3.5, 3.0, 3.0, 888); ---Testcase 624: -SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; -ERROR: lower bound cannot equal upper bound ---Testcase 625: -DELETE FROM width_bucket_tbl; ---Testcase 626: -INSERT INTO width_bucket_tbl VALUES ('NaN'::numeric, 3.0, 4.0, 888); ---Testcase 627: -SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; - width_bucket --------------- - -(1 row) - ---Testcase 628: -DELETE FROM width_bucket_tbl; ---Testcase 629: -INSERT INTO width_bucket_tbl VALUES (0, 'NaN'::numeric, 4.0, 888); ---Testcase 630: -SELECT width_bucket(id1::float8, id2, id3::float8, id4) FROM width_bucket_tbl; - width_bucket --------------- - -(1 row) - --- normal operation ---Testcase 631: -CREATE FOREIGN TABLE width_bucket_test ( - operand_num numeric OPTIONS (key 'true'), - operand_f8 float8 -) SERVER sqlite_svr; ---COPY width_bucket_test (operand_num) FROM stdin; ---Testcase 507: -INSERT INTO width_bucket_test (operand_num) VALUES -(-5.2), -(-0.0000000001), -(0.000000000001), -(1), -(1.99999999999999), -(2), -(2.00000000000001), -(3), -(4), -(4.5), -(5), -(5.5), -(6), -(7), -(8), -(9), -(9.99999999999999), -(10), -(10.0000000000001); ---Testcase 508: -UPDATE width_bucket_test SET operand_f8 = operand_num::float8; ---Testcase 509: -SELECT - operand_num, - width_bucket(operand_num, 0, 10, 5) AS wb_1, - width_bucket(operand_f8, 0, 10, 5) AS wb_1f, - width_bucket(operand_num, 10, 0, 5) AS wb_2, - width_bucket(operand_f8, 10, 0, 5) AS wb_2f, - width_bucket(operand_num, 2, 8, 4) AS wb_3, - width_bucket(operand_f8, 2, 8, 4) AS wb_3f, - width_bucket(operand_num, 5.0, 5.5, 20) AS wb_4, - width_bucket(operand_f8, 5.0, 5.5, 20) AS wb_4f, - width_bucket(operand_num, -25, 25, 10) AS wb_5, - width_bucket(operand_f8, -25, 25, 10) AS wb_5f - FROM width_bucket_test; - operand_num | wb_1 | wb_1f | wb_2 | wb_2f | wb_3 | wb_3f | wb_4 | wb_4f | wb_5 | wb_5f -------------------+------+-------+------+-------+------+-------+------+-------+------+------- - -5.2 | 0 | 0 | 6 | 6 | 0 | 0 | 0 | 0 | 4 | 4 - -0.0000000001 | 0 | 0 | 6 | 6 | 0 | 0 | 0 | 0 | 5 | 5 - 0.000000000001 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 - 1 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 - 1.99999999999999 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 - 2 | 2 | 2 | 5 | 5 | 1 | 1 | 0 | 0 | 6 | 6 - 2.00000000000001 | 2 | 2 | 4 | 4 | 1 | 1 | 0 | 0 | 6 | 6 - 3 | 2 | 2 | 4 | 4 | 1 | 1 | 0 | 0 | 6 | 6 - 4 | 3 | 3 | 4 | 4 | 2 | 2 | 0 | 0 | 6 | 6 - 4.5 | 3 | 3 | 3 | 3 | 2 | 2 | 0 | 0 | 6 | 6 - 5 | 3 | 3 | 3 | 3 | 3 | 3 | 1 | 1 | 7 | 7 - 5.5 | 3 | 3 | 3 | 3 | 3 | 3 | 21 | 21 | 7 | 7 - 6 | 4 | 4 | 3 | 3 | 3 | 3 | 21 | 21 | 7 | 7 - 7 | 4 | 4 | 2 | 2 | 4 | 4 | 21 | 21 | 7 | 7 - 8 | 5 | 5 | 2 | 2 | 5 | 5 | 21 | 21 | 7 | 7 - 9 | 5 | 5 | 1 | 1 | 5 | 5 | 21 | 21 | 7 | 7 - 9.99999999999999 | 5 | 5 | 1 | 1 | 5 | 5 | 21 | 21 | 7 | 7 - 10 | 6 | 6 | 1 | 1 | 5 | 5 | 21 | 21 | 8 | 8 - 10.0000000000001 | 6 | 6 | 0 | 0 | 5 | 5 | 21 | 21 | 8 | 8 -(19 rows) - --- for float8 only, check positive and negative infinity: we require --- finite bucket bounds, but allow an infinite operand ---Testcase 510: -DELETE FROM width_bucket_tbl; --- postgres does not support insert 'Infinity' and '-Infinity' as numeric. ---Testcase 632: -INSERT INTO width_bucket_tbl VALUES (0.0, 0.0, 5, 10); ---Testcase 633: -SELECT width_bucket(id1::float8, 'Infinity'::float8, id3, id4) FROM width_bucket_tbl; -- error -ERROR: lower and upper bounds must be finite ---Testcase 511: -DELETE FROM width_bucket_tbl; ---Testcase 634: -INSERT INTO width_bucket_tbl VALUES (0.0, 5, 0.0, 20); ---Testcase 635: -SELECT width_bucket(id1::float8, id2, 'Infinity'::float8, id4) FROM width_bucket_tbl; -- error -ERROR: lower and upper bounds must be finite ---Testcase 512: -DELETE FROM width_bucket_tbl; ---Testcase 636: -INSERT INTO width_bucket_tbl VALUES (0.0, 1, 10, 10); ---Testcase 637: -SELECT width_bucket('Infinity'::float8, id2, id3, id4), width_bucket('-Infinity'::float8, id2, id3, id4) FROM width_bucket_tbl; - width_bucket | width_bucket ---------------+-------------- - 11 | 0 -(1 row) - ---Testcase 638: -DROP FOREIGN TABLE width_bucket_test; --- TO_CHAR() --- ---Testcase 513: -SELECT '' AS to_char_1, to_char(val, '9G999G999G999G999G999') - FROM num_data; - to_char_1 | to_char ------------+------------------------ - | 0 - | 0 - | -34,338,492 - | 4 - | 7,799,461 - | 16,397 - | 93,902 - | -83,028,485 - | 74,881 - | -24,926,804 -(10 rows) - ---Testcase 514: -SELECT '' AS to_char_2, to_char(val, '9G999G999G999G999G999D999G999G999G999G999') - FROM num_data; - to_char_2 | to_char ------------+-------------------------------------------- - | .000,000,000,000,000 - | .000,000,000,000,000 - | -34,338,492.215,397,045,000,000 - | 4.310,000,000,000,000 - | 7,799,461.411,900,000,000,000 - | 16,397.038,491,000,000,000 - | 93,901.577,630,260,000,000 - | -83,028,485.000,000,000,000,000 - | 74,881.000,000,000,000,000 - | -24,926,804.045,047,420,000,000 -(10 rows) - ---Testcase 515: -SELECT '' AS to_char_3, to_char(val, '9999999999999999.999999999999999PR') - FROM num_data; - to_char_3 | to_char ------------+------------------------------------ - | .000000000000000 - | .000000000000000 - | <34338492.215397045000000> - | 4.310000000000000 - | 7799461.411900000000000 - | 16397.038491000000000 - | 93901.577630260000000 - | <83028485.000000000000000> - | 74881.000000000000000 - | <24926804.045047420000000> -(10 rows) - ---Testcase 516: -SELECT '' AS to_char_4, to_char(val, '9999999999999999.999999999999999S') - FROM num_data; - to_char_4 | to_char ------------+----------------------------------- - | .000000000000000+ - | .000000000000000+ - | 34338492.215397045000000- - | 4.310000000000000+ - | 7799461.411900000000000+ - | 16397.038491000000000+ - | 93901.577630260000000+ - | 83028485.000000000000000- - | 74881.000000000000000+ - | 24926804.045047420000000- -(10 rows) - ---Testcase 517: -SELECT '' AS to_char_5, to_char(val, 'MI9999999999999999.999999999999999') FROM num_data; - to_char_5 | to_char ------------+----------------------------------- - | .000000000000000 - | .000000000000000 - | - 34338492.215397045000000 - | 4.310000000000000 - | 7799461.411900000000000 - | 16397.038491000000000 - | 93901.577630260000000 - | - 83028485.000000000000000 - | 74881.000000000000000 - | - 24926804.045047420000000 -(10 rows) - ---Testcase 518: -SELECT '' AS to_char_6, to_char(val, 'FMS9999999999999999.999999999999999') FROM num_data; - to_char_6 | to_char ------------+--------------------- - | +0. - | +0. - | -34338492.215397045 - | +4.31 - | +7799461.4119 - | +16397.038491 - | +93901.57763026 - | -83028485. - | +74881. - | -24926804.04504742 -(10 rows) - ---Testcase 519: -SELECT '' AS to_char_7, to_char(val, 'FM9999999999999999.999999999999999THPR') FROM num_data; - to_char_7 | to_char ------------+---------------------- - | 0. - | 0. - | <34338492.215397045> - | 4.31 - | 7799461.4119 - | 16397.038491 - | 93901.57763026 - | <83028485.> - | 74881. - | <24926804.04504742> -(10 rows) - ---Testcase 520: -SELECT '' AS to_char_8, to_char(val, 'SG9999999999999999.999999999999999th') FROM num_data; - to_char_8 | to_char ------------+----------------------------------- - | + .000000000000000 - | + .000000000000000 - | - 34338492.215397045000000 - | + 4.310000000000000 - | + 7799461.411900000000000 - | + 16397.038491000000000 - | + 93901.577630260000000 - | - 83028485.000000000000000 - | + 74881.000000000000000 - | - 24926804.045047420000000 -(10 rows) - ---Testcase 521: -SELECT '' AS to_char_9, to_char(val, '0999999999999999.999999999999999') FROM num_data; - to_char_9 | to_char ------------+----------------------------------- - | 0000000000000000.000000000000000 - | 0000000000000000.000000000000000 - | -0000000034338492.215397045000000 - | 0000000000000004.310000000000000 - | 0000000007799461.411900000000000 - | 0000000000016397.038491000000000 - | 0000000000093901.577630260000000 - | -0000000083028485.000000000000000 - | 0000000000074881.000000000000000 - | -0000000024926804.045047420000000 -(10 rows) - ---Testcase 522: -SELECT '' AS to_char_10, to_char(val, 'S0999999999999999.999999999999999') FROM num_data; - to_char_10 | to_char -------------+----------------------------------- - | +0000000000000000.000000000000000 - | +0000000000000000.000000000000000 - | -0000000034338492.215397045000000 - | +0000000000000004.310000000000000 - | +0000000007799461.411900000000000 - | +0000000000016397.038491000000000 - | +0000000000093901.577630260000000 - | -0000000083028485.000000000000000 - | +0000000000074881.000000000000000 - | -0000000024926804.045047420000000 -(10 rows) - ---Testcase 523: -SELECT '' AS to_char_11, to_char(val, 'FM0999999999999999.999999999999999') FROM num_data; - to_char_11 | to_char -------------+----------------------------- - | 0000000000000000. - | 0000000000000000. - | -0000000034338492.215397045 - | 0000000000000004.31 - | 0000000007799461.4119 - | 0000000000016397.038491 - | 0000000000093901.57763026 - | -0000000083028485. - | 0000000000074881. - | -0000000024926804.04504742 -(10 rows) - ---Testcase 524: -SELECT '' AS to_char_12, to_char(val, 'FM9999999999999999.099999999999999') FROM num_data; - to_char_12 | to_char -------------+--------------------- - | .0 - | .0 - | -34338492.215397045 - | 4.31 - | 7799461.4119 - | 16397.038491 - | 93901.57763026 - | -83028485.0 - | 74881.0 - | -24926804.04504742 -(10 rows) - ---Testcase 525: -SELECT '' AS to_char_13, to_char(val, 'FM9999999999990999.990999999999999') FROM num_data; - to_char_13 | to_char -------------+--------------------- - | 0000.000 - | 0000.000 - | -34338492.215397045 - | 0004.310 - | 7799461.4119 - | 16397.038491 - | 93901.57763026 - | -83028485.000 - | 74881.000 - | -24926804.04504742 -(10 rows) - ---Testcase 526: -SELECT '' AS to_char_14, to_char(val, 'FM0999999999999999.999909999999999') FROM num_data; - to_char_14 | to_char -------------+----------------------------- - | 0000000000000000.00000 - | 0000000000000000.00000 - | -0000000034338492.215397045 - | 0000000000000004.31000 - | 0000000007799461.41190 - | 0000000000016397.038491 - | 0000000000093901.57763026 - | -0000000083028485.00000 - | 0000000000074881.00000 - | -0000000024926804.04504742 -(10 rows) - ---Testcase 527: -SELECT '' AS to_char_15, to_char(val, 'FM9999999990999999.099999999999999') FROM num_data; - to_char_15 | to_char -------------+--------------------- - | 0000000.0 - | 0000000.0 - | -34338492.215397045 - | 0000004.31 - | 7799461.4119 - | 0016397.038491 - | 0093901.57763026 - | -83028485.0 - | 0074881.0 - | -24926804.04504742 -(10 rows) - ---Testcase 528: -SELECT '' AS to_char_16, to_char(val, 'L9999999999999999.099999999999999') FROM num_data; - to_char_16 | to_char -------------+------------------------------------ - | .000000000000000 - | .000000000000000 - | -34338492.215397045000000 - | 4.310000000000000 - | 7799461.411900000000000 - | 16397.038491000000000 - | 93901.577630260000000 - | -83028485.000000000000000 - | 74881.000000000000000 - | -24926804.045047420000000 -(10 rows) - ---Testcase 529: -SELECT '' AS to_char_17, to_char(val, 'FM9999999999999999.99999999999999') FROM num_data; - to_char_17 | to_char -------------+--------------------- - | 0. - | 0. - | -34338492.215397045 - | 4.31 - | 7799461.4119 - | 16397.038491 - | 93901.57763026 - | -83028485. - | 74881. - | -24926804.04504742 -(10 rows) - ---Testcase 530: -SELECT '' AS to_char_18, to_char(val, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; - to_char_18 | to_char -------------+----------------------------------------------------------------------- - | +. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - | +. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - | -3 4 3 3 8 4 9 2 . 2 1 5 3 9 7 0 4 5 0 0 0 0 0 0 0 0 - | +4 . 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - | +7 7 9 9 4 6 1 . 4 1 1 9 0 0 0 0 0 0 0 0 0 0 0 0 0 - | +1 6 3 9 7 . 0 3 8 4 9 1 0 0 0 0 0 0 0 0 0 0 0 - | +9 3 9 0 1 . 5 7 7 6 3 0 2 6 0 0 0 0 0 0 0 0 0 - | -8 3 0 2 8 4 8 5 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - | +7 4 8 8 1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - | -2 4 9 2 6 8 0 4 . 0 4 5 0 4 7 4 2 0 0 0 0 0 0 0 0 0 -(10 rows) - ---Testcase 531: -SELECT '' AS to_char_19, to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; - to_char_19 | to_char -------------+------------------------------------------------------- - | +0 . - | +0 . - | -3 4 3 3 8 4 9 2 . 2 1 5 3 9 7 0 4 5 - | +4 . 3 1 - | +7 7 9 9 4 6 1 . 4 1 1 9 - | +1 6 3 9 7 . 0 3 8 4 9 1 - | +9 3 9 0 1 . 5 7 7 6 3 0 2 6 - | -8 3 0 2 8 4 8 5 . - | +7 4 8 8 1 . - | -2 4 9 2 6 8 0 4 . 0 4 5 0 4 7 4 2 -(10 rows) - ---Testcase 532: -SELECT '' AS to_char_20, to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data; - to_char_20 | to_char -------------+----------------------------------------------------------- - | text 9999 "text between quote marks" 0 - | text 9999 "text between quote marks" 0 - | text -3 9999 433 "text between quote marks" 8492 - | text 9999 "text between quote marks" 4 - | text 9999 779 "text between quote marks" 9461 - | text 9999 1 "text between quote marks" 6397 - | text 9999 9 "text between quote marks" 3902 - | text -8 9999 302 "text between quote marks" 8485 - | text 9999 7 "text between quote marks" 4881 - | text -2 9999 492 "text between quote marks" 6804 -(10 rows) - ---Testcase 533: -SELECT '' AS to_char_21, to_char(val, '999999SG9999999999') FROM num_data; - to_char_21 | to_char -------------+------------------- - | + 0 - | + 0 - | - 34338492 - | + 4 - | + 7799461 - | + 16397 - | + 93902 - | - 83028485 - | + 74881 - | - 24926804 -(10 rows) - ---Testcase 534: -SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM num_data; - to_char_22 | to_char -------------+--------------------- - | 0. - | 0. - | -34338492.215397045 - | 4.31 - | 7799461.4119 - | 16397.038491 - | 93901.57763026 - | -83028485. - | 74881. - | -24926804.04504742 -(10 rows) - ---Testcase 535: -SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data; - to_char_23 | to_char -------------+------------ - | 0.000e+00 - | 0.000e+00 - | -3.434e+07 - | 4.310e+00 - | 7.799e+06 - | 1.640e+04 - | 9.390e+04 - | -8.303e+07 - | 7.488e+04 - | -2.493e+07 -(10 rows) - ---Testcase 536: -DELETE FROM ceil_floor_round; ---Testcase 537: -INSERT INTO ceil_floor_round VALUES ('100'::numeric); ---Testcase 538: -SELECT '' AS to_char_24, to_char(a, 'FM999.9') FROM ceil_floor_round; - to_char_24 | to_char -------------+--------- - | 100. -(1 row) - ---Testcase 539: -SELECT '' AS to_char_25, to_char(a, 'FM999.') FROM ceil_floor_round; - to_char_25 | to_char -------------+--------- - | 100 -(1 row) - ---Testcase 540: -SELECT '' AS to_char_26, to_char(a, 'FM999') FROM ceil_floor_round; - to_char_26 | to_char -------------+--------- - | 100 -(1 row) - --- Check parsing of literal text in a format string ---Testcase 541: -SELECT '' AS to_char_27, to_char(a, 'foo999') FROM ceil_floor_round; - to_char_27 | to_char -------------+--------- - | foo 100 -(1 row) - ---Testcase 542: -SELECT '' AS to_char_28, to_char(a, 'f\oo999') FROM ceil_floor_round; - to_char_28 | to_char -------------+---------- - | f\oo 100 -(1 row) - ---Testcase 543: -SELECT '' AS to_char_29, to_char(a, 'f\\oo999') FROM ceil_floor_round; - to_char_29 | to_char -------------+----------- - | f\\oo 100 -(1 row) - ---Testcase 544: -SELECT '' AS to_char_30, to_char(a, 'f\"oo999') FROM ceil_floor_round; - to_char_30 | to_char -------------+---------- - | f"oo 100 -(1 row) - ---Testcase 545: -SELECT '' AS to_char_31, to_char(a, 'f\\"oo999') FROM ceil_floor_round; - to_char_31 | to_char -------------+----------- - | f\"oo 100 -(1 row) - ---Testcase 546: -SELECT '' AS to_char_32, to_char(a, 'f"ool"999') FROM ceil_floor_round; - to_char_32 | to_char -------------+---------- - | fool 100 -(1 row) - ---Testcase 547: -SELECT '' AS to_char_33, to_char(a, 'f"\ool"999') FROM ceil_floor_round; - to_char_33 | to_char -------------+---------- - | fool 100 -(1 row) - ---Testcase 548: -SELECT '' AS to_char_34, to_char(a, 'f"\\ool"999') FROM ceil_floor_round; - to_char_34 | to_char -------------+----------- - | f\ool 100 -(1 row) - ---Testcase 549: -SELECT '' AS to_char_35, to_char(a, 'f"ool\"999') FROM ceil_floor_round; - to_char_35 | to_char -------------+---------- - | fool"999 -(1 row) - ---Testcase 550: -SELECT '' AS to_char_36, to_char(a, 'f"ool\\"999') FROM ceil_floor_round; - to_char_36 | to_char -------------+----------- - | fool\ 100 -(1 row) - --- TO_NUMBER() --- ---Testcase 639: -create foreign table to_number_tbl (a text, id int options (key 'true')) server sqlite_svr; -SET lc_numeric = 'C'; ---Testcase 640: -DELETE FROM to_number_tbl; ---Testcase 641: -INSERT INTO to_number_tbl VALUES ('-34,338,492'); ---Testcase 642: -SELECT '' AS to_number_1, to_number(a, '99G999G999') FROM to_number_tbl; - to_number_1 | to_number --------------+----------- - | -34338492 -(1 row) - ---Testcase 643: -DELETE FROM to_number_tbl; ---Testcase 644: -INSERT INTO to_number_tbl VALUES ('-34,338,492.654,878'); ---Testcase 645: -SELECT '' AS to_number_2, to_number(a, '99G999G999D999G999') FROM to_number_tbl; - to_number_2 | to_number --------------+------------------ - | -34338492.654878 -(1 row) - ---Testcase 646: -DELETE FROM to_number_tbl; ---Testcase 647: -INSERT INTO to_number_tbl VALUES ('<564646.654564>'); ---Testcase 648: -SELECT '' AS to_number_3, to_number(a, '999999.999999PR') FROM to_number_tbl; - to_number_3 | to_number --------------+---------------- - | -564646.654564 -(1 row) - ---Testcase 649: -DELETE FROM to_number_tbl; ---Testcase 650: -INSERT INTO to_number_tbl VALUES ('0.00001-'); ---Testcase 651: -SELECT '' AS to_number_4, to_number(a, '9.999999S') FROM to_number_tbl; - to_number_4 | to_number --------------+----------- - | -0.00001 -(1 row) - ---Testcase 652: -DELETE FROM to_number_tbl; ---Testcase 653: -INSERT INTO to_number_tbl VALUES ('5.01-'); ---Testcase 654: -SELECT '' AS to_number_5, to_number(a, 'FM9.999999S') FROM to_number_tbl; - to_number_5 | to_number --------------+----------- - | -5.01 -(1 row) - ---Testcase 655: -DELETE FROM to_number_tbl; ---Testcase 656: -INSERT INTO to_number_tbl VALUES ('5.01-'); ---Testcase 657: -SELECT '' AS to_number_5, to_number(a, 'FM9.999999MI') FROM to_number_tbl; - to_number_5 | to_number --------------+----------- - | -5.01 -(1 row) - ---Testcase 658: -DELETE FROM to_number_tbl; ---Testcase 659: -INSERT INTO to_number_tbl VALUES ('5 4 4 4 4 8 . 7 8'); ---Testcase 660: -SELECT '' AS to_number_7, to_number(a, '9 9 9 9 9 9 . 9 9') FROM to_number_tbl; - to_number_7 | to_number --------------+----------- - | 544448.78 -(1 row) - ---Testcase 661: -DELETE FROM to_number_tbl; ---Testcase 662: -INSERT INTO to_number_tbl VALUES ('.01'); ---Testcase 663: -SELECT '' AS to_number_8, to_number(a, 'FM9.99') FROM to_number_tbl; - to_number_8 | to_number --------------+----------- - | 0.01 -(1 row) - ---Testcase 664: -DELETE FROM to_number_tbl; ---Testcase 665: -INSERT INTO to_number_tbl VALUES ('.0'); ---Testcase 666: -SELECT '' AS to_number_9, to_number(a, '99999999.99999999') FROM to_number_tbl; - to_number_9 | to_number --------------+----------- - | 0.0 -(1 row) - ---Testcase 667: -DELETE FROM to_number_tbl; ---Testcase 668: -INSERT INTO to_number_tbl VALUES ('0'); ---Testcase 669: -SELECT '' AS to_number_10, to_number(a, '99.99') FROM to_number_tbl; - to_number_10 | to_number ---------------+----------- - | 0 -(1 row) - ---Testcase 670: -DELETE FROM to_number_tbl; ---Testcase 671: -INSERT INTO to_number_tbl VALUES ('.-01'); ---Testcase 672: -SELECT '' AS to_number_11, to_number(a, 'S99.99') FROM to_number_tbl; - to_number_11 | to_number ---------------+----------- - | -0.01 -(1 row) - ---Testcase 673: -DELETE FROM to_number_tbl; ---Testcase 674: -INSERT INTO to_number_tbl VALUES ('.01-'); ---Testcase 675: -SELECT '' AS to_number_12, to_number(a, '99.99S') FROM to_number_tbl; - to_number_12 | to_number ---------------+----------- - | -0.01 -(1 row) - ---Testcase 676: -DELETE FROM to_number_tbl; ---Testcase 677: -INSERT INTO to_number_tbl VALUES (' . 0 1-'); ---Testcase 678: -SELECT '' AS to_number_13, to_number(a, ' 9 9 . 9 9 S') FROM to_number_tbl; - to_number_13 | to_number ---------------+----------- - | -0.01 -(1 row) - ---Testcase 679: -DELETE FROM to_number_tbl; ---Testcase 680: -INSERT INTO to_number_tbl VALUES ('34,50'); ---Testcase 681: -SELECT '' AS to_number_14, to_number(a,'999,99') FROM to_number_tbl; - to_number_14 | to_number ---------------+----------- - | 3450 -(1 row) - ---Testcase 682: -DELETE FROM to_number_tbl; ---Testcase 683: -INSERT INTO to_number_tbl VALUES ('123,000'); ---Testcase 684: -SELECT '' AS to_number_15, to_number(a,'999G') FROM to_number_tbl; - to_number_15 | to_number ---------------+----------- - | 123 -(1 row) - ---Testcase 685: -DELETE FROM to_number_tbl; ---Testcase 686: -INSERT INTO to_number_tbl VALUES ('123456'); ---Testcase 687: -SELECT '' AS to_number_16, to_number(a,'999G999') FROM to_number_tbl; - to_number_16 | to_number ---------------+----------- - | 123456 -(1 row) - ---Testcase 688: -DELETE FROM to_number_tbl; ---Testcase 689: -INSERT INTO to_number_tbl VALUES ('$1234.56'); ---Testcase 690: -SELECT '' AS to_number_17, to_number(a,'L9,999.99') FROM to_number_tbl; - to_number_17 | to_number ---------------+----------- - | 1234.56 -(1 row) - ---Testcase 691: -DELETE FROM to_number_tbl; ---Testcase 692: -INSERT INTO to_number_tbl VALUES ('$1234.56'); ---Testcase 693: -SELECT '' AS to_number_18, to_number(a,'L99,999.99') FROM to_number_tbl; - to_number_18 | to_number ---------------+----------- - | 1234.56 -(1 row) - ---Testcase 694: -DELETE FROM to_number_tbl; ---Testcase 695: -INSERT INTO to_number_tbl VALUES ('$1,234.56'); ---Testcase 696: -SELECT '' AS to_number_19, to_number(a,'L99,999.99') FROM to_number_tbl; - to_number_19 | to_number ---------------+----------- - | 1234.56 -(1 row) - ---Testcase 697: -DELETE FROM to_number_tbl; ---Testcase 698: -INSERT INTO to_number_tbl VALUES ('1234.56'); ---Testcase 699: -SELECT '' AS to_number_20, to_number(a,'L99,999.99') FROM to_number_tbl; - to_number_20 | to_number ---------------+----------- - | 1234.56 -(1 row) - ---Testcase 700: -DELETE FROM to_number_tbl; ---Testcase 701: -INSERT INTO to_number_tbl VALUES ('1,234.56'); ---Testcase 702: -SELECT '' AS to_number_21, to_number(a,'L99,999.99') FROM to_number_tbl; - to_number_21 | to_number ---------------+----------- - | 1234.56 -(1 row) - ---Testcase 703: -DELETE FROM to_number_tbl; ---Testcase 704: -INSERT INTO to_number_tbl VALUES ('42nd'); ---Testcase 705: -SELECT '' AS to_number_22, to_number(a, '99th') FROM to_number_tbl; - to_number_22 | to_number ---------------+----------- - | 42 -(1 row) - -RESET lc_numeric; --- --- Input syntax --- ---Testcase 706: -CREATE FOREIGN TABLE num_input_test (n1 numeric) SERVER sqlite_svr; --- good inputs ---Testcase 551: -INSERT INTO num_input_test(n1) VALUES (' 123'); ---Testcase 552: -INSERT INTO num_input_test(n1) VALUES (' 3245874 '); ---Testcase 553: -INSERT INTO num_input_test(n1) VALUES (' -93853'); ---Testcase 554: -INSERT INTO num_input_test(n1) VALUES ('555.50'); ---Testcase 555: -INSERT INTO num_input_test(n1) VALUES ('-555.50'); ---Testcase 556: -INSERT INTO num_input_test(n1) VALUES ('NaN '); ---Testcase 557: -INSERT INTO num_input_test(n1) VALUES (' nan'); --- bad inputs ---Testcase 558: -INSERT INTO num_input_test(n1) VALUES (' '); -ERROR: invalid input syntax for type numeric: " " -LINE 1: INSERT INTO num_input_test(n1) VALUES (' '); - ^ ---Testcase 559: -INSERT INTO num_input_test(n1) VALUES (' 1234 %'); -ERROR: invalid input syntax for type numeric: " 1234 %" -LINE 1: INSERT INTO num_input_test(n1) VALUES (' 1234 %'); - ^ ---Testcase 560: -INSERT INTO num_input_test(n1) VALUES ('xyz'); -ERROR: invalid input syntax for type numeric: "xyz" -LINE 1: INSERT INTO num_input_test(n1) VALUES ('xyz'); - ^ ---Testcase 561: -INSERT INTO num_input_test(n1) VALUES ('- 1234'); -ERROR: invalid input syntax for type numeric: "- 1234" -LINE 1: INSERT INTO num_input_test(n1) VALUES ('- 1234'); - ^ ---Testcase 562: -INSERT INTO num_input_test(n1) VALUES ('5 . 0'); -ERROR: invalid input syntax for type numeric: "5 . 0" -LINE 1: INSERT INTO num_input_test(n1) VALUES ('5 . 0'); - ^ ---Testcase 563: -INSERT INTO num_input_test(n1) VALUES ('5. 0 '); -ERROR: invalid input syntax for type numeric: "5. 0 " -LINE 1: INSERT INTO num_input_test(n1) VALUES ('5. 0 '); - ^ ---Testcase 564: -INSERT INTO num_input_test(n1) VALUES (''); -ERROR: invalid input syntax for type numeric: "" -LINE 1: INSERT INTO num_input_test(n1) VALUES (''); - ^ ---Testcase 565: -INSERT INTO num_input_test(n1) VALUES (' N aN '); -ERROR: invalid input syntax for type numeric: " N aN " -LINE 1: INSERT INTO num_input_test(n1) VALUES (' N aN '); - ^ ---Testcase 566: -SELECT * FROM num_input_test; - n1 ---------- - 123 - 3245874 - -93853 - 555.5 - -555.5 - - -(7 rows) - --- --- Test some corner cases for multiplication --- ---Testcase 707: -CREATE FOREIGN TABLE num_tmp (n1 numeric, n2 numeric, id int options (key 'true')) SERVER sqlite_svr; ---Testcase 708: -INSERT INTO num_tmp VALUES (4790999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); ---Testcase 709: -SELECT n1 * n2 FROM num_tmp; - ?column? ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 47910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -(1 row) - ---Testcase 710: -DELETE FROM num_tmp; ---Testcase 711: -INSERT INTO num_tmp VALUES (4789999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); ---Testcase 712: -SELECT n1 * n2 FROM num_tmp; - ?column? ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 47900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -(1 row) - ---Testcase 713: -DELETE FROM num_tmp; ---Testcase 714: -INSERT INTO num_tmp VALUES (4770999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); ---Testcase 715: -SELECT n1 * n2 FROM num_tmp; - ?column? ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 47710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -(1 row) - ---Testcase 716: -DELETE FROM num_tmp; ---Testcase 717: -INSERT INTO num_tmp VALUES (4769999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); ---Testcase 718: -SELECT n1 * n2 FROM num_tmp; - ?column? ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 47700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -(1 row) - --- --- Test some corner cases for division --- ---Testcase 719: -DELETE FROM num_tmp; ---Testcase 720: -INSERT INTO num_tmp VALUES (999999999999999999999, 1000000000000000000000); ---Testcase 721: -SELECT n1::numeric / n2 FROM num_tmp; - ?column? ------------------------- - 1.00000000000000000000 -(1 row) - ---Testcase 722: -DELETE FROM num_tmp; ---Testcase 723: -INSERT INTO num_tmp VALUES (999999999999999999999, 1000000000000000000000); ---Testcase 724: -SELECT div(n1::numeric, n2) FROM num_tmp; - div ------ - 1 -(1 row) - ---Testcase 725: -SELECT mod(n1::numeric, n2) FROM num_tmp; - mod ------ - 0 -(1 row) - ---Testcase 726: -SELECT div(-n1::numeric, n2) FROM num_tmp; - div ------ - -1 -(1 row) - ---Testcase 727: -SELECT mod(-n1::numeric, n2) FROM num_tmp; - mod ------ - 0 -(1 row) - ---Testcase 728: -select div(-n1::numeric,n2)*n2 + mod(-n1::numeric,n2) FROM num_tmp; - ?column? -------------------------- - -1000000000000000000000 -(1 row) - ---Testcase 729: -DELETE FROM num_tmp; ---Testcase 730: -INSERT INTO num_tmp VALUES (70.0,70); ---Testcase 731: -select mod (n1, n2) FROM num_tmp; - mod ------ - 0 -(1 row) - ---Testcase 732: -select div (n1, n2) FROM num_tmp; - div ------ - 1 -(1 row) - ---Testcase 733: -select n1 / n2 FROM num_tmp; - ?column? ------------------------- - 1.00000000000000000000 -(1 row) - ---Testcase 734: -DELETE FROM num_tmp; ---Testcase 735: -INSERT INTO num_tmp VALUES (12345678901234567890, 123); ---Testcase 736: -select n1 % n2 FROM num_tmp; - ?column? ----------- - 49 -(1 row) - ---Testcase 737: -select n1 / n2 FROM num_tmp; - ?column? --------------------- - 100371373180768837 -(1 row) - ---Testcase 738: -select div(n1, n2) FROM num_tmp; - div --------------------- - 100371373180768837 -(1 row) - ---Testcase 739: -select div(n1, n2) * n2 + n1 % n2 FROM num_tmp; - ?column? ----------------------- - 12345678901234567000 -(1 row) - --- --- Test some corner cases for square root --- ---Testcase 740: -DELETE FROM num_tmp; ---Testcase 741: -INSERT INTO num_tmp VALUES (1.000000000000003::numeric); ---Testcase 742: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 1.000000000000002 -(1 row) - ---Testcase 743: -DELETE FROM num_tmp; ---Testcase 744: -INSERT INTO num_tmp VALUES (1.000000000000004::numeric); ---Testcase 745: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 1.000000000000002 -(1 row) - ---Testcase 746: -DELETE FROM num_tmp; ---Testcase 747: -INSERT INTO num_tmp VALUES (96627521408608.56340355805::numeric); ---Testcase 748: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 9829929.878112486 -(1 row) - ---Testcase 749: -DELETE FROM num_tmp; ---Testcase 750: -INSERT INTO num_tmp VALUES (96627521408608.56340355806::numeric); ---Testcase 751: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 9829929.878112486 -(1 row) - ---Testcase 752: -DELETE FROM num_tmp; ---Testcase 753: -INSERT INTO num_tmp VALUES (515549506212297735.073688290367::numeric); ---Testcase 754: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 718017761.7665859 -(1 row) - ---Testcase 755: -DELETE FROM num_tmp; ---Testcase 756: -INSERT INTO num_tmp VALUES (515549506212297735.073688290368::numeric); ---Testcase 757: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 718017761.7665859 -(1 row) - ---Testcase 758: -DELETE FROM num_tmp; ---Testcase 759: -INSERT INTO num_tmp VALUES (8015491789940783531003294973900306::numeric); ---Testcase 760: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 89529278953540020 -(1 row) - ---Testcase 761: -DELETE FROM num_tmp; ---Testcase 762: -INSERT INTO num_tmp VALUES (8015491789940783531003294973900307::numeric); ---Testcase 763: -SELECT sqrt(n1) FROM num_tmp; - sqrt -------------------- - 89529278953540020 -(1 row) - --- --- Test code path for raising to integer powers --- ---Testcase 764: -DELETE FROM num_tmp; ---Testcase 765: -INSERT INTO num_tmp VALUES (10.0, -2147483648); ---Testcase 766: -SELECT n1 ^ n2 as rounds_to_zero FROM num_tmp; - rounds_to_zero --------------------- - 0.0000000000000000 -(1 row) - ---Testcase 767: -DELETE FROM num_tmp; ---Testcase 768: -INSERT INTO num_tmp VALUES (10.0, -2147483647); ---Testcase 769: -SELECT n1 ^ n2 as rounds_to_zero FROM num_tmp; - rounds_to_zero --------------------- - 0.0000000000000000 -(1 row) - ---Testcase 770: -DELETE FROM num_tmp; ---Testcase 771: -INSERT INTO num_tmp VALUES (10.0, 2147483647); ---Testcase 772: -SELECT n1 ^ n2 as overflows FROM num_tmp; -ERROR: value overflows numeric format ---Testcase 773: -DELETE FROM num_tmp; ---Testcase 774: -INSERT INTO num_tmp VALUES (117743296169.0, -1000000000); ---Testcase 775: -SELECT n1 ^ n2 as overflows FROM num_tmp; - overflows --------------------- - 0.0000000000000000 -(1 row) - --- cases that used to return inaccurate results ---Testcase 776: -DELETE FROM num_tmp; ---Testcase 777: -INSERT INTO num_tmp VALUES (3.789, 21); ---Testcase 778: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------------------- - 1409343026052.8716016316022141 -(1 row) - ---Testcase 779: -DELETE FROM num_tmp; ---Testcase 780: -INSERT INTO num_tmp VALUES (3.789, 35); ---Testcase 781: -select n1 ^ n2 FROM num_tmp; - ?column? ----------------------------------------- - 177158169650516670809.3820586142670135 -(1 row) - ---Testcase 782: -DELETE FROM num_tmp; ---Testcase 783: -INSERT INTO num_tmp VALUES (1.2, 345); ---Testcase 784: -select n1 ^ n2 FROM num_tmp; - ?column? ------------------------------------------------ - 2077446682327378559843444695.5827049735727869 -(1 row) - ---Testcase 785: -DELETE FROM num_tmp; ---Testcase 786: -INSERT INTO num_tmp VALUES (0.12, (-20)); ---Testcase 787: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------------------------- - 2608405330458882702.5529619561355838 -(1 row) - --- cases that used to error out ---Testcase 788: -DELETE FROM num_tmp; ---Testcase 789: -INSERT INTO num_tmp VALUES (0.12, (-25)); ---Testcase 790: -select n1 ^ n2 FROM num_tmp; - ?column? -------------------------------------------- - 104825960103961013959336.4983657883169110 -(1 row) - ---Testcase 791: -DELETE FROM num_tmp; ---Testcase 792: -INSERT INTO num_tmp VALUES (0.5678, (-85)); ---Testcase 793: -select n1 ^ n2 FROM num_tmp; - ?column? ----------------------------------------- - 782333637740774446257.7719390061997396 -(1 row) - --- --- Tests for raising to non-integer powers --- --- special cases ---Testcase 794: -DELETE FROM num_tmp; ---Testcase 795: -INSERT INTO num_tmp VALUES (0.0, 0.0); ---Testcase 796: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 797: -DELETE FROM num_tmp; ---Testcase 798: -INSERT INTO num_tmp VALUES ((-12.34), 0.0); ---Testcase 799: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 800: -DELETE FROM num_tmp; ---Testcase 801: -INSERT INTO num_tmp VALUES (12.34, 0.0); ---Testcase 802: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 803: -DELETE FROM num_tmp; ---Testcase 804: -INSERT INTO num_tmp VALUES (0.0, 12.34); ---Testcase 805: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------- - 0.0000000000000000 -(1 row) - --- NaNs ---Testcase 806: -DELETE FROM num_tmp; ---Testcase 807: -INSERT INTO num_tmp VALUES ('NaN'::numeric, 'NaN'::numeric); ---Testcase 808: -select n1 ^ n2 FROM num_tmp; - ?column? ----------- - -(1 row) - ---Testcase 809: -DELETE FROM num_tmp; ---Testcase 810: -INSERT INTO num_tmp VALUES ('NaN'::numeric, 0); ---Testcase 811: -select n1 ^ n2 FROM num_tmp; - ?column? ----------- - -(1 row) - ---Testcase 812: -DELETE FROM num_tmp; ---Testcase 813: -INSERT INTO num_tmp VALUES ('NaN'::numeric, 1); ---Testcase 814: -select n1 ^ n2 FROM num_tmp; - ?column? ----------- - -(1 row) - ---Testcase 815: -DELETE FROM num_tmp; ---Testcase 816: -INSERT INTO num_tmp VALUES (0, 'NaN'::numeric); ---Testcase 817: -select n1 ^ n2 FROM num_tmp; - ?column? ----------- - -(1 row) - ---Testcase 818: -DELETE FROM num_tmp; ---Testcase 819: -INSERT INTO num_tmp VALUES (1, 'NaN'::numeric); ---Testcase 820: -select n1 ^ n2 FROM num_tmp; - ?column? ----------- - -(1 row) - --- invalid inputs ---Testcase 821: -DELETE FROM num_tmp; ---Testcase 822: -INSERT INTO num_tmp VALUES (0.0, (-12.34)); ---Testcase 823: -select n1 ^ n2 FROM num_tmp; -ERROR: zero raised to a negative power is undefined ---Testcase 824: -DELETE FROM num_tmp; ---Testcase 825: -INSERT INTO num_tmp VALUES ((-12.34), 1.2); ---Testcase 826: -select n1 ^ n2 FROM num_tmp; -ERROR: a negative number raised to a non-integer power yields a complex result --- cases that used to generate inaccurate results ---Testcase 827: -DELETE FROM num_tmp; ---Testcase 828: -INSERT INTO num_tmp VALUES (32.1, 9.8); ---Testcase 829: -select n1 ^ n2 FROM num_tmp; - ?column? --------------------- - 580429286790711.10 -(1 row) - ---Testcase 830: -DELETE FROM num_tmp; ---Testcase 831: -INSERT INTO num_tmp VALUES (32.1, (-9.8)); ---Testcase 832: -select n1 ^ n2 FROM num_tmp; - ?column? ----------------------------------- - 0.000000000000001722862754788209 -(1 row) - ---Testcase 833: -DELETE FROM num_tmp; ---Testcase 834: -INSERT INTO num_tmp VALUES (12.3, 45.6); ---Testcase 835: -select n1 ^ n2 FROM num_tmp; - ?column? ------------------------------------------------------- - 50081010321492803393171165777624533697036806969694.9 -(1 row) - ---Testcase 836: -DELETE FROM num_tmp; ---Testcase 837: -INSERT INTO num_tmp VALUES (12.3, (-45.6)); ---Testcase 838: -select n1 ^ n2 FROM num_tmp; - ?column? ---------------------------------------------------------------------- - 0.00000000000000000000000000000000000000000000000001996764828785491 -(1 row) - --- big test ---Testcase 839: -DELETE FROM num_tmp; ---Testcase 840: -INSERT INTO num_tmp VALUES (1.234, 5678); ---Testcase 841: -select n1 ^ n2 FROM num_tmp; - ?column? ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 307239295662090741644584872593956173493568238595074141254349565406661439636598896798876823220904084953233015553994854875890890858118656468658643918169805277399402542281777901029346337707622181574346585989613344285010764501017625366742865066948856161360224801370482171458030533346309750557140549621313515752078638620714732831815297168231790779296290266207315344008883935010274044001522606235576584215999260117523114297033944018699691024106823438431754073086813382242140602291215149759520833200152654884259619588924545324.5973362312547382 -(1 row) - --- --- Tests for EXP() --- --- special cases ---Testcase 842: -DELETE FROM num_tmp; ---Testcase 843: -INSERT INTO num_tmp VALUES (0.0); ---Testcase 844: -select exp(n1) from num_tmp; - exp --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 845: -DELETE FROM num_tmp; ---Testcase 846: -INSERT INTO num_tmp VALUES (1.0); ---Testcase 847: -select exp(n1) from num_tmp; - exp --------------------- - 2.7182818284590452 -(1 row) - ---Testcase 848: -DELETE FROM num_tmp; ---Testcase 849: -INSERT INTO num_tmp VALUES (1.0::numeric(71,70)); ---Testcase 850: -select exp(n1) from num_tmp; - exp --------------------- - 2.7182818284590452 -(1 row) - --- cases that used to generate inaccurate results ---Testcase 851: -DELETE FROM num_tmp; ---Testcase 852: -INSERT INTO num_tmp VALUES (32.999); ---Testcase 853: -select exp(n1) from num_tmp; - exp ---------------------- - 214429043492155.053 -(1 row) - ---Testcase 854: -DELETE FROM num_tmp; ---Testcase 855: -INSERT INTO num_tmp VALUES (-32.999); ---Testcase 856: -select exp(n1) from num_tmp; - exp ----------------------------------- - 0.000000000000004663547361468248 -(1 row) - ---Testcase 857: -DELETE FROM num_tmp; ---Testcase 858: -INSERT INTO num_tmp VALUES (123.456); ---Testcase 859: -select exp(n1) from num_tmp; - exp ------------------------------------------------------------- - 413294435277809344957685441227343146614594393746575438.725 -(1 row) - ---Testcase 860: -DELETE FROM num_tmp; ---Testcase 861: -INSERT INTO num_tmp VALUES (-123.456); ---Testcase 862: -select exp(n1) from num_tmp; - exp -------------------------------------------------------------------------- - 0.000000000000000000000000000000000000000000000000000002419582541264601 -(1 row) - --- big test ---Testcase 863: -DELETE FROM num_tmp; ---Testcase 864: -INSERT INTO num_tmp VALUES (1234.5678); ---Testcase 865: -select exp(n1) from num_tmp; - exp ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 146549072930959479983482138503979804217622199675223653966270157446954995433819741094410764947112047906012815540251009949604426069672532417736057033099274204598385314594846509975629046864798765888104789074984927709616261452461385220475510438783429612447831614003668421849727379202555580791042606170523016207262965336641214601082882495255771621327088265411334088968112458492660609809762865582162764292604697957813514621259353683899630997077707406305730694385703091201347848855199354307506425820147289848677003277208302716466011827836279231.9667 -(1 row) - --- --- Tests for generate_series --- ---Testcase 866: -DELETE FROM num_tmp; ---Testcase 867: -INSERT INTO num_tmp select * from generate_series(0.0::numeric, 4.0::numeric); ---Testcase 868: -SELECT n1 FROM num_tmp; - n1 ----- - 0 - 1 - 2 - 3 - 4 -(5 rows) - ---Testcase 869: -DELETE FROM num_tmp; ---Testcase 870: -INSERT INTO num_tmp select * from generate_series(0.1::numeric, 4.0::numeric, 1.3::numeric); ---Testcase 871: -SELECT n1 FROM num_tmp; - n1 ------ - 0.1 - 1.4 - 2.7 - 4 -(4 rows) - ---Testcase 872: -DELETE FROM num_tmp; ---Testcase 873: -INSERT INTO num_tmp select * from generate_series(4.0::numeric, -1.5::numeric, -2.2::numeric); ---Testcase 874: -SELECT n1 FROM num_tmp; - n1 ------- - 4 - 1.8 - -0.4 -(3 rows) - --- Trigger errors ---Testcase 875: -DELETE FROM num_tmp; ---Testcase 876: -INSERT INTO num_tmp select * from generate_series(-100::numeric, 100::numeric, 0::numeric); -ERROR: step size cannot equal zero ---Testcase 877: -SELECT n1 FROM num_tmp; - n1 ----- -(0 rows) - ---Testcase 878: -DELETE FROM num_tmp; ---Testcase 879: -INSERT INTO num_tmp select * from generate_series(-100::numeric, 100::numeric, 'nan'::numeric); -ERROR: step size cannot be NaN ---Testcase 880: -SELECT n1 FROM num_tmp; - n1 ----- -(0 rows) - ---Testcase 881: -DELETE FROM num_tmp; ---Testcase 882: -INSERT INTO num_tmp select * from generate_series('nan'::numeric, 100::numeric, 10::numeric); -ERROR: start value cannot be NaN ---Testcase 883: -SELECT n1 FROM num_tmp; - n1 ----- -(0 rows) - ---Testcase 884: -DELETE FROM num_tmp; ---Testcase 885: -INSERT INTO num_tmp select * from generate_series(0::numeric, 'nan'::numeric, 10::numeric); -ERROR: stop value cannot be NaN ---Testcase 886: -SELECT n2 FROM num_tmp; - n2 ----- -(0 rows) - --- Checks maximum, output is truncated ---Testcase 887: -DELETE FROM num_tmp; ---Testcase 888: -INSERT INTO num_tmp select (i / (10::numeric ^ 131071))::numeric(1,0) - from generate_series(6 * (10::numeric ^ 131071), - 9 * (10::numeric ^ 131071), - 10::numeric ^ 131071) i; ---Testcase 889: -SELECT n1 FROM num_tmp; - n1 ----- - 6 - 7 - 8 - 9 -(4 rows) - - --- Check usage with variables ---Testcase 890: -DELETE FROM num_tmp; ---Testcase 891: -INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j; ---Testcase 892: -SELECT n1, n2 FROM num_tmp; - n1 | n2 -----+---- - 1 | 1 - 1 | 2 - 1 | 3 - 2 | 2 - 2 | 3 - 3 | 3 -(6 rows) - ---Testcase 893: -DELETE FROM num_tmp; ---Testcase 894: -INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j; ---Testcase 895: -SELECT n1, n2 FROM num_tmp; - n1 | n2 -----+---- - 1 | 1 - 2 | 1 - 2 | 2 - 3 | 1 - 3 | 2 - 3 | 3 -(6 rows) - ---Testcase 896: -DELETE FROM num_tmp; ---Testcase 897: -INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j; ---Testcase 898: -SELECT n1, n2 FROM num_tmp; - n1 | n2 -----+---- - 1 | 1 - 1 | 2 - 1 | 3 - 1 | 4 - 1 | 5 - 2 | 1 - 2 | 3 - 2 | 5 - 3 | 1 - 3 | 4 -(10 rows) - --- --- Tests for LN() --- --- Invalid inputs ---Testcase 899: -DELETE FROM num_tmp; ---Testcase 900: -INSERT INTO num_tmp VALUES (-12.34); ---Testcase 901: -select ln(n1) from num_tmp; -ERROR: cannot take logarithm of a negative number ---Testcase 902: -DELETE FROM num_tmp; ---Testcase 903: -INSERT INTO num_tmp VALUES (0.0); ---Testcase 904: -select ln(n1) from num_tmp; -ERROR: cannot take logarithm of zero --- Some random tests ---Testcase 905: -DELETE FROM num_tmp; ---Testcase 906: -INSERT INTO num_tmp VALUES (1.2345678e-28); ---Testcase 907: -select ln(n1) from num_tmp; - ln ------------------------------------------ - -64.26166165451762991204894255882820859 -(1 row) - ---Testcase 908: -DELETE FROM num_tmp; ---Testcase 909: -INSERT INTO num_tmp VALUES (0.0456789); ---Testcase 910: -select ln(n1) from num_tmp; - ln ---------------------- - -3.0861187944847439 -(1 row) - ---Testcase 911: -DELETE FROM num_tmp; ---Testcase 912: -INSERT INTO num_tmp VALUES (0.349873948359354029493948309745709580730482050975); ---Testcase 913: -select ln(n1) from num_tmp; - ln ----------------------- - -1.05018233691208275 -(1 row) - ---Testcase 914: -DELETE FROM num_tmp; ---Testcase 915: -INSERT INTO num_tmp VALUES (0.99949452); ---Testcase 916: -select ln(n1) from num_tmp; - ln -------------------------- - -0.00050560779808326467 -(1 row) - ---Testcase 917: -DELETE FROM num_tmp; ---Testcase 918: -INSERT INTO num_tmp VALUES (1.00049687395); ---Testcase 919: -select ln(n1) from num_tmp; - ln ------------------------- - 0.00049675054901370394 -(1 row) - ---Testcase 920: -DELETE FROM num_tmp; ---Testcase 921: -INSERT INTO num_tmp VALUES (1234.567890123456789); ---Testcase 922: -select ln(n1) from num_tmp; - ln --------------------- - 7.1184763012977898 -(1 row) - ---Testcase 923: -DELETE FROM num_tmp; ---Testcase 924: -INSERT INTO num_tmp VALUES (5.80397490724e5); ---Testcase 925: -select ln(n1) from num_tmp; - ln --------------------- - 13.271468476626518 -(1 row) - ---Testcase 926: -DELETE FROM num_tmp; ---Testcase 927: -INSERT INTO num_tmp VALUES (9.342536355e34); ---Testcase 928: -select ln(n1) from num_tmp; - ln --------------------- - 80.522470935524187 -(1 row) - --- --- Tests for LOG() (base 10) --- --- invalid inputs ---Testcase 929: -DELETE FROM num_tmp; ---Testcase 930: -INSERT INTO num_tmp VALUES (-12.34); ---Testcase 931: -select log(n1) from num_tmp; -ERROR: cannot take logarithm of a negative number ---Testcase 932: -DELETE FROM num_tmp; ---Testcase 933: -INSERT INTO num_tmp VALUES (0.0); ---Testcase 934: -select log(n1) from num_tmp; -ERROR: cannot take logarithm of zero --- some random tests ---Testcase 935: -DELETE FROM num_tmp; ---Testcase 936: -INSERT INTO num_tmp VALUES (1.234567e-89); ---Testcase 937: -select log(n1) from num_tmp; - log ------------------------------------------------------------------------------------------------------ - -88.90848533591373725637496492944925187293052336306443143312825869985819779294142441287021741054275 -(1 row) - ---Testcase 938: -DELETE FROM num_tmp; ---Testcase 939: -INSERT INTO num_tmp VALUES (3.4634998359873254962349856073435545); ---Testcase 940: -select log(n1) from num_tmp; - log --------------------- - 0.5395151714070135 -(1 row) - ---Testcase 941: -DELETE FROM num_tmp; ---Testcase 942: -INSERT INTO num_tmp VALUES (9.999999999999999999); ---Testcase 943: -select log(n1) from num_tmp; - log --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 944: -DELETE FROM num_tmp; ---Testcase 945: -INSERT INTO num_tmp VALUES (10.00000000000000000); ---Testcase 946: -select log(n1) from num_tmp; - log --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 947: -DELETE FROM num_tmp; ---Testcase 948: -INSERT INTO num_tmp VALUES (10.00000000000000001); ---Testcase 949: -select log(n1) from num_tmp; - log --------------------- - 1.0000000000000000 -(1 row) - ---Testcase 950: -DELETE FROM num_tmp; ---Testcase 951: -INSERT INTO num_tmp VALUES (590489.45235237); ---Testcase 952: -select log(n1) from num_tmp; - log -------------------- - 5.771212144411727 -(1 row) - --- --- Tests for LOG() (arbitrary base) --- --- invalid inputs ---Testcase 953: -DELETE FROM num_tmp; ---Testcase 954: -INSERT INTO num_tmp VALUES (-12.34, 56.78); ---Testcase 955: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of a negative number ---Testcase 956: -DELETE FROM num_tmp; ---Testcase 957: -INSERT INTO num_tmp VALUES (-12.34, -56.78); ---Testcase 958: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of a negative number ---Testcase 959: -DELETE FROM num_tmp; ---Testcase 960: -INSERT INTO num_tmp VALUES (12.34, -56.78); ---Testcase 961: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of a negative number ---Testcase 962: -DELETE FROM num_tmp; ---Testcase 963: -INSERT INTO num_tmp VALUES (0.0, 12.34); ---Testcase 964: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of zero ---Testcase 965: -DELETE FROM num_tmp; ---Testcase 966: -INSERT INTO num_tmp VALUES (12.34, 0.0); ---Testcase 967: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of zero ---Testcase 968: -DELETE FROM num_tmp; ---Testcase 969: -INSERT INTO num_tmp VALUES (.0, 12.34); ---Testcase 970: -select log(n1, n2) from num_tmp; -ERROR: cannot take logarithm of zero --- some random tests ---Testcase 971: -DELETE FROM num_tmp; ---Testcase 972: -INSERT INTO num_tmp VALUES (1.23e-89, 6.4689e45); ---Testcase 973: -select log(n1, n2) from num_tmp; - log ------------------------------------------------------------------------------------------------- - -0.5152489207781856983977054971756484879653568168479201885425588841094788842469115325262329756 -(1 row) - ---Testcase 974: -DELETE FROM num_tmp; ---Testcase 975: -INSERT INTO num_tmp VALUES (0.99923, 4.58934e34); ---Testcase 976: -select log(n1, n2) from num_tmp; - log ---------------------- - -103611.55579544132 -(1 row) - ---Testcase 977: -DELETE FROM num_tmp; ---Testcase 978: -INSERT INTO num_tmp VALUES (1.000016, 8.452010e18); ---Testcase 979: -select log(n1, n2) from num_tmp; - log --------------------- - 2723830.2877097365 -(1 row) - ---Testcase 980: -DELETE FROM num_tmp; ---Testcase 981: -INSERT INTO num_tmp VALUES (3.1954752e47, 9.4792021e-73); ---Testcase 982: -select log(n1, n2) from num_tmp; - log -------------------------------------------------------------------------------------- - -1.51613372350688302142917386143459361608600157692779164475351842333265418126982165 -(1 row) - --- --- Tests for scale() --- ---Testcase 983: -DELETE FROM num_tmp; ---Testcase 984: -INSERT INTO num_tmp VALUES (numeric 'NaN'); ---Testcase 985: -select scale(n1) from num_tmp; - scale -------- - -(1 row) - ---Testcase 986: -DELETE FROM num_tmp; ---Testcase 987: -INSERT INTO num_tmp VALUES (NULL::numeric); ---Testcase 988: -select scale(n1) from num_tmp; - scale -------- - -(1 row) - ---Testcase 989: -DELETE FROM num_tmp; ---Testcase 990: -INSERT INTO num_tmp VALUES (1.12); ---Testcase 991: -select scale(n1) from num_tmp; - scale -------- - 2 -(1 row) - ---Testcase 992: -DELETE FROM num_tmp; ---Testcase 993: -INSERT INTO num_tmp VALUES (0); ---Testcase 994: -select scale(n1) from num_tmp; - scale -------- - 0 -(1 row) - ---Testcase 995: -DELETE FROM num_tmp; ---Testcase 996: -INSERT INTO num_tmp VALUES (0.00); ---Testcase 997: -select scale(n1) from num_tmp; - scale -------- - 0 -(1 row) - ---Testcase 998: -DELETE FROM num_tmp; ---Testcase 999: -INSERT INTO num_tmp VALUES (1.12345); ---Testcase 1000: -select scale(n1) from num_tmp; - scale -------- - 5 -(1 row) - ---Testcase 1001: -DELETE FROM num_tmp; ---Testcase 1002: -INSERT INTO num_tmp VALUES (110123.12475871856128); ---Testcase 1003: -select scale(n1) from num_tmp; - scale -------- - 11 -(1 row) - ---Testcase 1004: -DELETE FROM num_tmp; ---Testcase 1005: -INSERT INTO num_tmp VALUES (-1123.12471856128); ---Testcase 1006: -select scale(n1) from num_tmp; - scale -------- - 11 -(1 row) - ---Testcase 1007: -DELETE FROM num_tmp; ---Testcase 1008: -INSERT INTO num_tmp VALUES (-13.000000000000000); ---Testcase 1009: -select scale(n1) from num_tmp; - scale -------- - 0 -(1 row) - --- --- Tests for min_scale() --- ---Testcase 1010: -DELETE FROM num_tmp; ---Testcase 1011: -INSERT INTO num_tmp VALUES (numeric 'NaN'); ---Testcase 1012: -select min_scale(n1) is NULL from num_tmp; -- should be true -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) is NULL from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1013: -DELETE FROM num_tmp; ---Testcase 1014: -INSERT INTO num_tmp VALUES (0); ---Testcase 1015: -select min_scale(n1) from num_tmp; -- no digits -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1016: -DELETE FROM num_tmp; ---Testcase 1017: -INSERT INTO num_tmp VALUES (0.00); ---Testcase 1018: -select min_scale(n1) from num_tmp; -- no digits again -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1019: -DELETE FROM num_tmp; ---Testcase 1020: -INSERT INTO num_tmp VALUES (1.0); ---Testcase 1021: -select min_scale(n1) from num_tmp; -- no scale -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1022: -DELETE FROM num_tmp; ---Testcase 1023: -INSERT INTO num_tmp VALUES (1.1); ---Testcase 1024: -select min_scale(n1) from num_tmp; -- scale 1 -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1025: -DELETE FROM num_tmp; ---Testcase 1026: -INSERT INTO num_tmp VALUES (1.12); ---Testcase 1027: -select min_scale(n1) from num_tmp; -- scale 2 -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1028: -DELETE FROM num_tmp; ---Testcase 1029: -INSERT INTO num_tmp VALUES (1.123); ---Testcase 1030: -select min_scale(n1) from num_tmp; -- scale 3 -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1031: -DELETE FROM num_tmp; ---Testcase 1032: -INSERT INTO num_tmp VALUES (1.1234); ---Testcase 1033: -select min_scale(n1) from num_tmp; -- scale 4, filled digit -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1034: -DELETE FROM num_tmp; ---Testcase 1035: -INSERT INTO num_tmp VALUES (1.12345); ---Testcase 1036: -select min_scale(n1) from num_tmp; -- scale 5, 2 NDIGITS -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1037: -DELETE FROM num_tmp; ---Testcase 1038: -INSERT INTO num_tmp VALUES (1.1000); ---Testcase 1039: -select min_scale(n1) from num_tmp; -- 1 pos in NDIGITS -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1040: -DELETE FROM num_tmp; ---Testcase 1041: -INSERT INTO num_tmp VALUES (1e100); ---Testcase 1042: -select min_scale(n1) from num_tmp; -- very big number -ERROR: function min_scale(numeric) does not exist -LINE 1: select min_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- --- Tests for trim_scale() --- ---Testcase 1043: -DELETE FROM num_tmp; ---Testcase 1044: -INSERT INTO num_tmp VALUES (numeric 'NaN'); ---Testcase 1045: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1046: -DELETE FROM num_tmp; ---Testcase 1047: -INSERT INTO num_tmp VALUES (1.120); ---Testcase 1048: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1049: -DELETE FROM num_tmp; ---Testcase 1050: -INSERT INTO num_tmp VALUES (0); ---Testcase 1051: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1052: -DELETE FROM num_tmp; ---Testcase 1053: -INSERT INTO num_tmp VALUES (0.00); ---Testcase 1054: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1055: -DELETE FROM num_tmp; ---Testcase 1056: -INSERT INTO num_tmp VALUES (1.1234500); ---Testcase 1057: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1058: -DELETE FROM num_tmp; ---Testcase 1059: -INSERT INTO num_tmp VALUES (110123.12475871856128000); ---Testcase 1060: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1061: -DELETE FROM num_tmp; ---Testcase 1062: -INSERT INTO num_tmp VALUES (-123.124718561280000000); ---Testcase 1063: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1064: -DELETE FROM num_tmp; ---Testcase 1065: -INSERT INTO num_tmp VALUES (-13.00000000000000000000); ---Testcase 1066: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1067: -DELETE FROM num_tmp; ---Testcase 1068: -INSERT INTO num_tmp VALUES (1e100); ---Testcase 1069: -select trim_scale(n1) from num_tmp; -ERROR: function trim_scale(numeric) does not exist -LINE 1: select trim_scale(n1) from num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- --- Tests for SUM() --- --- cases that need carry propagation ---Testcase 1070: -DELETE FROM num_tmp; ---Testcase 1071: -INSERT INTO num_tmp SELECT * FROM generate_series(1, 100000); ---Testcase 1072: -SELECT SUM(9999::numeric) FROM num_tmp; - sum ------------ - 999900000 -(1 row) - ---Testcase 1073: -SELECT SUM((-9999)::numeric) FROM num_tmp; - sum ------------- - -999900000 -(1 row) - --- --- Tests for GCD() --- ---Testcase 1074: -DELETE FROM num_tmp; ---Testcase 1075: -INSERT INTO num_tmp VALUES - (0::numeric, 0::numeric), - (0::numeric, numeric 'NaN'), - (0::numeric, 46375::numeric), - (433125::numeric, 46375::numeric), - (43312.5::numeric, 4637.5::numeric), - (4331.250::numeric, 463.75000::numeric); ---Testcase 1076: -SELECT n1 as a, n2 as b, gcd(n1, n2), gcd(n1, -n2), gcd(-n2, n1), gcd(-n2, -n1) FROM num_tmp; -ERROR: function gcd(numeric, numeric) does not exist -LINE 1: SELECT n1 as a, n2 as b, gcd(n1, n2), gcd(n1, -n2), gcd(-n2,... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. --- --- Tests for LCM() --- ---Testcase 1077: -DELETE FROM num_tmp; ---Testcase 1078: -INSERT INTO num_tmp VALUES - (0::numeric, 0::numeric), - (0::numeric, numeric 'NaN'), - (0::numeric, 13272::numeric), - (13272::numeric, 13272::numeric), - (423282::numeric, 13272::numeric), - (42328.2::numeric, 1327.2::numeric), - (4232.820::numeric, 132.72000::numeric); ---Testcase 1079: -SELECT n1 as a, n2 as b, lcm(n1, n2), lcm(n1, -n2), lcm(-n2, n1), lcm(-n2, -n1) FROM num_tmp; -ERROR: function lcm(numeric, numeric) does not exist -LINE 1: SELECT n1 as a, n2 as b, lcm(n1, n2), lcm(n1, -n2), lcm(-n2,... - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. ---Testcase 1080: -DELETE FROM num_tmp; ---Testcase 1081: -INSERT INTO num_tmp VALUES (10::numeric, 131068); ---Testcase 1082: -SELECT lcm(9999 * (n1)^n2 + (n1^n2 - 1), 2) FROM num_tmp; -- overflow -ERROR: function lcm(numeric, integer) does not exist -LINE 1: SELECT lcm(9999 * (n1)^n2 + (n1^n2 - 1), 2) FROM num_tmp; - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; ---Testcase 1083: -DROP SERVER sqlite_svr; ---Testcase 1084: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/sqlite_fdw_post.out b/expected/12.16/extra/sqlite_fdw_post.out deleted file mode 100644 index bc27ca17..00000000 --- a/expected/12.16/extra/sqlite_fdw_post.out +++ /dev/null @@ -1,9972 +0,0 @@ --- =================================================================== --- create FDW objects --- =================================================================== ---Testcase 483: -CREATE EXTENSION sqlite_fdw; -DO $d$ - BEGIN - EXECUTE $$CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - EXECUTE $$CREATE SERVER sqlite_svr2 FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; ---Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; ---Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --- =================================================================== --- create objects used through FDW sqlite server --- =================================================================== ---Testcase 486: -CREATE SCHEMA "S 1"; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO "S 1"; ---Testcase 1: -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10, - 'foo' - FROM generate_series(1, 1000) id; ---Testcase 2: -INSERT INTO "S 1"."T 2" - SELECT id, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 3: -INSERT INTO "S 1"."T 3" - SELECT id, - id + 1, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 487: -DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests ---Testcase 4: -INSERT INTO "S 1"."T 4" - SELECT id, - id + 1, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 488: -DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests -/*ANALYZE "S 1"."T 1"; -ANALYZE "S 1"."T 2"; -ANALYZE "S 1"."T 3"; -ANALYZE "S 1"."T 4";*/ --- =================================================================== --- create foreign tables --- =================================================================== ---Testcase 489: -CREATE FOREIGN TABLE ft1 ( - c0 int, - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_svr; -ALTER FOREIGN TABLE ft1 DROP COLUMN c0; ---Testcase 490: -CREATE FOREIGN TABLE ft2 ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - cx int, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft2', - c8 text -) SERVER sqlite_svr; -ALTER FOREIGN TABLE ft2 DROP COLUMN cx; ---Testcase 491: -CREATE FOREIGN TABLE ft4 ( - c1 int NOT NULL, - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr OPTIONS (table 'T 3'); ---Testcase 492: -CREATE FOREIGN TABLE ft5 ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr OPTIONS (table 'T 4'); ---Testcase 493: -CREATE FOREIGN TABLE ft6 ( - c1 int NOT NULL, - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr2 OPTIONS (table 'T 4'); -ALTER FOREIGN TABLE ft1 OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft2 OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); -ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); ---Testcase 5: -\det+ - List of foreign tables - Schema | Table | Server | FDW options | Description ---------+-------+-------------+-----------------+------------- - public | ft1 | sqlite_svr | ("table" 'T 1') | - public | ft2 | sqlite_svr | ("table" 'T 1') | - public | ft4 | sqlite_svr | ("table" 'T 3') | - public | ft5 | sqlite_svr | ("table" 'T 4') | - public | ft6 | sqlite_svr2 | ("table" 'T 4') | -(5 rows) - --- Test that alteration of server options causes reconnection --- Remote's errors might be non-English, so hide them to ensure stable results -\set VERBOSITY terse ---Testcase 6: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work - c3 | c4 --------+------------------------------ - 00001 | Fri Jan 02 00:00:00 1970 PST -(1 row) - -ALTER SERVER sqlite_svr OPTIONS (SET database 'no such database'); ---Testcase 7: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail -ERROR: Failed to open SQLite DB, file 'no such database', result code 14 -DO $d$ - BEGIN - EXECUTE $$ALTER SERVER sqlite_svr - OPTIONS (SET database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; ---Testcase 8: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again - c3 | c4 --------+------------------------------ - 00001 | Fri Jan 02 00:00:00 1970 PST -(1 row) - -\set VERBOSITY default --- Now we should be able to run ANALYZE. --- To exercise multiple code paths, we use local stats on ft1 --- and remote-estimate mode on ft2. ---ANALYZE ft1; ---ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true'); --- =================================================================== --- simple queries --- =================================================================== --- single table without alias ---Testcase 9: -EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; - QUERY PLAN ---------------------- - Foreign Scan on ft1 -(1 row) - ---Testcase 10: -SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo - 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo - 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo - 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo -(10 rows) - --- single table with alias - also test that tableoid sort is not pushed to remote side ---Testcase 11: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------- - Limit - Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid - -> Sort - Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid - Sort Key: t1.c3, t1.c1, t1.tableoid - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(8 rows) - ---Testcase 12: -SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo - 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo - 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo - 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo -(10 rows) - --- whole-row reference ---Testcase 13: -EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: t1.*, c3, c1 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 14: -SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - t1 --------------------------------------------------------------------------------------------- - (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1 ",foo) - (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2 ",foo) - (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3 ",foo) - (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4 ",foo) - (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5 ",foo) - (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6 ",foo) - (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7 ",foo) - (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8 ",foo) - (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9 ",foo) - (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0 ",foo) -(10 rows) - --- empty result ---Testcase 15: -SELECT * FROM ft1 WHERE false; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+----+----+----+----+----+---- -(0 rows) - --- with WHERE clause ---Testcase 16: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c7` >= '1')) AND ((`C 1` = 101)) AND ((`c6` = '1')) -(3 rows) - ---Testcase 17: -SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - --- with FOR UPDATE/SHARE ---Testcase 18: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - LockRows - Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 101)) -(5 rows) - ---Testcase 19: -SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - ---Testcase 20: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - LockRows - Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 102)) -(5 rows) - ---Testcase 21: -SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo -(1 row) - --- aggregate ---Testcase 22: -SELECT COUNT(*) FROM ft1 t1; - count -------- - 1000 -(1 row) - --- subquery ---Testcase 23: -SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo - 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo - 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo -(10 rows) - --- subquery+MAX ---Testcase 24: -SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+----+-------+------------------------------+--------------------------+----+------------+----- - 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo -(1 row) - --- used in CTE ---Testcase 25: -WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1; - c1 | c2 | c3 | c4 -----+----+-------+------------------------------ - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST - 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST - 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST - 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST - 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST - 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST -(10 rows) - --- fixed values ---Testcase 26: -SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1; - ?column? | ?column? -----------+---------- - fixed | -(1 row) - --- Test forcing the remote server to produce sorted data for a merge join. -SET enable_hashjoin TO false; -SET enable_nestloop TO false; --- inner join; expressions in the clauses appear in the equivalence class list ---Testcase 27: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2."C 1" - SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 28: -SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; - c1 | C 1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- outer join; expressions in the clauses do not appear in equivalence class --- list but no output change as compared to the previous query ---Testcase 29: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: t1.c1, t2."C 1" - SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 30: -SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; - c1 | C 1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- A join between local table and foreign join. ORDER BY clause is added to the --- foreign join so that the local table can be joined using merge join strategy. ---Testcase 31: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1."C 1" - SQLite query: SELECT r1.`C 1` FROM (main."T 1" r1 LEFT JOIN (main."T 1" r2 INNER JOIN main."T 1" r3 ON (((r2.`C 1` = r3.`C 1`)))) ON (((r3.`C 1` = r1.`C 1`)))) LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 32: -SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - C 1 ------ - 101 - 102 - 103 - 104 - 105 - 106 - 107 - 108 - 109 - 110 -(10 rows) - --- Test similar to above, except that the full join prevents any equivalence --- classes from being merged. This produces single relation equivalence classes --- included in join restrictions. ---Testcase 33: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1."C 1", t2.c1, t3.c1 - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r3.`C 1` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r3 ON (((r3.`C 1` = r1.`C 1`)))) LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r3.`C 1`)))) LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 34: -SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - C 1 | c1 | c1 ------+-----+----- - 101 | 101 | 101 - 102 | 102 | 102 - 103 | 103 | 103 - 104 | 104 | 104 - 105 | 105 | 105 - 106 | 106 | 106 - 107 | 107 | 107 - 108 | 108 | 108 - 109 | 109 | 109 - 110 | 110 | 110 -(10 rows) - --- Test similar to above with all full outer joins ---Testcase 35: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------- - Limit - Output: t1."C 1", t2.c1, t3.c1 - -> Merge Full Join - Output: t1."C 1", t2.c1, t3.c1 - Merge Cond: (t1."C 1" = t3.c1) - -> Sort - Output: t1."C 1" - Sort Key: t1."C 1" - -> Foreign Scan on "S 1"."T 1" t1 - Output: t1."C 1" - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t2.c1, t3.c1 - Sort Key: t3.c1 - -> Merge Full Join - Output: t2.c1, t3.c1 - Merge Cond: (t2.c1 = t3.c1) - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft1 t2 - Output: t2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t3.c1 - Sort Key: t3.c1 - -> Foreign Scan on public.ft2 t3 - Output: t3.c1 - SQLite query: SELECT `C 1` FROM main."T 1" -(29 rows) - ---Testcase 36: -SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; - C 1 | c1 | c1 ------+-----+----- - 101 | 101 | 101 - 102 | 102 | 102 - 103 | 103 | 103 - 104 | 104 | 104 - 105 | 105 | 105 - 106 | 106 | 106 - 107 | 107 | 107 - 108 | 108 | 108 - 109 | 109 | 109 - 110 | 110 | 110 -(10 rows) - -RESET enable_hashjoin; -RESET enable_nestloop; --- =================================================================== --- WHERE with remotely-executable conditions --- =================================================================== ---Testcase 37: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - ---Testcase 38: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 100)) AND ((`c2` = 0)) -(3 rows) - ---Testcase 39: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL; -- NullTest - QUERY PLAN ----------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` IS NULL)) -(3 rows) - ---Testcase 40: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; -- NullTest - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` IS NOT NULL)) -(3 rows) - ---Testcase 41: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((round(abs(`C 1`), 0) = 1)) -(3 rows) - ---Testcase 42: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) - QUERY PLAN --------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = (- `C 1`))) -(3 rows) - ---Testcase 43: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r) - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: ('1'::numeric = ((t1.c1)::bigint !)) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(4 rows) - ---Testcase 44: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: ((t1.c1 IS NOT NULL) IS DISTINCT FROM (t1.c1 IS NOT NULL)) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(4 rows) - ---Testcase 45: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (`C 1` IN (`c2`, 1, (`C 1` + 0))) -(3 rows) - ---Testcase 46: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: (t1.c1 = (ARRAY[t1.c1, t1.c2, 3])[1]) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(4 rows) - ---Testcase 47: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c6` = 'foo''s\\bar')) -(3 rows) - ---Testcase 48: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote - QUERY PLAN ---------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) -(3 rows) - --- parameterized remote path for foreign table ---Testcase 49: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 - SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND ((r1.`C 1` = 47)))) -(3 rows) - ---Testcase 50: -SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+----- - 47 | 7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo | 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo -(1 row) - --- check both safe and unsafe join conditions ---Testcase 51: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 a, ft2 b - WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 - Filter: (upper((a.c7)::text) = (b.c7)::text) - SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = 6)) AND ((r1.`c8` = 'foo')))) -(4 rows) - ---Testcase 52: -SELECT * FROM ft2 a, ft2 b -WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+----- - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo - 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo - 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo - 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo - 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo - 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo - 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo - 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo - 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo - 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo -(100 rows) - --- bug before 9.3.5 due to sloppy handling of remote-estimate parameters ---Testcase 53: -SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5)); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo -(4 rows) - ---Testcase 54: -SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5)); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo -(4 rows) - --- we should not push order by clause with volatile expressions or unsafe --- collations ---Testcase 55: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 ORDER BY ft2.c1, random(); - QUERY PLAN ----------------------------------------------------------------------------------------------- - Sort - Output: c1, c2, c3, c4, c5, c6, c7, c8, (random()) - Sort Key: ft2.c1, (random()) - -> Foreign Scan on public.ft2 - Output: c1, c2, c3, c4, c5, c6, c7, c8, random() - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(6 rows) - ---Testcase 56: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C"; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Sort - Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text) - Sort Key: ft2.c1, ft2.c3 COLLATE "C" - -> Foreign Scan on public.ft2 - Output: c1, c2, c3, c4, c5, c6, c7, c8, c3 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(6 rows) - --- user-defined operator/function ---Testcase 494: -CREATE FUNCTION sqlite_fdw_abs(int) RETURNS int AS $$ -BEGIN -RETURN abs($1); -END -$$ LANGUAGE plpgsql IMMUTABLE; ---Testcase 495: -CREATE OPERATOR === ( - LEFTARG = int, - RIGHTARG = int, - PROCEDURE = int4eq, - COMMUTATOR = === -); --- built-in operators and functions can be shipped for remote execution ---Testcase 57: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan - Output: (count(c3)) - SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = abs(`c2`))) -(3 rows) - ---Testcase 58: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); - count -------- - 9 -(1 row) - ---Testcase 59: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; - QUERY PLAN ---------------------------------------------------------------------------- - Foreign Scan - Output: (count(c3)) - SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = `c2`)) -(3 rows) - ---Testcase 60: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; - count -------- - 9 -(1 row) - --- by default, user-defined ones cannot ---Testcase 61: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---Testcase 62: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); - count -------- - 9 -(1 row) - ---Testcase 63: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---Testcase 64: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - count -------- - 9 -(1 row) - --- ORDER BY can be shipped, though ---Testcase 496: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Limit - Output: c1, c2, c3, c4, c5, c6, c7, c8 - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(6 rows) - ---Testcase 497: -SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - --- but let's put them in an extension ... -ALTER EXTENSION sqlite_fdw ADD FUNCTION sqlite_fdw_abs(int); -ALTER EXTENSION sqlite_fdw ADD OPERATOR === (int, int); ---ALTER SERVER sqlite_svr2 OPTIONS (ADD extensions 'sqlite_fdw'); --- ... now they can be shipped ---Testcase 498: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---Testcase 499: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); - count -------- - 9 -(1 row) - ---Testcase 500: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---Testcase 501: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - count -------- - 9 -(1 row) - --- and both ORDER BY and LIMIT can be shipped ---Testcase 502: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Limit - Output: c1, c2, c3, c4, c5, c6, c7, c8 - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(6 rows) - ---Testcase 503: -SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - --- =================================================================== --- JOIN queries --- =================================================================== --- Analyze ft4 and ft5 so that we have better statistics. These tables do not --- have use_remote_estimate set. ---ANALYZE ft4; ---ANALYZE ft5; --- join two tables ---Testcase 65: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1, t1.c3 - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 66: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- join three tables ---Testcase 67: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3, t1.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3`, r1.`c3` FROM ((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) INNER JOIN main."T 3" r4 ON (((r1.`C 1` = r4.`c1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 68: -SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 22 | 2 | AAA022 - 24 | 4 | AAA024 - 26 | 6 | AAA026 - 28 | 8 | AAA028 - 30 | 0 | AAA030 - 32 | 2 | AAA032 - 34 | 4 | AAA034 - 36 | 6 | AAA036 - 38 | 8 | AAA038 - 40 | 0 | AAA040 -(10 rows) - --- left outer join ---Testcase 69: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1 - SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 LEFT JOIN main."T 4" r2 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r1.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 70: -SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c1 -----+---- - 22 | - 24 | 24 - 26 | - 28 | - 30 | 30 - 32 | - 34 | - 36 | 36 - 38 | - 40 | -(10 rows) - --- left outer join three tables ---Testcase 71: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 72: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- left outer join + placement of clauses. --- clauses within the nullable side are not pulled up, but top level clause on --- non-nullable side is pushed into non-nullable side ---Testcase 73: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; - QUERY PLAN ------------------------------------------------------------------------------------ - Hash Left Join - Output: t1.c1, t1.c2, ft5.c1, ft5.c2 - Hash Cond: (t1.c1 = ft5.c1) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) - -> Hash - Output: ft5.c1, ft5.c2 - -> Foreign Scan on public.ft5 - Output: ft5.c1, ft5.c2 - SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) -(11 rows) - ---Testcase 74: -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; - c1 | c2 | c1 | c2 -----+----+----+---- - 2 | 3 | | - 4 | 5 | | - 6 | 7 | 6 | 7 - 8 | 9 | | -(4 rows) - --- clauses within the nullable side are not pulled up, but the top level clause --- on nullable side is not pushed down into nullable side ---Testcase 75: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) - WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; - QUERY PLAN ------------------------------------------------------------------------------------ - Hash Left Join - Output: t1.c1, t1.c2, ft5.c1, ft5.c2 - Hash Cond: (t1.c1 = ft5.c1) - Filter: ((ft5.c1 < 10) OR (ft5.c1 IS NULL)) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) - -> Hash - Output: ft5.c1, ft5.c2 - -> Foreign Scan on public.ft5 - Output: ft5.c1, ft5.c2 - SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) -(12 rows) - ---Testcase 76: -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) - WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; - c1 | c2 | c1 | c2 -----+----+----+---- - 2 | 3 | | - 4 | 5 | | - 6 | 7 | 6 | 7 - 8 | 9 | | -(4 rows) - --- right outer join ---Testcase 77: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1 - SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r2 LEFT JOIN main."T 4" r1 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r2.`c1` ASC NULLS LAST, r1.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 78: -SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; - c1 | c1 -----+---- - | 22 - 24 | 24 - | 26 - | 28 - 30 | 30 - | 32 - | 34 - 36 | 36 - | 38 - | 40 -(10 rows) - --- right outer join three tables ---Testcase 79: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 80: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 22 | 2 | AAA022 - 24 | 4 | AAA024 - 26 | 6 | AAA026 - 28 | 8 | AAA028 - 30 | 0 | AAA030 - 32 | 2 | AAA032 - 34 | 4 | AAA034 - 36 | 6 | AAA036 - 38 | 8 | AAA038 - 40 | 0 | AAA040 -(10 rows) - --- full outer join ---Testcase 81: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1 - -> Sort - Output: t1.c1, t2.c1 - Sort Key: t1.c1, t2.c1 - -> Merge Full Join - Output: t1.c1, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - -> Sort - Output: t1.c1 - Sort Key: t1.c1 - -> Foreign Scan on public.ft4 t1 - Output: t1.c1 - SQLite query: SELECT `c1` FROM main."T 3" - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" -(20 rows) - ---Testcase 82: -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; - c1 | c1 ------+---- - 92 | - 94 | - 96 | 96 - 98 | - 100 | - | 3 - | 9 - | 15 - | 21 - | 27 -(10 rows) - --- full outer join with restrictions on the joining relations --- a. the joining relations are both base relations ---Testcase 83: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; - QUERY PLAN -------------------------------------------------------------------------------------------------------- - Sort - Output: ft4.c1, ft5.c1 - Sort Key: ft4.c1, ft5.c1 - -> Hash Full Join - Output: ft4.c1, ft5.c1 - Hash Cond: (ft4.c1 = ft5.c1) - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.c2, ft4.c3 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Hash - Output: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c1 - SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(14 rows) - ---Testcase 84: -SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; - c1 | c1 -----+---- - 50 | - 52 | - 54 | 54 - 56 | - 58 | - 60 | 60 - | 51 - | 57 -(8 rows) - ---Testcase 85: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; - QUERY PLAN -------------------------------------------------------------------------------------------------------- - Limit - Output: 1 - -> Merge Full Join - Output: 1 - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.c2, ft4.c3 - SQLite query: SELECT NULL FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Materialize - Output: ft5.c1, ft5.c2, ft5.c3 - -> Foreign Scan on public.ft5 - Output: ft5.c1, ft5.c2, ft5.c3 - SQLite query: SELECT NULL FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(12 rows) - ---Testcase 86: -SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; - ?column? ----------- - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 -(10 rows) - --- b. one of the joining relations is a base relation and the other is a join --- relation ---Testcase 87: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: ft4.c1, t2.c1, t3.c1 - Sort Key: ft4.c1, t2.c1, t3.c1 - -> Hash Full Join - Output: ft4.c1, t2.c1, t3.c1 - Hash Cond: (t2.c1 = ft4.c1) - -> Foreign Scan - Output: t2.c1, t3.c1 - SQLite query: SELECT r5.`c1`, r6.`c1` FROM (main."T 3" r5 LEFT JOIN main."T 4" r6 ON (((r5.`c1` = r6.`c1`)))) WHERE ((r5.`c1` >= 50)) AND ((r5.`c1` <= 60)) - -> Hash - Output: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(14 rows) - ---Testcase 88: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; - c1 | a | b -----+----+---- - 50 | 50 | - 52 | 52 | - 54 | 54 | 54 - 56 | 56 | - 58 | 58 | - 60 | 60 | 60 -(6 rows) - --- c. test deparsing the remote query as nested subqueries ---Testcase 89: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Sort - Output: ft4.c1, ft4_1.c1, ft5.c1 - Sort Key: ft4.c1, ft4_1.c1, ft5.c1 - -> Hash Full Join - Output: ft4.c1, ft4_1.c1, ft5.c1 - Hash Cond: (ft4_1.c1 = ft4.c1) - -> Hash Full Join - Output: ft4_1.c1, ft5.c1 - Hash Cond: (ft4_1.c1 = ft5.c1) - Filter: ((ft4_1.c1 IS NULL) OR (ft4_1.c1 IS NOT NULL)) - -> Foreign Scan on public.ft4 ft4_1 - Output: ft4_1.c1, ft4_1.c2, ft4_1.c3 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Hash - Output: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c1 - SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Hash - Output: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(23 rows) - ---Testcase 90: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; - c1 | a | b -----+----+---- - 50 | 50 | - 52 | 52 | - 54 | 54 | 54 - 56 | 56 | - 58 | 58 | - 60 | 60 | 60 - | | 51 - | | 57 -(8 rows) - --- d. test deparsing rowmarked relations as subqueries ---Testcase 91: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------- - LockRows - Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* - -> Sort - Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* - Sort Key: ft4.c1, ft5.c1 - -> Nested Loop - Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* - -> Foreign Scan on "S 1"."T 3" - Output: "T 3".c1, "T 3".* - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` = 50)) - -> Materialize - Output: ft4.c1, ft4.*, ft5.c1, ft5.* - -> Merge Full Join - Output: ft4.c1, ft4.*, ft5.c1, ft5.* - Merge Cond: (ft4.c1 = ft5.c1) - Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL)) - -> Sort - Output: ft4.c1, ft4.* - Sort Key: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.* - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Sort - Output: ft5.c1, ft5.* - Sort Key: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c1, ft5.* - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(28 rows) - ---Testcase 92: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; - c1 | a | b -----+----+---- - 50 | 50 | - 50 | 52 | - 50 | 54 | 54 - 50 | 56 | - 50 | 58 | - 50 | 60 | 60 - 50 | | 51 - 50 | | 57 -(8 rows) - --- full outer join + inner join ---Testcase 93: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1, t3.c1 - -> Sort - Output: t1.c1, t2.c1, t3.c1 - Sort Key: t1.c1, t2.c1, t3.c1 - -> Hash Full Join - Output: t1.c1, t2.c1, t3.c1 - Hash Cond: (t3.c1 = t2.c1) - -> Foreign Scan on public.ft4 t3 - Output: t3.c1, t3.c2, t3.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Hash - Output: t1.c1, t2.c1 - -> Foreign Scan - Output: t1.c1, t2.c1 - SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 INNER JOIN main."T 4" r2 ON (((r1.`c1` = (r2.`c1` + 1))) AND ((r1.`c1` >= 50)) AND ((r1.`c1` <= 60)))) -(16 rows) - ---Testcase 94: -SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; - c1 | c1 | c1 -----+----+---- - 52 | 51 | - 58 | 57 | - | | 2 - | | 4 - | | 6 - | | 8 - | | 10 - | | 12 - | | 14 - | | 16 -(10 rows) - --- full outer join three tables ---Testcase 95: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t3.c3 - -> Hash Full Join - Output: t1.c1, t2.c2, t3.c3 - Hash Cond: (t2.c1 = t3.c1) - -> Hash Full Join - Output: t1.c1, t2.c2, t2.c1 - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft2 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Hash - Output: t2.c2, t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Hash - Output: t3.c3, t3.c1 - -> Foreign Scan on public.ft4 t3 - Output: t3.c3, t3.c1 - SQLite query: SELECT `c1`, `c3` FROM main."T 3" -(21 rows) - ---Testcase 96: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- full outer join + right outer join ---Testcase 97: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 98: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 22 | 2 | AAA022 - 24 | 4 | AAA024 - 26 | 6 | AAA026 - 28 | 8 | AAA028 - 30 | 0 | AAA030 - 32 | 2 | AAA032 - 34 | 4 | AAA034 - 36 | 6 | AAA036 - 38 | 8 | AAA038 - 40 | 0 | AAA040 -(10 rows) - --- right outer join + full outer join ---Testcase 99: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t3.c3 - -> Hash Full Join - Output: t1.c1, t2.c2, t3.c3 - Hash Cond: (t2.c1 = t3.c1) - -> Nested Loop Left Join - Output: t2.c2, t2.c1, t1.c1 - Join Filter: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Materialize - Output: t1.c1 - -> Foreign Scan on public.ft2 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Hash - Output: t3.c3, t3.c1 - -> Foreign Scan on public.ft4 t3 - Output: t3.c3, t3.c1 - SQLite query: SELECT `c1`, `c3` FROM main."T 3" -(21 rows) - ---Testcase 100: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- full outer join + left outer join ---Testcase 101: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t3.c3 - -> Nested Loop Left Join - Output: t1.c1, t2.c2, t3.c3 - Join Filter: (t2.c1 = t3.c1) - -> Hash Full Join - Output: t1.c1, t2.c2, t2.c1 - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft2 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Hash - Output: t2.c2, t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Materialize - Output: t3.c3, t3.c1 - -> Foreign Scan on public.ft4 t3 - Output: t3.c3, t3.c1 - SQLite query: SELECT `c1`, `c3` FROM main."T 3" -(21 rows) - ---Testcase 102: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- left outer join + full outer join ---Testcase 103: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t3.c3 - -> Hash Full Join - Output: t1.c1, t2.c2, t3.c3 - Hash Cond: (t2.c1 = t3.c1) - -> Nested Loop Left Join - Output: t1.c1, t2.c2, t2.c1 - Join Filter: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft2 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Materialize - Output: t2.c2, t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Hash - Output: t3.c3, t3.c1 - -> Foreign Scan on public.ft4 t3 - Output: t3.c3, t3.c1 - SQLite query: SELECT `c1`, `c3` FROM main."T 3" -(21 rows) - ---Testcase 104: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- right outer join + left outer join ---Testcase 105: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 106: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 11 | 1 | - 12 | 2 | AAA012 - 13 | 3 | - 14 | 4 | AAA014 - 15 | 5 | - 16 | 6 | AAA016 - 17 | 7 | - 18 | 8 | AAA018 - 19 | 9 | - 20 | 0 | AAA020 -(10 rows) - --- left outer join + right outer join ---Testcase 107: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c2, t3.c3 - SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM (main."T 3" r4 LEFT JOIN (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 108: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; - c1 | c2 | c3 -----+----+-------- - 22 | 2 | AAA022 - 24 | 4 | AAA024 - 26 | 6 | AAA026 - 28 | 8 | AAA028 - 30 | 0 | AAA030 - 32 | 2 | AAA032 - 34 | 4 | AAA034 - 36 | 6 | AAA036 - 38 | 8 | AAA038 - 40 | 0 | AAA040 -(10 rows) - --- full outer join + WHERE clause, only matched rows ---Testcase 109: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1 - -> Sort - Output: t1.c1, t2.c1 - Sort Key: t1.c1, t2.c1 - -> Merge Full Join - Output: t1.c1, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - Filter: ((t1.c1 = t2.c1) OR (t1.c1 IS NULL)) - -> Sort - Output: t1.c1 - Sort Key: t1.c1 - -> Foreign Scan on public.ft4 t1 - Output: t1.c1 - SQLite query: SELECT `c1` FROM main."T 3" - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" -(21 rows) - ---Testcase 110: -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c1 -----+---- - 66 | 66 - 72 | 72 - 78 | 78 - 84 | 84 - 90 | 90 - 96 | 96 - | 3 - | 9 - | 15 - | 21 -(10 rows) - --- full outer join + WHERE clause with shippable extensions set ---Testcase 504: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t1.c3 - -> Hash Full Join - Output: t1.c1, t2.c2, t1.c3 - Hash Cond: (t2.c1 = t1.c1) - Filter: (sqlite_fdw_abs(t1.c1) > 0) - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Hash - Output: t1.c1, t1.c3 - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3 - SQLite query: SELECT `C 1`, `c3` FROM main."T 1" -(14 rows) - ---ALTER SERVER sqlite_svr2 OPTIONS (DROP extensions); --- full outer join + WHERE clause with shippable extensions not set ---Testcase 505: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c2, t1.c3 - -> Hash Full Join - Output: t1.c1, t2.c2, t1.c3 - Hash Cond: (t2.c1 = t1.c1) - Filter: (sqlite_fdw_abs(t1.c1) > 0) - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Hash - Output: t1.c1, t1.c3 - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3 - SQLite query: SELECT `C 1`, `c3` FROM main."T 1" -(14 rows) - -ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); -ERROR: server "loopback" does not exist --- join two tables with FOR UPDATE clause --- tests whole-row reference for row marks ---Testcase 111: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> LockRows - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> Foreign Scan - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST - -> Sort - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 - -> Hash Join - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST - -> Hash - Output: t2.c1, t2.* - -> Foreign Scan on public.ft2 t2 - Output: t2.c1, t2.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(21 rows) - ---Testcase 112: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - ---Testcase 113: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> LockRows - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> Foreign Scan - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST - -> Sort - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 - -> Hash Join - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST - -> Hash - Output: t2.c1, t2.* - -> Foreign Scan on public.ft2 t2 - Output: t2.c1, t2.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(21 rows) - ---Testcase 114: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- join two tables with FOR SHARE clause ---Testcase 115: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> LockRows - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> Foreign Scan - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST - -> Sort - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 - -> Hash Join - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST - -> Hash - Output: t2.c1, t2.* - -> Foreign Scan on public.ft2 t2 - Output: t2.c1, t2.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(21 rows) - ---Testcase 116: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - ---Testcase 117: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> LockRows - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - -> Foreign Scan - Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST - -> Sort - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 - -> Hash Join - Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3, t1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST - -> Hash - Output: t2.c1, t2.* - -> Foreign Scan on public.ft2 t2 - Output: t2.c1, t2.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(21 rows) - ---Testcase 118: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- join in CTE ---Testcase 119: -EXPLAIN (VERBOSE, COSTS OFF) -WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------- - Limit - Output: t.c1_1, t.c2_1, t.c1_3 - CTE t - -> Merge Join - Output: t1.c1, t1.c3, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - -> Sort - Output: t1.c1, t1.c3 - Sort Key: t1.c1 - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c3 - SQLite query: SELECT `C 1`, `c3` FROM main."T 1" - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t.c1_1, t.c2_1, t.c1_3 - Sort Key: t.c1_3, t.c1_1 - -> CTE Scan on t - Output: t.c1_1, t.c2_1, t.c1_3 -(23 rows) - ---Testcase 120: -WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; - c1_1 | c2_1 -------+------ - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- ctid with whole-row reference ---Testcase 121: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3 - SQLite query: SELECT r1.`ctid`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r1.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - --- SEMI JOIN, not pushed down ---Testcase 122: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------- - Limit - Output: t1.c1 - -> Merge Semi Join - Output: t1.c1 - Merge Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST - -> Foreign Scan on public.ft2 t2 - Output: t2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST -(11 rows) - ---Testcase 123: -SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; - c1 ------ - 101 - 102 - 103 - 104 - 105 - 106 - 107 - 108 - 109 - 110 -(10 rows) - --- ANTI JOIN, not pushed down ---Testcase 124: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------- - Limit - Output: t1.c1 - -> Nested Loop Anti Join - Output: t1.c1 - Join Filter: (t1.c1 = t2.c2) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST - -> Materialize - Output: t2.c2 - -> Foreign Scan on public.ft2 t2 - Output: t2.c2 - SQLite query: SELECT `c2` FROM main."T 1" -(13 rows) - ---Testcase 125: -SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; - c1 ------ - 110 - 111 - 112 - 113 - 114 - 115 - 116 - 117 - 118 - 119 -(10 rows) - --- CROSS JOIN can be pushed down ---Testcase 126: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1 - SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (TRUE)) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 127: -SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - c1 | c1 -----+----- - 1 | 101 - 1 | 102 - 1 | 103 - 1 | 104 - 1 | 105 - 1 | 106 - 1 | 107 - 1 | 108 - 1 | 109 - 1 | 110 -(10 rows) - --- different server, not pushed down. No result expected. ---Testcase 128: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------- - Limit - Output: t1.c1, t2.c1 - -> Merge Join - Output: t1.c1, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft5 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST - -> Materialize - Output: t2.c1, t2.c2, t2.c3 - -> Foreign Scan on public.ft6 t2 - Output: t2.c1, t2.c2, t2.c3 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST -(13 rows) - ---Testcase 129: -SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - c1 | c1 -----+---- -(0 rows) - --- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS --- JOIN since c8 in both tables has same value. ---Testcase 130: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1 - SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`c8` = r2.`c8`)))) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 131: -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; - c1 | c1 -----+----- - 1 | 101 - 1 | 102 - 1 | 103 - 1 | 104 - 1 | 105 - 1 | 106 - 1 | 107 - 1 | 108 - 1 | 109 - 1 | 110 -(10 rows) - --- unsafe conditions on one side (c8 has a UDT), not pushed down. ---Testcase 132: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1, t1.c3 - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) WHERE ((r1.`c8` = 'foo')) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 133: -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- join where unsafe to pushdown condition in WHERE clause has a column not --- in the SELECT clause. In this test unsafe clause needs to have column --- references from both joining sides so that the clause is not pushed down --- into one of the joining sides. ---Testcase 134: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: t1.c1, t2.c1, t1.c3 - SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c8` = r2.`c8`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 -(3 rows) - ---Testcase 135: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; - c1 | c1 ------+----- - 101 | 101 - 102 | 102 - 103 | 103 - 104 | 104 - 105 | 105 - 106 | 106 - 107 | 107 - 108 | 108 - 109 | 109 - 110 | 110 -(10 rows) - --- Aggregate after UNION, for testing setrefs ---Testcase 136: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------- - Limit - Output: t1.c1, (avg((t1.c1 + t2.c1))) - -> Sort - Output: t1.c1, (avg((t1.c1 + t2.c1))) - Sort Key: t1.c1 - -> HashAggregate - Output: t1.c1, avg((t1.c1 + t2.c1)) - Group Key: t1.c1 - -> HashAggregate - Output: t1.c1, t2.c1 - Group Key: t1.c1, t2.c1 - -> Append - -> Merge Join - Output: t1.c1, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - -> Sort - Output: t1.c1 - Sort Key: t1.c1 - -> Foreign Scan on public.ft1 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Merge Join - Output: t1_1.c1, t2_1.c1 - Merge Cond: (t1_1.c1 = t2_1.c1) - -> Sort - Output: t1_1.c1 - Sort Key: t1_1.c1 - -> Foreign Scan on public.ft1 t1_1 - Output: t1_1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t2_1.c1 - Sort Key: t2_1.c1 - -> Foreign Scan on public.ft2 t2_1 - Output: t2_1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" -(42 rows) - ---Testcase 137: -SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; - t1c1 | avg -------+---------------------- - 101 | 202.0000000000000000 - 102 | 204.0000000000000000 - 103 | 206.0000000000000000 - 104 | 208.0000000000000000 - 105 | 210.0000000000000000 - 106 | 212.0000000000000000 - 107 | 214.0000000000000000 - 108 | 216.0000000000000000 - 109 | 218.0000000000000000 - 110 | 220.0000000000000000 -(10 rows) - --- join with lateral reference ---Testcase 138: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t1."C 1" - -> Nested Loop - Output: t1."C 1" - -> Foreign Scan on "S 1"."T 1" t1 - Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST - -> Unique - Output: t2.c1, t3.c1 - -> Foreign Scan - Output: t2.c1, t3.c1 - SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = ?)))) ORDER BY r1.`C 1` ASC NULLS LAST -(12 rows) - ---Testcase 139: -SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; - C 1 ------ - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 -(10 rows) - --- non-Var items in targetlist of the nullable rel of a join preventing --- push-down in some cases --- unable to push {ft1, ft2} ---Testcase 140: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Nested Loop Left Join - Output: (13), ft2.c1 - Join Filter: (13 = ft2.c1) - -> Foreign Scan on public.ft2 - Output: ft2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` >= 10)) AND ((`C 1` <= 15)) - -> Materialize - Output: (13) - -> Foreign Scan on public.ft1 - Output: 13 - SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 13)) -(11 rows) - ---Testcase 141: -SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; - a | c1 -----+---- - | 10 - | 11 - | 12 - 13 | 13 - | 14 - | 15 -(6 rows) - --- ok to push {ft1, ft2} but not {ft1, ft2, ft4} ---Testcase 142: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; - QUERY PLAN -------------------------------------------------------------------------------------------------- - Hash Right Join - Output: ft4.c1, (13), ft1.c1, ft2.c1 - Hash Cond: (ft1.c1 = ft4.c1) - -> Nested Loop - Output: ft1.c1, ft2.c1, 13 - -> Foreign Scan on public.ft1 - Output: ft1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) - -> Materialize - Output: ft2.c1 - -> Foreign Scan on public.ft2 - Output: ft2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) - -> Hash - Output: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 10)) AND ((`c1` <= 15)) -(18 rows) - ---Testcase 143: -SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; - c1 | a | b | c -----+----+----+---- - 12 | 13 | 12 | 12 - 10 | | | - 14 | | | -(3 rows) - --- join with nullable side with some columns with null values ---Testcase 144: -UPDATE ft5 SET c3 = null where c1 % 9 = 0; ---Testcase 145: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 - SQLite query: SELECT CASE WHEN ( r1.`c1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) THEN ("(" || COALESCE(r1.`c1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '')|| ")") END, r1.`c1`, r1.`c2`, r1.`c3`, r2.`c1`, r2.`c2` FROM (main."T 4" r1 INNER JOIN main."T 3" r2 ON (((r1.`c1` = r2.`c1`)) AND ((r2.`c1` >= 10)) AND ((r2.`c1` <= 30)))) ORDER BY r1.`c1` ASC NULLS LAST -(3 rows) - ---Testcase 146: -SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; - ft5 | c1 | c2 | c3 | c1 | c2 -----------------+----+----+--------+----+---- - (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13 - (18,19,) | 18 | 19 | | 18 | 19 - (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25 - (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31 -(4 rows) - --- multi-way join involving multiple merge joins --- (this case used to have EPQ-related planning problems) ---Testcase 506: -CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1)); ---Testcase 507: -INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; -ANALYZE local_tbl; -SET enable_nestloop TO false; -SET enable_hashjoin TO false; ---Testcase 147: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 - AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - LockRows - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid - -> Merge Join - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid - Merge Cond: (local_tbl.c1 = ft1.c2) - -> Index Scan using local_tbl_pkey on public.local_tbl - Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid - -> Sort - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* - Sort Key: ft1.c2 - -> Foreign Scan - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* - SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r3.`c1`, r3.`c2`, r3.`c3`, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END, r4.`c1`, r4.`c2`, r4.`c3`, CASE WHEN ( r4.`c1` IS NOT NULL) OR ( r4.`c2` IS NOT NULL) OR ( r4.`c3` IS NOT NULL) THEN ("(" || COALESCE(r4.`c1`, '') || "," || COALESCE(r4.`c2`, '') || "," || COALESCE(r4.`c3`, '')|| ")") END FROM (((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r2.`C 1` < 100)) AND ((r1.`C 1` < 100)))) INNER JOIN main."T 3" r3 ON (((r1.`c2` = r3.`c1`)))) INNER JOIN main."T 4" r4 ON (((r1.`c2` = r4.`c1`)))) - -> Merge Join - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* - Merge Cond: (ft1.c2 = ft5.c1) - -> Sort - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* - Sort Key: ft1.c2 - -> Merge Join - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* - Merge Cond: (ft1.c2 = ft4.c1) - -> Sort - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* - Sort Key: ft1.c2 - -> Merge Join - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* - Merge Cond: (ft1.c1 = ft2.c1) - -> Sort - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* - Sort Key: ft1.c1 - -> Foreign Scan on public.ft1 - Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) - -> Sort - Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* - Sort Key: ft2.c1 - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) - -> Sort - Output: ft4.c1, ft4.c2, ft4.c3, ft4.* - Sort Key: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.c2, ft4.c3, ft4.* - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" - -> Sort - Output: ft5.c1, ft5.c2, ft5.c3, ft5.* - Sort Key: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c1, ft5.c2, ft5.c3, ft5.* - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" -(52 rows) - ---Testcase 148: -SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 - AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 ORDER BY ft1.c1 FOR UPDATE; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 | c1 | c2 | c3 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------ - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 - 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 -(10 rows) - -RESET enable_nestloop; -RESET enable_hashjoin; ---DROP TABLE local_tbl; --- check join pushdown in situations where multiple userids are involved ---Testcase 508: -CREATE ROLE regress_view_owner SUPERUSER; ---Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; -GRANT SELECT ON ft4 TO regress_view_owner; -GRANT SELECT ON ft5 TO regress_view_owner; ---Testcase 510: -CREATE VIEW v4 AS SELECT * FROM ft4; ---Testcase 511: -CREATE VIEW v5 AS SELECT * FROM ft5; -ALTER VIEW v5 OWNER TO regress_view_owner; ---Testcase 149: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, different view owners - QUERY PLAN ---------------------------------------------------------------------------- - Limit - Output: ft4.c1, ft5.c2, ft5.c1 - -> Sort - Output: ft4.c1, ft5.c2, ft5.c1 - Sort Key: ft4.c1, ft5.c1 - -> Merge Right Join - Output: ft4.c1, ft5.c2, ft5.c1 - Merge Cond: (ft5.c1 = ft4.c1) - -> Sort - Output: ft5.c2, ft5.c1 - Sort Key: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c2, ft5.c1 - SQLite query: SELECT `c1`, `c2` FROM main."T 4" - -> Sort - Output: ft4.c1 - Sort Key: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1 - SQLite query: SELECT `c1` FROM main."T 3" -(20 rows) - ---Testcase 150: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c2 -----+---- - 22 | - 24 | 25 - 26 | - 28 | - 30 | 31 - 32 | - 34 | - 36 | 37 - 38 | - 40 | -(10 rows) - -ALTER VIEW v4 OWNER TO regress_view_owner; ---Testcase 151: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: ft4.c1, ft5.c2, ft5.c1 - SQLite query: SELECT r6.`c1`, r9.`c2`, r9.`c1` FROM (main."T 3" r6 LEFT JOIN main."T 4" r9 ON (((r6.`c1` = r9.`c1`)))) ORDER BY r6.`c1` ASC NULLS LAST, r9.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 152: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c2 -----+---- - 22 | - 24 | 25 - 26 | - 28 | - 30 | 31 - 32 | - 34 | - 36 | 37 - 38 | - 40 | -(10 rows) - ---Testcase 153: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, view owner not current user - QUERY PLAN ---------------------------------------------------------------------------- - Limit - Output: ft4.c1, t2.c2, t2.c1 - -> Sort - Output: ft4.c1, t2.c2, t2.c1 - Sort Key: ft4.c1, t2.c1 - -> Merge Right Join - Output: ft4.c1, t2.c2, t2.c1 - Merge Cond: (t2.c1 = ft4.c1) - -> Sort - Output: t2.c2, t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `c1`, `c2` FROM main."T 4" - -> Sort - Output: ft4.c1 - Sort Key: ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.c1 - SQLite query: SELECT `c1` FROM main."T 3" -(20 rows) - ---Testcase 154: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c2 -----+---- - 22 | - 24 | 25 - 26 | - 28 | - 30 | 31 - 32 | - 34 | - 36 | 37 - 38 | - 40 | -(10 rows) - -ALTER VIEW v4 OWNER TO CURRENT_USER; ---Testcase 155: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: ft4.c1, t2.c2, t2.c1 - SQLite query: SELECT r6.`c1`, r2.`c2`, r2.`c1` FROM (main."T 3" r6 LEFT JOIN main."T 4" r2 ON (((r6.`c1` = r2.`c1`)))) ORDER BY r6.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 -(3 rows) - ---Testcase 156: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - c1 | c2 -----+---- - 22 | - 24 | 25 - 26 | - 28 | - 30 | 31 - 32 | - 34 | - 36 | 37 - 38 | - 40 | -(10 rows) - -ALTER VIEW v4 OWNER TO regress_view_owner; --- cleanup ---Testcase 512: -DROP OWNED BY regress_view_owner; ---Testcase 513: -DROP ROLE regress_view_owner; --- =================================================================== --- Aggregate and grouping queries --- =================================================================== --- Simple aggregates ---Testcase 157: -explain (verbose, costs off) -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 - -> Sort - Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 - Sort Key: (count(ft1.c6)), (sum(ft1.c1)) - -> GroupAggregate - Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c6, c1, c2 - SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST -(11 rows) - ---Testcase 158: -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; - count | sum | avg | min | max | stddev | sum2 --------+-------+----------------------+-----+------+--------+------- - 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 - 100 | 49700 | 497.0000000000000000 | 2 | 992 | 0 | 49700 - 100 | 49800 | 498.0000000000000000 | 3 | 993 | 0 | 49800 - 100 | 49900 | 499.0000000000000000 | 4 | 994 | 0 | 49900 - 100 | 50500 | 505.0000000000000000 | 0 | 1000 | 0 | 50500 -(5 rows) - ---Testcase 514: -explain (verbose, costs off) -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), (((sum(c1)) * ((random() <= '1'::double precision))::integer)), c2 - -> Result - Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 - -> Sort - Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 - Sort Key: (count(ft1.c6)), (sum(ft1.c1)) - -> GroupAggregate - Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c6, c1, c2 - SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST -(13 rows) - ---Testcase 515: -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; - count | sum | avg | min | max | stddev | sum2 --------+-------+----------------------+-----+-----+--------+------- - 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 -(1 row) - --- Aggregate is not pushed down as aggregation contains random() ---Testcase 159: -explain (verbose, costs off) -select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1; - QUERY PLAN -------------------------------------------------------------------------------- - Aggregate - Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1) - -> Foreign Scan on public.ft1 - Output: c1 - SQLite query: SELECT `C 1` FROM main."T 1" -(5 rows) - --- Aggregate over join query ---Testcase 160: -explain (verbose, costs off) -select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: (count(*)), (sum(t1.c1)), (avg(t2.c1)) - SQLite query: SELECT count(*), sum(r1.`C 1`), avg(r2.`C 1`) FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r2.`c2` = 6)) AND ((r1.`c2` = 6)))) -(3 rows) - ---Testcase 161: -select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; - count | sum | avg --------+---------+----- - 10000 | 5010000 | 501 -(1 row) - --- Not pushed down due to local conditions present in underneath input rel ---Testcase 162: -explain (verbose, costs off) -select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: sum(t1.c1), count(t2.c1) - -> Merge Join - Output: t1.c1, t2.c1 - Merge Cond: (t1.c1 = t2.c1) - Join Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision) - -> Sort - Output: t1.c1 - Sort Key: t1.c1 - -> Foreign Scan on public.ft1 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" - -> Sort - Output: t2.c1 - Sort Key: t2.c1 - -> Foreign Scan on public.ft2 t2 - Output: t2.c1 - SQLite query: SELECT `C 1` FROM main."T 1" -(18 rows) - --- GROUP BY clause having expressions ---Testcase 163: -explain (verbose, costs off) -select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: ((c2 / 2)), ((sum(c2) * (c2 / 2))) - SQLite query: SELECT (`c2` / 2), (sum(`c2`) * (`c2` / 2)) FROM main."T 1" GROUP BY 1 ORDER BY (`c2` / 2) ASC NULLS LAST -(3 rows) - ---Testcase 164: -select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; - ?column? | ?column? -----------+---------- - 0 | 0 - 1 | 500 - 2 | 1800 - 3 | 3900 - 4 | 6800 -(5 rows) - --- Aggregates in subquery are pushed down. ---Testcase 165: -explain (verbose, costs off) -select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; - QUERY PLAN -------------------------------------------------------------------------------- - Aggregate - Output: count(ft1.c2), sum(ft1.c2) - -> Sort - Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision)) - Sort Key: ft1.c2, (sum(ft1.c1)) - -> HashAggregate - Output: ft1.c2, sum(ft1.c1), (sqrt((ft1.c1)::double precision)) - Group Key: ft1.c2, sqrt((ft1.c1)::double precision) - -> Foreign Scan on public.ft1 - Output: ft1.c2, sqrt((ft1.c1)::double precision), ft1.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -(11 rows) - ---Testcase 166: -select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; - count | sum --------+------ - 1000 | 4500 -(1 row) - --- Aggregate is still pushed down by taking unshippable expression out ---Testcase 167: -explain (verbose, costs off) -select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; - QUERY PLAN ---------------------------------------------------------------------------------------------------- - Sort - Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2 - Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2)) - -> Foreign Scan - Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2 - SQLite query: SELECT (sum(`C 1`) * `c2`), `c2` FROM main."T 1" GROUP BY 2 -(6 rows) - ---Testcase 168: -select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; - sum1 | sum2 -------+-------- - 0 | 0 - 1 | 49600 - 2 | 99400 - 3 | 149400 - 4 | 199600 - 5 | 250000 - 6 | 300600 - 7 | 351400 - 8 | 402400 - 9 | 453600 -(10 rows) - --- Aggregate with unshippable GROUP BY clause are not pushed ---Testcase 169: -explain (verbose, costs off) -select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1; - QUERY PLAN ------------------------------------------------------------------------------- - Sort - Output: ((c2 * ((random() <= '1'::double precision))::integer)) - Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer)) - -> HashAggregate - Output: ((c2 * ((random() <= '1'::double precision))::integer)) - Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer) - -> Foreign Scan on public.ft2 - Output: (c2 * ((random() <= '1'::double precision))::integer) - SQLite query: SELECT `c2` FROM main."T 1" -(9 rows) - --- GROUP BY clause in various forms, cardinal, alias and constant expression ---Testcase 516: -explain (verbose, costs off) -select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: (count(c2)), c2, 5, 7.0, 9 - SQLite query: SELECT count(`c2`), `c2`, 5, 7.0, 9 FROM main."T 1" GROUP BY 2, 3, 5 ORDER BY `c2` ASC NULLS LAST -(3 rows) - ---Testcase 517: -select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; - w | x | y | z ------+---+---+----- - 100 | 0 | 5 | 7.0 - 100 | 1 | 5 | 7.0 - 100 | 2 | 5 | 7.0 - 100 | 3 | 5 | 7.0 - 100 | 4 | 5 | 7.0 - 100 | 5 | 5 | 7.0 - 100 | 6 | 5 | 7.0 - 100 | 7 | 5 | 7.0 - 100 | 8 | 5 | 7.0 - 100 | 9 | 5 | 7.0 -(10 rows) - --- GROUP BY clause referring to same column multiple times --- Also, ORDER BY contains an aggregate function ---Testcase 170: -explain (verbose, costs off) -select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan - Output: c2, c2, (sum(c1)) - SQLite query: SELECT `c2`, `c2`, sum(`C 1`) FROM main."T 1" WHERE ((`c2` > 6)) GROUP BY 1, 2 ORDER BY sum(`C 1`) ASC NULLS LAST -(3 rows) - ---Testcase 171: -select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); - c2 | c2 -----+---- - 7 | 7 - 8 | 8 - 9 | 9 -(3 rows) - --- Testing HAVING clause shippability ---Testcase 172: -explain (verbose, costs off) -select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan - Output: c2, (sum(c1)) - SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 HAVING ((avg(`C 1`) < 500)) AND ((sum(`C 1`) < 49800)) ORDER BY `c2` ASC NULLS LAST -(3 rows) - ---Testcase 173: -select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; - c2 | sum -----+------- - 1 | 49600 - 2 | 49700 -(2 rows) - --- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down ---Testcase 174: -explain (verbose, costs off) -select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: count(*) - -> HashAggregate - Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision)) - Group Key: ft1.c5, sqrt((ft1.c2)::double precision) - Filter: ((avg(ft1.c1) < '500'::numeric) AND ((((avg(ft1.c1) / avg(ft1.c1)))::double precision * random()) <= '1'::double precision)) - -> Foreign Scan on public.ft1 - Output: ft1.c5, sqrt((ft1.c2)::double precision), ft1.c1 - SQLite query: SELECT `C 1`, `c2`, `c5` FROM main."T 1" -(9 rows) - ---Testcase 175: -select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; - count -------- - 49 -(1 row) - --- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down ---Testcase 176: -explain (verbose, costs off) -select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------- - Sort - Output: (sum(c1)), c2 - Sort Key: (sum(ft1.c1)) - -> GroupAggregate - Output: sum(c1), c2 - Group Key: ft1.c2 - Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric) - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(10 rows) - --- Remote aggregate in combination with a local Param (for the output --- of an initplan) can be trouble, per bug #15781 ---Testcase 518: -explain (verbose, costs off) -select exists(select 1 from pg_enum), sum(c1) from ft1; - QUERY PLAN ---------------------------------------------------- - Foreign Scan - Output: $0, (sum(ft1.c1)) - SQLite query: SELECT sum(`C 1`) FROM main."T 1" - InitPlan 1 (returns $0) - -> Seq Scan on pg_catalog.pg_enum -(5 rows) - ---Testcase 519: -select exists(select 1 from pg_enum), sum(c1) from ft1; - exists | sum ---------+-------- - f | 500500 -(1 row) - ---Testcase 520: -explain (verbose, costs off) -select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; - QUERY PLAN ----------------------------------------------------- - GroupAggregate - Output: ($0), sum(ft1.c1) - Group Key: $0 - InitPlan 1 (returns $0) - -> Seq Scan on pg_catalog.pg_enum - -> Foreign Scan on public.ft1 - Output: $0, ft1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" -(8 rows) - ---Testcase 521: -select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; - exists | sum ---------+-------- - f | 500500 -(1 row) - --- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates --- ORDER BY within aggregate, same column used to order ---Testcase 177: -explain (verbose, costs off) -select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------- - Sort - Output: (array_agg(c1 ORDER BY c1)), c2 - Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1)) - -> GroupAggregate - Output: array_agg(c1 ORDER BY c1), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST -(9 rows) - ---Testcase 178: -select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; - array_agg --------------------------------- - {1,11,21,31,41,51,61,71,81,91} - {2,12,22,32,42,52,62,72,82,92} - {3,13,23,33,43,53,63,73,83,93} - {4,14,24,34,44,54,64,74,84,94} - {5,15,25,35,45,55,65,75,85,95} - {6,16,26,36,46,56,66,76,86,96} - {7,17,27,37,47,57,67,77,87,97} - {8,18,28,38,48,58,68,78,88,98} - {9,19,29,39,49,59,69,79,89,99} - {10,20,30,40,50,60,70,80,90} -(10 rows) - --- ORDER BY within aggregate, different column used to order also using DESC ---Testcase 179: -explain (verbose, costs off) -select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; - QUERY PLAN ------------------------------------------------------------------------------------------------- - Aggregate - Output: array_agg(c5 ORDER BY c1 DESC) - -> Foreign Scan on public.ft2 - Output: c5, c1 - SQLite query: SELECT `C 1`, `c5` FROM main."T 1" WHERE ((`C 1` < 50)) AND ((`c2` = 6)) -(5 rows) - ---Testcase 180: -select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; - array_agg ------------------------------------------------------------------------------------------------------------------------------------------- - {"Mon Feb 16 00:00:00 1970","Fri Feb 06 00:00:00 1970","Tue Jan 27 00:00:00 1970","Sat Jan 17 00:00:00 1970","Wed Jan 07 00:00:00 1970"} -(1 row) - --- DISTINCT within aggregate ---Testcase 181: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------- - Sort - Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3)) - Sort Key: (array_agg(DISTINCT (t1.c1 % 5))) - -> GroupAggregate - Output: array_agg(DISTINCT (t1.c1 % 5)), ((t2.c1 % 3)) - Group Key: ((t2.c1 % 3)) - -> Sort - Output: ((t2.c1 % 3)), t1.c1 - Sort Key: ((t2.c1 % 3)) - -> Hash Full Join - Output: (t2.c1 % 3), t1.c1 - Hash Cond: (t1.c1 = t2.c1) - Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Hash - Output: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST -(21 rows) - ---Testcase 182: -select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - array_agg --------------- - {0,1,2,3,4} - {1,2,3,NULL} -(2 rows) - --- DISTINCT combined with ORDER BY within aggregate ---Testcase 183: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------- - Sort - Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3)) - Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))) - -> GroupAggregate - Output: array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5)), ((t2.c1 % 3)) - Group Key: ((t2.c1 % 3)) - -> Sort - Output: ((t2.c1 % 3)), t1.c1 - Sort Key: ((t2.c1 % 3)) - -> Hash Full Join - Output: (t2.c1 % 3), t1.c1 - Hash Cond: (t1.c1 = t2.c1) - Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Hash - Output: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST -(21 rows) - ---Testcase 184: -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - array_agg --------------- - {0,1,2,3,4} - {1,2,3,NULL} -(2 rows) - ---Testcase 185: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - QUERY PLAN --------------------------------------------------------------------------------------------------------------- - Sort - Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3)) - Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)) - -> GroupAggregate - Output: array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST), ((t2.c1 % 3)) - Group Key: ((t2.c1 % 3)) - -> Sort - Output: ((t2.c1 % 3)), t1.c1 - Sort Key: ((t2.c1 % 3)) - -> Hash Full Join - Output: (t2.c1 % 3), t1.c1 - Hash Cond: (t1.c1 = t2.c1) - Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Hash - Output: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST -(21 rows) - ---Testcase 186: -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - array_agg --------------- - {3,2,1,NULL} - {4,3,2,1,0} -(2 rows) - --- FILTER within aggregate ---Testcase 187: -explain (verbose, costs off) -select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; - QUERY PLAN ---------------------------------------------------------------------------------------------- - Sort - Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2 - Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5)))) - -> GroupAggregate - Output: sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5))), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(9 rows) - ---Testcase 188: -select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; - sum ------ - 510 - 520 - 530 - 540 - - - - - - -(10 rows) - --- DISTINCT, ORDER BY and FILTER within aggregate ---Testcase 189: -explain (verbose, costs off) -select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: sum((c1 % 3)), sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2)), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` = 6)) -(6 rows) - ---Testcase 190: -select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; - sum | sum | c2 ------+-----+---- - 99 | 1 | 6 -(1 row) - --- Outer query is aggregation query ---Testcase 191: -explain (verbose, costs off) -select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------ - Unique - Output: ((SubPlan 1)) - -> Sort - Output: ((SubPlan 1)) - Sort Key: ((SubPlan 1)) - -> Aggregate - Output: (SubPlan 1) - -> Foreign Scan on public.ft2 t2 - Output: t2.c2, t2.c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) - SubPlan 1 - -> Foreign Scan on public.ft1 t1 - Output: count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) - SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 6)) -(14 rows) - ---Testcase 192: -select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; - count -------- - 1 -(1 row) - --- Inner query is aggregation query ---Testcase 193: -explain (verbose, costs off) -select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; - QUERY PLAN --------------------------------------------------------------------------------------------- - Unique - Output: ((SubPlan 1)) - -> Sort - Output: ((SubPlan 1)) - Sort Key: ((SubPlan 1)) - -> Foreign Scan on public.ft2 t2 - Output: (SubPlan 1) - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) - SubPlan 1 - -> Aggregate - Output: count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1 - SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 6)) -(14 rows) - ---Testcase 194: -select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; - count -------- - 0 - 1 -(2 rows) - --- Aggregate not pushed down as FILTER condition is not pushable ---Testcase 195: -explain (verbose, costs off) -select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- - Sort - Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2 - Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision))) - -> GroupAggregate - Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(9 rows) - ---Testcase 196: -explain (verbose, costs off) -select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; - QUERY PLAN ------------------------------------------------------------------------- - Aggregate - Output: sum(ft1.c2) FILTER (WHERE (hashed SubPlan 1)) - -> Foreign Scan on public.ft1 - Output: ft1.c2 - SQLite query: SELECT `c2` FROM main."T 1" - SubPlan 1 - -> Foreign Scan on public.ft1 ft1_1 - Output: ft1_1.c2 - SQLite query: SELECT `c2` FROM main."T 1" WHERE ((`c2` < 5)) -(9 rows) - --- Ordered-sets within aggregate ---Testcase 197: -explain (verbose, costs off) -select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: c2, rank('10'::character varying) WITHIN GROUP (ORDER BY c6), percentile_cont((((c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)) - Group Key: ft1.c2 - Filter: (percentile_cont((((ft1.c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((ft1.c1)::double precision)) < '500'::double precision) - -> Foreign Scan on public.ft1 - Output: c2, c6, c1 - SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 10)) ORDER BY `c2` ASC NULLS LAST -(7 rows) - ---Testcase 198: -select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; - c2 | rank | percentile_cont -----+------+----------------- - 0 | 101 | 10 - 1 | 101 | 100 - 2 | 1 | 200 - 3 | 1 | 300 - 4 | 1 | 400 -(5 rows) - --- Using multiple arguments within aggregates ---Testcase 199: -explain (verbose, costs off) -select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: c1, rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2), c2 - Group Key: ft1.c1, ft1.c2 - -> Foreign Scan on public.ft1 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` = 6)) ORDER BY `c2` ASC NULLS LAST -(6 rows) - ---Testcase 200: -select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; - c1 | rank -----+------ - 6 | 1 -(1 row) - --- User defined function for user defined aggregate, VARIADIC ---Testcase 522: -create function least_accum(anyelement, variadic anyarray) -returns anyelement language sql as - 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; ---Testcase 523: -create aggregate least_agg(variadic items anyarray) ( - stype = anyelement, sfunc = least_accum -); --- Disable hash aggregation for plan stability. -set enable_hashagg to false; --- Not pushed down due to user defined aggregate ---Testcase 524: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 group by c2 order by c2; - QUERY PLAN ---------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, least_agg(VARIADIC ARRAY[c1]) - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(6 rows) - --- Add function and aggregate into extension ---alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray); ---alter extension postgres_fdw add aggregate least_agg(variadic items anyarray); ---alter server loopback options (set extensions 'postgres_fdw'); --- Now aggregate will be pushed. Aggregate will display VARIADIC argument. ---Testcase 525: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, least_agg(VARIADIC ARRAY[c1]) - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 100)) ORDER BY `c2` ASC NULLS LAST -(6 rows) - ---Testcase 526: -select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; - c2 | least_agg -----+----------- - 0 | 10 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - --- Remove function and aggregate from extension ---alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray); ---alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray); ---alter server loopback options (set extensions 'postgres_fdw'); --- Not pushed down as we have dropped objects from extension. ---Testcase 527: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 group by c2 order by c2; - QUERY PLAN ---------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, least_agg(VARIADIC ARRAY[c1]) - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST -(6 rows) - --- Cleanup -reset enable_hashagg; ---Testcase 528: -drop aggregate least_agg(variadic items anyarray); ---Testcase 529: -drop function least_accum(anyelement, variadic anyarray); --- Testing USING OPERATOR() in ORDER BY within aggregate. --- For this, we need user defined operators along with operator family and --- operator class. Create those and then add them in extension. Note that --- user defined objects are considered unshippable unless they are part of --- the extension. ---Testcase 530: -create operator public.<^ ( - leftarg = int4, - rightarg = int4, - procedure = int4eq -); ---Testcase 531: -create operator public.=^ ( - leftarg = int4, - rightarg = int4, - procedure = int4lt -); ---Testcase 532: -create operator public.>^ ( - leftarg = int4, - rightarg = int4, - procedure = int4gt -); ---Testcase 533: -create operator family my_op_family using btree; ---Testcase 534: -create function my_op_cmp(a int, b int) returns int as - $$begin return btint4cmp(a, b); end $$ language plpgsql; ---Testcase 535: -create operator class my_op_class for type int using btree family my_op_family as - operator 1 public.<^, - operator 3 public.=^, - operator 5 public.>^, - function 1 my_op_cmp(int, int); --- This will not be pushed as user defined sort operator is not part of the --- extension yet. ---Testcase 536: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 - Group Key: ft2.c2 - -> Foreign Scan on public.ft2 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) -(6 rows) - --- Update local stats on ft2 ---ANALYZE ft2; --- Add into extension -alter extension sqlite_fdw add operator class my_op_class using btree; -alter extension sqlite_fdw add function my_op_cmp(a int, b int); -alter extension sqlite_fdw add operator family my_op_family using btree; -alter extension sqlite_fdw add operator public.<^(int, int); -alter extension sqlite_fdw add operator public.=^(int, int); -alter extension sqlite_fdw add operator public.>^(int, int); ---alter server loopback options (set extensions 'postgres_fdw'); --- Now this will be pushed as sort operator is part of the extension. ---Testcase 537: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 - Group Key: ft2.c2 - -> Foreign Scan on public.ft2 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) -(6 rows) - ---Testcase 538: -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - array_agg --------------------------------- - {6,16,26,36,46,56,66,76,86,96} -(1 row) - --- Remove from extension -alter extension sqlite_fdw drop operator class my_op_class using btree; -alter extension sqlite_fdw drop function my_op_cmp(a int, b int); -alter extension sqlite_fdw drop operator family my_op_family using btree; -alter extension sqlite_fdw drop operator public.<^(int, int); -alter extension sqlite_fdw drop operator public.=^(int, int); -alter extension sqlite_fdw drop operator public.>^(int, int); ---alter server loopback options (set extensions 'postgres_fdw'); --- This will not be pushed as sort operator is now removed from the extension. ---Testcase 539: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 - Group Key: ft2.c2 - -> Foreign Scan on public.ft2 - Output: c1, c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) -(6 rows) - --- Cleanup ---Testcase 540: -drop operator class my_op_class using btree; ---Testcase 541: -drop function my_op_cmp(a int, b int); ---Testcase 542: -drop operator family my_op_family using btree; ---Testcase 543: -drop operator public.>^(int, int); ---Testcase 544: -drop operator public.=^(int, int); ---Testcase 545: -drop operator public.<^(int, int); --- Input relation to aggregate push down hook is not safe to pushdown and thus --- the aggregate cannot be pushed down to foreign server. ---Testcase 201: -explain (verbose, costs off) -select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2); - QUERY PLAN -------------------------------------------------------------------------------------------- - Aggregate - Output: count(t1.c3) - -> Nested Loop Left Join - Output: t1.c3 - Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision)) - -> Foreign Scan on public.ft2 t1 - Output: t1.c3, t1.c1 - SQLite query: SELECT `C 1`, `c3` FROM main."T 1" - -> Materialize - Output: t2.c2 - -> Foreign Scan on public.ft2 t2 - Output: t2.c2 - SQLite query: SELECT `c2` FROM main."T 1" -(13 rows) - --- Subquery in FROM clause having aggregate ---Testcase 202: -explain (verbose, costs off) -select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; - QUERY PLAN --------------------------------------------------------------------------------------------------------- - Sort - Output: (count(*)), x.b - Sort Key: (count(*)), x.b - -> GroupAggregate - Output: count(*), x.b - Group Key: x.b - -> Sort - Output: x.b - Sort Key: x.b - -> Hash Join - Output: x.b - Inner Unique: true - Hash Cond: (ft1.c2 = x.a) - -> Foreign Scan on public.ft1 - Output: ft1.c2 - SQLite query: SELECT `c2` FROM main."T 1" - -> Hash - Output: x.b, x.a - -> Subquery Scan on x - Output: x.b, x.a - -> Foreign Scan - Output: ft1_1.c2, (sum(ft1_1.c1)) - SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 -(23 rows) - ---Testcase 203: -select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; - count | b --------+------- - 100 | 49600 - 100 | 49700 - 100 | 49800 - 100 | 49900 - 100 | 50000 - 100 | 50100 - 100 | 50200 - 100 | 50300 - 100 | 50400 - 100 | 50500 -(10 rows) - --- FULL join with IS NULL check in HAVING ---Testcase 204: -explain (verbose, costs off) -select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; - QUERY PLAN --------------------------------------------------------------------------------------------------- - Sort - Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1 - Sort Key: (avg(t1.c1)), (sum(t2.c1)) - -> HashAggregate - Output: avg(t1.c1), sum(t2.c1), t2.c1 - Group Key: t2.c1 - Filter: (((avg(t1.c1) IS NULL) AND (sum(t2.c1) < 10)) OR (sum(t2.c1) IS NULL)) - -> Hash Full Join - Output: t2.c1, t1.c1 - Hash Cond: (t1.c1 = t2.c1) - -> Foreign Scan on public.ft4 t1 - Output: t1.c1, t1.c2, t1.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Hash - Output: t2.c1 - -> Foreign Scan on public.ft5 t2 - Output: t2.c1 - SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST -(18 rows) - ---Testcase 205: -select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; - avg | sum ----------------------+----- - 51.0000000000000000 | - | 3 - | 9 -(3 rows) - --- Aggregate over FULL join needing to deparse the joining relations as --- subqueries. ---Testcase 206: -explain (verbose, costs off) -select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); - QUERY PLAN -------------------------------------------------------------------------------------------------------- - Aggregate - Output: count(*), sum(ft4.c1), avg(ft5.c1) - -> Hash Full Join - Output: ft4.c1, ft5.c1 - Hash Cond: (ft4.c1 = ft5.c1) - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.c2, ft4.c3 - SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) - -> Hash - Output: ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.c1 - SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -(13 rows) - ---Testcase 207: -select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); - count | sum | avg --------+-----+--------------------- - 8 | 330 | 55.5000000000000000 -(1 row) - --- ORDER BY expression is part of the target list but not pushed down to --- foreign server. ---Testcase 208: -explain (verbose, costs off) -select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; - QUERY PLAN --------------------------------------------------------------------------------- - Sort - Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer)) - Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer)) - -> Foreign Scan - Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer) - SQLite query: SELECT sum(`c2`) FROM main."T 1" -(6 rows) - ---Testcase 209: -select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; - sum ------- - 4500 -(1 row) - --- LATERAL join, with parameterization -set enable_hashagg to false; ---Testcase 210: -explain (verbose, costs off) -select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: t1.c2, qry.sum - -> Foreign Scan on "S 1"."T 1" t1 - Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) AND ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST - -> Subquery Scan on qry - Output: qry.sum, t2.c1 - Filter: (((t1.c2 * 2))::numeric = qry.sum) - -> Foreign Scan - Output: (sum((t2.c1 + t1."C 1"))), t2.c1 - SQLite query: SELECT sum((`C 1` + ?)), `C 1` FROM main."T 1" GROUP BY 2 -(11 rows) - ---Testcase 211: -select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; - c2 | sum -----+----- - 1 | 2 - 2 | 4 -(2 rows) - -reset enable_hashagg; --- bug #15613: bad plan for foreign table scan with lateral reference ---Testcase 546: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ref_0.c2, subq_1.* -FROM - "S 1"."T 1" AS ref_0, - LATERAL ( - SELECT ref_0."C 1" c1, subq_0.* - FROM (SELECT ref_0.c2, ref_1.c3 - FROM ft1 AS ref_1) AS subq_0 - RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) - ) AS subq_1 -WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' -ORDER BY ref_0."C 1"; - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1" - -> Foreign Scan on "S 1"."T 1" ref_0 - Output: ref_0."C 1", ref_0.c2, ref_0.c3, ref_0.c4, ref_0.c5, ref_0.c6, ref_0.c7, ref_0.c8 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 10)) ORDER BY `C 1` ASC NULLS LAST - -> Nested Loop - Output: ref_1.c3, (ref_0.c2) - -> Foreign Scan on public.ft2 ref_3 - Output: ref_3.c3 - SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) - -> Materialize - Output: ref_1.c3, (ref_0.c2) - -> Foreign Scan on public.ft1 ref_1 - Output: ref_1.c3, ref_0.c2 - SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) -(15 rows) - ---Testcase 547: -SELECT ref_0.c2, subq_1.* -FROM - "S 1"."T 1" AS ref_0, - LATERAL ( - SELECT ref_0."C 1" c1, subq_0.* - FROM (SELECT ref_0.c2, ref_1.c3 - FROM ft1 AS ref_1) AS subq_0 - RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) - ) AS subq_1 -WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' -ORDER BY ref_0."C 1"; - c2 | c1 | c2 | c3 -----+----+----+------- - 1 | 1 | 1 | 00001 - 2 | 2 | 2 | 00001 - 3 | 3 | 3 | 00001 - 4 | 4 | 4 | 00001 - 5 | 5 | 5 | 00001 - 6 | 6 | 6 | 00001 - 7 | 7 | 7 | 00001 - 8 | 8 | 8 | 00001 - 9 | 9 | 9 | 00001 -(9 rows) - --- Check with placeHolderVars ---Testcase 212: -explain (verbose, costs off) -select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: sum(q.a), count(q.b) - -> Nested Loop Left Join - Output: q.a, q.b - Inner Unique: true - Join Filter: ((ft4.c1)::numeric <= q.b) - -> Foreign Scan on public.ft4 - Output: ft4.c1, ft4.c2, ft4.c3 - SQLite query: SELECT `c1` FROM main."T 3" - -> Materialize - Output: q.a, q.b - -> Subquery Scan on q - Output: q.a, q.b - -> Foreign Scan - Output: 13, (avg(ft1.c1)), NULL::bigint - SQLite query: SELECT 13, avg(r1.`C 1`), NULL FROM (main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) -(16 rows) - ---Testcase 213: -select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); - sum | count ------+------- - 650 | 50 -(1 row) - --- Not supported cases --- Grouping sets ---Testcase 214: -explain (verbose, costs off) -select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, sum(c1) - Group Key: ft1.c2 - Group Key: () - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST -(7 rows) - ---Testcase 215: -select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; - c2 | sum -----+-------- - 0 | 50500 - 1 | 49600 - 2 | 49700 - | 149800 -(4 rows) - ---Testcase 216: -explain (verbose, costs off) -select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, sum(c1) - Group Key: ft1.c2 - Group Key: () - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST -(7 rows) - ---Testcase 217: -select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; - c2 | sum -----+-------- - 0 | 50500 - 1 | 49600 - 2 | 49700 - | 149800 -(4 rows) - ---Testcase 218: -explain (verbose, costs off) -select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Sort - Output: c2, c6, (sum(c1)) - Sort Key: ft1.c2, ft1.c6 - -> MixedAggregate - Output: c2, c6, sum(c1) - Hash Key: ft1.c6 - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c2, c6, c1 - SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST -(10 rows) - ---Testcase 219: -select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; - c2 | c6 | sum -----+----+------- - 0 | | 50500 - 1 | | 49600 - 2 | | 49700 - | 0 | 50500 - | 1 | 49600 - | 2 | 49700 -(6 rows) - ---Testcase 220: -explain (verbose, costs off) -select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: c2, sum(c1), GROUPING(c2) - Group Key: ft1.c2 - -> Foreign Scan on public.ft1 - Output: c2, c1 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST -(6 rows) - ---Testcase 221: -select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; - c2 | sum | grouping -----+-------+---------- - 0 | 50500 | 0 - 1 | 49600 | 0 - 2 | 49700 | 0 -(3 rows) - --- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed ---Testcase 222: -explain (verbose, costs off) -select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Unique - Output: ((sum(c1) / 1000)), c2 - -> Sort - Output: ((sum(c1) / 1000)), c2 - Sort Key: ((sum(ft2.c1) / 1000)) - -> Foreign Scan - Output: ((sum(c1) / 1000)), c2 - SQLite query: SELECT (sum(`C 1`) / 1000), `c2` FROM main."T 1" WHERE ((`c2` < 6)) GROUP BY 2 -(8 rows) - ---Testcase 223: -select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; - s ----- - 49 - 50 -(2 rows) - --- WindowAgg ---Testcase 224: -explain (verbose, costs off) -select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- - Sort - Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2)) - Sort Key: ft2.c2 - -> WindowAgg - Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2)) - -> Sort - Output: c2, ((c2 % 2)), (sum(c2)) - Sort Key: ((ft2.c2 % 2)) - -> Foreign Scan - Output: c2, ((c2 % 2)), (sum(c2)) - SQLite query: SELECT `c2`, (`c2` % 2), sum(`c2`) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 -(11 rows) - ---Testcase 225: -select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; - c2 | sum | count -----+-----+------- - 0 | 0 | 5 - 1 | 100 | 5 - 2 | 200 | 5 - 3 | 300 | 5 - 4 | 400 | 5 - 5 | 500 | 5 - 6 | 600 | 5 - 7 | 700 | 5 - 8 | 800 | 5 - 9 | 900 | 5 -(10 rows) - ---Testcase 226: -explain (verbose, costs off) -select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - Sort - Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) - Sort Key: ft1.c2 - -> WindowAgg - Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) - -> Sort - Output: c2, ((c2 % 2)) - Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC - -> Foreign Scan - Output: c2, ((c2 % 2)) - SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 -(11 rows) - ---Testcase 227: -select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; - c2 | array_agg -----+------------- - 0 | {8,6,4,2,0} - 1 | {9,7,5,3,1} - 2 | {8,6,4,2} - 3 | {9,7,5,3} - 4 | {8,6,4} - 5 | {9,7,5} - 6 | {8,6} - 7 | {9,7} - 8 | {8} - 9 | {9} -(10 rows) - ---Testcase 228: -explain (verbose, costs off) -select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; - QUERY PLAN ----------------------------------------------------------------------------------------------------------- - Sort - Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) - Sort Key: ft1.c2 - -> WindowAgg - Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) - -> Sort - Output: c2, ((c2 % 2)) - Sort Key: ((ft1.c2 % 2)), ft1.c2 - -> Foreign Scan - Output: c2, ((c2 % 2)) - SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 -(11 rows) - ---Testcase 229: -select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; - c2 | array_agg -----+------------- - 0 | {0,2,4,6,8} - 1 | {1,3,5,7,9} - 2 | {2,4,6,8} - 3 | {3,5,7,9} - 4 | {4,6,8} - 5 | {5,7,9} - 6 | {6,8} - 7 | {7,9} - 8 | {8} - 9 | {9} -(10 rows) - --- =================================================================== --- parameterized queries --- =================================================================== --- simple join ---Testcase 230: -PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2; ---Testcase 231: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2); - QUERY PLAN ------------------------------------------------------------------------------ - Nested Loop - Output: t1.c3, t2.c3 - -> Foreign Scan on public.ft1 t1 - Output: t1.c3 - SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 1)) - -> Materialize - Output: t2.c3 - -> Foreign Scan on public.ft2 t2 - Output: t2.c3 - SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 2)) -(10 rows) - ---Testcase 232: -EXECUTE st1(1, 1); - c3 | c3 --------+------- - 00001 | 00001 -(1 row) - ---Testcase 233: -EXECUTE st1(101, 101); - c3 | c3 --------+------- - 00101 | 00101 -(1 row) - --- subquery using stable function (can't be sent to remote) ---Testcase 234: -PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1; ---Testcase 235: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - Sort Key: t1.c1 - -> Hash Semi Join - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - Hash Cond: (t1.c3 = t2.c3) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST - -> Hash - Output: t2.c3 - -> Foreign Scan on public.ft2 t2 - Output: t2.c3 - Filter: (date(t2.c4) = '01-17-1970'::date) - SQLite query: SELECT `c3`, `c4` FROM main."T 1" WHERE ((`C 1` > 10)) -(15 rows) - ---Testcase 236: -EXECUTE st2(10, 20); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo -(1 row) - ---Testcase 237: -EXECUTE st2(101, 121); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- - 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo -(1 row) - --- subquery using immutable function (can be sent to remote) ---Testcase 238: -PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1; ---Testcase 239: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - Sort Key: t1.c1 - -> Hash Semi Join - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - Hash Cond: (t1.c3 = t2.c3) - -> Foreign Scan on public.ft1 t1 - Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST - -> Hash - Output: t2.c3 - -> Foreign Scan on public.ft2 t2 - Output: t2.c3 - Filter: (date(t2.c5) = '01-17-1970'::date) - SQLite query: SELECT `c3`, `c5` FROM main."T 1" WHERE ((`C 1` > 10)) -(15 rows) - ---Testcase 240: -EXECUTE st3(10, 20); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo -(1 row) - ---Testcase 241: -EXECUTE st3(20, 30); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+----+----+----+----+----+---- -(0 rows) - --- custom plan should be chosen initially ---Testcase 242: -PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1; ---Testcase 243: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - ---Testcase 244: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - ---Testcase 245: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - ---Testcase 246: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - ---Testcase 247: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) -(3 rows) - --- once we try it enough times, should switch to generic plan ---Testcase 248: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = ?)) -(3 rows) - --- value of $1 should not be sent to remote ---Testcase 249: -PREPARE st5(text,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2; ---Testcase 250: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) -(3 rows) - ---Testcase 251: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) -(3 rows) - ---Testcase 252: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) -(3 rows) - ---Testcase 253: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) -(3 rows) - ---Testcase 254: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) -(3 rows) - ---Testcase 255: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = ?)) AND ((`C 1` = ?)) -(3 rows) - ---Testcase 256: -EXECUTE st5('foo', 1); - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - --- altering FDW options requires replanning ---Testcase 257: -PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2; ---Testcase 258: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = `c2`)) -(3 rows) - ---Testcase 259: -PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); ---Testcase 260: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Insert on public.ft1 - -> Result - Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text -(3 rows) - ---Testcase 548: -INSERT INTO "S 1"."T 0" SELECT * FROM "S 1"."T 1"; -ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 0'); ---Testcase 261: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 0" WHERE ((`C 1` = `c2`)) -(3 rows) - ---Testcase 262: -EXECUTE st6; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo - 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo - 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo -(9 rows) - ---Testcase 263: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Insert on public.ft1 - -> Result - Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text -(3 rows) - -ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 1'); ---Testcase 549: -PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; ---Testcase 550: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---ALTER SERVER loopback OPTIONS (DROP extensions); ---Testcase 551: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; - QUERY PLAN ----------------------------------------------------------------- - Aggregate - Output: count(c3) - -> Foreign Scan on public.ft1 t1 - Output: c3 - Filter: (t1.c1 === t1.c2) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" -(6 rows) - ---Testcase 552: -EXECUTE st8; - count -------- - 9 -(1 row) - ---ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --- cleanup -DEALLOCATE st1; -DEALLOCATE st2; -DEALLOCATE st3; -DEALLOCATE st4; -DEALLOCATE st5; -DEALLOCATE st6; -DEALLOCATE st7; -DEALLOCATE st8; --- System columns, except ctid and oid, should not be sent to remote ---Testcase 264: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Limit - Output: c1, c2, c3, c4, c5, c6, c7, c8 - -> Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: (t1.tableoid = '1259'::oid) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(6 rows) - ---Testcase 265: -SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - ---Testcase 266: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; - QUERY PLAN ------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 -(3 rows) - ---Testcase 267: -SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; - tableoid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----------+----+----+-------+------------------------------+--------------------------+----+------------+----- - ft1 | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - ---Testcase 268: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - Filter: (t1.ctid = '(0,2)'::tid) - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(4 rows) - ---Testcase 553: -SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+----+----+----+----+----+---- -(0 rows) - ---Testcase 554: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ctid, * FROM ft1 t1 LIMIT 1; - QUERY PLAN ------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 t1 - Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 -(3 rows) - ---Testcase 271: -SELECT ctid, * FROM ft1 t1 LIMIT 1; - ctid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----------------+----+----+-------+------------------------------+--------------------------+----+------------+----- - (4294967295,0) | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - --- =================================================================== --- used in PL/pgSQL function --- =================================================================== ---Testcase 555: -CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$ -DECLARE - v_c1 int; -BEGIN ---Testcase 556: - SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1; - PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1; - RETURN v_c1; -END; -$$ LANGUAGE plpgsql; ---Testcase 272: -SELECT f_test(100); - f_test --------- - 100 -(1 row) - ---Testcase 557: -DROP FUNCTION f_test(int); --- =================================================================== --- conversion error --- =================================================================== -ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int; ---Testcase 273: -SELECT * FROM ft1 WHERE c1 = 1; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (3 bytes) : 'foo' -CONTEXT: foreign table "ft1" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column ---Testcase 274: -SELECT ft1.c1, ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (3 bytes) : 'foo' -CONTEXT: foreign table "ft1" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column ---Testcase 275: -SELECT ft1.c1, ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (3 bytes) : 'foo' -CONTEXT: foreign table "ft1" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column ---Testcase 276: -SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (3 bytes) : 'foo' -CONTEXT: foreign table "ft1" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column -ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text; --- =================================================================== --- subtransaction --- + local/remote error doesn't break cursor --- =================================================================== -BEGIN; -DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1; ---Testcase 277: -FETCH c; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - -SAVEPOINT s; -ERROR OUT; -- ERROR -ERROR: syntax error at or near "ERROR" -LINE 1: ERROR OUT; - ^ -ROLLBACK TO s; ---Testcase 278: -FETCH c; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo -(1 row) - -SAVEPOINT s; ---Testcase 279: -SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo -(1 row) - -ROLLBACK TO s; ---Testcase 280: -FETCH c; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo -(1 row) - ---Testcase 281: -SELECT * FROM ft1 ORDER BY c1 LIMIT 1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo -(1 row) - -COMMIT; --- =================================================================== --- test handling of collations --- =================================================================== ---Testcase 558: -create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10)) server sqlite_svr; --- can be sent to remote ---Testcase 559: -explain (verbose, costs off) select * from ft3 where f1 = 'foo'; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) -(3 rows) - ---Testcase 560: -explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo'; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) -(3 rows) - ---Testcase 561: -explain (verbose, costs off) select * from ft3 where f2 = 'foo'; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f2` = 'foo')) -(3 rows) - ---Testcase 562: -explain (verbose, costs off) select * from ft3 where f3 = 'foo'; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f3` = 'foo')) -(3 rows) - ---Testcase 563: -explain (verbose, costs off) select * from ft3 f, loct3 l - where f.f3 = l.f3 and l.f1 = 'foo'; -ERROR: relation "loct3" does not exist -LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l - ^ --- can't be sent to remote ---Testcase 564: -explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo'; - QUERY PLAN ---------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - Filter: ((ft3.f1)::text = 'foo'::text) - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" -(4 rows) - ---Testcase 565: -explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C"; - QUERY PLAN ---------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - Filter: (ft3.f1 = 'foo'::text COLLATE "C") - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" -(4 rows) - ---Testcase 566: -explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo'; - QUERY PLAN ---------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - Filter: ((ft3.f2)::text = 'foo'::text) - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" -(4 rows) - ---Testcase 567: -explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C"; - QUERY PLAN ---------------------------------------------------------- - Foreign Scan on public.ft3 - Output: f1, f2, f3 - Filter: (ft3.f2 = 'foo'::text COLLATE "C") - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" -(4 rows) - ---Testcase 568: -explain (verbose, costs off) select * from ft3 f, loct3 l - where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo'; -ERROR: relation "loct3" does not exist -LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l - ^ --- =================================================================== --- test writable foreign table stuff --- =================================================================== ---Testcase 282: -EXPLAIN (verbose, costs off) -INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Insert on public.ft2 - -> Subquery Scan on "*SELECT*" - Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text - -> Foreign Scan on public.ft2 ft2_1 - Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3) - SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" LIMIT 20 -(6 rows) - ---Testcase 283: -INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; ---Testcase 284: -INSERT INTO ft2 (c1,c2,c3) VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc'); ---Testcase 285: -SELECT * FROM ft2 WHERE c1 >= 1101; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-----+----+----+----+------------+---- - 1101 | 201 | aaa | | | | ft2 | - 1102 | 202 | bbb | | | | ft2 | - 1103 | 203 | ccc | | | | ft2 | -(3 rows) - ---Testcase 286: -INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); ---Testcase 287: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- - Update on public.ft2 - -> Foreign Update on public.ft2 - SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 300), `c3` = (`c3` || '_update3') WHERE (((`C 1` % 10) = 3)) -(3 rows) - ---Testcase 288: -UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; ---Testcase 289: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; -- can be pushed down - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- - Update on public.ft2 - -> Foreign Update on public.ft2 - SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 400), `c3` = (`c3` || '_update7') WHERE (((`C 1` % 10) = 7)) -(3 rows) - ---Testcase 290: -UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; ---Testcase 291: -SELECT * FROM ft2 WHERE c1 % 10 = 7; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+--------------------+------------------------------+--------------------------+----+------------+----- - 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo - 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo - 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo - 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo - 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo - 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo - 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo - 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo - 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo - 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo - 1007 | 507 | 0000700007_update7 | | | | ft2 | - 1017 | 507 | 0001700017_update7 | | | | ft2 | -(102 rows) - ---Testcase 292: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT - FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Update on public.ft2 - -> Foreign Scan - Output: ft2.c1, (ft2.c2 + 500), NULL::integer, (ft2.c3 || '_update9'::text), ft2.c4, ft2.c5, ft2.c6, 'ft2 '::character(10), ft2.c8, ft2.c1, ft1.* - SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c8`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 9)))) - -> Hash Join - Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft1.* - Hash Cond: (ft2.c2 = ft1.c1) - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c8` FROM main."T 1" - -> Hash - Output: ft1.*, ft1.c1 - -> Foreign Scan on public.ft1 - Output: ft1.*, ft1.c1 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 9)) -(15 rows) - ---Testcase 293: -UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT - FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; ---Testcase 294: -EXPLAIN (verbose, costs off) - DELETE FROM ft2 WHERE c1 % 10 = 5; -- can be pushed down - QUERY PLAN -------------------------------------------------------------------------- - Delete on public.ft2 - -> Foreign Delete on public.ft2 - SQLite query: DELETE FROM main."T 1" WHERE (((`C 1` % 10) = 5)) -(3 rows) - ---Testcase 295: -SELECT c1, c4 FROM ft2 WHERE c1 % 10 = 5; - c1 | c4 -------+------------------------------ - 5 | Tue Jan 06 00:00:00 1970 PST - 15 | Fri Jan 16 00:00:00 1970 PST - 25 | Mon Jan 26 00:00:00 1970 PST - 35 | Thu Feb 05 00:00:00 1970 PST - 45 | Sun Feb 15 00:00:00 1970 PST - 55 | Wed Feb 25 00:00:00 1970 PST - 65 | Sat Mar 07 00:00:00 1970 PST - 75 | Tue Mar 17 00:00:00 1970 PST - 85 | Fri Mar 27 00:00:00 1970 PST - 95 | Mon Apr 06 00:00:00 1970 PST - 105 | Tue Jan 06 00:00:00 1970 PST - 115 | Fri Jan 16 00:00:00 1970 PST - 125 | Mon Jan 26 00:00:00 1970 PST - 135 | Thu Feb 05 00:00:00 1970 PST - 145 | Sun Feb 15 00:00:00 1970 PST - 155 | Wed Feb 25 00:00:00 1970 PST - 165 | Sat Mar 07 00:00:00 1970 PST - 175 | Tue Mar 17 00:00:00 1970 PST - 185 | Fri Mar 27 00:00:00 1970 PST - 195 | Mon Apr 06 00:00:00 1970 PST - 205 | Tue Jan 06 00:00:00 1970 PST - 215 | Fri Jan 16 00:00:00 1970 PST - 225 | Mon Jan 26 00:00:00 1970 PST - 235 | Thu Feb 05 00:00:00 1970 PST - 245 | Sun Feb 15 00:00:00 1970 PST - 255 | Wed Feb 25 00:00:00 1970 PST - 265 | Sat Mar 07 00:00:00 1970 PST - 275 | Tue Mar 17 00:00:00 1970 PST - 285 | Fri Mar 27 00:00:00 1970 PST - 295 | Mon Apr 06 00:00:00 1970 PST - 305 | Tue Jan 06 00:00:00 1970 PST - 315 | Fri Jan 16 00:00:00 1970 PST - 325 | Mon Jan 26 00:00:00 1970 PST - 335 | Thu Feb 05 00:00:00 1970 PST - 345 | Sun Feb 15 00:00:00 1970 PST - 355 | Wed Feb 25 00:00:00 1970 PST - 365 | Sat Mar 07 00:00:00 1970 PST - 375 | Tue Mar 17 00:00:00 1970 PST - 385 | Fri Mar 27 00:00:00 1970 PST - 395 | Mon Apr 06 00:00:00 1970 PST - 405 | Tue Jan 06 00:00:00 1970 PST - 415 | Fri Jan 16 00:00:00 1970 PST - 425 | Mon Jan 26 00:00:00 1970 PST - 435 | Thu Feb 05 00:00:00 1970 PST - 445 | Sun Feb 15 00:00:00 1970 PST - 455 | Wed Feb 25 00:00:00 1970 PST - 465 | Sat Mar 07 00:00:00 1970 PST - 475 | Tue Mar 17 00:00:00 1970 PST - 485 | Fri Mar 27 00:00:00 1970 PST - 495 | Mon Apr 06 00:00:00 1970 PST - 505 | Tue Jan 06 00:00:00 1970 PST - 515 | Fri Jan 16 00:00:00 1970 PST - 525 | Mon Jan 26 00:00:00 1970 PST - 535 | Thu Feb 05 00:00:00 1970 PST - 545 | Sun Feb 15 00:00:00 1970 PST - 555 | Wed Feb 25 00:00:00 1970 PST - 565 | Sat Mar 07 00:00:00 1970 PST - 575 | Tue Mar 17 00:00:00 1970 PST - 585 | Fri Mar 27 00:00:00 1970 PST - 595 | Mon Apr 06 00:00:00 1970 PST - 605 | Tue Jan 06 00:00:00 1970 PST - 615 | Fri Jan 16 00:00:00 1970 PST - 625 | Mon Jan 26 00:00:00 1970 PST - 635 | Thu Feb 05 00:00:00 1970 PST - 645 | Sun Feb 15 00:00:00 1970 PST - 655 | Wed Feb 25 00:00:00 1970 PST - 665 | Sat Mar 07 00:00:00 1970 PST - 675 | Tue Mar 17 00:00:00 1970 PST - 685 | Fri Mar 27 00:00:00 1970 PST - 695 | Mon Apr 06 00:00:00 1970 PST - 705 | Tue Jan 06 00:00:00 1970 PST - 715 | Fri Jan 16 00:00:00 1970 PST - 725 | Mon Jan 26 00:00:00 1970 PST - 735 | Thu Feb 05 00:00:00 1970 PST - 745 | Sun Feb 15 00:00:00 1970 PST - 755 | Wed Feb 25 00:00:00 1970 PST - 765 | Sat Mar 07 00:00:00 1970 PST - 775 | Tue Mar 17 00:00:00 1970 PST - 785 | Fri Mar 27 00:00:00 1970 PST - 795 | Mon Apr 06 00:00:00 1970 PST - 805 | Tue Jan 06 00:00:00 1970 PST - 815 | Fri Jan 16 00:00:00 1970 PST - 825 | Mon Jan 26 00:00:00 1970 PST - 835 | Thu Feb 05 00:00:00 1970 PST - 845 | Sun Feb 15 00:00:00 1970 PST - 855 | Wed Feb 25 00:00:00 1970 PST - 865 | Sat Mar 07 00:00:00 1970 PST - 875 | Tue Mar 17 00:00:00 1970 PST - 885 | Fri Mar 27 00:00:00 1970 PST - 895 | Mon Apr 06 00:00:00 1970 PST - 905 | Tue Jan 06 00:00:00 1970 PST - 915 | Fri Jan 16 00:00:00 1970 PST - 925 | Mon Jan 26 00:00:00 1970 PST - 935 | Thu Feb 05 00:00:00 1970 PST - 945 | Sun Feb 15 00:00:00 1970 PST - 955 | Wed Feb 25 00:00:00 1970 PST - 965 | Sat Mar 07 00:00:00 1970 PST - 975 | Tue Mar 17 00:00:00 1970 PST - 985 | Fri Mar 27 00:00:00 1970 PST - 995 | Mon Apr 06 00:00:00 1970 PST - 1005 | - 1015 | - 1105 | -(103 rows) - ---Testcase 569: -DELETE FROM ft2 WHERE c1 % 10 = 5; ---Testcase 297: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Delete on public.ft2 - -> Foreign Scan - Output: ft2.c1, ft1.* - SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 2)))) - -> Hash Join - Output: ft2.c1, ft1.* - Hash Cond: (ft2.c2 = ft1.c1) - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" - -> Hash - Output: ft1.*, ft1.c1 - -> Foreign Scan on public.ft1 - Output: ft1.*, ft1.c1 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 2)) -(15 rows) - ---Testcase 298: -DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; ---Testcase 299: -SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; - c1 | c2 | c3 | c4 -------+-----+--------------------+------------------------------ - 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST - 3 | 303 | 00003_update3 | Sun Jan 04 00:00:00 1970 PST - 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST - 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST - 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST - 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST - 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST - 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST - 11 | 1 | 00011 | Mon Jan 12 00:00:00 1970 PST - 13 | 303 | 00013_update3 | Wed Jan 14 00:00:00 1970 PST - 14 | 4 | 00014 | Thu Jan 15 00:00:00 1970 PST - 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST - 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST - 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST - 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST - 20 | 0 | 00020 | Wed Jan 21 00:00:00 1970 PST - 21 | 1 | 00021 | Thu Jan 22 00:00:00 1970 PST - 23 | 303 | 00023_update3 | Sat Jan 24 00:00:00 1970 PST - 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST - 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST - 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST - 28 | 8 | 00028 | Thu Jan 29 00:00:00 1970 PST - 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST - 30 | 0 | 00030 | Sat Jan 31 00:00:00 1970 PST - 31 | 1 | 00031 | Sun Feb 01 00:00:00 1970 PST - 33 | 303 | 00033_update3 | Tue Feb 03 00:00:00 1970 PST - 34 | 4 | 00034 | Wed Feb 04 00:00:00 1970 PST - 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST - 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST - 38 | 8 | 00038 | Sun Feb 08 00:00:00 1970 PST - 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST - 40 | 0 | 00040 | Tue Feb 10 00:00:00 1970 PST - 41 | 1 | 00041 | Wed Feb 11 00:00:00 1970 PST - 43 | 303 | 00043_update3 | Fri Feb 13 00:00:00 1970 PST - 44 | 4 | 00044 | Sat Feb 14 00:00:00 1970 PST - 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST - 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST - 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST - 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST - 50 | 0 | 00050 | Fri Feb 20 00:00:00 1970 PST - 51 | 1 | 00051 | Sat Feb 21 00:00:00 1970 PST - 53 | 303 | 00053_update3 | Mon Feb 23 00:00:00 1970 PST - 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST - 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST - 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST - 58 | 8 | 00058 | Sat Feb 28 00:00:00 1970 PST - 59 | 509 | 00059_update9 | Sun Mar 01 00:00:00 1970 PST - 60 | 0 | 00060 | Mon Mar 02 00:00:00 1970 PST - 61 | 1 | 00061 | Tue Mar 03 00:00:00 1970 PST - 63 | 303 | 00063_update3 | Thu Mar 05 00:00:00 1970 PST - 64 | 4 | 00064 | Fri Mar 06 00:00:00 1970 PST - 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST - 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST - 68 | 8 | 00068 | Tue Mar 10 00:00:00 1970 PST - 69 | 509 | 00069_update9 | Wed Mar 11 00:00:00 1970 PST - 70 | 0 | 00070 | Thu Mar 12 00:00:00 1970 PST - 71 | 1 | 00071 | Fri Mar 13 00:00:00 1970 PST - 73 | 303 | 00073_update3 | Sun Mar 15 00:00:00 1970 PST - 74 | 4 | 00074 | Mon Mar 16 00:00:00 1970 PST - 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST - 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST - 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST - 79 | 509 | 00079_update9 | Sat Mar 21 00:00:00 1970 PST - 80 | 0 | 00080 | Sun Mar 22 00:00:00 1970 PST - 81 | 1 | 00081 | Mon Mar 23 00:00:00 1970 PST - 83 | 303 | 00083_update3 | Wed Mar 25 00:00:00 1970 PST - 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST - 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST - 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST - 88 | 8 | 00088 | Mon Mar 30 00:00:00 1970 PST - 89 | 509 | 00089_update9 | Tue Mar 31 00:00:00 1970 PST - 90 | 0 | 00090 | Wed Apr 01 00:00:00 1970 PST - 91 | 1 | 00091 | Thu Apr 02 00:00:00 1970 PST - 93 | 303 | 00093_update3 | Sat Apr 04 00:00:00 1970 PST - 94 | 4 | 00094 | Sun Apr 05 00:00:00 1970 PST - 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST - 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST - 98 | 8 | 00098 | Thu Apr 09 00:00:00 1970 PST - 99 | 509 | 00099_update9 | Fri Apr 10 00:00:00 1970 PST - 100 | 0 | 00100 | Thu Jan 01 00:00:00 1970 PST - 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST - 103 | 303 | 00103_update3 | Sun Jan 04 00:00:00 1970 PST - 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST - 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST - 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST - 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST - 109 | 509 | 00109_update9 | Sat Jan 10 00:00:00 1970 PST - 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST - 111 | 1 | 00111 | Mon Jan 12 00:00:00 1970 PST - 113 | 303 | 00113_update3 | Wed Jan 14 00:00:00 1970 PST - 114 | 4 | 00114 | Thu Jan 15 00:00:00 1970 PST - 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST - 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST - 118 | 8 | 00118 | Mon Jan 19 00:00:00 1970 PST - 119 | 509 | 00119_update9 | Tue Jan 20 00:00:00 1970 PST - 120 | 0 | 00120 | Wed Jan 21 00:00:00 1970 PST - 121 | 1 | 00121 | Thu Jan 22 00:00:00 1970 PST - 123 | 303 | 00123_update3 | Sat Jan 24 00:00:00 1970 PST - 124 | 4 | 00124 | Sun Jan 25 00:00:00 1970 PST - 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST - 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST - 128 | 8 | 00128 | Thu Jan 29 00:00:00 1970 PST - 129 | 509 | 00129_update9 | Fri Jan 30 00:00:00 1970 PST - 130 | 0 | 00130 | Sat Jan 31 00:00:00 1970 PST - 131 | 1 | 00131 | Sun Feb 01 00:00:00 1970 PST - 133 | 303 | 00133_update3 | Tue Feb 03 00:00:00 1970 PST - 134 | 4 | 00134 | Wed Feb 04 00:00:00 1970 PST - 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST - 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST - 138 | 8 | 00138 | Sun Feb 08 00:00:00 1970 PST - 139 | 509 | 00139_update9 | Mon Feb 09 00:00:00 1970 PST - 140 | 0 | 00140 | Tue Feb 10 00:00:00 1970 PST - 141 | 1 | 00141 | Wed Feb 11 00:00:00 1970 PST - 143 | 303 | 00143_update3 | Fri Feb 13 00:00:00 1970 PST - 144 | 4 | 00144 | Sat Feb 14 00:00:00 1970 PST - 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST - 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST - 148 | 8 | 00148 | Wed Feb 18 00:00:00 1970 PST - 149 | 509 | 00149_update9 | Thu Feb 19 00:00:00 1970 PST - 150 | 0 | 00150 | Fri Feb 20 00:00:00 1970 PST - 151 | 1 | 00151 | Sat Feb 21 00:00:00 1970 PST - 153 | 303 | 00153_update3 | Mon Feb 23 00:00:00 1970 PST - 154 | 4 | 00154 | Tue Feb 24 00:00:00 1970 PST - 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST - 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST - 158 | 8 | 00158 | Sat Feb 28 00:00:00 1970 PST - 159 | 509 | 00159_update9 | Sun Mar 01 00:00:00 1970 PST - 160 | 0 | 00160 | Mon Mar 02 00:00:00 1970 PST - 161 | 1 | 00161 | Tue Mar 03 00:00:00 1970 PST - 163 | 303 | 00163_update3 | Thu Mar 05 00:00:00 1970 PST - 164 | 4 | 00164 | Fri Mar 06 00:00:00 1970 PST - 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST - 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST - 168 | 8 | 00168 | Tue Mar 10 00:00:00 1970 PST - 169 | 509 | 00169_update9 | Wed Mar 11 00:00:00 1970 PST - 170 | 0 | 00170 | Thu Mar 12 00:00:00 1970 PST - 171 | 1 | 00171 | Fri Mar 13 00:00:00 1970 PST - 173 | 303 | 00173_update3 | Sun Mar 15 00:00:00 1970 PST - 174 | 4 | 00174 | Mon Mar 16 00:00:00 1970 PST - 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST - 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST - 178 | 8 | 00178 | Fri Mar 20 00:00:00 1970 PST - 179 | 509 | 00179_update9 | Sat Mar 21 00:00:00 1970 PST - 180 | 0 | 00180 | Sun Mar 22 00:00:00 1970 PST - 181 | 1 | 00181 | Mon Mar 23 00:00:00 1970 PST - 183 | 303 | 00183_update3 | Wed Mar 25 00:00:00 1970 PST - 184 | 4 | 00184 | Thu Mar 26 00:00:00 1970 PST - 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST - 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST - 188 | 8 | 00188 | Mon Mar 30 00:00:00 1970 PST - 189 | 509 | 00189_update9 | Tue Mar 31 00:00:00 1970 PST - 190 | 0 | 00190 | Wed Apr 01 00:00:00 1970 PST - 191 | 1 | 00191 | Thu Apr 02 00:00:00 1970 PST - 193 | 303 | 00193_update3 | Sat Apr 04 00:00:00 1970 PST - 194 | 4 | 00194 | Sun Apr 05 00:00:00 1970 PST - 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST - 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST - 198 | 8 | 00198 | Thu Apr 09 00:00:00 1970 PST - 199 | 509 | 00199_update9 | Fri Apr 10 00:00:00 1970 PST - 200 | 0 | 00200 | Thu Jan 01 00:00:00 1970 PST - 201 | 1 | 00201 | Fri Jan 02 00:00:00 1970 PST - 203 | 303 | 00203_update3 | Sun Jan 04 00:00:00 1970 PST - 204 | 4 | 00204 | Mon Jan 05 00:00:00 1970 PST - 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST - 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST - 208 | 8 | 00208 | Fri Jan 09 00:00:00 1970 PST - 209 | 509 | 00209_update9 | Sat Jan 10 00:00:00 1970 PST - 210 | 0 | 00210 | Sun Jan 11 00:00:00 1970 PST - 211 | 1 | 00211 | Mon Jan 12 00:00:00 1970 PST - 213 | 303 | 00213_update3 | Wed Jan 14 00:00:00 1970 PST - 214 | 4 | 00214 | Thu Jan 15 00:00:00 1970 PST - 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST - 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST - 218 | 8 | 00218 | Mon Jan 19 00:00:00 1970 PST - 219 | 509 | 00219_update9 | Tue Jan 20 00:00:00 1970 PST - 220 | 0 | 00220 | Wed Jan 21 00:00:00 1970 PST - 221 | 1 | 00221 | Thu Jan 22 00:00:00 1970 PST - 223 | 303 | 00223_update3 | Sat Jan 24 00:00:00 1970 PST - 224 | 4 | 00224 | Sun Jan 25 00:00:00 1970 PST - 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST - 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST - 228 | 8 | 00228 | Thu Jan 29 00:00:00 1970 PST - 229 | 509 | 00229_update9 | Fri Jan 30 00:00:00 1970 PST - 230 | 0 | 00230 | Sat Jan 31 00:00:00 1970 PST - 231 | 1 | 00231 | Sun Feb 01 00:00:00 1970 PST - 233 | 303 | 00233_update3 | Tue Feb 03 00:00:00 1970 PST - 234 | 4 | 00234 | Wed Feb 04 00:00:00 1970 PST - 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST - 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST - 238 | 8 | 00238 | Sun Feb 08 00:00:00 1970 PST - 239 | 509 | 00239_update9 | Mon Feb 09 00:00:00 1970 PST - 240 | 0 | 00240 | Tue Feb 10 00:00:00 1970 PST - 241 | 1 | 00241 | Wed Feb 11 00:00:00 1970 PST - 243 | 303 | 00243_update3 | Fri Feb 13 00:00:00 1970 PST - 244 | 4 | 00244 | Sat Feb 14 00:00:00 1970 PST - 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST - 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST - 248 | 8 | 00248 | Wed Feb 18 00:00:00 1970 PST - 249 | 509 | 00249_update9 | Thu Feb 19 00:00:00 1970 PST - 250 | 0 | 00250 | Fri Feb 20 00:00:00 1970 PST - 251 | 1 | 00251 | Sat Feb 21 00:00:00 1970 PST - 253 | 303 | 00253_update3 | Mon Feb 23 00:00:00 1970 PST - 254 | 4 | 00254 | Tue Feb 24 00:00:00 1970 PST - 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST - 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST - 258 | 8 | 00258 | Sat Feb 28 00:00:00 1970 PST - 259 | 509 | 00259_update9 | Sun Mar 01 00:00:00 1970 PST - 260 | 0 | 00260 | Mon Mar 02 00:00:00 1970 PST - 261 | 1 | 00261 | Tue Mar 03 00:00:00 1970 PST - 263 | 303 | 00263_update3 | Thu Mar 05 00:00:00 1970 PST - 264 | 4 | 00264 | Fri Mar 06 00:00:00 1970 PST - 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST - 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST - 268 | 8 | 00268 | Tue Mar 10 00:00:00 1970 PST - 269 | 509 | 00269_update9 | Wed Mar 11 00:00:00 1970 PST - 270 | 0 | 00270 | Thu Mar 12 00:00:00 1970 PST - 271 | 1 | 00271 | Fri Mar 13 00:00:00 1970 PST - 273 | 303 | 00273_update3 | Sun Mar 15 00:00:00 1970 PST - 274 | 4 | 00274 | Mon Mar 16 00:00:00 1970 PST - 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST - 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST - 278 | 8 | 00278 | Fri Mar 20 00:00:00 1970 PST - 279 | 509 | 00279_update9 | Sat Mar 21 00:00:00 1970 PST - 280 | 0 | 00280 | Sun Mar 22 00:00:00 1970 PST - 281 | 1 | 00281 | Mon Mar 23 00:00:00 1970 PST - 283 | 303 | 00283_update3 | Wed Mar 25 00:00:00 1970 PST - 284 | 4 | 00284 | Thu Mar 26 00:00:00 1970 PST - 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST - 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST - 288 | 8 | 00288 | Mon Mar 30 00:00:00 1970 PST - 289 | 509 | 00289_update9 | Tue Mar 31 00:00:00 1970 PST - 290 | 0 | 00290 | Wed Apr 01 00:00:00 1970 PST - 291 | 1 | 00291 | Thu Apr 02 00:00:00 1970 PST - 293 | 303 | 00293_update3 | Sat Apr 04 00:00:00 1970 PST - 294 | 4 | 00294 | Sun Apr 05 00:00:00 1970 PST - 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST - 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST - 298 | 8 | 00298 | Thu Apr 09 00:00:00 1970 PST - 299 | 509 | 00299_update9 | Fri Apr 10 00:00:00 1970 PST - 300 | 0 | 00300 | Thu Jan 01 00:00:00 1970 PST - 301 | 1 | 00301 | Fri Jan 02 00:00:00 1970 PST - 303 | 303 | 00303_update3 | Sun Jan 04 00:00:00 1970 PST - 304 | 4 | 00304 | Mon Jan 05 00:00:00 1970 PST - 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST - 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST - 308 | 8 | 00308 | Fri Jan 09 00:00:00 1970 PST - 309 | 509 | 00309_update9 | Sat Jan 10 00:00:00 1970 PST - 310 | 0 | 00310 | Sun Jan 11 00:00:00 1970 PST - 311 | 1 | 00311 | Mon Jan 12 00:00:00 1970 PST - 313 | 303 | 00313_update3 | Wed Jan 14 00:00:00 1970 PST - 314 | 4 | 00314 | Thu Jan 15 00:00:00 1970 PST - 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST - 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST - 318 | 8 | 00318 | Mon Jan 19 00:00:00 1970 PST - 319 | 509 | 00319_update9 | Tue Jan 20 00:00:00 1970 PST - 320 | 0 | 00320 | Wed Jan 21 00:00:00 1970 PST - 321 | 1 | 00321 | Thu Jan 22 00:00:00 1970 PST - 323 | 303 | 00323_update3 | Sat Jan 24 00:00:00 1970 PST - 324 | 4 | 00324 | Sun Jan 25 00:00:00 1970 PST - 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST - 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST - 328 | 8 | 00328 | Thu Jan 29 00:00:00 1970 PST - 329 | 509 | 00329_update9 | Fri Jan 30 00:00:00 1970 PST - 330 | 0 | 00330 | Sat Jan 31 00:00:00 1970 PST - 331 | 1 | 00331 | Sun Feb 01 00:00:00 1970 PST - 333 | 303 | 00333_update3 | Tue Feb 03 00:00:00 1970 PST - 334 | 4 | 00334 | Wed Feb 04 00:00:00 1970 PST - 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST - 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST - 338 | 8 | 00338 | Sun Feb 08 00:00:00 1970 PST - 339 | 509 | 00339_update9 | Mon Feb 09 00:00:00 1970 PST - 340 | 0 | 00340 | Tue Feb 10 00:00:00 1970 PST - 341 | 1 | 00341 | Wed Feb 11 00:00:00 1970 PST - 343 | 303 | 00343_update3 | Fri Feb 13 00:00:00 1970 PST - 344 | 4 | 00344 | Sat Feb 14 00:00:00 1970 PST - 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST - 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST - 348 | 8 | 00348 | Wed Feb 18 00:00:00 1970 PST - 349 | 509 | 00349_update9 | Thu Feb 19 00:00:00 1970 PST - 350 | 0 | 00350 | Fri Feb 20 00:00:00 1970 PST - 351 | 1 | 00351 | Sat Feb 21 00:00:00 1970 PST - 353 | 303 | 00353_update3 | Mon Feb 23 00:00:00 1970 PST - 354 | 4 | 00354 | Tue Feb 24 00:00:00 1970 PST - 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST - 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST - 358 | 8 | 00358 | Sat Feb 28 00:00:00 1970 PST - 359 | 509 | 00359_update9 | Sun Mar 01 00:00:00 1970 PST - 360 | 0 | 00360 | Mon Mar 02 00:00:00 1970 PST - 361 | 1 | 00361 | Tue Mar 03 00:00:00 1970 PST - 363 | 303 | 00363_update3 | Thu Mar 05 00:00:00 1970 PST - 364 | 4 | 00364 | Fri Mar 06 00:00:00 1970 PST - 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST - 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST - 368 | 8 | 00368 | Tue Mar 10 00:00:00 1970 PST - 369 | 509 | 00369_update9 | Wed Mar 11 00:00:00 1970 PST - 370 | 0 | 00370 | Thu Mar 12 00:00:00 1970 PST - 371 | 1 | 00371 | Fri Mar 13 00:00:00 1970 PST - 373 | 303 | 00373_update3 | Sun Mar 15 00:00:00 1970 PST - 374 | 4 | 00374 | Mon Mar 16 00:00:00 1970 PST - 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST - 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST - 378 | 8 | 00378 | Fri Mar 20 00:00:00 1970 PST - 379 | 509 | 00379_update9 | Sat Mar 21 00:00:00 1970 PST - 380 | 0 | 00380 | Sun Mar 22 00:00:00 1970 PST - 381 | 1 | 00381 | Mon Mar 23 00:00:00 1970 PST - 383 | 303 | 00383_update3 | Wed Mar 25 00:00:00 1970 PST - 384 | 4 | 00384 | Thu Mar 26 00:00:00 1970 PST - 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST - 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST - 388 | 8 | 00388 | Mon Mar 30 00:00:00 1970 PST - 389 | 509 | 00389_update9 | Tue Mar 31 00:00:00 1970 PST - 390 | 0 | 00390 | Wed Apr 01 00:00:00 1970 PST - 391 | 1 | 00391 | Thu Apr 02 00:00:00 1970 PST - 393 | 303 | 00393_update3 | Sat Apr 04 00:00:00 1970 PST - 394 | 4 | 00394 | Sun Apr 05 00:00:00 1970 PST - 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST - 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST - 398 | 8 | 00398 | Thu Apr 09 00:00:00 1970 PST - 399 | 509 | 00399_update9 | Fri Apr 10 00:00:00 1970 PST - 400 | 0 | 00400 | Thu Jan 01 00:00:00 1970 PST - 401 | 1 | 00401 | Fri Jan 02 00:00:00 1970 PST - 403 | 303 | 00403_update3 | Sun Jan 04 00:00:00 1970 PST - 404 | 4 | 00404 | Mon Jan 05 00:00:00 1970 PST - 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST - 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST - 408 | 8 | 00408 | Fri Jan 09 00:00:00 1970 PST - 409 | 509 | 00409_update9 | Sat Jan 10 00:00:00 1970 PST - 410 | 0 | 00410 | Sun Jan 11 00:00:00 1970 PST - 411 | 1 | 00411 | Mon Jan 12 00:00:00 1970 PST - 413 | 303 | 00413_update3 | Wed Jan 14 00:00:00 1970 PST - 414 | 4 | 00414 | Thu Jan 15 00:00:00 1970 PST - 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST - 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST - 418 | 8 | 00418 | Mon Jan 19 00:00:00 1970 PST - 419 | 509 | 00419_update9 | Tue Jan 20 00:00:00 1970 PST - 420 | 0 | 00420 | Wed Jan 21 00:00:00 1970 PST - 421 | 1 | 00421 | Thu Jan 22 00:00:00 1970 PST - 423 | 303 | 00423_update3 | Sat Jan 24 00:00:00 1970 PST - 424 | 4 | 00424 | Sun Jan 25 00:00:00 1970 PST - 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST - 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST - 428 | 8 | 00428 | Thu Jan 29 00:00:00 1970 PST - 429 | 509 | 00429_update9 | Fri Jan 30 00:00:00 1970 PST - 430 | 0 | 00430 | Sat Jan 31 00:00:00 1970 PST - 431 | 1 | 00431 | Sun Feb 01 00:00:00 1970 PST - 433 | 303 | 00433_update3 | Tue Feb 03 00:00:00 1970 PST - 434 | 4 | 00434 | Wed Feb 04 00:00:00 1970 PST - 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST - 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST - 438 | 8 | 00438 | Sun Feb 08 00:00:00 1970 PST - 439 | 509 | 00439_update9 | Mon Feb 09 00:00:00 1970 PST - 440 | 0 | 00440 | Tue Feb 10 00:00:00 1970 PST - 441 | 1 | 00441 | Wed Feb 11 00:00:00 1970 PST - 443 | 303 | 00443_update3 | Fri Feb 13 00:00:00 1970 PST - 444 | 4 | 00444 | Sat Feb 14 00:00:00 1970 PST - 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST - 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST - 448 | 8 | 00448 | Wed Feb 18 00:00:00 1970 PST - 449 | 509 | 00449_update9 | Thu Feb 19 00:00:00 1970 PST - 450 | 0 | 00450 | Fri Feb 20 00:00:00 1970 PST - 451 | 1 | 00451 | Sat Feb 21 00:00:00 1970 PST - 453 | 303 | 00453_update3 | Mon Feb 23 00:00:00 1970 PST - 454 | 4 | 00454 | Tue Feb 24 00:00:00 1970 PST - 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST - 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST - 458 | 8 | 00458 | Sat Feb 28 00:00:00 1970 PST - 459 | 509 | 00459_update9 | Sun Mar 01 00:00:00 1970 PST - 460 | 0 | 00460 | Mon Mar 02 00:00:00 1970 PST - 461 | 1 | 00461 | Tue Mar 03 00:00:00 1970 PST - 463 | 303 | 00463_update3 | Thu Mar 05 00:00:00 1970 PST - 464 | 4 | 00464 | Fri Mar 06 00:00:00 1970 PST - 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST - 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST - 468 | 8 | 00468 | Tue Mar 10 00:00:00 1970 PST - 469 | 509 | 00469_update9 | Wed Mar 11 00:00:00 1970 PST - 470 | 0 | 00470 | Thu Mar 12 00:00:00 1970 PST - 471 | 1 | 00471 | Fri Mar 13 00:00:00 1970 PST - 473 | 303 | 00473_update3 | Sun Mar 15 00:00:00 1970 PST - 474 | 4 | 00474 | Mon Mar 16 00:00:00 1970 PST - 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST - 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST - 478 | 8 | 00478 | Fri Mar 20 00:00:00 1970 PST - 479 | 509 | 00479_update9 | Sat Mar 21 00:00:00 1970 PST - 480 | 0 | 00480 | Sun Mar 22 00:00:00 1970 PST - 481 | 1 | 00481 | Mon Mar 23 00:00:00 1970 PST - 483 | 303 | 00483_update3 | Wed Mar 25 00:00:00 1970 PST - 484 | 4 | 00484 | Thu Mar 26 00:00:00 1970 PST - 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST - 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST - 488 | 8 | 00488 | Mon Mar 30 00:00:00 1970 PST - 489 | 509 | 00489_update9 | Tue Mar 31 00:00:00 1970 PST - 490 | 0 | 00490 | Wed Apr 01 00:00:00 1970 PST - 491 | 1 | 00491 | Thu Apr 02 00:00:00 1970 PST - 493 | 303 | 00493_update3 | Sat Apr 04 00:00:00 1970 PST - 494 | 4 | 00494 | Sun Apr 05 00:00:00 1970 PST - 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST - 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST - 498 | 8 | 00498 | Thu Apr 09 00:00:00 1970 PST - 499 | 509 | 00499_update9 | Fri Apr 10 00:00:00 1970 PST - 500 | 0 | 00500 | Thu Jan 01 00:00:00 1970 PST - 501 | 1 | 00501 | Fri Jan 02 00:00:00 1970 PST - 503 | 303 | 00503_update3 | Sun Jan 04 00:00:00 1970 PST - 504 | 4 | 00504 | Mon Jan 05 00:00:00 1970 PST - 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST - 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST - 508 | 8 | 00508 | Fri Jan 09 00:00:00 1970 PST - 509 | 509 | 00509_update9 | Sat Jan 10 00:00:00 1970 PST - 510 | 0 | 00510 | Sun Jan 11 00:00:00 1970 PST - 511 | 1 | 00511 | Mon Jan 12 00:00:00 1970 PST - 513 | 303 | 00513_update3 | Wed Jan 14 00:00:00 1970 PST - 514 | 4 | 00514 | Thu Jan 15 00:00:00 1970 PST - 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST - 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST - 518 | 8 | 00518 | Mon Jan 19 00:00:00 1970 PST - 519 | 509 | 00519_update9 | Tue Jan 20 00:00:00 1970 PST - 520 | 0 | 00520 | Wed Jan 21 00:00:00 1970 PST - 521 | 1 | 00521 | Thu Jan 22 00:00:00 1970 PST - 523 | 303 | 00523_update3 | Sat Jan 24 00:00:00 1970 PST - 524 | 4 | 00524 | Sun Jan 25 00:00:00 1970 PST - 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST - 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST - 528 | 8 | 00528 | Thu Jan 29 00:00:00 1970 PST - 529 | 509 | 00529_update9 | Fri Jan 30 00:00:00 1970 PST - 530 | 0 | 00530 | Sat Jan 31 00:00:00 1970 PST - 531 | 1 | 00531 | Sun Feb 01 00:00:00 1970 PST - 533 | 303 | 00533_update3 | Tue Feb 03 00:00:00 1970 PST - 534 | 4 | 00534 | Wed Feb 04 00:00:00 1970 PST - 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST - 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST - 538 | 8 | 00538 | Sun Feb 08 00:00:00 1970 PST - 539 | 509 | 00539_update9 | Mon Feb 09 00:00:00 1970 PST - 540 | 0 | 00540 | Tue Feb 10 00:00:00 1970 PST - 541 | 1 | 00541 | Wed Feb 11 00:00:00 1970 PST - 543 | 303 | 00543_update3 | Fri Feb 13 00:00:00 1970 PST - 544 | 4 | 00544 | Sat Feb 14 00:00:00 1970 PST - 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST - 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST - 548 | 8 | 00548 | Wed Feb 18 00:00:00 1970 PST - 549 | 509 | 00549_update9 | Thu Feb 19 00:00:00 1970 PST - 550 | 0 | 00550 | Fri Feb 20 00:00:00 1970 PST - 551 | 1 | 00551 | Sat Feb 21 00:00:00 1970 PST - 553 | 303 | 00553_update3 | Mon Feb 23 00:00:00 1970 PST - 554 | 4 | 00554 | Tue Feb 24 00:00:00 1970 PST - 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST - 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST - 558 | 8 | 00558 | Sat Feb 28 00:00:00 1970 PST - 559 | 509 | 00559_update9 | Sun Mar 01 00:00:00 1970 PST - 560 | 0 | 00560 | Mon Mar 02 00:00:00 1970 PST - 561 | 1 | 00561 | Tue Mar 03 00:00:00 1970 PST - 563 | 303 | 00563_update3 | Thu Mar 05 00:00:00 1970 PST - 564 | 4 | 00564 | Fri Mar 06 00:00:00 1970 PST - 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST - 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST - 568 | 8 | 00568 | Tue Mar 10 00:00:00 1970 PST - 569 | 509 | 00569_update9 | Wed Mar 11 00:00:00 1970 PST - 570 | 0 | 00570 | Thu Mar 12 00:00:00 1970 PST - 571 | 1 | 00571 | Fri Mar 13 00:00:00 1970 PST - 573 | 303 | 00573_update3 | Sun Mar 15 00:00:00 1970 PST - 574 | 4 | 00574 | Mon Mar 16 00:00:00 1970 PST - 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST - 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST - 578 | 8 | 00578 | Fri Mar 20 00:00:00 1970 PST - 579 | 509 | 00579_update9 | Sat Mar 21 00:00:00 1970 PST - 580 | 0 | 00580 | Sun Mar 22 00:00:00 1970 PST - 581 | 1 | 00581 | Mon Mar 23 00:00:00 1970 PST - 583 | 303 | 00583_update3 | Wed Mar 25 00:00:00 1970 PST - 584 | 4 | 00584 | Thu Mar 26 00:00:00 1970 PST - 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST - 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST - 588 | 8 | 00588 | Mon Mar 30 00:00:00 1970 PST - 589 | 509 | 00589_update9 | Tue Mar 31 00:00:00 1970 PST - 590 | 0 | 00590 | Wed Apr 01 00:00:00 1970 PST - 591 | 1 | 00591 | Thu Apr 02 00:00:00 1970 PST - 593 | 303 | 00593_update3 | Sat Apr 04 00:00:00 1970 PST - 594 | 4 | 00594 | Sun Apr 05 00:00:00 1970 PST - 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST - 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST - 598 | 8 | 00598 | Thu Apr 09 00:00:00 1970 PST - 599 | 509 | 00599_update9 | Fri Apr 10 00:00:00 1970 PST - 600 | 0 | 00600 | Thu Jan 01 00:00:00 1970 PST - 601 | 1 | 00601 | Fri Jan 02 00:00:00 1970 PST - 603 | 303 | 00603_update3 | Sun Jan 04 00:00:00 1970 PST - 604 | 4 | 00604 | Mon Jan 05 00:00:00 1970 PST - 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST - 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST - 608 | 8 | 00608 | Fri Jan 09 00:00:00 1970 PST - 609 | 509 | 00609_update9 | Sat Jan 10 00:00:00 1970 PST - 610 | 0 | 00610 | Sun Jan 11 00:00:00 1970 PST - 611 | 1 | 00611 | Mon Jan 12 00:00:00 1970 PST - 613 | 303 | 00613_update3 | Wed Jan 14 00:00:00 1970 PST - 614 | 4 | 00614 | Thu Jan 15 00:00:00 1970 PST - 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST - 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST - 618 | 8 | 00618 | Mon Jan 19 00:00:00 1970 PST - 619 | 509 | 00619_update9 | Tue Jan 20 00:00:00 1970 PST - 620 | 0 | 00620 | Wed Jan 21 00:00:00 1970 PST - 621 | 1 | 00621 | Thu Jan 22 00:00:00 1970 PST - 623 | 303 | 00623_update3 | Sat Jan 24 00:00:00 1970 PST - 624 | 4 | 00624 | Sun Jan 25 00:00:00 1970 PST - 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST - 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST - 628 | 8 | 00628 | Thu Jan 29 00:00:00 1970 PST - 629 | 509 | 00629_update9 | Fri Jan 30 00:00:00 1970 PST - 630 | 0 | 00630 | Sat Jan 31 00:00:00 1970 PST - 631 | 1 | 00631 | Sun Feb 01 00:00:00 1970 PST - 633 | 303 | 00633_update3 | Tue Feb 03 00:00:00 1970 PST - 634 | 4 | 00634 | Wed Feb 04 00:00:00 1970 PST - 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST - 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST - 638 | 8 | 00638 | Sun Feb 08 00:00:00 1970 PST - 639 | 509 | 00639_update9 | Mon Feb 09 00:00:00 1970 PST - 640 | 0 | 00640 | Tue Feb 10 00:00:00 1970 PST - 641 | 1 | 00641 | Wed Feb 11 00:00:00 1970 PST - 643 | 303 | 00643_update3 | Fri Feb 13 00:00:00 1970 PST - 644 | 4 | 00644 | Sat Feb 14 00:00:00 1970 PST - 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST - 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST - 648 | 8 | 00648 | Wed Feb 18 00:00:00 1970 PST - 649 | 509 | 00649_update9 | Thu Feb 19 00:00:00 1970 PST - 650 | 0 | 00650 | Fri Feb 20 00:00:00 1970 PST - 651 | 1 | 00651 | Sat Feb 21 00:00:00 1970 PST - 653 | 303 | 00653_update3 | Mon Feb 23 00:00:00 1970 PST - 654 | 4 | 00654 | Tue Feb 24 00:00:00 1970 PST - 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST - 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST - 658 | 8 | 00658 | Sat Feb 28 00:00:00 1970 PST - 659 | 509 | 00659_update9 | Sun Mar 01 00:00:00 1970 PST - 660 | 0 | 00660 | Mon Mar 02 00:00:00 1970 PST - 661 | 1 | 00661 | Tue Mar 03 00:00:00 1970 PST - 663 | 303 | 00663_update3 | Thu Mar 05 00:00:00 1970 PST - 664 | 4 | 00664 | Fri Mar 06 00:00:00 1970 PST - 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST - 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST - 668 | 8 | 00668 | Tue Mar 10 00:00:00 1970 PST - 669 | 509 | 00669_update9 | Wed Mar 11 00:00:00 1970 PST - 670 | 0 | 00670 | Thu Mar 12 00:00:00 1970 PST - 671 | 1 | 00671 | Fri Mar 13 00:00:00 1970 PST - 673 | 303 | 00673_update3 | Sun Mar 15 00:00:00 1970 PST - 674 | 4 | 00674 | Mon Mar 16 00:00:00 1970 PST - 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST - 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST - 678 | 8 | 00678 | Fri Mar 20 00:00:00 1970 PST - 679 | 509 | 00679_update9 | Sat Mar 21 00:00:00 1970 PST - 680 | 0 | 00680 | Sun Mar 22 00:00:00 1970 PST - 681 | 1 | 00681 | Mon Mar 23 00:00:00 1970 PST - 683 | 303 | 00683_update3 | Wed Mar 25 00:00:00 1970 PST - 684 | 4 | 00684 | Thu Mar 26 00:00:00 1970 PST - 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST - 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST - 688 | 8 | 00688 | Mon Mar 30 00:00:00 1970 PST - 689 | 509 | 00689_update9 | Tue Mar 31 00:00:00 1970 PST - 690 | 0 | 00690 | Wed Apr 01 00:00:00 1970 PST - 691 | 1 | 00691 | Thu Apr 02 00:00:00 1970 PST - 693 | 303 | 00693_update3 | Sat Apr 04 00:00:00 1970 PST - 694 | 4 | 00694 | Sun Apr 05 00:00:00 1970 PST - 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST - 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST - 698 | 8 | 00698 | Thu Apr 09 00:00:00 1970 PST - 699 | 509 | 00699_update9 | Fri Apr 10 00:00:00 1970 PST - 700 | 0 | 00700 | Thu Jan 01 00:00:00 1970 PST - 701 | 1 | 00701 | Fri Jan 02 00:00:00 1970 PST - 703 | 303 | 00703_update3 | Sun Jan 04 00:00:00 1970 PST - 704 | 4 | 00704 | Mon Jan 05 00:00:00 1970 PST - 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST - 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST - 708 | 8 | 00708 | Fri Jan 09 00:00:00 1970 PST - 709 | 509 | 00709_update9 | Sat Jan 10 00:00:00 1970 PST - 710 | 0 | 00710 | Sun Jan 11 00:00:00 1970 PST - 711 | 1 | 00711 | Mon Jan 12 00:00:00 1970 PST - 713 | 303 | 00713_update3 | Wed Jan 14 00:00:00 1970 PST - 714 | 4 | 00714 | Thu Jan 15 00:00:00 1970 PST - 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST - 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST - 718 | 8 | 00718 | Mon Jan 19 00:00:00 1970 PST - 719 | 509 | 00719_update9 | Tue Jan 20 00:00:00 1970 PST - 720 | 0 | 00720 | Wed Jan 21 00:00:00 1970 PST - 721 | 1 | 00721 | Thu Jan 22 00:00:00 1970 PST - 723 | 303 | 00723_update3 | Sat Jan 24 00:00:00 1970 PST - 724 | 4 | 00724 | Sun Jan 25 00:00:00 1970 PST - 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST - 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST - 728 | 8 | 00728 | Thu Jan 29 00:00:00 1970 PST - 729 | 509 | 00729_update9 | Fri Jan 30 00:00:00 1970 PST - 730 | 0 | 00730 | Sat Jan 31 00:00:00 1970 PST - 731 | 1 | 00731 | Sun Feb 01 00:00:00 1970 PST - 733 | 303 | 00733_update3 | Tue Feb 03 00:00:00 1970 PST - 734 | 4 | 00734 | Wed Feb 04 00:00:00 1970 PST - 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST - 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST - 738 | 8 | 00738 | Sun Feb 08 00:00:00 1970 PST - 739 | 509 | 00739_update9 | Mon Feb 09 00:00:00 1970 PST - 740 | 0 | 00740 | Tue Feb 10 00:00:00 1970 PST - 741 | 1 | 00741 | Wed Feb 11 00:00:00 1970 PST - 743 | 303 | 00743_update3 | Fri Feb 13 00:00:00 1970 PST - 744 | 4 | 00744 | Sat Feb 14 00:00:00 1970 PST - 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST - 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST - 748 | 8 | 00748 | Wed Feb 18 00:00:00 1970 PST - 749 | 509 | 00749_update9 | Thu Feb 19 00:00:00 1970 PST - 750 | 0 | 00750 | Fri Feb 20 00:00:00 1970 PST - 751 | 1 | 00751 | Sat Feb 21 00:00:00 1970 PST - 753 | 303 | 00753_update3 | Mon Feb 23 00:00:00 1970 PST - 754 | 4 | 00754 | Tue Feb 24 00:00:00 1970 PST - 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST - 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST - 758 | 8 | 00758 | Sat Feb 28 00:00:00 1970 PST - 759 | 509 | 00759_update9 | Sun Mar 01 00:00:00 1970 PST - 760 | 0 | 00760 | Mon Mar 02 00:00:00 1970 PST - 761 | 1 | 00761 | Tue Mar 03 00:00:00 1970 PST - 763 | 303 | 00763_update3 | Thu Mar 05 00:00:00 1970 PST - 764 | 4 | 00764 | Fri Mar 06 00:00:00 1970 PST - 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST - 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST - 768 | 8 | 00768 | Tue Mar 10 00:00:00 1970 PST - 769 | 509 | 00769_update9 | Wed Mar 11 00:00:00 1970 PST - 770 | 0 | 00770 | Thu Mar 12 00:00:00 1970 PST - 771 | 1 | 00771 | Fri Mar 13 00:00:00 1970 PST - 773 | 303 | 00773_update3 | Sun Mar 15 00:00:00 1970 PST - 774 | 4 | 00774 | Mon Mar 16 00:00:00 1970 PST - 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST - 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST - 778 | 8 | 00778 | Fri Mar 20 00:00:00 1970 PST - 779 | 509 | 00779_update9 | Sat Mar 21 00:00:00 1970 PST - 780 | 0 | 00780 | Sun Mar 22 00:00:00 1970 PST - 781 | 1 | 00781 | Mon Mar 23 00:00:00 1970 PST - 783 | 303 | 00783_update3 | Wed Mar 25 00:00:00 1970 PST - 784 | 4 | 00784 | Thu Mar 26 00:00:00 1970 PST - 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST - 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST - 788 | 8 | 00788 | Mon Mar 30 00:00:00 1970 PST - 789 | 509 | 00789_update9 | Tue Mar 31 00:00:00 1970 PST - 790 | 0 | 00790 | Wed Apr 01 00:00:00 1970 PST - 791 | 1 | 00791 | Thu Apr 02 00:00:00 1970 PST - 793 | 303 | 00793_update3 | Sat Apr 04 00:00:00 1970 PST - 794 | 4 | 00794 | Sun Apr 05 00:00:00 1970 PST - 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST - 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST - 798 | 8 | 00798 | Thu Apr 09 00:00:00 1970 PST - 799 | 509 | 00799_update9 | Fri Apr 10 00:00:00 1970 PST - 800 | 0 | 00800 | Thu Jan 01 00:00:00 1970 PST - 801 | 1 | 00801 | Fri Jan 02 00:00:00 1970 PST - 803 | 303 | 00803_update3 | Sun Jan 04 00:00:00 1970 PST - 804 | 4 | 00804 | Mon Jan 05 00:00:00 1970 PST - 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST - 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST - 808 | 8 | 00808 | Fri Jan 09 00:00:00 1970 PST - 809 | 509 | 00809_update9 | Sat Jan 10 00:00:00 1970 PST - 810 | 0 | 00810 | Sun Jan 11 00:00:00 1970 PST - 811 | 1 | 00811 | Mon Jan 12 00:00:00 1970 PST - 813 | 303 | 00813_update3 | Wed Jan 14 00:00:00 1970 PST - 814 | 4 | 00814 | Thu Jan 15 00:00:00 1970 PST - 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST - 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST - 818 | 8 | 00818 | Mon Jan 19 00:00:00 1970 PST - 819 | 509 | 00819_update9 | Tue Jan 20 00:00:00 1970 PST - 820 | 0 | 00820 | Wed Jan 21 00:00:00 1970 PST - 821 | 1 | 00821 | Thu Jan 22 00:00:00 1970 PST - 823 | 303 | 00823_update3 | Sat Jan 24 00:00:00 1970 PST - 824 | 4 | 00824 | Sun Jan 25 00:00:00 1970 PST - 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST - 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST - 828 | 8 | 00828 | Thu Jan 29 00:00:00 1970 PST - 829 | 509 | 00829_update9 | Fri Jan 30 00:00:00 1970 PST - 830 | 0 | 00830 | Sat Jan 31 00:00:00 1970 PST - 831 | 1 | 00831 | Sun Feb 01 00:00:00 1970 PST - 833 | 303 | 00833_update3 | Tue Feb 03 00:00:00 1970 PST - 834 | 4 | 00834 | Wed Feb 04 00:00:00 1970 PST - 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST - 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST - 838 | 8 | 00838 | Sun Feb 08 00:00:00 1970 PST - 839 | 509 | 00839_update9 | Mon Feb 09 00:00:00 1970 PST - 840 | 0 | 00840 | Tue Feb 10 00:00:00 1970 PST - 841 | 1 | 00841 | Wed Feb 11 00:00:00 1970 PST - 843 | 303 | 00843_update3 | Fri Feb 13 00:00:00 1970 PST - 844 | 4 | 00844 | Sat Feb 14 00:00:00 1970 PST - 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST - 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST - 848 | 8 | 00848 | Wed Feb 18 00:00:00 1970 PST - 849 | 509 | 00849_update9 | Thu Feb 19 00:00:00 1970 PST - 850 | 0 | 00850 | Fri Feb 20 00:00:00 1970 PST - 851 | 1 | 00851 | Sat Feb 21 00:00:00 1970 PST - 853 | 303 | 00853_update3 | Mon Feb 23 00:00:00 1970 PST - 854 | 4 | 00854 | Tue Feb 24 00:00:00 1970 PST - 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST - 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST - 858 | 8 | 00858 | Sat Feb 28 00:00:00 1970 PST - 859 | 509 | 00859_update9 | Sun Mar 01 00:00:00 1970 PST - 860 | 0 | 00860 | Mon Mar 02 00:00:00 1970 PST - 861 | 1 | 00861 | Tue Mar 03 00:00:00 1970 PST - 863 | 303 | 00863_update3 | Thu Mar 05 00:00:00 1970 PST - 864 | 4 | 00864 | Fri Mar 06 00:00:00 1970 PST - 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST - 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST - 868 | 8 | 00868 | Tue Mar 10 00:00:00 1970 PST - 869 | 509 | 00869_update9 | Wed Mar 11 00:00:00 1970 PST - 870 | 0 | 00870 | Thu Mar 12 00:00:00 1970 PST - 871 | 1 | 00871 | Fri Mar 13 00:00:00 1970 PST - 873 | 303 | 00873_update3 | Sun Mar 15 00:00:00 1970 PST - 874 | 4 | 00874 | Mon Mar 16 00:00:00 1970 PST - 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST - 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST - 878 | 8 | 00878 | Fri Mar 20 00:00:00 1970 PST - 879 | 509 | 00879_update9 | Sat Mar 21 00:00:00 1970 PST - 880 | 0 | 00880 | Sun Mar 22 00:00:00 1970 PST - 881 | 1 | 00881 | Mon Mar 23 00:00:00 1970 PST - 883 | 303 | 00883_update3 | Wed Mar 25 00:00:00 1970 PST - 884 | 4 | 00884 | Thu Mar 26 00:00:00 1970 PST - 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST - 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST - 888 | 8 | 00888 | Mon Mar 30 00:00:00 1970 PST - 889 | 509 | 00889_update9 | Tue Mar 31 00:00:00 1970 PST - 890 | 0 | 00890 | Wed Apr 01 00:00:00 1970 PST - 891 | 1 | 00891 | Thu Apr 02 00:00:00 1970 PST - 893 | 303 | 00893_update3 | Sat Apr 04 00:00:00 1970 PST - 894 | 4 | 00894 | Sun Apr 05 00:00:00 1970 PST - 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST - 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST - 898 | 8 | 00898 | Thu Apr 09 00:00:00 1970 PST - 899 | 509 | 00899_update9 | Fri Apr 10 00:00:00 1970 PST - 900 | 0 | 00900 | Thu Jan 01 00:00:00 1970 PST - 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST - 903 | 303 | 00903_update3 | Sun Jan 04 00:00:00 1970 PST - 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST - 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST - 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST - 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST - 909 | 509 | 00909_update9 | Sat Jan 10 00:00:00 1970 PST - 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST - 911 | 1 | 00911 | Mon Jan 12 00:00:00 1970 PST - 913 | 303 | 00913_update3 | Wed Jan 14 00:00:00 1970 PST - 914 | 4 | 00914 | Thu Jan 15 00:00:00 1970 PST - 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST - 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST - 918 | 8 | 00918 | Mon Jan 19 00:00:00 1970 PST - 919 | 509 | 00919_update9 | Tue Jan 20 00:00:00 1970 PST - 920 | 0 | 00920 | Wed Jan 21 00:00:00 1970 PST - 921 | 1 | 00921 | Thu Jan 22 00:00:00 1970 PST - 923 | 303 | 00923_update3 | Sat Jan 24 00:00:00 1970 PST - 924 | 4 | 00924 | Sun Jan 25 00:00:00 1970 PST - 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST - 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST - 928 | 8 | 00928 | Thu Jan 29 00:00:00 1970 PST - 929 | 509 | 00929_update9 | Fri Jan 30 00:00:00 1970 PST - 930 | 0 | 00930 | Sat Jan 31 00:00:00 1970 PST - 931 | 1 | 00931 | Sun Feb 01 00:00:00 1970 PST - 933 | 303 | 00933_update3 | Tue Feb 03 00:00:00 1970 PST - 934 | 4 | 00934 | Wed Feb 04 00:00:00 1970 PST - 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST - 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST - 938 | 8 | 00938 | Sun Feb 08 00:00:00 1970 PST - 939 | 509 | 00939_update9 | Mon Feb 09 00:00:00 1970 PST - 940 | 0 | 00940 | Tue Feb 10 00:00:00 1970 PST - 941 | 1 | 00941 | Wed Feb 11 00:00:00 1970 PST - 943 | 303 | 00943_update3 | Fri Feb 13 00:00:00 1970 PST - 944 | 4 | 00944 | Sat Feb 14 00:00:00 1970 PST - 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST - 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST - 948 | 8 | 00948 | Wed Feb 18 00:00:00 1970 PST - 949 | 509 | 00949_update9 | Thu Feb 19 00:00:00 1970 PST - 950 | 0 | 00950 | Fri Feb 20 00:00:00 1970 PST - 951 | 1 | 00951 | Sat Feb 21 00:00:00 1970 PST - 953 | 303 | 00953_update3 | Mon Feb 23 00:00:00 1970 PST - 954 | 4 | 00954 | Tue Feb 24 00:00:00 1970 PST - 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST - 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST - 958 | 8 | 00958 | Sat Feb 28 00:00:00 1970 PST - 959 | 509 | 00959_update9 | Sun Mar 01 00:00:00 1970 PST - 960 | 0 | 00960 | Mon Mar 02 00:00:00 1970 PST - 961 | 1 | 00961 | Tue Mar 03 00:00:00 1970 PST - 963 | 303 | 00963_update3 | Thu Mar 05 00:00:00 1970 PST - 964 | 4 | 00964 | Fri Mar 06 00:00:00 1970 PST - 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST - 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST - 968 | 8 | 00968 | Tue Mar 10 00:00:00 1970 PST - 969 | 509 | 00969_update9 | Wed Mar 11 00:00:00 1970 PST - 970 | 0 | 00970 | Thu Mar 12 00:00:00 1970 PST - 971 | 1 | 00971 | Fri Mar 13 00:00:00 1970 PST - 973 | 303 | 00973_update3 | Sun Mar 15 00:00:00 1970 PST - 974 | 4 | 00974 | Mon Mar 16 00:00:00 1970 PST - 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST - 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST - 978 | 8 | 00978 | Fri Mar 20 00:00:00 1970 PST - 979 | 509 | 00979_update9 | Sat Mar 21 00:00:00 1970 PST - 980 | 0 | 00980 | Sun Mar 22 00:00:00 1970 PST - 981 | 1 | 00981 | Mon Mar 23 00:00:00 1970 PST - 983 | 303 | 00983_update3 | Wed Mar 25 00:00:00 1970 PST - 984 | 4 | 00984 | Thu Mar 26 00:00:00 1970 PST - 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST - 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST - 988 | 8 | 00988 | Mon Mar 30 00:00:00 1970 PST - 989 | 509 | 00989_update9 | Tue Mar 31 00:00:00 1970 PST - 990 | 0 | 00990 | Wed Apr 01 00:00:00 1970 PST - 991 | 1 | 00991 | Thu Apr 02 00:00:00 1970 PST - 993 | 303 | 00993_update3 | Sat Apr 04 00:00:00 1970 PST - 994 | 4 | 00994 | Sun Apr 05 00:00:00 1970 PST - 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST - 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST - 998 | 8 | 00998 | Thu Apr 09 00:00:00 1970 PST - 999 | 509 | 00999_update9 | Fri Apr 10 00:00:00 1970 PST - 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST - 1001 | 101 | 0000100001 | - 1003 | 403 | 0000300003_update3 | - 1004 | 104 | 0000400004 | - 1006 | 106 | 0000600006 | - 1007 | 507 | 0000700007_update7 | - 1008 | 108 | 0000800008 | - 1009 | 609 | 0000900009_update9 | - 1010 | 100 | 0001000010 | - 1011 | 101 | 0001100011 | - 1013 | 403 | 0001300013_update3 | - 1014 | 104 | 0001400014 | - 1016 | 106 | 0001600016 | - 1017 | 507 | 0001700017_update7 | - 1018 | 108 | 0001800018 | - 1019 | 609 | 0001900019_update9 | - 1020 | 100 | 0002000020 | - 1101 | 201 | aaa | - 1103 | 503 | ccc_update3 | - 1104 | 204 | ddd | -(819 rows) - ---Testcase 300: -EXPLAIN (verbose, costs off) -INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Insert on public.ft2 - -> Result - Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text -(3 rows) - ---Testcase 301: -INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); ---Testcase 302: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; -- can be pushed down - QUERY PLAN ---------------------------------------------------------------------------------- - Update on public.ft2 - -> Foreign Update on public.ft2 - SQLite query: UPDATE main."T 1" SET `c3` = 'bar' WHERE ((`C 1` = 1200)) -(3 rows) - ---Testcase 303: -UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; ---Testcase 304: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 WHERE c1 = 1200; -- can be pushed down - QUERY PLAN ---------------------------------------------------------------------- - Delete on public.ft2 - -> Foreign Delete on public.ft2 - SQLite query: DELETE FROM main."T 1" WHERE ((`C 1` = 1200)) -(3 rows) - ---Testcase 305: -DELETE FROM ft2 WHERE c1 = 1200; --- Test UPDATE/DELETE on a three-table join ---Testcase 306: -INSERT INTO ft2 (c1,c2,c3) - SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id; ---Testcase 307: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'foo' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; -- can be pushed down - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Update on public.ft2 - -> Hash Join - Output: ft2.c1, ft2.c2, NULL::integer, 'foo'::text, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.c1, ft4.*, ft5.* - Hash Cond: (ft5.c1 = ft4.c1) - -> Foreign Scan on public.ft5 - Output: ft5.*, ft5.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" - -> Hash - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1 - -> Foreign Scan - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1 - SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, r2.`c1` FROM (main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)))) - -> Hash Join - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1 - Hash Cond: (ft2.c2 = ft4.c1) - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8 - SQLite query: SELECT `C 1`, `c2`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1200)) - -> Hash - Output: ft4.*, ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.*, ft4.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" -(23 rows) - ---Testcase 308: -UPDATE ft2 SET c3 = 'foo' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; ---Testcase 309: -SELECT ft2, ft2.*, ft4, ft4.* - FROM ft2 INNER JOIN ft4 ON (ft2.c1 > 1200 AND ft2.c2 = ft4.c1) - INNER JOIN ft5 ON (ft4.c1 = ft5.c1); - ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3 ---------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+-------- - (1206,6,foo,,,,"ft2 ",) | 1206 | 6 | foo | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006 - (1212,12,foo,,,,"ft2 ",) | 1212 | 12 | foo | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012 - (1218,18,foo,,,,"ft2 ",) | 1218 | 18 | foo | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018 - (1224,24,foo,,,,"ft2 ",) | 1224 | 24 | foo | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024 - (1230,30,foo,,,,"ft2 ",) | 1230 | 30 | foo | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030 - (1236,36,foo,,,,"ft2 ",) | 1236 | 36 | foo | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036 - (1242,42,foo,,,,"ft2 ",) | 1242 | 42 | foo | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042 - (1248,48,foo,,,,"ft2 ",) | 1248 | 48 | foo | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048 - (1254,54,foo,,,,"ft2 ",) | 1254 | 54 | foo | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054 - (1260,60,foo,,,,"ft2 ",) | 1260 | 60 | foo | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060 - (1266,66,foo,,,,"ft2 ",) | 1266 | 66 | foo | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066 - (1272,72,foo,,,,"ft2 ",) | 1272 | 72 | foo | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072 - (1278,78,foo,,,,"ft2 ",) | 1278 | 78 | foo | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078 - (1284,84,foo,,,,"ft2 ",) | 1284 | 84 | foo | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084 - (1290,90,foo,,,,"ft2 ",) | 1290 | 90 | foo | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090 - (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096 -(16 rows) - ---Testcase 310: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 - USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; -- can be pushed down - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Delete on public.ft2 - -> Foreign Scan - Output: ft2.c1, ft4.*, ft5.* - SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END FROM ((main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)) AND (((r1.`C 1` % 10) = 0)))) LEFT JOIN main."T 4" r3 ON (((r2.`c1` = r3.`c1`)))) - -> Hash Left Join - Output: ft2.c1, ft4.*, ft5.* - Hash Cond: (ft4.c1 = ft5.c1) - -> Hash Join - Output: ft2.c1, ft4.*, ft4.c1 - Hash Cond: (ft2.c2 = ft4.c1) - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 1200)) AND (((`C 1` % 10) = 0)) - -> Hash - Output: ft4.*, ft4.c1 - -> Foreign Scan on public.ft4 - Output: ft4.*, ft4.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" - -> Hash - Output: ft5.*, ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.*, ft5.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" -(23 rows) - ---Testcase 311: -SELECT 100 FROM ft2, ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; - ?column? ----------- - 100 - 100 - 100 - 100 - 100 - 100 - 100 - 100 - 100 - 100 -(10 rows) - ---Testcase 570: -DELETE FROM ft2 - USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; ---Testcase 312: -DELETE FROM ft2 WHERE ft2.c1 > 1200; --- Test UPDATE with a MULTIEXPR sub-select --- (maybe someday this'll be remotely executable, but not today) ---Testcase 571: -EXPLAIN (verbose, costs off) -UPDATE ft2 AS target SET (c2, c7) = ( - SELECT c2 * 10, c7 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- - Update on public.ft2 target - -> Foreign Scan on public.ft2 target - Output: target.c1, $1, NULL::integer, target.c3, target.c4, target.c5, target.c6, $2, target.c8, (SubPlan 1 (returns $1,$2)), target.c1 - SQLite query: SELECT `C 1`, `c3`, `c4`, `c5`, `c6`, `c8` FROM main."T 1" WHERE ((`C 1` > 1100)) - SubPlan 1 (returns $1,$2) - -> Foreign Scan on public.ft2 src - Output: (src.c2 * 10), src.c7 - SQLite query: SELECT `c2`, `c7` FROM main."T 1" WHERE ((? = `C 1`)) -(8 rows) - ---Testcase 572: -UPDATE ft2 AS target SET (c2, c7) = ( - SELECT c2 * 10, c7 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; ---Testcase 573: -UPDATE ft2 AS target SET (c2) = ( - SELECT c2 / 10 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; --- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing --- user-defined operators/functions ---ALTER SERVER loopback OPTIONS (DROP extensions); ---Testcase 574: -INSERT INTO ft2 (c1,c2,c3) - SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id; ---Testcase 575: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; -- can't be pushed down - QUERY PLAN ----------------------------------------------------------------------------------------- - Update on public.ft2 - -> Foreign Scan on public.ft2 - Output: c1, c2, NULL::integer, 'bar'::text, c4, c5, c6, c7, c8, c1 - Filter: (sqlite_fdw_abs(ft2.c1) > 2000) - SQLite query: SELECT `C 1`, `c2`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -(5 rows) - ---Testcase 576: -UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; ---Testcase 577: -SELECT * FROM ft2 WHERE sqlite_fdw_abs(c1) > 2000; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+----+-----+----+----+----+------------+---- - 2001 | 1 | bar | | | | ft2 | - 2002 | 2 | bar | | | | ft2 | - 2003 | 3 | bar | | | | ft2 | - 2004 | 4 | bar | | | | ft2 | - 2005 | 5 | bar | | | | ft2 | - 2006 | 6 | bar | | | | ft2 | - 2007 | 7 | bar | | | | ft2 | - 2008 | 8 | bar | | | | ft2 | - 2009 | 9 | bar | | | | ft2 | - 2010 | 0 | bar | | | | ft2 | -(10 rows) - ---Testcase 578: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'baz' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; -- can't be pushed down - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Update on public.ft2 - -> Nested Loop - Output: ft2.c1, ft2.c2, NULL::integer, 'baz'::text, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.c1, ft4.*, ft5.* - Join Filter: (ft2.c2 === ft4.c1) - -> Hash Join - Output: ft4.*, ft4.c1, ft5.* - Hash Cond: (ft4.c1 = ft5.c1) - -> Foreign Scan on public.ft4 - Output: ft4.*, ft4.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" - -> Hash - Output: ft5.*, ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.*, ft5.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" - -> Materialize - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8 - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8 - SQLite query: SELECT `C 1`, `c2`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 2000)) -(20 rows) - ---Testcase 579: -UPDATE ft2 SET c3 = 'baz' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; ---Testcase 580: -SELECT ft2.*, ft4.*, ft5.* - FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 -------+----+-----+----+----+----+------------+----+----+----+--------+----+----+-------- - 2006 | 6 | baz | | | | ft2 | | 6 | 7 | AAA006 | 6 | 7 | AAA006 -(1 row) - ---Testcase 581: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 - USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down - QUERY PLAN ---------------------------------------------------------------------------------------------------- - Delete on public.ft2 - -> Nested Loop - Output: ft2.c1, ft4.*, ft5.* - Join Filter: (ft4.c1 === ft5.c1) - -> Hash Join - Output: ft2.c1, ft4.*, ft4.c1 - Hash Cond: (ft4.c1 = ft2.c2) - -> Foreign Scan on public.ft4 - Output: ft4.*, ft4.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" - -> Hash - Output: ft2.c1, ft2.c2 - -> Foreign Scan on public.ft2 - Output: ft2.c1, ft2.c2 - SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 2000)) - -> Materialize - Output: ft5.*, ft5.c1 - -> Foreign Scan on public.ft5 - Output: ft5.*, ft5.c1 - SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" -(20 rows) - ---Testcase 582: -SELECT ft2.c1, ft2.c2, ft2.c3 FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down - c1 | c2 | c3 -------+----+----- - 2006 | 6 | baz -(1 row) - ---Testcase 583: -DELETE FROM ft2 - USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; ---Testcase 584: -DELETE FROM ft2 WHERE ft2.c1 > 2000; ---ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --- Test that trigger on remote table works as expected ---Testcase 585: -CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$ -BEGIN - NEW.c3 = NEW.c3 || '_trig_update'; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; ---Testcase 586: -CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE - ON ft2 FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG(); ---Testcase 313: -INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff'); ---Testcase 314: -SELECT * FROM ft2 WHERE c1 = 1208; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-----------------+----+----+----+------------+---- - 1208 | 818 | fff_trig_update | | | | ft2 | -(1 row) - ---Testcase 315: -INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;'); ---Testcase 316: -SELECT * FROM ft2 WHERE c1 = 1218; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-----------------+----+----+------+------------+---- - 1218 | 818 | ggg_trig_update | | | (--; | ft2 | -(1 row) - ---Testcase 317: -UPDATE ft2 SET c2 = c2 + 600, c3 = c3 WHERE c1 % 10 = 8 AND c1 < 1200; ---Testcase 318: -SELECT * FROM ft2 WHERE c1 % 10 = 8 AND c1 < 1200; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+------------------------+------------------------------+--------------------------+----+------------+----- - 8 | 608 | 00008_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 18 | 608 | 00018_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 28 | 608 | 00028_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 38 | 608 | 00038_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 48 | 608 | 00048_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 58 | 608 | 00058_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 68 | 608 | 00068_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 78 | 608 | 00078_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 88 | 608 | 00088_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 98 | 608 | 00098_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 108 | 608 | 00108_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 118 | 608 | 00118_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 128 | 608 | 00128_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 138 | 608 | 00138_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 148 | 608 | 00148_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 158 | 608 | 00158_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 168 | 608 | 00168_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 178 | 608 | 00178_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 188 | 608 | 00188_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 198 | 608 | 00198_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 208 | 608 | 00208_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 218 | 608 | 00218_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 228 | 608 | 00228_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 238 | 608 | 00238_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 248 | 608 | 00248_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 258 | 608 | 00258_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 268 | 608 | 00268_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 278 | 608 | 00278_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 288 | 608 | 00288_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 298 | 608 | 00298_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 308 | 608 | 00308_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 318 | 608 | 00318_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 328 | 608 | 00328_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 338 | 608 | 00338_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 348 | 608 | 00348_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 358 | 608 | 00358_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 368 | 608 | 00368_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 378 | 608 | 00378_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 388 | 608 | 00388_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 398 | 608 | 00398_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 408 | 608 | 00408_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 418 | 608 | 00418_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 428 | 608 | 00428_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 438 | 608 | 00438_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 448 | 608 | 00448_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 458 | 608 | 00458_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 468 | 608 | 00468_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 478 | 608 | 00478_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 488 | 608 | 00488_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 498 | 608 | 00498_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 508 | 608 | 00508_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 518 | 608 | 00518_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 528 | 608 | 00528_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 538 | 608 | 00538_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 548 | 608 | 00548_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 558 | 608 | 00558_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 568 | 608 | 00568_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 578 | 608 | 00578_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 588 | 608 | 00588_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 598 | 608 | 00598_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 608 | 608 | 00608_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 618 | 608 | 00618_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 628 | 608 | 00628_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 638 | 608 | 00638_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 648 | 608 | 00648_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 658 | 608 | 00658_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 668 | 608 | 00668_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 678 | 608 | 00678_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 688 | 608 | 00688_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 698 | 608 | 00698_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 708 | 608 | 00708_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 718 | 608 | 00718_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 728 | 608 | 00728_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 738 | 608 | 00738_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 748 | 608 | 00748_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 758 | 608 | 00758_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 768 | 608 | 00768_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 778 | 608 | 00778_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 788 | 608 | 00788_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 798 | 608 | 00798_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 808 | 608 | 00808_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 818 | 608 | 00818_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 828 | 608 | 00828_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 838 | 608 | 00838_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 848 | 608 | 00848_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 858 | 608 | 00858_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 868 | 608 | 00868_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 878 | 608 | 00878_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 888 | 608 | 00888_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 898 | 608 | 00898_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 908 | 608 | 00908_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo - 918 | 608 | 00918_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo - 928 | 608 | 00928_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo - 938 | 608 | 00938_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo - 948 | 608 | 00948_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo - 958 | 608 | 00958_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo - 968 | 608 | 00968_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo - 978 | 608 | 00978_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo - 988 | 608 | 00988_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo - 998 | 608 | 00998_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo - 1008 | 708 | 0000800008_trig_update | | | | ft2 | - 1018 | 708 | 0001800018_trig_update | | | | ft2 | -(102 rows) - --- Test errors thrown on remote side during update --- create table in the remote server with check contraint ---Testcase 738: -CREATE FOREIGN TABLE ft1_constraint ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_svr OPTIONS (table 't1_constraint'); ---Testcase 747: -INSERT INTO ft1_constraint SELECT * FROM ft1 ON CONFLICT DO NOTHING; --- c2 must be greater than or equal to 0, so this case is ignored. ---Testcase 754: -INSERT INTO ft1_constraint(c1, c2) VALUES (2222, -2) ON CONFLICT DO NOTHING; -- ignore, do nothing ---Testcase 755: -SELECT c1, c2 FROM ft1_constraint WHERE c1 = 2222 or c2 = -2; -- empty result - c1 | c2 -----+---- -(0 rows) - ---Testcase 748: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; ---Testcase 749: -ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; ---Testcase 319: -INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: t1_constraint.c1', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ---Testcase 320: -INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported -ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification ---Testcase 321: -INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported -ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification ---Testcase 743: -INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive -ERROR: Failed to execute remote SQL -HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ---Testcase 744: -UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive -ERROR: Failed to execute remote SQL -HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 -CONTEXT: SQL query: UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) ---Testcase 750: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_constraint; ---Testcase 751: -ALTER FOREIGN TABLE ft1_org RENAME TO ft1; --- Test savepoint/rollback behavior ---Testcase 322: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 0 | 100 - 1 | 100 - 4 | 100 - 6 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - ---Testcase 323: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 0 | 100 - 1 | 100 - 4 | 100 - 6 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -begin; ---Testcase 324: -update ft2 set c2 = 42 where c2 = 0; ---Testcase 325: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 4 | 100 - 6 | 100 - 42 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -savepoint s1; ---Testcase 326: -update ft2 set c2 = 44 where c2 = 4; ---Testcase 327: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -release savepoint s1; ---Testcase 328: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -savepoint s2; ---Testcase 329: -update ft2 set c2 = 46 where c2 = 6; ---Testcase 330: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 42 | 100 - 44 | 100 - 46 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -rollback to savepoint s2; ---Testcase 331: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -release savepoint s2; ---Testcase 332: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -savepoint s3; ---Testcase 333: ---skip, does not support CHECK ---update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side -rollback to savepoint s3; ---Testcase 334: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -release savepoint s3; ---Testcase 335: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - --- none of the above is committed yet remotely ---Testcase 336: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - -commit; ---Testcase 337: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - ---Testcase 338: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; - c2 | count ------+------- - 1 | 100 - 6 | 100 - 42 | 100 - 44 | 100 - 100 | 2 - 101 | 2 - 104 | 2 - 106 | 2 - 201 | 1 - 204 | 1 - 303 | 100 - 403 | 2 - 407 | 100 -(13 rows) - ---VACUUM ANALYZE "S 1"."T 1"; --- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs --- FIRST behavior here. --- ORDER BY DESC NULLS LAST options ---Testcase 339: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 795 -(3 rows) - ---Testcase 340: -SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+--------------------+------------------------------+--------------------------+------+------------+----- - 960 | 42 | 00960_trig_update | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0 | 0 | foo - 970 | 42 | 00970_trig_update | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0 | 0 | foo - 980 | 42 | 00980_trig_update | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0 | 0 | foo - 990 | 42 | 00990_trig_update | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0 | 0 | foo - 1000 | 42 | 01000_trig_update | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo - 1218 | 818 | ggg_trig_update | | | (--; | ft2 | - 1001 | 101 | 0000100001 | | | | ft2 | - 1003 | 403 | 0000300003_update3 | | | | ft2 | - 1004 | 104 | 0000400004 | | | | ft2 | - 1006 | 106 | 0000600006 | | | | ft2 | -(10 rows) - --- ORDER BY DESC NULLS FIRST options ---Testcase 341: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 -(3 rows) - ---Testcase 342: -SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-----------------+------------------------------+--------------------------+----+------------+----- - 1020 | 100 | 0002000020 | | | | ft2 | - 1101 | 201 | aaa | | | | ft2 | - 1103 | 503 | ccc_update3 | | | | ft2 | - 1104 | 204 | ddd | | | | ft2 | - 1208 | 818 | fff_trig_update | | | | ft2 | - 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | ft2 | foo - 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | ft2 | foo - 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9 | ft2 | foo - 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9 | ft2 | foo - 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9 | ft2 | foo -(10 rows) - --- ORDER BY ASC NULLS FIRST options ---Testcase 343: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.ft1 - Output: c1, c2, c3, c4, c5, c6, c7, c8 - SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` ASC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 -(3 rows) - ---Testcase 344: -SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-------------------+------------------------------+--------------------------+------+------------+----- - 1020 | 100 | 0002000020 | | | | ft2 | - 1101 | 201 | aaa | | | | ft2 | - 1103 | 503 | ccc_update3 | | | | ft2 | - 1104 | 204 | ddd | | | | ft2 | - 1208 | 818 | fff_trig_update | | | | ft2 | - 1218 | 818 | ggg_trig_update | | | (--; | ft2 | - 10 | 42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo - 20 | 42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0 | 0 | foo - 30 | 42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0 | 0 | foo - 40 | 42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0 | 0 | foo -(10 rows) - --- =================================================================== --- test check constraints --- =================================================================== ---Testcase 752: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; ---Testcase 753: -ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; --- Consistent check constraints provide consistent results -ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0); ---Testcase 587: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; - QUERY PLAN ------------------------------------------------------------------------------- - Foreign Scan - Output: (count(*)) - SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` < 0)) -(3 rows) - ---Testcase 588: -SELECT count(*) FROM ft1 WHERE c2 < 0; - count -------- - 0 -(1 row) - -SET constraint_exclusion = 'on'; ---Testcase 589: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; - QUERY PLAN --------------------------------- - Aggregate - Output: count(*) - -> Result - One-Time Filter: false -(4 rows) - ---Testcase 590: -SELECT count(*) FROM ft1 WHERE c2 < 0; - count -------- - 0 -(1 row) - -RESET constraint_exclusion; --- check constraint is enforced on the remote side, not locally ---Testcase 745: -INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive -ERROR: Failed to execute remote SQL -HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ---Testcase 746: -UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive -ERROR: Failed to execute remote SQL -HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 -CONTEXT: SQL query: UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) -ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive; --- But inconsistent check constraints provide inconsistent results -ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0); ---Testcase 591: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; - QUERY PLAN -------------------------------------------------------------------------------- - Foreign Scan - Output: (count(*)) - SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` >= 0)) -(3 rows) - ---Testcase 592: -SELECT count(*) FROM ft1 WHERE c2 >= 0; - count -------- - 821 -(1 row) - -SET constraint_exclusion = 'on'; ---Testcase 593: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; - QUERY PLAN --------------------------------- - Aggregate - Output: count(*) - -> Result - One-Time Filter: false -(4 rows) - ---Testcase 594: -SELECT count(*) FROM ft1 WHERE c2 >= 0; - count -------- - 0 -(1 row) - -RESET constraint_exclusion; --- local check constraint is not actually enforced ---Testcase 595: -INSERT INTO ft1(c1, c2) VALUES(1111, 2); ---Testcase 596: -UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1; -ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative; --- =================================================================== --- test WITH CHECK OPTION constraints --- =================================================================== ---Testcase 597: -CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql; ---Testcase 598: -CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) - SERVER sqlite_svr; ---Testcase 599: -CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); ---Testcase 600: -CREATE VIEW rw_view AS SELECT * FROM foreign_tbl - WHERE a < b WITH CHECK OPTION; ---Testcase 601: -\d+ rw_view - View "public.rw_view" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | - b | integer | | | | plain | -View definition: - SELECT foreign_tbl.a, - foreign_tbl.b - FROM foreign_tbl - WHERE foreign_tbl.a < foreign_tbl.b; -Options: check_option=cascaded - ---Testcase 345: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 5); - QUERY PLAN ------------------------------- - Insert on public.foreign_tbl - -> Result - Output: 0, 5 -(3 rows) - ---Testcase 602: -INSERT INTO rw_view VALUES (0, 5); -- should fail -ERROR: new row violates check option for view "rw_view" -DETAIL: Failing row contains (10, 5). ---Testcase 603: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 15); - QUERY PLAN ------------------------------- - Insert on public.foreign_tbl - -> Result - Output: 0, 15 -(3 rows) - ---Testcase 604: -INSERT INTO rw_view VALUES (0, 15); -- error ---Testcase 605: -SELECT * FROM foreign_tbl; - a | b -----+---- - 10 | 15 -(1 row) - ---Testcase 606: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 5; - QUERY PLAN ------------------------------------------------------------------------------------ - Update on public.foreign_tbl - -> Foreign Scan on public.foreign_tbl - Output: foreign_tbl.a, (foreign_tbl.b + 5), foreign_tbl.a, foreign_tbl.* - SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) -(4 rows) - ---Testcase 607: -UPDATE rw_view SET b = b + 5; -- should fail -ERROR: new row violates check option for view "rw_view" -DETAIL: Failing row contains (20, 20). ---Testcase 608: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 15; - QUERY PLAN ------------------------------------------------------------------------------------ - Update on public.foreign_tbl - -> Foreign Scan on public.foreign_tbl - Output: foreign_tbl.a, (foreign_tbl.b + 15), foreign_tbl.a, foreign_tbl.* - SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) -(4 rows) - ---Testcase 609: -UPDATE rw_view SET b = b + 15; -- ok ---Testcase 610: -SELECT * FROM foreign_tbl; - a | b -----+---- - 20 | 30 -(1 row) - ---Testcase 611: -DROP FOREIGN TABLE foreign_tbl CASCADE; -NOTICE: drop cascades to view rw_view ---Testcase 612: -DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; -ERROR: relation "foreign_tbl" does not exist --- test WCO for partitions ---Testcase 613: -CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) - SERVER sqlite_svr; ---Testcase 614: -CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); ---Testcase 615: -CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a); -ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); ---Testcase 616: -CREATE VIEW rw_view AS SELECT * FROM parent_tbl - WHERE a < b WITH CHECK OPTION; ---Testcase 617: -\d+ rw_view - View "public.rw_view" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | - b | integer | | | | plain | -View definition: - SELECT parent_tbl.a, - parent_tbl.b - FROM parent_tbl - WHERE parent_tbl.a < parent_tbl.b; -Options: check_option=cascaded - ---Testcase 618: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 5); - QUERY PLAN ------------------------------ - Insert on public.parent_tbl - -> Result - Output: 0, 5 -(3 rows) - ---Testcase 619: -INSERT INTO rw_view VALUES (0, 5); -- should fail -ERROR: Not support partition insert ---Testcase 620: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 15); - QUERY PLAN ------------------------------ - Insert on public.parent_tbl - -> Result - Output: 0, 15 -(3 rows) - ---Testcase 621: -INSERT INTO rw_view VALUES (0, 15); -- ok -ERROR: Not support partition insert ---Testcase 622: -SELECT * FROM foreign_tbl; - a | b -----+---- - 20 | 30 -(1 row) - ---Testcase 623: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 5; - QUERY PLAN ------------------------------------------------------------------------------------ - Update on public.parent_tbl - Foreign Update on public.foreign_tbl - -> Foreign Scan on public.foreign_tbl - Output: foreign_tbl.a, (foreign_tbl.b + 5), foreign_tbl.a, foreign_tbl.* - SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) -(5 rows) - ---Testcase 624: -UPDATE rw_view SET b = b + 5; -- should fail ---Testcase 625: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 15; - QUERY PLAN ------------------------------------------------------------------------------------ - Update on public.parent_tbl - Foreign Update on public.foreign_tbl - -> Foreign Scan on public.foreign_tbl - Output: foreign_tbl.a, (foreign_tbl.b + 15), foreign_tbl.a, foreign_tbl.* - SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) -(5 rows) - ---Testcase 626: -UPDATE rw_view SET b = b + 15; -- ok ---Testcase 627: -SELECT * FROM foreign_tbl; - a | b -----+---- - 40 | 50 -(1 row) - ---Testcase 628: -DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; ---Testcase 629: -DROP FOREIGN TABLE foreign_tbl CASCADE; ---Testcase 630: -DROP TABLE parent_tbl CASCADE; -NOTICE: drop cascades to view rw_view ---Testcase 631: -DROP FUNCTION row_before_insupd_trigfunc; --- =================================================================== --- test serial columns (ie, sequence-based defaults) --- =================================================================== ---Testcase 632: -create foreign table loc1 (f1 serial, f2 text, id integer options (key 'true')) - server sqlite_svr; ---Testcase 633: -create foreign table rem1 (f1 serial, f2 text, id integer options (key 'true')) - server sqlite_svr options(table 'loc1'); ---Testcase 352: -select pg_catalog.setval('rem1_f1_seq', 10, false); - setval --------- - 10 -(1 row) - ---Testcase 353: -insert into loc1(f2) values('hi'); ---Testcase 634: -insert into rem1(f2) values('hi remote'); ---Testcase 354: -insert into loc1(f2) values('bye'); ---Testcase 635: -insert into rem1(f2) values('bye remote'); ---Testcase 355: -select f1, f2 from loc1; - f1 | f2 -----+------------ - 1 | hi - 10 | hi remote - 2 | bye - 11 | bye remote -(4 rows) - ---Testcase 636: -select f1, f2 from rem1; - f1 | f2 -----+------------ - 1 | hi - 10 | hi remote - 2 | bye - 11 | bye remote -(4 rows) - --- =================================================================== --- test generated columns --- =================================================================== ---Testcase 637: -create foreign table grem1 ( - a int options (key 'true'), - b int generated always as (a * 2) stored) - server sqlite_svr; ---Testcase 638: -insert into grem1 (a) values (1), (2); ---Testcase 639: -update grem1 set a = 22 where a = 2; ---Testcase 640: -select * from grem1; - a | b -----+---- - 1 | 2 - 22 | 44 -(2 rows) - --- =================================================================== --- test local triggers --- =================================================================== --- Trigger functions "borrowed" from triggers regress test. ---Testcase 641: -CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$ -BEGIN - RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %', - TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END;$$; ---Testcase 642: -CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 643: -CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 644: -CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger -LANGUAGE plpgsql AS $$ - -declare - oldnew text[]; - relid text; - argstr text; -begin - - relid := TG_relid::regclass; - argstr := ''; - for i in 0 .. TG_nargs - 1 loop - if i > 0 then - argstr := argstr || ', '; - end if; - argstr := argstr || TG_argv[i]; - end loop; - - RAISE NOTICE '%(%) % % % ON %', - tg_name, argstr, TG_when, TG_level, TG_OP, relid; - oldnew := '{}'::text[]; - if TG_OP != 'INSERT' then - oldnew := array_append(oldnew, format('OLD: %s', OLD)); - end if; - - if TG_OP != 'DELETE' then - oldnew := array_append(oldnew, format('NEW: %s', NEW)); - end if; - - RAISE NOTICE '%', array_to_string(oldnew, ','); - - if TG_OP = 'DELETE' then - return OLD; - else - return NEW; - end if; -end; -$$; --- Test basic functionality ---Testcase 645: -CREATE TRIGGER trig_row_before -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 646: -CREATE TRIGGER trig_row_after -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 356: -delete from rem1; -NOTICE: trigger_func() called: action = DELETE, when = BEFORE, level = STATEMENT -NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 -NOTICE: OLD: (1,hi,1) -NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 -NOTICE: OLD: (10,"hi remote",2) -NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 -NOTICE: OLD: (2,bye,3) -NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 -NOTICE: OLD: (11,"bye remote",4) -NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (1,hi,1) -NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (10,"hi remote",2) -NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (2,bye,3) -NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (11,"bye remote",4) -NOTICE: trigger_func() called: action = DELETE, when = AFTER, level = STATEMENT ---Testcase 357: -insert into rem1 values(1,'insert'); -NOTICE: trigger_func() called: action = INSERT, when = BEFORE, level = STATEMENT -NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 -NOTICE: NEW: (1,insert,) -NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (1,insert,) -NOTICE: trigger_func() called: action = INSERT, when = AFTER, level = STATEMENT ---Testcase 358: -update rem1 set f2 = 'update' where f1 = 1; -NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 -NOTICE: OLD: (1,insert,5),NEW: (1,update,5) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,insert,5),NEW: (1,update,5) -NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT ---Testcase 359: -update rem1 set f2 = f2 || f2; -NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 -NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) -NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT --- cleanup ---Testcase 647: -DROP TRIGGER trig_row_before ON rem1; ---Testcase 648: -DROP TRIGGER trig_row_after ON rem1; ---Testcase 649: -DROP TRIGGER trig_stmt_before ON rem1; ---Testcase 650: -DROP TRIGGER trig_stmt_after ON rem1; ---Testcase 360: -DELETE from rem1; --- Test multiple AFTER ROW triggers on a foreign table ---Testcase 651: -CREATE TRIGGER trig_row_after1 -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 652: -CREATE TRIGGER trig_row_after2 -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 653: -insert into rem1 values(1,'insert'); -NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (1,insert,) -NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (1,insert,) ---Testcase 654: -update rem1 set f2 = 'update' where f1 = 1; -NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,insert,6),NEW: (1,update,6) -NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,insert,6),NEW: (1,update,6) ---Testcase 655: -update rem1 set f2 = f2 || f2; -NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) -NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) ---Testcase 656: -delete from rem1; -NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (1,updateupdate,6) -NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (1,updateupdate,6) --- cleanup ---Testcase 657: -DROP TRIGGER trig_row_after1 ON rem1; ---Testcase 658: -DROP TRIGGER trig_row_after2 ON rem1; --- Test WHEN conditions ---Testcase 659: -CREATE TRIGGER trig_row_before_insupd -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW -WHEN (NEW.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 660: -CREATE TRIGGER trig_row_after_insupd -AFTER INSERT OR UPDATE ON rem1 -FOR EACH ROW -WHEN (NEW.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); --- Insert or update not matching: nothing happens ---Testcase 363: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 364: -UPDATE rem1 set f2 = 'test'; --- Insert or update matching: triggers are fired ---Testcase 365: -INSERT INTO rem1 values(2, 'update'); -NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1 -NOTICE: NEW: (2,update,) -NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (2,update,) ---Testcase 366: -UPDATE rem1 set f2 = 'update update' where f1 = '2'; -NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1 -NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) -NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) ---Testcase 661: -CREATE TRIGGER trig_row_before_delete -BEFORE DELETE ON rem1 -FOR EACH ROW -WHEN (OLD.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 662: -CREATE TRIGGER trig_row_after_delete -AFTER DELETE ON rem1 -FOR EACH ROW -WHEN (OLD.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); --- Trigger is fired for f1=2, not for f1=1 ---Testcase 369: -DELETE FROM rem1; -NOTICE: trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1 -NOTICE: OLD: (2,"update update",8) -NOTICE: trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1 -NOTICE: OLD: (2,"update update",8) --- cleanup ---Testcase 663: -DROP TRIGGER trig_row_before_insupd ON rem1; ---Testcase 664: -DROP TRIGGER trig_row_after_insupd ON rem1; ---Testcase 665: -DROP TRIGGER trig_row_before_delete ON rem1; ---Testcase 666: -DROP TRIGGER trig_row_after_delete ON rem1; --- Test various RETURN statements in BEFORE triggers. ---Testcase 667: -CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ - BEGIN - NEW.f2 := NEW.f2 || ' triggered !'; - RETURN NEW; - END -$$ language plpgsql; ---Testcase 668: -CREATE TRIGGER trig_row_before_insupd -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); --- The new values should have 'triggered' appended ---Testcase 370: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 371: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------- - 1 | insert triggered ! -(1 row) - ---Testcase 372: -INSERT INTO rem1 values(2, 'insert'); ---Testcase 373: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------- - 1 | insert triggered ! - 2 | insert triggered ! -(2 rows) - ---Testcase 374: -UPDATE rem1 set f2 = ''; ---Testcase 375: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------- - 1 | triggered ! - 2 | triggered ! -(2 rows) - ---Testcase 376: -UPDATE rem1 set f2 = 'skidoo'; ---Testcase 377: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------- - 1 | skidoo triggered ! - 2 | skidoo triggered ! -(2 rows) - ---Testcase 669: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f1 = 10; -- all columns should be transmitted - QUERY PLAN ----------------------------------------------------------------- - Update on public.rem1 - -> Foreign Scan on public.rem1 - Output: 10, f2, id, id, rem1.* - SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" -(4 rows) - ---Testcase 670: -UPDATE rem1 set f1 = 10; ---Testcase 671: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------------------- - 10 | skidoo triggered ! triggered ! - 10 | skidoo triggered ! triggered ! -(2 rows) - ---Testcase 378: -DELETE FROM rem1; --- Add a second trigger, to check that the changes are propagated correctly --- from trigger to trigger ---Testcase 672: -CREATE TRIGGER trig_row_before_insupd2 -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); ---Testcase 379: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 380: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------------------- - 1 | insert triggered ! triggered ! -(1 row) - ---Testcase 381: -INSERT INTO rem1 values(2, 'insert'); ---Testcase 382: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------------------- - 1 | insert triggered ! triggered ! - 2 | insert triggered ! triggered ! -(2 rows) - ---Testcase 383: -UPDATE rem1 set f2 = ''; ---Testcase 384: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------------- - 1 | triggered ! triggered ! - 2 | triggered ! triggered ! -(2 rows) - ---Testcase 385: -UPDATE rem1 set f2 = 'skidoo'; ---Testcase 386: -SELECT f1, f2 from rem1; - f1 | f2 -----+-------------------------------- - 1 | skidoo triggered ! triggered ! - 2 | skidoo triggered ! triggered ! -(2 rows) - ---Testcase 673: -DROP TRIGGER trig_row_before_insupd ON rem1; ---Testcase 674: -DROP TRIGGER trig_row_before_insupd2 ON rem1; ---Testcase 387: -DELETE from rem1; ---Testcase 388: -INSERT INTO rem1 VALUES (1, 'test'); --- Test with a trigger returning NULL ---Testcase 675: -CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$ - BEGIN - RETURN NULL; - END -$$ language plpgsql; ---Testcase 676: -CREATE TRIGGER trig_null -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_null(); --- Nothing should have changed. ---Testcase 389: -INSERT INTO rem1 VALUES (2, 'test2'); ---Testcase 390: -SELECT f1, f2 from rem1; - f1 | f2 -----+------ - 1 | test -(1 row) - ---Testcase 391: -UPDATE rem1 SET f2 = 'test2'; ---Testcase 392: -SELECT f1, f2 from rem1; - f1 | f2 -----+------ - 1 | test -(1 row) - ---Testcase 393: -DELETE from rem1; ---Testcase 394: -SELECT f1, f2 from rem1; - f1 | f2 -----+------ - 1 | test -(1 row) - ---Testcase 677: -DROP TRIGGER trig_null ON rem1; ---Testcase 395: -DELETE from rem1; --- Test a combination of local and remote triggers ---Testcase 678: -CREATE TRIGGER trig_row_before -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 679: -CREATE TRIGGER trig_row_after -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 680: -CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); ---Testcase 681: -INSERT INTO rem1(f2) VALUES ('test'); -NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 -NOTICE: NEW: (12,"test triggered !",) -NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (12,"test triggered !",) ---Testcase 682: -UPDATE rem1 SET f2 = 'testo'; -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 -NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 -NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) --- Test returning a system attribute ---Testcase 683: -INSERT INTO rem1(f2) VALUES ('test'); -NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 -NOTICE: NEW: (13,"test triggered !",) -NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 -NOTICE: NEW: (13,"test triggered !",) --- cleanup ---Testcase 684: -DROP TRIGGER trig_row_before ON rem1; ---Testcase 685: -DROP TRIGGER trig_row_after ON rem1; ---Testcase 686: -DROP TRIGGER trig_local_before ON rem1; --- Test direct foreign table modification functionality --- Test with statement-level triggers ---Testcase 687: -CREATE TRIGGER trig_stmt_before - BEFORE DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 396: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 397: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 688: -DROP TRIGGER trig_stmt_before ON rem1; ---Testcase 689: -CREATE TRIGGER trig_stmt_after - AFTER DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 398: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 399: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 690: -DROP TRIGGER trig_stmt_after ON rem1; --- Test with row-level ON INSERT triggers ---Testcase 691: -CREATE TRIGGER trig_row_before_insert -BEFORE INSERT ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 400: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 401: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 692: -DROP TRIGGER trig_row_before_insert ON rem1; ---Testcase 693: -CREATE TRIGGER trig_row_after_insert -AFTER INSERT ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 402: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 403: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 694: -DROP TRIGGER trig_row_after_insert ON rem1; --- Test with row-level ON UPDATE triggers ---Testcase 695: -CREATE TRIGGER trig_row_before_update -BEFORE UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 404: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can't be pushed down - QUERY PLAN ----------------------------------------------------------------- - Update on public.rem1 - -> Foreign Scan on public.rem1 - Output: f1, ''::text, id, id, rem1.* - SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" -(4 rows) - ---Testcase 405: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 696: -DROP TRIGGER trig_row_before_update ON rem1; ---Testcase 697: -CREATE TRIGGER trig_row_after_update -AFTER UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 406: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can't be pushed down - QUERY PLAN ----------------------------------------------------------------- - Update on public.rem1 - -> Foreign Scan on public.rem1 - Output: f1, ''::text, id, id, rem1.* - SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" -(4 rows) - ---Testcase 407: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down - QUERY PLAN ------------------------------------------------ - Delete on public.rem1 - -> Foreign Delete on public.rem1 - SQLite query: DELETE FROM main."loc1" -(3 rows) - ---Testcase 698: -DROP TRIGGER trig_row_after_update ON rem1; --- Test with row-level ON DELETE triggers ---Testcase 699: -CREATE TRIGGER trig_row_before_delete -BEFORE DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 408: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 409: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can't be pushed down - QUERY PLAN ----------------------------------------------------------------- - Delete on public.rem1 - -> Foreign Scan on public.rem1 - Output: id, rem1.* - SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" -(4 rows) - ---Testcase 700: -DROP TRIGGER trig_row_before_delete ON rem1; ---Testcase 701: -CREATE TRIGGER trig_row_after_delete -AFTER DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 410: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down - QUERY PLAN --------------------------------------------------------- - Update on public.rem1 - -> Foreign Update on public.rem1 - SQLite query: UPDATE main."loc1" SET `f2` = '' -(3 rows) - ---Testcase 411: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can't be pushed down - QUERY PLAN ----------------------------------------------------------------- - Delete on public.rem1 - -> Foreign Scan on public.rem1 - Output: id, rem1.* - SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" -(4 rows) - ---Testcase 702: -DROP TRIGGER trig_row_after_delete ON rem1; --- =================================================================== --- test inheritance features --- =================================================================== ---Testcase 703: -CREATE TABLE a (aa TEXT); -ALTER TABLE a SET (autovacuum_enabled = 'false'); ---Testcase 704: -CREATE FOREIGN TABLE b (aa TEXT OPTIONS (key 'true'), bb TEXT) INHERITS (a) - SERVER sqlite_svr OPTIONS (table 'loct'); -NOTICE: merging column "aa" with inherited definition ---Testcase 412: -INSERT INTO a(aa) VALUES('aaa'); ---Testcase 413: -INSERT INTO a(aa) VALUES('aaaa'); ---Testcase 414: -INSERT INTO a(aa) VALUES('aaaaa'); ---Testcase 415: -INSERT INTO b(aa) VALUES('bbb'); ---Testcase 416: -INSERT INTO b(aa) VALUES('bbbb'); ---Testcase 417: -INSERT INTO b(aa) VALUES('bbbbb'); ---Testcase 418: -SELECT tableoid::regclass, * FROM a; - tableoid | aa -----------+------- - a | aaa - a | aaaa - a | aaaaa - b | bbb - b | bbbb - b | bbbbb -(6 rows) - ---Testcase 419: -SELECT tableoid::regclass, * FROM b; - tableoid | aa | bb -----------+-------+---- - b | bbb | - b | bbbb | - b | bbbbb | -(3 rows) - ---Testcase 420: -SELECT tableoid::regclass, * FROM ONLY a; - tableoid | aa -----------+------- - a | aaa - a | aaaa - a | aaaaa -(3 rows) - ---Testcase 421: -UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%'; ---Testcase 422: -SELECT tableoid::regclass, * FROM a; - tableoid | aa -----------+-------- - a | aaa - a | zzzzzz - a | zzzzzz - b | bbb - b | bbbb - b | bbbbb -(6 rows) - ---Testcase 423: -SELECT tableoid::regclass, * FROM b; - tableoid | aa | bb -----------+-------+---- - b | bbb | - b | bbbb | - b | bbbbb | -(3 rows) - ---Testcase 424: -SELECT tableoid::regclass, * FROM ONLY a; - tableoid | aa -----------+-------- - a | aaa - a | zzzzzz - a | zzzzzz -(3 rows) - ---Testcase 425: -UPDATE b SET aa = 'new'; ---Testcase 426: -SELECT tableoid::regclass, * FROM a; - tableoid | aa -----------+-------- - a | aaa - a | zzzzzz - a | zzzzzz - b | new - b | new - b | new -(6 rows) - ---Testcase 427: -SELECT tableoid::regclass, * FROM b; - tableoid | aa | bb -----------+-----+---- - b | new | - b | new | - b | new | -(3 rows) - ---Testcase 428: -SELECT tableoid::regclass, * FROM ONLY a; - tableoid | aa -----------+-------- - a | aaa - a | zzzzzz - a | zzzzzz -(3 rows) - ---Testcase 429: -UPDATE a SET aa = 'newtoo'; ---Testcase 430: -SELECT tableoid::regclass, * FROM a; - tableoid | aa -----------+-------- - a | newtoo - a | newtoo - a | newtoo - b | newtoo - b | newtoo - b | newtoo -(6 rows) - ---Testcase 431: -SELECT tableoid::regclass, * FROM b; - tableoid | aa | bb -----------+--------+---- - b | newtoo | - b | newtoo | - b | newtoo | -(3 rows) - ---Testcase 432: -SELECT tableoid::regclass, * FROM ONLY a; - tableoid | aa -----------+-------- - a | newtoo - a | newtoo - a | newtoo -(3 rows) - ---Testcase 433: -DELETE FROM a; ---Testcase 434: -SELECT tableoid::regclass, * FROM a; - tableoid | aa -----------+---- -(0 rows) - ---Testcase 435: -SELECT tableoid::regclass, * FROM b; - tableoid | aa | bb -----------+----+---- -(0 rows) - ---Testcase 436: -SELECT tableoid::regclass, * FROM ONLY a; - tableoid | aa -----------+---- -(0 rows) - ---Testcase 705: -DROP TABLE a CASCADE; -NOTICE: drop cascades to foreign table b --- Check SELECT FOR UPDATE/SHARE with an inherited source table ---Testcase 706: -create table foo (f1 int, f2 int); ---Testcase 707: -create foreign table foo2 (f3 int OPTIONS (key 'true')) inherits (foo) - server sqlite_svr options (table 'loct1'); ---Testcase 708: -create table bar (f1 int, f2 int); ---Testcase 709: -create foreign table bar2 (f3 int OPTIONS (key 'true')) inherits (bar) - server sqlite_svr options (table 'loct2'); -alter table foo set (autovacuum_enabled = 'false'); -alter table bar set (autovacuum_enabled = 'false'); ---Testcase 437: -insert into foo values(1,1); ---Testcase 438: -insert into foo values(3,3); ---Testcase 439: -insert into foo2 values(2,2,2); ---Testcase 440: -insert into foo2 values(4,4,4); ---Testcase 441: -insert into bar values(1,11); ---Testcase 442: -insert into bar values(2,22); ---Testcase 443: -insert into bar values(6,66); ---Testcase 444: -insert into bar2 values(3,33,33); ---Testcase 445: -insert into bar2 values(4,44,44); ---Testcase 446: -insert into bar2 values(7,77,77); ---Testcase 447: -explain (verbose, costs off) -select * from bar where f1 in (select f1 from foo) for update; - QUERY PLAN ----------------------------------------------------------------------------------------------- - LockRows - Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid - -> Hash Join - Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid - Inner Unique: true - Hash Cond: (bar.f1 = foo.f1) - -> Append - -> Seq Scan on public.bar - Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid - -> Foreign Scan on public.bar2 - Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" - -> Hash - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> HashAggregate - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - Group Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> Foreign Scan on public.foo2 - Output: foo2.ctid, foo2.f1, foo2.*, foo2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" -(23 rows) - ---Testcase 448: -select * from bar where f1 in (select f1 from foo) for update; - f1 | f2 -----+---- - 1 | 11 - 2 | 22 - 3 | 33 - 4 | 44 -(4 rows) - ---Testcase 449: -explain (verbose, costs off) -select * from bar where f1 in (select f1 from foo) for share; - QUERY PLAN ----------------------------------------------------------------------------------------------- - LockRows - Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid - -> Hash Join - Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid - Inner Unique: true - Hash Cond: (bar.f1 = foo.f1) - -> Append - -> Seq Scan on public.bar - Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid - -> Foreign Scan on public.bar2 - Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" - -> Hash - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> HashAggregate - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - Group Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> Foreign Scan on public.foo2 - Output: foo2.ctid, foo2.f1, foo2.*, foo2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" -(23 rows) - ---Testcase 450: -select * from bar where f1 in (select f1 from foo) for share; - f1 | f2 -----+---- - 1 | 11 - 2 | 22 - 3 | 33 - 4 | 44 -(4 rows) - --- Check UPDATE with inherited target and an inherited source table ---Testcase 451: -explain (verbose, costs off) -update bar set f2 = f2 + 100 where f1 in (select f1 from foo); - QUERY PLAN -------------------------------------------------------------------------------------------- - Update on public.bar - Update on public.bar - Foreign Update on public.bar2 - -> Hash Join - Output: bar.f1, (bar.f2 + 100), bar.ctid, foo.ctid, foo.*, foo.tableoid - Inner Unique: true - Hash Cond: (bar.f1 = foo.f1) - -> Seq Scan on public.bar - Output: bar.f1, bar.f2, bar.ctid - -> Hash - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> HashAggregate - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - Group Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> Foreign Scan on public.foo2 - Output: foo2.ctid, foo2.f1, foo2.*, foo2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" - -> Hash Join - Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.f3, foo.ctid, foo.*, foo.tableoid - Inner Unique: true - Hash Cond: (bar2.f1 = foo.f1) - -> Foreign Scan on public.bar2 - Output: bar2.f1, bar2.f2, bar2.f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" - -> Hash - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> HashAggregate - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - Group Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.ctid, foo.f1, foo.*, foo.tableoid - -> Foreign Scan on public.foo2 - Output: foo2.ctid, foo2.f1, foo2.*, foo2.tableoid - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" -(38 rows) - ---Testcase 452: -update bar set f2 = f2 + 100 where f1 in (select f1 from foo); ---Testcase 453: -select tableoid::regclass, * from bar order by 1,2; - tableoid | f1 | f2 -----------+----+----- - bar | 1 | 111 - bar | 2 | 122 - bar | 6 | 66 - bar2 | 3 | 133 - bar2 | 4 | 144 - bar2 | 7 | 77 -(6 rows) - --- Check UPDATE with inherited target and an appendrel subquery ---Testcase 454: -explain (verbose, costs off) -update bar set f2 = f2 + 100 -from - ( select f1 from foo union all select f1+3 from foo ) ss -where bar.f1 = ss.f1; - QUERY PLAN ------------------------------------------------------------------------------ - Update on public.bar - Update on public.bar - Foreign Update on public.bar2 - -> Hash Join - Output: bar.f1, (bar.f2 + 100), bar.ctid, (ROW(foo.f1)) - Hash Cond: (foo.f1 = bar.f1) - -> Append - -> Seq Scan on public.foo - Output: ROW(foo.f1), foo.f1 - -> Foreign Scan on public.foo2 - Output: ROW(foo2.f1), foo2.f1 - SQLite query: SELECT `f1` FROM main."loct1" - -> Seq Scan on public.foo foo_1 - Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3) - -> Foreign Scan on public.foo2 foo2_1 - Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3) - SQLite query: SELECT `f1` FROM main."loct1" - -> Hash - Output: bar.f1, bar.f2, bar.ctid - -> Seq Scan on public.bar - Output: bar.f1, bar.f2, bar.ctid - -> Merge Join - Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.f3, (ROW(foo.f1)) - Merge Cond: (bar2.f1 = foo.f1) - -> Sort - Output: bar2.f1, bar2.f2, bar2.f3 - Sort Key: bar2.f1 - -> Foreign Scan on public.bar2 - Output: bar2.f1, bar2.f2, bar2.f3 - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" - -> Sort - Output: (ROW(foo.f1)), foo.f1 - Sort Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: ROW(foo.f1), foo.f1 - -> Foreign Scan on public.foo2 - Output: ROW(foo2.f1), foo2.f1 - SQLite query: SELECT `f1` FROM main."loct1" - -> Seq Scan on public.foo foo_1 - Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3) - -> Foreign Scan on public.foo2 foo2_1 - Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3) - SQLite query: SELECT `f1` FROM main."loct1" -(44 rows) - ---Testcase 455: -update bar set f2 = f2 + 100 -from - ( select f1 from foo union all select f1+3 from foo ) ss -where bar.f1 = ss.f1; ---Testcase 456: -select tableoid::regclass, * from bar order by 1,2; - tableoid | f1 | f2 -----------+----+----- - bar | 1 | 211 - bar | 2 | 222 - bar | 6 | 166 - bar2 | 3 | 233 - bar2 | 4 | 244 - bar2 | 7 | 177 -(6 rows) - --- Test forcing the remote server to produce sorted data for a merge join, --- but the foreign table is an inheritance child. ---truncate table loct1; ---Testcase 710: -delete from foo2; -truncate table only foo; -\set num_rows_foo 2000 ---Testcase 711: -insert into foo2 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2); ---Testcase 712: -insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2); -SET enable_hashjoin to false; -SET enable_nestloop to false; ---alter foreign table foo2 options (use_remote_estimate 'true'); ---create index i_loct1_f1 on loct1(f1); ---Testcase 713: -create index i_foo_f1 on foo(f1); -analyze foo; ---analyze loct1; --- inner join; expressions in the clauses appear in the equivalence class list ---Testcase 714: -explain (verbose, costs off) - select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------- - Limit - Output: foo.f1, foo2.f1, foo.f2 - -> Sort - Output: foo.f1, foo2.f1, foo.f2 - Sort Key: foo.f2 - -> Merge Join - Output: foo.f1, foo2.f1, foo.f2 - Merge Cond: (foo.f1 = foo2.f1) - -> Sort - Output: foo.f1, foo.f2 - Sort Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.f1, foo.f2 - -> Foreign Scan on public.foo2 foo2_1 - Output: foo2_1.f1, foo2_1.f2 - SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST - -> Sort - Output: foo2.f1 - Sort Key: foo2.f1 - -> Foreign Scan on public.foo2 - Output: foo2.f1 - SQLite query: SELECT `f1` FROM main."loct1" -(23 rows) - ---Testcase 715: -select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; - f1 | f1 -----+---- - 20 | 20 - 22 | 22 - 24 | 24 - 26 | 26 - 28 | 28 - 30 | 30 - 32 | 32 - 34 | 34 - 36 | 36 - 38 | 38 -(10 rows) - --- outer join; expressions in the clauses do not appear in equivalence class --- list but no output change as compared to the previous query ---Testcase 716: -explain (verbose, costs off) - select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------- - Limit - Output: foo.f1, foo2.f1, foo.f2 - -> Sort - Output: foo.f1, foo2.f1, foo.f2 - Sort Key: foo.f2 - -> Merge Left Join - Output: foo.f1, foo2.f1, foo.f2 - Merge Cond: (foo.f1 = foo2.f1) - -> Sort - Output: foo.f1, foo.f2 - Sort Key: foo.f1 - -> Append - -> Seq Scan on public.foo - Output: foo.f1, foo.f2 - -> Foreign Scan on public.foo2 foo2_1 - Output: foo2_1.f1, foo2_1.f2 - SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST - -> Sort - Output: foo2.f1 - Sort Key: foo2.f1 - -> Foreign Scan on public.foo2 - Output: foo2.f1 - SQLite query: SELECT `f1` FROM main."loct1" -(23 rows) - ---Testcase 717: -select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; - f1 | f1 -----+---- - 10 | 10 - 11 | - 12 | 12 - 13 | - 14 | 14 - 15 | - 16 | 16 - 17 | - 18 | 18 - 19 | -(10 rows) - -RESET enable_hashjoin; -RESET enable_nestloop; --- Test that WHERE CURRENT OF is not supported -begin; -declare c cursor for select * from bar where f1 = 7; ---Testcase 457: -fetch from c; - f1 | f2 -----+----- - 7 | 177 -(1 row) - ---Testcase 458: -update bar set f2 = null where current of c; -ERROR: WHERE CURRENT OF is not supported for this table type -rollback; ---Testcase 459: -explain (verbose, costs off) -delete from foo where f1 < 5; - QUERY PLAN -------------------------------------------------------------------- - Delete on public.foo - Delete on public.foo - Foreign Delete on public.foo2 - -> Index Scan using i_foo_f1 on public.foo - Output: foo.ctid - Index Cond: (foo.f1 < 5) - -> Foreign Delete on public.foo2 - SQLite query: DELETE FROM main."loct1" WHERE ((`f1` < 5)) -(8 rows) - ---Testcase 460: -delete from foo where f1 < 5; ---Testcase 461: -explain (verbose, costs off) -update bar set f2 = f2 + 100; - QUERY PLAN -------------------------------------------------------------------- - Update on public.bar - Update on public.bar - Foreign Update on public.bar2 - -> Seq Scan on public.bar - Output: bar.f1, (bar.f2 + 100), bar.ctid - -> Foreign Update on public.bar2 - SQLite query: UPDATE main."loct2" SET `f2` = (`f2` + 100) -(7 rows) - ---Testcase 462: -update bar set f2 = f2 + 100; ---Testcase 463: -select * from bar; - f1 | f2 -----+----- - 1 | 311 - 2 | 322 - 6 | 266 - 3 | 333 - 4 | 344 - 7 | 277 -(6 rows) - --- Test that UPDATE/DELETE with inherited target works with row-level triggers ---Testcase 718: -CREATE TRIGGER trig_row_before -BEFORE UPDATE OR DELETE ON bar2 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 719: -CREATE TRIGGER trig_row_after -AFTER UPDATE OR DELETE ON bar2 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 464: -explain (verbose, costs off) -update bar set f2 = f2 + 100; - QUERY PLAN --------------------------------------------------------------------- - Update on public.bar - Update on public.bar - Foreign Update on public.bar2 - -> Seq Scan on public.bar - Output: bar.f1, (bar.f2 + 100), bar.ctid - -> Foreign Scan on public.bar2 - Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.f3, bar2.* - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -(8 rows) - ---Testcase 465: -update bar set f2 = f2 + 100; -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 -NOTICE: OLD: (3,333,33),NEW: (3,433,33) -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 -NOTICE: OLD: (4,344,44),NEW: (4,444,44) -NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 -NOTICE: OLD: (7,277,77),NEW: (7,377,77) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 -NOTICE: OLD: (3,333,33),NEW: (3,433,33) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 -NOTICE: OLD: (4,344,44),NEW: (4,444,44) -NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 -NOTICE: OLD: (7,277,77),NEW: (7,377,77) ---Testcase 466: -explain (verbose, costs off) -delete from bar where f2 < 400; - QUERY PLAN --------------------------------------------------------------------------------------- - Delete on public.bar - Delete on public.bar - Foreign Delete on public.bar2 - -> Seq Scan on public.bar - Output: bar.ctid - Filter: (bar.f2 < 400) - -> Foreign Scan on public.bar2 - Output: bar2.f3, bar2.* - SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" WHERE ((`f2` < 400)) -(9 rows) - ---Testcase 467: -delete from bar where f2 < 400; -NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2 -NOTICE: OLD: (7,377,77) -NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2 -NOTICE: OLD: (7,377,77) --- cleanup ---Testcase 720: -drop table foo cascade; -NOTICE: drop cascades to foreign table foo2 ---Testcase 721: -drop table bar cascade; -NOTICE: drop cascades to foreign table bar2 --- Test pushing down UPDATE/DELETE joins to the remote server ---Testcase 722: -create table parent (a int, b text); ---Testcase 723: -create foreign table remt1 (a int OPTIONS (key 'true'), b text) - server sqlite_svr options (table 'loct3'); ---Testcase 724: -create foreign table remt2 (a int OPTIONS (key 'true'), b text) - server sqlite_svr options (table 'loct4'); -alter foreign table remt1 inherit parent; ---Testcase 468: -insert into remt1 values (1, 'foo'); ---Testcase 469: -insert into remt1 values (2, 'bar'); ---Testcase 470: -insert into remt2 values (1, 'foo'); ---Testcase 471: -insert into remt2 values (2, 'bar'); ---Testcase 472: -explain (verbose, costs off) -update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; - QUERY PLAN ------------------------------------------------------------------------ - Update on public.parent - Update on public.parent - Foreign Update on public.remt1 - -> Hash Join - Output: parent.a, (parent.b || remt2.b), parent.ctid, remt2.* - Hash Cond: (remt2.a = parent.a) - -> Foreign Scan on public.remt2 - Output: remt2.b, remt2.*, remt2.a - SQLite query: SELECT `a`, `b` FROM main."loct4" - -> Hash - Output: parent.a, parent.b, parent.ctid - -> Seq Scan on public.parent - Output: parent.a, parent.b, parent.ctid - -> Hash Join - Output: remt1.a, (remt1.b || remt2.b), remt1.a, remt2.* - Hash Cond: (remt1.a = remt2.a) - -> Foreign Scan on public.remt1 - Output: remt1.a, remt1.b - SQLite query: SELECT `a`, `b` FROM main."loct3" - -> Hash - Output: remt2.b, remt2.*, remt2.a - -> Foreign Scan on public.remt2 - Output: remt2.b, remt2.*, remt2.a - SQLite query: SELECT `a`, `b` FROM main."loct4" -(24 rows) - ---Testcase 473: -update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; ---Testcase 474: -select * from parent inner join remt2 on (parent.a = remt2.a); - a | b | a | b ----+--------+---+----- - 1 | foofoo | 1 | foo - 2 | barbar | 2 | bar -(2 rows) - ---Testcase 475: -explain (verbose, costs off) -delete from parent using remt2 where parent.a = remt2.a; - QUERY PLAN ---------------------------------------------------------------------- - Delete on public.parent - Delete on public.parent - Foreign Delete on public.remt1 - -> Hash Join - Output: parent.ctid, remt2.* - Hash Cond: (remt2.a = parent.a) - -> Foreign Scan on public.remt2 - Output: remt2.*, remt2.a - SQLite query: SELECT `a`, `b` FROM main."loct4" - -> Hash - Output: parent.ctid, parent.a - -> Seq Scan on public.parent - Output: parent.ctid, parent.a - -> Merge Join - Output: remt1.a, remt2.* - Merge Cond: (remt2.a = remt1.a) - -> Sort - Output: remt2.*, remt2.a - Sort Key: remt2.a - -> Foreign Scan on public.remt2 - Output: remt2.*, remt2.a - SQLite query: SELECT `a`, `b` FROM main."loct4" - -> Sort - Output: remt1.a - Sort Key: remt1.a - -> Foreign Scan on public.remt1 - Output: remt1.a - SQLite query: SELECT `a` FROM main."loct3" -(28 rows) - ---Testcase 476: -delete from parent using remt2 where parent.a = remt2.a; --- cleanup ---Testcase 725: -drop foreign table remt1; ---Testcase 726: -drop foreign table remt2; ---Testcase 727: -drop table parent; -/* --- Skip these tests, sqlite fdw does not support partition table, check constraint, copy from --- =================================================================== --- test tuple routing for foreign-table partitions --- =================================================================== - --- Test insert tuple routing -create table itrtest (a int, b text) partition by list (a); -create table loct1 (a int check (a in (1)), b text); -create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); -create table loct2 (a int check (a in (2)), b text); -create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); -alter table itrtest attach partition remp1 for values in (1); -alter table itrtest attach partition remp2 for values in (2); - -insert into itrtest values (1, 'foo'); -insert into itrtest values (1, 'bar') returning *; -insert into itrtest values (2, 'baz'); -insert into itrtest values (2, 'qux') returning *; -insert into itrtest values (1, 'test1'), (2, 'test2') returning *; - -select tableoid::regclass, * FROM itrtest; -select tableoid::regclass, * FROM remp1; -select tableoid::regclass, * FROM remp2; - -delete from itrtest; - -create unique index loct1_idx on loct1 (a); - --- DO NOTHING without an inference specification is supported -insert into itrtest values (1, 'foo') on conflict do nothing returning *; -insert into itrtest values (1, 'foo') on conflict do nothing returning *; - --- But other cases are not supported -insert into itrtest values (1, 'bar') on conflict (a) do nothing; -insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b; - -select tableoid::regclass, * FROM itrtest; - -delete from itrtest; - -drop index loct1_idx; - --- Test that remote triggers work with insert tuple routing -create function br_insert_trigfunc() returns trigger as $$ -begin - new.b := new.b || ' triggered !'; - return new; -end -$$ language plpgsql; -create trigger loct1_br_insert_trigger before insert on loct1 - for each row execute procedure br_insert_trigfunc(); -create trigger loct2_br_insert_trigger before insert on loct2 - for each row execute procedure br_insert_trigfunc(); - --- The new values are concatenated with ' triggered !' -insert into itrtest values (1, 'foo') returning *; -insert into itrtest values (2, 'qux') returning *; -insert into itrtest values (1, 'test1'), (2, 'test2') returning *; -with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result; - -drop trigger loct1_br_insert_trigger on loct1; -drop trigger loct2_br_insert_trigger on loct2; - -drop table itrtest; -drop table loct1; -drop table loct2; - --- Test update tuple routing -create table utrtest (a int, b text) partition by list (a); -create table loct (a int check (a in (1)), b text); -create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct'); -create table locp (a int check (a in (2)), b text); -alter table utrtest attach partition remp for values in (1); -alter table utrtest attach partition locp for values in (2); - -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - -select tableoid::regclass, * FROM utrtest; -select tableoid::regclass, * FROM remp; -select tableoid::regclass, * FROM locp; - --- It's not allowed to move a row from a partition that is foreign to another -update utrtest set a = 2 where b = 'foo' returning *; - --- But the reverse is allowed -update utrtest set a = 1 where b = 'qux' returning *; - -select tableoid::regclass, * FROM utrtest; -select tableoid::regclass, * FROM remp; -select tableoid::regclass, * FROM locp; - --- The executor should not let unexercised FDWs shut down -update utrtest set a = 1 where b = 'foo'; - --- Test that remote triggers work with update tuple routing -create trigger loct_br_insert_trigger before insert on loct - for each row execute procedure br_insert_trigfunc(); - -delete from utrtest; -insert into utrtest values (2, 'qux'); - --- Check case where the foreign partition is a subplan target rel -explain (verbose, costs off) -update utrtest set a = 1 where a = 1 or a = 2 returning *; --- The new values are concatenated with ' triggered !' -update utrtest set a = 1 where a = 1 or a = 2 returning *; - -delete from utrtest; -insert into utrtest values (2, 'qux'); - --- Check case where the foreign partition isn't a subplan target rel -explain (verbose, costs off) -update utrtest set a = 1 where a = 2 returning *; --- The new values are concatenated with ' triggered !' -update utrtest set a = 1 where a = 2 returning *; - -drop trigger loct_br_insert_trigger on loct; - --- We can move rows to a foreign partition that has been updated already, --- but can't move rows to a foreign partition that hasn't been updated yet - -delete from utrtest; -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - --- Test the former case: --- with a direct modification plan -explain (verbose, costs off) -update utrtest set a = 1 returning *; -update utrtest set a = 1 returning *; - -delete from utrtest; -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - --- with a non-direct modification plan -explain (verbose, costs off) -update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; -update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; - --- Change the definition of utrtest so that the foreign partition get updated --- after the local partition -delete from utrtest; -alter table utrtest detach partition remp; -drop foreign table remp; -alter table loct drop constraint loct_a_check; -alter table loct add check (a in (3)); -create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct'); -alter table utrtest attach partition remp for values in (3); -insert into utrtest values (2, 'qux'); -insert into utrtest values (3, 'xyzzy'); - --- Test the latter case: --- with a direct modification plan -explain (verbose, costs off) -update utrtest set a = 3 returning *; -update utrtest set a = 3 returning *; -- ERROR - --- with a non-direct modification plan -explain (verbose, costs off) -update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR - -drop table utrtest; -drop table loct; - --- Test copy tuple routing -create table ctrtest (a int, b text) partition by list (a); -create table loct1 (a int check (a in (1)), b text); -create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); -create table loct2 (a int check (a in (2)), b text); -create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); -alter table ctrtest attach partition remp1 for values in (1); -alter table ctrtest attach partition remp2 for values in (2); - -copy ctrtest from stdin; -1 foo -2 qux -\. - -select tableoid::regclass, * FROM ctrtest; -select tableoid::regclass, * FROM remp1; -select tableoid::regclass, * FROM remp2; - --- Copying into foreign partitions directly should work as well -copy remp1 from stdin; -1 bar -\. - -select tableoid::regclass, * FROM remp1; - -drop table ctrtest; -drop table loct1; -drop table loct2; - --- =================================================================== --- test COPY FROM --- =================================================================== - -create table loc2 (f1 int, f2 text); -alter table loc2 set (autovacuum_enabled = 'false'); -create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2'); - --- Test basic functionality -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -delete from rem2; - --- Test check constraints -alter table loc2 add constraint loc2_f1positive check (f1 >= 0); -alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); - --- check constraint is enforced on the remote side, not locally -copy rem2 from stdin; -1 foo -2 bar -\. -copy rem2 from stdin; -- ERROR --1 xyzzy -\. -select * from rem2; - -alter foreign table rem2 drop constraint rem2_f1positive; -alter table loc2 drop constraint loc2_f1positive; - -delete from rem2; - --- Test local triggers -create trigger trig_stmt_before before insert on rem2 - for each statement execute procedure trigger_func(); -create trigger trig_stmt_after after insert on rem2 - for each statement execute procedure trigger_func(); -create trigger trig_row_before before insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger trig_row_after after insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); - -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before on rem2; -drop trigger trig_row_after on rem2; -drop trigger trig_stmt_before on rem2; -drop trigger trig_stmt_after on rem2; - -delete from rem2; - -create trigger trig_row_before_insert before insert on rem2 - for each row execute procedure trig_row_before_insupdate(); - --- The new values are concatenated with ' triggered !' -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before_insert on rem2; - -delete from rem2; - -create trigger trig_null before insert on rem2 - for each row execute procedure trig_null(); - --- Nothing happens -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_null on rem2; - -delete from rem2; - --- Test remote triggers -create trigger trig_row_before_insert before insert on loc2 - for each row execute procedure trig_row_before_insupdate(); - --- The new values are concatenated with ' triggered !' -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before_insert on loc2; - -delete from rem2; - -create trigger trig_null before insert on loc2 - for each row execute procedure trig_null(); - --- Nothing happens -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_null on loc2; - -delete from rem2; - --- Test a combination of local and remote triggers -create trigger rem2_trig_row_before before insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger rem2_trig_row_after after insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger loc2_trig_row_before_insert before insert on loc2 - for each row execute procedure trig_row_before_insupdate(); - -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger rem2_trig_row_before on rem2; -drop trigger rem2_trig_row_after on rem2; -drop trigger loc2_trig_row_before_insert on loc2; - -delete from rem2; - --- test COPY FROM with foreign table created in the same transaction -create table loc3 (f1 int, f2 text); -begin; -create foreign table rem3 (f1 int, f2 text) - server loopback options(table_name 'loc3'); -copy rem3 from stdin; -1 foo -2 bar -\. -commit; -select * from rem3; -drop foreign table rem3; -drop table loc3; -*/ --- =================================================================== --- test IMPORT FOREIGN SCHEMA --- =================================================================== ---Testcase 728: -CREATE SCHEMA import_dest1; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; ---Testcase 477: -\det+ import_dest1.* - List of foreign tables - Schema | Table | Server | FDW options | Description ---------------+-------------------+------------+-------------------------------+------------- - import_dest1 | T 0 | sqlite_svr | ("table" 'T 0') | - import_dest1 | T 1 | sqlite_svr | ("table" 'T 1') | - import_dest1 | T 2 | sqlite_svr | ("table" 'T 2') | - import_dest1 | T 3 | sqlite_svr | ("table" 'T 3') | - import_dest1 | T 4 | sqlite_svr | ("table" 'T 4') | - import_dest1 | base_tbl | sqlite_svr | ("table" 'base_tbl') | - import_dest1 | batch_table | sqlite_svr | ("table" 'batch_table') | - import_dest1 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | - import_dest1 | ft3 | sqlite_svr | ("table" 'ft3') | - import_dest1 | grem1 | sqlite_svr | ("table" 'grem1') | - import_dest1 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | - import_dest1 | loc1 | sqlite_svr | ("table" 'loc1') | - import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | - import_dest1 | loct | sqlite_svr | ("table" 'loct') | - import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | - import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | - import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | - import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | - import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | - import_dest1 | loct5 | sqlite_svr | ("table" 'loct5') | - import_dest1 | loct6 | sqlite_svr | ("table" 'loct6') | - import_dest1 | loct7 | sqlite_svr | ("table" 'loct7') | - import_dest1 | loct_empty | sqlite_svr | ("table" 'loct_empty') | - import_dest1 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | - import_dest1 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | - import_dest1 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | - import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | - import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | - import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) - ---Testcase 478: -\d import_dest1.* - Foreign table "import_dest1.T 0" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - C 1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 0') - - Foreign table "import_dest1.T 1" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - C 1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 1') - - Foreign table "import_dest1.T 2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 2') - - Foreign table "import_dest1.T 3" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 3') - - Foreign table "import_dest1.T 4" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 4') - - Foreign table "import_dest1.base_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'base_tbl') - - Foreign table "import_dest1.batch_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - x | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'batch_table') - - Foreign table "import_dest1.foreign_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'foreign_tbl') - - Foreign table "import_dest1.ft3" - Column | Type | Collation | Nullable | Default | FDW options ---------+------+-----------+----------+---------+-------------- - f1 | text | | | | (key 'true') - f2 | text | | | | (key 'true') - f3 | text | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'ft3') - - Foreign table "import_dest1.grem1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'grem1') - - Foreign table "import_dest1.grem1_post14" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'grem1_post14') - - Foreign table "import_dest1.loc1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - f1 | bigint | | | | - f2 | text | | | | - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'loc1') - - Foreign table "import_dest1.local_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'local_tbl') - - Foreign table "import_dest1.loct" - Column | Type | Collation | Nullable | Default | FDW options ---------+------+-----------+----------+---------+------------- - aa | text | | | | - bb | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct') - - Foreign table "import_dest1.loct1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct1') - - Foreign table "import_dest1.loct2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct2') - - Foreign table "import_dest1.loct3" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct3') - - Foreign table "import_dest1.loct4" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct4') - - Foreign table "import_dest1.loct4_2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct4_2') - - Foreign table "import_dest1.loct5" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct5') - - Foreign table "import_dest1.loct6" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct6') - - Foreign table "import_dest1.loct7" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct7') - - Foreign table "import_dest1.loct_empty" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | not null | | (key 'true') - c2 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct_empty') - - Foreign table "import_dest1.t1_constraint" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 't1_constraint') - - Foreign table "import_dest1.tru_fk_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - fkey | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_fk_table') - - Foreign table "import_dest1.tru_pk_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'tru_pk_table') - - Foreign table "import_dest1.tru_rtable0" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'tru_rtable0') - - Foreign table "import_dest1.tru_rtable_child" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - id | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_rtable_child') - - Foreign table "import_dest1.tru_rtable_parent" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - id | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_rtable_parent') - --- Options ---Testcase 729: -CREATE SCHEMA import_dest2; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 - OPTIONS (import_default 'true'); ---Testcase 479: -\det+ import_dest2.* - List of foreign tables - Schema | Table | Server | FDW options | Description ---------------+-------------------+------------+-------------------------------+------------- - import_dest2 | T 0 | sqlite_svr | ("table" 'T 0') | - import_dest2 | T 1 | sqlite_svr | ("table" 'T 1') | - import_dest2 | T 2 | sqlite_svr | ("table" 'T 2') | - import_dest2 | T 3 | sqlite_svr | ("table" 'T 3') | - import_dest2 | T 4 | sqlite_svr | ("table" 'T 4') | - import_dest2 | base_tbl | sqlite_svr | ("table" 'base_tbl') | - import_dest2 | batch_table | sqlite_svr | ("table" 'batch_table') | - import_dest2 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | - import_dest2 | ft3 | sqlite_svr | ("table" 'ft3') | - import_dest2 | grem1 | sqlite_svr | ("table" 'grem1') | - import_dest2 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | - import_dest2 | loc1 | sqlite_svr | ("table" 'loc1') | - import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | - import_dest2 | loct | sqlite_svr | ("table" 'loct') | - import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | - import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | - import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | - import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | - import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | - import_dest2 | loct5 | sqlite_svr | ("table" 'loct5') | - import_dest2 | loct6 | sqlite_svr | ("table" 'loct6') | - import_dest2 | loct7 | sqlite_svr | ("table" 'loct7') | - import_dest2 | loct_empty | sqlite_svr | ("table" 'loct_empty') | - import_dest2 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | - import_dest2 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | - import_dest2 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | - import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | - import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | - import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) - ---Testcase 480: -\d import_dest2.* - Foreign table "import_dest2.T 0" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - C 1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 0') - - Foreign table "import_dest2.T 1" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - C 1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 1') - - Foreign table "import_dest2.T 2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 2') - - Foreign table "import_dest2.T 3" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 3') - - Foreign table "import_dest2.T 4" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'T 4') - - Foreign table "import_dest2.base_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'base_tbl') - - Foreign table "import_dest2.batch_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - x | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'batch_table') - - Foreign table "import_dest2.foreign_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'foreign_tbl') - - Foreign table "import_dest2.ft3" - Column | Type | Collation | Nullable | Default | FDW options ---------+------+-----------+----------+---------+-------------- - f1 | text | | | | (key 'true') - f2 | text | | | | (key 'true') - f3 | text | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'ft3') - - Foreign table "import_dest2.grem1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') - b | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'grem1') - - Foreign table "import_dest2.grem1_post14" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - a | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'grem1_post14') - - Foreign table "import_dest2.loc1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - f1 | bigint | | | | - f2 | text | | | | - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'loc1') - - Foreign table "import_dest2.local_tbl" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | | | - c3 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'local_tbl') - - Foreign table "import_dest2.loct" - Column | Type | Collation | Nullable | Default | FDW options ---------+------+-----------+----------+---------+------------- - aa | text | | | | - bb | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct') - - Foreign table "import_dest2.loct1" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct1') - - Foreign table "import_dest2.loct2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct2') - - Foreign table "import_dest2.loct3" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct3') - - Foreign table "import_dest2.loct4" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct4') - - Foreign table "import_dest2.loct4_2" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - f1 | bigint | | | | - f2 | bigint | | | | - f3 | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'loct4_2') - - Foreign table "import_dest2.loct5" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct5') - - Foreign table "import_dest2.loct6" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct6') - - Foreign table "import_dest2.loct7" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - a | bigint | | | | - b | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct7') - - Foreign table "import_dest2.loct_empty" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - c1 | bigint | | not null | | (key 'true') - c2 | text | | | | -Server: sqlite_svr -FDW options: ("table" 'loct_empty') - - Foreign table "import_dest2.t1_constraint" - Column | Type | Collation | Nullable | Default | FDW options ---------+-----------------------------+-----------+----------+---------+-------------- - c1 | bigint | | | | (key 'true') - c2 | bigint | | not null | | - c3 | text | | | | - c4 | timestamp with time zone | | | | - c5 | timestamp without time zone | | | | - c6 | character varying(10) | | | | - c7 | character(10) | | | | - c8 | text | | | | -Server: sqlite_svr -FDW options: ("table" 't1_constraint') - - Foreign table "import_dest2.tru_fk_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - fkey | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_fk_table') - - Foreign table "import_dest2.tru_pk_table" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'tru_pk_table') - - Foreign table "import_dest2.tru_rtable0" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+-------------- - id | bigint | | | | (key 'true') -Server: sqlite_svr -FDW options: ("table" 'tru_rtable0') - - Foreign table "import_dest2.tru_rtable_child" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - id | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_rtable_child') - - Foreign table "import_dest2.tru_rtable_parent" - Column | Type | Collation | Nullable | Default | FDW options ---------+--------+-----------+----------+---------+------------- - id | bigint | | | | -Server: sqlite_svr -FDW options: ("table" 'tru_rtable_parent') - --- Check LIMIT TO and EXCEPT ---Testcase 730: -CREATE SCHEMA import_dest3; -IMPORT FOREIGN SCHEMA public LIMIT TO ("T 1", loct6, nonesuch) - FROM SERVER sqlite_svr INTO import_dest3; ---Testcase 481: -\det+ import_dest3.* - List of foreign tables - Schema | Table | Server | FDW options | Description ---------------+-------+------------+-------------------+------------- - import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | - import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | -(2 rows) - -IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) - FROM SERVER sqlite_svr INTO import_dest3; ---Testcase 482: -\det+ import_dest3.* - List of foreign tables - Schema | Table | Server | FDW options | Description ---------------+-------------------+------------+-------------------------------+------------- - import_dest3 | T 0 | sqlite_svr | ("table" 'T 0') | - import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | - import_dest3 | T 2 | sqlite_svr | ("table" 'T 2') | - import_dest3 | T 3 | sqlite_svr | ("table" 'T 3') | - import_dest3 | T 4 | sqlite_svr | ("table" 'T 4') | - import_dest3 | base_tbl | sqlite_svr | ("table" 'base_tbl') | - import_dest3 | batch_table | sqlite_svr | ("table" 'batch_table') | - import_dest3 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | - import_dest3 | ft3 | sqlite_svr | ("table" 'ft3') | - import_dest3 | grem1 | sqlite_svr | ("table" 'grem1') | - import_dest3 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | - import_dest3 | loc1 | sqlite_svr | ("table" 'loc1') | - import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | - import_dest3 | loct | sqlite_svr | ("table" 'loct') | - import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | - import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | - import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | - import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | - import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | - import_dest3 | loct5 | sqlite_svr | ("table" 'loct5') | - import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | - import_dest3 | loct7 | sqlite_svr | ("table" 'loct7') | - import_dest3 | loct_empty | sqlite_svr | ("table" 'loct_empty') | - import_dest3 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | - import_dest3 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | - import_dest3 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | - import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | - import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | - import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) - --- Assorted error cases -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; -ERROR: relation "T 0" already exists -CONTEXT: importing foreign table "T 0" -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO notthere; -ERROR: schema "notthere" does not exist -IMPORT FOREIGN SCHEMA public FROM SERVER nowhere INTO notthere; -ERROR: server "nowhere" does not exist -/* --- Skip these test, sqlite fdw does not support fetch_size option, partition table --- Check case of a type present only on the remote server. --- We can fake this by dropping the type locally in our transaction. -CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue'); -CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors"); - -CREATE SCHEMA import_dest5; -BEGIN; -DROP TYPE "Colors" CASCADE; -IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5) - FROM SERVER loopback INTO import_dest5; -- ERROR - -ROLLBACK; - -BEGIN; - - -CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' ); - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=101']; - -ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' ); - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=101']; - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=202']; - -CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' ); - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=30000']; - -ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000'); - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=30000']; - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=60000']; - -ROLLBACK; - --- =================================================================== --- test partitionwise joins --- =================================================================== -SET enable_partitionwise_join=on; - -CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a); -CREATE TABLE fprt1_p1 (LIKE fprt1); -CREATE TABLE fprt1_p2 (LIKE fprt1); -ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false'); -ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false'); -INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i; -INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i; -CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250) - SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true'); -CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500) - SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2'); -ANALYZE fprt1; -ANALYZE fprt1_p1; -ANALYZE fprt1_p2; - -CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b); -CREATE TABLE fprt2_p1 (LIKE fprt2); -CREATE TABLE fprt2_p2 (LIKE fprt2); -ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false'); -ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false'); -INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i; -INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i; -CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int) - SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true'); -ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250); -CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500) - SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true'); -ANALYZE fprt2; -ANALYZE fprt2_p1; -ANALYZE fprt2_p2; - --- inner join three tables -EXPLAIN (COSTS OFF) -SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; -SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; - --- left outer join + nullable clause -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; -SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; - --- with whole-row reference; partitionwise join does not apply -EXPLAIN (COSTS OFF) -SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; -SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; - --- join with lateral reference -EXPLAIN (COSTS OFF) -SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; -SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; - --- with PHVs, partitionwise join selected but no join pushdown -EXPLAIN (COSTS OFF) -SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; -SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; - --- test FOR UPDATE; partitionwise join does not apply -EXPLAIN (COSTS OFF) -SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; -SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; - -RESET enable_partitionwise_join; - - --- =================================================================== --- test partitionwise aggregates --- =================================================================== - -CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); - -CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); -CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); -CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); - -INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; -INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; -INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; - --- Create foreign partitions -CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); -CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');; -CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');; - -ANALYZE pagg_tab; -ANALYZE fpagg_tab_p1; -ANALYZE fpagg_tab_p2; -ANALYZE fpagg_tab_p3; - --- When GROUP BY clause matches with PARTITION KEY. --- Plan with partitionwise aggregates is disabled -SET enable_partitionwise_aggregate TO false; -EXPLAIN (COSTS OFF) -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- Plan with partitionwise aggregates is enabled -SET enable_partitionwise_aggregate TO true; -EXPLAIN (COSTS OFF) -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- Check with whole-row reference --- Should have all the columns in the target list for the given relation -EXPLAIN (VERBOSE, COSTS OFF) -SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- When GROUP BY clause does not match with PARTITION KEY. -EXPLAIN (COSTS OFF) -SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; -*/ -/* --- Skip these tests, sqlite fdw does not support nosuper user. --- =================================================================== --- access rights and superuser --- =================================================================== - --- Non-superuser cannot create a FDW without a password in the connstr -CREATE ROLE regress_nosuper NOSUPERUSER; - -GRANT USAGE ON FOREIGN DATA WRAPPER sqlite_fdw TO regress_nosuper; - -SET ROLE regress_nosuper; - -SHOW is_superuser; - --- This will be OK, we can create the FDW -DO $d$ - BEGIN - EXECUTE $$CREATE SERVER sqlite_nopw FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; - --- But creation of user mappings for non-superusers should fail -CREATE USER MAPPING FOR public SERVER sqlite_nopw; -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; - -CREATE FOREIGN TABLE ft1_nopw ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_nopw; - -ALTER FOREIGN TABLE ft1_nopw OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft1_nopw ALTER COLUMN c1 OPTIONS (column_name 'C 1'); - -SELECT * FROM ft1_nopw LIMIT 1; - --- If we add a password to the connstr it'll fail, because we don't allow passwords --- in connstrs only in user mappings. - -DO $d$ - BEGIN - EXECUTE $$ALTER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw')$$; - END; -$d$; - --- If we add a password for our user mapping instead, we should get a different --- error because the password wasn't actually *used* when we run with trust auth. --- --- This won't work with installcheck, but neither will most of the FDW checks. - -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw'); - -SELECT * FROM ft1_nopw LIMIT 1; - --- Unpriv user cannot make the mapping passwordless -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); - - -SELECT * FROM ft1_nopw LIMIT 1; - -RESET ROLE; - --- But the superuser can -ALTER USER MAPPING FOR regress_nosuper SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); - -SET ROLE regress_nosuper; - --- Should finally work now -SELECT * FROM ft1_nopw LIMIT 1; - --- unpriv user also cannot set sslcert / sslkey on the user mapping --- first set password_required so we see the right error messages -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (SET password_required 'true'); -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslcert 'foo.crt'); -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslkey 'foo.key'); - --- We're done with the role named after a specific user and need to check the --- changes to the public mapping. -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; - --- This will fail again as it'll resolve the user mapping for public, which --- lacks password_required=false -SELECT * FROM ft1_nopw LIMIT 1; - -RESET ROLE; - --- The user mapping for public is passwordless and lacks the password_required=false --- mapping option, but will work because the current user is a superuser. -SELECT * FROM ft1_nopw LIMIT 1; - --- cleanup -DROP USER MAPPING FOR public SERVER sqlite_nopw; -DROP OWNED BY regress_nosuper; -DROP ROLE regress_nosuper; - --- Clean-up -RESET enable_partitionwise_aggregate; -*/ --- Two-phase transactions are not supported. -BEGIN; ---Testcase 731: -SELECT count(*) FROM ft1; - count -------- - 822 -(1 row) - --- error here ---Testcase 732: -PREPARE TRANSACTION 'fdw_tpc'; -ERROR: cannot prepare a transaction that modified remote tables -ROLLBACK; -WARNING: there is no transaction in progress --- Clean-up ---Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; ---Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; ---Testcase 735: -DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 125 other objects -DETAIL: drop cascades to foreign table "S 1"."T 0" -drop cascades to foreign table "S 1"."T 1" -drop cascades to foreign table "S 1"."T 2" -drop cascades to foreign table "S 1"."T 3" -drop cascades to foreign table "S 1"."T 4" -drop cascades to foreign table "S 1".base_tbl -drop cascades to foreign table "S 1".loc1 -drop cascades to foreign table "S 1".loct -drop cascades to foreign table "S 1".loct1 -drop cascades to foreign table "S 1".loct2 -drop cascades to foreign table "S 1".loct3 -drop cascades to foreign table "S 1".loct4 -drop cascades to foreign table "S 1".loct4_2 -drop cascades to foreign table "S 1".loct5 -drop cascades to foreign table "S 1".loct6 -drop cascades to foreign table "S 1".loct7 -drop cascades to foreign table "S 1".local_tbl -drop cascades to foreign table "S 1".ft3 -drop cascades to foreign table "S 1".foreign_tbl -drop cascades to foreign table "S 1".grem1 -drop cascades to foreign table "S 1".grem1_post14 -drop cascades to foreign table "S 1".t1_constraint -drop cascades to foreign table "S 1".tru_rtable0 -drop cascades to foreign table "S 1".tru_pk_table -drop cascades to foreign table "S 1".tru_fk_table -drop cascades to foreign table "S 1".tru_rtable_parent -drop cascades to foreign table "S 1".tru_rtable_child -drop cascades to foreign table "S 1".loct_empty -drop cascades to foreign table "S 1".batch_table -drop cascades to foreign table ft1_org -drop cascades to foreign table ft2 -drop cascades to foreign table ft4 -drop cascades to foreign table ft5 -drop cascades to foreign table ft3 -drop cascades to foreign table ft1 -drop cascades to foreign table loc1 -drop cascades to foreign table rem1 -drop cascades to foreign table grem1 -drop cascades to foreign table import_dest1."T 0" -drop cascades to foreign table import_dest1."T 1" -drop cascades to foreign table import_dest1."T 2" -drop cascades to foreign table import_dest1."T 3" -drop cascades to foreign table import_dest1."T 4" -drop cascades to foreign table import_dest1.base_tbl -drop cascades to foreign table import_dest1.loc1 -drop cascades to foreign table import_dest1.loct -drop cascades to foreign table import_dest1.loct1 -drop cascades to foreign table import_dest1.loct2 -drop cascades to foreign table import_dest1.loct3 -drop cascades to foreign table import_dest1.loct4 -drop cascades to foreign table import_dest1.loct4_2 -drop cascades to foreign table import_dest1.loct5 -drop cascades to foreign table import_dest1.loct6 -drop cascades to foreign table import_dest1.loct7 -drop cascades to foreign table import_dest1.local_tbl -drop cascades to foreign table import_dest1.ft3 -drop cascades to foreign table import_dest1.foreign_tbl -drop cascades to foreign table import_dest1.grem1 -drop cascades to foreign table import_dest1.grem1_post14 -drop cascades to foreign table import_dest1.t1_constraint -drop cascades to foreign table import_dest1.tru_rtable0 -drop cascades to foreign table import_dest1.tru_pk_table -drop cascades to foreign table import_dest1.tru_fk_table -drop cascades to foreign table import_dest1.tru_rtable_parent -drop cascades to foreign table import_dest1.tru_rtable_child -drop cascades to foreign table import_dest1.loct_empty -drop cascades to foreign table import_dest1.batch_table -drop cascades to foreign table import_dest2."T 0" -drop cascades to foreign table import_dest2."T 1" -drop cascades to foreign table import_dest2."T 2" -drop cascades to foreign table import_dest2."T 3" -drop cascades to foreign table import_dest2."T 4" -drop cascades to foreign table import_dest2.base_tbl -drop cascades to foreign table import_dest2.loc1 -drop cascades to foreign table import_dest2.loct -drop cascades to foreign table import_dest2.loct1 -drop cascades to foreign table import_dest2.loct2 -drop cascades to foreign table import_dest2.loct3 -drop cascades to foreign table import_dest2.loct4 -drop cascades to foreign table import_dest2.loct4_2 -drop cascades to foreign table import_dest2.loct5 -drop cascades to foreign table import_dest2.loct6 -drop cascades to foreign table import_dest2.loct7 -drop cascades to foreign table import_dest2.local_tbl -drop cascades to foreign table import_dest2.ft3 -drop cascades to foreign table import_dest2.foreign_tbl -drop cascades to foreign table import_dest2.grem1 -drop cascades to foreign table import_dest2.grem1_post14 -drop cascades to foreign table import_dest2.t1_constraint -drop cascades to foreign table import_dest2.tru_rtable0 -drop cascades to foreign table import_dest2.tru_pk_table -drop cascades to foreign table import_dest2.tru_fk_table -drop cascades to foreign table import_dest2.tru_rtable_parent -drop cascades to foreign table import_dest2.tru_rtable_child -drop cascades to foreign table import_dest2.loct_empty -drop cascades to foreign table import_dest2.batch_table -drop cascades to foreign table import_dest3."T 1" -drop cascades to foreign table import_dest3.loct6 -drop cascades to foreign table import_dest3."T 0" -drop cascades to foreign table import_dest3."T 2" -and 25 other objects (see server log for list) ---Testcase 736: -DROP SERVER sqlite_svr2 CASCADE; -NOTICE: drop cascades to foreign table ft6 ---Testcase 737: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/sqlite_fdw.out b/expected/12.16/sqlite_fdw.out deleted file mode 100644 index 525744f0..00000000 --- a/expected/12.16/sqlite_fdw.out +++ /dev/null @@ -1,2109 +0,0 @@ ---SET log_min_messages TO DEBUG1; ---SET client_min_messages TO DEBUG1; ---Testcase 129: -CREATE EXTENSION sqlite_fdw; ---Testcase 130: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); ---Testcase 131: -CREATE FOREIGN TABLE department(department_id int OPTIONS (key 'true'), department_name text) SERVER sqlite_svr; ---Testcase 132: -CREATE FOREIGN TABLE employee(emp_id int OPTIONS (key 'true'), emp_name text, emp_dept_id int) SERVER sqlite_svr; ---Testcase 133: -CREATE FOREIGN TABLE empdata(emp_id int OPTIONS (key 'true'), emp_dat bytea) SERVER sqlite_svr; ---Testcase 134: -CREATE FOREIGN TABLE numbers(a int OPTIONS (key 'true'), b varchar(255)) SERVER sqlite_svr; ---Testcase 135: -CREATE FOREIGN TABLE multiprimary(a int, b int OPTIONS (key 'true'), c int OPTIONS(key 'true')) SERVER sqlite_svr; ---Testcase 136: -CREATE FOREIGN TABLE noprimary(a int, b text) SERVER sqlite_svr; --- updatable option test (github pull 59) -CREATE FOREIGN TABLE RO_RW_test(i int OPTIONS (key 'true'), a text, b float, c int) SERVER sqlite_svr; ---Testcase 1: -SELECT * FROM department LIMIT 10; - department_id | department_name ----------------+----------------- -(0 rows) - ---Testcase 2: -SELECT * FROM employee LIMIT 10; - emp_id | emp_name | emp_dept_id ---------+----------+------------- -(0 rows) - ---Testcase 3: -SELECT * FROM empdata LIMIT 10; - emp_id | emp_dat ---------+--------- -(0 rows) - ---Testcase 4: -INSERT INTO department VALUES(generate_series(1,100), 'dept - ' || generate_series(1,100)); ---Testcase 5: -INSERT INTO employee VALUES(generate_series(1,100), 'emp - ' || generate_series(1,100), generate_series(1,100)); ---Testcase 6: -INSERT INTO empdata VALUES(1, decode ('01234567', 'hex')); ---Testcase 7: -INSERT INTO numbers VALUES(1, 'One'); ---Testcase 8: -INSERT INTO numbers VALUES(2, 'Two'); ---Testcase 9: -INSERT INTO numbers VALUES(3, 'Three'); ---Testcase 10: -INSERT INTO numbers VALUES(4, 'Four'); ---Testcase 11: -INSERT INTO numbers VALUES(5, 'Five'); ---Testcase 12: -INSERT INTO numbers VALUES(6, 'Six'); ---Testcase 13: -INSERT INTO numbers VALUES(7, 'Seven'); ---Testcase 14: -INSERT INTO numbers VALUES(8, 'Eight'); ---Testcase 15: -INSERT INTO numbers VALUES(9, 'Nine'); ---Testcase 16: -SELECT count(*) FROM department; - count -------- - 100 -(1 row) - ---Testcase 17: -SELECT count(*) FROM employee; - count -------- - 100 -(1 row) - ---Testcase 18: -SELECT count(*) FROM empdata; - count -------- - 1 -(1 row) - ---Testcase 19: -EXPLAIN (COSTS FALSE) SELECT * FROM department d, employee e WHERE d.department_id = e.emp_dept_id LIMIT 10; - QUERY PLAN --------------- - Foreign Scan -(1 row) - ---Testcase 20: -EXPLAIN (COSTS FALSE) SELECT * FROM department d, employee e WHERE d.department_id IN (SELECT department_id FROM department) LIMIT 10; - QUERY PLAN -------------------------------------------------------------------------- - Limit - -> Nested Loop - -> Nested Loop Semi Join - Join Filter: (d.department_id = department.department_id) - -> Foreign Scan on department d - -> Materialize - -> Foreign Scan on department - -> Materialize - -> Foreign Scan on employee e -(9 rows) - ---Testcase 21: -SELECT * FROM department d, employee e WHERE d.department_id = e.emp_dept_id LIMIT 10; - department_id | department_name | emp_id | emp_name | emp_dept_id ----------------+-----------------+--------+----------+------------- - 1 | dept - 1 | 1 | emp - 1 | 1 - 2 | dept - 2 | 2 | emp - 2 | 2 - 3 | dept - 3 | 3 | emp - 3 | 3 - 4 | dept - 4 | 4 | emp - 4 | 4 - 5 | dept - 5 | 5 | emp - 5 | 5 - 6 | dept - 6 | 6 | emp - 6 | 6 - 7 | dept - 7 | 7 | emp - 7 | 7 - 8 | dept - 8 | 8 | emp - 8 | 8 - 9 | dept - 9 | 9 | emp - 9 | 9 - 10 | dept - 10 | 10 | emp - 10 | 10 -(10 rows) - ---Testcase 22: -SELECT * FROM department d, employee e WHERE d.department_id IN (SELECT department_id FROM department) ORDER BY d.department_id LIMIT 10; - department_id | department_name | emp_id | emp_name | emp_dept_id ----------------+-----------------+--------+----------+------------- - 1 | dept - 1 | 1 | emp - 1 | 1 - 1 | dept - 1 | 2 | emp - 2 | 2 - 1 | dept - 1 | 3 | emp - 3 | 3 - 1 | dept - 1 | 4 | emp - 4 | 4 - 1 | dept - 1 | 5 | emp - 5 | 5 - 1 | dept - 1 | 6 | emp - 6 | 6 - 1 | dept - 1 | 7 | emp - 7 | 7 - 1 | dept - 1 | 8 | emp - 8 | 8 - 1 | dept - 1 | 9 | emp - 9 | 9 - 1 | dept - 1 | 10 | emp - 10 | 10 -(10 rows) - ---Testcase 23: -SELECT * FROM empdata; - emp_id | emp_dat ---------+------------ - 1 | \x01234567 -(1 row) - ---Testcase 24: -DELETE FROM employee WHERE emp_id = 10; ---Testcase 25: -SELECT COUNT(*) FROM department LIMIT 10; - count -------- - 100 -(1 row) - ---Testcase 26: -SELECT COUNT(*) FROM employee WHERE emp_id = 10; - count -------- - 0 -(1 row) - ---Testcase 27: -UPDATE employee SET emp_name = 'UPDATEd emp' WHERE emp_id = 20; ---Testcase 28: -SELECT emp_id, emp_name FROM employee WHERE emp_name like 'UPDATEd emp'; - emp_id | emp_name ---------+------------- - 20 | UPDATEd emp -(1 row) - ---Testcase 29: -UPDATE empdata SET emp_dat = decode ('0123', 'hex'); ---Testcase 30: -SELECT * FROM empdata; - emp_id | emp_dat ---------+--------- - 1 | \x0123 -(1 row) - ---Testcase 31: -SELECT * FROM employee LIMIT 10; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 1 | emp - 1 | 1 - 2 | emp - 2 | 2 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 - 6 | emp - 6 | 6 - 7 | emp - 7 | 7 - 8 | emp - 8 | 8 - 9 | emp - 9 | 9 - 11 | emp - 11 | 11 -(10 rows) - ---Testcase 32: -SELECT * FROM employee WHERE emp_id IN (1); - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 1 | emp - 1 | 1 -(1 row) - ---Testcase 33: -SELECT * FROM employee WHERE emp_id IN (1,3,4,5); - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 1 | emp - 1 | 1 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 -(4 rows) - ---Testcase 34: -SELECT * FROM employee WHERE emp_id IN (10000,1000); - emp_id | emp_name | emp_dept_id ---------+----------+------------- -(0 rows) - ---Testcase 35: -SELECT * FROM employee WHERE emp_id NOT IN (1) LIMIT 5; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 2 | emp - 2 | 2 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 - 6 | emp - 6 | 6 -(5 rows) - ---Testcase 36: -SELECT * FROM employee WHERE emp_id NOT IN (1,3,4,5) LIMIT 5; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 2 | emp - 2 | 2 - 6 | emp - 6 | 6 - 7 | emp - 7 | 7 - 8 | emp - 8 | 8 - 9 | emp - 9 | 9 -(5 rows) - ---Testcase 37: -SELECT * FROM employee WHERE emp_id NOT IN (10000,1000) LIMIT 5; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 1 | emp - 1 | 1 - 2 | emp - 2 | 2 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 -(5 rows) - ---Testcase 38: -SELECT * FROM employee WHERE emp_id NOT IN (SELECT emp_id FROM employee WHERE emp_id IN (1,10)); - emp_id | emp_name | emp_dept_id ---------+-------------+------------- - 2 | emp - 2 | 2 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 - 6 | emp - 6 | 6 - 7 | emp - 7 | 7 - 8 | emp - 8 | 8 - 9 | emp - 9 | 9 - 11 | emp - 11 | 11 - 12 | emp - 12 | 12 - 13 | emp - 13 | 13 - 14 | emp - 14 | 14 - 15 | emp - 15 | 15 - 16 | emp - 16 | 16 - 17 | emp - 17 | 17 - 18 | emp - 18 | 18 - 19 | emp - 19 | 19 - 20 | UPDATEd emp | 20 - 21 | emp - 21 | 21 - 22 | emp - 22 | 22 - 23 | emp - 23 | 23 - 24 | emp - 24 | 24 - 25 | emp - 25 | 25 - 26 | emp - 26 | 26 - 27 | emp - 27 | 27 - 28 | emp - 28 | 28 - 29 | emp - 29 | 29 - 30 | emp - 30 | 30 - 31 | emp - 31 | 31 - 32 | emp - 32 | 32 - 33 | emp - 33 | 33 - 34 | emp - 34 | 34 - 35 | emp - 35 | 35 - 36 | emp - 36 | 36 - 37 | emp - 37 | 37 - 38 | emp - 38 | 38 - 39 | emp - 39 | 39 - 40 | emp - 40 | 40 - 41 | emp - 41 | 41 - 42 | emp - 42 | 42 - 43 | emp - 43 | 43 - 44 | emp - 44 | 44 - 45 | emp - 45 | 45 - 46 | emp - 46 | 46 - 47 | emp - 47 | 47 - 48 | emp - 48 | 48 - 49 | emp - 49 | 49 - 50 | emp - 50 | 50 - 51 | emp - 51 | 51 - 52 | emp - 52 | 52 - 53 | emp - 53 | 53 - 54 | emp - 54 | 54 - 55 | emp - 55 | 55 - 56 | emp - 56 | 56 - 57 | emp - 57 | 57 - 58 | emp - 58 | 58 - 59 | emp - 59 | 59 - 60 | emp - 60 | 60 - 61 | emp - 61 | 61 - 62 | emp - 62 | 62 - 63 | emp - 63 | 63 - 64 | emp - 64 | 64 - 65 | emp - 65 | 65 - 66 | emp - 66 | 66 - 67 | emp - 67 | 67 - 68 | emp - 68 | 68 - 69 | emp - 69 | 69 - 70 | emp - 70 | 70 - 71 | emp - 71 | 71 - 72 | emp - 72 | 72 - 73 | emp - 73 | 73 - 74 | emp - 74 | 74 - 75 | emp - 75 | 75 - 76 | emp - 76 | 76 - 77 | emp - 77 | 77 - 78 | emp - 78 | 78 - 79 | emp - 79 | 79 - 80 | emp - 80 | 80 - 81 | emp - 81 | 81 - 82 | emp - 82 | 82 - 83 | emp - 83 | 83 - 84 | emp - 84 | 84 - 85 | emp - 85 | 85 - 86 | emp - 86 | 86 - 87 | emp - 87 | 87 - 88 | emp - 88 | 88 - 89 | emp - 89 | 89 - 90 | emp - 90 | 90 - 91 | emp - 91 | 91 - 92 | emp - 92 | 92 - 93 | emp - 93 | 93 - 94 | emp - 94 | 94 - 95 | emp - 95 | 95 - 96 | emp - 96 | 96 - 97 | emp - 97 | 97 - 98 | emp - 98 | 98 - 99 | emp - 99 | 99 - 100 | emp - 100 | 100 -(98 rows) - ---Testcase 39: -SELECT * FROM employee WHERE emp_name NOT IN ('emp - 1', 'emp - 2') LIMIT 5; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 - 6 | emp - 6 | 6 - 7 | emp - 7 | 7 -(5 rows) - ---Testcase 40: -SELECT * FROM employee WHERE emp_name NOT IN ('emp - 10') LIMIT 5; - emp_id | emp_name | emp_dept_id ---------+----------+------------- - 1 | emp - 1 | 1 - 2 | emp - 2 | 2 - 3 | emp - 3 | 3 - 4 | emp - 4 | 4 - 5 | emp - 5 | 5 -(5 rows) - ---Testcase 41: -SELECT * FROM numbers WHERE (CASE WHEN a % 2 = 0 THEN 1 WHEN a % 5 = 0 THEN 1 ELSE 0 END) = 1; - a | b ----+------- - 2 | Two - 4 | Four - 5 | Five - 6 | Six - 8 | Eight -(5 rows) - ---Testcase 42: -SELECT * FROM numbers WHERE (CASE b WHEN 'Two' THEN 1 WHEN 'Six' THEN 1 ELSE 0 END) = 1; - a | b ----+----- - 2 | Two - 6 | Six -(2 rows) - ---Testcase 152: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE (round(abs(a)) = 1); - QUERY PLAN ------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((round(abs(`a`)) = 1)) -(3 rows) - ---Testcase 153: -SELECT * FROM numbers WHERE (round(abs(a)) = 1); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 137: -create or replace function test_param_WHERE() returns void as $$ -DECLARE - n varchar; -BEGIN - FOR x IN 1..9 LOOP ---Testcase 138: - SELECT b INTO n from numbers WHERE a=x; - raise notice 'Found number %', n; - end loop; - return; -END -$$ LANGUAGE plpgsql; ---Testcase 43: -SELECT test_param_WHERE(); -NOTICE: Found number One -NOTICE: Found number Two -NOTICE: Found number Three -NOTICE: Found number Four -NOTICE: Found number Five -NOTICE: Found number Six -NOTICE: Found number Seven -NOTICE: Found number Eight -NOTICE: Found number Nine - test_param_where ------------------- - -(1 row) - ---Testcase 44: -SELECT b from numbers WHERE a=1; - b ------ - One -(1 row) - ---Testcase 45: -EXPLAIN(COSTS OFF) SELECT b from numbers WHERE a=1; - QUERY PLAN -------------------------- - Foreign Scan on numbers -(1 row) - ---Testcase 46: -SELECT a FROM numbers WHERE b = (SELECT NULL::text); - a ---- -(0 rows) - ---Testcase 47: -PREPARE stmt1 (int, int) AS - SELECT * FROM numbers WHERE a=$1 or a=$2; ---Testcase 48: -EXECUTE stmt1(1,2); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 49: -EXECUTE stmt1(2,2); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 50: -EXECUTE stmt1(3,2); - a | b ----+------- - 2 | Two - 3 | Three -(2 rows) - ---Testcase 51: -EXECUTE stmt1(4,2); - a | b ----+------ - 2 | Two - 4 | Four -(2 rows) - --- generic plan ---Testcase 52: -EXECUTE stmt1(5,2); - a | b ----+------ - 2 | Two - 5 | Five -(2 rows) - ---Testcase 53: -EXECUTE stmt1(6,2); - a | b ----+----- - 2 | Two - 6 | Six -(2 rows) - ---Testcase 54: -EXECUTE stmt1(7,2); - a | b ----+------- - 2 | Two - 7 | Seven -(2 rows) - ---Testcase 55: -DELETE FROM employee; ---Testcase 56: -DELETE FROM department; ---Testcase 57: -DELETE FROM empdata; ---Testcase 58: -DELETE FROM numbers; -BEGIN; ---Testcase 59: -INSERT INTO numbers VALUES(1, 'One'); ---Testcase 60: -INSERT INTO numbers VALUES(2, 'Two'); -COMMIT; ---Testcase 61: -SELECT * from numbers; - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - -BEGIN; ---Testcase 62: -INSERT INTO numbers VALUES(3, 'Three'); -ROLLBACK; ---Testcase 63: -SELECT * from numbers; - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - -BEGIN; ---Testcase 64: -INSERT INTO numbers VALUES(4, 'Four'); -SAVEPOINT my_savepoint; ---Testcase 65: -INSERT INTO numbers VALUES(5, 'Five'); -ROLLBACK TO SAVEPOINT my_savepoint; ---Testcase 66: -INSERT INTO numbers VALUES(6, 'Six'); -COMMIT; ---Testcase 67: -SELECT * from numbers; - a | b ----+------ - 1 | One - 2 | Two - 4 | Four - 6 | Six -(4 rows) - --- duplicate key ---Testcase 68: -INSERT INTO numbers VALUES(1, 'One'); -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: numbers.b', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."numbers"(`a`, `b`) VALUES (?, ?) ---Testcase 69: -DELETE from numbers; -BEGIN; ---Testcase 70: -INSERT INTO numbers VALUES(1, 'One'); ---Testcase 71: -INSERT INTO numbers VALUES(2, 'Two'); -COMMIT; --- violate unique constraint ---Testcase 72: -UPDATE numbers SET b='Two' WHERE a = 1; -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: numbers.b', SQLite result code 19 -CONTEXT: SQL query: UPDATE main."numbers" SET `b` = 'Two' WHERE ((`a` = 1)) ---Testcase 73: -SELECT * from numbers; - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - --- push down ---Testcase 74: -explain (verbose, costs off) SELECT * from numbers WHERE a = any(ARRAY[2,3,4,5]::int[]); - QUERY PLAN ---------------------------------------------------------------------------------- - Foreign Scan on public.numbers - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (2, 3, 4, 5)) -(3 rows) - --- (1,2,3) is pushed down ---Testcase 75: -explain (verbose, costs off) SELECT * from numbers WHERE a in (1,2,3) AND (1,2) < (a,5); - QUERY PLAN ------------------------------------------------------------------------------- - Foreign Scan on public.numbers - Output: a, b - Filter: (ROW(1, 2) < ROW(numbers.a, 5)) - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, 3)) -(4 rows) - ---Testcase 76: -explain (verbose, costs off) SELECT * from numbers WHERE a in (a+2*a,5); - QUERY PLAN ------------------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (((`a` = (`a` + (2 * `a`))) OR (`a` = 5))) -(3 rows) - ---Testcase 77: -explain (verbose, costs off) SELECT * from numbers WHERE a = any(ARRAY[1,2,a]::int[]); - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.numbers - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, `a`)) -(3 rows) - ---Testcase 78: -SELECT * from numbers WHERE a = any(ARRAY[2,3,4,5]::int[]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 79: -SELECT * from numbers WHERE a = any(ARRAY[1,2,a]::int[]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - --- ANY with ARRAY expression ---Testcase 154: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY(ARRAY[1, a + 1]); - QUERY PLAN ------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, (`a` + 1))) -(3 rows) - ---Testcase 155: -SELECT * FROM numbers WHERE a = ANY(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 156: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, a + 1]); - QUERY PLAN ----------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <> 1) OR (`a` <> (`a` + 1))) -(3 rows) - ---Testcase 157: -SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 158: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, a + 1]); - QUERY PLAN ----------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` >= 1) OR (`a` >= (`a` + 1))) -(3 rows) - ---Testcase 159: -SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 160: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, a + 1]); - QUERY PLAN ----------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <= 1) OR (`a` <= (`a` + 1))) -(3 rows) - ---Testcase 161: -SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 162: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ANY(ARRAY[1, a + 1]); - QUERY PLAN --------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` > 1) OR (`a` > (`a` + 1))) -(3 rows) - ---Testcase 163: -SELECT * FROM numbers WHERE a > ANY(ARRAY[1, a + 1]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 164: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ANY(ARRAY[1, a + 1]); - QUERY PLAN --------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` < 1) OR (`a` < (`a` + 1))) -(3 rows) - ---Testcase 165: -SELECT * FROM numbers WHERE a < ANY(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - --- ANY with ARRAY const ---Testcase 166: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY(ARRAY[1, 2]); - QUERY PLAN ---------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2)) -(3 rows) - ---Testcase 167: -SELECT * FROM numbers WHERE a = ANY(ARRAY[1, 2]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 168: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, 2]); - QUERY PLAN ----------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <> 1 OR `a` <> 2) -(3 rows) - ---Testcase 169: -SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, 2]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 170: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, 2]); - QUERY PLAN ----------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` >= 1 OR `a` >= 2) -(3 rows) - ---Testcase 171: -SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, 2]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 172: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, 2]); - QUERY PLAN ----------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <= 1 OR `a` <= 2) -(3 rows) - ---Testcase 173: -SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, 2]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 174: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ANY(ARRAY[1, 2]); - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` > 1 OR `a` > 2) -(3 rows) - ---Testcase 175: -SELECT * FROM numbers WHERE a > ANY(ARRAY[1, 2]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 176: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ANY(ARRAY[1, 2]); - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` < 1 OR `a` < 2) -(3 rows) - ---Testcase 177: -SELECT * FROM numbers WHERE a < ANY(ARRAY[1, 2]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 210: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY('{1, 2, 3}'); - QUERY PLAN ------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..3.00 rows=3 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, 3)) -(3 rows) - ---Testcase 211: -SELECT * FROM numbers WHERE a = ANY('{1, 2, 3}'); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 212: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY('{1, 2, 3}'); - QUERY PLAN ----------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <> 1 OR `a` <> 2 OR `a` <> 3) -(3 rows) - ---Testcase 213: -SELECT * FROM numbers WHERE a <> ANY('{1, 2, 3}'); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - --- ALL with ARRAY expression ---Testcase 178: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ALL(ARRAY[1, a * 1]); - QUERY PLAN ---------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` = 1) AND (`a` = (`a` * 1))) -(3 rows) - ---Testcase 179: -SELECT * FROM numbers WHERE a = ALL(ARRAY[1, a * 1]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 180: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, a + 1]); - QUERY PLAN ---------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` NOT IN (1, (`a` + 1))) -(3 rows) - ---Testcase 181: -SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, a + 1]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 182: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, a / 1]); - QUERY PLAN ------------------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` >= 1) AND (`a` >= (`a` / 1))) -(3 rows) - ---Testcase 183: -SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, a / 1]); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 184: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, a + 1]); - QUERY PLAN ------------------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <= 1) AND (`a` <= (`a` + 1))) -(3 rows) - ---Testcase 185: -SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, a + 1]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 186: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ALL(ARRAY[1, a - 1]); - QUERY PLAN ---------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` > 1) AND (`a` > (`a` - 1))) -(3 rows) - ---Testcase 187: -SELECT * FROM numbers WHERE a > ALL(ARRAY[1, a - 1]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 188: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ALL(ARRAY[2, a + 1]); - QUERY PLAN ---------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` < 2) AND (`a` < (`a` + 1))) -(3 rows) - ---Testcase 189: -SELECT * FROM numbers WHERE a < ALL(ARRAY[2, a + 1]); - a | b ----+----- - 1 | One -(1 row) - --- ALL with ARRAY const ---Testcase 190: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ALL(ARRAY[1, 1]); - QUERY PLAN ---------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` = 1 AND `a` = 1) -(3 rows) - ---Testcase 191: -SELECT * FROM numbers WHERE a = ALL(ARRAY[1, 1]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 192: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, 3]); - QUERY PLAN -------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` NOT IN (1, 3)) -(3 rows) - ---Testcase 193: -SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, 3]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 194: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, 2]); - QUERY PLAN ------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` >= 1 AND `a` >= 2) -(3 rows) - ---Testcase 195: -SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, 2]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 196: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, 2]); - QUERY PLAN ------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <= 1 AND `a` <= 2) -(3 rows) - ---Testcase 197: -SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, 2]); - a | b ----+----- - 1 | One -(1 row) - ---Testcase 198: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ALL(ARRAY[0, 1]); - QUERY PLAN ---------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` > 0 AND `a` > 1) -(3 rows) - ---Testcase 199: -SELECT * FROM numbers WHERE a > ALL(ARRAY[0, 1]); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 200: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ALL(ARRAY[2, 3]); - QUERY PLAN ---------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` < 2 AND `a` < 3) -(3 rows) - ---Testcase 201: -SELECT * FROM numbers WHERE a < ALL(ARRAY[2, 3]); - a | b ----+----- - 1 | One -(1 row) - --- ANY/ALL with TEXT ARRAY const ---Testcase 202: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE b = ANY(ARRAY['One', 'Two']); - QUERY PLAN ------------------------------------------------------------------------------------ - Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` IN ('One', 'Two')) -(3 rows) - ---Testcase 203: -SELECT * FROM numbers WHERE b = ANY(ARRAY['One', 'Two']); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 204: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE b <> ALL(ARRAY['One', 'Four']); - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` NOT IN ('One', 'Four')) -(3 rows) - ---Testcase 205: -SELECT * FROM numbers WHERE b <> ALL(ARRAY['One', 'Four']); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 206: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE b > ANY(ARRAY['One', 'Two']); - QUERY PLAN ----------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` > 'One' OR `b` > 'Two') -(3 rows) - ---Testcase 207: -SELECT * FROM numbers WHERE b > ANY(ARRAY['One', 'Two']); - a | b ----+----- - 2 | Two -(1 row) - ---Testcase 208: -EXPLAIN VERBOSE SELECT * FROM numbers WHERE b > ALL(ARRAY['Four', 'Five']); - QUERY PLAN -------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` > 'Four' AND `b` > 'Five') -(3 rows) - ---Testcase 209: -SELECT * FROM numbers WHERE b > ALL(ARRAY['Four', 'Five']); - a | b ----+----- - 1 | One - 2 | Two -(2 rows) - ---Testcase 80: -INSERT INTO multiprimary VALUES(1,2,3); ---Testcase 81: -INSERT INTO multiprimary VALUES(1,2,4); ---Testcase 82: -UPDATE multiprimary SET b = 10 WHERE c = 3; ---Testcase 83: -SELECT * from multiprimary; - a | b | c ----+----+--- - 1 | 10 | 3 - 1 | 2 | 4 -(2 rows) - ---Testcase 84: -UPDATE multiprimary SET a = 10 WHERE a = 1; ---Testcase 85: -SELECT * from multiprimary; - a | b | c -----+----+--- - 10 | 10 | 3 - 10 | 2 | 4 -(2 rows) - ---Testcase 86: -UPDATE multiprimary SET a = 100, b=200, c=300 WHERE a=10 AND b=10; ---Testcase 87: -SELECT * from multiprimary; - a | b | c ------+-----+----- - 100 | 200 | 300 - 10 | 2 | 4 -(2 rows) - ---Testcase 88: -UPDATE multiprimary SET a = 1234; ---Testcase 89: -SELECT * from multiprimary; - a | b | c -------+-----+----- - 1234 | 200 | 300 - 1234 | 2 | 4 -(2 rows) - ---Testcase 90: -UPDATE multiprimary SET a = a+1, b=b+1 WHERE b=200 AND c=300; ---Testcase 91: -SELECT * from multiprimary; - a | b | c -------+-----+----- - 1235 | 201 | 300 - 1234 | 2 | 4 -(2 rows) - ---Testcase 92: -DELETE from multiprimary WHERE a = 1235; ---Testcase 93: -SELECT * from multiprimary; - a | b | c -------+---+--- - 1234 | 2 | 4 -(1 row) - ---Testcase 94: -DELETE from multiprimary WHERE b = 2; ---Testcase 95: -SELECT * from multiprimary; - a | b | c ----+---+--- -(0 rows) - ---Testcase 96: -INSERT INTO multiprimary VALUES(1,2,3); ---Testcase 97: -INSERT INTO multiprimary VALUES(1,2,4); ---Testcase 98: -INSERT INTO multiprimary VALUES(1,10,20); ---Testcase 99: -INSERT INTO multiprimary VALUES(2,20,40); ---Testcase 100: -SELECT count(distinct a) from multiprimary; - count -------- - 2 -(1 row) - ---Testcase 101: -SELECT sum(b),max(b), min(b) from multiprimary; - sum | max | min ------+-----+----- - 34 | 20 | 2 -(1 row) - ---Testcase 102: -SELECT sum(b+5)+2 from multiprimary group by b/2 order by b/2; - ?column? ----------- - 16 - 17 - 27 -(3 rows) - ---Testcase 103: -SELECT sum(a) from multiprimary group by b having sum(a) > 0 order by sum(a); - sum ------ - 1 - 2 - 2 -(3 rows) - ---Testcase 104: -SELECT sum(a) A from multiprimary group by b having avg(abs(a)) > 0 AND sum(a) > 0 order by A; - a ---- - 1 - 2 - 2 -(3 rows) - ---Testcase 105: -SELECT count(nullif(a, 1)) FROM multiprimary; - count -------- - 1 -(1 row) - ---Testcase 106: -SELECT a,a FROM multiprimary group by 1,2; - a | a ----+--- - 1 | 1 - 2 | 2 -(2 rows) - ---Testcase 107: -SELECT * from multiprimary, numbers WHERE multiprimary.a=numbers.a; - a | b | c | a | b ----+----+----+---+----- - 1 | 2 | 3 | 1 | One - 1 | 2 | 4 | 1 | One - 1 | 10 | 20 | 1 | One - 2 | 20 | 40 | 2 | Two -(4 rows) - ---Testcase 108: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT sum(a) FROM multiprimary HAVING sum(a) > 0; - QUERY PLAN ------------------------------------------------------------ - Aggregate - Output: sum(a) - Filter: (sum(multiprimary.a) > 0) - -> Foreign Scan on public.multiprimary - Output: a, b, c - SQLite query: SELECT `a` FROM main."multiprimary" -(6 rows) - ---Testcase 109: -SELECT sum(a) FROM multiprimary HAVING sum(a) > 0; - sum ------ - 5 -(1 row) - ---Testcase 110: -INSERT INTO numbers VALUES(4, 'Four'); --- All where clauses are pushed down ---Testcase 111: -SELECT * FROM numbers WHERE abs(a) = 4 AND upper(b) = 'FOUR' AND lower(b) = 'four'; - a | b ----+------ - 4 | Four -(1 row) - ---Testcase 112: -EXPLAIN (verbose, costs off) SELECT b, length(b) FROM numbers WHERE abs(a) = 4 AND upper(b) = 'FOUR' AND lower(b) = 'four'; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - Foreign Scan on public.numbers - Output: b, length((b)::text) - Filter: ((upper((numbers.b)::text) = 'FOUR'::text) AND (lower((numbers.b)::text) = 'four'::text)) - SQLite query: SELECT `b` FROM main."numbers" WHERE ((abs(`a`) = 4)) -(4 rows) - --- Only "length(b) = 4" are pushed down ---Testcase 113: -SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND length(reverse(b)) = 4; - b | length -------+-------- - Four | 4 -(1 row) - ---Testcase 114: -EXPLAIN (verbose, costs off) SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND length(reverse(b)) = 4; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.numbers - Output: b, length((b)::text) - Filter: ((power('1'::double precision, (numbers.a)::double precision) <> '0'::double precision) AND (length(reverse((numbers.b)::text)) = 4)) - SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((length(`b`) = 4)) -(4 rows) - --- Aggregates in subquery are pushed down. ---Testcase 214: -explain (verbose, costs off) -select count(x.a), sum(x.a) from (select a a, sum(a) b from numbers group by a, abs(a) order by 1, 2) x; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: count(numbers.a), sum(numbers.a) - -> Foreign Scan - Output: numbers.a, (sum(numbers.a)), (abs(numbers.a)) - SQLite query: SELECT `a`, sum(`a`), abs(`a`) FROM main."numbers" GROUP BY 1, 3 ORDER BY `a` ASC NULLS LAST, sum(`a`) ASC NULLS LAST -(5 rows) - ---Testcase 215: -select count(x.a), sum(x.a) from (select a a, sum(a) b from numbers group by a, abs(a) order by 1, 2) x; - count | sum --------+----- - 3 | 7 -(1 row) - ---Testcase 115: -INSERT INTO multiprimary (b,c) VALUES (99, 100); ---Testcase 116: -SELECT c FROM multiprimary WHERE COALESCE(a,b,c) = 99; - c ------ - 100 -(1 row) - ---Testcase 139: -CREATE FOREIGN TABLE multiprimary2(a int, b int, c int OPTIONS(column_name 'b')) SERVER sqlite_svr OPTIONS (table 'multiprimary'); ---Testcase 117: -SELECT * FROM multiprimary2; - a | b | c ----+----+---- - 1 | 2 | 2 - 1 | 2 | 2 - 1 | 10 | 10 - 2 | 20 | 20 - | 99 | 99 -(5 rows) - -ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN a OPTIONS(ADD column_name 'b'); ---Testcase 118: -SELECT * FROM multiprimary2; - a | b | c -----+----+---- - 2 | 2 | 2 - 2 | 2 | 2 - 10 | 10 | 10 - 20 | 20 | 20 - 99 | 99 | 99 -(5 rows) - -ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN b OPTIONS (column_name 'nosuch column'); ---Testcase 119: -SELECT * FROM multiprimary2; -ERROR: SQL error during prepare: no such column: nosuch column SELECT `b`, `nosuch column`, `b` FROM main."multiprimary" ---Testcase 140: -EXPLAIN (VERBOSE) SELECT * FROM multiprimary2; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public.multiprimary2 (cost=10.00..2275.00 rows=2275 width=12) - Output: a, b, c - SQLite query: SELECT `b`, `nosuch column`, `b` FROM main."multiprimary" -(3 rows) - ---Testcase 120: -SELECT a FROM multiprimary2 WHERE b = 1; -ERROR: SQL error during prepare: no such column: nosuch column SELECT `b` FROM main."multiprimary" WHERE ((`nosuch column` = 1)) ---Testcase 141: -CREATE FOREIGN TABLE columntest(a int OPTIONS(column_name 'a a', key 'true'), "b b" int OPTIONS(key 'true'), c int OPTIONS(column_name 'c c')) SERVER sqlite_svr; ---Testcase 121: -INSERT INTO columntest VALUES(1,2,3); ---Testcase 122: -UPDATE columntest SET c=10 WHERE a = 1; ---Testcase 123: -SELECT * FROM columntest; - a | b b | c ----+-----+---- - 1 | 2 | 10 -(1 row) - ---Testcase 124: -UPDATE columntest SET a=100 WHERE c = 10; ---Testcase 125: -SELECT * FROM columntest; - a | b b | c ------+-----+---- - 100 | 2 | 10 -(1 row) - ---Testcase 126: -INSERT INTO noprimary VALUES(1,'2'); ---Testcase 127: -INSERT INTO noprimary SELECT * FROM noprimary; ---Testcase 128: -SELECT * FROM noprimary; - a | b ----+--- - 1 | 2 - 1 | 2 -(2 rows) - ---get version ---Testcase 153: -\df sqlite* - List of functions - Schema | Name | Result data type | Argument data types | Type ---------+----------------------------+------------------+-----------------------------------------+------ - public | sqlite_fdw_disconnect | boolean | text | func - public | sqlite_fdw_disconnect_all | boolean | | func - public | sqlite_fdw_get_connections | SETOF record | OUT server_name text, OUT valid boolean | func - public | sqlite_fdw_handler | fdw_handler | | func - public | sqlite_fdw_validator | void | text[], oid | func - public | sqlite_fdw_version | integer | | func -(6 rows) - ---Testcase 154: -SELECT * FROM public.sqlite_fdw_version(); - sqlite_fdw_version --------------------- - 20400 -(1 row) - ---Testcase 155: -SELECT sqlite_fdw_version(); - sqlite_fdw_version --------------------- - 20400 -(1 row) - --- issue #44 github ---Testcase 156: -CREATE FOREIGN TABLE fts_table (name text, description text) SERVER sqlite_svr; ---Testcase 157: -INSERT INTO fts_table VALUES ('this is name', 'this is description'); ---Testcase 158: -SELECT * FROM fts_table; -- should work - name | description ---------------+--------------------- - this is name | this is description -(1 row) - ---Testcase 159: -ALTER TABLE fts_table ALTER COLUMN name TYPE int; ---Testcase 160: -SELECT * FROM fts_table; -- should fail -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (12 bytes) : 'this is name' -CONTEXT: foreign table "fts_table" foreign column "name" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table --- issue #62 github ---Testcase 236: -INSERT INTO noprimary VALUES (4, 'Test''s'); ---Testcase 237: -INSERT INTO noprimary VALUES (5, 'Test'); ---Testcase 238: -SELECT * FROM noprimary; - a | b ----+-------- - 1 | 2 - 1 | 2 - 4 | Test's - 5 | Test -(4 rows) - ---Testcase 239: -EXPLAIN VERBOSE -SELECT * FROM noprimary where b = 'Test''s'; - QUERY PLAN ---------------------------------------------------------------------------------- - Foreign Scan on public.noprimary (cost=10.00..7.00 rows=7 width=36) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."noprimary" WHERE ((`b` = 'Test''s')) -(3 rows) - ---Testcase 240: -SELECT * FROM noprimary where b = 'Test''s'; - a | b ----+-------- - 4 | Test's -(1 row) - ---Testcase 241: -EXPLAIN VERBOSE -SELECT * FROM noprimary where b in ('Test''s', 'Test'); - QUERY PLAN ------------------------------------------------------------------------------------------- - Foreign Scan on public.noprimary (cost=10.00..14.00 rows=14 width=36) - Output: a, b - SQLite query: SELECT `a`, `b` FROM main."noprimary" WHERE (`b` IN ('Test''s', 'Test')) -(3 rows) - ---Testcase 242: -SELECT * FROM noprimary where b in ('Test''s', 'Test'); - a | b ----+-------- - 4 | Test's - 5 | Test -(2 rows) - --- Executable test case for pushdown CASE expressions (results) ---Testcase 224: -CREATE FOREIGN TABLE case_exp(c1 int OPTIONS (key 'true'), c3 text, c6 varchar(10)) SERVER sqlite_svr; ---Testcase 225: -INSERT INTO case_exp - SELECT id, - to_char(id, 'FM00000'), - id % 10 - FROM generate_series(1, 10) id; ---Testcase 226: -SELECT * FROM case_exp; - c1 | c3 | c6 -----+-------+---- - 1 | 00001 | 1 - 2 | 00002 | 2 - 3 | 00003 | 3 - 4 | 00004 | 4 - 5 | 00005 | 5 - 6 | 00006 | 6 - 7 | 00007 | 7 - 8 | 00008 | 8 - 9 | 00009 | 9 - 10 | 00010 | 0 -(10 rows) - --- CASE arg WHEN ---Testcase 227: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM case_exp WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.case_exp - Output: c1, c3, c6 - SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE ((`c1` > CASE mod(`c1`, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)) -(3 rows) - ---Testcase 228: -SELECT * FROM case_exp WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); - c1 | c3 | c6 -----+-------+---- - 4 | 00004 | 4 - 8 | 00008 | 8 -(2 rows) - --- these are shippable ---Testcase 229: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM case_exp WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.case_exp - Output: c1, c3, c6 - SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE (CASE `c6` WHEN 'foo' THEN 1 ELSE (`c3` < 'bar') END) -(3 rows) - ---Testcase 230: -SELECT * FROM case_exp WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; - c1 | c3 | c6 -----+-------+---- - 1 | 00001 | 1 - 2 | 00002 | 2 - 3 | 00003 | 3 - 4 | 00004 | 4 - 5 | 00005 | 5 - 6 | 00006 | 6 - 7 | 00007 | 7 - 8 | 00008 | 8 - 9 | 00009 | 9 - 10 | 00010 | 0 -(10 rows) - ---Testcase 231: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM case_exp WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.case_exp - Output: c1, c3, c6 - SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE (CASE `c3` WHEN `c6` THEN 1 ELSE (`c3` < 'bar') END) -(3 rows) - ---Testcase 232: -SELECT * FROM case_exp WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; - c1 | c3 | c6 -----+-------+---- - 1 | 00001 | 1 - 2 | 00002 | 2 - 3 | 00003 | 3 - 4 | 00004 | 4 - 5 | 00005 | 5 - 6 | 00006 | 6 - 7 | 00007 | 7 - 8 | 00008 | 8 - 9 | 00009 | 9 - 10 | 00010 | 0 -(10 rows) - --- but this is not because of collation ---Testcase 233: -SELECT * FROM case_exp WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END; - c1 | c3 | c6 -----+-------+---- - 1 | 00001 | 1 - 2 | 00002 | 2 - 3 | 00003 | 3 - 4 | 00004 | 4 - 5 | 00005 | 5 - 6 | 00006 | 6 - 7 | 00007 | 7 - 8 | 00008 | 8 - 9 | 00009 | 9 - 10 | 00010 | 0 -(10 rows) - ---Testcase 234: -DELETE FROM case_exp; --- readonly/readwrite tests --- Full combinations --- force_RO default SERVER default TABLE default --- force_RO default SERVER true TABLE default --- force_RO default SERVER false TABLE default --- force_RO default SERVER default TABLE true --- force_RO default SERVER default TABLE false --- force_RO default SERVER true TABLE true --- force_RO default SERVER false TABLE true --- force_RO default SERVER false TABLE false --- force_RO default SERVER true TABLE false --- force_RO false SERVER default TABLE default --- force_RO false SERVER true TABLE default --- force_RO false SERVER false TABLE default --- force_RO false SERVER default TABLE true --- force_RO false SERVER default TABLE false --- force_RO false SERVER true TABLE true --- force_RO false SERVER false TABLE true --- force_RO false SERVER false TABLE false --- force_RO false SERVER true TABLE false --- force_RO true SERVER default TABLE default --- force_RO true SERVER true TABLE default --- force_RO true SERVER false TABLE default --- force_RO true SERVER default TABLE true --- force_RO true SERVER default TABLE false --- force_RO true SERVER true TABLE true --- force_RO true SERVER false TABLE true --- force_RO true SERVER false TABLE false --- force_RO true SERVER true TABLE false --- force_RO default SERVER default TABLE default ---Testcase 235: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- OK ---Testcase 236: -UPDATE RO_RW_test SET a='C' WHERE i=2; -- OK ---Testcase 237: -DELETE FROM RO_RW_test WHERE i=2; -- OK --- force_RO default SERVER true TABLE default ---Testcase 238: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); ---Testcase 239: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- OK ---Testcase 240: -UPDATE RO_RW_test SET a='E' WHERE i=3; -- OK ---Testcase 241: -DELETE FROM RO_RW_test WHERE i=3; -- OK ---Testcase 242: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- OK --- force_RO default SERVER false TABLE default ---Testcase 243: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 244: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 245: -UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 246: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO default SERVER default TABLE true ---Testcase 247: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 248: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); ---Testcase 249: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- OK ---Testcase 250: -UPDATE RO_RW_test SET a='J' WHERE i=6; -- OK ---Testcase 251: -DELETE FROM RO_RW_test WHERE i=6; -- OK --- force_RO default SERVER default TABLE false ---Testcase 252: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 253: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 254: -UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 255: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO default SERVER true TABLE true ---Testcase 256: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); ---Testcase 257: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); ---Testcase 258: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- OK ---Testcase 258: -UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK ---Testcase 260: -DELETE FROM RO_RW_test WHERE i=8; -- OK ---Testcase 261: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- OK --- force_RO default SERVER false TABLE true ---Testcase 262: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 263: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- OK ---Testcase 264: -UPDATE RO_RW_test SET a='Q' WHERE i=9; -- OK ---Testcase 265: -DELETE FROM RO_RW_test WHERE i=9; -- OK --- force_RO default SERVER false TABLE false ---Testcase 266: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 267: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 268: -UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 269: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO default SERVER true TABLE false ---Testcase 270: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); ---Testcase 271: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 272: -UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 273: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes ---Testcase 274: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 275: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); ---Testcase 276: -SELECT * FROM RO_RW_test ORDER BY i; - i | a | b | c -----+---+-------+--- - 1 | A | 1.001 | 0 - 4 | F | 0.005 | 5 - 10 | P | 4.15 | 1 -(3 rows) - ---Bind error message test for some unsupported data type ---Testcase 277: -ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE tsquery; ---Testcase 278: -INSERT INTO numbers VALUES(8,'fat & (rat | cat)'); -ERROR: cannot convert constant value to Sqlite value -HINT: Constant value data type: "tsquery" in column "b" ---Testcase 279: -ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE varchar(255); ---Testcase 277: -DELETE FROM RO_RW_test; ---Testcase 278: -ALTER SERVER sqlite_svr OPTIONS (ADD force_readonly 'false'); --- force_RO false SERVER default TABLE default ---Testcase 279: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- OK ---Testcase 280: -UPDATE RO_RW_test SET a='C' WHERE i=2; -- OK ---Testcase 281: -DELETE FROM RO_RW_test WHERE i=2; -- OK --- force_RO false SERVER true TABLE default ---Testcase 282: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); ---Testcase 283: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- OK ---Testcase 284: -UPDATE RO_RW_test SET a='E' WHERE i=3; -- OK ---Testcase 285: -DELETE FROM RO_RW_test WHERE i=3; -- OK ---Testcase 286: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- OK --- force_RO false SERVER false TABLE default ---Testcase 287: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 288: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 289: -UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 290: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO false SERVER default TABLE true ---Testcase 291: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 292: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); ---Testcase 293: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- OK ---Testcase 294: -UPDATE RO_RW_test SET a='J' WHERE i=6; -- OK ---Testcase 295: -DELETE FROM RO_RW_test WHERE i=6; -- OK --- force_RO false SERVER default TABLE false ---Testcase 296: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 297: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 298: -UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 299: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO false SERVER true TABLE true ---Testcase 300: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); ---Testcase 301: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); ---Testcase 302: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- OK ---Testcase 303: -UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK ---Testcase 304: -DELETE FROM RO_RW_test WHERE i=8; -- OK ---Testcase 305: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- OK --- force_RO false SERVER false TABLE true ---Testcase 306: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 307: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- OK ---Testcase 308: -UPDATE RO_RW_test SET a='Q' WHERE i=9; -- OK ---Testcase 309: -DELETE FROM RO_RW_test WHERE i=9; -- OK --- force_RO false SERVER false TABLE false ---Testcase 310: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 311: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 312: -UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 313: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO false SERVER true TABLE false ---Testcase 314: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); ---Testcase 315: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 316: -UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 317: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes ---Testcase 318: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 319: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); ---Testcase 320: -SELECT * FROM RO_RW_test ORDER BY i; - i | a | b | c -----+---+-------+--- - 4 | F | 0.005 | 5 - 10 | P | 4.15 | 1 -(2 rows) - ---Testcase 321: -DELETE FROM RO_RW_test; ---Testcase 322: -ALTER SERVER sqlite_svr OPTIONS (SET force_readonly 'true'); --- force_RO true SERVER default TABLE default ---Testcase 323: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 324: -UPDATE RO_RW_test SET a='C' WHERE i=2; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 325: -DELETE FROM RO_RW_test WHERE i=2; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER true TABLE default ---Testcase 326: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); ---Testcase 327: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 328: -UPDATE RO_RW_test SET a='E' WHERE i=3; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 329: -DELETE FROM RO_RW_test WHERE i=3; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes ---Testcase 330: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts --- force_RO true SERVER false TABLE default ---Testcase 331: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 332: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 333: -UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 334: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER default TABLE true ---Testcase 335: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 336: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); ---Testcase 337: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 338: -UPDATE RO_RW_test SET a='J' WHERE i=6; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 339: -DELETE FROM RO_RW_test WHERE i=6; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER default TABLE false ---Testcase 340: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 341: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 342: -UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 343: -DELETE FROM RO_RW_test WHERE i=4; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER true TABLE true ---Testcase 344: -ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); -- ERR ---Testcase 345: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); -- ERR ---Testcase 346: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 347: -UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 348: -DELETE FROM RO_RW_test WHERE i=8; -- OK -ERROR: foreign table "ro_rw_test" does not allow deletes ---Testcase 349: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts --- force_RO true SERVER false TABLE true ---Testcase 350: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); ---Testcase 351: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 352: -UPDATE RO_RW_test SET a='Q' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 353: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER false TABLE false ---Testcase 354: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); ---Testcase 355: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 356: -UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 357: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes --- force_RO true SERVER true TABLE false ---Testcase 358: -ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); ---Testcase 359: -INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR -ERROR: foreign table "ro_rw_test" does not allow inserts ---Testcase 360: -UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow updates ---Testcase 361: -DELETE FROM RO_RW_test WHERE i=9; -- ERR -ERROR: foreign table "ro_rw_test" does not allow deletes ---Testcase 362: -ALTER SERVER sqlite_svr OPTIONS (DROP updatable); ---Testcase 363: -ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); ---Testcase 364: -ALTER SERVER sqlite_svr OPTIONS (DROP force_readonly); ---Testcase 365: -SELECT * FROM RO_RW_test ORDER BY i; - i | a | b | c ----+---+---+--- -(0 rows) - ---Testcase 366: -DROP FOREIGN TABLE RO_RW_test; --- End of RO/RW test ---Bind error message test for some unsupported data type ---Testcase 366: -ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE tsquery; ---Testcase 367: -INSERT INTO numbers VALUES(8,'fat & (rat | cat)'); -ERROR: cannot convert constant value to Sqlite value -HINT: Constant value data type: "tsquery" in column "b" ---Testcase 368: -ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE varchar(255); ---Testcase 142: -DROP FUNCTION test_param_WHERE(); ---Testcase 143: -DROP FOREIGN TABLE numbers; ---Testcase 144: -DROP FOREIGN TABLE department; ---Testcase 145: -DROP FOREIGN TABLE employee; ---Testcase 146: -DROP FOREIGN TABLE empdata; ---Testcase 147: -DROP FOREIGN TABLE multiprimary; ---Testcase 148: -DROP FOREIGN TABLE multiprimary2; ---Testcase 149: -DROP FOREIGN TABLE columntest; ---Testcase 150: -DROP FOREIGN TABLE noprimary; ---Testcase 161: -DROP FOREIGN TABLE fts_table; ---Testcase 235: -DROP FOREIGN TABLE case_exp; ---Testcase 151: -DROP SERVER sqlite_svr; ---Testcase 152: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/13.12/aggregate.out b/expected/13.15/aggregate.out similarity index 100% rename from expected/13.12/aggregate.out rename to expected/13.15/aggregate.out diff --git a/expected/13.12/extra/aggregates.out b/expected/13.15/extra/aggregates.out similarity index 98% rename from expected/13.12/extra/aggregates.out rename to expected/13.15/extra/aggregates.out index 3cf00087..9bdaa016 100644 --- a/expected/13.12/extra/aggregates.out +++ b/expected/13.15/extra/aggregates.out @@ -61,14 +61,44 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 588: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 589: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 590: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 591: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 592: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 593: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 594: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 595: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 596: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 597: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; --Testcase 275: CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 598: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 599: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 600: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 601: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 602: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: SET extra_float_digits = 0; @@ -129,7 +159,7 @@ HINT: No function matches the given name and argument types. You might need to -- In 7.1, avg(float4) is computed using float8 arithmetic. --Testcase 3: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 678: +--Testcase 603: SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; avg_107_943 ------------- @@ -138,7 +168,7 @@ SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; --Testcase 4: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 679: +--Testcase 604: SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; avg_3_4 --------- @@ -161,7 +191,7 @@ SELECT sum(a) AS sum_198 FROM aggtest; --Testcase 7: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 680: +--Testcase 605: SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; avg_431_773 ------------- @@ -170,7 +200,7 @@ SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; --Testcase 8: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 681: +--Testcase 606: SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; avg_6_8 --------- @@ -207,7 +237,7 @@ SELECT max(student.gpa) AS max_3_7 FROM student; --Testcase 13: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 682: +--Testcase 607: SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; stddev_pop ---------------- @@ -216,7 +246,7 @@ SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; --Testcase 14: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 683: +--Testcase 608: SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; stddev_samp ---------------- @@ -225,7 +255,7 @@ SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; --Testcase 15: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 684: +--Testcase 609: SELECT var_pop(b)::numeric(20,10) FROM aggtest; var_pop ------------------ @@ -234,7 +264,7 @@ SELECT var_pop(b)::numeric(20,10) FROM aggtest; --Testcase 16: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 685: +--Testcase 610: SELECT var_samp(b)::numeric(20,10) FROM aggtest; var_samp ------------------ @@ -544,10 +574,10 @@ DELETE FROM agg_t3; --Testcase 332: INSERT INTO agg_t3 VALUES ('1'::float8), ('infinity'::float8); --Testcase 333: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN +SELECT avg(a), var_pop(a) FROM agg_t3; + avg | var_pop +----------+--------- + Infinity | NaN (1 row) --Testcase 334: @@ -555,10 +585,10 @@ DELETE FROM agg_t3; --Testcase 335: INSERT INTO agg_t3 VALUES ('infinity'::float8), ('1'::float8); --Testcase 336: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN +SELECT avg(a), var_pop(a) FROM agg_t3; + avg | var_pop +----------+--------- + Infinity | NaN (1 row) --Testcase 337: @@ -566,10 +596,10 @@ DELETE FROM agg_t3; --Testcase 338: INSERT INTO agg_t3 VALUES ('infinity'::float8), ('infinity'::float8); --Testcase 339: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN +SELECT avg(a), var_pop(a) FROM agg_t3; + avg | var_pop +----------+--------- + Infinity | NaN (1 row) --Testcase 340: @@ -706,7 +736,7 @@ SELECT regr_sxx(b, a) FROM aggtest; --Testcase 23: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 686: +--Testcase 611: SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; regr_syy ------------------ @@ -715,7 +745,7 @@ SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; --Testcase 24: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 687: +--Testcase 612: SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; regr_sxy ----------------- @@ -724,7 +754,7 @@ SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; --Testcase 25: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 688: +--Testcase 613: SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; regr_avgx | regr_avgy -----------+---------------- @@ -733,7 +763,7 @@ SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; --Testcase 26: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 689: +--Testcase 614: SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; regr_r2 -------------- @@ -742,7 +772,7 @@ SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; --Testcase 27: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 690: +--Testcase 615: SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; regr_slope | regr_intercept --------------+---------------- @@ -751,7 +781,7 @@ SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FR --Testcase 28: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 691: +--Testcase 616: SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; covar_pop | covar_samp ----------------+---------------- @@ -760,7 +790,7 @@ SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM ag --Testcase 29: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 692: +--Testcase 617: SELECT corr(b, a)::numeric(20,10) FROM aggtest; corr -------------- @@ -2773,7 +2803,7 @@ LINE 1: select f1, percentile_cont(f1,f1) rollback; --Testcase 179: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 693: +--Testcase 618: select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; percentile_cont ----------------- @@ -2782,7 +2812,7 @@ select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from agg --Testcase 180: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 694: +--Testcase 619: select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; percentile_cont | sum -----------------+--------- @@ -2791,7 +2821,7 @@ select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b): --Testcase 181: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 695: +--Testcase 620: select percentile_cont(0.5) within group (order by thousand) from tenk1; percentile_cont ----------------- @@ -2828,7 +2858,7 @@ select cume_dist(3) within group (order by f1) from INT4_TBL; insert into INT4_TBL values (5); --Testcase 458: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 696: +--Testcase 621: select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; percent_rank -------------- @@ -3975,6 +4005,12 @@ set work_mem to default; ----+----+---- (0 rows) +--Testcase 622: +DELETE FROM INT4_TBL; +--Testcase 623: +DELETE FROM INT8_TBL; +--Testcase 624: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/12.16/extra/bitstring.out b/expected/13.15/extra/bitstring.out similarity index 100% rename from expected/12.16/extra/bitstring.out rename to expected/13.15/extra/bitstring.out diff --git a/expected/14.9/extra/bool.out b/expected/13.15/extra/bool.out similarity index 99% rename from expected/14.9/extra/bool.out rename to expected/13.15/extra/bool.out index ec908ab6..ccb740e5 100644 --- a/expected/14.9/extra/bool.out +++ b/expected/13.15/extra/bool.out @@ -1263,6 +1263,8 @@ SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; | (2 rows) +--Testcase 79: +DELETE FROM "type_BOOLEAN"; --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; NOTICE: drop cascades to 6 other objects diff --git a/expected/12.16/extra/encodings.out b/expected/13.15/extra/encodings.out similarity index 100% rename from expected/12.16/extra/encodings.out rename to expected/13.15/extra/encodings.out diff --git a/expected/12.16/extra/float4.out b/expected/13.15/extra/float4.out similarity index 100% rename from expected/12.16/extra/float4.out rename to expected/13.15/extra/float4.out diff --git a/expected/13.12/extra/float8.out b/expected/13.15/extra/float8.out similarity index 99% rename from expected/13.12/extra/float8.out rename to expected/13.15/extra/float8.out index e9e029a1..0ea3f770 100644 --- a/expected/13.12/extra/float8.out +++ b/expected/13.15/extra/float8.out @@ -1617,6 +1617,8 @@ drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 drop cascades to cast from xfloat8 to bigint drop cascades to cast from bigint to xfloat8 +--Testcase 272: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/12.16/extra/insert.out b/expected/13.15/extra/insert.out similarity index 100% rename from expected/12.16/extra/insert.out rename to expected/13.15/extra/insert.out diff --git a/expected/13.12/extra/int4.out b/expected/13.15/extra/int4.out similarity index 99% rename from expected/13.12/extra/int4.out rename to expected/13.15/extra/int4.out index 6c9329ab..d6db89b4 100644 --- a/expected/13.12/extra/int4.out +++ b/expected/13.15/extra/int4.out @@ -633,6 +633,8 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow ERROR: integer out of range +--Testcase 137: +DELETE FROM INT4_TBL; -- Clean up DO $d$ declare diff --git a/expected/13.12/extra/int8.out b/expected/13.15/extra/int8.out similarity index 99% rename from expected/13.12/extra/int8.out rename to expected/13.15/extra/int8.out index a3fd3d02..c406e610 100644 --- a/expected/13.12/extra/int8.out +++ b/expected/13.15/extra/int8.out @@ -1306,6 +1306,8 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow ERROR: bigint out of range +--Testcase 251: +DELETE FROM INT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/13.12/extra/join.out b/expected/13.15/extra/join.out similarity index 99% rename from expected/13.12/extra/join.out rename to expected/13.15/extra/join.out index db3f4bea..43b9818b 100644 --- a/expected/13.12/extra/join.out +++ b/expected/13.15/extra/join.out @@ -58,13 +58,43 @@ CREATE FOREIGN TABLE tenk2 ( ) SERVER sqlite_svr; --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 489: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 490: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 491: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 492: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 493: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 494: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 495: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 496: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 497: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 498: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 499: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 500: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 501: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 502: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 503: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 1: @@ -2642,6 +2672,7 @@ ERROR: column t12.x does not exist LINE 1: select t12.x from t12 join t32 on (t12.a = t32.x); ^ HINT: Perhaps you meant to reference the column "t32.x". +--Testcase 504: drop table t2a; -- -- regression test for 8.1 merge right join bug @@ -2869,6 +2900,7 @@ where f2 = 53; 53 | | | (1 row) +--Testcase 505: drop view zv1; -- -- regression test for improper extraction of OR indexqual conditions @@ -6913,6 +6945,12 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 506: +DELETE FROM INT4_TBL; +--Testcase 507: +DELETE FROM INT8_TBL; +--Testcase 508: +DELETE FROM FLOAT8_TBL; DO $d$ declare l_rec record; diff --git a/expected/15.4/extra/limit.out b/expected/13.15/extra/limit.out similarity index 98% rename from expected/15.4/extra/limit.out rename to expected/13.15/extra/limit.out index 8998e395..7890cb30 100644 --- a/expected/15.4/extra/limit.out +++ b/expected/13.15/extra/limit.out @@ -28,6 +28,16 @@ CREATE FOREIGN TABLE onek( ) SERVER sqlite_svr; --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 104: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 105: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 107: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 108: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -960,12 +970,6 @@ SELECT thousand 0 (2 rows) --- SKIP LOCKED and WITH TIES are incompatible ---Testcase 104: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; -ERROR: SKIP LOCKED and WITH TIES options cannot be used together -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -1044,6 +1048,8 @@ View definition: LIMIT ALL; -- leave these views +--Testcase 109: +DELETE FROM int8_tbl; -- Clean up DO $d$ declare diff --git a/expected/13.12/extra/numeric.out b/expected/13.15/extra/numeric.out similarity index 100% rename from expected/13.12/extra/numeric.out rename to expected/13.15/extra/numeric.out diff --git a/expected/12.16/extra/out_of_range.out b/expected/13.15/extra/out_of_range.out similarity index 93% rename from expected/12.16/extra/out_of_range.out rename to expected/13.15/extra/out_of_range.out index 8de68b14..be2f8256 100644 --- a/expected/12.16/extra/out_of_range.out +++ b/expected/13.15/extra/out_of_range.out @@ -96,27 +96,17 @@ INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; --Testcase 34: SELECT * FROM INT8_TBL; -- NO overflow - q1 | q2 -----------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 - -9223372036854775808 | 0 -(6 rows) + q1 | q2 +----------------------+---- + -9223372036854775808 | 0 +(1 row) --Testcase 35: SELECT q1 FROM INT8_TBL; -- NO overflow q1 ---------------------- - 123 - 123 - 4567890123456789 - 4567890123456789 - 4567890123456789 -9223372036854775808 -(6 rows) +(1 row) --Testcase 36: ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; diff --git a/expected/13.12/extra/prepare.out b/expected/13.15/extra/prepare.out similarity index 100% rename from expected/13.12/extra/prepare.out rename to expected/13.15/extra/prepare.out diff --git a/expected/13.12/extra/select.out b/expected/13.15/extra/select.out similarity index 98% rename from expected/13.12/extra/select.out rename to expected/13.15/extra/select.out index 86567108..2a0c983d 100644 --- a/expected/13.12/extra/select.out +++ b/expected/13.15/extra/select.out @@ -49,6 +49,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -912,6 +922,8 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/expected/12.16/extra/select_having.out b/expected/13.15/extra/select_having.out similarity index 100% rename from expected/12.16/extra/select_having.out rename to expected/13.15/extra/select_having.out diff --git a/expected/13.12/extra/sqlite_fdw_post.out b/expected/13.15/extra/sqlite_fdw_post.out similarity index 99% rename from expected/13.12/extra/sqlite_fdw_post.out rename to expected/13.15/extra/sqlite_fdw_post.out index 0c262b49..cdf38ad7 100644 --- a/expected/13.12/extra/sqlite_fdw_post.out +++ b/expected/13.15/extra/sqlite_fdw_post.out @@ -11,10 +11,11 @@ DO $d$ OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -2607,10 +2608,19 @@ RESET enable_nestloop; RESET enable_hashjoin; --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; --Testcase 510: @@ -8942,7 +8952,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest1 | loct | sqlite_svr | ("table" 'loct') | import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest1 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest1 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -8956,7 +8968,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 478: \d import_dest1.* @@ -9096,6 +9108,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest1.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest1.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9105,6 +9124,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest1.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest1.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9236,7 +9263,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest2 | loct | sqlite_svr | ("table" 'loct') | import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest2 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest2 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9250,7 +9279,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 480: \d import_dest2.* @@ -9390,6 +9419,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest2.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest2.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9399,6 +9435,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest2.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest2.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9541,7 +9585,9 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest3 | loct | sqlite_svr | ("table" 'loct') | import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest3 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest3 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9555,7 +9601,7 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) -- Assorted error cases IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; @@ -9860,12 +9906,12 @@ ROLLBACK; WARNING: there is no transaction in progress -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 125 other objects +NOTICE: drop cascades to 133 other objects DETAIL: drop cascades to foreign table "S 1"."T 0" drop cascades to foreign table "S 1"."T 1" drop cascades to foreign table "S 1"."T 2" @@ -9887,6 +9933,8 @@ drop cascades to foreign table "S 1".ft3 drop cascades to foreign table "S 1".foreign_tbl drop cascades to foreign table "S 1".grem1 drop cascades to foreign table "S 1".grem1_post14 +drop cascades to foreign table "S 1".loct1_rescan +drop cascades to foreign table "S 1".loct2_rescan drop cascades to foreign table "S 1".t1_constraint drop cascades to foreign table "S 1".tru_rtable0 drop cascades to foreign table "S 1".tru_pk_table @@ -9925,6 +9973,8 @@ drop cascades to foreign table import_dest1.ft3 drop cascades to foreign table import_dest1.foreign_tbl drop cascades to foreign table import_dest1.grem1 drop cascades to foreign table import_dest1.grem1_post14 +drop cascades to foreign table import_dest1.loct1_rescan +drop cascades to foreign table import_dest1.loct2_rescan drop cascades to foreign table import_dest1.t1_constraint drop cascades to foreign table import_dest1.tru_rtable0 drop cascades to foreign table import_dest1.tru_pk_table @@ -9954,19 +10004,15 @@ drop cascades to foreign table import_dest2.ft3 drop cascades to foreign table import_dest2.foreign_tbl drop cascades to foreign table import_dest2.grem1 drop cascades to foreign table import_dest2.grem1_post14 +drop cascades to foreign table import_dest2.loct1_rescan +drop cascades to foreign table import_dest2.loct2_rescan drop cascades to foreign table import_dest2.t1_constraint drop cascades to foreign table import_dest2.tru_rtable0 drop cascades to foreign table import_dest2.tru_pk_table drop cascades to foreign table import_dest2.tru_fk_table drop cascades to foreign table import_dest2.tru_rtable_parent drop cascades to foreign table import_dest2.tru_rtable_child -drop cascades to foreign table import_dest2.loct_empty -drop cascades to foreign table import_dest2.batch_table -drop cascades to foreign table import_dest3."T 1" -drop cascades to foreign table import_dest3.loct6 -drop cascades to foreign table import_dest3."T 0" -drop cascades to foreign table import_dest3."T 2" -and 25 other objects (see server log for list) +and 33 other objects (see server log for list) --Testcase 736: DROP SERVER sqlite_svr2 CASCADE; NOTICE: drop cascades to foreign table ft6 diff --git a/expected/12.16/extra/timestamp.out b/expected/13.15/extra/timestamp.out similarity index 100% rename from expected/12.16/extra/timestamp.out rename to expected/13.15/extra/timestamp.out diff --git a/expected/12.16/extra/update.out b/expected/13.15/extra/update.out similarity index 100% rename from expected/12.16/extra/update.out rename to expected/13.15/extra/update.out diff --git a/expected/12.16/extra/uuid.out b/expected/13.15/extra/uuid.out similarity index 100% rename from expected/12.16/extra/uuid.out rename to expected/13.15/extra/uuid.out diff --git a/expected/12.16/selectfunc.out b/expected/13.15/selectfunc.out similarity index 100% rename from expected/12.16/selectfunc.out rename to expected/13.15/selectfunc.out diff --git a/expected/13.12/sqlite_fdw.out b/expected/13.15/sqlite_fdw.out similarity index 99% rename from expected/13.12/sqlite_fdw.out rename to expected/13.15/sqlite_fdw.out index 40995678..ff8b260c 100644 --- a/expected/13.12/sqlite_fdw.out +++ b/expected/13.15/sqlite_fdw.out @@ -1477,14 +1477,14 @@ SELECT * FROM noprimary; SELECT * FROM public.sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) --Testcase 155: SELECT sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) -- issue #44 github diff --git a/expected/13.12/type.out b/expected/13.15/type.out similarity index 97% rename from expected/13.12/type.out rename to expected/13.15/type.out index d23c7be1..deedc213 100644 --- a/expected/13.12/type.out +++ b/expected/13.15/type.out @@ -298,7 +298,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/expected/14.9/aggregate.out b/expected/14.12/aggregate.out similarity index 100% rename from expected/14.9/aggregate.out rename to expected/14.12/aggregate.out diff --git a/expected/14.9/extra/aggregates.out b/expected/14.12/extra/aggregates.out similarity index 98% rename from expected/14.9/extra/aggregates.out rename to expected/14.12/extra/aggregates.out index b06a4442..b4dc5539 100644 --- a/expected/14.9/extra/aggregates.out +++ b/expected/14.12/extra/aggregates.out @@ -61,14 +61,44 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 678: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 679: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 680: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 681: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 682: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 683: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 684: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 685: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 686: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 687: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; --Testcase 275: CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 688: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 689: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 690: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 691: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 692: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: SET extra_float_digits = 0; @@ -129,7 +159,7 @@ HINT: No function matches the given name and argument types. You might need to -- In 7.1, avg(float4) is computed using float8 arithmetic. --Testcase 3: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 678: +--Testcase 693: SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; avg_107_943 ------------- @@ -138,7 +168,7 @@ SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; --Testcase 4: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 679: +--Testcase 694: SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; avg_3_4 --------- @@ -161,7 +191,7 @@ SELECT sum(a) AS sum_198 FROM aggtest; --Testcase 7: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 680: +--Testcase 695: SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; avg_431_773 ------------- @@ -170,7 +200,7 @@ SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; --Testcase 8: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 681: +--Testcase 696: SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; avg_6_8 --------- @@ -207,7 +237,7 @@ SELECT max(student.gpa) AS max_3_7 FROM student; --Testcase 13: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 682: +--Testcase 697: SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; stddev_pop ---------------- @@ -216,7 +246,7 @@ SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; --Testcase 14: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 683: +--Testcase 698: SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; stddev_samp ---------------- @@ -225,7 +255,7 @@ SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; --Testcase 15: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 684: +--Testcase 699: SELECT var_pop(b)::numeric(20,10) FROM aggtest; var_pop ------------------ @@ -234,7 +264,7 @@ SELECT var_pop(b)::numeric(20,10) FROM aggtest; --Testcase 16: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 685: +--Testcase 700: SELECT var_samp(b)::numeric(20,10) FROM aggtest; var_samp ------------------ @@ -685,7 +715,7 @@ SELECT regr_sxx(b, a) FROM aggtest; --Testcase 23: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 686: +--Testcase 701: SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; regr_syy ------------------ @@ -694,7 +724,7 @@ SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; --Testcase 24: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 687: +--Testcase 702: SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; regr_sxy ----------------- @@ -703,7 +733,7 @@ SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; --Testcase 25: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 688: +--Testcase 703: SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; regr_avgx | regr_avgy -----------+---------------- @@ -712,7 +742,7 @@ SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; --Testcase 26: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 689: +--Testcase 704: SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; regr_r2 -------------- @@ -721,7 +751,7 @@ SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; --Testcase 27: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 690: +--Testcase 705: SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; regr_slope | regr_intercept --------------+---------------- @@ -730,7 +760,7 @@ SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FR --Testcase 28: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 691: +--Testcase 706: SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; covar_pop | covar_samp ----------------+---------------- @@ -739,7 +769,7 @@ SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM ag --Testcase 29: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 692: +--Testcase 707: SELECT corr(b, a)::numeric(20,10) FROM aggtest; corr -------------- @@ -2754,7 +2784,7 @@ LINE 1: select f1, percentile_cont(f1,f1) rollback; --Testcase 179: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 693: +--Testcase 708: select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; percentile_cont ----------------- @@ -2763,7 +2793,7 @@ select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from agg --Testcase 180: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 694: +--Testcase 709: select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; percentile_cont | sum -----------------+--------- @@ -2772,7 +2802,7 @@ select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b): --Testcase 181: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 695: +--Testcase 710: select percentile_cont(0.5) within group (order by thousand) from tenk1; percentile_cont ----------------- @@ -2809,7 +2839,7 @@ select cume_dist(3) within group (order by f1) from INT4_TBL; insert into INT4_TBL values (5); --Testcase 458: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 696: +--Testcase 711: select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; percent_rank -------------- @@ -3954,6 +3984,12 @@ set work_mem to default; ----+----+---- (0 rows) +--Testcase 712: +DELETE FROM INT4_TBL; +--Testcase 713: +DELETE FROM INT8_TBL; +--Testcase 714: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/13.12/extra/bitstring.out b/expected/14.12/extra/bitstring.out similarity index 100% rename from expected/13.12/extra/bitstring.out rename to expected/14.12/extra/bitstring.out diff --git a/expected/12.16/extra/bool.out b/expected/14.12/extra/bool.out similarity index 99% rename from expected/12.16/extra/bool.out rename to expected/14.12/extra/bool.out index ec908ab6..ccb740e5 100644 --- a/expected/12.16/extra/bool.out +++ b/expected/14.12/extra/bool.out @@ -1263,6 +1263,8 @@ SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; | (2 rows) +--Testcase 79: +DELETE FROM "type_BOOLEAN"; --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; NOTICE: drop cascades to 6 other objects diff --git a/expected/13.12/extra/encodings.out b/expected/14.12/extra/encodings.out similarity index 100% rename from expected/13.12/extra/encodings.out rename to expected/14.12/extra/encodings.out diff --git a/expected/14.9/extra/float4.out b/expected/14.12/extra/float4.out similarity index 100% rename from expected/14.9/extra/float4.out rename to expected/14.12/extra/float4.out diff --git a/expected/14.9/extra/float8.out b/expected/14.12/extra/float8.out similarity index 99% rename from expected/14.9/extra/float8.out rename to expected/14.12/extra/float8.out index 8baeb448..f7607012 100644 --- a/expected/14.9/extra/float8.out +++ b/expected/14.12/extra/float8.out @@ -1946,6 +1946,8 @@ drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 drop cascades to cast from xfloat8 to bigint drop cascades to cast from bigint to xfloat8 +--Testcase 363: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/14.9/extra/insert.out b/expected/14.12/extra/insert.out similarity index 100% rename from expected/14.9/extra/insert.out rename to expected/14.12/extra/insert.out diff --git a/expected/14.9/extra/int4.out b/expected/14.12/extra/int4.out similarity index 99% rename from expected/14.9/extra/int4.out rename to expected/14.12/extra/int4.out index d5d7231f..113f70ac 100644 --- a/expected/14.9/extra/int4.out +++ b/expected/14.12/extra/int4.out @@ -611,6 +611,8 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow ERROR: integer out of range +--Testcase 137: +DELETE FROM INT4_TBL; -- Clean up DO $d$ declare diff --git a/expected/15.4/extra/int8.out b/expected/14.12/extra/int8.out similarity index 99% rename from expected/15.4/extra/int8.out rename to expected/14.12/extra/int8.out index d40b12c9..01ac92d6 100644 --- a/expected/15.4/extra/int8.out +++ b/expected/14.12/extra/int8.out @@ -1306,6 +1306,8 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow ERROR: bigint out of range +--Testcase 251: +DELETE FROM INT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/14.9/extra/join.out b/expected/14.12/extra/join.out similarity index 99% rename from expected/14.9/extra/join.out rename to expected/14.12/extra/join.out index 0b9ab1c3..efa6f277 100644 --- a/expected/14.9/extra/join.out +++ b/expected/14.12/extra/join.out @@ -58,13 +58,43 @@ CREATE FOREIGN TABLE tenk2 ( ) SERVER sqlite_svr; --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 539: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 540: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 541: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 542: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 543: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 544: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 545: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 546: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 547: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 548: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 549: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 550: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 551: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 552: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 553: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 1: @@ -7242,6 +7272,12 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 554: +DELETE FROM INT4_TBL; +--Testcase 555: +DELETE FROM INT8_TBL; +--Testcase 556: +DELETE FROM FLOAT8_TBL; DO $d$ declare l_rec record; diff --git a/expected/14.9/extra/limit.out b/expected/14.12/extra/limit.out similarity index 98% rename from expected/14.9/extra/limit.out rename to expected/14.12/extra/limit.out index c8e8d24a..7890cb30 100644 --- a/expected/14.9/extra/limit.out +++ b/expected/14.12/extra/limit.out @@ -28,6 +28,16 @@ CREATE FOREIGN TABLE onek( ) SERVER sqlite_svr; --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 104: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 105: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 107: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 108: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -1038,6 +1048,8 @@ View definition: LIMIT ALL; -- leave these views +--Testcase 109: +DELETE FROM int8_tbl; -- Clean up DO $d$ declare diff --git a/expected/14.9/extra/numeric.out b/expected/14.12/extra/numeric.out similarity index 100% rename from expected/14.9/extra/numeric.out rename to expected/14.12/extra/numeric.out diff --git a/expected/13.12/extra/out_of_range.out b/expected/14.12/extra/out_of_range.out similarity index 93% rename from expected/13.12/extra/out_of_range.out rename to expected/14.12/extra/out_of_range.out index 8de68b14..be2f8256 100644 --- a/expected/13.12/extra/out_of_range.out +++ b/expected/14.12/extra/out_of_range.out @@ -96,27 +96,17 @@ INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; --Testcase 34: SELECT * FROM INT8_TBL; -- NO overflow - q1 | q2 -----------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 - -9223372036854775808 | 0 -(6 rows) + q1 | q2 +----------------------+---- + -9223372036854775808 | 0 +(1 row) --Testcase 35: SELECT q1 FROM INT8_TBL; -- NO overflow q1 ---------------------- - 123 - 123 - 4567890123456789 - 4567890123456789 - 4567890123456789 -9223372036854775808 -(6 rows) +(1 row) --Testcase 36: ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; diff --git a/expected/14.9/extra/prepare.out b/expected/14.12/extra/prepare.out similarity index 100% rename from expected/14.9/extra/prepare.out rename to expected/14.12/extra/prepare.out diff --git a/expected/12.16/extra/select.out b/expected/14.12/extra/select.out similarity index 98% rename from expected/12.16/extra/select.out rename to expected/14.12/extra/select.out index 86567108..2a0c983d 100644 --- a/expected/12.16/extra/select.out +++ b/expected/14.12/extra/select.out @@ -49,6 +49,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -912,6 +922,8 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/expected/13.12/extra/select_having.out b/expected/14.12/extra/select_having.out similarity index 100% rename from expected/13.12/extra/select_having.out rename to expected/14.12/extra/select_having.out diff --git a/expected/14.9/extra/sqlite_fdw_post.out b/expected/14.12/extra/sqlite_fdw_post.out similarity index 99% rename from expected/14.9/extra/sqlite_fdw_post.out rename to expected/14.12/extra/sqlite_fdw_post.out index 85f777d5..bcd7c3d4 100644 --- a/expected/14.9/extra/sqlite_fdw_post.out +++ b/expected/14.12/extra/sqlite_fdw_post.out @@ -13,12 +13,13 @@ DO $d$ OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -2652,10 +2653,19 @@ RESET enable_nestloop; RESET enable_hashjoin; --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; --Testcase 510: @@ -9410,7 +9420,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest1 | loct | sqlite_svr | ("table" 'loct') | import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest1 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest1 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9424,7 +9436,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 478: \d import_dest1.* @@ -9564,6 +9576,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest1.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest1.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9573,6 +9592,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest1.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest1.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9704,7 +9731,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest2 | loct | sqlite_svr | ("table" 'loct') | import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest2 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest2 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9718,7 +9747,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 480: \d import_dest2.* @@ -9858,6 +9887,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest2.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest2.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9867,6 +9903,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest2.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest2.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10009,7 +10053,9 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest3 | loct | sqlite_svr | ("table" 'loct') | import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest3 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest3 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -10023,7 +10069,7 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) -- Assorted error cases IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; @@ -10412,9 +10458,7 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); --Testcase 886: DROP SERVER sqlite_svr3 CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to user mapping for public on server sqlite_svr3 -drop cascades to foreign table ft7 +NOTICE: drop cascades to foreign table ft7 -- List all the existing cached connections. sqlite_svr and sqlite_svr3 -- should be output as invalid connections. Also the server name for -- sqlite_svr3 should be NULL because the server was dropped. @@ -10545,15 +10589,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 --Testcase 908: @@ -10579,7 +10628,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name @@ -10605,9 +10654,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -11035,12 +11084,12 @@ CREATE FOREIGN TABLE inv_bsz (c1 int ) ERROR: invalid value for integer option "batch_size": 100$%$#$# -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 126 other objects +NOTICE: drop cascades to 134 other objects DETAIL: drop cascades to foreign table "S 1"."T 0" drop cascades to foreign table "S 1"."T 1" drop cascades to foreign table "S 1"."T 2" @@ -11062,6 +11111,8 @@ drop cascades to foreign table "S 1".ft3 drop cascades to foreign table "S 1".foreign_tbl drop cascades to foreign table "S 1".grem1 drop cascades to foreign table "S 1".grem1_post14 +drop cascades to foreign table "S 1".loct1_rescan +drop cascades to foreign table "S 1".loct2_rescan drop cascades to foreign table "S 1".t1_constraint drop cascades to foreign table "S 1".tru_rtable0 drop cascades to foreign table "S 1".tru_pk_table @@ -11101,6 +11152,8 @@ drop cascades to foreign table import_dest1.ft3 drop cascades to foreign table import_dest1.foreign_tbl drop cascades to foreign table import_dest1.grem1 drop cascades to foreign table import_dest1.grem1_post14 +drop cascades to foreign table import_dest1.loct1_rescan +drop cascades to foreign table import_dest1.loct2_rescan drop cascades to foreign table import_dest1.t1_constraint drop cascades to foreign table import_dest1.tru_rtable0 drop cascades to foreign table import_dest1.tru_pk_table @@ -11130,18 +11183,14 @@ drop cascades to foreign table import_dest2.ft3 drop cascades to foreign table import_dest2.foreign_tbl drop cascades to foreign table import_dest2.grem1 drop cascades to foreign table import_dest2.grem1_post14 +drop cascades to foreign table import_dest2.loct1_rescan +drop cascades to foreign table import_dest2.loct2_rescan drop cascades to foreign table import_dest2.t1_constraint drop cascades to foreign table import_dest2.tru_rtable0 drop cascades to foreign table import_dest2.tru_pk_table drop cascades to foreign table import_dest2.tru_fk_table drop cascades to foreign table import_dest2.tru_rtable_parent -drop cascades to foreign table import_dest2.tru_rtable_child -drop cascades to foreign table import_dest2.loct_empty -drop cascades to foreign table import_dest2.batch_table -drop cascades to foreign table import_dest3."T 1" -drop cascades to foreign table import_dest3.loct6 -drop cascades to foreign table import_dest3."T 0" -and 26 other objects (see server log for list) +and 34 other objects (see server log for list) --Testcase 736: DROP SERVER sqlite_svr2 CASCADE; NOTICE: drop cascades to foreign table ft6 diff --git a/expected/13.12/extra/timestamp.out b/expected/14.12/extra/timestamp.out similarity index 100% rename from expected/13.12/extra/timestamp.out rename to expected/14.12/extra/timestamp.out diff --git a/expected/14.9/extra/update.out b/expected/14.12/extra/update.out similarity index 100% rename from expected/14.9/extra/update.out rename to expected/14.12/extra/update.out diff --git a/expected/14.9/extra/uuid.out b/expected/14.12/extra/uuid.out similarity index 100% rename from expected/14.9/extra/uuid.out rename to expected/14.12/extra/uuid.out diff --git a/expected/13.12/selectfunc.out b/expected/14.12/selectfunc.out similarity index 100% rename from expected/13.12/selectfunc.out rename to expected/14.12/selectfunc.out diff --git a/expected/14.9/sqlite_fdw.out b/expected/14.12/sqlite_fdw.out similarity index 99% rename from expected/14.9/sqlite_fdw.out rename to expected/14.12/sqlite_fdw.out index 2a7a5832..c902d3d0 100644 --- a/expected/14.9/sqlite_fdw.out +++ b/expected/14.12/sqlite_fdw.out @@ -1459,14 +1459,14 @@ SELECT * FROM noprimary; SELECT * FROM public.sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) --Testcase 155: SELECT sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) -- issue #44 github diff --git a/expected/15.4/type.out b/expected/14.12/type.out similarity index 97% rename from expected/15.4/type.out rename to expected/14.12/type.out index d23c7be1..deedc213 100644 --- a/expected/15.4/type.out +++ b/expected/14.12/type.out @@ -298,7 +298,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/expected/15.4/aggregate.out b/expected/15.7/aggregate.out similarity index 100% rename from expected/15.4/aggregate.out rename to expected/15.7/aggregate.out diff --git a/expected/15.4/extra/aggregates.out b/expected/15.7/extra/aggregates.out similarity index 98% rename from expected/15.4/extra/aggregates.out rename to expected/15.7/extra/aggregates.out index b2bba040..dd672571 100644 --- a/expected/15.4/extra/aggregates.out +++ b/expected/15.7/extra/aggregates.out @@ -61,14 +61,44 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 697: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 698: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 699: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 700: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 701: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 702: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 703: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 704: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 705: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 706: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; --Testcase 275: CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 707: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 708: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 709: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 710: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 711: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: SET extra_float_digits = 0; @@ -3954,6 +3984,12 @@ set work_mem to default; ----+----+---- (0 rows) +--Testcase 712: +DELETE FROM INT4_TBL; +--Testcase 713: +DELETE FROM INT8_TBL; +--Testcase 714: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/14.9/extra/bitstring.out b/expected/15.7/extra/bitstring.out similarity index 100% rename from expected/14.9/extra/bitstring.out rename to expected/15.7/extra/bitstring.out diff --git a/expected/15.4/extra/bool.out b/expected/15.7/extra/bool.out similarity index 99% rename from expected/15.4/extra/bool.out rename to expected/15.7/extra/bool.out index ec908ab6..ccb740e5 100644 --- a/expected/15.4/extra/bool.out +++ b/expected/15.7/extra/bool.out @@ -1263,6 +1263,8 @@ SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; | (2 rows) +--Testcase 79: +DELETE FROM "type_BOOLEAN"; --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; NOTICE: drop cascades to 6 other objects diff --git a/expected/14.9/extra/encodings.out b/expected/15.7/extra/encodings.out similarity index 100% rename from expected/14.9/extra/encodings.out rename to expected/15.7/extra/encodings.out diff --git a/expected/15.4/extra/float4.out b/expected/15.7/extra/float4.out similarity index 100% rename from expected/15.4/extra/float4.out rename to expected/15.7/extra/float4.out diff --git a/expected/15.4/extra/float8.out b/expected/15.7/extra/float8.out similarity index 99% rename from expected/15.4/extra/float8.out rename to expected/15.7/extra/float8.out index 8baeb448..f7607012 100644 --- a/expected/15.4/extra/float8.out +++ b/expected/15.7/extra/float8.out @@ -1946,6 +1946,8 @@ drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 drop cascades to cast from xfloat8 to bigint drop cascades to cast from bigint to xfloat8 +--Testcase 363: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/15.4/extra/insert.out b/expected/15.7/extra/insert.out similarity index 100% rename from expected/15.4/extra/insert.out rename to expected/15.7/extra/insert.out diff --git a/expected/15.4/extra/int4.out b/expected/15.7/extra/int4.out similarity index 99% rename from expected/15.4/extra/int4.out rename to expected/15.7/extra/int4.out index d5d7231f..113f70ac 100644 --- a/expected/15.4/extra/int4.out +++ b/expected/15.7/extra/int4.out @@ -611,6 +611,8 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow ERROR: integer out of range +--Testcase 137: +DELETE FROM INT4_TBL; -- Clean up DO $d$ declare diff --git a/expected/14.9/extra/int8.out b/expected/15.7/extra/int8.out similarity index 99% rename from expected/14.9/extra/int8.out rename to expected/15.7/extra/int8.out index d40b12c9..01ac92d6 100644 --- a/expected/14.9/extra/int8.out +++ b/expected/15.7/extra/int8.out @@ -1306,6 +1306,8 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow ERROR: bigint out of range +--Testcase 251: +DELETE FROM INT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/15.4/extra/join.out b/expected/15.7/extra/join.out similarity index 99% rename from expected/15.4/extra/join.out rename to expected/15.7/extra/join.out index 4c5a6dde..7cb6d714 100644 --- a/expected/15.4/extra/join.out +++ b/expected/15.7/extra/join.out @@ -58,13 +58,43 @@ CREATE FOREIGN TABLE tenk2 ( ) SERVER sqlite_svr; --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 545: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 546: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 547: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 548: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 549: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 550: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 551: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 552: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 553: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 554: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 555: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 556: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 557: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 558: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 559: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 1: @@ -7284,6 +7314,12 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 560: +DELETE FROM INT4_TBL; +--Testcase 561: +DELETE FROM INT8_TBL; +--Testcase 562: +DELETE FROM FLOAT8_TBL; DO $d$ declare l_rec record; diff --git a/expected/13.12/extra/limit.out b/expected/15.7/extra/limit.out similarity index 97% rename from expected/13.12/extra/limit.out rename to expected/15.7/extra/limit.out index c8e8d24a..6b01e3f9 100644 --- a/expected/13.12/extra/limit.out +++ b/expected/15.7/extra/limit.out @@ -28,6 +28,16 @@ CREATE FOREIGN TABLE onek( ) SERVER sqlite_svr; --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -960,6 +970,12 @@ SELECT thousand 0 (2 rows) +-- SKIP LOCKED and WITH TIES are incompatible +--Testcase 104: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; +ERROR: SKIP LOCKED and WITH TIES options cannot be used together -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -1038,6 +1054,8 @@ View definition: LIMIT ALL; -- leave these views +--Testcase 110: +DELETE FROM int8_tbl; -- Clean up DO $d$ declare diff --git a/expected/15.4/extra/numeric.out b/expected/15.7/extra/numeric.out similarity index 100% rename from expected/15.4/extra/numeric.out rename to expected/15.7/extra/numeric.out diff --git a/expected/14.9/extra/out_of_range.out b/expected/15.7/extra/out_of_range.out similarity index 93% rename from expected/14.9/extra/out_of_range.out rename to expected/15.7/extra/out_of_range.out index 8de68b14..be2f8256 100644 --- a/expected/14.9/extra/out_of_range.out +++ b/expected/15.7/extra/out_of_range.out @@ -96,27 +96,17 @@ INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; --Testcase 34: SELECT * FROM INT8_TBL; -- NO overflow - q1 | q2 -----------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 - -9223372036854775808 | 0 -(6 rows) + q1 | q2 +----------------------+---- + -9223372036854775808 | 0 +(1 row) --Testcase 35: SELECT q1 FROM INT8_TBL; -- NO overflow q1 ---------------------- - 123 - 123 - 4567890123456789 - 4567890123456789 - 4567890123456789 -9223372036854775808 -(6 rows) +(1 row) --Testcase 36: ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; diff --git a/expected/15.4/extra/prepare.out b/expected/15.7/extra/prepare.out similarity index 100% rename from expected/15.4/extra/prepare.out rename to expected/15.7/extra/prepare.out diff --git a/expected/16.0/extra/select.out b/expected/15.7/extra/select.out similarity index 98% rename from expected/16.0/extra/select.out rename to expected/15.7/extra/select.out index 2f7f5359..7dddc119 100644 --- a/expected/16.0/extra/select.out +++ b/expected/15.7/extra/select.out @@ -49,6 +49,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -912,6 +922,8 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/expected/14.9/extra/select_having.out b/expected/15.7/extra/select_having.out similarity index 100% rename from expected/14.9/extra/select_having.out rename to expected/15.7/extra/select_having.out diff --git a/expected/15.4/extra/sqlite_fdw_post.out b/expected/15.7/extra/sqlite_fdw_post.out similarity index 99% rename from expected/15.4/extra/sqlite_fdw_post.out rename to expected/15.7/extra/sqlite_fdw_post.out index 2528a481..0b5fe4dc 100644 --- a/expected/15.4/extra/sqlite_fdw_post.out +++ b/expected/15.7/extra/sqlite_fdw_post.out @@ -13,12 +13,13 @@ DO $d$ OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -2855,10 +2856,19 @@ SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1. -- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; --Testcase 510: @@ -9756,7 +9766,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest1 | loct | sqlite_svr | ("table" 'loct') | import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest1 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest1 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9770,7 +9782,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 478: \d import_dest1.* @@ -9910,6 +9922,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest1.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest1.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -9919,6 +9938,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest1.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest1.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10050,7 +10077,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest2 | loct | sqlite_svr | ("table" 'loct') | import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest2 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest2 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -10064,7 +10093,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 480: \d import_dest2.* @@ -10204,6 +10233,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest2.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest2.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10213,6 +10249,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest2.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest2.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10355,7 +10399,9 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest3 | loct | sqlite_svr | ("table" 'loct') | import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest3 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest3 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -10369,7 +10415,7 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) -- Assorted error cases IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; @@ -10758,9 +10804,7 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); --Testcase 886: DROP SERVER sqlite_svr3 CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to user mapping for public on server sqlite_svr3 -drop cascades to foreign table ft7 +NOTICE: drop cascades to foreign table ft7 -- List all the existing cached connections. sqlite_svr and sqlite_svr3 -- should be output as invalid connections. Also the server name for -- sqlite_svr3 should be NULL because the server was dropped. @@ -10891,15 +10935,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 --Testcase 908: @@ -10925,7 +10974,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name @@ -10951,9 +11000,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -11549,12 +11598,12 @@ ERROR: invalid value for integer option "batch_size": 100$%$#$# -- ALTER SERVER loopback2 OPTIONS (DROP parallel_commit); -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 126 other objects +NOTICE: drop cascades to 134 other objects DETAIL: drop cascades to foreign table "S 1"."T 0" drop cascades to foreign table "S 1"."T 1" drop cascades to foreign table "S 1"."T 2" @@ -11576,6 +11625,8 @@ drop cascades to foreign table "S 1".ft3 drop cascades to foreign table "S 1".foreign_tbl drop cascades to foreign table "S 1".grem1 drop cascades to foreign table "S 1".grem1_post14 +drop cascades to foreign table "S 1".loct1_rescan +drop cascades to foreign table "S 1".loct2_rescan drop cascades to foreign table "S 1".t1_constraint drop cascades to foreign table "S 1".tru_rtable0 drop cascades to foreign table "S 1".tru_pk_table @@ -11615,6 +11666,8 @@ drop cascades to foreign table import_dest1.ft3 drop cascades to foreign table import_dest1.foreign_tbl drop cascades to foreign table import_dest1.grem1 drop cascades to foreign table import_dest1.grem1_post14 +drop cascades to foreign table import_dest1.loct1_rescan +drop cascades to foreign table import_dest1.loct2_rescan drop cascades to foreign table import_dest1.t1_constraint drop cascades to foreign table import_dest1.tru_rtable0 drop cascades to foreign table import_dest1.tru_pk_table @@ -11644,18 +11697,14 @@ drop cascades to foreign table import_dest2.ft3 drop cascades to foreign table import_dest2.foreign_tbl drop cascades to foreign table import_dest2.grem1 drop cascades to foreign table import_dest2.grem1_post14 +drop cascades to foreign table import_dest2.loct1_rescan +drop cascades to foreign table import_dest2.loct2_rescan drop cascades to foreign table import_dest2.t1_constraint drop cascades to foreign table import_dest2.tru_rtable0 drop cascades to foreign table import_dest2.tru_pk_table drop cascades to foreign table import_dest2.tru_fk_table drop cascades to foreign table import_dest2.tru_rtable_parent -drop cascades to foreign table import_dest2.tru_rtable_child -drop cascades to foreign table import_dest2.loct_empty -drop cascades to foreign table import_dest2.batch_table -drop cascades to foreign table import_dest3."T 1" -drop cascades to foreign table import_dest3.loct6 -drop cascades to foreign table import_dest3."T 0" -and 26 other objects (see server log for list) +and 34 other objects (see server log for list) --Testcase 736: DROP SERVER sqlite_svr2 CASCADE; NOTICE: drop cascades to foreign table ft6 diff --git a/expected/14.9/extra/timestamp.out b/expected/15.7/extra/timestamp.out similarity index 100% rename from expected/14.9/extra/timestamp.out rename to expected/15.7/extra/timestamp.out diff --git a/expected/15.4/extra/update.out b/expected/15.7/extra/update.out similarity index 100% rename from expected/15.4/extra/update.out rename to expected/15.7/extra/update.out diff --git a/expected/15.4/extra/uuid.out b/expected/15.7/extra/uuid.out similarity index 100% rename from expected/15.4/extra/uuid.out rename to expected/15.7/extra/uuid.out diff --git a/expected/14.9/selectfunc.out b/expected/15.7/selectfunc.out similarity index 100% rename from expected/14.9/selectfunc.out rename to expected/15.7/selectfunc.out diff --git a/expected/15.4/sqlite_fdw.out b/expected/15.7/sqlite_fdw.out similarity index 99% rename from expected/15.4/sqlite_fdw.out rename to expected/15.7/sqlite_fdw.out index 9577e4a8..ba1d798c 100644 --- a/expected/15.4/sqlite_fdw.out +++ b/expected/15.7/sqlite_fdw.out @@ -1459,14 +1459,14 @@ SELECT * FROM noprimary; SELECT * FROM public.sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) --Testcase 155: SELECT sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) -- issue #44 github diff --git a/expected/12.16/type.out b/expected/15.7/type.out similarity index 97% rename from expected/12.16/type.out rename to expected/15.7/type.out index d23c7be1..deedc213 100644 --- a/expected/12.16/type.out +++ b/expected/15.7/type.out @@ -298,7 +298,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/expected/16.0/extra/bool.out b/expected/16.0/extra/bool.out deleted file mode 100644 index ec908ab6..00000000 --- a/expected/16.0/extra/bool.out +++ /dev/null @@ -1,1274 +0,0 @@ ---SET log_min_messages TO DEBUG1; ---SET client_min_messages TO DEBUG1; ---Testcase 000: -CREATE EXTENSION sqlite_fdw; ---Testcase 001: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); ---Testcase 002: -CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; ---Testcase 01: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int OPTIONS (key 'true'), b bool) SERVER sqlite_svr; ---Testcase 02: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (1, TRUE); ---Testcase 03: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (2, FALSE); ---Testcase 04: -CREATE FOREIGN TABLE "type_BOOLEAN+"( "i" int, "b" bool, "t" text, "l" smallint) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN+'); ---Testcase 05: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE text; ---Testcase 06: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (3, TRUE); ---Testcase 07: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (4, FALSE); ---Testcase 08: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (5, true); ---Testcase 09: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (6, false); ---Testcase 10: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (7, 'Yes'); ---Testcase 11: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (8, 'YeS'); ---Testcase 12: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (9, 'yes'); ---Testcase 13: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (10, 'no'); ---Testcase 14: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (11, 'No'); ---Testcase 15: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (12, 'nO'); ---Testcase 16: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (13, 'off'); ---Testcase 17: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (14, 'oFf'); ---Testcase 18: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (15, 'on'); ---Testcase 19: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (16, 'ON'); ---Testcase 20: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (17, 't'); ---Testcase 21: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (18, 'T'); ---Testcase 22: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (19, 'Y'); ---Testcase 23: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (20, 'y'); ---Testcase 24: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (21, 'F'); ---Testcase 25: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (22, 'f'); ---Testcase 26: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (23, 'x'); ---Testcase 27: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (24, '0'); ---Testcase 28: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (25, '1'); ---Testcase 29: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (26, NULL); ---Testcase 30: -SELECT * FROM "type_BOOLEAN"; - i | b -----+------- - 1 | 1 - 2 | 0 - 3 | true - 4 | false - 5 | true - 6 | false - 7 | Yes - 8 | YeS - 9 | yes - 10 | no - 11 | No - 12 | nO - 13 | off - 14 | oFf - 15 | on - 16 | ON - 17 | t - 18 | T - 19 | Y - 20 | y - 21 | F - 22 | f - 23 | x - 24 | 0 - 25 | 1 - 26 | -(26 rows) - ---Testcase 31: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; ---Testcase 32: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM "type_BOOLEAN"; - QUERY PLAN ---------------------------------------------------------------------------- - Foreign Scan on public."type_BOOLEAN" - Output: i, b - SQLite query: SELECT `i`, sqlite_fdw_bool(`b`) FROM main."type_BOOLEAN" -(3 rows) - ---Testcase 33: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM "type_BOOLEAN+"; - QUERY PLAN --------------------------------------------------------------------------------------- - Foreign Scan on public."type_BOOLEAN+" - Output: i, b, t, l - SQLite query: SELECT `i`, sqlite_fdw_bool(`b`), `t`, `l` FROM main."type_BOOLEAN+" -(3 rows) - ---Testcase 34: ERR - invalid text affinity because not ISO:SQL text input -SELECT * FROM "type_BOOLEAN+"; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "text" affinity (1 bytes) : 'x' -CONTEXT: foreign table "type_BOOLEAN+" foreign column "b" have data type "boolean" (usual affinity "integer"), in query there is reference to foreign column ---Testcase 35 -DELETE FROM "type_BOOLEAN" WHERE i = 23; ---Testcase 36: -SELECT * FROM "type_BOOLEAN+"; - i | b | t | l -----+---+---------+--- - 1 | t | integer | 1 - 2 | f | integer | 1 - 3 | t | text | 4 - 4 | f | text | 5 - 5 | t | text | 4 - 6 | f | text | 5 - 7 | t | text | 3 - 8 | t | text | 3 - 9 | t | text | 3 - 10 | f | text | 2 - 11 | f | text | 2 - 12 | f | text | 2 - 13 | f | text | 3 - 14 | f | text | 3 - 15 | t | text | 2 - 16 | t | text | 2 - 17 | t | text | 1 - 18 | t | text | 1 - 19 | t | text | 1 - 20 | t | text | 1 - 21 | f | text | 1 - 22 | f | text | 1 - 24 | f | integer | 1 - 25 | t | integer | 1 - 26 | | null | -(25 rows) - ---Testcase 37: -SELECT * FROM "type_BOOLEAN+" WHERE b IS NULL; - i | b | t | l -----+---+------+--- - 26 | | null | -(1 row) - ---Testcase 38: -SELECT * FROM "type_BOOLEAN+" WHERE b IS NOT NULL; - i | b | t | l -----+---+---------+--- - 1 | t | integer | 1 - 2 | f | integer | 1 - 3 | t | text | 4 - 4 | f | text | 5 - 5 | t | text | 4 - 6 | f | text | 5 - 7 | t | text | 3 - 8 | t | text | 3 - 9 | t | text | 3 - 10 | f | text | 2 - 11 | f | text | 2 - 12 | f | text | 2 - 13 | f | text | 3 - 14 | f | text | 3 - 15 | t | text | 2 - 16 | t | text | 2 - 17 | t | text | 1 - 18 | t | text | 1 - 19 | t | text | 1 - 20 | t | text | 1 - 21 | f | text | 1 - 22 | f | text | 1 - 24 | f | integer | 1 - 25 | t | integer | 1 -(24 rows) - ---Testcase 39: -SELECT * FROM "type_BOOLEAN+" WHERE b; - i | b | t | l -----+---+---------+--- - 1 | t | integer | 1 - 3 | t | text | 4 - 5 | t | text | 4 - 7 | t | text | 3 - 8 | t | text | 3 - 9 | t | text | 3 - 15 | t | text | 2 - 16 | t | text | 2 - 17 | t | text | 1 - 18 | t | text | 1 - 19 | t | text | 1 - 20 | t | text | 1 - 25 | t | integer | 1 -(13 rows) - ---Testcase 40: -SELECT * FROM "type_BOOLEAN+" WHERE NOT b; - i | b | t | l -----+---+---------+--- - 2 | f | integer | 1 - 4 | f | text | 5 - 6 | f | text | 5 - 10 | f | text | 2 - 11 | f | text | 2 - 12 | f | text | 2 - 13 | f | text | 3 - 14 | f | text | 3 - 21 | f | text | 1 - 22 | f | text | 1 - 24 | f | integer | 1 -(11 rows) - ---Testcase 41: -CREATE FOREIGN TABLE "type_BOOLEANpk" (col bool OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 42: -INSERT INTO "type_BOOLEANpk" VALUES (TRUE); ---Testcase 43: -INSERT INTO "type_BOOLEANpk" VALUES (FALSE); ---Testcase 44: ERR - primary key -INSERT INTO "type_BOOLEANpk" VALUES (TRUE); -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: type_BOOLEANpk.col', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."type_BOOLEANpk"(`col`) VALUES (?) ---Testcase 45: -DELETE FROM "type_BOOLEANpk"; ---Testcase 46: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE float8; ---Testcase 47: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (27, 3.14159265358979); ---Testcase 48: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; ---Testcase 49: ERR - invalid float for bool column -SELECT * FROM "type_BOOLEAN+"; -ERROR: SQLite value is not compatible with PostgreSQL column data type -HINT: SQLite value with "real" affinity : 3.14159265358979 -CONTEXT: foreign table "type_BOOLEAN+" foreign column "b" have data type "boolean" (usual affinity "integer"), in query there is reference to foreign column ---Testcase 50 -DELETE FROM "type_BOOLEAN" WHERE i = 27; ---Testcase 51: -SELECT * FROM "type_BOOLEAN+"; - i | b | t | l -----+---+---------+--- - 1 | t | integer | 1 - 2 | f | integer | 1 - 3 | t | text | 4 - 4 | f | text | 5 - 5 | t | text | 4 - 6 | f | text | 5 - 7 | t | text | 3 - 8 | t | text | 3 - 9 | t | text | 3 - 10 | f | text | 2 - 11 | f | text | 2 - 12 | f | text | 2 - 13 | f | text | 3 - 14 | f | text | 3 - 15 | t | text | 2 - 16 | t | text | 2 - 17 | t | text | 1 - 18 | t | text | 1 - 19 | t | text | 1 - 20 | t | text | 1 - 21 | f | text | 1 - 22 | f | text | 1 - 24 | f | integer | 1 - 25 | t | integer | 1 - 26 | | null | -(25 rows) - ---Testcase 52: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN" SET b = NULL WHERE b; - QUERY PLAN ----------------------------------------------------------------------------------------------- - Update on public."type_BOOLEAN" - -> Foreign Update on public."type_BOOLEAN" - SQLite query: UPDATE main."type_BOOLEAN" SET `b` = NULL WHERE (sqlite_fdw_bool(`b`)) -(3 rows) - ---Testcase 53: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN" SET b = NULL WHERE NOT b; - QUERY PLAN ----------------------------------------------------------------------------------------------------- - Update on public."type_BOOLEAN" - -> Foreign Update on public."type_BOOLEAN" - SQLite query: UPDATE main."type_BOOLEAN" SET `b` = NULL WHERE ((NOT sqlite_fdw_bool(`b`))) -(3 rows) - ---Testcase 54: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN" WHERE b; - QUERY PLAN ------------------------------------------------------------------------------------- - Delete on public."type_BOOLEAN" - -> Foreign Delete on public."type_BOOLEAN" - SQLite query: DELETE FROM main."type_BOOLEAN" WHERE (sqlite_fdw_bool(`b`)) -(3 rows) - ---Testcase 55: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN" WHERE NOT b; - QUERY PLAN ------------------------------------------------------------------------------------------- - Delete on public."type_BOOLEAN" - -> Foreign Delete on public."type_BOOLEAN" - SQLite query: DELETE FROM main."type_BOOLEAN" WHERE ((NOT sqlite_fdw_bool(`b`))) -(3 rows) - ---Testcase 56: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT *, NOT b nb FROM "type_BOOLEAN+" b; - QUERY PLAN --------------------------------------------------------------------------------------- - Foreign Scan on public."type_BOOLEAN+" b - Output: i, b, t, l, (NOT b) - SQLite query: SELECT `i`, sqlite_fdw_bool(`b`), `t`, `l` FROM main."type_BOOLEAN+" -(3 rows) - ---Testcase 57: -SELECT *, NOT b nb FROM "type_BOOLEAN+" b; - i | b | t | l | nb -----+---+---------+---+---- - 1 | t | integer | 1 | f - 2 | f | integer | 1 | t - 3 | t | text | 4 | f - 4 | f | text | 5 | t - 5 | t | text | 4 | f - 6 | f | text | 5 | t - 7 | t | text | 3 | f - 8 | t | text | 3 | f - 9 | t | text | 3 | f - 10 | f | text | 2 | t - 11 | f | text | 2 | t - 12 | f | text | 2 | t - 13 | f | text | 3 | t - 14 | f | text | 3 | t - 15 | t | text | 2 | f - 16 | t | text | 2 | f - 17 | t | text | 1 | f - 18 | t | text | 1 | f - 19 | t | text | 1 | f - 20 | t | text | 1 | f - 21 | f | text | 1 | t - 22 | f | text | 1 | t - 24 | f | integer | 1 | t - 25 | t | integer | 1 | f - 26 | | null | | -(25 rows) - ---Testcase 58: -CREATE FOREIGN TABLE "type_BOOLEAN_oper"( "i" int OPTIONS (key 'true'), i1 smallint, b1 boolean, i2 smallint, b2 boolean) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN_oper'); ---Testcase 59: see INIT.SQL with mixed affinity boolean data -SELECT * FROM "type_BOOLEAN_oper"; - i | i1 | b1 | i2 | b2 ------+----+----+----+---- - 1 | 1 | t | 1 | t - 2 | 1 | t | 2 | t - 3 | 1 | t | 3 | t - 4 | 1 | t | 4 | t - 5 | 1 | t | 5 | t - 6 | 1 | t | 6 | t - 7 | 1 | t | 7 | t - 8 | 1 | t | 8 | t - 9 | 1 | t | 9 | t - 10 | 1 | t | 10 | t - 11 | 1 | t | 11 | t - 12 | 1 | t | 12 | t - 13 | 1 | t | 13 | t - 14 | 1 | t | 14 | f - 15 | 1 | t | 15 | f - 16 | 1 | t | 16 | f - 17 | 1 | t | 17 | f - 18 | 1 | t | 18 | f - 19 | 1 | t | 19 | f - 20 | 1 | t | 20 | f - 21 | 1 | t | 21 | f - 22 | 1 | t | 22 | f - 23 | 1 | t | 23 | f - 24 | 1 | t | 24 | f - 25 | 1 | t | 25 | f - 26 | 1 | t | 26 | f - 27 | 1 | t | 27 | - 28 | 2 | t | 1 | t - 29 | 2 | t | 2 | t - 30 | 2 | t | 3 | t - 31 | 2 | t | 4 | t - 32 | 2 | t | 5 | t - 33 | 2 | t | 6 | t - 34 | 2 | t | 7 | t - 35 | 2 | t | 8 | t - 36 | 2 | t | 9 | t - 37 | 2 | t | 10 | t - 38 | 2 | t | 11 | t - 39 | 2 | t | 12 | t - 40 | 2 | t | 13 | t - 41 | 2 | t | 14 | f - 42 | 2 | t | 15 | f - 43 | 2 | t | 16 | f - 44 | 2 | t | 17 | f - 45 | 2 | t | 18 | f - 46 | 2 | t | 19 | f - 47 | 2 | t | 20 | f - 48 | 2 | t | 21 | f - 49 | 2 | t | 22 | f - 50 | 2 | t | 23 | f - 51 | 2 | t | 24 | f - 52 | 2 | t | 25 | f - 53 | 2 | t | 26 | f - 54 | 2 | t | 27 | - 55 | 3 | t | 1 | t - 56 | 3 | t | 2 | t - 57 | 3 | t | 3 | t - 58 | 3 | t | 4 | t - 59 | 3 | t | 5 | t - 60 | 3 | t | 6 | t - 61 | 3 | t | 7 | t - 62 | 3 | t | 8 | t - 63 | 3 | t | 9 | t - 64 | 3 | t | 10 | t - 65 | 3 | t | 11 | t - 66 | 3 | t | 12 | t - 67 | 3 | t | 13 | t - 68 | 3 | t | 14 | f - 69 | 3 | t | 15 | f - 70 | 3 | t | 16 | f - 71 | 3 | t | 17 | f - 72 | 3 | t | 18 | f - 73 | 3 | t | 19 | f - 74 | 3 | t | 20 | f - 75 | 3 | t | 21 | f - 76 | 3 | t | 22 | f - 77 | 3 | t | 23 | f - 78 | 3 | t | 24 | f - 79 | 3 | t | 25 | f - 80 | 3 | t | 26 | f - 81 | 3 | t | 27 | - 82 | 4 | t | 1 | t - 83 | 4 | t | 2 | t - 84 | 4 | t | 3 | t - 85 | 4 | t | 4 | t - 86 | 4 | t | 5 | t - 87 | 4 | t | 6 | t - 88 | 4 | t | 7 | t - 89 | 4 | t | 8 | t - 90 | 4 | t | 9 | t - 91 | 4 | t | 10 | t - 92 | 4 | t | 11 | t - 93 | 4 | t | 12 | t - 94 | 4 | t | 13 | t - 95 | 4 | t | 14 | f - 96 | 4 | t | 15 | f - 97 | 4 | t | 16 | f - 98 | 4 | t | 17 | f - 99 | 4 | t | 18 | f - 100 | 4 | t | 19 | f - 101 | 4 | t | 20 | f - 102 | 4 | t | 21 | f - 103 | 4 | t | 22 | f - 104 | 4 | t | 23 | f - 105 | 4 | t | 24 | f - 106 | 4 | t | 25 | f - 107 | 4 | t | 26 | f - 108 | 4 | t | 27 | - 109 | 5 | t | 1 | t - 110 | 5 | t | 2 | t - 111 | 5 | t | 3 | t - 112 | 5 | t | 4 | t - 113 | 5 | t | 5 | t - 114 | 5 | t | 6 | t - 115 | 5 | t | 7 | t - 116 | 5 | t | 8 | t - 117 | 5 | t | 9 | t - 118 | 5 | t | 10 | t - 119 | 5 | t | 11 | t - 120 | 5 | t | 12 | t - 121 | 5 | t | 13 | t - 122 | 5 | t | 14 | f - 123 | 5 | t | 15 | f - 124 | 5 | t | 16 | f - 125 | 5 | t | 17 | f - 126 | 5 | t | 18 | f - 127 | 5 | t | 19 | f - 128 | 5 | t | 20 | f - 129 | 5 | t | 21 | f - 130 | 5 | t | 22 | f - 131 | 5 | t | 23 | f - 132 | 5 | t | 24 | f - 133 | 5 | t | 25 | f - 134 | 5 | t | 26 | f - 135 | 5 | t | 27 | - 136 | 6 | t | 1 | t - 137 | 6 | t | 2 | t - 138 | 6 | t | 3 | t - 139 | 6 | t | 4 | t - 140 | 6 | t | 5 | t - 141 | 6 | t | 6 | t - 142 | 6 | t | 7 | t - 143 | 6 | t | 8 | t - 144 | 6 | t | 9 | t - 145 | 6 | t | 10 | t - 146 | 6 | t | 11 | t - 147 | 6 | t | 12 | t - 148 | 6 | t | 13 | t - 149 | 6 | t | 14 | f - 150 | 6 | t | 15 | f - 151 | 6 | t | 16 | f - 152 | 6 | t | 17 | f - 153 | 6 | t | 18 | f - 154 | 6 | t | 19 | f - 155 | 6 | t | 20 | f - 156 | 6 | t | 21 | f - 157 | 6 | t | 22 | f - 158 | 6 | t | 23 | f - 159 | 6 | t | 24 | f - 160 | 6 | t | 25 | f - 161 | 6 | t | 26 | f - 162 | 6 | t | 27 | - 163 | 7 | t | 1 | t - 164 | 7 | t | 2 | t - 165 | 7 | t | 3 | t - 166 | 7 | t | 4 | t - 167 | 7 | t | 5 | t - 168 | 7 | t | 6 | t - 169 | 7 | t | 7 | t - 170 | 7 | t | 8 | t - 171 | 7 | t | 9 | t - 172 | 7 | t | 10 | t - 173 | 7 | t | 11 | t - 174 | 7 | t | 12 | t - 175 | 7 | t | 13 | t - 176 | 7 | t | 14 | f - 177 | 7 | t | 15 | f - 178 | 7 | t | 16 | f - 179 | 7 | t | 17 | f - 180 | 7 | t | 18 | f - 181 | 7 | t | 19 | f - 182 | 7 | t | 20 | f - 183 | 7 | t | 21 | f - 184 | 7 | t | 22 | f - 185 | 7 | t | 23 | f - 186 | 7 | t | 24 | f - 187 | 7 | t | 25 | f - 188 | 7 | t | 26 | f - 189 | 7 | t | 27 | - 190 | 8 | t | 1 | t - 191 | 8 | t | 2 | t - 192 | 8 | t | 3 | t - 193 | 8 | t | 4 | t - 194 | 8 | t | 5 | t - 195 | 8 | t | 6 | t - 196 | 8 | t | 7 | t - 197 | 8 | t | 8 | t - 198 | 8 | t | 9 | t - 199 | 8 | t | 10 | t - 200 | 8 | t | 11 | t - 201 | 8 | t | 12 | t - 202 | 8 | t | 13 | t - 203 | 8 | t | 14 | f - 204 | 8 | t | 15 | f - 205 | 8 | t | 16 | f - 206 | 8 | t | 17 | f - 207 | 8 | t | 18 | f - 208 | 8 | t | 19 | f - 209 | 8 | t | 20 | f - 210 | 8 | t | 21 | f - 211 | 8 | t | 22 | f - 212 | 8 | t | 23 | f - 213 | 8 | t | 24 | f - 214 | 8 | t | 25 | f - 215 | 8 | t | 26 | f - 216 | 8 | t | 27 | - 217 | 9 | t | 1 | t - 218 | 9 | t | 2 | t - 219 | 9 | t | 3 | t - 220 | 9 | t | 4 | t - 221 | 9 | t | 5 | t - 222 | 9 | t | 6 | t - 223 | 9 | t | 7 | t - 224 | 9 | t | 8 | t - 225 | 9 | t | 9 | t - 226 | 9 | t | 10 | t - 227 | 9 | t | 11 | t - 228 | 9 | t | 12 | t - 229 | 9 | t | 13 | t - 230 | 9 | t | 14 | f - 231 | 9 | t | 15 | f - 232 | 9 | t | 16 | f - 233 | 9 | t | 17 | f - 234 | 9 | t | 18 | f - 235 | 9 | t | 19 | f - 236 | 9 | t | 20 | f - 237 | 9 | t | 21 | f - 238 | 9 | t | 22 | f - 239 | 9 | t | 23 | f - 240 | 9 | t | 24 | f - 241 | 9 | t | 25 | f - 242 | 9 | t | 26 | f - 243 | 9 | t | 27 | - 244 | 10 | t | 1 | t - 245 | 10 | t | 2 | t - 246 | 10 | t | 3 | t - 247 | 10 | t | 4 | t - 248 | 10 | t | 5 | t - 249 | 10 | t | 6 | t - 250 | 10 | t | 7 | t - 251 | 10 | t | 8 | t - 252 | 10 | t | 9 | t - 253 | 10 | t | 10 | t - 254 | 10 | t | 11 | t - 255 | 10 | t | 12 | t - 256 | 10 | t | 13 | t - 257 | 10 | t | 14 | f - 258 | 10 | t | 15 | f - 259 | 10 | t | 16 | f - 260 | 10 | t | 17 | f - 261 | 10 | t | 18 | f - 262 | 10 | t | 19 | f - 263 | 10 | t | 20 | f - 264 | 10 | t | 21 | f - 265 | 10 | t | 22 | f - 266 | 10 | t | 23 | f - 267 | 10 | t | 24 | f - 268 | 10 | t | 25 | f - 269 | 10 | t | 26 | f - 270 | 10 | t | 27 | - 271 | 11 | t | 1 | t - 272 | 11 | t | 2 | t - 273 | 11 | t | 3 | t - 274 | 11 | t | 4 | t - 275 | 11 | t | 5 | t - 276 | 11 | t | 6 | t - 277 | 11 | t | 7 | t - 278 | 11 | t | 8 | t - 279 | 11 | t | 9 | t - 280 | 11 | t | 10 | t - 281 | 11 | t | 11 | t - 282 | 11 | t | 12 | t - 283 | 11 | t | 13 | t - 284 | 11 | t | 14 | f - 285 | 11 | t | 15 | f - 286 | 11 | t | 16 | f - 287 | 11 | t | 17 | f - 288 | 11 | t | 18 | f - 289 | 11 | t | 19 | f - 290 | 11 | t | 20 | f - 291 | 11 | t | 21 | f - 292 | 11 | t | 22 | f - 293 | 11 | t | 23 | f - 294 | 11 | t | 24 | f - 295 | 11 | t | 25 | f - 296 | 11 | t | 26 | f - 297 | 11 | t | 27 | - 298 | 12 | t | 1 | t - 299 | 12 | t | 2 | t - 300 | 12 | t | 3 | t - 301 | 12 | t | 4 | t - 302 | 12 | t | 5 | t - 303 | 12 | t | 6 | t - 304 | 12 | t | 7 | t - 305 | 12 | t | 8 | t - 306 | 12 | t | 9 | t - 307 | 12 | t | 10 | t - 308 | 12 | t | 11 | t - 309 | 12 | t | 12 | t - 310 | 12 | t | 13 | t - 311 | 12 | t | 14 | f - 312 | 12 | t | 15 | f - 313 | 12 | t | 16 | f - 314 | 12 | t | 17 | f - 315 | 12 | t | 18 | f - 316 | 12 | t | 19 | f - 317 | 12 | t | 20 | f - 318 | 12 | t | 21 | f - 319 | 12 | t | 22 | f - 320 | 12 | t | 23 | f - 321 | 12 | t | 24 | f - 322 | 12 | t | 25 | f - 323 | 12 | t | 26 | f - 324 | 12 | t | 27 | - 325 | 13 | t | 1 | t - 326 | 13 | t | 2 | t - 327 | 13 | t | 3 | t - 328 | 13 | t | 4 | t - 329 | 13 | t | 5 | t - 330 | 13 | t | 6 | t - 331 | 13 | t | 7 | t - 332 | 13 | t | 8 | t - 333 | 13 | t | 9 | t - 334 | 13 | t | 10 | t - 335 | 13 | t | 11 | t - 336 | 13 | t | 12 | t - 337 | 13 | t | 13 | t - 338 | 13 | t | 14 | f - 339 | 13 | t | 15 | f - 340 | 13 | t | 16 | f - 341 | 13 | t | 17 | f - 342 | 13 | t | 18 | f - 343 | 13 | t | 19 | f - 344 | 13 | t | 20 | f - 345 | 13 | t | 21 | f - 346 | 13 | t | 22 | f - 347 | 13 | t | 23 | f - 348 | 13 | t | 24 | f - 349 | 13 | t | 25 | f - 350 | 13 | t | 26 | f - 351 | 13 | t | 27 | - 352 | 14 | f | 1 | t - 353 | 14 | f | 2 | t - 354 | 14 | f | 3 | t - 355 | 14 | f | 4 | t - 356 | 14 | f | 5 | t - 357 | 14 | f | 6 | t - 358 | 14 | f | 7 | t - 359 | 14 | f | 8 | t - 360 | 14 | f | 9 | t - 361 | 14 | f | 10 | t - 362 | 14 | f | 11 | t - 363 | 14 | f | 12 | t - 364 | 14 | f | 13 | t - 365 | 14 | f | 14 | f - 366 | 14 | f | 15 | f - 367 | 14 | f | 16 | f - 368 | 14 | f | 17 | f - 369 | 14 | f | 18 | f - 370 | 14 | f | 19 | f - 371 | 14 | f | 20 | f - 372 | 14 | f | 21 | f - 373 | 14 | f | 22 | f - 374 | 14 | f | 23 | f - 375 | 14 | f | 24 | f - 376 | 14 | f | 25 | f - 377 | 14 | f | 26 | f - 378 | 14 | f | 27 | - 379 | 15 | f | 1 | t - 380 | 15 | f | 2 | t - 381 | 15 | f | 3 | t - 382 | 15 | f | 4 | t - 383 | 15 | f | 5 | t - 384 | 15 | f | 6 | t - 385 | 15 | f | 7 | t - 386 | 15 | f | 8 | t - 387 | 15 | f | 9 | t - 388 | 15 | f | 10 | t - 389 | 15 | f | 11 | t - 390 | 15 | f | 12 | t - 391 | 15 | f | 13 | t - 392 | 15 | f | 14 | f - 393 | 15 | f | 15 | f - 394 | 15 | f | 16 | f - 395 | 15 | f | 17 | f - 396 | 15 | f | 18 | f - 397 | 15 | f | 19 | f - 398 | 15 | f | 20 | f - 399 | 15 | f | 21 | f - 400 | 15 | f | 22 | f - 401 | 15 | f | 23 | f - 402 | 15 | f | 24 | f - 403 | 15 | f | 25 | f - 404 | 15 | f | 26 | f - 405 | 15 | f | 27 | - 406 | 16 | f | 1 | t - 407 | 16 | f | 2 | t - 408 | 16 | f | 3 | t - 409 | 16 | f | 4 | t - 410 | 16 | f | 5 | t - 411 | 16 | f | 6 | t - 412 | 16 | f | 7 | t - 413 | 16 | f | 8 | t - 414 | 16 | f | 9 | t - 415 | 16 | f | 10 | t - 416 | 16 | f | 11 | t - 417 | 16 | f | 12 | t - 418 | 16 | f | 13 | t - 419 | 16 | f | 14 | f - 420 | 16 | f | 15 | f - 421 | 16 | f | 16 | f - 422 | 16 | f | 17 | f - 423 | 16 | f | 18 | f - 424 | 16 | f | 19 | f - 425 | 16 | f | 20 | f - 426 | 16 | f | 21 | f - 427 | 16 | f | 22 | f - 428 | 16 | f | 23 | f - 429 | 16 | f | 24 | f - 430 | 16 | f | 25 | f - 431 | 16 | f | 26 | f - 432 | 16 | f | 27 | - 433 | 17 | f | 1 | t - 434 | 17 | f | 2 | t - 435 | 17 | f | 3 | t - 436 | 17 | f | 4 | t - 437 | 17 | f | 5 | t - 438 | 17 | f | 6 | t - 439 | 17 | f | 7 | t - 440 | 17 | f | 8 | t - 441 | 17 | f | 9 | t - 442 | 17 | f | 10 | t - 443 | 17 | f | 11 | t - 444 | 17 | f | 12 | t - 445 | 17 | f | 13 | t - 446 | 17 | f | 14 | f - 447 | 17 | f | 15 | f - 448 | 17 | f | 16 | f - 449 | 17 | f | 17 | f - 450 | 17 | f | 18 | f - 451 | 17 | f | 19 | f - 452 | 17 | f | 20 | f - 453 | 17 | f | 21 | f - 454 | 17 | f | 22 | f - 455 | 17 | f | 23 | f - 456 | 17 | f | 24 | f - 457 | 17 | f | 25 | f - 458 | 17 | f | 26 | f - 459 | 17 | f | 27 | - 460 | 18 | f | 1 | t - 461 | 18 | f | 2 | t - 462 | 18 | f | 3 | t - 463 | 18 | f | 4 | t - 464 | 18 | f | 5 | t - 465 | 18 | f | 6 | t - 466 | 18 | f | 7 | t - 467 | 18 | f | 8 | t - 468 | 18 | f | 9 | t - 469 | 18 | f | 10 | t - 470 | 18 | f | 11 | t - 471 | 18 | f | 12 | t - 472 | 18 | f | 13 | t - 473 | 18 | f | 14 | f - 474 | 18 | f | 15 | f - 475 | 18 | f | 16 | f - 476 | 18 | f | 17 | f - 477 | 18 | f | 18 | f - 478 | 18 | f | 19 | f - 479 | 18 | f | 20 | f - 480 | 18 | f | 21 | f - 481 | 18 | f | 22 | f - 482 | 18 | f | 23 | f - 483 | 18 | f | 24 | f - 484 | 18 | f | 25 | f - 485 | 18 | f | 26 | f - 486 | 18 | f | 27 | - 487 | 19 | f | 1 | t - 488 | 19 | f | 2 | t - 489 | 19 | f | 3 | t - 490 | 19 | f | 4 | t - 491 | 19 | f | 5 | t - 492 | 19 | f | 6 | t - 493 | 19 | f | 7 | t - 494 | 19 | f | 8 | t - 495 | 19 | f | 9 | t - 496 | 19 | f | 10 | t - 497 | 19 | f | 11 | t - 498 | 19 | f | 12 | t - 499 | 19 | f | 13 | t - 500 | 19 | f | 14 | f - 501 | 19 | f | 15 | f - 502 | 19 | f | 16 | f - 503 | 19 | f | 17 | f - 504 | 19 | f | 18 | f - 505 | 19 | f | 19 | f - 506 | 19 | f | 20 | f - 507 | 19 | f | 21 | f - 508 | 19 | f | 22 | f - 509 | 19 | f | 23 | f - 510 | 19 | f | 24 | f - 511 | 19 | f | 25 | f - 512 | 19 | f | 26 | f - 513 | 19 | f | 27 | - 514 | 20 | f | 1 | t - 515 | 20 | f | 2 | t - 516 | 20 | f | 3 | t - 517 | 20 | f | 4 | t - 518 | 20 | f | 5 | t - 519 | 20 | f | 6 | t - 520 | 20 | f | 7 | t - 521 | 20 | f | 8 | t - 522 | 20 | f | 9 | t - 523 | 20 | f | 10 | t - 524 | 20 | f | 11 | t - 525 | 20 | f | 12 | t - 526 | 20 | f | 13 | t - 527 | 20 | f | 14 | f - 528 | 20 | f | 15 | f - 529 | 20 | f | 16 | f - 530 | 20 | f | 17 | f - 531 | 20 | f | 18 | f - 532 | 20 | f | 19 | f - 533 | 20 | f | 20 | f - 534 | 20 | f | 21 | f - 535 | 20 | f | 22 | f - 536 | 20 | f | 23 | f - 537 | 20 | f | 24 | f - 538 | 20 | f | 25 | f - 539 | 20 | f | 26 | f - 540 | 20 | f | 27 | - 541 | 21 | f | 1 | t - 542 | 21 | f | 2 | t - 543 | 21 | f | 3 | t - 544 | 21 | f | 4 | t - 545 | 21 | f | 5 | t - 546 | 21 | f | 6 | t - 547 | 21 | f | 7 | t - 548 | 21 | f | 8 | t - 549 | 21 | f | 9 | t - 550 | 21 | f | 10 | t - 551 | 21 | f | 11 | t - 552 | 21 | f | 12 | t - 553 | 21 | f | 13 | t - 554 | 21 | f | 14 | f - 555 | 21 | f | 15 | f - 556 | 21 | f | 16 | f - 557 | 21 | f | 17 | f - 558 | 21 | f | 18 | f - 559 | 21 | f | 19 | f - 560 | 21 | f | 20 | f - 561 | 21 | f | 21 | f - 562 | 21 | f | 22 | f - 563 | 21 | f | 23 | f - 564 | 21 | f | 24 | f - 565 | 21 | f | 25 | f - 566 | 21 | f | 26 | f - 567 | 21 | f | 27 | - 568 | 22 | f | 1 | t - 569 | 22 | f | 2 | t - 570 | 22 | f | 3 | t - 571 | 22 | f | 4 | t - 572 | 22 | f | 5 | t - 573 | 22 | f | 6 | t - 574 | 22 | f | 7 | t - 575 | 22 | f | 8 | t - 576 | 22 | f | 9 | t - 577 | 22 | f | 10 | t - 578 | 22 | f | 11 | t - 579 | 22 | f | 12 | t - 580 | 22 | f | 13 | t - 581 | 22 | f | 14 | f - 582 | 22 | f | 15 | f - 583 | 22 | f | 16 | f - 584 | 22 | f | 17 | f - 585 | 22 | f | 18 | f - 586 | 22 | f | 19 | f - 587 | 22 | f | 20 | f - 588 | 22 | f | 21 | f - 589 | 22 | f | 22 | f - 590 | 22 | f | 23 | f - 591 | 22 | f | 24 | f - 592 | 22 | f | 25 | f - 593 | 22 | f | 26 | f - 594 | 22 | f | 27 | - 595 | 23 | f | 1 | t - 596 | 23 | f | 2 | t - 597 | 23 | f | 3 | t - 598 | 23 | f | 4 | t - 599 | 23 | f | 5 | t - 600 | 23 | f | 6 | t - 601 | 23 | f | 7 | t - 602 | 23 | f | 8 | t - 603 | 23 | f | 9 | t - 604 | 23 | f | 10 | t - 605 | 23 | f | 11 | t - 606 | 23 | f | 12 | t - 607 | 23 | f | 13 | t - 608 | 23 | f | 14 | f - 609 | 23 | f | 15 | f - 610 | 23 | f | 16 | f - 611 | 23 | f | 17 | f - 612 | 23 | f | 18 | f - 613 | 23 | f | 19 | f - 614 | 23 | f | 20 | f - 615 | 23 | f | 21 | f - 616 | 23 | f | 22 | f - 617 | 23 | f | 23 | f - 618 | 23 | f | 24 | f - 619 | 23 | f | 25 | f - 620 | 23 | f | 26 | f - 621 | 23 | f | 27 | - 622 | 24 | f | 1 | t - 623 | 24 | f | 2 | t - 624 | 24 | f | 3 | t - 625 | 24 | f | 4 | t - 626 | 24 | f | 5 | t - 627 | 24 | f | 6 | t - 628 | 24 | f | 7 | t - 629 | 24 | f | 8 | t - 630 | 24 | f | 9 | t - 631 | 24 | f | 10 | t - 632 | 24 | f | 11 | t - 633 | 24 | f | 12 | t - 634 | 24 | f | 13 | t - 635 | 24 | f | 14 | f - 636 | 24 | f | 15 | f - 637 | 24 | f | 16 | f - 638 | 24 | f | 17 | f - 639 | 24 | f | 18 | f - 640 | 24 | f | 19 | f - 641 | 24 | f | 20 | f - 642 | 24 | f | 21 | f - 643 | 24 | f | 22 | f - 644 | 24 | f | 23 | f - 645 | 24 | f | 24 | f - 646 | 24 | f | 25 | f - 647 | 24 | f | 26 | f - 648 | 24 | f | 27 | - 649 | 25 | f | 1 | t - 650 | 25 | f | 2 | t - 651 | 25 | f | 3 | t - 652 | 25 | f | 4 | t - 653 | 25 | f | 5 | t - 654 | 25 | f | 6 | t - 655 | 25 | f | 7 | t - 656 | 25 | f | 8 | t - 657 | 25 | f | 9 | t - 658 | 25 | f | 10 | t - 659 | 25 | f | 11 | t - 660 | 25 | f | 12 | t - 661 | 25 | f | 13 | t - 662 | 25 | f | 14 | f - 663 | 25 | f | 15 | f - 664 | 25 | f | 16 | f - 665 | 25 | f | 17 | f - 666 | 25 | f | 18 | f - 667 | 25 | f | 19 | f - 668 | 25 | f | 20 | f - 669 | 25 | f | 21 | f - 670 | 25 | f | 22 | f - 671 | 25 | f | 23 | f - 672 | 25 | f | 24 | f - 673 | 25 | f | 25 | f - 674 | 25 | f | 26 | f - 675 | 25 | f | 27 | - 676 | 26 | f | 1 | t - 677 | 26 | f | 2 | t - 678 | 26 | f | 3 | t - 679 | 26 | f | 4 | t - 680 | 26 | f | 5 | t - 681 | 26 | f | 6 | t - 682 | 26 | f | 7 | t - 683 | 26 | f | 8 | t - 684 | 26 | f | 9 | t - 685 | 26 | f | 10 | t - 686 | 26 | f | 11 | t - 687 | 26 | f | 12 | t - 688 | 26 | f | 13 | t - 689 | 26 | f | 14 | f - 690 | 26 | f | 15 | f - 691 | 26 | f | 16 | f - 692 | 26 | f | 17 | f - 693 | 26 | f | 18 | f - 694 | 26 | f | 19 | f - 695 | 26 | f | 20 | f - 696 | 26 | f | 21 | f - 697 | 26 | f | 22 | f - 698 | 26 | f | 23 | f - 699 | 26 | f | 24 | f - 700 | 26 | f | 25 | f - 701 | 26 | f | 26 | f - 702 | 26 | f | 27 | - 703 | 27 | | 1 | t - 704 | 27 | | 2 | t - 705 | 27 | | 3 | t - 706 | 27 | | 4 | t - 707 | 27 | | 5 | t - 708 | 27 | | 6 | t - 709 | 27 | | 7 | t - 710 | 27 | | 8 | t - 711 | 27 | | 9 | t - 712 | 27 | | 10 | t - 713 | 27 | | 11 | t - 714 | 27 | | 12 | t - 715 | 27 | | 13 | t - 716 | 27 | | 14 | f - 717 | 27 | | 15 | f - 718 | 27 | | 16 | f - 719 | 27 | | 17 | f - 720 | 27 | | 18 | f - 721 | 27 | | 19 | f - 722 | 27 | | 20 | f - 723 | 27 | | 21 | f - 724 | 27 | | 22 | f - 725 | 27 | | 23 | f - 726 | 27 | | 24 | f - 727 | 27 | | 25 | f - 728 | 27 | | 26 | f - 729 | 27 | | 27 | -(729 rows) - ---Testcase 60: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Unique - Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) - -> Foreign Scan on public."type_BOOLEAN_oper" - Output: b1, b2, (b1 AND b2), (b1 OR b2) - SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST -(5 rows) - ---Testcase 61: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; - b1 | b2 | a | o -----+----+---+--- - f | f | f | f - f | t | f | t - f | | f | - t | f | f | t - t | t | t | t - t | | | t - | f | f | - | t | | t - | | | -(9 rows) - ---Testcase 62: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Unique - Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) - -> Foreign Scan on public."type_BOOLEAN_oper" - Output: b1, b2, (b1 AND b2), (b1 OR b2) - SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" WHERE (sqlite_fdw_bool(`b1`)) AND (sqlite_fdw_bool(`b2`)) ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST -(5 rows) - ---Testcase 63: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; - b1 | b2 | a | o -----+----+---+--- - t | t | t | t -(1 row) - ---Testcase 64: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Unique - Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) - -> Foreign Scan on public."type_BOOLEAN_oper" - Output: b1, b2, (b1 AND b2), (b1 OR b2) - SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" WHERE ((sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`))) ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST -(5 rows) - ---Testcase 65: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; - b1 | b2 | a | o -----+----+---+--- - f | t | f | t - t | f | f | t - t | t | t | t - t | | | t - | t | | t -(5 rows) - ---Testcase 66: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------ - Update on public."type_BOOLEAN_oper" - -> Foreign Update on public."type_BOOLEAN_oper" - SQLite query: UPDATE main."type_BOOLEAN_oper" SET `b1` = NULL WHERE ((NOT sqlite_fdw_bool(`b1`))) -(3 rows) - ---Testcase 67: -UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; ---Testcase 68: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - b1 | b2 -----+---- - t | f - t | t - t | - | f - | t - | -(6 rows) - ---Testcase 69: -UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; ---Testcase 70: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Update on public."type_BOOLEAN_oper" - -> Foreign Update on public."type_BOOLEAN_oper" - SQLite query: UPDATE main."type_BOOLEAN_oper" SET `b1` = 0 WHERE ((sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`))) -(3 rows) - ---Testcase 71: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - b1 | b2 -----+---- - f | f - f | t - f | - | f - | -(5 rows) - ---Testcase 72: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Delete on public."type_BOOLEAN_oper" - -> Foreign Delete on public."type_BOOLEAN_oper" - SQLite query: DELETE FROM main."type_BOOLEAN_oper" WHERE ((NOT sqlite_fdw_bool(`b1`))) AND (sqlite_fdw_bool(`b2`)) -(3 rows) - ---Testcase 73: -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; ---Testcase 74: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - b1 | b2 -----+---- - f | f - f | - | f - | -(4 rows) - ---Testcase 75: -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b2; ---Testcase 76: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - b1 | b2 -----+---- - f | - | -(2 rows) - ---Testcase 77: -DELETE FROM "type_BOOLEAN_oper" WHERE b2; ---Testcase 78: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - b1 | b2 -----+---- - f | - | -(2 rows) - ---Testcase 003: -DROP EXTENSION sqlite_fdw CASCADE; -NOTICE: drop cascades to 6 other objects -DETAIL: drop cascades to server sqlite_svr -drop cascades to foreign table "type_BOOLEAN" -drop cascades to foreign table "type_BOOLEAN+" -drop cascades to foreign table "type_BOOLEANpk" -drop cascades to foreign table "type_BOOLEAN_oper" -drop cascades to server sqlite2 diff --git a/expected/16.0/extra/out_of_range.out b/expected/16.0/extra/out_of_range.out deleted file mode 100644 index 8de68b14..00000000 --- a/expected/16.0/extra/out_of_range.out +++ /dev/null @@ -1,172 +0,0 @@ --- --- INT4 + INT2 --- ---Testcase 001: -CREATE EXTENSION sqlite_fdw; ---Testcase 002: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 01: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 02: -CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 03: -DELETE FROM INT4_TMP; ---Testcase 04: -ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int8; ---Testcase 05: -INSERT INTO INT4_TMP VALUES (x'7FFFFFFF'::int8 + 1, 0); ---Testcase 06: -ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int4; ---Testcase 07: -SELECT * FROM INT4_TMP; -- overflow -ERROR: integer out of range -HINT: SQLite value with "integer" affinity : 2147483648 -CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 08: -SELECT f1 FROM INT4_TMP; -- overflow -ERROR: integer out of range -HINT: SQLite value with "integer" affinity : 2147483648 -CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 09: -DELETE FROM INT4_TMP; ---Testcase 10: -ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int8; ---Testcase 11: -INSERT INTO INT4_TMP VALUES (-(x'7FFFFFFF'::int8) - 2, 0); ---Testcase 12: -ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int4; ---Testcase 13: -SELECT * FROM INT4_TMP; -- overflow -ERROR: integer out of range -HINT: SQLite value with "integer" affinity : -2147483649 -CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 14: -SELECT f1 FROM INT4_TMP; -- overflow -ERROR: integer out of range -HINT: SQLite value with "integer" affinity : -2147483649 -CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 15: -CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 16: -CREATE FOREIGN TABLE INT2_TMP(f1 int2, f2 int2, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 17: -DELETE FROM INT2_TMP; ---Testcase 18: -ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int4; ---Testcase 19: -INSERT INTO INT2_TMP VALUES (x'7FFF'::int8 + 1, 0); ---Testcase 20: -ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int2; ---Testcase 21: -SELECT * FROM INT2_TMP; -- overflow -ERROR: smallint out of range -HINT: SQLite value with "integer" affinity : 32768 -CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 22: -SELECT f1 FROM INT2_TMP; -- overflow -ERROR: smallint out of range -HINT: SQLite value with "integer" affinity : 32768 -CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 23: -DELETE FROM INT2_TMP; ---Testcase 24: -ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int4; ---Testcase 25: -INSERT INTO INT2_TMP VALUES (-(x'7FFF'::int8) - 2, 0); ---Testcase 26: -ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int2; ---Testcase 27: -SELECT * FROM INT2_TMP; -- overflow -ERROR: smallint out of range -HINT: SQLite value with "integer" affinity : -32769 -CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 28: -SELECT f1 FROM INT2_TMP; -- overflow -ERROR: smallint out of range -HINT: SQLite value with "integer" affinity : -32769 -CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 29: -CREATE FOREIGN TABLE INT8_TBL(q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 31: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; ---Testcase 32: -INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); ---Testcase 33: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; ---Testcase 34: -SELECT * FROM INT8_TBL; -- NO overflow - q1 | q2 -----------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 - -9223372036854775808 | 0 -(6 rows) - ---Testcase 35: -SELECT q1 FROM INT8_TBL; -- NO overflow - q1 ----------------------- - 123 - 123 - 4567890123456789 - 4567890123456789 - 4567890123456789 - -9223372036854775808 -(6 rows) - ---Testcase 36: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; ---Testcase 37: -DELETE FROM INT8_TBL WHERE q1 = -9223372036854775810; ---Testcase 38: -INSERT INTO INT8_TBL VALUES (9223372036854775809, 0); ---Testcase 39: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; ---Testcase 40: -SELECT * FROM INT8_TBL; -- overflow -ERROR: bigint out of range -HINT: SQLite value with "real" affinity : 9.22337203685478e+18 -CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 41: -SELECT q1 FROM INT8_TBL; -- overflow -ERROR: bigint out of range -HINT: SQLite value with "real" affinity : 9.22337203685478e+18 -CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 42: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; ---Testcase 43: -DELETE FROM INT8_TBL WHERE q1 = 9223372036854775809; ---Testcase 44: -INSERT INTO INT8_TBL VALUES (10 * -9223372036854775810, 0); ---Testcase 45: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; ---Testcase 46: -SELECT * FROM INT8_TBL; -- overflow -ERROR: bigint out of range -HINT: SQLite value with "real" affinity : -9.22337203685478e+19 -CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 47: -SELECT q1 FROM INT8_TBL; -- overflow -ERROR: bigint out of range -HINT: SQLite value with "real" affinity : -9.22337203685478e+19 -CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table ---Testcase 48: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; ---Testcase 49: -DELETE FROM INT8_TBL WHERE q1 = 10 * -9223372036854775810; ---Testcase 50: -ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; ---Testcase 003: -DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 5 other objects -DETAIL: drop cascades to foreign table int4_tbl -drop cascades to foreign table int4_tmp -drop cascades to foreign table int2_tbl -drop cascades to foreign table int2_tmp -drop cascades to foreign table int8_tbl ---Testcase 004: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/16.0/type.out b/expected/16.0/type.out deleted file mode 100644 index d23c7be1..00000000 --- a/expected/16.0/type.out +++ /dev/null @@ -1,603 +0,0 @@ ---SET log_min_messages TO DEBUG1; ---SET client_min_messages TO DEBUG1; ---Testcase 44: -CREATE EXTENSION sqlite_fdw; ---Testcase 45: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); ---Testcase 46: -CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO public; ---Testcase 1: -INSERT INTO "type_STRING"(col) VALUES ('string'); ---Testcase 4: -INSERT INTO "type_BYTE"(col) VALUES ('c'); ---Testcase 5: -INSERT INTO "type_SINT"(col) VALUES (32767); ---Testcase 6: -INSERT INTO "type_SINT"(col) VALUES (-32768); ---Testcase 7: -INSERT INTO "type_BINT"(col) VALUES (9223372036854775807); ---Testcase 8: -INSERT INTO "type_BINT"(col) VALUES (-9223372036854775808); ---Testcase 9: -INSERT INTO "type_INTEGER"(col) VALUES (9223372036854775807); ---Testcase 10: -INSERT INTO "type_FLOAT"(col) VALUES (3.1415); ---Testcase 11: -INSERT INTO "type_DOUBLE"(col) VALUES (3.14159265); ---Testcase 12: -INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 12:34:56.789', '2017.11.06'); ---Testcase 13: -INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 1:3:0', '2017.11.07'); ---Testcase 14: -INSERT INTO "type_BLOB"(col) VALUES (bytea('\xDEADBEEF')); ---Testcase 15: -INSERT INTO typetest VALUES(1,'a', 'b', 'c','2017.11.06 12:34:56.789', '2017.11.06 12:34:56.789' ) ; ---Testcase 16: -SELECT * FROM "type_STRING"; - col --------- - string -(1 row) - ---Testcase 18: -SELECT * FROM "type_BYTE"; - col ------ - c -(1 row) - ---Testcase 19: -SELECT * FROM "type_SINT"; - col --------- - 32767 - -32768 -(2 rows) - ---Testcase 20: -SELECT * FROM "type_BINT"; - col ----------------------- - 9223372036854775807 - -9223372036854775808 -(2 rows) - ---Testcase 21: -SELECT * FROM "type_INTEGER"; - col ---------------------- - 9223372036854775807 -(1 row) - ---Testcase 22: -SELECT * FROM "type_FLOAT"; - col --------- - 3.1415 -(1 row) - ---Testcase 23: -SELECT * FROM "type_DOUBLE"; - col ------------- - 3.14159265 -(1 row) - -set datestyle=ISO; ---Testcase 24: -SELECT * FROM "type_TIMESTAMP"; - col | b --------------------------+--------------------- - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 - 2017-11-06 01:03:00 | 2017-11-07 00:00:00 -(2 rows) - ---Testcase 25: -SELECT * FROM "type_BLOB"; - col ------------- - \xdeadbeef -(1 row) - ---Testcase 26: -SELECT * FROM typetest; - i | v | c | t | d | ti ----+---+------------+---+-------------------------+------------------------- - 1 | a | b | c | 2017-11-06 12:34:56.789 | 2017-11-06 12:34:56.789 -(1 row) - ---Testcase 27: -insert into "type_STRING" values('TYPE'); ---Testcase 28: -insert into "type_STRING" values('type'); --- not pushdown ---Testcase 29: -SELECT *FROM "type_STRING" WHERE col like 'TYP%'; - col ------- - TYPE -(1 row) - ---Testcase 30: -EXPLAIN SELECT *FROM "type_STRING" WHERE col like 'TYP%'; - QUERY PLAN -------------------------------------------------------------------- - Foreign Scan on "type_STRING" (cost=10.00..7.00 rows=7 width=32) -(1 row) - --- pushdown ---Testcase 31: -SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; - col ------- - TYPE - type -(2 rows) - ---Testcase 32: -EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; - QUERY PLAN ---------------------------------------------------------------------- - Foreign Scan on "type_STRING" (cost=10.00..58.00 rows=58 width=32) - Filter: (col ~~* 'typ%'::text) -(2 rows) - ---Testcase 33: -SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; - col ------- - TYPE -(1 row) - ---Testcase 34: -EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; - QUERY PLAN -------------------------------------------------------------------- - Foreign Scan on "type_STRING" (cost=10.00..1.00 rows=1 width=32) - Filter: (col ~~* 'typ%'::text) -(2 rows) - ---Testcase 35: -SELECT * FROM "type_TIMESTAMP"; - col | b --------------------------+--------------------- - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 - 2017-11-06 01:03:00 | 2017-11-07 00:00:00 -(2 rows) - ---Testcase 36: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; - QUERY PLAN ---------------------------------------------------------------------------------------------- - Foreign Scan on public."type_TIMESTAMP" - Output: col, b - SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" WHERE ((`col` > '2017-11-06')) -(3 rows) - ---Testcase 37: -SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; - col | b --------------------------+--------------------- - 2017-11-06 01:03:00 | 2017-11-07 00:00:00 - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 -(2 rows) - ---Testcase 38: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; - QUERY PLAN ------------------------------------------------------------------------ - Foreign Scan on public."type_TIMESTAMP" - Output: col, b - Filter: (("type_TIMESTAMP".col)::text > ('2017-11-06'::date)::text) - SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" -(4 rows) - ---Testcase 39: -SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; - col | b --------------------------+--------------------- - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 - 2017-11-06 01:03:00 | 2017-11-07 00:00:00 -(2 rows) - ---Testcase 40: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; - QUERY PLAN --------------------------------------------------------------------------------- - Foreign Scan on public."type_TIMESTAMP" - Output: col, b - Filter: ("type_TIMESTAMP".col > ("type_TIMESTAMP".b - '@ 1 hour'::interval)) - SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" -(4 rows) - ---Testcase 41: -SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; - col | b --------------------------+--------------------- - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 -(1 row) - ---Testcase 42: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b; - QUERY PLAN ------------------------------------------------------------------------------------- - Foreign Scan on public."type_TIMESTAMP" - Output: col, b - SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" WHERE ((`col` > `b`)) -(3 rows) - ---Testcase 43: -SELECT * FROM "type_TIMESTAMP" WHERE col > b; - col | b --------------------------+--------------------- - 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 -(1 row) - ---Testcase 48: -INSERT INTO "type_DATE"(col) VALUES ('2021.02.23'); ---Testcase 49: -INSERT INTO "type_DATE"(col) VALUES ('2021/03/08'); ---Testcase 50: -INSERT INTO "type_DATE"(col) VALUES ('9999-12-30'); ---Testcase 58: -SELECT * FROM "type_DATE"; - col ------------- - 2021-02-23 - 2021-03-08 - 9999-12-30 -(3 rows) - ---Testcase 51: -INSERT INTO "type_TIME"(col) VALUES ('01:23:45'); ---Testcase 52: -INSERT INTO "type_TIME"(col) VALUES ('01:23:45.6789'); ---Testcase 59: -SELECT * FROM "type_TIME"; - col ---------------- - 01:23:45 - 01:23:45.6789 -(2 rows) - ---Testcase 60: -EXPLAIN VERBOSE -SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Foreign Scan on public.alltypetest (cost=10.00..57.00 rows=57 width=1400) - Output: c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 - SQLite query: SELECT `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`, `c9`, `c10`, `c11`, `c12`, `c13`, `c14`, `c15`, sqlite_fdw_float(`c17`), sqlite_fdw_float(`c18`), sqlite_fdw_float(`c19`), sqlite_fdw_float(`c21`), sqlite_fdw_float(`c22`), `c23`, `c24` FROM main."alltypetest" -(3 rows) - ---Testcase 61: -SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | c17 | c18 | c19 | c2 | c21 | c22 | c23 | c24 ---------+-----+-------+--------+---------------+--------------+---------------+------------+----------------------+------------------------+---------------------+------------------+-------------------------------------------+-----------------------------+--------------------------+---------+--------------+-------------+-----+------+-------------+------------+--------------------- - 583647 | 127 | 12767 | 388607 | 2036854775807 | 573709551615 | 2036854775807 | abcdefghij | abcdefghijjhgfjfuafh | Côte dIvoire Fijifoxju | Hôm nay tôi rất vui | I am happy today | 今日はとても幸せです 今日はとても幸せです | The quick brown fox jumps o | ABCDEFGHIJKLMNOPQRSTUVWX | 3.4e+18 | 1.79769e+108 | 1.79769e+88 | 127 | 1234 | 99999.99999 | 9999-12-31 | 9999-12-31 23:59:59 -(1 row) - ---Testcase 53: -CREATE FOREIGN TABLE type_JSON(col JSON OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'type_TEXT'); ---Testcase 54: -INSERT INTO type_JSON(col) VALUES ('[1, 2, "foo", null]'); ---Testcase 55: -INSERT INTO type_JSON(col) VALUES ('{"bar": "baz", "balance": 7.77, "active": false}'::json); ---Testcase 56 -SELECT * FROM type_JSON; - col --------------------------------------------------- - [1, 2, "foo", null] - {"bar": "baz", "balance": 7.77, "active": false} -(2 rows) - ---Testcase 57 -DELETE FROM type_JSON; ---Testcase 62: -DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; ---Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; ---Testcase 64: -ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; ---Testcase 65: -SELECT * FROM "type_BOOLEAN"; -- OK - b ---- - t - f - t - f - t - f - t - t - t - f - f - f - f - f - t - t - t - t - t - t - f - f - f - t - -(25 rows) - --- define INTEGER as TEXT column ---Testcase 67: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE text; ---Testcase 68: -SELECT * FROM "type_INTEGER"; -- OK - col ---------------------- - 9223372036854775807 -(1 row) - --- define INTEGER as bpchar ---Testcase 69: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE char(30); ---Testcase 70: -SELECT * FROM "type_INTEGER"; -- OK - col --------------------------------- - 9223372036854775807 -(1 row) - --- define INTEGER as varchar ---Testcase 71: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE varchar(30); ---Testcase 72: -SELECT * FROM "type_INTEGER"; -- OK - col ---------------------- - 9223372036854775807 -(1 row) - --- define INTEGER as name ---Testcase 73: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE name; ---Testcase 74: -SELECT * FROM "type_INTEGER"; -- OK - col ---------------------- - 9223372036854775807 -(1 row) - --- define INTEGER as json ---Testcase 75: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE json; ---Testcase 76: -SELECT * FROM "type_INTEGER"; -- OK - col ---------------------- - 9223372036854775807 -(1 row) - --- define INTEGER as time ---Testcase 77: -DELETE FROM "type_INTEGER"; ---Testcase 78: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; ---Testcase 79: -INSERT INTO "type_INTEGER" VALUES (120506); ---Testcase 80: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE time; ---Testcase 81: -SELECT * FROM "type_INTEGER"; -- OK - col ----------- - 12:05:06 -(1 row) - --- define INTEGER as date ---Testcase 82: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE date; ---Testcase 83: -SELECT * FROM "type_INTEGER"; -- OK - col ------------- - 2012-05-06 -(1 row) - ---Testcase 84: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; ---Testcase 85: -INSERT INTO "type_DOUBLE" VALUES (1.3e-5); ---Testcase 86: -SELECT * FROM "type_DOUBLE"; - col ------------- - 3.14159265 - 1.3e-05 -(2 rows) - --- define DOUBLE as TEXT column ---Testcase 87: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE text; ---Testcase 88: -SELECT * FROM "type_DOUBLE"; -- OK - col ------------- - 3.14159265 - 1.3e-05 -(2 rows) - --- define DOUBLE as bpchar ---Testcase 89: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE char(30); ---Testcase 90: -SELECT * FROM "type_DOUBLE"; -- OK - col --------------------------------- - 3.14159265 - 1.3e-05 -(2 rows) - --- define DOUBLE as varchar ---Testcase 91: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE varchar(30); ---Testcase 92: -SELECT * FROM "type_DOUBLE"; -- OK - col ------------- - 3.14159265 - 1.3e-05 -(2 rows) - --- define DOUBLE as name ---Testcase 93: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE name; ---Testcase 94: -SELECT * FROM "type_DOUBLE"; -- OK - col ------------- - 3.14159265 - 1.3e-05 -(2 rows) - --- define DOUBLE as json ---Testcase 95: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE json; ---Testcase 96: -SELECT * FROM "type_DOUBLE"; -- OK - col ------------- - 3.14159265 - 1.3e-05 -(2 rows) - ---Testcase 97: -DELETE FROM "type_DOUBLE"; ---Testcase 98: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; ---Testcase 99: -INSERT INTO "type_DOUBLE" VALUES (120506.12); --- define DOUBLE as time ---Testcase 100: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE time; ---Testcase 101: -SELECT * FROM "type_DOUBLE"; -- OK - col -------------- - 12:05:06.12 -(1 row) - ---Testcase 102: -DELETE FROM "type_DOUBLE"; ---Testcase 103: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; ---Testcase 104: -INSERT INTO "type_DOUBLE" VALUES (1999.012); --- define DOUBLE as date ---Testcase 105: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE date; ---Testcase 106: -SELECT * FROM "type_DOUBLE"; -- OK - col ------------- - 1999-01-12 -(1 row) - ---Testcase 107: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; ---Testcase 108: -INSERT INTO "type_DOUBLE" VALUES (PI()); ---Testcase 109: ERR primary key -INSERT INTO "type_DOUBLE" VALUES (PI()); -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) ---Testcase 110: -INSERT INTO "type_DOUBLE" VALUES ('Infinity'); ---Testcase 111: -INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); ---Testcase 113: -SELECT * FROM "type_DOUBLE"; -- OK, +- Inf - col -------------------- - 1999.012 - 3.141592653589793 - Infinity - -Infinity -(4 rows) - ---Testcase 114: ERR primary key -INSERT INTO "type_DOUBLE" VALUES ('Infinity'); -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) ---Testcase 115: ERR primary key -INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); -ERROR: Failed to execute remote SQL -HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 -CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) ---Testcase 116: -SELECT * FROM "type_DOUBLE"; -- OK, +- Inf - col -------------------- - 1999.012 - 3.141592653589793 - Infinity - -Infinity -(4 rows) - ---Testcase 47: -DROP EXTENSION sqlite_fdw CASCADE; -NOTICE: drop cascades to 48 other objects -DETAIL: drop cascades to server sqlite_svr -drop cascades to foreign table department -drop cascades to foreign table employee -drop cascades to foreign table empdata -drop cascades to foreign table numbers -drop cascades to foreign table t -drop cascades to foreign table multiprimary -drop cascades to foreign table columntest -drop cascades to foreign table noprimary -drop cascades to foreign table limittest -drop cascades to foreign table grem1_1 -drop cascades to foreign table grem1_2 -drop cascades to foreign table case_exp -drop cascades to foreign table "type_STRING" -drop cascades to foreign table "type_BOOLEANpk" -drop cascades to foreign table "type_BYTE" -drop cascades to foreign table "type_SINT" -drop cascades to foreign table "type_BINT" -drop cascades to foreign table "type_INTEGER" -drop cascades to foreign table "type_FLOAT" -drop cascades to foreign table "type_DOUBLE" -drop cascades to foreign table "type_TIMESTAMP" -drop cascades to foreign table "type_BLOB" -drop cascades to foreign table "type_DATE" -drop cascades to foreign table "type_TIME" -drop cascades to foreign table "type_BIT" -drop cascades to foreign table "type_VARBIT" -drop cascades to foreign table "type_UUIDpk" -drop cascades to foreign table "type_UUID" -drop cascades to foreign table "BitT" -drop cascades to foreign table notype -drop cascades to foreign table typetest -drop cascades to foreign table "type_TEXT" -drop cascades to foreign table alltypetest -drop cascades to foreign table shorty -drop cascades to foreign table "A a" -drop cascades to foreign table fts_table -drop cascades to foreign table fts_table_data -drop cascades to foreign table fts_table_idx -drop cascades to foreign table fts_table_content -drop cascades to foreign table fts_table_docsize -drop cascades to foreign table fts_table_config -drop cascades to foreign table "RO_RW_test" -drop cascades to foreign table "Unicode data" -drop cascades to foreign table "type_BOOLEAN_oper" -drop cascades to foreign table type_json -drop cascades to foreign table "type_BOOLEAN" -drop cascades to server sqlite2 diff --git a/expected/16.0/aggregate.out b/expected/16.3/aggregate.out similarity index 100% rename from expected/16.0/aggregate.out rename to expected/16.3/aggregate.out diff --git a/expected/16.0/extra/aggregates.out b/expected/16.3/extra/aggregates.out similarity index 98% rename from expected/16.0/extra/aggregates.out rename to expected/16.3/extra/aggregates.out index 5127cc38..f685392e 100644 --- a/expected/16.0/extra/aggregates.out +++ b/expected/16.3/extra/aggregates.out @@ -61,8 +61,28 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 697: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 698: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 699: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 700: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 701: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 702: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 703: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 704: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 705: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 706: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; --Testcase 275: @@ -86,44 +106,44 @@ SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100; 32.6666666666667 (1 row) ---Testcase 697: +--Testcase 707: CREATE FOREIGN TABLE agg_tb(v int, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 698: +--Testcase 708: INSERT INTO agg_tb(v) VALUES(1), (2), (3); ---Testcase 699: -- Pg 16+ +--Testcase 709: -- Pg 16+ SELECT any_value(v) FROM agg_tb; any_value ----------- 1 (1 row) ---Testcase 700: +--Testcase 710: DELETE FROM agg_tb; ---Testcase 701: +--Testcase 711: INSERT INTO agg_tb(v) VALUES (NULL); ---Testcase 702: -- Pg 16+ +--Testcase 712: -- Pg 16+ SELECT any_value(v) FROM agg_tb; any_value ----------- (1 row) ---Testcase 703: +--Testcase 713: DELETE FROM agg_tb; ---Testcase 704: +--Testcase 714: INSERT INTO agg_tb(v) VALUES (NULL), (1), (2); ---Testcase 705: -- Pg 16+ +--Testcase 715: -- Pg 16+ SELECT any_value(v) FROM agg_tb; any_value ----------- 1 (1 row) ---Testcase 706: +--Testcase 716: CREATE FOREIGN TABLE agg_tb2(v text) SERVER sqlite_svr; ---Testcase 707: +--Testcase 717: INSERT INTO agg_tb2(v) VALUES (array['hello', 'world']); ---Testcase 708: -- Pg 16+ +--Testcase 718: -- Pg 16+ SELECT any_value(v) FROM agg_tb2; any_value --------------- @@ -1731,6 +1751,7 @@ select (select max(min(unique1)) from int8_tbl) from tenk1; ERROR: aggregate function calls cannot be nested LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1; ^ +--Testcase 719: select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) from tenk1 a1(col1))) from tenk1 a2(col2); @@ -1859,6 +1880,7 @@ ERROR: column "t1.f1" must appear in the GROUP BY clause or be used in an aggre LINE 1: select t1.f1 from t1 left join t2 using (f1) group by f1; ^ -- check case where we have to inject nullingrels into coerced join alias +--Testcase 720: select f1, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) group by f1; @@ -1867,6 +1889,7 @@ group by f1; (0 rows) -- same, for a RelabelType coercion +--Testcase 721: select f2, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) group by f2; @@ -1880,6 +1903,7 @@ drop foreign table t1, t2; -- Test planner's selection of pathkeys for ORDER BY aggregates -- -- Ensure we order by four. This suits the most aggregate functions. +--Testcase 722: explain (costs off) select sum(two order by two),max(four order by four), min(four order by four) from tenk1; @@ -1891,6 +1915,7 @@ from tenk1; -- Ensure we order by two. It's a tie between ordering by two and four but -- we tiebreak on the aggregate's position. +--Testcase 723: explain (costs off) select sum(two order by two), max(four order by four), @@ -1903,6 +1928,7 @@ from tenk1; (2 rows) -- Similar to above, but tiebreak on ordering by four +--Testcase 724: explain (costs off) select max(four order by four), sum(two order by two), @@ -1916,6 +1942,7 @@ from tenk1; -- Ensure this one orders by ten since there are 3 aggregates that require ten -- vs two that suit two and four. +--Testcase 725: explain (costs off) select max(four order by four), sum(two order by two), @@ -1931,6 +1958,7 @@ from tenk1; -- Try a case involving a GROUP BY clause where the GROUP BY column is also -- part of an aggregate's ORDER BY clause. We want a sort order that works -- for the GROUP BY along with the first and the last aggregate. +--Testcase 726: explain (costs off) select sum(unique1 order by ten, two), sum(unique1 order by four), @@ -1947,6 +1975,7 @@ group by ten; -- Ensure that we never choose to provide presorted input to an Aggref with -- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure -- these sorts are performed individually rather than at the query level. +--Testcase 727: explain (costs off) select sum(unique1 order by two), sum(unique1 order by four), @@ -1962,8 +1991,9 @@ group by ten; (3 rows) -- Ensure consecutive NULLs are properly treated as distinct from each other +--Testcase 728: select array_agg(distinct val) -from (select null as val from generate_series(1, 2)) g; +from (select null as val from generate_series(1, 2)); array_agg ----------- {NULL} @@ -1971,6 +2001,7 @@ from (select null as val from generate_series(1, 2)) g; -- Ensure no ordering is requested when enable_presorted_aggregate is off set enable_presorted_aggregate to off; +--Testcase 729: explain (costs off) select sum(two order by two) from tenk1; QUERY PLAN @@ -2425,7 +2456,9 @@ select string_agg(v, decode('ee', 'hex')) from bytea_test_table; --Testcase 447: drop foreign table bytea_test_table; -- Test parallel string_agg and array_agg +--Testcase 730: create foreign table pagg_test (x int, y int) server sqlite_svr; +--Testcase 731: insert into pagg_test select (case x % 4 when 1 then null else x end), x % 10 from generate_series(1,5000) x; @@ -2436,6 +2469,7 @@ set min_parallel_table_scan_size = 0; set bytea_output = 'escape'; set max_parallel_workers_per_gather = 2; -- create a view as we otherwise have to repeat this query a few times. +--Testcase 732: create view v_pagg_test AS select y, @@ -2463,6 +2497,7 @@ from ( ) a2 group by y; -- Ensure results are correct. +--Testcase 733: select * from v_pagg_test order by y; y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- @@ -2479,6 +2514,7 @@ select * from v_pagg_test order by y; (10 rows) -- Ensure parallel aggregation is actually being used. +--Testcase 734: explain (costs off) select * from v_pagg_test order by y; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------- @@ -2495,6 +2531,7 @@ explain (costs off) select * from v_pagg_test order by y; set max_parallel_workers_per_gather = 0; -- Ensure results are the same without parallel aggregation. +--Testcase 735: select * from v_pagg_test order by y; y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- @@ -2517,7 +2554,9 @@ reset min_parallel_table_scan_size; reset parallel_leader_participation; reset parallel_tuple_cost; reset parallel_setup_cost; +--Testcase 736: drop view v_pagg_test; +--Testcase 737: drop foreign table pagg_test; -- FILTER tests --Testcase 158: @@ -2576,8 +2615,11 @@ from agg_t17; a (1 row) +--Testcase 738: create foreign table agg_t170(v int) server sqlite_svr; +--Testcase 739: insert into agg_t170(v) values (1), (2), (3); +--Testcase 740: select any_value(v) filter (where v > 2) from agg_t170; any_value ----------- @@ -3519,12 +3561,14 @@ CREATE AGGREGATE balk(int4) ROLLBACK; -- test multiple usage of an aggregate whose finalfn returns a R/W datum BEGIN; +--Testcase 741: CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN RETURN array_fill(y[1], ARRAY[4]); END; $$; +--Testcase 742: CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray LANGUAGE plpgsql STRICT IMMUTABLE AS $$ DECLARE @@ -3535,11 +3579,13 @@ BEGIN RETURN res; END; $$; +--Testcase 743: CREATE AGGREGATE rwagg(anyarray) ( STYPE = anyarray, SFUNC = rwagg_sfunc, FINALFUNC = rwagg_finalfunc ); +--Testcase 744: CREATE FUNCTION eatarray(x real[]) RETURNS real[] LANGUAGE plpgsql STRICT IMMUTABLE AS $$ BEGIN @@ -3547,8 +3593,11 @@ BEGIN RETURN x; END; $$; +--Testcase 745: CREATE FOREIGN TABLE float_tb(f real) SERVER sqlite_svr; +--Testcase 746: INSERT INTO float_tb(f) VALUES (1.0); +--Testcase 747: SELECT eatarray(rwagg(ARRAY[f::real])), eatarray(rwagg(ARRAY[f::real])) FROM float_tb; eatarray | eatarray -----------+----------- @@ -3957,6 +4006,10 @@ set work_mem to default; ----+----+---- (0 rows) +--Testcase 748: +DELETE FROM INT4_TBL; +--Testcase 749: +DELETE FROM INT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/15.4/extra/bitstring.out b/expected/16.3/extra/bitstring.out similarity index 100% rename from expected/15.4/extra/bitstring.out rename to expected/16.3/extra/bitstring.out diff --git a/expected/13.12/extra/bool.out b/expected/16.3/extra/bool.out similarity index 99% rename from expected/13.12/extra/bool.out rename to expected/16.3/extra/bool.out index ec908ab6..ccb740e5 100644 --- a/expected/13.12/extra/bool.out +++ b/expected/16.3/extra/bool.out @@ -1263,6 +1263,8 @@ SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; | (2 rows) +--Testcase 79: +DELETE FROM "type_BOOLEAN"; --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; NOTICE: drop cascades to 6 other objects diff --git a/expected/15.4/extra/encodings.out b/expected/16.3/extra/encodings.out similarity index 100% rename from expected/15.4/extra/encodings.out rename to expected/16.3/extra/encodings.out diff --git a/expected/16.0/extra/float4.out b/expected/16.3/extra/float4.out similarity index 100% rename from expected/16.0/extra/float4.out rename to expected/16.3/extra/float4.out diff --git a/expected/16.0/extra/float8.out b/expected/16.3/extra/float8.out similarity index 99% rename from expected/16.0/extra/float8.out rename to expected/16.3/extra/float8.out index a6d2f712..aff54f77 100644 --- a/expected/16.0/extra/float8.out +++ b/expected/16.3/extra/float8.out @@ -2014,6 +2014,8 @@ drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 drop cascades to cast from xfloat8 to bigint drop cascades to cast from bigint to xfloat8 +--Testcase 363: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/16.0/extra/insert.out b/expected/16.3/extra/insert.out similarity index 100% rename from expected/16.0/extra/insert.out rename to expected/16.3/extra/insert.out diff --git a/expected/16.0/extra/int4.out b/expected/16.3/extra/int4.out similarity index 94% rename from expected/16.0/extra/int4.out rename to expected/16.3/extra/int4.out index 448e7481..f623f8c3 100644 --- a/expected/16.0/extra/int4.out +++ b/expected/16.3/extra/int4.out @@ -75,26 +75,32 @@ SELECT * FROM INT4_TBL; (5 rows) -- Also try it with non-error-throwing API +--Testcase 137: CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 138: INSERT INTO NON_ERROR_THROWING_API_INT4 VALUES ('34', 1), ('asdf', 2), ('1000000000000', 3); +--Testcase 139: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 1; pg_input_is_valid ------------------- t (1 row) +--Testcase 140: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 2; pg_input_is_valid ------------------- f (1 row) +--Testcase 141: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3; pg_input_is_valid ------------------- f (1 row) +--Testcase 142: SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3), 'int4'); message | detail | hint | sql_error_code --------------------------------------------------------+--------+------+---------------- @@ -639,204 +645,273 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow ERROR: integer out of range -- non-decimal literals +--Testcase 143: CREATE FOREIGN TABLE special_case_int4 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 144: INSERT INTO special_case_int4 VALUES ('0b100101'::int4); +--Testcase 145: SELECT f1 FROM special_case_int4; f1 ---- 37 (1 row) +--Testcase 146: DELETE FROM special_case_int4; +--Testcase 147: INSERT INTO special_case_int4 VALUES ('0o273'::int4); +--Testcase 148: SELECT f1 FROM special_case_int4; f1 ----- 187 (1 row) +--Testcase 149: DELETE FROM special_case_int4; +--Testcase 150: INSERT INTO special_case_int4 VALUES ('0x42F'::int4); +--Testcase 151: SELECT f1 FROM special_case_int4; f1 ------ 1071 (1 row) +--Testcase 152: DELETE FROM special_case_int4; +--Testcase 153: INSERT INTO special_case_int4 VALUES ('0b'::int4); ERROR: invalid input syntax for type integer: "0b" LINE 1: INSERT INTO special_case_int4 VALUES ('0b'::int4); ^ +--Testcase 154: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 155: DELETE FROM special_case_int4; +--Testcase 156: INSERT INTO special_case_int4 VALUES ('0x'::int4); ERROR: invalid input syntax for type integer: "0x" LINE 1: INSERT INTO special_case_int4 VALUES ('0x'::int4); ^ +--Testcase 157: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 158: DELETE FROM special_case_int4; +--Testcase 159: INSERT INTO special_case_int4 VALUES ('0x'::int4); ERROR: invalid input syntax for type integer: "0x" LINE 1: INSERT INTO special_case_int4 VALUES ('0x'::int4); ^ +--Testcase 160: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) -- cases near overflow +--Testcase 161: DELETE FROM special_case_int4; +--Testcase 162: INSERT INTO special_case_int4 VALUES ('0b1111111111111111111111111111111'::int4); +--Testcase 163: SELECT f1 FROM special_case_int4; f1 ------------ 2147483647 (1 row) +--Testcase 164: DELETE FROM special_case_int4; +--Testcase 165: INSERT INTO special_case_int4 VALUES ('0b10000000000000000000000000000000'::int4); ERROR: value "0b10000000000000000000000000000000" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('0b1000000000000000000... ^ +--Testcase 166: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 167: DELETE FROM special_case_int4; +--Testcase 168: INSERT INTO special_case_int4 VALUES ('0o17777777777'::int4); +--Testcase 169: SELECT f1 FROM special_case_int4; f1 ------------ 2147483647 (1 row) +--Testcase 170: DELETE FROM special_case_int4; +--Testcase 171: INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4); ERROR: value "0o20000000000" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4)... ^ +--Testcase 172: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 173: DELETE FROM special_case_int4; +--Testcase 174: INSERT INTO special_case_int4 VALUES ('0x7FFFFFFF'::int4); +--Testcase 175: SELECT f1 FROM special_case_int4; f1 ------------ 2147483647 (1 row) +--Testcase 176: DELETE FROM special_case_int4; +--Testcase 177: INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); ERROR: value "0x80000000" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); ^ +--Testcase 178: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 179: DELETE FROM special_case_int4; +--Testcase 180: INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000000'::int4); +--Testcase 181: SELECT f1 FROM special_case_int4; f1 ------------- -2147483648 (1 row) +--Testcase 182: DELETE FROM special_case_int4; +--Testcase 183: INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000001'::int4); ERROR: value "-0b10000000000000000000000000000001" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('-0b100000000000000000... ^ +--Testcase 184: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 185: DELETE FROM special_case_int4; +--Testcase 186: INSERT INTO special_case_int4 VALUES ('-0o20000000000'::int4); +--Testcase 187: SELECT f1 FROM special_case_int4; f1 ------------- -2147483648 (1 row) +--Testcase 188: DELETE FROM special_case_int4; +--Testcase 189: INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4); ERROR: value "-0o20000000001" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4... ^ +--Testcase 190: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 191: DELETE FROM special_case_int4; +--Testcase 192: INSERT INTO special_case_int4 VALUES ('-0x80000000'::int4); +--Testcase 193: SELECT f1 FROM special_case_int4; f1 ------------- -2147483648 (1 row) +--Testcase 194: DELETE FROM special_case_int4; +--Testcase 195: INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); ERROR: value "-0x80000001" is out of range for type integer LINE 1: INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); ^ +--Testcase 196: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) -- underscores +--Testcase 197: DELETE FROM special_case_int4; +--Testcase 198: INSERT INTO special_case_int4 VALUES ('1_000_000'::int4); +--Testcase 199: SELECT f1 FROM special_case_int4; f1 --------- 1000000 (1 row) +--Testcase 200: DELETE FROM special_case_int4; +--Testcase 201: INSERT INTO special_case_int4 VALUES ('1_2_3'::int4); +--Testcase 202: SELECT f1 FROM special_case_int4; f1 ----- 123 (1 row) +--Testcase 203: DELETE FROM special_case_int4; +--Testcase 204: INSERT INTO special_case_int4 VALUES ('0x1EEE_FFFF'::int4); +--Testcase 205: SELECT f1 FROM special_case_int4; f1 ----------- 518979583 (1 row) +--Testcase 206: DELETE FROM special_case_int4; +--Testcase 207: INSERT INTO special_case_int4 VALUES ('0o2_73'::int4); +--Testcase 208: SELECT f1 FROM special_case_int4; f1 ----- 187 (1 row) +--Testcase 209: DELETE FROM special_case_int4; +--Testcase 210: INSERT INTO special_case_int4 VALUES ('0b_10_0101'::int4); +--Testcase 211: SELECT f1 FROM special_case_int4; f1 ---- @@ -844,36 +919,47 @@ SELECT f1 FROM special_case_int4; (1 row) -- error cases +--Testcase 212: DELETE FROM special_case_int4; +--Testcase 213: INSERT INTO special_case_int4 VALUES ('_100'::int4); ERROR: invalid input syntax for type integer: "_100" LINE 1: INSERT INTO special_case_int4 VALUES ('_100'::int4); ^ +--Testcase 214: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 215: DELETE FROM special_case_int4; +--Testcase 216: INSERT INTO special_case_int4 VALUES ('100_'::int4); ERROR: invalid input syntax for type integer: "100_" LINE 1: INSERT INTO special_case_int4 VALUES ('100_'::int4); ^ +--Testcase 217: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 218: DELETE FROM special_case_int4; +--Testcase 219: INSERT INTO special_case_int4 VALUES ('100__000'::int4); ERROR: invalid input syntax for type integer: "100__000" LINE 1: INSERT INTO special_case_int4 VALUES ('100__000'::int4); ^ +--Testcase 220: SELECT f1 FROM special_case_int4; f1 ---- (0 rows) +--Testcase 221: +DELETE FROM INT4_TBL; -- Clean up DO $d$ declare diff --git a/expected/16.0/extra/int8.out b/expected/16.3/extra/int8.out similarity index 97% rename from expected/16.0/extra/int8.out rename to expected/16.3/extra/int8.out index 5472a108..90376dc8 100644 --- a/expected/16.0/extra/int8.out +++ b/expected/16.3/extra/int8.out @@ -79,26 +79,32 @@ SELECT * FROM INT8_TBL; (5 rows) -- Also try it with non-error-throwing API +--Testcase 251: CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 252: INSERT INTO NON_ERROR_THROWING_API_INT8 VALUES ('34', 1), ('asdf', 2), ('10000000000000000000', 3); +--Testcase 253: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 1; pg_input_is_valid ------------------- t (1 row) +--Testcase 254: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 2; pg_input_is_valid ------------------- f (1 row) +--Testcase 255: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3; pg_input_is_valid ------------------- f (1 row) +--Testcase 256: SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3), 'int8'); message | detail | hint | sql_error_code --------------------------------------------------------------+--------+------+---------------- @@ -1334,204 +1340,273 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow ERROR: bigint out of range -- non-decimal literals +--Testcase 257: CREATE FOREIGN TABLE special_case_int8 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 258: INSERT INTO special_case_int8 VALUES ('0b100101'::int8); +--Testcase 259: SELECT f1 FROM special_case_int8; f1 ---- 37 (1 row) +--Testcase 260: DELETE FROM special_case_int8; +--Testcase 261: INSERT INTO special_case_int8 VALUES ('0o273'::int8); +--Testcase 262: SELECT f1 FROM special_case_int8; f1 ----- 187 (1 row) +--Testcase 263: DELETE FROM special_case_int8; +--Testcase 264: INSERT INTO special_case_int8 VALUES ('0x42F'::int8); +--Testcase 265: SELECT f1 FROM special_case_int8; f1 ------ 1071 (1 row) +--Testcase 266: DELETE FROM special_case_int8; +--Testcase 267: INSERT INTO special_case_int8 VALUES ('0b'::int8); ERROR: invalid input syntax for type bigint: "0b" LINE 1: INSERT INTO special_case_int8 VALUES ('0b'::int8); ^ +--Testcase 268: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 269: DELETE FROM special_case_int8; +--Testcase 270: INSERT INTO special_case_int8 VALUES ('0o'::int8); ERROR: invalid input syntax for type bigint: "0o" LINE 1: INSERT INTO special_case_int8 VALUES ('0o'::int8); ^ +--Testcase 271: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 272: DELETE FROM special_case_int8; +--Testcase 273: INSERT INTO special_case_int8 VALUES ('0x'::int8); ERROR: invalid input syntax for type bigint: "0x" LINE 1: INSERT INTO special_case_int8 VALUES ('0x'::int8); ^ +--Testcase 274: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) -- cases near overflow +--Testcase 275: DELETE FROM special_case_int8; +--Testcase 276: INSERT INTO special_case_int8 VALUES ('0b111111111111111111111111111111111111111111111111111111111111111'::int8); +--Testcase 277: SELECT f1 FROM special_case_int8; f1 --------------------- 9223372036854775807 (1 row) +--Testcase 278: DELETE FROM special_case_int8; +--Testcase 279: INSERT INTO special_case_int8 VALUES ('0b1000000000000000000000000000000000000000000000000000000000000000'::int8); ERROR: value "0b1000000000000000000000000000000000000000000000000000000000000000" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('0b1000000000000000000... ^ +--Testcase 280: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 281: DELETE FROM special_case_int8; +--Testcase 282: INSERT INTO special_case_int8 VALUES ('0o777777777777777777777'::int8); +--Testcase 283: SELECT f1 FROM special_case_int8; f1 --------------------- 9223372036854775807 (1 row) +--Testcase 284: DELETE FROM special_case_int8; +--Testcase 285: INSERT INTO special_case_int8 VALUES ('0o1000000000000000000000'::int8); ERROR: value "0o1000000000000000000000" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('0o1000000000000000000... ^ +--Testcase 286: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 287: DELETE FROM special_case_int8; +--Testcase 288: INSERT INTO special_case_int8 VALUES ('0x7FFFFFFFFFFFFFFF'::int8); +--Testcase 289: SELECT f1 FROM special_case_int8; f1 --------------------- 9223372036854775807 (1 row) +--Testcase 290: DELETE FROM special_case_int8; +--Testcase 291: INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::int8); ERROR: value "0x8000000000000000" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::... ^ +--Testcase 292: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 293: DELETE FROM special_case_int8; +--Testcase 294: INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 295: SELECT f1 FROM special_case_int8; f1 ---------------------- -9223372036854775808 (1 row) +--Testcase 296: DELETE FROM special_case_int8; +--Testcase 297: INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000001'::int8); ERROR: value "-0b1000000000000000000000000000000000000000000000000000000000000001" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('-0b100000000000000000... ^ +--Testcase 298: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 299: DELETE FROM special_case_int8; +--Testcase 300: INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000000'::int8); +--Testcase 301: SELECT f1 FROM special_case_int8; f1 ---------------------- -9223372036854775808 (1 row) +--Testcase 302: DELETE FROM special_case_int8; +--Testcase 303: INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000001'::int8); ERROR: value "-0o1000000000000000000001" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('-0o100000000000000000... ^ +--Testcase 304: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 305: DELETE FROM special_case_int8; +--Testcase 306: INSERT INTO special_case_int8 VALUES ('-0x8000000000000000'::int8); +--Testcase 307: SELECT f1 FROM special_case_int8; f1 ---------------------- -9223372036854775808 (1 row) +--Testcase 308: DELETE FROM special_case_int8; +--Testcase 309: INSERT INTO special_case_int8 VALUES ('-0x8000000000000001'::int8); ERROR: value "-0x8000000000000001" is out of range for type bigint LINE 1: INSERT INTO special_case_int8 VALUES ('-0x8000000000000001':... ^ +--Testcase 310: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) -- underscores +--Testcase 311: DELETE FROM special_case_int8; +--Testcase 312: INSERT INTO special_case_int8 VALUES ('1_000_000'::int8); +--Testcase 313: SELECT f1 FROM special_case_int8; f1 --------- 1000000 (1 row) +--Testcase 314: DELETE FROM special_case_int8; +--Testcase 315: INSERT INTO special_case_int8 VALUES ('1_2_3'::int8); +--Testcase 316: SELECT f1 FROM special_case_int8; f1 ----- 123 (1 row) +--Testcase 317: DELETE FROM special_case_int8; +--Testcase 318: INSERT INTO special_case_int8 VALUES ('0x1EEE_FFFF'::int8); +--Testcase 319: SELECT f1 FROM special_case_int8; f1 ----------- 518979583 (1 row) +--Testcase 320: DELETE FROM special_case_int8; +--Testcase 321: INSERT INTO special_case_int8 VALUES ('0o2_73'::int8); +--Testcase 322: SELECT f1 FROM special_case_int8; f1 ----- 187 (1 row) +--Testcase 323: DELETE FROM special_case_int8; +--Testcase 324: INSERT INTO special_case_int8 VALUES ('0b_10_0101'::int8); +--Testcase 325: SELECT f1 FROM special_case_int8; f1 ---- @@ -1539,36 +1614,47 @@ SELECT f1 FROM special_case_int8; (1 row) -- error cases +--Testcase 326: DELETE FROM special_case_int8; +--Testcase 327: INSERT INTO special_case_int8 VALUES ('_100'::int8); ERROR: invalid input syntax for type bigint: "_100" LINE 1: INSERT INTO special_case_int8 VALUES ('_100'::int8); ^ +--Testcase 328: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 329: DELETE FROM special_case_int8; +--Testcase 330: INSERT INTO special_case_int8 VALUES ('100_'::int8); ERROR: invalid input syntax for type bigint: "100_" LINE 1: INSERT INTO special_case_int8 VALUES ('100_'::int8); ^ +--Testcase 331: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 332: DELETE FROM special_case_int8; +--Testcase 333: INSERT INTO special_case_int8 VALUES ('100__000'::int8); ERROR: invalid input syntax for type bigint: "100__000" LINE 1: INSERT INTO special_case_int8 VALUES ('100__000'::int8); ^ +--Testcase 334: SELECT f1 FROM special_case_int8; f1 ---- (0 rows) +--Testcase 335: +DELETE FROM INT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/16.0/extra/join.out b/expected/16.3/extra/join.out similarity index 99% rename from expected/16.0/extra/join.out rename to expected/16.3/extra/join.out index c683d1e4..df320b02 100644 --- a/expected/16.0/extra/join.out +++ b/expected/16.3/extra/join.out @@ -58,13 +58,43 @@ CREATE FOREIGN TABLE tenk2 ( ) SERVER sqlite_svr; --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 632: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 633: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 634: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 635: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 636: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 637: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 638: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 639: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 640: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 641: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 642: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 643: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 644: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 645: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 646: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; --Testcase 1: @@ -8587,6 +8617,12 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 647: +DELETE FROM INT4_TBL; +--Testcase 648: +DELETE FROM INT8_TBL; +--Testcase 649: +DELETE FROM FLOAT8_TBL; DO $d$ declare l_rec record; diff --git a/expected/16.0/extra/limit.out b/expected/16.3/extra/limit.out similarity index 98% rename from expected/16.0/extra/limit.out rename to expected/16.3/extra/limit.out index 411a8fdb..71fcb283 100644 --- a/expected/16.0/extra/limit.out +++ b/expected/16.3/extra/limit.out @@ -28,6 +28,16 @@ CREATE FOREIGN TABLE onek( ) SERVER sqlite_svr; --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -1044,6 +1054,8 @@ View definition: LIMIT ALL; -- leave these views +--Testcase 110: +DELETE FROM int8_tbl; -- Clean up DO $d$ declare diff --git a/expected/16.0/extra/numeric.out b/expected/16.3/extra/numeric.out similarity index 100% rename from expected/16.0/extra/numeric.out rename to expected/16.3/extra/numeric.out diff --git a/expected/15.4/extra/out_of_range.out b/expected/16.3/extra/out_of_range.out similarity index 93% rename from expected/15.4/extra/out_of_range.out rename to expected/16.3/extra/out_of_range.out index 8de68b14..be2f8256 100644 --- a/expected/15.4/extra/out_of_range.out +++ b/expected/16.3/extra/out_of_range.out @@ -96,27 +96,17 @@ INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; --Testcase 34: SELECT * FROM INT8_TBL; -- NO overflow - q1 | q2 -----------------------+------------------- - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 - 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 - -9223372036854775808 | 0 -(6 rows) + q1 | q2 +----------------------+---- + -9223372036854775808 | 0 +(1 row) --Testcase 35: SELECT q1 FROM INT8_TBL; -- NO overflow q1 ---------------------- - 123 - 123 - 4567890123456789 - 4567890123456789 - 4567890123456789 -9223372036854775808 -(6 rows) +(1 row) --Testcase 36: ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; diff --git a/expected/16.0/extra/prepare.out b/expected/16.3/extra/prepare.out similarity index 100% rename from expected/16.0/extra/prepare.out rename to expected/16.3/extra/prepare.out diff --git a/expected/15.4/extra/select.out b/expected/16.3/extra/select.out similarity index 98% rename from expected/15.4/extra/select.out rename to expected/16.3/extra/select.out index 2f7f5359..7dddc119 100644 --- a/expected/15.4/extra/select.out +++ b/expected/16.3/extra/select.out @@ -49,6 +49,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -912,6 +922,8 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/expected/15.4/extra/select_having.out b/expected/16.3/extra/select_having.out similarity index 100% rename from expected/15.4/extra/select_having.out rename to expected/16.3/extra/select_having.out diff --git a/expected/16.0/extra/sqlite_fdw_post.out b/expected/16.3/extra/sqlite_fdw_post.out similarity index 99% rename from expected/16.0/extra/sqlite_fdw_post.out rename to expected/16.3/extra/sqlite_fdw_post.out index 3f2c26a3..750d2207 100644 --- a/expected/16.0/extra/sqlite_fdw_post.out +++ b/expected/16.3/extra/sqlite_fdw_post.out @@ -13,12 +13,13 @@ DO $d$ OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -2899,10 +2900,19 @@ SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1. -- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; --Testcase 510: @@ -9977,7 +9987,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest1 | loct | sqlite_svr | ("table" 'loct') | import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest1 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest1 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -9991,7 +10003,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 478: \d import_dest1.* @@ -10131,6 +10143,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest1.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest1.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10140,6 +10159,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest1.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest1.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10271,7 +10298,9 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest2 | loct | sqlite_svr | ("table" 'loct') | import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest2 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest2 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -10285,7 +10314,7 @@ IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) --Testcase 480: \d import_dest2.* @@ -10425,6 +10454,13 @@ FDW options: ("table" 'loct') Server: sqlite_svr FDW options: ("table" 'loct1') + Foreign table "import_dest2.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + Foreign table "import_dest2.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10434,6 +10470,14 @@ FDW options: ("table" 'loct1') Server: sqlite_svr FDW options: ("table" 'loct2') + Foreign table "import_dest2.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + Foreign table "import_dest2.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- @@ -10576,7 +10620,9 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest3 | loct | sqlite_svr | ("table" 'loct') | import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest3 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest3 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | @@ -10590,7 +10636,7 @@ IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | -(29 rows) +(31 rows) -- Assorted error cases IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; @@ -10976,9 +11022,7 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); --Testcase 886: DROP SERVER sqlite_svr3 CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to user mapping for public on server sqlite_svr3 -drop cascades to foreign table ft7 +NOTICE: drop cascades to foreign table ft7 -- List all the existing cached connections. sqlite_svr and sqlite_svr3 -- should be output as invalid connections. Also the server name for -- sqlite_svr3 should be NULL because the server was dropped. @@ -11109,15 +11153,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 --Testcase 908: @@ -11143,7 +11192,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name @@ -11169,9 +11218,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -11909,12 +11958,12 @@ ERROR: invalid value for integer option "batch_size": 100$%$#$# -- DROP TABLE analyze_table; -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; -NOTICE: drop cascades to 126 other objects +NOTICE: drop cascades to 134 other objects DETAIL: drop cascades to foreign table "S 1"."T 0" drop cascades to foreign table "S 1"."T 1" drop cascades to foreign table "S 1"."T 2" @@ -11936,6 +11985,8 @@ drop cascades to foreign table "S 1".ft3 drop cascades to foreign table "S 1".foreign_tbl drop cascades to foreign table "S 1".grem1 drop cascades to foreign table "S 1".grem1_post14 +drop cascades to foreign table "S 1".loct1_rescan +drop cascades to foreign table "S 1".loct2_rescan drop cascades to foreign table "S 1".t1_constraint drop cascades to foreign table "S 1".tru_rtable0 drop cascades to foreign table "S 1".tru_pk_table @@ -11975,6 +12026,8 @@ drop cascades to foreign table import_dest1.ft3 drop cascades to foreign table import_dest1.foreign_tbl drop cascades to foreign table import_dest1.grem1 drop cascades to foreign table import_dest1.grem1_post14 +drop cascades to foreign table import_dest1.loct1_rescan +drop cascades to foreign table import_dest1.loct2_rescan drop cascades to foreign table import_dest1.t1_constraint drop cascades to foreign table import_dest1.tru_rtable0 drop cascades to foreign table import_dest1.tru_pk_table @@ -12004,18 +12057,14 @@ drop cascades to foreign table import_dest2.ft3 drop cascades to foreign table import_dest2.foreign_tbl drop cascades to foreign table import_dest2.grem1 drop cascades to foreign table import_dest2.grem1_post14 +drop cascades to foreign table import_dest2.loct1_rescan +drop cascades to foreign table import_dest2.loct2_rescan drop cascades to foreign table import_dest2.t1_constraint drop cascades to foreign table import_dest2.tru_rtable0 drop cascades to foreign table import_dest2.tru_pk_table drop cascades to foreign table import_dest2.tru_fk_table drop cascades to foreign table import_dest2.tru_rtable_parent -drop cascades to foreign table import_dest2.tru_rtable_child -drop cascades to foreign table import_dest2.loct_empty -drop cascades to foreign table import_dest2.batch_table -drop cascades to foreign table import_dest3."T 1" -drop cascades to foreign table import_dest3.loct6 -drop cascades to foreign table import_dest3."T 0" -and 26 other objects (see server log for list) +and 34 other objects (see server log for list) --Testcase 736: DROP SERVER sqlite_svr2 CASCADE; NOTICE: drop cascades to foreign table ft6 diff --git a/expected/15.4/extra/timestamp.out b/expected/16.3/extra/timestamp.out similarity index 100% rename from expected/15.4/extra/timestamp.out rename to expected/16.3/extra/timestamp.out diff --git a/expected/16.0/extra/update.out b/expected/16.3/extra/update.out similarity index 100% rename from expected/16.0/extra/update.out rename to expected/16.3/extra/update.out diff --git a/expected/16.0/extra/uuid.out b/expected/16.3/extra/uuid.out similarity index 100% rename from expected/16.0/extra/uuid.out rename to expected/16.3/extra/uuid.out diff --git a/expected/15.4/selectfunc.out b/expected/16.3/selectfunc.out similarity index 100% rename from expected/15.4/selectfunc.out rename to expected/16.3/selectfunc.out diff --git a/expected/16.0/sqlite_fdw.out b/expected/16.3/sqlite_fdw.out similarity index 99% rename from expected/16.0/sqlite_fdw.out rename to expected/16.3/sqlite_fdw.out index cea486ad..ccdff790 100644 --- a/expected/16.0/sqlite_fdw.out +++ b/expected/16.3/sqlite_fdw.out @@ -1459,14 +1459,14 @@ SELECT * FROM noprimary; SELECT * FROM public.sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) --Testcase 155: SELECT sqlite_fdw_version(); sqlite_fdw_version -------------------- - 20400 + 20500 (1 row) -- issue #44 github diff --git a/expected/14.9/type.out b/expected/16.3/type.out similarity index 97% rename from expected/14.9/type.out rename to expected/16.3/type.out index d23c7be1..deedc213 100644 --- a/expected/14.9/type.out +++ b/expected/16.3/type.out @@ -298,7 +298,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/expected/12.16/aggregate.out b/expected/17.0/aggregate.out similarity index 79% rename from expected/12.16/aggregate.out rename to expected/17.0/aggregate.out index d56c8769..584a2c11 100644 --- a/expected/12.16/aggregate.out +++ b/expected/17.0/aggregate.out @@ -107,36 +107,66 @@ INSERT INTO limittest(x, y) VALUES (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'); --Testcase 20: EXPLAIN VERBOSE SELECT avg(x) FROM limittest GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 2: ...est GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; - ^ + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + Limit (cost=1.00..1.00 rows=1 width=64) + Output: (avg(x)), y + -> Foreign Scan (cost=1.00..1.00 rows=1 width=64) + Output: (avg(x)), y + SQLite query: SELECT avg(`x`), `y` FROM main."limittest" GROUP BY 2 ORDER BY avg(`x`) DESC NULLS FIRST +(5 rows) + --Testcase 21: SELECT avg(x) FROM limittest GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 1: ...est GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; - ^ + avg +----- + 2.5 + 2.5 + 2.5 +(3 rows) + --Testcase 22: EXPLAIN VERBOSE SELECT avg(x) FROM limittest WHERE x >= 0 GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 2: ...= 0 GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; - ^ + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Limit (cost=1.00..1.00 rows=1 width=64) + Output: (avg(x)), y + -> Foreign Scan (cost=1.00..1.00 rows=1 width=64) + Output: (avg(x)), y + SQLite query: SELECT avg(`x`), `y` FROM main."limittest" WHERE ((`x` >= 0)) GROUP BY 2 ORDER BY avg(`x`) DESC NULLS FIRST +(5 rows) + --Testcase 23: SELECT avg(x) FROM limittest WHERE x >= 0 GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 1: ...= 0 GROUP BY y ORDER BY 1 DESC FETCH FIRST 2 ROWS WITH TIES; - ^ + avg +----- + 2.5 + 2.5 + 2.5 +(3 rows) + --Testcase 24: EXPLAIN VERBOSE SELECT x FROM limittest WHERE x > 0 ORDER BY 1 FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 2: ...mittest WHERE x > 0 ORDER BY 1 FETCH FIRST 2 ROWS WITH TIES; - ^ + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Limit (cost=10.00..10.00 rows=2 width=4) + Output: x + -> Foreign Scan on public.limittest (cost=10.00..10.00 rows=10 width=4) + Output: x + SQLite query: SELECT `x` FROM main."limittest" WHERE ((`x` > 0)) ORDER BY `x` ASC NULLS LAST +(5 rows) + --Testcase 25: SELECT x FROM limittest WHERE x > 0 ORDER BY 1 FETCH FIRST 2 ROWS WITH TIES; -ERROR: syntax error at or near "WITH" -LINE 1: ...mittest WHERE x > 0 ORDER BY 1 FETCH FIRST 2 ROWS WITH TIES; - ^ + x +--- + 1 + 1 + 1 +(3 rows) + --Testcase 26: EXPLAIN VERBOSE SELECT x FROM limittest ORDER BY 1 FETCH FIRST 2 ROWS ONLY; diff --git a/expected/17.0/extra/aggregates.out b/expected/17.0/extra/aggregates.out new file mode 100644 index 00000000..c5a63bca --- /dev/null +++ b/expected/17.0/extra/aggregates.out @@ -0,0 +1,4256 @@ +-- +-- AGGREGATES +-- +--Testcase 266: +CREATE EXTENSION sqlite_fdw; +--Testcase 267: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 268: +CREATE FOREIGN TABLE onek( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 269: +CREATE FOREIGN TABLE aggtest ( + a int2, + b float4 +) SERVER sqlite_svr; +--Testcase 270: +CREATE FOREIGN TABLE student ( + name text, + age int4, + location point, + gpa float8 +) SERVER sqlite_svr; +--Testcase 271: +CREATE FOREIGN TABLE tenk1 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 272: +CREATE FOREIGN TABLE INT8_TBL( + q1 int8 OPTIONS (key 'true'), + q2 int8 OPTIONS (key 'true') +) SERVER sqlite_svr; +--Testcase 782: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 783: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 784: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 785: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 786: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); +--Testcase 273: +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 787: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 788: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 789: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 790: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 791: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); +--Testcase 274: +CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; +--Testcase 275: +CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 276: +CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +-- avoid bit-exact output here because operations may not be bit-exact. +--Testcase 588: +SET extra_float_digits = 0; +--Testcase 1: +SELECT avg(four) AS avg_1 FROM onek; + avg_1 +------- + 1.5 +(1 row) + +--Testcase 2: +SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100; + avg_32 +------------------ + 32.6666666666667 +(1 row) + +--Testcase 697: +CREATE FOREIGN TABLE agg_tb(v int, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 698: +INSERT INTO agg_tb(v) VALUES(1), (2), (3); +--Testcase 699: -- Pg 16+ +SELECT any_value(v) FROM agg_tb; + any_value +----------- + 1 +(1 row) + +--Testcase 700: +DELETE FROM agg_tb; +--Testcase 701: +INSERT INTO agg_tb(v) VALUES (NULL); +--Testcase 702: -- Pg 16+ +SELECT any_value(v) FROM agg_tb; + any_value +----------- + +(1 row) + +--Testcase 703: +DELETE FROM agg_tb; +--Testcase 704: +INSERT INTO agg_tb(v) VALUES (NULL), (1), (2); +--Testcase 705: -- Pg 16+ +SELECT any_value(v) FROM agg_tb; + any_value +----------- + 1 +(1 row) + +--Testcase 706: +CREATE FOREIGN TABLE agg_tb2(v text) SERVER sqlite_svr; +--Testcase 707: +INSERT INTO agg_tb2(v) VALUES (array['hello', 'world']); +--Testcase 708: -- Pg 16+ +SELECT any_value(v) FROM agg_tb2; + any_value +--------------- + {hello,world} +(1 row) + +-- In 7.1, avg(float4) is computed using float8 arithmetic. +--Testcase 3: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 678: +SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; + avg_107_943 +------------- + 107.943 +(1 row) + +--Testcase 4: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 679: +SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; + avg_3_4 +--------- + 3.400 +(1 row) + +--Testcase 5: +SELECT sum(four) AS sum_1500 FROM onek; + sum_1500 +---------- + 1500 +(1 row) + +--Testcase 6: +SELECT sum(a) AS sum_198 FROM aggtest; + sum_198 +--------- + 198 +(1 row) + +--Testcase 7: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 680: +SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; + avg_431_773 +------------- + 431.773 +(1 row) + +--Testcase 8: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 681: +SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; + avg_6_8 +--------- + 6.800 +(1 row) + +--Testcase 9: +SELECT max(four) AS max_3 FROM onek; + max_3 +------- + 3 +(1 row) + +--Testcase 10: +SELECT max(a) AS max_100 FROM aggtest; + max_100 +--------- + 100 +(1 row) + +--Testcase 11: +SELECT max(aggtest.b) AS max_324_78 FROM aggtest; + max_324_78 +------------ + 324.78 +(1 row) + +--Testcase 12: +SELECT max(student.gpa) AS max_3_7 FROM student; + max_3_7 +--------- + 3.7 +(1 row) + +--Testcase 13: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 682: +SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; + stddev_pop +---------------- + 131.1070323190 +(1 row) + +--Testcase 14: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 683: +SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; + stddev_samp +---------------- + 151.3893608040 +(1 row) + +--Testcase 15: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 684: +SELECT var_pop(b)::numeric(20,10) FROM aggtest; + var_pop +------------------ + 17189.0539234823 +(1 row) + +--Testcase 16: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 685: +SELECT var_samp(b)::numeric(20,10) FROM aggtest; + var_samp +------------------ + 22918.7385646431 +(1 row) + +--Testcase 17: +SELECT stddev_pop(b::numeric) FROM aggtest; + stddev_pop +------------------ + 131.107032862199 +(1 row) + +--Testcase 18: +SELECT stddev_samp(b::numeric) FROM aggtest; + stddev_samp +------------------ + 151.389361431288 +(1 row) + +--Testcase 19: +SELECT var_pop(b::numeric) FROM aggtest; + var_pop +-------------------- + 17189.054065929769 +(1 row) + +--Testcase 20: +SELECT var_samp(b::numeric) FROM aggtest; + var_samp +-------------------- + 22918.738754573025 +(1 row) + +-- population variance is defined for a single tuple, sample variance +-- is not +--Testcase 277: +CREATE FOREIGN TABLE agg_t3(a float8, b float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 278: +DELETE FROM agg_t3; +--Testcase 279: +INSERT INTO agg_t3 values (1.0::float8, 2.0::float8); +--Testcase 280: +SELECT var_pop(a), var_samp(b) FROM agg_t3; + var_pop | var_samp +---------+---------- + 0 | +(1 row) + +--Testcase 281: +DELETE FROM agg_t3; +--Testcase 282: +INSERT INTO agg_t3 values (3.0::float8, 4.0::float8); +--Testcase 283: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; + stddev_pop | stddev_samp +------------+------------- + 0 | +(1 row) + +--Testcase 284: +DELETE FROM agg_t3; +--Testcase 285: +INSERT INTO agg_t3 values ('inf'::float8, 'inf'::float8); +--Testcase 286: +SELECT var_pop(a), var_samp(b) FROM agg_t3; + var_pop | var_samp +---------+---------- + NaN | +(1 row) + +--Testcase 287: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; + stddev_pop | stddev_samp +------------+------------- + NaN | +(1 row) + +--Testcase 288: +DELETE FROM agg_t3; +--Testcase 289: +INSERT INTO agg_t3 values ('nan'::float8, 'nan'::float8); +--Testcase 290: +SELECT var_pop(a), var_samp(b) FROM agg_t3; + var_pop | var_samp +---------+---------- + | +(1 row) + +--Testcase 291: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t3; + stddev_pop | stddev_samp +------------+------------- + | +(1 row) + +--Testcase 292: +CREATE FOREIGN TABLE agg_t4(a float4, b float4, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 293: +DELETE FROM agg_t4; +--Testcase 294: +INSERT INTO agg_t4 values (1.0::float4, 2.0::float4); +--Testcase 295: +SELECT var_pop(a), var_samp(b) FROM agg_t4; + var_pop | var_samp +---------+---------- + 0 | +(1 row) + +--Testcase 296: +DELETE FROM agg_t4; +--Testcase 297: +INSERT INTO agg_t4 values (3.0::float4, 4.0::float4); +--Testcase 298: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; + stddev_pop | stddev_samp +------------+------------- + 0 | +(1 row) + +--Testcase 299: +DELETE FROM agg_t4; +--Testcase 300: +INSERT INTO agg_t4 values ('inf'::float4, 'inf'::float4); +--Testcase 301: +SELECT var_pop(a), var_samp(b) FROM agg_t4; + var_pop | var_samp +---------+---------- + NaN | +(1 row) + +--Testcase 302: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; + stddev_pop | stddev_samp +------------+------------- + NaN | +(1 row) + +--Testcase 303: +DELETE FROM agg_t4; +--Testcase 304: +INSERT INTO agg_t4 values ('nan'::float4, 'nan'::float4); +--Testcase 305: +SELECT var_pop(a), var_samp(b) FROM agg_t4; + var_pop | var_samp +---------+---------- + | +(1 row) + +--Testcase 306: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t4; + stddev_pop | stddev_samp +------------+------------- + | +(1 row) + +--Testcase 307: +CREATE FOREIGN TABLE agg_t5(a numeric, b numeric, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 308: +DELETE FROM agg_t5; +--Testcase 309: +INSERT INTO agg_t5 values (1.0::numeric, 2.0::numeric); +--Testcase 310: +SELECT var_pop(a), var_samp(b) FROM agg_t5; + var_pop | var_samp +---------+---------- + 0 | +(1 row) + +--Testcase 311: +DELETE FROM agg_t5; +--Testcase 312: +INSERT INTO agg_t5 values (3.0::numeric, 4.0::numeric); +--Testcase 313: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; + stddev_pop | stddev_samp +------------+------------- + 0 | +(1 row) + +--Testcase 597: +DELETE FROM agg_t5; +--Testcase 598: +INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); +--Testcase 599: +SELECT var_pop(a), var_samp(b) FROM agg_t5; + var_pop | var_samp +---------+---------- + NaN | +(1 row) + +--Testcase 600: +DELETE FROM agg_t5; +--Testcase 601: +INSERT INTO agg_t5 values ('inf'::numeric, 'inf'::numeric); +--Testcase 602: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; + stddev_pop | stddev_samp +------------+------------- + NaN | +(1 row) + +--Testcase 314: +DELETE FROM agg_t5; +--Testcase 315: +INSERT INTO agg_t5 values ('nan'::numeric, 'nan'::numeric); +--Testcase 316: +SELECT var_pop(a), var_samp(b) FROM agg_t5; + var_pop | var_samp +---------+---------- + | +(1 row) + +--Testcase 317: +SELECT stddev_pop(a), stddev_samp(b) FROM agg_t5; + stddev_pop | stddev_samp +------------+------------- + | +(1 row) + +-- verify correct results for null and NaN inputs +--Testcase 318: +CREATE FOREIGN TABLE agg_t8(a text OPTIONS (key 'true'), b text) SERVER sqlite_svr; +--Testcase 319: +DELETE FROM agg_t8; +--Testcase 320: +INSERT INTO agg_t8 select * from generate_series(1,3); +--Testcase 321: +select sum(null::int4) from agg_t8; + sum +----- + +(1 row) + +--Testcase 322: +select sum(null::int8) from agg_t8; + sum +----- + +(1 row) + +--Testcase 323: +select sum(null::numeric) from agg_t8; + sum +----- + +(1 row) + +--Testcase 324: +select sum(null::float8) from agg_t8; + sum +----- + +(1 row) + +--Testcase 325: +select avg(null::int4) from agg_t8; + avg +----- + +(1 row) + +--Testcase 326: +select avg(null::int8) from agg_t8; + avg +----- + +(1 row) + +--Testcase 327: +select avg(null::numeric) from agg_t8; + avg +----- + +(1 row) + +--Testcase 328: +select avg(null::float8) from agg_t8; + avg +----- + +(1 row) + +--Testcase 329: +select sum('NaN'::numeric) from agg_t8; + sum +----- + 0 +(1 row) + +--Testcase 330: +select avg('NaN'::numeric) from agg_t8; + avg +----- + 0 +(1 row) + +-- verify correct results for infinite inputs +--Testcase 331: +DELETE FROM agg_t3; +--Testcase 332: +INSERT INTO agg_t3 VALUES ('1'::float8), ('infinity'::float8); +--Testcase 333: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 334: +DELETE FROM agg_t3; +--Testcase 335: +INSERT INTO agg_t3 VALUES ('infinity'::float8), ('1'::float8); +--Testcase 336: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 337: +DELETE FROM agg_t3; +--Testcase 338: +INSERT INTO agg_t3 VALUES ('infinity'::float8), ('infinity'::float8); +--Testcase 339: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 340: +DELETE FROM agg_t3; +--Testcase 341: +INSERT INTO agg_t3 VALUES ('-infinity'::float8), ('infinity'::float8); +--Testcase 342: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +-----+-----+--------- + NaN | NaN | NaN +(1 row) + +--Testcase 603: +DELETE FROM agg_t3; +--Testcase 604: +INSERT INTO agg_t3 VALUES ('-infinity'::float8), ('-infinity'::float8); +--Testcase 605: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +-----------+-----------+--------- + -Infinity | -Infinity | NaN +(1 row) + +--Testcase 606: +DELETE FROM agg_t3; +--Testcase 607: +INSERT INTO agg_t3 VALUES ('1'::numeric), ('infinity'::numeric); +--Testcase 608: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 609: +DELETE FROM agg_t3; +--Testcase 610: +INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('1'::numeric); +--Testcase 611: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 612: +DELETE FROM agg_t3; +--Testcase 613: +INSERT INTO agg_t3 VALUES ('infinity'::numeric), ('infinity'::numeric); +--Testcase 614: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +----------+----------+--------- + Infinity | Infinity | NaN +(1 row) + +--Testcase 615: +DELETE FROM agg_t3; +--Testcase 616: +INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('infinity'::numeric); +--Testcase 617: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +-----+-----+--------- + NaN | NaN | NaN +(1 row) + +--Testcase 618: +DELETE FROM agg_t3; +--Testcase 619: +INSERT INTO agg_t3 VALUES ('-infinity'::numeric), ('-infinity'::numeric); +--Testcase 620: +SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; + sum | avg | var_pop +-----------+-----------+--------- + -Infinity | -Infinity | NaN +(1 row) + +-- test accuracy with a large input offset +--Testcase 343: +CREATE FOREIGN TABLE agg_t6(a float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 344: +DELETE FROM agg_t6; +--Testcase 345: +INSERT INTO agg_t6 VALUES (100000003), (100000004), (100000006), (100000007); +--Testcase 346: +SELECT avg(a), var_pop(a) FROM agg_t6; + avg | var_pop +-----------+--------- + 100000005 | 2.5 +(1 row) + +--Testcase 347: +DELETE FROM agg_t6; +--Testcase 348: +INSERT INTO agg_t6 VALUES (7000000000005), (7000000000007); +--Testcase 349: +SELECT avg(a), var_pop(a) FROM agg_t6; + avg | var_pop +---------------+--------- + 7000000000006 | 1 +(1 row) + +-- SQL2003 binary aggregates +--Testcase 21: +SELECT regr_count(b, a) FROM aggtest; + regr_count +------------ + 4 +(1 row) + +--Testcase 22: +SELECT regr_sxx(b, a) FROM aggtest; + regr_sxx +---------- + 5099 +(1 row) + +--Testcase 23: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 686: +SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; + regr_syy +------------------ + 68756.2156939293 +(1 row) + +--Testcase 24: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 687: +SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; + regr_sxy +----------------- + 2614.5158215500 +(1 row) + +--Testcase 25: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 688: +SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; + regr_avgx | regr_avgy +-----------+---------------- + 49.5 | 107.9431522731 +(1 row) + +--Testcase 26: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 689: +SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; + regr_r2 +-------------- + 0.0194977982 +(1 row) + +--Testcase 27: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 690: +SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; + regr_slope | regr_intercept +--------------+---------------- + 0.5127507004 | 82.5619926012 +(1 row) + +--Testcase 28: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 691: +SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; + covar_pop | covar_samp +----------------+---------------- + 653.6289553875 | 871.5052738500 +(1 row) + +--Testcase 29: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 692: +SELECT corr(b, a)::numeric(20,10) FROM aggtest; + corr +-------------- + 0.1396345165 +(1 row) + +-- check single-tuple behavior +--Testcase 350: +CREATE FOREIGN TABLE agg_t7(a float8, b float8, c float8, d float8, id integer OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 351: +DELETE FROM agg_t7; +--Testcase 352: +INSERT INTO agg_t7 VALUES (1, 2, 3, 4); +--Testcase 353: +SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; + covar_pop | covar_samp +-----------+------------ + 0 | +(1 row) + +--Testcase 354: +DELETE FROM agg_t7; +--Testcase 355: +INSERT INTO agg_t7 VALUES (1, 'inf', 3, 'inf'); +--Testcase 356: +SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; + covar_pop | covar_samp +-----------+------------ + NaN | +(1 row) + +--Testcase 357: +DELETE FROM agg_t7; +--Testcase 358: +INSERT INTO agg_t7 VALUES (1, 'nan', 3, 'nan'); +--Testcase 359: +SELECT covar_pop(a,b), covar_samp(c,d) FROM agg_t7; + covar_pop | covar_samp +-----------+------------ + | +(1 row) + +-- test accum and combine functions directly +--Testcase 360: +CREATE FOREIGN TABLE regr_test (x float8, y float8, id int options (key 'true')) SERVER sqlite_svr; +--Testcase 361: +DELETE FROM regr_test; +--Testcase 362: +INSERT INTO regr_test VALUES (10,150),(20,250),(30,350),(80,540),(100,200); +--Testcase 363: +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test WHERE x IN (10,20,30,80); + count | sum | regr_sxx | sum | regr_syy | regr_sxy +-------+-----+----------+------+----------+---------- + 4 | 140 | 2900 | 1290 | 83075 | 15050 +(1 row) + +--Testcase 364: +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test; + count | sum | regr_sxx | sum | regr_syy | regr_sxy +-------+-----+----------+------+----------+---------- + 5 | 240 | 6280 | 1490 | 95080 | 8680 +(1 row) + +--Testcase 590: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test WHERE x IN (10,20,30,80); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*), sum(x), regr_sxx(y, x), sum(y), regr_syy(y, x), regr_sxy(y, x) + -> Foreign Scan on public.regr_test + Output: x, y, id + SQLite query: SELECT sqlite_fdw_float(`x`), sqlite_fdw_float(`y`) FROM main."regr_test" WHERE (sqlite_fdw_float(`x`) IN (10, 20, 30, 80)) +(5 rows) + +--Testcase 591: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test; + QUERY PLAN +------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*), sum(x), regr_sxx(y, x), sum(y), regr_syy(y, x), regr_sxy(y, x) + -> Foreign Scan on public.regr_test + Output: x, y, id + SQLite query: SELECT sqlite_fdw_float(`x`), sqlite_fdw_float(`y`) FROM main."regr_test" +(5 rows) + +--Testcase 365: +CREATE FOREIGN TABLE agg_t15 (a text, b int, c int, id int options (key 'true')) SERVER sqlite_svr; +--Testcase 366: +delete from agg_t15; +--Testcase 367: +insert into agg_t15 values ('{4,140,2900}', 100); +--Testcase 368: +SELECT float8_accum(a::float8[], b) from agg_t15; + float8_accum +-------------- + {5,240,6280} +(1 row) + +--Testcase 369: +delete from agg_t15; +--Testcase 370: +insert into agg_t15 values ('{4,140,2900,1290,83075,15050}', 200, 100); +--Testcase 371: +SELECT float8_regr_accum(a::float8[], b, c) from agg_t15; + float8_regr_accum +------------------------------ + {5,240,6280,1490,95080,8680} +(1 row) + +--Testcase 372: +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test WHERE x IN (10,20,30); + count | sum | regr_sxx | sum | regr_syy | regr_sxy +-------+-----+----------+-----+----------+---------- + 3 | 60 | 200 | 750 | 20000 | 2000 +(1 row) + +--Testcase 373: +SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) +FROM regr_test WHERE x IN (80,100); + count | sum | regr_sxx | sum | regr_syy | regr_sxy +-------+-----+----------+-----+----------+---------- + 2 | 180 | 200 | 740 | 57800 | -3400 +(1 row) + +--Testcase 374: +CREATE FOREIGN TABLE agg_t16 (a text, b text, id int options (key 'true')) SERVER sqlite_svr; +--Testcase 375: +delete from agg_t16; +--Testcase 376: +insert into agg_t16 values ('{3,60,200}', '{0,0,0}'); +--Testcase 377: +insert into agg_t16 values ('{0,0,0}', '{2,180,200}'); +--Testcase 378: +insert into agg_t16 values ('{3,60,200}', '{2,180,200}'); +--Testcase 379: +SELECT float8_combine(a::float8[], b::float8[]) FROM agg_t16; + float8_combine +---------------- + {3,60,200} + {2,180,200} + {5,240,6280} +(3 rows) + +--Testcase 380: +delete from agg_t16; +--Testcase 381: +insert into agg_t16 values ('{3,60,200,750,20000,2000}', '{0,0,0,0,0,0}'); +--Testcase 382: +insert into agg_t16 values ('{0,0,0,0,0,0}', '{2,180,200,740,57800,-3400}'); +--Testcase 383: +insert into agg_t16 values ('{3,60,200,750,20000,2000}', '{2,180,200,740,57800,-3400}'); +--Testcase 384: +SELECT float8_regr_combine(a::float8[], b::float8[]) FROM agg_t16; + float8_regr_combine +------------------------------ + {3,60,200,750,20000,2000} + {2,180,200,740,57800,-3400} + {5,240,6280,1490,95080,8680} +(3 rows) + +--Testcase 385: +DROP FOREIGN TABLE regr_test; +-- test count, distinct +--Testcase 30: +SELECT count(four) AS cnt_1000 FROM onek; + cnt_1000 +---------- + 1000 +(1 row) + +--Testcase 31: +SELECT count(DISTINCT four) AS cnt_4 FROM onek; + cnt_4 +------- + 4 +(1 row) + +--Testcase 32: +select ten, count(*), sum(four) from onek +group by ten order by ten; + ten | count | sum +-----+-------+----- + 0 | 100 | 100 + 1 | 100 | 200 + 2 | 100 | 100 + 3 | 100 | 200 + 4 | 100 | 100 + 5 | 100 | 200 + 6 | 100 | 100 + 7 | 100 | 200 + 8 | 100 | 100 + 9 | 100 | 200 +(10 rows) + +--Testcase 33: +select ten, count(four), sum(DISTINCT four) from onek +group by ten order by ten; + ten | count | sum +-----+-------+----- + 0 | 100 | 2 + 1 | 100 | 4 + 2 | 100 | 2 + 3 | 100 | 4 + 4 | 100 | 2 + 5 | 100 | 4 + 6 | 100 | 2 + 7 | 100 | 4 + 8 | 100 | 2 + 9 | 100 | 4 +(10 rows) + +-- user-defined aggregates +--Testcase 386: +CREATE AGGREGATE newavg ( + sfunc = int4_avg_accum, basetype = int4, stype = _int8, + finalfunc = int8_avg, + initcond1 = '{0,0}' +); +--Testcase 387: +CREATE AGGREGATE newsum ( + sfunc1 = int4pl, basetype = int4, stype1 = int4, + initcond1 = '0' +); +--Testcase 388: +CREATE AGGREGATE newcnt (*) ( + sfunc = int8inc, stype = int8, + initcond = '0', parallel = safe +); +--Testcase 389: +CREATE AGGREGATE newcnt ("any") ( + sfunc = int8inc_any, stype = int8, + initcond = '0' +); +--Testcase 390: +CREATE AGGREGATE oldcnt ( + sfunc = int8inc, basetype = 'ANY', stype = int8, + initcond = '0' +); +--Testcase 391: +create function sum3(int8,int8,int8) returns int8 as +'select $1 + $2 + $3' language sql strict immutable; +--Testcase 392: +create aggregate sum2(int8,int8) ( + sfunc = sum3, stype = int8, + initcond = '0' +); +--Testcase 34: +SELECT newavg(four) AS avg_1 FROM onek; + avg_1 +-------------------- + 1.5000000000000000 +(1 row) + +--Testcase 35: +SELECT newsum(four) AS sum_1500 FROM onek; + sum_1500 +---------- + 1500 +(1 row) + +--Testcase 36: +SELECT newcnt(four) AS cnt_1000 FROM onek; + cnt_1000 +---------- + 1000 +(1 row) + +--Testcase 37: +SELECT newcnt(*) AS cnt_1000 FROM onek; + cnt_1000 +---------- + 1000 +(1 row) + +--Testcase 38: +SELECT oldcnt(*) AS cnt_1000 FROM onek; + cnt_1000 +---------- + 1000 +(1 row) + +--Testcase 39: +SELECT sum2(q1,q2) FROM int8_tbl; + sum2 +------------------- + 18271560493827981 +(1 row) + +-- test for outer-level aggregates +-- this should work +--Testcase 40: +select ten, sum(distinct four) from onek a +group by ten +having exists (select 1 from onek b where sum(distinct a.four) = b.four); + ten | sum +-----+----- + 0 | 2 + 2 | 2 + 4 | 2 + 6 | 2 + 8 | 2 +(5 rows) + +-- this should fail because subquery has an agg of its own in WHERE +--Testcase 41: +select ten, sum(distinct four) from onek a +group by ten +having exists (select 1 from onek b + where sum(distinct a.four + b.four) = b.four); +ERROR: aggregate functions are not allowed in WHERE +LINE 4: where sum(distinct a.four + b.four) = b.four)... + ^ +-- Test handling of sublinks within outer-level aggregates. +-- Per bug report from Daniel Grace. +--Testcase 42: +select + (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1))) +from tenk1 o; + max +------ + 9999 +(1 row) + +-- Test handling of Params within aggregate arguments in hashed aggregation. +-- Per bug report from Jeevan Chalke. +--Testcase 393: +explain (verbose, costs off) +select s1, s2, sm +from generate_series(1, 3) s1, + lateral (select s2, sum(s1 + s2) sm + from generate_series(1, 3) s2 group by s2) ss +order by 1, 2; + QUERY PLAN +------------------------------------------------------------------ + Sort + Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) + Sort Key: s1.s1, s2.s2 + -> Nested Loop + Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) + -> Function Scan on pg_catalog.generate_series s1 + Output: s1.s1 + Function Call: generate_series(1, 3) + -> HashAggregate + Output: s2.s2, sum((s1.s1 + s2.s2)) + Group Key: s2.s2 + -> Function Scan on pg_catalog.generate_series s2 + Output: s2.s2 + Function Call: generate_series(1, 3) +(14 rows) + +--Testcase 394: +select s1, s2, sm +from generate_series(1, 3) s1, + lateral (select s2, sum(s1 + s2) sm + from generate_series(1, 3) s2 group by s2) ss +order by 1, 2; + s1 | s2 | sm +----+----+---- + 1 | 1 | 2 + 1 | 2 | 3 + 1 | 3 | 4 + 2 | 1 | 3 + 2 | 2 | 4 + 2 | 3 | 5 + 3 | 1 | 4 + 3 | 2 | 5 + 3 | 3 | 6 +(9 rows) + +--Testcase 395: +explain (verbose, costs off) +select array(select sum(x+y) s + from generate_series(1,3) y group by y order by s) + from generate_series(1,3) x; + QUERY PLAN +------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series x + Output: ARRAY(SubPlan 1) + Function Call: generate_series(1, 3) + SubPlan 1 + -> Sort + Output: (sum((x.x + y.y))), y.y + Sort Key: (sum((x.x + y.y))) + -> HashAggregate + Output: sum((x.x + y.y)), y.y + Group Key: y.y + -> Function Scan on pg_catalog.generate_series y + Output: y.y + Function Call: generate_series(1, 3) +(13 rows) + +--Testcase 396: +select array(select sum(x+y) s + from generate_series(1,3) y group by y order by s) + from generate_series(1,3) x; + array +--------- + {2,3,4} + {3,4,5} + {4,5,6} +(3 rows) + +-- +-- test for bitwise integer aggregates +-- +--Testcase 397: +CREATE FOREIGN TABLE bitwise_test( + i2 INT2, + i4 INT4, + i8 INT8, + i INTEGER, + x INT2 +) SERVER sqlite_svr; +-- empty case +--Testcase 43: +SELECT + BIT_AND(i2) AS "?", + BIT_OR(i4) AS "?", + BIT_XOR(i8) AS "?" +FROM bitwise_test; + ? | ? | ? +---+---+--- + | | +(1 row) + +--Testcase 44: +INSERT INTO bitwise_test VALUES + (1, 1, 1, 1, 1), + (3, 3, 3, null, 2), + (7, 7, 7, 3, 4); +--Testcase 45: +SELECT + BIT_AND(i2) AS "1", + BIT_AND(i4) AS "1", + BIT_AND(i8) AS "1", + BIT_AND(i) AS "?", + BIT_AND(x) AS "0", + BIT_OR(i2) AS "7", + BIT_OR(i4) AS "7", + BIT_OR(i8) AS "7", + BIT_OR(i) AS "?", + BIT_OR(x) AS "7", + BIT_XOR(i2) AS "5", + BIT_XOR(i4) AS "5", + BIT_XOR(i8) AS "5", + BIT_XOR(i) AS "?", + BIT_XOR(x) AS "7" +FROM bitwise_test; + 1 | 1 | 1 | ? | 0 | 7 | 7 | 7 | ? | 7 | 5 | 5 | 5 | ? | 7 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- + 1 | 1 | 1 | 1 | 0 | 7 | 7 | 7 | 3 | 7 | 5 | 5 | 5 | 2 | 7 +(1 row) + +-- +-- test boolean aggregates +-- +-- first test all possible transition and final states +--Testcase 398: +CREATE FOREIGN TABLE bool_test_tmp( + b1 BOOL OPTIONS (key 'true'), + b2 BOOL OPTIONS (key 'true') +) SERVER sqlite_svr; +-- boolean and transitions +-- null because strict +BEGIN; +--Testcase 399: +INSERT INTO bool_test_tmp VALUES + (NULL, NULL), + (TRUE, NULL), + (FALSE, NULL), + (NULL, TRUE), + (NULL, FALSE); +--Testcase 400: +SELECT booland_statefunc(b1, b2) IS NULL as "t" FROM bool_test_tmp; + t +--- + t + t + t + t + t +(5 rows) + +ROLLBACK; +-- and actual computations +BEGIN; +--Testcase 401: +INSERT INTO bool_test_tmp VALUES + (TRUE, TRUE); +--Testcase 402: +SELECT booland_statefunc(b1, b2) as "t" FROM bool_test_tmp; + t +--- + t +(1 row) + +ROLLBACK; +BEGIN; +--Testcase 403: +INSERT INTO bool_test_tmp VALUES + (TRUE, FALSE), + (FALSE, TRUE), + (FALSE, FALSE); +--Testcase 404: +SELECT NOT booland_statefunc(b1, b2) as "t" FROM bool_test_tmp; + t +--- + t + t + t +(3 rows) + +ROLLBACK; +-- boolean or transitions +-- null because strict +BEGIN; +--Testcase 405: +INSERT INTO bool_test_tmp VALUES + (NULL, NULL), + (TRUE, NULL), + (FALSE, NULL), + (NULL, TRUE), + (NULL, FALSE); +--Testcase 406: +SELECT boolor_statefunc(b1, b2) IS NULL as "t" FROM bool_test_tmp; + t +--- + t + t + t + t + t +(5 rows) + +ROLLBACK; +-- actual computations +BEGIN; +--Testcase 407: +INSERT INTO bool_test_tmp VALUES + (TRUE, TRUE), + (TRUE, FALSE), + (FALSE, TRUE); +--Testcase 408: +SELECT boolor_statefunc(b1, b2) as "t" FROM bool_test_tmp; + t +--- + t + t + t +(3 rows) + +ROLLBACK; +BEGIN; +--Testcase 409: +INSERT INTO bool_test_tmp VALUES + (FALSE, FALSE); +--Testcase 410: +SELECT NOT boolor_statefunc(b1, b2) as "t" FROM bool_test_tmp; + t +--- + t +(1 row) + +ROLLBACK; +--Testcase 411: +CREATE FOREIGN TABLE bool_test( + b1 BOOL, + b2 BOOL, + b3 BOOL, + b4 BOOL +) SERVER sqlite_svr; +-- empty case +--Testcase 46: +SELECT + BOOL_AND(b1) AS "n", + BOOL_OR(b3) AS "n" +FROM bool_test; + n | n +---+--- + | +(1 row) + +--Testcase 47: +INSERT INTO bool_test VALUES + (TRUE, null, FALSE, null), + (FALSE, TRUE, null, null), + (null, TRUE, FALSE, null); +--Testcase 48: +SELECT + BOOL_AND(b1) AS "f", + BOOL_AND(b2) AS "t", + BOOL_AND(b3) AS "f", + BOOL_AND(b4) AS "n", + BOOL_AND(NOT b2) AS "f", + BOOL_AND(NOT b3) AS "t" +FROM bool_test; + f | t | f | n | f | t +---+---+---+---+---+--- + f | t | f | | f | t +(1 row) + +--Testcase 49: +SELECT + EVERY(b1) AS "f", + EVERY(b2) AS "t", + EVERY(b3) AS "f", + EVERY(b4) AS "n", + EVERY(NOT b2) AS "f", + EVERY(NOT b3) AS "t" +FROM bool_test; + f | t | f | n | f | t +---+---+---+---+---+--- + f | t | f | | f | t +(1 row) + +--Testcase 50: +SELECT + BOOL_OR(b1) AS "t", + BOOL_OR(b2) AS "t", + BOOL_OR(b3) AS "f", + BOOL_OR(b4) AS "n", + BOOL_OR(NOT b2) AS "f", + BOOL_OR(NOT b3) AS "t" +FROM bool_test; + t | t | f | n | f | t +---+---+---+---+---+--- + t | t | f | | f | t +(1 row) + +-- +-- Test cases that should be optimized into indexscans instead of +-- the generic aggregate implementation. +-- +-- Basic cases +--Testcase 51: +explain (costs off) + select min(unique1) from tenk1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 52: +select min(unique1) from tenk1; + min +----- + 0 +(1 row) + +--Testcase 53: +explain (costs off) + select max(unique1) from tenk1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 54: +select max(unique1) from tenk1; + max +------ + 9999 +(1 row) + +--Testcase 55: +explain (costs off) + select max(unique1) from tenk1 where unique1 < 42; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 56: +select max(unique1) from tenk1 where unique1 < 42; + max +----- + 41 +(1 row) + +--Testcase 57: +explain (costs off) + select max(unique1) from tenk1 where unique1 > 42; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 58: +select max(unique1) from tenk1 where unique1 > 42; + max +------ + 9999 +(1 row) + +-- the planner may choose a generic aggregate here if parallel query is +-- enabled, since that plan will be parallel safe and the "optimized" +-- plan, which has almost identical cost, will not be. we want to test +-- the optimized plan, so temporarily disable parallel query. +begin; +--Testcase 628: +set local max_parallel_workers_per_gather = 0; +--Testcase 59: +explain (costs off) + select max(unique1) from tenk1 where unique1 > 42000; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 60: +select max(unique1) from tenk1 where unique1 > 42000; + max +----- + +(1 row) + +rollback; +-- multi-column index (uses tenk1_thous_tenthous) +--Testcase 61: +explain (costs off) + select max(tenthous) from tenk1 where thousand = 33; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 62: +select max(tenthous) from tenk1 where thousand = 33; + max +------ + 9033 +(1 row) + +--Testcase 63: +explain (costs off) + select min(tenthous) from tenk1 where thousand = 33; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 64: +select min(tenthous) from tenk1 where thousand = 33; + min +----- + 33 +(1 row) + +-- check parameter propagation into an indexscan subquery +--Testcase 65: +explain (costs off) + select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt + from int4_tbl; + QUERY PLAN +-------------------------- + Foreign Scan on int4_tbl + SubPlan 1 + -> Foreign Scan +(3 rows) + +--Testcase 66: +select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt + from int4_tbl; + f1 | gt +-------------+---- + 0 | 1 + 123456 | + -123456 | 0 + 2147483647 | + -2147483647 | 0 +(5 rows) + +-- check some cases that were handled incorrectly in 8.3.0 +--Testcase 67: +explain (costs off) + select distinct max(unique2) from tenk1; + QUERY PLAN +---------------------------------- + Unique + -> Sort + Sort Key: (max(unique2)) + -> Foreign Scan +(4 rows) + +--Testcase 68: +select distinct max(unique2) from tenk1; + max +------ + 9999 +(1 row) + +--Testcase 69: +explain (costs off) + select max(unique2) from tenk1 order by 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 70: +select max(unique2) from tenk1 order by 1; + max +------ + 9999 +(1 row) + +--Testcase 71: +explain (costs off) + select max(unique2) from tenk1 order by max(unique2); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 72: +select max(unique2) from tenk1 order by max(unique2); + max +------ + 9999 +(1 row) + +--Testcase 73: +explain (costs off) + select max(unique2) from tenk1 order by max(unique2)+1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 74: +select max(unique2) from tenk1 order by max(unique2)+1; + max +------ + 9999 +(1 row) + +--Testcase 75: +explain (costs off) + select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; + QUERY PLAN +------------------------------------------ + Sort + Sort Key: (generate_series(1, 3)) DESC + -> ProjectSet + -> Foreign Scan +(4 rows) + +--Testcase 76: +select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; + max | g +------+--- + 9999 | 3 + 9999 | 2 + 9999 | 1 +(3 rows) + +-- interesting corner case: constant gets optimized into a seqscan +--Testcase 77: +explain (costs off) + select max(100) from tenk1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 78: +select max(100) from tenk1; + max +----- + 100 +(1 row) + +-- try it on an inheritance tree +--Testcase 412: +create foreign table minmaxtest(f1 int) server sqlite_svr; +--Testcase 413: +create table minmaxtest1() inherits (minmaxtest); +--Testcase 414: +create table minmaxtest2() inherits (minmaxtest); +--Testcase 415: +create table minmaxtest3() inherits (minmaxtest); +--Testcase 416: +create index minmaxtest1i on minmaxtest1(f1); +--Testcase 417: +create index minmaxtest2i on minmaxtest2(f1 desc); +--Testcase 418: +create index minmaxtest3i on minmaxtest3(f1) where f1 is not null; +--Testcase 79: +insert into minmaxtest values(11), (12); +--Testcase 80: +insert into minmaxtest1 values(13), (14); +--Testcase 81: +insert into minmaxtest2 values(15), (16); +--Testcase 82: +insert into minmaxtest3 values(17), (18); +--Testcase 83: +explain (costs off) + select min(f1), max(f1) from minmaxtest; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Result + InitPlan 1 + -> Limit + -> Merge Append + Sort Key: minmaxtest.f1 + -> Foreign Scan on minmaxtest minmaxtest_1 + -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4 + InitPlan 2 + -> Limit + -> Merge Append + Sort Key: minmaxtest_5.f1 DESC + -> Foreign Scan on minmaxtest minmaxtest_6 + -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9 +(21 rows) + +--Testcase 84: +select min(f1), max(f1) from minmaxtest; + min | max +-----+----- + 11 | 18 +(1 row) + +-- DISTINCT doesn't do anything useful here, but it shouldn't fail +--Testcase 85: +explain (costs off) + select distinct min(f1), max(f1) from minmaxtest; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Unique + InitPlan 1 + -> Limit + -> Merge Append + Sort Key: minmaxtest.f1 + -> Foreign Scan on minmaxtest minmaxtest_1 + -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4 + InitPlan 2 + -> Limit + -> Merge Append + Sort Key: minmaxtest_5.f1 DESC + -> Foreign Scan on minmaxtest minmaxtest_6 + -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8 + Index Cond: (f1 IS NOT NULL) + -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9 + -> Sort + Sort Key: ((InitPlan 1).col1), ((InitPlan 2).col1) + -> Result +(24 rows) + +--Testcase 86: +select distinct min(f1), max(f1) from minmaxtest; + min | max +-----+----- + 11 | 18 +(1 row) + +-- DISTINCT can also trigger wrong answers with hash aggregation (bug #18465) +begin; +set local enable_sort = off; +--Testcase 709: +explain (costs off) + select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) + from int4_tbl t0; + QUERY PLAN +----------------------------------- + Foreign Scan on int4_tbl t0 + SubPlan 1 + -> HashAggregate + Group Key: (min(t1.f1)) + -> Foreign Scan +(5 rows) + +--Testcase 710: +select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) +from int4_tbl t0; + f1 | min +-------------+------------- + 0 | 0 + 123456 | 123456 + -123456 | -123456 + 2147483647 | 2147483647 + -2147483647 | -2147483647 +(5 rows) + +rollback; +-- check for correct detection of nested-aggregate errors +--Testcase 87: +select max(min(unique1)) from tenk1; +ERROR: aggregate function calls cannot be nested +LINE 1: select max(min(unique1)) from tenk1; + ^ +--Testcase 88: +select (select max(min(unique1)) from int8_tbl) from tenk1; +ERROR: aggregate function calls cannot be nested +LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1; + ^ +--Testcase 711: +select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) + from tenk1 a1(col1))) +from tenk1 a2(col2); +ERROR: aggregate function calls cannot be nested +LINE 1: select avg((select avg(a1.col1 order by (select avg(a2.col2)... + ^ +-- +-- Test removal of redundant GROUP BY columns +-- +--Testcase 419: +create foreign table agg_t1 (a int OPTIONS (key 'true'), b int OPTIONS (key 'true'), c int, d int) server sqlite_svr; +--Testcase 420: +create foreign table agg_t2 (x int OPTIONS (key 'true'), y int OPTIONS (key 'true'), z int) server sqlite_svr; +--Testcase 421: +create foreign table agg_t9 (a int OPTIONS (key 'true'), b int OPTIONS (key 'true'), c int) server sqlite_svr; +-- Non-primary-key columns can be removed from GROUP BY +--Testcase 89: +explain (costs off) select * from agg_t1 group by a,b,c,d; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- No removal can happen if the complete PK is not present in GROUP BY +--Testcase 90: +explain (costs off) select a,c from agg_t1 group by a,c,d; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Test removal across multiple relations +--Testcase 91: +explain (costs off) select * +from agg_t1 inner join agg_t2 on agg_t1.a = agg_t2.x and agg_t1.b = agg_t2.y +group by agg_t1.a,agg_t1.b,agg_t1.c,agg_t1.d,agg_t2.x,agg_t2.y,agg_t2.z; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Test case where agg_t1 can be optimized but not agg_t2 +--Testcase 92: +explain (costs off) select agg_t1.*,agg_t2.x,agg_t2.z +from agg_t1 inner join agg_t2 on agg_t1.a = agg_t2.x and agg_t1.b = agg_t2.y +group by agg_t1.a,agg_t1.b,agg_t1.c,agg_t1.d,agg_t2.x,agg_t2.z; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Cannot optimize when PK is deferrable +--Testcase 422: +explain (costs off) select * from agg_t9 group by a,b,c; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 423: +create temp table t1c () inherits (agg_t1); +-- Ensure we don't remove any columns when t1 has a child table +--Testcase 424: +explain (costs off) select * from agg_t1 group by a,b,c,d; + QUERY PLAN +----------------------------------------------------- + HashAggregate + Group Key: agg_t1.a, agg_t1.b, agg_t1.c, agg_t1.d + -> Append + -> Foreign Scan on agg_t1 agg_t1_1 + -> Seq Scan on t1c agg_t1_2 +(5 rows) + +-- Okay to remove columns if we're only querying the parent. +--Testcase 425: +explain (costs off) select * from only agg_t1 group by a,b,c,d; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Skip this test, sqlite_fdw does not support partition table +--create foreign table p_t1 ( +-- a int options (key 'true'), +-- b int options (key 'true'), +-- c int, +-- d int, +--) partition by list(a) server sqlite_svr; +--create temp table p_t1_1 partition of p_t1 for values in(1); +--create temp table p_t1_2 partition of p_t1 for values in(2); +-- Ensure we can remove non-PK columns for partitioned tables. +--explain (costs off) select * from p_t1 group by a,b,c,d; +--drop table t1 cascade; +--drop table t2; +--drop table t3; +--drop table p_t1; +-- +-- Test GROUP BY matching of join columns that are type-coerced due to USING +-- +--Testcase 426: +create foreign table t1(f1 int, f2 int) server sqlite_svr; +--Testcase 427: +create foreign table t2(f1 bigint, f2 oid) server sqlite_svr; +--Testcase 428: +select f1 from t1 left join t2 using (f1) group by f1; + f1 +---- +(0 rows) + +--Testcase 429: +select f1 from t1 left join t2 using (f1) group by t1.f1; + f1 +---- +(0 rows) + +--Testcase 430: +select t1.f1 from t1 left join t2 using (f1) group by t1.f1; + f1 +---- +(0 rows) + +-- only this one should fail: +--Testcase 431: +select t1.f1 from t1 left join t2 using (f1) group by f1; +ERROR: column "t1.f1" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: select t1.f1 from t1 left join t2 using (f1) group by f1; + ^ +-- check case where we have to inject nullingrels into coerced join alias +--Testcase 712: +select f1, count(*) from +t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) +group by f1; + f1 | count +----+------- +(0 rows) + +-- same, for a RelabelType coercion +--Testcase 713: +select f2, count(*) from +t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) +group by f2; + f2 | count +----+------- +(0 rows) + +--Testcase 432: +drop foreign table t1, t2; +-- +-- Test planner's selection of pathkeys for ORDER BY aggregates +-- +-- Ensure we order by four. This suits the most aggregate functions. +--Testcase 714: +explain (costs off) +select sum(two order by two),max(four order by four), min(four order by four) +from tenk1; + QUERY PLAN +----------------------------- + Aggregate + -> Foreign Scan on tenk1 +(2 rows) + +-- Ensure we order by two. It's a tie between ordering by two and four but +-- we tiebreak on the aggregate's position. +--Testcase 715: +explain (costs off) +select + sum(two order by two), max(four order by four), + min(four order by four), max(two order by two) +from tenk1; + QUERY PLAN +----------------------------- + Aggregate + -> Foreign Scan on tenk1 +(2 rows) + +-- Similar to above, but tiebreak on ordering by four +--Testcase 716: +explain (costs off) +select + max(four order by four), sum(two order by two), + min(four order by four), max(two order by two) +from tenk1; + QUERY PLAN +----------------------------- + Aggregate + -> Foreign Scan on tenk1 +(2 rows) + +-- Ensure this one orders by ten since there are 3 aggregates that require ten +-- vs two that suit two and four. +--Testcase 717: +explain (costs off) +select + max(four order by four), sum(two order by two), + min(four order by four), max(two order by two), + sum(ten order by ten), min(ten order by ten), max(ten order by ten) +from tenk1; + QUERY PLAN +----------------------------- + Aggregate + -> Foreign Scan on tenk1 +(2 rows) + +-- Try a case involving a GROUP BY clause where the GROUP BY column is also +-- part of an aggregate's ORDER BY clause. We want a sort order that works +-- for the GROUP BY along with the first and the last aggregate. +--Testcase 718: +explain (costs off) +select + sum(unique1 order by ten, two), sum(unique1 order by four), + sum(unique1 order by two, four) +from tenk1 +group by ten; + QUERY PLAN +----------------------------- + GroupAggregate + Group Key: ten + -> Foreign Scan on tenk1 +(3 rows) + +-- Ensure that we never choose to provide presorted input to an Aggref with +-- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure +-- these sorts are performed individually rather than at the query level. +--Testcase 719: +explain (costs off) +select + sum(unique1 order by two), sum(unique1 order by four), + sum(unique1 order by four, two), sum(unique1 order by two, random()), + sum(unique1 order by two, random(), random() + 1) +from tenk1 +group by ten; + QUERY PLAN +----------------------------- + GroupAggregate + Group Key: ten + -> Foreign Scan on tenk1 +(3 rows) + +-- Ensure consecutive NULLs are properly treated as distinct from each other +--Testcase 720: +select array_agg(distinct val) +from (select null as val from generate_series(1, 2)); + array_agg +----------- + {NULL} +(1 row) + +-- Ensure no ordering is requested when enable_presorted_aggregate is off +set enable_presorted_aggregate to off; +--Testcase 721: +explain (costs off) +select sum(two order by two) from tenk1; + QUERY PLAN +----------------------------- + Aggregate + -> Foreign Scan on tenk1 +(2 rows) + +reset enable_presorted_aggregate; +-- +-- Test combinations of DISTINCT and/or ORDER BY +-- +begin; +--Testcase 93: +delete from INT8_TBL; +--Testcase 94: +insert into INT8_TBL values (1,4),(2,3),(3,1),(4,2); +--Testcase 95: +select array_agg(q1 order by q2) + from INT8_TBL; + array_agg +----------- + {3,4,2,1} +(1 row) + +--Testcase 96: +select array_agg(q1 order by q1) + from INT8_TBL; + array_agg +----------- + {1,2,3,4} +(1 row) + +--Testcase 97: +select array_agg(q1 order by q1 desc) + from INT8_TBL; + array_agg +----------- + {4,3,2,1} +(1 row) + +--Testcase 98: +select array_agg(q2 order by q1 desc) + from INT8_TBL; + array_agg +----------- + {2,1,3,4} +(1 row) + +--Testcase 99: +delete from INT4_TBL; +--Testcase 100: +insert into INT4_TBL values (1),(2),(1),(3),(null),(2); +--Testcase 101: +select array_agg(distinct f1) + from INT4_TBL; + array_agg +-------------- + {1,2,3,NULL} +(1 row) + +--Testcase 102: +select array_agg(distinct f1 order by f1) + from INT4_TBL; + array_agg +-------------- + {1,2,3,NULL} +(1 row) + +--Testcase 103: +select array_agg(distinct f1 order by f1 desc) + from INT4_TBL; + array_agg +-------------- + {NULL,3,2,1} +(1 row) + +--Testcase 104: +select array_agg(distinct f1 order by f1 desc nulls last) + from INT4_TBL; + array_agg +-------------- + {3,2,1,NULL} +(1 row) + +rollback; +-- multi-arg aggs, strict/nonstrict, distinct/order by +--Testcase 433: +create type aggtype as (a integer, b integer, c text); +--Testcase 434: +create function aggf_trans(aggtype[],integer,integer,text) returns aggtype[] +as 'select array_append($1,ROW($2,$3,$4)::aggtype)' +language sql strict immutable; +--Testcase 435: +create function aggfns_trans(aggtype[],integer,integer,text) returns aggtype[] +as 'select array_append($1,ROW($2,$3,$4)::aggtype)' +language sql immutable; +--Testcase 436: +create aggregate aggfstr(integer,integer,text) ( + sfunc = aggf_trans, stype = aggtype[], + initcond = '{}' +); +--Testcase 437: +create aggregate aggfns(integer,integer,text) ( + sfunc = aggfns_trans, stype = aggtype[], sspace = 10000, + initcond = '{}' +); +begin; +--Testcase 105: +insert into multi_arg_agg values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz'); +--Testcase 106: +select aggfstr(a,b,c) from multi_arg_agg; + aggfstr +--------------------------------------- + {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 107: +select aggfns(a,b,c) from multi_arg_agg; + aggfns +----------------------------------------------- + {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 108: +select aggfstr(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; + aggfstr +--------------------------------------- + {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 109: +select aggfns(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; + aggfns +----------------------------------------------- + {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 110: +select aggfstr(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; + aggfstr +--------------------------------------- + {"(3,1,baz)","(2,2,bar)","(1,3,foo)"} +(1 row) + +--Testcase 111: +select aggfns(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; + aggfns +----------------------------------------------- + {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} +(1 row) + +-- test specific code paths +--Testcase 112: +select aggfns(distinct a,a,c order by c using ~<~,a) from multi_arg_agg, generate_series(1,2) i; + aggfns +------------------------------------------------ + {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} +(1 row) + +--Testcase 113: +select aggfns(distinct a,a,c order by c using ~<~) from multi_arg_agg, generate_series(1,2) i; + aggfns +------------------------------------------------ + {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} +(1 row) + +--Testcase 114: +select aggfns(distinct a,a,c order by a) from multi_arg_agg, generate_series(1,2) i; + aggfns +------------------------------------------------ + {"(0,0,)","(1,1,foo)","(2,2,bar)","(3,3,baz)"} +(1 row) + +--Testcase 115: +select aggfns(distinct a,b,c order by a,c using ~<~,b) from multi_arg_agg, generate_series(1,2) i; + aggfns +----------------------------------------------- + {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +-- test a more complex permutation that has previous caused issues +--Testcase 761: +create foreign table agg_t22 (c1 text, id int) server sqlite_svr; +--Testcase 762: +create foreign table agg_t23 (id int) server sqlite_svr; +--Testcase 763: +insert into agg_t22 values ('a', 1); +--Testcase 764: +insert into agg_t23 values (1); +--Testcase 765: +select + string_agg(distinct c1, ','), + sum(( + select sum(b.id) + from agg_t23 b + where a.id = b.id +)) from agg_t22 a; + string_agg | sum +------------+----- + a | 1 +(1 row) + +-- check node I/O via view creation and usage, also deparsing logic +--Testcase 438: +create view agg_view1 as + select aggfns(a,b,c) from multi_arg_agg; +--Testcase 116: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 117: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +----------------------------------- + SELECT aggfns(a, b, c) AS aggfns+ + FROM multi_arg_agg; +(1 row) + +--Testcase 439: +create or replace view agg_view1 as + select aggfns(distinct a,b,c) from multi_arg_agg, generate_series(1,3) i; +--Testcase 118: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 119: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +-------------------------------------------------------------------------------------- + SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c) AS aggfns+ + FROM multi_arg_agg, + + generate_series(1, 3) i(i); +(1 row) + +--Testcase 440: +create or replace view agg_view1 as + select aggfns(distinct a,b,c order by b) from multi_arg_agg, generate_series(1,3) i; +--Testcase 120: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} +(1 row) + +--Testcase 121: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +--------------------------------------------------------------------------------------------------------------- + SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY multi_arg_agg.b) AS aggfns+ + FROM multi_arg_agg, + + generate_series(1, 3) i(i); +(1 row) + +--Testcase 441: +create or replace view agg_view1 as + select aggfns(a,b,c order by b+1) from multi_arg_agg; +--Testcase 122: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} +(1 row) + +--Testcase 123: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +---------------------------------------------------- + SELECT aggfns(a, b, c ORDER BY (b + 1)) AS aggfns+ + FROM multi_arg_agg; +(1 row) + +--Testcase 442: +create or replace view agg_view1 as + select aggfns(a,a,c order by b) from multi_arg_agg; +--Testcase 124: +select * from agg_view1; + aggfns +------------------------------------------------ + {"(3,3,baz)","(2,2,bar)","(1,1,foo)","(0,0,)"} +(1 row) + +--Testcase 125: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +---------------------------------------------- + SELECT aggfns(a, a, c ORDER BY b) AS aggfns+ + FROM multi_arg_agg; +(1 row) + +--Testcase 443: +create or replace view agg_view1 as + select aggfns(a,b,c order by c using ~<~) from multi_arg_agg; +--Testcase 126: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(2,2,bar)","(3,1,baz)","(1,3,foo)","(0,,)"} +(1 row) + +--Testcase 127: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +------------------------------------------------------------------- + SELECT aggfns(a, b, c ORDER BY c USING ~<~ NULLS LAST) AS aggfns+ + FROM multi_arg_agg; +(1 row) + +--Testcase 444: +create or replace view agg_view1 as + select aggfns(distinct a,b,c order by a,c using ~<~,b) from multi_arg_agg, generate_series(1,2) i; +--Testcase 128: +select * from agg_view1; + aggfns +----------------------------------------------- + {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} +(1 row) + +--Testcase 129: +select pg_get_viewdef('agg_view1'::regclass); + pg_get_viewdef +---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT aggfns(DISTINCT multi_arg_agg.a, multi_arg_agg.b, multi_arg_agg.c ORDER BY multi_arg_agg.a, multi_arg_agg.c USING ~<~ NULLS LAST, multi_arg_agg.b) AS aggfns+ + FROM multi_arg_agg, + + generate_series(1, 2) i(i); +(1 row) + +--Testcase 445: +drop view agg_view1; +rollback; +-- incorrect DISTINCT usage errors +--Testcase 130: +insert into multi_arg_agg values (1,1,'foo'); +--Testcase 131: +select aggfns(distinct a,b,c order by i) from multi_arg_agg, generate_series(1,2) i; +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select aggfns(distinct a,b,c order by i) from multi_arg_agg,... + ^ +--Testcase 132: +select aggfns(distinct a,b,c order by a,b+1) from multi_arg_agg, generate_series(1,2) i; +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select aggfns(distinct a,b,c order by a,b+1) from multi_arg_... + ^ +--Testcase 133: +select aggfns(distinct a,b,c order by a,b,i,c) from multi_arg_agg, generate_series(1,2) i; +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select aggfns(distinct a,b,c order by a,b,i,c) from multi_ar... + ^ +--Testcase 134: +select aggfns(distinct a,a,c order by a,b) from multi_arg_agg, generate_series(1,2) i; +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select aggfns(distinct a,a,c order by a,b) from multi_arg_ag... + ^ +-- string_agg tests +begin; +--Testcase 135: +delete from varchar_tbl; +--Testcase 136: +insert into varchar_tbl values ('aaaa'),('bbbb'),('cccc'); +--Testcase 137: +select string_agg(f1,',') from varchar_tbl; + string_agg +---------------- + aaaa,bbbb,cccc +(1 row) + +--Testcase 138: +delete from varchar_tbl; +--Testcase 139: +insert into varchar_tbl values ('aaaa'),(null),('bbbb'),('cccc'); +--Testcase 140: +select string_agg(f1,',') from varchar_tbl; + string_agg +---------------- + aaaa,bbbb,cccc +(1 row) + +--Testcase 141: +delete from varchar_tbl; +--Testcase 142: +insert into varchar_tbl values (null),(null),('bbbb'),('cccc'); +--Testcase 143: +select string_agg(f1,'AB') from varchar_tbl; + string_agg +------------ + bbbbABcccc +(1 row) + +--Testcase 144: +delete from varchar_tbl; +--Testcase 145: +insert into varchar_tbl values (null),(null); +--Testcase 146: +select string_agg(f1,',') from varchar_tbl; + string_agg +------------ + +(1 row) + +rollback; +-- check some implicit casting cases, as per bug #5564 +--Testcase 147: +select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok + string_agg +------------ + a,ab,abcd +(1 row) + +--Testcase 148: +select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select string_agg(distinct f1::text, ',' order by f1) from v... + ^ +--Testcase 149: +select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok +ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list +LINE 1: select string_agg(distinct f1, ',' order by f1::text) from v... + ^ +--Testcase 150: +select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok + string_agg +------------ + a,ab,abcd +(1 row) + +-- string_agg bytea tests +--Testcase 446: +create foreign table bytea_test_table(v bytea) server sqlite_svr; +--Testcase 151: +select string_agg(v, '') from bytea_test_table; + string_agg +------------ + +(1 row) + +--Testcase 152: +insert into bytea_test_table values(decode('ff','hex')); +--Testcase 153: +select string_agg(v, '') from bytea_test_table; + string_agg +------------ + \xff +(1 row) + +--Testcase 154: +insert into bytea_test_table values(decode('aa','hex')); +--Testcase 155: +select string_agg(v, '') from bytea_test_table; + string_agg +------------ + \xffaa +(1 row) + +--Testcase 156: +select string_agg(v, NULL) from bytea_test_table; + string_agg +------------ + \xffaa +(1 row) + +--Testcase 157: +select string_agg(v, decode('ee', 'hex')) from bytea_test_table; + string_agg +------------ + \xffeeaa +(1 row) + +--Testcase 447: +drop foreign table bytea_test_table; +-- Test parallel string_agg and array_agg +--Testcase 723: +create foreign table pagg_test (x int, y int) server sqlite_svr; +--Testcase 724: +insert into pagg_test +select (case x % 4 when 1 then null else x end), x % 10 +from generate_series(1,5000) x; +set parallel_setup_cost TO 0; +set parallel_tuple_cost TO 0; +set parallel_leader_participation TO 0; +set min_parallel_table_scan_size = 0; +set bytea_output = 'escape'; +set max_parallel_workers_per_gather = 2; +-- create a view as we otherwise have to repeat this query a few times. +--Testcase 725: +create view v_pagg_test AS +select + y, + min(t) AS tmin,max(t) AS tmax,count(distinct t) AS tndistinct, + min(b) AS bmin,max(b) AS bmax,count(distinct b) AS bndistinct, + min(a) AS amin,max(a) AS amax,count(distinct a) AS andistinct, + min(aa) AS aamin,max(aa) AS aamax,count(distinct aa) AS aandistinct +from ( + select + y, + unnest(regexp_split_to_array(a1.t, ','))::int AS t, + unnest(regexp_split_to_array(a1.b::text, ',')) AS b, + unnest(a1.a) AS a, + unnest(a1.aa) AS aa + from ( + select + y, + string_agg(x::text, ',') AS t, + string_agg(x::text::bytea, ',') AS b, + array_agg(x) AS a, + array_agg(ARRAY[x]) AS aa + from pagg_test + group by y + ) a1 +) a2 +group by y; +-- Ensure results are correct. +--Testcase 726: +select * from v_pagg_test order by y; + y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct +---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- + 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 + 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 + 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 + 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 + 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 + 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 + 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 + 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 + 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 + 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 +(10 rows) + +-- Ensure parallel aggregation is actually being used. +--Testcase 727: +explain (costs off) select * from v_pagg_test order by y; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Group Key: pagg_test.y + -> Sort + Sort Key: pagg_test.y, (((unnest(regexp_split_to_array((string_agg((pagg_test.x)::text, ','::text)), ','::text))))::integer) + -> Result + -> ProjectSet + -> GroupAggregate + Group Key: pagg_test.y + -> Foreign Scan on pagg_test +(9 rows) + +set max_parallel_workers_per_gather = 0; +-- Ensure results are the same without parallel aggregation. +--Testcase 728: +select * from v_pagg_test order by y; + y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct +---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- + 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 + 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 + 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 + 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 + 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 + 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 + 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 + 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 + 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 + 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 +(10 rows) + +-- Clean up +reset max_parallel_workers_per_gather; +reset bytea_output; +reset min_parallel_table_scan_size; +reset parallel_leader_participation; +reset parallel_tuple_cost; +reset parallel_setup_cost; +--Testcase 729: +drop view v_pagg_test; +--Testcase 730: +drop foreign table pagg_test; +-- FILTER tests +--Testcase 158: +select min(unique1) filter (where unique1 > 100) from tenk1; + min +----- + 101 +(1 row) + +--Testcase 159: +select sum(1/ten) filter (where ten > 0) from tenk1; + sum +------ + 1000 +(1 row) + +--Testcase 160: +select ten, sum(distinct four) filter (where four::text ~ '123') from onek a +group by ten; + ten | sum +-----+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +--Testcase 161: +select ten, sum(distinct four) filter (where four > 10) from onek a +group by ten +having exists (select 1 from onek b where sum(distinct a.four) = b.four); + ten | sum +-----+----- + 0 | + 2 | + 4 | + 6 | + 8 | +(5 rows) + +--Testcase 448: +create foreign table agg_t17(foo text, bar text) server sqlite_svr; +--Testcase 449: +insert into agg_t17 values ('a', 'b'); +--Testcase 450: +select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0') +from agg_t17; + max +----- + a +(1 row) + +--Testcase 731: +create foreign table agg_t170(v int) server sqlite_svr; +--Testcase 732: +insert into agg_t170(v) values (1), (2), (3); +--Testcase 733: +select any_value(v) filter (where v > 2) from agg_t170; + any_value +----------- + 3 +(1 row) + +-- outer reference in FILTER (PostgreSQL extension) +--Testcase 451: +create foreign table agg_t18 (inner_c int) server sqlite_svr; +--Testcase 452: +create foreign table agg_t19 (outer_c int) server sqlite_svr; +--Testcase 453: +insert into agg_t18 values (1); +--Testcase 454: +insert into agg_t19 values (2), (3); +--Testcase 455: +select (select count(*) + from agg_t18) from agg_t19; -- inner query is aggregation query + count +------- + 1 + 1 +(2 rows) + +--Testcase 456: +select (select count(*) filter (where outer_c <> 0) + from agg_t18) from agg_t19; -- outer query is aggregation query + count +------- + 2 +(1 row) + +--Testcase 457: +select (select count(inner_c) filter (where outer_c <> 0) + from agg_t18) from agg_t19; -- inner query is aggregation query + count +------- + 1 + 1 +(2 rows) + +--Testcase 162: +select + (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)) + filter (where o.unique1 < 10)) +from tenk1 o; -- outer query is aggregation query + max +------ + 9998 +(1 row) + +-- subquery in FILTER clause (PostgreSQL extension) +--Testcase 163: +select sum(unique1) FILTER (WHERE + unique1 IN (SELECT unique1 FROM onek where unique1 < 100)) FROM tenk1; + sum +------ + 4950 +(1 row) + +-- exercise lots of aggregate parts with FILTER +begin; +--Testcase 164: +delete from multi_arg_agg; +--Testcase 165: +insert into multi_arg_agg values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz'); +--Testcase 166: +select aggfns(distinct a,b,c order by a,c using ~<~,b) filter (where a > 1) from multi_arg_agg, generate_series(1,2) i; + aggfns +--------------------------- + {"(2,2,bar)","(3,1,baz)"} +(1 row) + +rollback; +-- check handling of bare boolean Var in FILTER +--Testcase 672: +select max(0) filter (where b1) from bool_test; + max +----- + 0 +(1 row) + +--Testcase 673: +select (select max(0) filter (where b1)) from bool_test; + max +----- + 0 +(1 row) + +-- check for correct detection of nested-aggregate errors in FILTER +--Testcase 674: +select max(unique1) filter (where sum(ten) > 0) from tenk1; +ERROR: aggregate functions are not allowed in FILTER +LINE 1: select max(unique1) filter (where sum(ten) > 0) from tenk1; + ^ +--Testcase 675: +select (select max(unique1) filter (where sum(ten) > 0) from int8_tbl) from tenk1; +ERROR: aggregate function calls cannot be nested +LINE 1: select (select max(unique1) filter (where sum(ten) > 0) from... + ^ +--Testcase 676: +select max(unique1) filter (where bool_or(ten > 0)) from tenk1; +ERROR: aggregate functions are not allowed in FILTER +LINE 1: select max(unique1) filter (where bool_or(ten > 0)) from ten... + ^ +--Testcase 677: +select (select max(unique1) filter (where bool_or(ten > 0)) from int8_tbl) from tenk1; +ERROR: aggregate function calls cannot be nested +LINE 1: select (select max(unique1) filter (where bool_or(ten > 0)) ... + ^ +-- ordered-set aggregates +begin; +--Testcase 167: +delete from FLOAT8_TBL; +--Testcase 168: +insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); +--Testcase 169: +select f1, percentile_cont(f1) within group (order by x::float8) +from generate_series(1,5) x, + FLOAT8_TBL +group by f1 order by f1; + f1 | percentile_cont +------+----------------- + 0 | 1 + 0.1 | 1.4 + 0.25 | 2 + 0.4 | 2.6 + 0.5 | 3 + 0.6 | 3.4 + 0.75 | 4 + 0.9 | 4.6 + 1 | 5 +(9 rows) + +rollback; +begin; +--Testcase 170: +delete from FLOAT8_TBL; +--Testcase 171: +insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); +--Testcase 172: +select f1, percentile_cont(f1 order by f1) within group (order by x) -- error +from generate_series(1,5) x, + FLOAT8_TBL +group by f1 order by f1; +ERROR: cannot use multiple ORDER BY clauses with WITHIN GROUP +LINE 1: select f1, percentile_cont(f1 order by f1) within group (ord... + ^ +rollback; +begin; +--Testcase 173: +delete from FLOAT8_TBL; +--Testcase 174: +insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); +--Testcase 175: +select f1, sum() within group (order by x::float8) -- error +from generate_series(1,5) x, + FLOAT8_TBL +group by f1 order by f1; +ERROR: sum is not an ordered-set aggregate, so it cannot have WITHIN GROUP +LINE 1: select f1, sum() within group (order by x::float8) -- error + ^ +rollback; +begin; +--Testcase 176: +delete from FLOAT8_TBL; +--Testcase 177: +insert into FLOAT8_TBL values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1); +--Testcase 178: +select f1, percentile_cont(f1,f1) -- error +from generate_series(1,5) x, + FLOAT8_TBL +group by f1 order by f1; +ERROR: WITHIN GROUP is required for ordered-set aggregate percentile_cont +LINE 1: select f1, percentile_cont(f1,f1) -- error + ^ +rollback; +--Testcase 179: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 693: +select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; + percentile_cont +----------------- + 53.4485001564 +(1 row) + +--Testcase 180: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 694: +select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; + percentile_cont | sum +-----------------+--------- + 53.4485001564 | 431.773 +(1 row) + +--Testcase 181: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 695: +select percentile_cont(0.5) within group (order by thousand) from tenk1; + percentile_cont +----------------- + 499.5 +(1 row) + +--Testcase 182: +select percentile_disc(0.5) within group (order by thousand) from tenk1; + percentile_disc +----------------- + 499 +(1 row) + +begin; +--Testcase 183: +delete from INT4_TBL; +--Testcase 184: +insert into INT4_TBL values (1),(1),(2),(2),(3),(3),(4); +--Testcase 185: +select rank(3) within group (order by f1) from INT4_TBL; + rank +------ + 5 +(1 row) + +--Testcase 186: +select cume_dist(3) within group (order by f1) from INT4_TBL; + cume_dist +----------- + 0.875 +(1 row) + +--Testcase 187: +insert into INT4_TBL values (5); +--Testcase 458: +-- Round the result to limited digits to avoid platform-specific results. +--Testcase 696: +select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; + percent_rank +-------------- + 0.5000000000 +(1 row) + +--Testcase 459: +delete from INT4_TBL where f1 = 5; +--Testcase 188: +select dense_rank(3) within group (order by f1) from INT4_TBL; + dense_rank +------------ + 3 +(1 row) + +rollback; +--Testcase 189: +select percentile_disc(array[0,0.1,0.25,0.5,0.75,0.9,1]) within group (order by thousand) +from tenk1; + percentile_disc +---------------------------- + {0,99,249,499,749,899,999} +(1 row) + +--Testcase 190: +select percentile_cont(array[0,0.25,0.5,0.75,1]) within group (order by thousand) +from tenk1; + percentile_cont +----------------------------- + {0,249.75,499.5,749.25,999} +(1 row) + +--Testcase 191: +select percentile_disc(array[[null,1,0.5],[0.75,0.25,null]]) within group (order by thousand) +from tenk1; + percentile_disc +--------------------------------- + {{NULL,999,499},{749,249,NULL}} +(1 row) + +--Testcase 460: +create foreign table agg_t21 (x int) server sqlite_svr; +begin; +--Testcase 248: +insert into agg_t21 select * from generate_series(1,6); +--Testcase 249: +select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x) +from agg_t21; + percentile_cont +------------------------------------------ + {1,6,2.25,4.75,3.5,6,2.5,2.6,2.75,2.9,3} +(1 row) + +rollback; +--Testcase 192: +select ten, mode() within group (order by string4) from tenk1 group by ten; + ten | mode +-----+-------- + 0 | HHHHxx + 1 | OOOOxx + 2 | VVVVxx + 3 | OOOOxx + 4 | HHHHxx + 5 | HHHHxx + 6 | OOOOxx + 7 | AAAAxx + 8 | VVVVxx + 9 | VVVVxx +(10 rows) + +--Testcase 461: +create foreign table agg_t20 (x text) server sqlite_svr; +begin; +--Testcase 462: +insert into agg_t20 values (unnest('{fred,jim,fred,jack,jill,fred,jill,jim,jim,sheila,jim,sheila}'::text[])); +--Testcase 463: +select percentile_disc(array[0.25,0.5,0.75]) within group (order by x) from agg_t20; + percentile_disc +----------------- + {fred,jill,jim} +(1 row) + +rollback; +-- check collation propagates up in suitable cases: +begin; +--Testcase 464: +insert into agg_t20 values ('fred'), ('jim'); +--Testcase 465: +select pg_collation_for(percentile_disc(1) within group (order by x collate "POSIX")) from agg_t20; + pg_collation_for +------------------ + "POSIX" +(1 row) + +rollback; +-- ordered-set aggs created with CREATE AGGREGATE +--Testcase 466: +create aggregate my_percentile_disc(float8 ORDER BY anyelement) ( + stype = internal, + sfunc = ordered_set_transition, + finalfunc = percentile_disc_final, + finalfunc_extra = true, + finalfunc_modify = read_write +); +--Testcase 467: +create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") ( + stype = internal, + sfunc = ordered_set_transition_multi, + finalfunc = rank_final, + finalfunc_extra = true, + hypothetical +); +--Testcase 633: +alter aggregate my_percentile_disc(float8 ORDER BY anyelement) + rename to test_percentile_disc; + +--Testcase 634: +alter aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") + rename to test_rank; +begin; +--Testcase 468: +insert into agg_t21 values (1),(1),(2),(2),(3),(3),(4); +--Testcase 469: +select test_rank(3) within group (order by x) from agg_t21; + test_rank +----------- + 5 +(1 row) + +rollback; + +--Testcase 193: +select test_percentile_disc(0.5) within group (order by thousand) from tenk1; + test_percentile_disc +---------------------- + 499 +(1 row) + +-- ordered-set aggs can't use ungrouped vars in direct args: +begin; +--Testcase 470: +insert into agg_t21 select * from generate_series(1,5); +--Testcase 471: +select rank(x) within group (order by x) from agg_t21; +ERROR: column "agg_t21.x" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: select rank(x) within group (order by x) from agg_t21; + ^ +DETAIL: Direct arguments of an ordered-set aggregate must use only grouped columns. +rollback; +-- outer-level agg can't use a grouped arg of a lower level, either: +begin; +--Testcase 472: +insert into agg_t21 select * from generate_series(1,5); +--Testcase 473: +select array(select percentile_disc(a) within group (order by x) + from (values (0.3),(0.7)) v(a) group by a) + from agg_t21; +ERROR: outer-level aggregate cannot contain a lower-level variable in its direct arguments +LINE 1: select array(select percentile_disc(a) within group (order b... + ^ +rollback; +-- agg in the direct args is a grouping violation, too: +begin; +--Testcase 474: +insert into agg_t21 select * from generate_series(1,5); +--Testcase 475: +select rank(sum(x)) within group (order by x) from agg_t21; +ERROR: aggregate function calls cannot be nested +LINE 1: select rank(sum(x)) within group (order by x) from agg_t21; + ^ +rollback; +-- hypothetical-set type unification and argument-count failures: +begin; +--Testcase 264: +insert into agg_t20 values ('fred'), ('jim'); +--Testcase 265: +select rank(3) within group (order by x) from agg_t20; +ERROR: WITHIN GROUP types text and integer cannot be matched +LINE 1: select rank(3) within group (order by x) from agg_t20; + ^ +rollback; +--Testcase 194: +select rank(3) within group (order by stringu1,stringu2) from tenk1; +ERROR: function rank(integer, name, name) does not exist +LINE 1: select rank(3) within group (order by stringu1,stringu2) fro... + ^ +HINT: To use the hypothetical-set aggregate rank, the number of hypothetical direct arguments (here 1) must match the number of ordering columns (here 2). +begin; +--Testcase 476: +insert into agg_t21 select * from generate_series(1,5); +--Testcase 477: +select rank('fred') within group (order by x) from agg_t21; +ERROR: invalid input syntax for type integer: "fred" +LINE 1: select rank('fred') within group (order by x) from agg_t21; + ^ +rollback; +begin; +--Testcase 478: +insert into agg_t20 values ('fred'), ('jim'); +--Testcase 479: +select rank('adam'::text collate "C") within group (order by x collate "POSIX") + from agg_t20; +ERROR: collation mismatch between explicit collations "C" and "POSIX" +LINE 1: ...adam'::text collate "C") within group (order by x collate "P... + ^ +rollback; +-- hypothetical-set type unification successes: +begin; +--Testcase 480: +insert into agg_t20 values ('fred'), ('jim'); +--Testcase 481: +select rank('adam'::varchar) within group (order by x) from agg_t20; + rank +------ + 1 +(1 row) + +rollback; +begin; +--Testcase 482: +insert into agg_t21 select * from generate_series(1,5); +--Testcase 483: +select rank('3') within group (order by x) from agg_t21; + rank +------ + 3 +(1 row) + +rollback; +-- divide by zero check +begin; +--Testcase 484: +insert into agg_t21 select * from generate_series(1,0); +--Testcase 485: +select percent_rank(0) within group (order by x) from agg_t21; + percent_rank +-------------- + 0 +(1 row) + +rollback; +-- deparse and multiple features: +--Testcase 486: +create view aggordview1 as +select ten, + percentile_disc(0.5) within group (order by thousand) as p50, + percentile_disc(0.5) within group (order by thousand) filter (where hundred=1) as px, + rank(5,'AZZZZ',50) within group (order by hundred, string4 desc, hundred) + from tenk1 + group by ten order by ten; +--Testcase 196: +select pg_get_viewdef('aggordview1'); + pg_get_viewdef +------------------------------------------------------------------------------------------------------------------- + SELECT ten, + + percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY thousand) AS p50, + + percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY thousand) FILTER (WHERE (hundred = 1)) AS px,+ + rank(5, 'AZZZZ'::name, 50) WITHIN GROUP (ORDER BY hundred, string4 DESC, hundred) AS rank + + FROM tenk1 + + GROUP BY ten + + ORDER BY ten; +(1 row) + +--Testcase 197: +select * from aggordview1 order by ten; + ten | p50 | px | rank +-----+-----+-----+------ + 0 | 490 | | 101 + 1 | 491 | 401 | 101 + 2 | 492 | | 101 + 3 | 493 | | 101 + 4 | 494 | | 101 + 5 | 495 | | 67 + 6 | 496 | | 1 + 7 | 497 | | 1 + 8 | 498 | | 1 + 9 | 499 | | 1 +(10 rows) + +--Testcase 487: +drop view aggordview1; +-- variadic aggregates +--Testcase 488: +create function least_accum(anyelement, variadic anyarray) +returns anyelement language sql as + 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; +--Testcase 489: +create aggregate least_agg(variadic items anyarray) ( + stype = anyelement, sfunc = least_accum +); +--Testcase 490: +create function cleast_accum(anycompatible, variadic anycompatiblearray) +returns anycompatible language sql as + 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; +--Testcase 491: +create aggregate cleast_agg(variadic items anycompatiblearray) ( + stype = anycompatible, sfunc = cleast_accum); +--Testcase 198: +select least_agg(q1,q2) from int8_tbl; + least_agg +------------------- + -4567890123456789 +(1 row) + +--Testcase 199: +select least_agg(variadic array[q1,q2]) from int8_tbl; + least_agg +------------------- + -4567890123456789 +(1 row) + +--Testcase 492: +select cleast_agg(q1,q2) from int8_tbl; + cleast_agg +------------------- + -4567890123456789 +(1 row) + +--Testcase 493: +select cleast_agg(4.5,f1) from int4_tbl; + cleast_agg +------------- + -2147483647 +(1 row) + +--Testcase 494: +select cleast_agg(variadic array[4.5,f1]) from int4_tbl; + cleast_agg +------------- + -2147483647 +(1 row) + +--Testcase 495: +select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl; + pg_typeof +----------- + numeric +(1 row) + +-- test aggregates with common transition functions share the same states +--Testcase 496: +create foreign table agg_t10(one int, id int options (key 'true')) server sqlite_svr; +--Testcase 497: +create foreign table agg_t11(one int, two int, id int options (key 'true')) server sqlite_svr; +--Testcase 498: +create foreign table agg_t12(a int, id int options (key 'true')) server sqlite_svr; +begin work; +--Testcase 499: +create type avg_state as (total bigint, count bigint); +--Testcase 500: +create or replace function avg_transfn(state avg_state, n int) returns avg_state as +$$ +declare new_state avg_state; +begin + raise notice 'avg_transfn called with %', n; + if state is null then + if n is not null then + new_state.total := n; + new_state.count := 1; + return new_state; + end if; + return null; + elsif n is not null then + state.total := state.total + n; + state.count := state.count + 1; + return state; + end if; + + return null; +end +$$ language plpgsql; +--Testcase 501: +create function avg_finalfn(state avg_state) returns int4 as +$$ +begin + if state is null then + return NULL; + else + return state.total / state.count; + end if; +end +$$ language plpgsql; +--Testcase 502: +create function sum_finalfn(state avg_state) returns int4 as +$$ +begin + if state is null then + return NULL; + else + return state.total; + end if; +end +$$ language plpgsql; +--Testcase 503: +create aggregate my_avg(int4) +( + stype = avg_state, + sfunc = avg_transfn, + finalfunc = avg_finalfn +); +--Testcase 504: +create aggregate my_sum(int4) +( + stype = avg_state, + sfunc = avg_transfn, + finalfunc = sum_finalfn +); +-- aggregate state should be shared as aggs are the same. +--Testcase 505: +delete from agg_t10; +--Testcase 506: +insert into agg_t10 values (1), (3); +--Testcase 507: +select my_avg(one),my_avg(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 + my_avg | my_avg +--------+-------- + 2 | 2 +(1 row) + +-- aggregate state should be shared as transfn is the same for both aggs. +--Testcase 508: +select my_avg(one),my_sum(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 + my_avg | my_sum +--------+-------- + 2 | 4 +(1 row) + +-- same as previous one, but with DISTINCT, which requires sorting the input. +--Testcase 509: +delete from agg_t10; +--Testcase 510: +insert into agg_t10 values (1), (3), (1); +--Testcase 511: +select my_avg(distinct one),my_sum(distinct one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 + my_avg | my_sum +--------+-------- + 2 | 4 +(1 row) + +-- shouldn't share states due to the distinctness not matching. +--Testcase 512: +delete from agg_t10; +--Testcase 513: +insert into agg_t10 values (1), (3); +--Testcase 514: +select my_avg(distinct one),my_sum(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 +NOTICE: avg_transfn called with 3 + my_avg | my_sum +--------+-------- + 2 | 4 +(1 row) + +-- shouldn't share states due to the filter clause not matching. +--Testcase 515: +select my_avg(one) filter (where one > 1),my_sum(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 +NOTICE: avg_transfn called with 3 + my_avg | my_sum +--------+-------- + 3 | 4 +(1 row) + +-- this should not share the state due to different input columns. +--Testcase 516: +delete from agg_t11; +--Testcase 517: +insert into agg_t11 values (1,2),(3,4); +--Testcase 518: +select my_avg(one),my_sum(two) from agg_t11; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 2 +NOTICE: avg_transfn called with 3 +NOTICE: avg_transfn called with 4 + my_avg | my_sum +--------+-------- + 2 | 6 +(1 row) + +-- exercise cases where OSAs share state +--Testcase 519: +delete from agg_t12; +--Testcase 520: +insert into agg_t12 values (1), (3), (5), (7); +--Testcase 521: +select + percentile_cont(0.5) within group (order by a), + percentile_disc(0.5) within group (order by a) +from agg_t12; + percentile_cont | percentile_disc +-----------------+----------------- + 4 | 3 +(1 row) + +--Testcase 522: +select + percentile_cont(0.25) within group (order by a), + percentile_disc(0.5) within group (order by a) +from agg_t12; + percentile_cont | percentile_disc +-----------------+----------------- + 2.5 | 3 +(1 row) + +-- these can't share state currently +--Testcase 523: +select + rank(4) within group (order by a), + dense_rank(4) within group (order by a) +from agg_t12; + rank | dense_rank +------+------------ + 3 | 3 +(1 row) + +-- test that aggs with the same sfunc and initcond share the same agg state +--Testcase 524: +create aggregate my_sum_init(int4) +( + stype = avg_state, + sfunc = avg_transfn, + finalfunc = sum_finalfn, + initcond = '(10,0)' +); +--Testcase 525: +create aggregate my_avg_init(int4) +( + stype = avg_state, + sfunc = avg_transfn, + finalfunc = avg_finalfn, + initcond = '(10,0)' +); +--Testcase 526: +create aggregate my_avg_init2(int4) +( + stype = avg_state, + sfunc = avg_transfn, + finalfunc = avg_finalfn, + initcond = '(4,0)' +); +-- state should be shared if INITCONDs are matching +--Testcase 527: +delete from agg_t10; +--Testcase 528: +insert into agg_t10 values (1), (3); +--Testcase 529: +select my_sum_init(one),my_avg_init(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 + my_sum_init | my_avg_init +-------------+------------- + 14 | 7 +(1 row) + +-- Varying INITCONDs should cause the states not to be shared. +--Testcase 530: +select my_sum_init(one),my_avg_init2(one) from agg_t10; +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 1 +NOTICE: avg_transfn called with 3 +NOTICE: avg_transfn called with 3 + my_sum_init | my_avg_init2 +-------------+-------------- + 14 | 4 +(1 row) + +rollback; +-- test aggregate state sharing to ensure it works if one aggregate has a +-- finalfn and the other one has none. +begin work; +--Testcase 531: +create or replace function sum_transfn(state int4, n int4) returns int4 as +$$ +declare new_state int4; +begin + raise notice 'sum_transfn called with %', n; + if state is null then + if n is not null then + new_state := n; + return new_state; + end if; + return null; + elsif n is not null then + state := state + n; + return state; + end if; + + return null; +end +$$ language plpgsql; +--Testcase 532: +create function halfsum_finalfn(state int4) returns int4 as +$$ +begin + if state is null then + return NULL; + else + return state / 2; + end if; +end +$$ language plpgsql; +--Testcase 533: +create aggregate my_sum(int4) +( + stype = int4, + sfunc = sum_transfn +); +--Testcase 534: +create aggregate my_half_sum(int4) +( + stype = int4, + sfunc = sum_transfn, + finalfunc = halfsum_finalfn +); +-- Agg state should be shared even though my_sum has no finalfn +--Testcase 535: +delete from agg_t10; +--Testcase 536: +insert into agg_t10 values (1), (2), (3), (4); +--Testcase 537: +select my_sum(one),my_half_sum(one) from agg_t10; +NOTICE: sum_transfn called with 1 +NOTICE: sum_transfn called with 2 +NOTICE: sum_transfn called with 3 +NOTICE: sum_transfn called with 4 + my_sum | my_half_sum +--------+------------- + 10 | 5 +(1 row) + +rollback; +-- test that the aggregate transition logic correctly handles +-- transition / combine functions returning NULL +-- First test the case of a normal transition function returning NULL +BEGIN; +--Testcase 538: +CREATE FUNCTION balkifnull(int8, int4) +RETURNS int8 +STRICT +LANGUAGE plpgsql AS $$ +BEGIN + IF $1 IS NULL THEN + RAISE 'erroneously called with NULL argument'; + END IF; + RETURN NULL; +END$$; +--Testcase 539: +CREATE AGGREGATE balk(int4) +( + SFUNC = balkifnull(int8, int4), + STYPE = int8, + PARALLEL = SAFE, + INITCOND = '0' +); +--Testcase 200: +SELECT balk(hundred) FROM tenk1; + balk +------ + +(1 row) + +ROLLBACK; +-- GROUP BY optimization by reordering GROUP BY clauses +--Testcase 766: +CREATE FOREIGN TABLE btg_groupby(x int, y int, z text, w int) SERVER sqlite_svr; +--Testcase 767: +INSERT INTO btg_groupby + SELECT + i % 10 AS x, + i % 10 AS y, + 'abc' || i % 10 AS z, + i AS w + FROM generate_series(1, 100) AS i; +-- CREATE INDEX is not supported for foreign tables. +-- CREATE INDEX btg_x_y_idx ON btg_groupby(x, y); +-- ANALYZE btg_groupby; +SET enable_hashagg = off; +SET enable_seqscan = off; +-- Because CREATE INDEX is not supported for foreign tables, +-- we cannot utilize the ordering of index scan to avoid a Sort operation +-- Utilize the ordering of index scan to avoid a Sort operation +--Testcase 768: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY y, x; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Engage incremental sort +--Testcase 769: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY z, y, w, x; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Utilize the ordering of subquery scan to avoid a Sort operation +--Testcase 770: +EXPLAIN (COSTS OFF) SELECT count(*) +FROM (SELECT * FROM btg_groupby ORDER BY x, y, w, z) AS q1 +GROUP BY w, x, z, y; + QUERY PLAN +------------------------------------------------------------------------- + GroupAggregate + Group Key: btg_groupby.x, btg_groupby.y, btg_groupby.w, btg_groupby.z + -> Foreign Scan on btg_groupby +(3 rows) + +-- Utilize the ordering of merge join to avoid a full Sort operation +SET enable_hashjoin = off; +SET enable_nestloop = off; +--Testcase 771: +EXPLAIN (COSTS OFF) +SELECT count(*) + FROM btg_groupby t1 JOIN btg_groupby t2 ON t1.z = t2.z AND t1.w = t2.w AND t1.x = t2.x + GROUP BY t1.x, t1.y, t1.z, t1.w; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +RESET enable_nestloop; +RESET enable_hashjoin; +-- Should work with and without GROUP-BY optimization +--Testcase 772: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY w, x, z, y ORDER BY y, x, z, w; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Utilize incremental sort to make the ORDER BY rule a bit cheaper +--Testcase 773: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY w, x, y, z ORDER BY x*x, z; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- Test the case where the number of incoming subtree path keys is more than +-- the number of grouping keys. +-- CREATE INDEX btg_y_x_w_idx ON btg_groupby(y, x, w); +--Testcase 774: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT y, x, array_agg(distinct w) + FROM btg_groupby WHERE y < 0 GROUP BY x, y; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: y, x, array_agg(DISTINCT w) + Group Key: btg_groupby.x, btg_groupby.y + -> Foreign Scan on public.btg_groupby + Output: x, y, z, w + SQLite query: SELECT `x`, `y`, `w` FROM main."btg_groupby" WHERE ((`y` < 0)) ORDER BY `x` ASC NULLS LAST, `y` ASC NULLS LAST, `w` ASC NULLS LAST +(6 rows) + +-- Ensure that we do not select the aggregate pathkeys instead of the grouping +-- pathkeys +--Testcase 775: +CREATE FOREIGN TABLE group_agg_pk(x int, y int, z int, w int, f int) SERVER sqlite_svr; +--Testcase 776: +INSERT INTO group_agg_pk SELECT + i % 10 AS x, + i % 2 AS y, + i % 2 AS z, + 2 AS w, + i % 10 AS f +FROM generate_series(1,100) AS i; +-- ANALYZE group_agg_pk; +SET enable_nestloop = off; +SET enable_hashjoin = off; +--Testcase 777: +EXPLAIN (COSTS OFF) +SELECT avg(c1.f ORDER BY c1.x, c1.y) +FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x +GROUP BY c1.w, c1.z; + QUERY PLAN +------------------------- + GroupAggregate + Group Key: c1.w, c1.z + -> Foreign Scan +(3 rows) + +--Testcase 778: +SELECT avg(c1.f ORDER BY c1.x, c1.y) +FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x +GROUP BY c1.w, c1.z; + avg +-------------------- + 4.0000000000000000 + 5.0000000000000000 +(2 rows) + +-- Pathkeys, built in a subtree, can be used to optimize GROUP-BY clause +-- ordering. Also, here we check that it doesn't depend on the initial clause +-- order in the GROUP-BY list. +--Testcase 780: +EXPLAIN (COSTS OFF) +SELECT c1.y,c1.x FROM group_agg_pk c1 + JOIN group_agg_pk c2 + ON c1.x = c2.x +GROUP BY c1.y,c1.x,c2.x; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 781: +EXPLAIN (COSTS OFF) +SELECT c1.y,c1.x FROM group_agg_pk c1 + JOIN group_agg_pk c2 + ON c1.x = c2.x +GROUP BY c1.y,c2.x,c1.x; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +RESET enable_nestloop; +RESET enable_hashjoin; +--Testcase 779: +DROP FOREIGN TABLE group_agg_pk; +-- -- CREATE UNIQUE INDEX is not supported for foreign table +-- -- Test the case where the ordering of the scan matches the ordering within the +-- -- aggregate but cannot be found in the group-by list +-- CREATE TABLE agg_sort_order (c1 int PRIMARY KEY, c2 int); +-- CREATE UNIQUE INDEX agg_sort_order_c2_idx ON agg_sort_order(c2); +-- INSERT INTO agg_sort_order SELECT i, i FROM generate_series(1,100)i; +-- ANALYZE agg_sort_order; +-- EXPLAIN (COSTS OFF) +-- SELECT array_agg(c1 ORDER BY c2),c2 +-- FROM agg_sort_order WHERE c2 < 100 GROUP BY c1 ORDER BY 2; +-- DROP TABLE agg_sort_order CASCADE; +--Testcase 678: +DROP FOREIGN TABLE btg_groupby; +RESET enable_hashagg; +RESET enable_seqscan; +-- Secondly test the case of a parallel aggregate combiner function +-- returning NULL. For that use normal transition function, but a +-- combiner function returning NULL. +BEGIN; +--Testcase 540: +CREATE FUNCTION balkifnull(int8, int8) +RETURNS int8 +PARALLEL SAFE +STRICT +LANGUAGE plpgsql AS $$ +BEGIN + IF $1 IS NULL THEN + RAISE 'erroneously called with NULL argument'; + END IF; + RETURN NULL; +END$$; +--Testcase 541: +CREATE AGGREGATE balk(int4) +( + SFUNC = int4_sum(int8, int4), + STYPE = int8, + COMBINEFUNC = balkifnull(int8, int8), + PARALLEL = SAFE, + INITCOND = '0' +); +-- force use of parallelism +-- Skip this test, cannot alter foreign table tenk1 +-- ALTER FOREIGN TABLE tenk1 set (parallel_workers = 4); +-- SET LOCAL parallel_setup_cost=0; +-- SET LOCAL max_parallel_workers_per_gather=4; +-- EXPLAIN (COSTS OFF) SELECT balk(hundred) FROM tenk1; +-- SELECT balk(hundred) FROM tenk1; +ROLLBACK; +-- test multiple usage of an aggregate whose finalfn returns a R/W datum +BEGIN; +--Testcase 754: +CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray +LANGUAGE plpgsql IMMUTABLE AS $$ +BEGIN + RETURN array_fill(y[1], ARRAY[4]); +END; +$$; +--Testcase 755: +CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray +LANGUAGE plpgsql STRICT IMMUTABLE AS $$ +DECLARE + res x%TYPE; +BEGIN + -- assignment is essential for this test, it expands the array to R/W + res := array_fill(x[1], ARRAY[4]); + RETURN res; +END; +$$; +--Testcase 756: +CREATE AGGREGATE rwagg(anyarray) ( + STYPE = anyarray, + SFUNC = rwagg_sfunc, + FINALFUNC = rwagg_finalfunc +); +--Testcase 757: +CREATE FUNCTION eatarray(x real[]) RETURNS real[] +LANGUAGE plpgsql STRICT IMMUTABLE AS $$ +BEGIN + x[1] := x[1] + 1; + RETURN x; +END; +$$; +--Testcase 758: +CREATE FOREIGN TABLE float_tb(f real) SERVER sqlite_svr; +--Testcase 759: +INSERT INTO float_tb(f) VALUES (1.0); +--Testcase 760: +SELECT eatarray(rwagg(ARRAY[f::real])), eatarray(rwagg(ARRAY[f::real])) FROM float_tb; + eatarray | eatarray +-----------+----------- + {2,1,1,1} | {2,1,1,1} +(1 row) + +ROLLBACK; +-- test coverage for aggregate combine/serial/deserial functions +BEGIN; +--Testcase 635: +SET parallel_setup_cost = 0; +--Testcase 636: +SET parallel_tuple_cost = 0; +--Testcase 637: +SET min_parallel_table_scan_size = 0; +--Testcase 638: +SET max_parallel_workers_per_gather = 4; +--Testcase 639: +SET parallel_leader_participation = off; +--Testcase 640: +SET enable_indexonlyscan = off; +-- variance(int4) covers numeric_poly_combine +-- sum(int8) covers int8_avg_combine +-- regr_count(float8, float8) covers int8inc_float8_float8 and aggregates with > 1 arg +--Testcase 542: +EXPLAIN (COSTS OFF, VERBOSE) +SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) +FROM (SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1) u; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: variance(tenk1.unique1), sum((tenk1.unique1)::bigint), regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision) + -> Append + -> Foreign Scan on public.tenk1 + Output: tenk1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_1 + Output: tenk1_1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_2 + Output: tenk1_2.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_3 + Output: tenk1_3.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" +(15 rows) + +--Testcase 543: +SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) +FROM (SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1) u; + variance | sum | regr_count +----------------------+-----------+------------ + 8333541.588539713493 | 199980000 | 40000 +(1 row) + +-- variance(int8) covers numeric_combine +-- avg(numeric) covers numeric_avg_combine +--Testcase 544: +EXPLAIN (COSTS OFF, VERBOSE) +SELECT variance(unique1::int8), avg(unique1::numeric) +FROM (SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1) u; + QUERY PLAN +---------------------------------------------------------------------------- + Aggregate + Output: variance((tenk1.unique1)::bigint), avg((tenk1.unique1)::numeric) + -> Append + -> Foreign Scan on public.tenk1 + Output: tenk1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_1 + Output: tenk1_1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_2 + Output: tenk1_2.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Foreign Scan on public.tenk1 tenk1_3 + Output: tenk1_3.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" +(15 rows) + +--Testcase 545: +SELECT variance(unique1::int8), avg(unique1::numeric) +FROM (SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1 + UNION ALL SELECT * FROM tenk1) u; + variance | avg +----------------------+----------------------- + 8333541.588539713493 | 4999.5000000000000000 +(1 row) + +ROLLBACK; +-- test coverage for dense_rank +--Testcase 546: +create foreign table agg_t13(x int, id int options (key 'true')) server sqlite_svr; +--Testcase 547: +insert into agg_t13 values (1),(1),(2),(2),(3),(3); +--Testcase 548: +SELECT dense_rank(x) WITHIN GROUP (ORDER BY x) FROM agg_t13 GROUP BY (x) ORDER BY 1; + dense_rank +------------ + 1 + 1 + 1 +(3 rows) + +--Testcase 549: +delete from agg_t13; +-- Ensure that the STRICT checks for aggregates does not take NULLness +-- of ORDER BY columns into account. See bug report around +-- 2a505161-2727-2473-7c46-591ed108ac52@email.cz +--Testcase 550: +create foreign table agg_t14(x int, y int, id int options (key 'true')) server sqlite_svr; +--Testcase 551: +insert into agg_t14 values (1, NULL), (1, 2); +--Testcase 552: +SELECT min(x ORDER BY y) FROM agg_t14; + min +----- + 1 +(1 row) + +--Testcase 553: +SELECT min(x ORDER BY y) FROM agg_t14; + min +----- + 1 +(1 row) + +-- check collation-sensitive matching between grouping expressions +begin; +--Testcase 554: +insert into agg_t20 values (unnest(array['a','b'])); +--Testcase 555: +select x||'a', case x||'a' when 'aa' then 1 else 0 end, count(*) + from agg_t20 group by x||'a' order by 1; + ?column? | case | count +----------+------+------- + aa | 1 | 1 + ba | 0 | 1 +(2 rows) + +rollback; +begin; +--Testcase 556: +insert into agg_t20 values (unnest(array['a','b'])); +--Testcase 557: +select x||'a', case when x||'a' = 'aa' then 1 else 0 end, count(*) + from agg_t20 group by x||'a' order by 1; + ?column? | case | count +----------+------+------- + aa | 1 | 1 + ba | 0 | 1 +(2 rows) + +rollback; +-- Make sure that generation of HashAggregate for uniqification purposes +-- does not lead to array overflow due to unexpected duplicate hash keys +-- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com +--Testcase 641: +set enable_memoize to off; +--Testcase 558: +explain (costs off) + select 1 from tenk1 + where (hundred, thousand) in (select twothousand, twothousand from onek); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 642: +reset enable_memoize; +-- +-- Hash Aggregation Spill tests +-- +--Testcase 643: +set enable_sort=false; +--Testcase 644: +set work_mem='64kB'; +--Testcase 559: +select unique1, count(*), sum(twothousand) from tenk1 +group by unique1 +having sum(fivethous) > 4975 +order by sum(twothousand); + unique1 | count | sum +---------+-------+------ + 4976 | 1 | 976 + 4977 | 1 | 977 + 4978 | 1 | 978 + 4979 | 1 | 979 + 4980 | 1 | 980 + 4981 | 1 | 981 + 4982 | 1 | 982 + 4983 | 1 | 983 + 4984 | 1 | 984 + 4985 | 1 | 985 + 4986 | 1 | 986 + 4987 | 1 | 987 + 4988 | 1 | 988 + 4989 | 1 | 989 + 4990 | 1 | 990 + 4991 | 1 | 991 + 4992 | 1 | 992 + 4993 | 1 | 993 + 4994 | 1 | 994 + 4995 | 1 | 995 + 4996 | 1 | 996 + 4997 | 1 | 997 + 4998 | 1 | 998 + 4999 | 1 | 999 + 9976 | 1 | 1976 + 9977 | 1 | 1977 + 9978 | 1 | 1978 + 9979 | 1 | 1979 + 9980 | 1 | 1980 + 9981 | 1 | 1981 + 9982 | 1 | 1982 + 9983 | 1 | 1983 + 9984 | 1 | 1984 + 9985 | 1 | 1985 + 9986 | 1 | 1986 + 9987 | 1 | 1987 + 9988 | 1 | 1988 + 9989 | 1 | 1989 + 9990 | 1 | 1990 + 9991 | 1 | 1991 + 9992 | 1 | 1992 + 9993 | 1 | 1993 + 9994 | 1 | 1994 + 9995 | 1 | 1995 + 9996 | 1 | 1996 + 9997 | 1 | 1997 + 9998 | 1 | 1998 + 9999 | 1 | 1999 +(48 rows) + +--Testcase 645: +set work_mem to default; +--Testcase 646: +set enable_sort to default; +-- +-- Compare results between plans using sorting and plans using hash +-- aggregation. Force spilling in both cases by setting work_mem low. +-- +--Testcase 647: +set work_mem='64kB'; +--Testcase 560: +create foreign table agg_data_2k(g int, id int options (key 'true')) server sqlite_svr; +--Testcase 561: +create foreign table agg_data_20k(g int, id int options (key 'true')) server sqlite_svr; +--Testcase 562: +create foreign table agg_group_1(c1 int, c2 numeric, c3 int) server sqlite_svr; +--Testcase 563: +create foreign table agg_group_2(a int, c1 numeric, c2 text, c3 int) server sqlite_svr; +--Testcase 564: +create foreign table agg_group_3(c1 numeric, c2 int4, c3 int) server sqlite_svr; +--Testcase 565: +create foreign table agg_group_4(c1 numeric, c2 text, c3 int) server sqlite_svr; +--Testcase 566: +create foreign table agg_hash_1(c1 int, c2 numeric, c3 int) server sqlite_svr; +--Testcase 567: +create foreign table agg_hash_2(a int, c1 numeric, c2 text, c3 int) server sqlite_svr; +--Testcase 568: +create foreign table agg_hash_3(c1 numeric, c2 int4, c3 int) server sqlite_svr; +--Testcase 569: +create foreign table agg_hash_4(c1 numeric, c2 text, c3 int) server sqlite_svr; +--Testcase 570: +insert into agg_data_2k select g from generate_series(0, 1999) g; +--analyze agg_data_2k; +--Testcase 571: +insert into agg_data_20k select g from generate_series(0, 19999) g; +--analyze agg_data_20k; +-- Produce results with sorting. +--Testcase 648: +set enable_hashagg = false; +--Testcase 649: +set jit_above_cost = 0; +--Testcase 572: +explain (costs off) +select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 + from agg_data_20k group by g%10000; + QUERY PLAN +------------------------------------ + GroupAggregate + Group Key: (g % 10000) + -> Foreign Scan on agg_data_20k +(3 rows) + +--Testcase 573: +insert into agg_group_1 +select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 + from agg_data_20k group by g%10000; +--Testcase 574: +insert into agg_group_2 +select * from + (values (100), (300), (500)) as r(a), + lateral ( + select (g/2)::numeric as c1, + array_agg(g::numeric) as c2, + count(*) as c3 + from agg_data_2k + where g < r.a + group by g/2) as s; +--Testcase 650: +set jit_above_cost to default; +--Testcase 575: +insert into agg_group_3 +select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 + from agg_data_2k group by g/2; +--Testcase 576: +insert into agg_group_4 +select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 + from agg_data_2k group by g/2; +-- Produce results with hash aggregation +--Testcase 651: +set enable_hashagg = true; +--Testcase 652: +set enable_sort = false; +--Testcase 653: +set jit_above_cost = 0; +--Testcase 577: +explain (costs off) +select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 + from agg_data_20k group by g%10000; + QUERY PLAN +------------------------------------ + GroupAggregate + Group Key: (g % 10000) + -> Foreign Scan on agg_data_20k +(3 rows) + +--Testcase 578: +insert into agg_hash_1 +select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 + from agg_data_20k group by g%10000; +--Testcase 579: +insert into agg_hash_2 +select * from + (values (100), (300), (500)) as r(a), + lateral ( + select (g/2)::numeric as c1, + array_agg(g::numeric) as c2, + count(*) as c3 + from agg_data_2k + where g < r.a + group by g/2) as s; +--Testcase 654: +set jit_above_cost to default; +--Testcase 580: +insert into agg_hash_3 +select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 + from agg_data_2k group by g/2; +--Testcase 581: +insert into agg_hash_4 +select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 + from agg_data_2k group by g/2; +--Testcase 655: +set enable_sort = true; +--Testcase 656: +set work_mem to default; +-- Compare group aggregation results to hash aggregation results +--Testcase 582: +(select * from agg_hash_1 except select * from agg_group_1) + union all +(select * from agg_group_1 except select * from agg_hash_1); + c1 | c2 | c3 +----+----+---- +(0 rows) + +--Testcase 583: +(select * from agg_hash_2 except select * from agg_group_2) + union all +(select * from agg_group_2 except select * from agg_hash_2); + a | c1 | c2 | c3 +---+----+----+---- +(0 rows) + +--Testcase 584: +(select * from agg_hash_3 except select * from agg_group_3) + union all +(select * from agg_group_3 except select * from agg_hash_3); + c1 | c2 | c3 +----+----+---- +(0 rows) + +--Testcase 585: +(select * from agg_hash_4 except select * from agg_group_4) + union all +(select * from agg_group_4 except select * from agg_hash_4); + c1 | c2 | c3 +----+----+---- +(0 rows) + +--Testcase 792: +DELETE FROM INT4_TBL; +--Testcase 793: +DELETE FROM INT8_TBL; +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table minmaxtest1 +drop cascades to table minmaxtest2 +drop cascades to table minmaxtest3 +NOTICE: drop cascades to table t1c +--Testcase 586: +DROP SERVER sqlite_svr CASCADE; +--Testcase 587: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/16.0/extra/bitstring.out b/expected/17.0/extra/bitstring.out similarity index 100% rename from expected/16.0/extra/bitstring.out rename to expected/17.0/extra/bitstring.out diff --git a/expected/17.0/extra/bool.out b/expected/17.0/extra/bool.out new file mode 100644 index 00000000..ccb740e5 --- /dev/null +++ b/expected/17.0/extra/bool.out @@ -0,0 +1,1276 @@ +--SET log_min_messages TO DEBUG1; +--SET client_min_messages TO DEBUG1; +--Testcase 000: +CREATE EXTENSION sqlite_fdw; +--Testcase 001: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); +--Testcase 002: +CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; +--Testcase 01: +CREATE FOREIGN TABLE "type_BOOLEAN" (i int OPTIONS (key 'true'), b bool) SERVER sqlite_svr; +--Testcase 02: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (1, TRUE); +--Testcase 03: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (2, FALSE); +--Testcase 04: +CREATE FOREIGN TABLE "type_BOOLEAN+"( "i" int, "b" bool, "t" text, "l" smallint) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN+'); +--Testcase 05: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE text; +--Testcase 06: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (3, TRUE); +--Testcase 07: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (4, FALSE); +--Testcase 08: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (5, true); +--Testcase 09: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (6, false); +--Testcase 10: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (7, 'Yes'); +--Testcase 11: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (8, 'YeS'); +--Testcase 12: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (9, 'yes'); +--Testcase 13: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (10, 'no'); +--Testcase 14: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (11, 'No'); +--Testcase 15: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (12, 'nO'); +--Testcase 16: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (13, 'off'); +--Testcase 17: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (14, 'oFf'); +--Testcase 18: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (15, 'on'); +--Testcase 19: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (16, 'ON'); +--Testcase 20: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (17, 't'); +--Testcase 21: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (18, 'T'); +--Testcase 22: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (19, 'Y'); +--Testcase 23: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (20, 'y'); +--Testcase 24: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (21, 'F'); +--Testcase 25: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (22, 'f'); +--Testcase 26: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (23, 'x'); +--Testcase 27: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (24, '0'); +--Testcase 28: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (25, '1'); +--Testcase 29: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (26, NULL); +--Testcase 30: +SELECT * FROM "type_BOOLEAN"; + i | b +----+------- + 1 | 1 + 2 | 0 + 3 | true + 4 | false + 5 | true + 6 | false + 7 | Yes + 8 | YeS + 9 | yes + 10 | no + 11 | No + 12 | nO + 13 | off + 14 | oFf + 15 | on + 16 | ON + 17 | t + 18 | T + 19 | Y + 20 | y + 21 | F + 22 | f + 23 | x + 24 | 0 + 25 | 1 + 26 | +(26 rows) + +--Testcase 31: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; +--Testcase 32: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM "type_BOOLEAN"; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan on public."type_BOOLEAN" + Output: i, b + SQLite query: SELECT `i`, sqlite_fdw_bool(`b`) FROM main."type_BOOLEAN" +(3 rows) + +--Testcase 33: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM "type_BOOLEAN+"; + QUERY PLAN +-------------------------------------------------------------------------------------- + Foreign Scan on public."type_BOOLEAN+" + Output: i, b, t, l + SQLite query: SELECT `i`, sqlite_fdw_bool(`b`), `t`, `l` FROM main."type_BOOLEAN+" +(3 rows) + +--Testcase 34: ERR - invalid text affinity because not ISO:SQL text input +SELECT * FROM "type_BOOLEAN+"; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (1 bytes) : 'x' +CONTEXT: foreign table "type_BOOLEAN+" foreign column "b" have data type "boolean" (usual affinity "integer"), in query there is reference to foreign column +--Testcase 35 +DELETE FROM "type_BOOLEAN" WHERE i = 23; +--Testcase 36: +SELECT * FROM "type_BOOLEAN+"; + i | b | t | l +----+---+---------+--- + 1 | t | integer | 1 + 2 | f | integer | 1 + 3 | t | text | 4 + 4 | f | text | 5 + 5 | t | text | 4 + 6 | f | text | 5 + 7 | t | text | 3 + 8 | t | text | 3 + 9 | t | text | 3 + 10 | f | text | 2 + 11 | f | text | 2 + 12 | f | text | 2 + 13 | f | text | 3 + 14 | f | text | 3 + 15 | t | text | 2 + 16 | t | text | 2 + 17 | t | text | 1 + 18 | t | text | 1 + 19 | t | text | 1 + 20 | t | text | 1 + 21 | f | text | 1 + 22 | f | text | 1 + 24 | f | integer | 1 + 25 | t | integer | 1 + 26 | | null | +(25 rows) + +--Testcase 37: +SELECT * FROM "type_BOOLEAN+" WHERE b IS NULL; + i | b | t | l +----+---+------+--- + 26 | | null | +(1 row) + +--Testcase 38: +SELECT * FROM "type_BOOLEAN+" WHERE b IS NOT NULL; + i | b | t | l +----+---+---------+--- + 1 | t | integer | 1 + 2 | f | integer | 1 + 3 | t | text | 4 + 4 | f | text | 5 + 5 | t | text | 4 + 6 | f | text | 5 + 7 | t | text | 3 + 8 | t | text | 3 + 9 | t | text | 3 + 10 | f | text | 2 + 11 | f | text | 2 + 12 | f | text | 2 + 13 | f | text | 3 + 14 | f | text | 3 + 15 | t | text | 2 + 16 | t | text | 2 + 17 | t | text | 1 + 18 | t | text | 1 + 19 | t | text | 1 + 20 | t | text | 1 + 21 | f | text | 1 + 22 | f | text | 1 + 24 | f | integer | 1 + 25 | t | integer | 1 +(24 rows) + +--Testcase 39: +SELECT * FROM "type_BOOLEAN+" WHERE b; + i | b | t | l +----+---+---------+--- + 1 | t | integer | 1 + 3 | t | text | 4 + 5 | t | text | 4 + 7 | t | text | 3 + 8 | t | text | 3 + 9 | t | text | 3 + 15 | t | text | 2 + 16 | t | text | 2 + 17 | t | text | 1 + 18 | t | text | 1 + 19 | t | text | 1 + 20 | t | text | 1 + 25 | t | integer | 1 +(13 rows) + +--Testcase 40: +SELECT * FROM "type_BOOLEAN+" WHERE NOT b; + i | b | t | l +----+---+---------+--- + 2 | f | integer | 1 + 4 | f | text | 5 + 6 | f | text | 5 + 10 | f | text | 2 + 11 | f | text | 2 + 12 | f | text | 2 + 13 | f | text | 3 + 14 | f | text | 3 + 21 | f | text | 1 + 22 | f | text | 1 + 24 | f | integer | 1 +(11 rows) + +--Testcase 41: +CREATE FOREIGN TABLE "type_BOOLEANpk" (col bool OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 42: +INSERT INTO "type_BOOLEANpk" VALUES (TRUE); +--Testcase 43: +INSERT INTO "type_BOOLEANpk" VALUES (FALSE); +--Testcase 44: ERR - primary key +INSERT INTO "type_BOOLEANpk" VALUES (TRUE); +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: type_BOOLEANpk.col', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."type_BOOLEANpk"(`col`) VALUES (?) +--Testcase 45: +DELETE FROM "type_BOOLEANpk"; +--Testcase 46: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE float8; +--Testcase 47: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (27, 3.14159265358979); +--Testcase 48: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; +--Testcase 49: ERR - invalid float for bool column +SELECT * FROM "type_BOOLEAN+"; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "real" affinity : 3.14159265358979 +CONTEXT: foreign table "type_BOOLEAN+" foreign column "b" have data type "boolean" (usual affinity "integer"), in query there is reference to foreign column +--Testcase 50 +DELETE FROM "type_BOOLEAN" WHERE i = 27; +--Testcase 51: +SELECT * FROM "type_BOOLEAN+"; + i | b | t | l +----+---+---------+--- + 1 | t | integer | 1 + 2 | f | integer | 1 + 3 | t | text | 4 + 4 | f | text | 5 + 5 | t | text | 4 + 6 | f | text | 5 + 7 | t | text | 3 + 8 | t | text | 3 + 9 | t | text | 3 + 10 | f | text | 2 + 11 | f | text | 2 + 12 | f | text | 2 + 13 | f | text | 3 + 14 | f | text | 3 + 15 | t | text | 2 + 16 | t | text | 2 + 17 | t | text | 1 + 18 | t | text | 1 + 19 | t | text | 1 + 20 | t | text | 1 + 21 | f | text | 1 + 22 | f | text | 1 + 24 | f | integer | 1 + 25 | t | integer | 1 + 26 | | null | +(25 rows) + +--Testcase 52: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN" SET b = NULL WHERE b; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Update on public."type_BOOLEAN" + -> Foreign Update on public."type_BOOLEAN" + SQLite query: UPDATE main."type_BOOLEAN" SET `b` = NULL WHERE (sqlite_fdw_bool(`b`)) +(3 rows) + +--Testcase 53: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN" SET b = NULL WHERE NOT b; + QUERY PLAN +---------------------------------------------------------------------------------------------------- + Update on public."type_BOOLEAN" + -> Foreign Update on public."type_BOOLEAN" + SQLite query: UPDATE main."type_BOOLEAN" SET `b` = NULL WHERE ((NOT sqlite_fdw_bool(`b`))) +(3 rows) + +--Testcase 54: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN" WHERE b; + QUERY PLAN +------------------------------------------------------------------------------------ + Delete on public."type_BOOLEAN" + -> Foreign Delete on public."type_BOOLEAN" + SQLite query: DELETE FROM main."type_BOOLEAN" WHERE (sqlite_fdw_bool(`b`)) +(3 rows) + +--Testcase 55: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN" WHERE NOT b; + QUERY PLAN +------------------------------------------------------------------------------------------ + Delete on public."type_BOOLEAN" + -> Foreign Delete on public."type_BOOLEAN" + SQLite query: DELETE FROM main."type_BOOLEAN" WHERE ((NOT sqlite_fdw_bool(`b`))) +(3 rows) + +--Testcase 56: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT *, NOT b nb FROM "type_BOOLEAN+" b; + QUERY PLAN +-------------------------------------------------------------------------------------- + Foreign Scan on public."type_BOOLEAN+" b + Output: i, b, t, l, (NOT b) + SQLite query: SELECT `i`, sqlite_fdw_bool(`b`), `t`, `l` FROM main."type_BOOLEAN+" +(3 rows) + +--Testcase 57: +SELECT *, NOT b nb FROM "type_BOOLEAN+" b; + i | b | t | l | nb +----+---+---------+---+---- + 1 | t | integer | 1 | f + 2 | f | integer | 1 | t + 3 | t | text | 4 | f + 4 | f | text | 5 | t + 5 | t | text | 4 | f + 6 | f | text | 5 | t + 7 | t | text | 3 | f + 8 | t | text | 3 | f + 9 | t | text | 3 | f + 10 | f | text | 2 | t + 11 | f | text | 2 | t + 12 | f | text | 2 | t + 13 | f | text | 3 | t + 14 | f | text | 3 | t + 15 | t | text | 2 | f + 16 | t | text | 2 | f + 17 | t | text | 1 | f + 18 | t | text | 1 | f + 19 | t | text | 1 | f + 20 | t | text | 1 | f + 21 | f | text | 1 | t + 22 | f | text | 1 | t + 24 | f | integer | 1 | t + 25 | t | integer | 1 | f + 26 | | null | | +(25 rows) + +--Testcase 58: +CREATE FOREIGN TABLE "type_BOOLEAN_oper"( "i" int OPTIONS (key 'true'), i1 smallint, b1 boolean, i2 smallint, b2 boolean) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN_oper'); +--Testcase 59: see INIT.SQL with mixed affinity boolean data +SELECT * FROM "type_BOOLEAN_oper"; + i | i1 | b1 | i2 | b2 +-----+----+----+----+---- + 1 | 1 | t | 1 | t + 2 | 1 | t | 2 | t + 3 | 1 | t | 3 | t + 4 | 1 | t | 4 | t + 5 | 1 | t | 5 | t + 6 | 1 | t | 6 | t + 7 | 1 | t | 7 | t + 8 | 1 | t | 8 | t + 9 | 1 | t | 9 | t + 10 | 1 | t | 10 | t + 11 | 1 | t | 11 | t + 12 | 1 | t | 12 | t + 13 | 1 | t | 13 | t + 14 | 1 | t | 14 | f + 15 | 1 | t | 15 | f + 16 | 1 | t | 16 | f + 17 | 1 | t | 17 | f + 18 | 1 | t | 18 | f + 19 | 1 | t | 19 | f + 20 | 1 | t | 20 | f + 21 | 1 | t | 21 | f + 22 | 1 | t | 22 | f + 23 | 1 | t | 23 | f + 24 | 1 | t | 24 | f + 25 | 1 | t | 25 | f + 26 | 1 | t | 26 | f + 27 | 1 | t | 27 | + 28 | 2 | t | 1 | t + 29 | 2 | t | 2 | t + 30 | 2 | t | 3 | t + 31 | 2 | t | 4 | t + 32 | 2 | t | 5 | t + 33 | 2 | t | 6 | t + 34 | 2 | t | 7 | t + 35 | 2 | t | 8 | t + 36 | 2 | t | 9 | t + 37 | 2 | t | 10 | t + 38 | 2 | t | 11 | t + 39 | 2 | t | 12 | t + 40 | 2 | t | 13 | t + 41 | 2 | t | 14 | f + 42 | 2 | t | 15 | f + 43 | 2 | t | 16 | f + 44 | 2 | t | 17 | f + 45 | 2 | t | 18 | f + 46 | 2 | t | 19 | f + 47 | 2 | t | 20 | f + 48 | 2 | t | 21 | f + 49 | 2 | t | 22 | f + 50 | 2 | t | 23 | f + 51 | 2 | t | 24 | f + 52 | 2 | t | 25 | f + 53 | 2 | t | 26 | f + 54 | 2 | t | 27 | + 55 | 3 | t | 1 | t + 56 | 3 | t | 2 | t + 57 | 3 | t | 3 | t + 58 | 3 | t | 4 | t + 59 | 3 | t | 5 | t + 60 | 3 | t | 6 | t + 61 | 3 | t | 7 | t + 62 | 3 | t | 8 | t + 63 | 3 | t | 9 | t + 64 | 3 | t | 10 | t + 65 | 3 | t | 11 | t + 66 | 3 | t | 12 | t + 67 | 3 | t | 13 | t + 68 | 3 | t | 14 | f + 69 | 3 | t | 15 | f + 70 | 3 | t | 16 | f + 71 | 3 | t | 17 | f + 72 | 3 | t | 18 | f + 73 | 3 | t | 19 | f + 74 | 3 | t | 20 | f + 75 | 3 | t | 21 | f + 76 | 3 | t | 22 | f + 77 | 3 | t | 23 | f + 78 | 3 | t | 24 | f + 79 | 3 | t | 25 | f + 80 | 3 | t | 26 | f + 81 | 3 | t | 27 | + 82 | 4 | t | 1 | t + 83 | 4 | t | 2 | t + 84 | 4 | t | 3 | t + 85 | 4 | t | 4 | t + 86 | 4 | t | 5 | t + 87 | 4 | t | 6 | t + 88 | 4 | t | 7 | t + 89 | 4 | t | 8 | t + 90 | 4 | t | 9 | t + 91 | 4 | t | 10 | t + 92 | 4 | t | 11 | t + 93 | 4 | t | 12 | t + 94 | 4 | t | 13 | t + 95 | 4 | t | 14 | f + 96 | 4 | t | 15 | f + 97 | 4 | t | 16 | f + 98 | 4 | t | 17 | f + 99 | 4 | t | 18 | f + 100 | 4 | t | 19 | f + 101 | 4 | t | 20 | f + 102 | 4 | t | 21 | f + 103 | 4 | t | 22 | f + 104 | 4 | t | 23 | f + 105 | 4 | t | 24 | f + 106 | 4 | t | 25 | f + 107 | 4 | t | 26 | f + 108 | 4 | t | 27 | + 109 | 5 | t | 1 | t + 110 | 5 | t | 2 | t + 111 | 5 | t | 3 | t + 112 | 5 | t | 4 | t + 113 | 5 | t | 5 | t + 114 | 5 | t | 6 | t + 115 | 5 | t | 7 | t + 116 | 5 | t | 8 | t + 117 | 5 | t | 9 | t + 118 | 5 | t | 10 | t + 119 | 5 | t | 11 | t + 120 | 5 | t | 12 | t + 121 | 5 | t | 13 | t + 122 | 5 | t | 14 | f + 123 | 5 | t | 15 | f + 124 | 5 | t | 16 | f + 125 | 5 | t | 17 | f + 126 | 5 | t | 18 | f + 127 | 5 | t | 19 | f + 128 | 5 | t | 20 | f + 129 | 5 | t | 21 | f + 130 | 5 | t | 22 | f + 131 | 5 | t | 23 | f + 132 | 5 | t | 24 | f + 133 | 5 | t | 25 | f + 134 | 5 | t | 26 | f + 135 | 5 | t | 27 | + 136 | 6 | t | 1 | t + 137 | 6 | t | 2 | t + 138 | 6 | t | 3 | t + 139 | 6 | t | 4 | t + 140 | 6 | t | 5 | t + 141 | 6 | t | 6 | t + 142 | 6 | t | 7 | t + 143 | 6 | t | 8 | t + 144 | 6 | t | 9 | t + 145 | 6 | t | 10 | t + 146 | 6 | t | 11 | t + 147 | 6 | t | 12 | t + 148 | 6 | t | 13 | t + 149 | 6 | t | 14 | f + 150 | 6 | t | 15 | f + 151 | 6 | t | 16 | f + 152 | 6 | t | 17 | f + 153 | 6 | t | 18 | f + 154 | 6 | t | 19 | f + 155 | 6 | t | 20 | f + 156 | 6 | t | 21 | f + 157 | 6 | t | 22 | f + 158 | 6 | t | 23 | f + 159 | 6 | t | 24 | f + 160 | 6 | t | 25 | f + 161 | 6 | t | 26 | f + 162 | 6 | t | 27 | + 163 | 7 | t | 1 | t + 164 | 7 | t | 2 | t + 165 | 7 | t | 3 | t + 166 | 7 | t | 4 | t + 167 | 7 | t | 5 | t + 168 | 7 | t | 6 | t + 169 | 7 | t | 7 | t + 170 | 7 | t | 8 | t + 171 | 7 | t | 9 | t + 172 | 7 | t | 10 | t + 173 | 7 | t | 11 | t + 174 | 7 | t | 12 | t + 175 | 7 | t | 13 | t + 176 | 7 | t | 14 | f + 177 | 7 | t | 15 | f + 178 | 7 | t | 16 | f + 179 | 7 | t | 17 | f + 180 | 7 | t | 18 | f + 181 | 7 | t | 19 | f + 182 | 7 | t | 20 | f + 183 | 7 | t | 21 | f + 184 | 7 | t | 22 | f + 185 | 7 | t | 23 | f + 186 | 7 | t | 24 | f + 187 | 7 | t | 25 | f + 188 | 7 | t | 26 | f + 189 | 7 | t | 27 | + 190 | 8 | t | 1 | t + 191 | 8 | t | 2 | t + 192 | 8 | t | 3 | t + 193 | 8 | t | 4 | t + 194 | 8 | t | 5 | t + 195 | 8 | t | 6 | t + 196 | 8 | t | 7 | t + 197 | 8 | t | 8 | t + 198 | 8 | t | 9 | t + 199 | 8 | t | 10 | t + 200 | 8 | t | 11 | t + 201 | 8 | t | 12 | t + 202 | 8 | t | 13 | t + 203 | 8 | t | 14 | f + 204 | 8 | t | 15 | f + 205 | 8 | t | 16 | f + 206 | 8 | t | 17 | f + 207 | 8 | t | 18 | f + 208 | 8 | t | 19 | f + 209 | 8 | t | 20 | f + 210 | 8 | t | 21 | f + 211 | 8 | t | 22 | f + 212 | 8 | t | 23 | f + 213 | 8 | t | 24 | f + 214 | 8 | t | 25 | f + 215 | 8 | t | 26 | f + 216 | 8 | t | 27 | + 217 | 9 | t | 1 | t + 218 | 9 | t | 2 | t + 219 | 9 | t | 3 | t + 220 | 9 | t | 4 | t + 221 | 9 | t | 5 | t + 222 | 9 | t | 6 | t + 223 | 9 | t | 7 | t + 224 | 9 | t | 8 | t + 225 | 9 | t | 9 | t + 226 | 9 | t | 10 | t + 227 | 9 | t | 11 | t + 228 | 9 | t | 12 | t + 229 | 9 | t | 13 | t + 230 | 9 | t | 14 | f + 231 | 9 | t | 15 | f + 232 | 9 | t | 16 | f + 233 | 9 | t | 17 | f + 234 | 9 | t | 18 | f + 235 | 9 | t | 19 | f + 236 | 9 | t | 20 | f + 237 | 9 | t | 21 | f + 238 | 9 | t | 22 | f + 239 | 9 | t | 23 | f + 240 | 9 | t | 24 | f + 241 | 9 | t | 25 | f + 242 | 9 | t | 26 | f + 243 | 9 | t | 27 | + 244 | 10 | t | 1 | t + 245 | 10 | t | 2 | t + 246 | 10 | t | 3 | t + 247 | 10 | t | 4 | t + 248 | 10 | t | 5 | t + 249 | 10 | t | 6 | t + 250 | 10 | t | 7 | t + 251 | 10 | t | 8 | t + 252 | 10 | t | 9 | t + 253 | 10 | t | 10 | t + 254 | 10 | t | 11 | t + 255 | 10 | t | 12 | t + 256 | 10 | t | 13 | t + 257 | 10 | t | 14 | f + 258 | 10 | t | 15 | f + 259 | 10 | t | 16 | f + 260 | 10 | t | 17 | f + 261 | 10 | t | 18 | f + 262 | 10 | t | 19 | f + 263 | 10 | t | 20 | f + 264 | 10 | t | 21 | f + 265 | 10 | t | 22 | f + 266 | 10 | t | 23 | f + 267 | 10 | t | 24 | f + 268 | 10 | t | 25 | f + 269 | 10 | t | 26 | f + 270 | 10 | t | 27 | + 271 | 11 | t | 1 | t + 272 | 11 | t | 2 | t + 273 | 11 | t | 3 | t + 274 | 11 | t | 4 | t + 275 | 11 | t | 5 | t + 276 | 11 | t | 6 | t + 277 | 11 | t | 7 | t + 278 | 11 | t | 8 | t + 279 | 11 | t | 9 | t + 280 | 11 | t | 10 | t + 281 | 11 | t | 11 | t + 282 | 11 | t | 12 | t + 283 | 11 | t | 13 | t + 284 | 11 | t | 14 | f + 285 | 11 | t | 15 | f + 286 | 11 | t | 16 | f + 287 | 11 | t | 17 | f + 288 | 11 | t | 18 | f + 289 | 11 | t | 19 | f + 290 | 11 | t | 20 | f + 291 | 11 | t | 21 | f + 292 | 11 | t | 22 | f + 293 | 11 | t | 23 | f + 294 | 11 | t | 24 | f + 295 | 11 | t | 25 | f + 296 | 11 | t | 26 | f + 297 | 11 | t | 27 | + 298 | 12 | t | 1 | t + 299 | 12 | t | 2 | t + 300 | 12 | t | 3 | t + 301 | 12 | t | 4 | t + 302 | 12 | t | 5 | t + 303 | 12 | t | 6 | t + 304 | 12 | t | 7 | t + 305 | 12 | t | 8 | t + 306 | 12 | t | 9 | t + 307 | 12 | t | 10 | t + 308 | 12 | t | 11 | t + 309 | 12 | t | 12 | t + 310 | 12 | t | 13 | t + 311 | 12 | t | 14 | f + 312 | 12 | t | 15 | f + 313 | 12 | t | 16 | f + 314 | 12 | t | 17 | f + 315 | 12 | t | 18 | f + 316 | 12 | t | 19 | f + 317 | 12 | t | 20 | f + 318 | 12 | t | 21 | f + 319 | 12 | t | 22 | f + 320 | 12 | t | 23 | f + 321 | 12 | t | 24 | f + 322 | 12 | t | 25 | f + 323 | 12 | t | 26 | f + 324 | 12 | t | 27 | + 325 | 13 | t | 1 | t + 326 | 13 | t | 2 | t + 327 | 13 | t | 3 | t + 328 | 13 | t | 4 | t + 329 | 13 | t | 5 | t + 330 | 13 | t | 6 | t + 331 | 13 | t | 7 | t + 332 | 13 | t | 8 | t + 333 | 13 | t | 9 | t + 334 | 13 | t | 10 | t + 335 | 13 | t | 11 | t + 336 | 13 | t | 12 | t + 337 | 13 | t | 13 | t + 338 | 13 | t | 14 | f + 339 | 13 | t | 15 | f + 340 | 13 | t | 16 | f + 341 | 13 | t | 17 | f + 342 | 13 | t | 18 | f + 343 | 13 | t | 19 | f + 344 | 13 | t | 20 | f + 345 | 13 | t | 21 | f + 346 | 13 | t | 22 | f + 347 | 13 | t | 23 | f + 348 | 13 | t | 24 | f + 349 | 13 | t | 25 | f + 350 | 13 | t | 26 | f + 351 | 13 | t | 27 | + 352 | 14 | f | 1 | t + 353 | 14 | f | 2 | t + 354 | 14 | f | 3 | t + 355 | 14 | f | 4 | t + 356 | 14 | f | 5 | t + 357 | 14 | f | 6 | t + 358 | 14 | f | 7 | t + 359 | 14 | f | 8 | t + 360 | 14 | f | 9 | t + 361 | 14 | f | 10 | t + 362 | 14 | f | 11 | t + 363 | 14 | f | 12 | t + 364 | 14 | f | 13 | t + 365 | 14 | f | 14 | f + 366 | 14 | f | 15 | f + 367 | 14 | f | 16 | f + 368 | 14 | f | 17 | f + 369 | 14 | f | 18 | f + 370 | 14 | f | 19 | f + 371 | 14 | f | 20 | f + 372 | 14 | f | 21 | f + 373 | 14 | f | 22 | f + 374 | 14 | f | 23 | f + 375 | 14 | f | 24 | f + 376 | 14 | f | 25 | f + 377 | 14 | f | 26 | f + 378 | 14 | f | 27 | + 379 | 15 | f | 1 | t + 380 | 15 | f | 2 | t + 381 | 15 | f | 3 | t + 382 | 15 | f | 4 | t + 383 | 15 | f | 5 | t + 384 | 15 | f | 6 | t + 385 | 15 | f | 7 | t + 386 | 15 | f | 8 | t + 387 | 15 | f | 9 | t + 388 | 15 | f | 10 | t + 389 | 15 | f | 11 | t + 390 | 15 | f | 12 | t + 391 | 15 | f | 13 | t + 392 | 15 | f | 14 | f + 393 | 15 | f | 15 | f + 394 | 15 | f | 16 | f + 395 | 15 | f | 17 | f + 396 | 15 | f | 18 | f + 397 | 15 | f | 19 | f + 398 | 15 | f | 20 | f + 399 | 15 | f | 21 | f + 400 | 15 | f | 22 | f + 401 | 15 | f | 23 | f + 402 | 15 | f | 24 | f + 403 | 15 | f | 25 | f + 404 | 15 | f | 26 | f + 405 | 15 | f | 27 | + 406 | 16 | f | 1 | t + 407 | 16 | f | 2 | t + 408 | 16 | f | 3 | t + 409 | 16 | f | 4 | t + 410 | 16 | f | 5 | t + 411 | 16 | f | 6 | t + 412 | 16 | f | 7 | t + 413 | 16 | f | 8 | t + 414 | 16 | f | 9 | t + 415 | 16 | f | 10 | t + 416 | 16 | f | 11 | t + 417 | 16 | f | 12 | t + 418 | 16 | f | 13 | t + 419 | 16 | f | 14 | f + 420 | 16 | f | 15 | f + 421 | 16 | f | 16 | f + 422 | 16 | f | 17 | f + 423 | 16 | f | 18 | f + 424 | 16 | f | 19 | f + 425 | 16 | f | 20 | f + 426 | 16 | f | 21 | f + 427 | 16 | f | 22 | f + 428 | 16 | f | 23 | f + 429 | 16 | f | 24 | f + 430 | 16 | f | 25 | f + 431 | 16 | f | 26 | f + 432 | 16 | f | 27 | + 433 | 17 | f | 1 | t + 434 | 17 | f | 2 | t + 435 | 17 | f | 3 | t + 436 | 17 | f | 4 | t + 437 | 17 | f | 5 | t + 438 | 17 | f | 6 | t + 439 | 17 | f | 7 | t + 440 | 17 | f | 8 | t + 441 | 17 | f | 9 | t + 442 | 17 | f | 10 | t + 443 | 17 | f | 11 | t + 444 | 17 | f | 12 | t + 445 | 17 | f | 13 | t + 446 | 17 | f | 14 | f + 447 | 17 | f | 15 | f + 448 | 17 | f | 16 | f + 449 | 17 | f | 17 | f + 450 | 17 | f | 18 | f + 451 | 17 | f | 19 | f + 452 | 17 | f | 20 | f + 453 | 17 | f | 21 | f + 454 | 17 | f | 22 | f + 455 | 17 | f | 23 | f + 456 | 17 | f | 24 | f + 457 | 17 | f | 25 | f + 458 | 17 | f | 26 | f + 459 | 17 | f | 27 | + 460 | 18 | f | 1 | t + 461 | 18 | f | 2 | t + 462 | 18 | f | 3 | t + 463 | 18 | f | 4 | t + 464 | 18 | f | 5 | t + 465 | 18 | f | 6 | t + 466 | 18 | f | 7 | t + 467 | 18 | f | 8 | t + 468 | 18 | f | 9 | t + 469 | 18 | f | 10 | t + 470 | 18 | f | 11 | t + 471 | 18 | f | 12 | t + 472 | 18 | f | 13 | t + 473 | 18 | f | 14 | f + 474 | 18 | f | 15 | f + 475 | 18 | f | 16 | f + 476 | 18 | f | 17 | f + 477 | 18 | f | 18 | f + 478 | 18 | f | 19 | f + 479 | 18 | f | 20 | f + 480 | 18 | f | 21 | f + 481 | 18 | f | 22 | f + 482 | 18 | f | 23 | f + 483 | 18 | f | 24 | f + 484 | 18 | f | 25 | f + 485 | 18 | f | 26 | f + 486 | 18 | f | 27 | + 487 | 19 | f | 1 | t + 488 | 19 | f | 2 | t + 489 | 19 | f | 3 | t + 490 | 19 | f | 4 | t + 491 | 19 | f | 5 | t + 492 | 19 | f | 6 | t + 493 | 19 | f | 7 | t + 494 | 19 | f | 8 | t + 495 | 19 | f | 9 | t + 496 | 19 | f | 10 | t + 497 | 19 | f | 11 | t + 498 | 19 | f | 12 | t + 499 | 19 | f | 13 | t + 500 | 19 | f | 14 | f + 501 | 19 | f | 15 | f + 502 | 19 | f | 16 | f + 503 | 19 | f | 17 | f + 504 | 19 | f | 18 | f + 505 | 19 | f | 19 | f + 506 | 19 | f | 20 | f + 507 | 19 | f | 21 | f + 508 | 19 | f | 22 | f + 509 | 19 | f | 23 | f + 510 | 19 | f | 24 | f + 511 | 19 | f | 25 | f + 512 | 19 | f | 26 | f + 513 | 19 | f | 27 | + 514 | 20 | f | 1 | t + 515 | 20 | f | 2 | t + 516 | 20 | f | 3 | t + 517 | 20 | f | 4 | t + 518 | 20 | f | 5 | t + 519 | 20 | f | 6 | t + 520 | 20 | f | 7 | t + 521 | 20 | f | 8 | t + 522 | 20 | f | 9 | t + 523 | 20 | f | 10 | t + 524 | 20 | f | 11 | t + 525 | 20 | f | 12 | t + 526 | 20 | f | 13 | t + 527 | 20 | f | 14 | f + 528 | 20 | f | 15 | f + 529 | 20 | f | 16 | f + 530 | 20 | f | 17 | f + 531 | 20 | f | 18 | f + 532 | 20 | f | 19 | f + 533 | 20 | f | 20 | f + 534 | 20 | f | 21 | f + 535 | 20 | f | 22 | f + 536 | 20 | f | 23 | f + 537 | 20 | f | 24 | f + 538 | 20 | f | 25 | f + 539 | 20 | f | 26 | f + 540 | 20 | f | 27 | + 541 | 21 | f | 1 | t + 542 | 21 | f | 2 | t + 543 | 21 | f | 3 | t + 544 | 21 | f | 4 | t + 545 | 21 | f | 5 | t + 546 | 21 | f | 6 | t + 547 | 21 | f | 7 | t + 548 | 21 | f | 8 | t + 549 | 21 | f | 9 | t + 550 | 21 | f | 10 | t + 551 | 21 | f | 11 | t + 552 | 21 | f | 12 | t + 553 | 21 | f | 13 | t + 554 | 21 | f | 14 | f + 555 | 21 | f | 15 | f + 556 | 21 | f | 16 | f + 557 | 21 | f | 17 | f + 558 | 21 | f | 18 | f + 559 | 21 | f | 19 | f + 560 | 21 | f | 20 | f + 561 | 21 | f | 21 | f + 562 | 21 | f | 22 | f + 563 | 21 | f | 23 | f + 564 | 21 | f | 24 | f + 565 | 21 | f | 25 | f + 566 | 21 | f | 26 | f + 567 | 21 | f | 27 | + 568 | 22 | f | 1 | t + 569 | 22 | f | 2 | t + 570 | 22 | f | 3 | t + 571 | 22 | f | 4 | t + 572 | 22 | f | 5 | t + 573 | 22 | f | 6 | t + 574 | 22 | f | 7 | t + 575 | 22 | f | 8 | t + 576 | 22 | f | 9 | t + 577 | 22 | f | 10 | t + 578 | 22 | f | 11 | t + 579 | 22 | f | 12 | t + 580 | 22 | f | 13 | t + 581 | 22 | f | 14 | f + 582 | 22 | f | 15 | f + 583 | 22 | f | 16 | f + 584 | 22 | f | 17 | f + 585 | 22 | f | 18 | f + 586 | 22 | f | 19 | f + 587 | 22 | f | 20 | f + 588 | 22 | f | 21 | f + 589 | 22 | f | 22 | f + 590 | 22 | f | 23 | f + 591 | 22 | f | 24 | f + 592 | 22 | f | 25 | f + 593 | 22 | f | 26 | f + 594 | 22 | f | 27 | + 595 | 23 | f | 1 | t + 596 | 23 | f | 2 | t + 597 | 23 | f | 3 | t + 598 | 23 | f | 4 | t + 599 | 23 | f | 5 | t + 600 | 23 | f | 6 | t + 601 | 23 | f | 7 | t + 602 | 23 | f | 8 | t + 603 | 23 | f | 9 | t + 604 | 23 | f | 10 | t + 605 | 23 | f | 11 | t + 606 | 23 | f | 12 | t + 607 | 23 | f | 13 | t + 608 | 23 | f | 14 | f + 609 | 23 | f | 15 | f + 610 | 23 | f | 16 | f + 611 | 23 | f | 17 | f + 612 | 23 | f | 18 | f + 613 | 23 | f | 19 | f + 614 | 23 | f | 20 | f + 615 | 23 | f | 21 | f + 616 | 23 | f | 22 | f + 617 | 23 | f | 23 | f + 618 | 23 | f | 24 | f + 619 | 23 | f | 25 | f + 620 | 23 | f | 26 | f + 621 | 23 | f | 27 | + 622 | 24 | f | 1 | t + 623 | 24 | f | 2 | t + 624 | 24 | f | 3 | t + 625 | 24 | f | 4 | t + 626 | 24 | f | 5 | t + 627 | 24 | f | 6 | t + 628 | 24 | f | 7 | t + 629 | 24 | f | 8 | t + 630 | 24 | f | 9 | t + 631 | 24 | f | 10 | t + 632 | 24 | f | 11 | t + 633 | 24 | f | 12 | t + 634 | 24 | f | 13 | t + 635 | 24 | f | 14 | f + 636 | 24 | f | 15 | f + 637 | 24 | f | 16 | f + 638 | 24 | f | 17 | f + 639 | 24 | f | 18 | f + 640 | 24 | f | 19 | f + 641 | 24 | f | 20 | f + 642 | 24 | f | 21 | f + 643 | 24 | f | 22 | f + 644 | 24 | f | 23 | f + 645 | 24 | f | 24 | f + 646 | 24 | f | 25 | f + 647 | 24 | f | 26 | f + 648 | 24 | f | 27 | + 649 | 25 | f | 1 | t + 650 | 25 | f | 2 | t + 651 | 25 | f | 3 | t + 652 | 25 | f | 4 | t + 653 | 25 | f | 5 | t + 654 | 25 | f | 6 | t + 655 | 25 | f | 7 | t + 656 | 25 | f | 8 | t + 657 | 25 | f | 9 | t + 658 | 25 | f | 10 | t + 659 | 25 | f | 11 | t + 660 | 25 | f | 12 | t + 661 | 25 | f | 13 | t + 662 | 25 | f | 14 | f + 663 | 25 | f | 15 | f + 664 | 25 | f | 16 | f + 665 | 25 | f | 17 | f + 666 | 25 | f | 18 | f + 667 | 25 | f | 19 | f + 668 | 25 | f | 20 | f + 669 | 25 | f | 21 | f + 670 | 25 | f | 22 | f + 671 | 25 | f | 23 | f + 672 | 25 | f | 24 | f + 673 | 25 | f | 25 | f + 674 | 25 | f | 26 | f + 675 | 25 | f | 27 | + 676 | 26 | f | 1 | t + 677 | 26 | f | 2 | t + 678 | 26 | f | 3 | t + 679 | 26 | f | 4 | t + 680 | 26 | f | 5 | t + 681 | 26 | f | 6 | t + 682 | 26 | f | 7 | t + 683 | 26 | f | 8 | t + 684 | 26 | f | 9 | t + 685 | 26 | f | 10 | t + 686 | 26 | f | 11 | t + 687 | 26 | f | 12 | t + 688 | 26 | f | 13 | t + 689 | 26 | f | 14 | f + 690 | 26 | f | 15 | f + 691 | 26 | f | 16 | f + 692 | 26 | f | 17 | f + 693 | 26 | f | 18 | f + 694 | 26 | f | 19 | f + 695 | 26 | f | 20 | f + 696 | 26 | f | 21 | f + 697 | 26 | f | 22 | f + 698 | 26 | f | 23 | f + 699 | 26 | f | 24 | f + 700 | 26 | f | 25 | f + 701 | 26 | f | 26 | f + 702 | 26 | f | 27 | + 703 | 27 | | 1 | t + 704 | 27 | | 2 | t + 705 | 27 | | 3 | t + 706 | 27 | | 4 | t + 707 | 27 | | 5 | t + 708 | 27 | | 6 | t + 709 | 27 | | 7 | t + 710 | 27 | | 8 | t + 711 | 27 | | 9 | t + 712 | 27 | | 10 | t + 713 | 27 | | 11 | t + 714 | 27 | | 12 | t + 715 | 27 | | 13 | t + 716 | 27 | | 14 | f + 717 | 27 | | 15 | f + 718 | 27 | | 16 | f + 719 | 27 | | 17 | f + 720 | 27 | | 18 | f + 721 | 27 | | 19 | f + 722 | 27 | | 20 | f + 723 | 27 | | 21 | f + 724 | 27 | | 22 | f + 725 | 27 | | 23 | f + 726 | 27 | | 24 | f + 727 | 27 | | 25 | f + 728 | 27 | | 26 | f + 729 | 27 | | 27 | +(729 rows) + +--Testcase 60: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Unique + Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) + -> Foreign Scan on public."type_BOOLEAN_oper" + Output: b1, b2, (b1 AND b2), (b1 OR b2) + SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST +(5 rows) + +--Testcase 61: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; + b1 | b2 | a | o +----+----+---+--- + f | f | f | f + f | t | f | t + f | | f | + t | f | f | t + t | t | t | t + t | | | t + | f | f | + | t | | t + | | | +(9 rows) + +--Testcase 62: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Unique + Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) + -> Foreign Scan on public."type_BOOLEAN_oper" + Output: b1, b2, (b1 AND b2), (b1 OR b2) + SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" WHERE (sqlite_fdw_bool(`b1`)) AND (sqlite_fdw_bool(`b2`)) ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST +(5 rows) + +--Testcase 63: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; + b1 | b2 | a | o +----+----+---+--- + t | t | t | t +(1 row) + +--Testcase 64: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Unique + Output: b1, b2, ((b1 AND b2)), ((b1 OR b2)) + -> Foreign Scan on public."type_BOOLEAN_oper" + Output: b1, b2, (b1 AND b2), (b1 OR b2) + SQLite query: SELECT sqlite_fdw_bool(`b1`), sqlite_fdw_bool(`b2`) FROM main."type_BOOLEAN_oper" WHERE ((sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`))) ORDER BY sqlite_fdw_bool(`b1`) ASC NULLS LAST, sqlite_fdw_bool(`b2`) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) AND sqlite_fdw_bool(`b2`)) ASC NULLS LAST, (sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`)) ASC NULLS LAST +(5 rows) + +--Testcase 65: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; + b1 | b2 | a | o +----+----+---+--- + f | t | f | t + t | f | f | t + t | t | t | t + t | | | t + | t | | t +(5 rows) + +--Testcase 66: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Update on public."type_BOOLEAN_oper" + -> Foreign Update on public."type_BOOLEAN_oper" + SQLite query: UPDATE main."type_BOOLEAN_oper" SET `b1` = NULL WHERE ((NOT sqlite_fdw_bool(`b1`))) +(3 rows) + +--Testcase 67: +UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; +--Testcase 68: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + b1 | b2 +----+---- + t | f + t | t + t | + | f + | t + | +(6 rows) + +--Testcase 69: +UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; +--Testcase 70: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Update on public."type_BOOLEAN_oper" + -> Foreign Update on public."type_BOOLEAN_oper" + SQLite query: UPDATE main."type_BOOLEAN_oper" SET `b1` = 0 WHERE ((sqlite_fdw_bool(`b1`) OR sqlite_fdw_bool(`b2`))) +(3 rows) + +--Testcase 71: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + b1 | b2 +----+---- + f | f + f | t + f | + | f + | +(5 rows) + +--Testcase 72: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Delete on public."type_BOOLEAN_oper" + -> Foreign Delete on public."type_BOOLEAN_oper" + SQLite query: DELETE FROM main."type_BOOLEAN_oper" WHERE ((NOT sqlite_fdw_bool(`b1`))) AND (sqlite_fdw_bool(`b2`)) +(3 rows) + +--Testcase 73: +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; +--Testcase 74: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + b1 | b2 +----+---- + f | f + f | + | f + | +(4 rows) + +--Testcase 75: +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b2; +--Testcase 76: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + b1 | b2 +----+---- + f | + | +(2 rows) + +--Testcase 77: +DELETE FROM "type_BOOLEAN_oper" WHERE b2; +--Testcase 78: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + b1 | b2 +----+---- + f | + | +(2 rows) + +--Testcase 79: +DELETE FROM "type_BOOLEAN"; +--Testcase 003: +DROP EXTENSION sqlite_fdw CASCADE; +NOTICE: drop cascades to 6 other objects +DETAIL: drop cascades to server sqlite_svr +drop cascades to foreign table "type_BOOLEAN" +drop cascades to foreign table "type_BOOLEAN+" +drop cascades to foreign table "type_BOOLEANpk" +drop cascades to foreign table "type_BOOLEAN_oper" +drop cascades to server sqlite2 diff --git a/expected/16.0/extra/encodings.out b/expected/17.0/extra/encodings.out similarity index 100% rename from expected/16.0/extra/encodings.out rename to expected/17.0/extra/encodings.out diff --git a/expected/13.12/extra/float4.out b/expected/17.0/extra/float4.out similarity index 95% rename from expected/13.12/extra/float4.out rename to expected/17.0/extra/float4.out index 7b53576e..1d3d83e2 100644 --- a/expected/13.12/extra/float4.out +++ b/expected/17.0/extra/float4.out @@ -114,6 +114,33 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type real: "123 5" LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); ^ +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_FLOAT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_FLOAT4 VALUES ('34.5', 1), ('xyz', 2), ('1e400', 3); +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 1; + pg_input_is_valid +------------------- + t +(1 row) + +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 2; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 3; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 3), 'float4'); + message | detail | hint | sql_error_code +---------------------------------------+--------+------+---------------- + "1e400" is out of range for type real | | | 22003 +(1 row) + -- special inputs --Testcase 18: DELETE FROM FLOAT4_TMP; @@ -232,6 +259,17 @@ SELECT f1 FROM FLOAT4_TMP; (1 row) +--Testcase 185: +DELETE FROM FLOAT4_TMP; +--Testcase 186: +INSERT INTO FLOAT4_TMP VALUES ('42'::float4 / 'Infinity'::float4); +--Testcase 187: +SELECT f1 FROM FLOAT4_TMP; + f1 +---- + 0 +(1 row) + --Testcase 31: DELETE FROM FLOAT4_TMP; --Testcase 78: @@ -243,6 +281,17 @@ SELECT f1 FROM FLOAT4_TMP; (1 row) +--Testcase 188: +DELETE FROM FLOAT4_TMP; +--Testcase 189: +INSERT INTO FLOAT4_TMP VALUES ('nan'::float4 / '0'::float4); +--Testcase 190: +SELECT f1 FROM FLOAT4_TMP; + f1 +---- + +(1 row) + --Testcase 32: DELETE FROM FLOAT4_TMP; --Testcase 80: @@ -255,14 +304,14 @@ SELECT f1 FROM FLOAT4_TMP; (1 row) --Testcase 34: -SELECT '' AS five, * FROM FLOAT4_TBL; - five | f1 -------+--------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345679e+20 - | 1.2345679e-20 +SELECT * FROM FLOAT4_TBL; + f1 +--------------- + 0 + 1004.3 + -34.84 + 1.2345679e+20 + 1.2345679e-20 (5 rows) --SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <> '1004.3'; @@ -270,90 +319,90 @@ SELECT '' AS five, * FROM FLOAT4_TBL; --SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE '1004.3' > f.f1; --SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE f.f1 < '1004.3'; --Testcase 35: -SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1; - four | f1 -------+--------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345679e-20 +SELECT f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1; + f1 +--------------- + 0 + 1004.3 + -34.84 + 1.2345679e-20 (4 rows) --Testcase 36: -SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <= '1004.3'; - four | f1 -------+--------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345679e-20 +SELECT f.* FROM FLOAT4_TBL f WHERE f.f1 <= '1004.3'; + f1 +--------------- + 0 + 1004.3 + -34.84 + 1.2345679e-20 (4 rows) --Testcase 37: -SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+---------------+---------------- - | 1004.3 | -10043 - | 1.2345679e+20 | -1.2345678e+21 - | 1.2345679e-20 | -1.2345678e-19 + f1 | x +---------------+---------------- + 1004.3 | -10043 + 1.2345679e+20 | -1.2345678e+21 + 1.2345679e-20 | -1.2345678e-19 (3 rows) --Testcase 38: -SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+---------------+--------------- - | 1004.3 | 994.3 - | 1.2345679e+20 | 1.2345679e+20 - | 1.2345679e-20 | -10 + f1 | x +---------------+--------------- + 1004.3 | 994.3 + 1.2345679e+20 | 1.2345679e+20 + 1.2345679e-20 | -10 (3 rows) --Testcase 39: -SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+---------------+---------------- - | 1004.3 | -100.43 - | 1.2345679e+20 | -1.2345679e+19 - | 1.2345679e-20 | -1.2345679e-21 + f1 | x +---------------+---------------- + 1004.3 | -100.43 + 1.2345679e+20 | -1.2345679e+19 + 1.2345679e-20 | -1.2345679e-21 (3 rows) --Testcase 40: -SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+---------------+--------------- - | 1004.3 | 1014.3 - | 1.2345679e+20 | 1.2345679e+20 - | 1.2345679e-20 | 10 + f1 | x +---------------+--------------- + 1004.3 | 1014.3 + 1.2345679e+20 | 1.2345679e+20 + 1.2345679e-20 | 10 (3 rows) -- test divide by zero --Testcase 41: -SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f; +SELECT f.f1 / '0.0' from FLOAT4_TBL f; ERROR: division by zero --Testcase 42: -SELECT '' AS five, * FROM FLOAT4_TBL; - five | f1 -------+--------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345679e+20 - | 1.2345679e-20 +SELECT * FROM FLOAT4_TBL; + f1 +--------------- + 0 + 1004.3 + -34.84 + 1.2345679e+20 + 1.2345679e-20 (5 rows) -- test the unary float4abs operator --Testcase 43: -SELECT '' AS five, f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; - five | f1 | abs_f1 -------+---------------+--------------- - | 0 | 0 - | 1004.3 | 1004.3 - | -34.84 | 34.84 - | 1.2345679e+20 | 1.2345679e+20 - | 1.2345679e-20 | 1.2345679e-20 +SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; + f1 | abs_f1 +---------------+--------------- + 0 | 0 + 1004.3 | 1004.3 + -34.84 | 34.84 + 1.2345679e+20 | 1.2345679e+20 + 1.2345679e-20 | 1.2345679e-20 (5 rows) --Testcase 44: @@ -361,14 +410,14 @@ UPDATE FLOAT4_TBL SET f1 = FLOAT4_TBL.f1 * '-1' WHERE FLOAT4_TBL.f1 > '0.0'; --Testcase 45: -SELECT '' AS five, * FROM FLOAT4_TBL; - five | f1 -------+---------------- - | 0 - | -1004.3 - | -34.84 - | -1.2345679e+20 - | -1.2345679e-20 +SELECT * FROM FLOAT4_TBL; + f1 +---------------- + 0 + -1004.3 + -34.84 + -1.2345679e+20 + -1.2345679e-20 (5 rows) -- test edge-case coercions to integer diff --git a/expected/12.16/extra/float8.out b/expected/17.0/extra/float8.out similarity index 84% rename from expected/12.16/extra/float8.out rename to expected/17.0/extra/float8.out index e9e029a1..aff54f77 100644 --- a/expected/12.16/extra/float8.out +++ b/expected/17.0/extra/float8.out @@ -92,6 +92,33 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ^ +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_FLOAT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_FLOAT8 VALUES ('34.5', 1), ('xyz', 2), ('1e4000', 3); +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 1; + pg_input_is_valid +------------------- + t +(1 row) + +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 2; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 3; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 3), 'float8'); + message | detail | hint | sql_error_code +----------------------------------------------------+--------+------+---------------- + "1e4000" is out of range for type double precision | | | 22003 +(1 row) + -- special inputs --Testcase 19: DELETE FROM FLOAT8_TMP; @@ -210,6 +237,17 @@ SELECT f1 FROM FLOAT8_TMP; (1 row) +--Testcase 272: +DELETE FROM FLOAT8_TMP; +--Testcase 273: +INSERT INTO FLOAT8_TMP VALUES ('42'::float8 / 'Infinity'::float8); +--Testcase 274: +SELECT f1 FROM FLOAT8_TMP; + f1 +---- + 0 +(1 row) + --Testcase 31: DELETE FROM FLOAT8_TMP; --Testcase 139: @@ -221,6 +259,17 @@ SELECT f1 FROM FLOAT8_TMP; (1 row) +--Testcase 275: +DELETE FROM FLOAT8_TMP; +--Testcase 276: +INSERT INTO FLOAT8_TMP VALUES ('nan'::float8 / '0'::float8); +--Testcase 277: +SELECT f1 FROM FLOAT8_TMP; + f1 +---- + +(1 row) + --Testcase 32: DELETE FROM FLOAT8_TMP; --Testcase 141: @@ -233,160 +282,160 @@ SELECT f1 FROM FLOAT8_TMP; (1 row) --Testcase 34: -SELECT '' AS five, * FROM FLOAT8_TBL; - five | f1 -------+---------------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345678901234e+200 - | 1.2345678901234e-200 +SELECT * FROM FLOAT8_TBL; + f1 +---------------------- + 0 + 1004.3 + -34.84 + 1.2345678901234e+200 + 1.2345678901234e-200 (5 rows) --Testcase 35: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; - four | f1 -------+---------------------- - | 0 - | -34.84 - | 1.2345678901234e+200 - | 1.2345678901234e-200 +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; + f1 +---------------------- + 0 + -34.84 + 1.2345678901234e+200 + 1.2345678901234e-200 (4 rows) --Testcase 36: -SELECT '' AS one, f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; - one | f1 ------+-------- - | 1004.3 +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; + f1 +-------- + 1004.3 (1 row) --Testcase 37: -SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; - three | f1 --------+---------------------- - | 0 - | -34.84 - | 1.2345678901234e-200 +SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; + f1 +---------------------- + 0 + -34.84 + 1.2345678901234e-200 (3 rows) --Testcase 38: -SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; - three | f1 --------+---------------------- - | 0 - | -34.84 - | 1.2345678901234e-200 +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; + f1 +---------------------- + 0 + -34.84 + 1.2345678901234e-200 (3 rows) --Testcase 39: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; - four | f1 -------+---------------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345678901234e-200 +SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; + f1 +---------------------- + 0 + 1004.3 + -34.84 + 1.2345678901234e-200 (4 rows) --Testcase 40: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; - four | f1 -------+---------------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345678901234e-200 +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; + f1 +---------------------- + 0 + 1004.3 + -34.84 + 1.2345678901234e-200 (4 rows) --Testcase 41: -SELECT '' AS three, f.f1, f.f1 * '-10' AS x +SELECT f.f1, f.f1 * '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+----------------------+----------------------- - | 1004.3 | -10043 - | 1.2345678901234e+200 | -1.2345678901234e+201 - | 1.2345678901234e-200 | -1.2345678901234e-199 + f1 | x +----------------------+----------------------- + 1004.3 | -10043 + 1.2345678901234e+200 | -1.2345678901234e+201 + 1.2345678901234e-200 | -1.2345678901234e-199 (3 rows) --Testcase 42: -SELECT '' AS three, f.f1, f.f1 + '-10' AS x +SELECT f.f1, f.f1 + '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+----------------------+---------------------- - | 1004.3 | 994.3 - | 1.2345678901234e+200 | 1.2345678901234e+200 - | 1.2345678901234e-200 | -10 + f1 | x +----------------------+---------------------- + 1004.3 | 994.3 + 1.2345678901234e+200 | 1.2345678901234e+200 + 1.2345678901234e-200 | -10 (3 rows) --Testcase 43: -SELECT '' AS three, f.f1, f.f1 / '-10' AS x +SELECT f.f1, f.f1 / '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+----------------------+----------------------- - | 1004.3 | -100.42999999999999 - | 1.2345678901234e+200 | -1.2345678901234e+199 - | 1.2345678901234e-200 | -1.2345678901234e-201 + f1 | x +----------------------+----------------------- + 1004.3 | -100.42999999999999 + 1.2345678901234e+200 | -1.2345678901234e+199 + 1.2345678901234e-200 | -1.2345678901234e-201 (3 rows) --Testcase 44: -SELECT '' AS three, f.f1, f.f1 - '-10' AS x +SELECT f.f1, f.f1 - '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | x --------+----------------------+---------------------- - | 1004.3 | 1014.3 - | 1.2345678901234e+200 | 1.2345678901234e+200 - | 1.2345678901234e-200 | 10 + f1 | x +----------------------+---------------------- + 1004.3 | 1014.3 + 1.2345678901234e+200 | 1.2345678901234e+200 + 1.2345678901234e-200 | 10 (3 rows) --Testcase 45: -SELECT '' AS one, f.f1 ^ '2.0' AS square_f1 +SELECT f.f1 ^ '2.0' AS square_f1 FROM FLOAT8_TBL f where f.f1 = '1004.3'; - one | square_f1 ------+-------------------- - | 1008618.4899999999 + square_f1 +-------------------- + 1008618.4899999999 (1 row) -- absolute value --Testcase 46: -SELECT '' AS five, f.f1, @f.f1 AS abs_f1 +SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT8_TBL f; - five | f1 | abs_f1 -------+----------------------+---------------------- - | 0 | 0 - | 1004.3 | 1004.3 - | -34.84 | 34.84 - | 1.2345678901234e+200 | 1.2345678901234e+200 - | 1.2345678901234e-200 | 1.2345678901234e-200 + f1 | abs_f1 +----------------------+---------------------- + 0 | 0 + 1004.3 | 1004.3 + -34.84 | 34.84 + 1.2345678901234e+200 | 1.2345678901234e+200 + 1.2345678901234e-200 | 1.2345678901234e-200 (5 rows) -- truncate --Testcase 47: -SELECT '' AS five, f.f1, trunc(f.f1) AS trunc_f1 +SELECT f.f1, trunc(f.f1) AS trunc_f1 FROM FLOAT8_TBL f; - five | f1 | trunc_f1 -------+----------------------+---------------------- - | 0 | 0 - | 1004.3 | 1004 - | -34.84 | -34 - | 1.2345678901234e+200 | 1.2345678901234e+200 - | 1.2345678901234e-200 | 0 + f1 | trunc_f1 +----------------------+---------------------- + 0 | 0 + 1004.3 | 1004 + -34.84 | -34 + 1.2345678901234e+200 | 1.2345678901234e+200 + 1.2345678901234e-200 | 0 (5 rows) -- round --Testcase 48: -SELECT '' AS five, f.f1, round(f.f1) AS round_f1 +SELECT f.f1, round(f.f1) AS round_f1 FROM FLOAT8_TBL f; - five | f1 | round_f1 -------+----------------------+---------------------- - | 0 | 0 - | 1004.3 | 1004 - | -34.84 | -35 - | 1.2345678901234e+200 | 1.2345678901234e+200 - | 1.2345678901234e-200 | 0 + f1 | round_f1 +----------------------+---------------------- + 0 | 0 + 1004.3 | 1004 + -34.84 | -35 + 1.2345678901234e+200 | 1.2345678901234e+200 + 1.2345678901234e-200 | 0 (5 rows) -- ceil / ceiling @@ -437,6 +486,7 @@ select sign(f1) as sign_f1 from float8_tbl f; (5 rows) -- avoid bit-exact output here because operations may not be bit-exact. +--Testcase 278: SET extra_float_digits = 0; -- square root BEGIN; @@ -460,14 +510,14 @@ SELECT |/f1 as eight FROM FLOAT8_TBL; ROLLBACK; --Testcase 57: -SELECT '' AS three, f.f1, |/f.f1 AS sqrt_f1 +SELECT f.f1, |/f.f1 AS sqrt_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | sqrt_f1 --------+----------------------+----------------------- - | 1004.3 | 31.6906926399535 - | 1.2345678901234e+200 | 1.11111110611109e+100 - | 1.2345678901234e-200 | 1.11111110611109e-100 + f1 | sqrt_f1 +----------------------+----------------------- + 1004.3 | 31.6906926399535 + 1.2345678901234e+200 | 1.11111110611109e+100 + 1.2345678901234e-200 | 1.11111110611109e-100 (3 rows) -- power @@ -548,16 +598,321 @@ SELECT power(f1, f2) FROM FLOAT8_TMP; (1 row) +--Testcase 279: +DELETE FROM FLOAT8_TMP; +--Testcase 280: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '0'::float8); +--Testcase 281: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 282: +DELETE FROM FLOAT8_TMP; +--Testcase 283: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '0'::float8); +--Testcase 284: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 285: +DELETE FROM FLOAT8_TMP; +--Testcase 286: +INSERT INTO FLOAT8_TMP VALUES ('0'::float8, 'infinity'::float8); +--Testcase 287: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 288: +DELETE FROM FLOAT8_TMP; +--Testcase 289: +INSERT INTO FLOAT8_TMP VALUES ('0'::float8, '-infinity'::float8); +--Testcase 290: +SELECT power(f1, f2) FROM FLOAT8_TMP; +ERROR: zero raised to a negative power is undefined +--Testcase 291: +DELETE FROM FLOAT8_TMP; +--Testcase 292: +INSERT INTO FLOAT8_TMP VALUES ('1'::float8, 'infinity'::float8); +--Testcase 293: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 294: +DELETE FROM FLOAT8_TMP; +--Testcase 295: +INSERT INTO FLOAT8_TMP VALUES ('1'::float8, '-infinity'::float8); +--Testcase 296: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 297: +DELETE FROM FLOAT8_TMP; +--Testcase 298: +INSERT INTO FLOAT8_TMP VALUES ('-1'::float8, 'infinity'::float8); +--Testcase 299: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 300: +DELETE FROM FLOAT8_TMP; +--Testcase 301: +INSERT INTO FLOAT8_TMP VALUES ('-1'::float8, '-infinity'::float8); +--Testcase 302: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 1 +(1 row) + +--Testcase 303: +DELETE FROM FLOAT8_TMP; +--Testcase 304: +INSERT INTO FLOAT8_TMP VALUES ('0.1'::float8, 'infinity'::float8); +--Testcase 305: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 306: +DELETE FROM FLOAT8_TMP; +--Testcase 307: +INSERT INTO FLOAT8_TMP VALUES ('-0.1'::float8, 'infinity'::float8); +--Testcase 308: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 309: +DELETE FROM FLOAT8_TMP; +--Testcase 310: +INSERT INTO FLOAT8_TMP VALUES ('1.1'::float8, 'infinity'::float8); +--Testcase 311: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 312: +DELETE FROM FLOAT8_TMP; +--Testcase 313: +INSERT INTO FLOAT8_TMP VALUES ('-1.1'::float8, 'infinity'::float8); +--Testcase 314: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 315: +DELETE FROM FLOAT8_TMP; +--Testcase 316: +INSERT INTO FLOAT8_TMP VALUES ('0.1'::float8, '-infinity'::float8); +--Testcase 317: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 318: +DELETE FROM FLOAT8_TMP; +--Testcase 319: +INSERT INTO FLOAT8_TMP VALUES ('-0.1'::float8, '-infinity'::float8); +--Testcase 320: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 321: +DELETE FROM FLOAT8_TMP; +--Testcase 322: +INSERT INTO FLOAT8_TMP VALUES ('1.1'::float8, '-infinity'::float8); +--Testcase 323: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 324: +DELETE FROM FLOAT8_TMP; +--Testcase 325: +INSERT INTO FLOAT8_TMP VALUES ('-1.1'::float8, '-infinity'::float8); +--Testcase 326: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 327: +DELETE FROM FLOAT8_TMP; +--Testcase 328: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '-2'::float8); +--Testcase 329: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +--Testcase 330: +DELETE FROM FLOAT8_TMP; +--Testcase 331: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '2'::float8); +--Testcase 332: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 333: +DELETE FROM FLOAT8_TMP; +--Testcase 334: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, 'infinity'::float8); +--Testcase 335: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 336: +DELETE FROM FLOAT8_TMP; +--Testcase 337: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '-infinity'::float8); +--Testcase 338: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + +-- Intel's icc misoptimizes the code that controls the sign of this result, +-- even with -mp1. Pending a fix for that, only test for "is it zero". +--Testcase 339: +DELETE FROM FLOAT8_TMP; +--Testcase 340: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-2'::float8); +--Testcase 341: +SELECT power(f1, f2) = '0' FROM FLOAT8_TMP; + ?column? +---------- + t +(1 row) + +--Testcase 342: +DELETE FROM FLOAT8_TMP; +--Testcase 343: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-3'::float8); +--Testcase 344: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + -0 +(1 row) + +--Testcase 345: +DELETE FROM FLOAT8_TMP; +--Testcase 346: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '2'::float8); +--Testcase 347: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 348: +DELETE FROM FLOAT8_TMP; +--Testcase 349: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '3'::float8); +--Testcase 350: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +----------- + -Infinity +(1 row) + +--Testcase 351: +DELETE FROM FLOAT8_TMP; +--Testcase 352: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-3.5'::float8); +--Testcase 353: +SELECT power(f1, f2) FROM FLOAT8_TMP; +ERROR: a negative number raised to a non-integer power yields a complex result +--Testcase 354: +DELETE FROM FLOAT8_TMP; +--Testcase 355: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, 'infinity'::float8); +--Testcase 356: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +---------- + Infinity +(1 row) + +--Testcase 357: +DELETE FROM FLOAT8_TMP; +--Testcase 358: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-infinity'::float8); +--Testcase 359: +SELECT power(f1, f2) FROM FLOAT8_TMP; + power +------- + 0 +(1 row) + -- take exp of ln(f.f1) --Testcase 67: -SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1 +SELECT f.f1, exp(ln(f.f1)) AS exp_ln_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; - three | f1 | exp_ln_f1 --------+----------------------+----------------------- - | 1004.3 | 1004.3 - | 1.2345678901234e+200 | 1.23456789012338e+200 - | 1.2345678901234e-200 | 1.23456789012339e-200 + f1 | exp_ln_f1 +----------------------+----------------------- + 1004.3 | 1004.3 + 1.2345678901234e+200 | 1.23456789012338e+200 + 1.2345678901234e-200 | 1.23456789012339e-200 +(3 rows) + +-- check edge cases for exp +--Testcase 360: +DELETE FROM FLOAT8_TMP; +--Testcase 361: +INSERT INTO FLOAT8_TMP VALUES ('inf'::float8), ('-inf'::float8), ('nan'::float8); +--Testcase 362: +SELECT exp(f1) FROM FLOAT8_TMP; + exp +---------- + Infinity + 0 + (3 rows) -- cube root @@ -575,25 +930,25 @@ SELECT ||/f1 as three FROM FLOAT8_TBL; ROLLBACK; --Testcase 71: -SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; - five | f1 | cbrt_f1 -------+----------------------+---------------------- - | 0 | 0 - | 1004.3 | 10.014312837827 - | -34.84 | -3.26607421344208 - | 1.2345678901234e+200 | 4.97933859234765e+66 - | 1.2345678901234e-200 | 2.3112042409018e-67 +SELECT f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; + f1 | cbrt_f1 +----------------------+---------------------- + 0 | 0 + 1004.3 | 10.014312837827 + -34.84 | -3.26607421344208 + 1.2345678901234e+200 | 4.97933859234765e+66 + 1.2345678901234e-200 | 2.3112042409018e-67 (5 rows) --Testcase 72: -SELECT '' AS five, * FROM FLOAT8_TBL; - five | f1 -------+---------------------- - | 0 - | 1004.3 - | -34.84 - | 1.2345678901234e+200 - | 1.2345678901234e-200 +SELECT * FROM FLOAT8_TBL; + f1 +---------------------- + 0 + 1004.3 + -34.84 + 1.2345678901234e+200 + 1.2345678901234e-200 (5 rows) --Testcase 73: @@ -601,10 +956,10 @@ UPDATE FLOAT8_TBL SET f1 = FLOAT8_TBL.f1 * '-1' WHERE FLOAT8_TBL.f1 > '0.0'; --Testcase 74: -SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; +SELECT f.f1 * '1e200' from FLOAT8_TBL f; ERROR: value out of range: overflow --Testcase 75: -SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; +SELECT f.f1 ^ '1e200' from FLOAT8_TBL f; ERROR: value out of range: overflow BEGIN; --Testcase 76: @@ -620,26 +975,26 @@ SELECT * FROM FLOAT8_TBL; ROLLBACK; --Testcase 79: -SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; +SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; ERROR: cannot take logarithm of zero --Testcase 80: -SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; +SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; ERROR: cannot take logarithm of a negative number --Testcase 81: -SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; +SELECT exp(f.f1) from FLOAT8_TBL f; ERROR: value out of range: underflow --Testcase 82: -SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; +SELECT f.f1 / '0.0' from FLOAT8_TBL f; ERROR: division by zero --Testcase 83: -SELECT '' AS five, * FROM FLOAT8_TBL; - five | f1 -------+----------------------- - | 0 - | -1004.3 - | -34.84 - | -1.2345678901234e+200 - | -1.2345678901234e-200 +SELECT * FROM FLOAT8_TBL; + f1 +----------------------- + 0 + -1004.3 + -34.84 + -1.2345678901234e+200 + -1.2345678901234e-200 (5 rows) -- hyperbolic functions @@ -877,6 +1232,48 @@ SELECT atanh(f1) FROM FLOAT8_TMP; (1 row) +-- error functions +-- we run these with extra_float_digits = -1, to get consistently rounded +-- results on all platforms. +SET extra_float_digits = -1; +DELETE FROM FLOAT8_TBL; +INSERT INTO FLOAT8_TBL(f1) VALUES (float8 '-infinity'), + (-28), (-6), (-3.4), (-2.1), (-1.1), (-0.45), + (-1.2e-9), (-2.3e-13), (-1.2e-17), (0), + (1.2e-17), (2.3e-13), (1.2e-9), + (0.45), (1.1), (2.1), (3.4), (6), (28), + (float8 'infinity'), (float8 'nan'); +SELECT f1, + erf(f1), + erfc(f1) +FROM FLOAT8_TBL; + f1 | erf | erfc +-----------+----------------------+--------------------- + -Infinity | -1 | 2 + -28 | -1 | 2 + -6 | -1 | 2 + -3.4 | -0.99999847800664 | 1.9999984780066 + -2.1 | -0.99702053334367 | 1.9970205333437 + -1.1 | -0.88020506957408 | 1.8802050695741 + -0.45 | -0.47548171978692 | 1.4754817197869 + -1.2e-09 | -1.3540550005146e-09 | 1.0000000013541 + -2.3e-13 | -2.5952720843197e-13 | 1.0000000000003 + -1.2e-17 | -1.3540550005146e-17 | 1 + 0 | 0 | 1 + 1.2e-17 | 1.3540550005146e-17 | 1 + 2.3e-13 | 2.5952720843197e-13 | 0.99999999999974 + 1.2e-09 | 1.3540550005146e-09 | 0.99999999864595 + 0.45 | 0.47548171978692 | 0.52451828021308 + 1.1 | 0.88020506957408 | 0.11979493042592 + 2.1 | 0.99702053334367 | 0.002979466656333 + 3.4 | 0.99999847800664 | 1.5219933628623e-06 + 6 | 1 | 2.1519736712499e-17 + 28 | 1 | 0 + Infinity | 1 | 0 + | | +(22 rows) + +--Testcase 369: RESET extra_float_digits; -- test for over- and underflow --Testcase 84: @@ -914,14 +1311,14 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e+200'); --Testcase 93: INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200'); --Testcase 94: -SELECT '' AS five, * FROM FLOAT8_TBL; - five | f1 -------+----------------------- - | 0 - | -34.84 - | -1004.3 - | -1.2345678901234e+200 - | -1.2345678901234e-200 +SELECT * FROM FLOAT8_TBL; + f1 +----------------------- + 0 + -34.84 + -1004.3 + -1.2345678901234e+200 + -1.2345678901234e-200 (5 rows) -- test edge-case coercions to integer @@ -1617,6 +2014,8 @@ drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 drop cascades to cast from xfloat8 to bigint drop cascades to cast from bigint to xfloat8 +--Testcase 363: +DELETE FROM FLOAT8_TBL; -- Clean up DO $d$ declare diff --git a/expected/13.12/extra/insert.out b/expected/17.0/extra/insert.out similarity index 86% rename from expected/13.12/extra/insert.out rename to expected/17.0/extra/insert.out index fa1e72bc..02e04b2c 100644 --- a/expected/13.12/extra/insert.out +++ b/expected/17.0/extra/insert.out @@ -102,6 +102,23 @@ select col1, col2, char_length(col3) from inserttest01; 30 | 50 | 10000 (8 rows) +-- +-- tuple larger than fillfactor +-- foreign table does not support fillfactor +-- +-- CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10); +-- ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain; +-- -- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize) +-- INSERT INTO large_tuple_test (select 1, NULL); +-- -- should still fit on the page +-- INSERT INTO large_tuple_test (select 2, repeat('a', 1000)); +-- SELECT pg_size_pretty(pg_relation_size('large_tuple_test'::regclass, 'main')); +-- -- add small record to the second page +-- INSERT INTO large_tuple_test (select 3, NULL); +-- -- now this tuple won't fit on the second page, but the insert should +-- -- still succeed by extending the relation +-- INSERT INTO large_tuple_test (select 4, repeat('a', 8126)); +-- DROP TABLE large_tuple_test; -- skip, sqlite fdw does not support customized type /* -- check indirection (field/array assignment), cf bug #14265 @@ -149,7 +166,83 @@ create rule irule3 as on insert to inserttest2 do also drop table inserttest2; drop table inserttest; -drop type insert_test_type; +-- Make the same tests with domains over the array and composite fields + +create domain insert_pos_ints as int[] check (value[1] > 0); + +create domain insert_test_domain as insert_test_type + check ((value).if2[1] is not null); + +create table inserttesta (f1 int, f2 insert_pos_ints); +create table inserttestb (f3 insert_test_domain, f4 insert_test_domain[]); + +insert into inserttesta (f2[1], f2[2]) values (1,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (5,6); +insert into inserttesta (f2[1], f2[2]) select 7,8; +insert into inserttesta (f2[1], f2[2]) values (1,default); -- not supported +insert into inserttesta (f2[1], f2[2]) values (0,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (0,6); +insert into inserttesta (f2[1], f2[2]) select 0,8; + +insert into inserttestb (f3.if1, f3.if2) values (1,array['foo']); +insert into inserttestb (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{baz,quux}'; +insert into inserttestb (f3.if1, f3.if2) values (1,default); -- not supported +insert into inserttestb (f3.if1, f3.if2) values (1,array[null]); +insert into inserttestb (f3.if1, f3.if2) values (1,'{null}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{null,quux}'; + +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'); +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux'); +insert into inserttestb (f3.if2[1], f3.if2[2]) select 'bear', 'beer'; + +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'), (row(2,'{y}'), 'baz', 'quux'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) select row(1,'{x}')::insert_test_domain, 'bear', 'beer'; + +select * from inserttesta; +select * from inserttestb; + +-- also check reverse-listing +create table inserttest2 (f1 bigint, f2 text); +create rule irule1 as on insert to inserttest2 do also + insert into inserttestb (f3.if2[1], f3.if2[2]) + values (new.f1,new.f2); +create rule irule2 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + values (1,'fool'),(new.f1,new.f2); +create rule irule3 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + select new.f1, new.f2; +\d+ inserttest2 + +drop table inserttest2; +drop table inserttesta; +drop table inserttestb; +drop domain insert_pos_ints; +drop domain insert_test_domain; + +-- Verify that multiple inserts to subfields of a domain-over-container +-- check the domain constraints only on the finished value + +create domain insert_nnarray as int[] + check (value[1] is not null and value[2] is not null); + +create domain insert_test_domain as insert_test_type + check ((value).if1 is not null and (value).if2 is not null); + +create table inserttesta (f1 insert_nnarray); +insert into inserttesta (f1[1]) values (1); -- fail +insert into inserttesta (f1[1], f1[2]) values (1, 2); + +create table inserttestb (f1 insert_test_domain); +insert into inserttestb (f1.if1) values (1); -- fail +insert into inserttestb (f1.if1, f1.if2) values (1, '{foo}'); + +drop table inserttesta; +drop table inserttestb; +drop domain insert_nnarray; +drop type insert_test_type cascade; -- direct partition inserts should check partition bound constraint create table range_parted ( @@ -294,33 +387,6 @@ select tableoid::regclass::text, a, min(b) as min_b, max(b) as max_b from list_p -- direct partition inserts should check hash partition bound constraint --- Use hand-rolled hash functions and operator classes to get predictable --- result on different machines. The hash function for int4 simply returns --- the sum of the values passed to it and the one for text returns the length --- of the non-empty string value passed to it or 0. - -create or replace function part_hashint4_noop(value int4, seed int8) -returns int8 as $$ -select value + seed; -$$ language sql immutable; - -create operator class part_test_int4_ops -for type int4 -using hash as -operator 1 =, -function 2 part_hashint4_noop(int4, int8); - -create or replace function part_hashtext_length(value text, seed int8) -RETURNS int8 AS $$ -select length(coalesce(value, ''))::int8 -$$ language sql immutable; - -create operator class part_test_text_ops -for type text -using hash as -operator 1 =, -function 2 part_hashtext_length(text, int8); - create table hash_parted ( a int ) partition by hash (a part_test_int4_ops); @@ -608,9 +674,7 @@ drop table inserttest3; drop table brtrigpartcon; drop function brtrigpartcon1trigf(); --- check that "do nothing" BR triggers work with tuple-routing (this checks --- that estate->es_result_relation_info is appropriately set/reset for each --- routed tuple) +-- check that "do nothing" BR triggers work with tuple-routing create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test2 (c text, b text, a int); diff --git a/expected/17.0/extra/int4.out b/expected/17.0/extra/int4.out new file mode 100644 index 00000000..f623f8c3 --- /dev/null +++ b/expected/17.0/extra/int4.out @@ -0,0 +1,977 @@ +-- +-- INT4 Based on PostgreSQL tests, please don't add additional tests here, use other test files +-- +--Testcase 61: +CREATE EXTENSION sqlite_fdw; +--Testcase 62: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 63: +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 64: +CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; + +--Testcase 1: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 2: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 3: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 4: +INSERT INTO INT4_TBL(f1) VALUES ('34.5'); +ERROR: invalid input syntax for type integer: "34.5" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('34.5'); + ^ +-- largest and smallest values +--Testcase 5: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 6: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); +-- bad input values -- should give errors +--Testcase 7: +INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); +ERROR: value "1000000000000" is out of range for type integer +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); + ^ +--Testcase 8: +INSERT INTO INT4_TBL(f1) VALUES ('asdf'); +ERROR: invalid input syntax for type integer: "asdf" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('asdf'); + ^ +--Testcase 9: +INSERT INTO INT4_TBL(f1) VALUES (' '); +ERROR: invalid input syntax for type integer: " " +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' '); + ^ +--Testcase 10: +INSERT INTO INT4_TBL(f1) VALUES (' asdf '); +ERROR: invalid input syntax for type integer: " asdf " +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (' asdf '); + ^ +--Testcase 11: +INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); +ERROR: invalid input syntax for type integer: "- 1234" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); + ^ +--Testcase 12: +INSERT INTO INT4_TBL(f1) VALUES ('123 5'); +ERROR: invalid input syntax for type integer: "123 5" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES ('123 5'); + ^ +--Testcase 13: +INSERT INTO INT4_TBL(f1) VALUES (''); +ERROR: invalid input syntax for type integer: "" +LINE 1: INSERT INTO INT4_TBL(f1) VALUES (''); + ^ +--Testcase 14: +SELECT * FROM INT4_TBL; + f1 +------------- + 0 + 123456 + -123456 + 2147483647 + -2147483647 +(5 rows) + +-- Also try it with non-error-throwing API +--Testcase 137: +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 138: +INSERT INTO NON_ERROR_THROWING_API_INT4 VALUES ('34', 1), ('asdf', 2), ('1000000000000', 3); +--Testcase 139: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 1; + pg_input_is_valid +------------------- + t +(1 row) + +--Testcase 140: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 2; + pg_input_is_valid +------------------- + f +(1 row) + +--Testcase 141: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3; + pg_input_is_valid +------------------- + f +(1 row) + +--Testcase 142: +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3), 'int4'); + message | detail | hint | sql_error_code +--------------------------------------------------------+--------+------+---------------- + value "1000000000000" is out of range for type integer | | | 22003 +(1 row) + +--Testcase 15: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <> int2 '0'; + f1 +------------- + 123456 + -123456 + 2147483647 + -2147483647 +(4 rows) + +--Testcase 16: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <> int4 '0'; + f1 +------------- + 123456 + -123456 + 2147483647 + -2147483647 +(4 rows) + +--Testcase 17: +SELECT i.* FROM INT4_TBL i WHERE i.f1 = int2 '0'; + f1 +---- + 0 +(1 row) + +--Testcase 18: +SELECT i.* FROM INT4_TBL i WHERE i.f1 = int4 '0'; + f1 +---- + 0 +(1 row) + +--Testcase 19: +SELECT i.* FROM INT4_TBL i WHERE i.f1 < int2 '0'; + f1 +------------- + -123456 + -2147483647 +(2 rows) + +--Testcase 20: +SELECT i.* FROM INT4_TBL i WHERE i.f1 < int4 '0'; + f1 +------------- + -123456 + -2147483647 +(2 rows) + +--Testcase 21: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <= int2 '0'; + f1 +------------- + 0 + -123456 + -2147483647 +(3 rows) + +--Testcase 22: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <= int4 '0'; + f1 +------------- + 0 + -123456 + -2147483647 +(3 rows) + +--Testcase 23: +SELECT i.* FROM INT4_TBL i WHERE i.f1 > int2 '0'; + f1 +------------ + 123456 + 2147483647 +(2 rows) + +--Testcase 24: +SELECT i.* FROM INT4_TBL i WHERE i.f1 > int4 '0'; + f1 +------------ + 123456 + 2147483647 +(2 rows) + +--Testcase 25: +SELECT i.* FROM INT4_TBL i WHERE i.f1 >= int2 '0'; + f1 +------------ + 0 + 123456 + 2147483647 +(3 rows) + +--Testcase 26: +SELECT i.* FROM INT4_TBL i WHERE i.f1 >= int4 '0'; + f1 +------------ + 0 + 123456 + 2147483647 +(3 rows) + +-- positive odds +--Testcase 27: +SELECT i.* FROM INT4_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; + f1 +------------ + 2147483647 +(1 row) + +-- any evens +--Testcase 28: +SELECT i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; + f1 +--------- + 0 + 123456 + -123456 +(3 rows) + +--Testcase 29: +SELECT i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 30: +SELECT i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i +WHERE abs(f1) < 1073741824; + f1 | x +---------+--------- + 0 | 0 + 123456 | 246912 + -123456 | -246912 +(3 rows) + +--Testcase 31: +SELECT i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 32: +SELECT i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i +WHERE abs(f1) < 1073741824; + f1 | x +---------+--------- + 0 | 0 + 123456 | 246912 + -123456 | -246912 +(3 rows) + +--Testcase 33: +SELECT i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 34: +SELECT i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i +WHERE f1 < 2147483646; + f1 | x +-------------+------------- + 0 | 2 + 123456 | 123458 + -123456 | -123454 + -2147483647 | -2147483645 +(4 rows) + +--Testcase 35: +SELECT i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 36: +SELECT i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i +WHERE f1 < 2147483646; + f1 | x +-------------+------------- + 0 | 2 + 123456 | 123458 + -123456 | -123454 + -2147483647 | -2147483645 +(4 rows) + +--Testcase 37: +SELECT i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 38: +SELECT i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i +WHERE f1 > -2147483647; + f1 | x +------------+------------ + 0 | -2 + 123456 | 123454 + -123456 | -123458 + 2147483647 | 2147483645 +(4 rows) + +--Testcase 39: +SELECT i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i; +ERROR: integer out of range +--Testcase 40: +SELECT i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i +WHERE f1 > -2147483647; + f1 | x +------------+------------ + 0 | -2 + 123456 | 123454 + -123456 | -123458 + 2147483647 | 2147483645 +(4 rows) + +--Testcase 41: +SELECT i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i; + f1 | x +-------------+------------- + 0 | 0 + 123456 | 61728 + -123456 | -61728 + 2147483647 | 1073741823 + -2147483647 | -1073741823 +(5 rows) + +--Testcase 42: +SELECT i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i; + f1 | x +-------------+------------- + 0 | 0 + 123456 | 61728 + -123456 | -61728 + 2147483647 | 1073741823 + -2147483647 | -1073741823 +(5 rows) + +-- +-- more complex expressions +-- +-- variations on unary minus parsing +--Testcase 65: +DELETE FROM INT4_TMP; +--Testcase 66: +INSERT INTO INT4_TMP VALUES (-2, 3); +--Testcase 67: +SELECT f1 + f2 as one FROM INT4_TMP; + one +----- + 1 +(1 row) + +--Testcase 68: +DELETE FROM INT4_TMP; +--Testcase 69: +INSERT INTO INT4_TMP VALUES (4, 2); +--Testcase 70: +SELECT f1 - f2 as two FROM INT4_TMP; + two +----- + 2 +(1 row) + +--Testcase 46: +DELETE FROM INT4_TMP; +--Testcase 71: +INSERT INTO INT4_TMP VALUES (2, 1); +--Testcase 72: +SELECT f1- -f2 as three FROM INT4_TMP; + three +------- + 3 +(1 row) + +--Testcase 47: +DELETE FROM INT4_TMP; +--Testcase 73: +INSERT INTO INT4_TMP VALUES (2, 2); +--Testcase 74: +SELECT f1 - -f2 as four FROM INT4_TMP; + four +------ + 4 +(1 row) + +--Testcase 75: +DELETE FROM INT4_TMP; +--Testcase 76: +INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int2, '16'::int2 / '4'::int2); +--Testcase 77: +SELECT f1 = f2 AS true FROM INT4_TMP; + true +------ + t +(1 row) + +--Testcase 78: +DELETE FROM INT4_TMP; +--Testcase 79: +INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int4, '16'::int2 / '4'::int4); +--Testcase 80: +SELECT f1 = f2 AS true FROM INT4_TMP; + true +------ + t +(1 row) + +--Testcase 81: +DELETE FROM INT4_TMP; +--Testcase 82: +INSERT INTO INT4_TMP VALUES ('2'::int4 * '2'::int2, '16'::int4 / '4'::int2); +--Testcase 83: +SELECT f1 = f2 AS true FROM INT4_TMP; + true +------ + t +(1 row) + +--Testcase 84: +DELETE FROM INT4_TMP; +--Testcase 85: +INSERT INTO INT4_TMP VALUES ('1000'::int4, '999'::int4); +--Testcase 86: +SELECT f1 < f2 AS false FROM INT4_TMP; + false +------- + f +(1 row) + +--Testcase 50: +DELETE FROM INT4_TMP; +--Testcase 91: +INSERT INTO INT4_TMP VALUES (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1); +--Testcase 92: +SELECT f1 as ten FROM INT4_TMP; + ten +----- + 10 +(1 row) + +--Testcase 51: +DELETE FROM INT4_TMP; +--Testcase 93: +INSERT INTO INT4_TMP VALUES (2 , 2); +--Testcase 94: +SELECT f1 + f1/f2 as three FROM INT4_TMP; + three +------- + 3 +(1 row) + +--Testcase 52: +DELETE FROM INT4_TMP; +--Testcase 95: +INSERT INTO INT4_TMP VALUES (2 , 2); +--Testcase 96: +SELECT (f1 + f2)/f2 as two FROM INT4_TMP; + two +----- + 2 +(1 row) + +-- corner case +--Testcase 54: +DELETE FROM INT4_TMP; +--Testcase 97: +INSERT INTO INT4_TMP VALUES (-1); +--Testcase 98: +SELECT (f1<<31)::text FROM INT4_TMP; + text +------------- + -2147483648 +(1 row) + +--Testcase 56: +DELETE FROM INT4_TMP; +--Testcase 99: +INSERT INTO INT4_TMP VALUES (-1); +--Testcase 100: +SELECT ((f1<<31)+1)::text FROM INT4_TMP; + text +------------- + -2147483647 +(1 row) + +-- check sane handling of INT_MIN overflow cases +--Testcase 58: +DELETE FROM INT4_TMP; +--Testcase 101: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int4); +--Testcase 102: +SELECT f1 * f2 FROM INT4_TMP; +ERROR: integer out of range +--Testcase 103: +SELECT f1 / f2 FROM INT4_TMP; +ERROR: integer out of range +--Testcase 104: +SELECT f1 % f2 FROM INT4_TMP; + ?column? +---------- + 0 +(1 row) + +--Testcase 60: +DELETE FROM INT4_TMP; +--Testcase 105: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int2); +--Testcase 106: +SELECT f1 * f2 FROM INT4_TMP; +ERROR: integer out of range +--Testcase 107: +SELECT f1 / f2 FROM INT4_TMP; +ERROR: integer out of range +--Testcase 108: +SELECT f1 % f2 FROM INT4_TMP; + ?column? +---------- + 0 +(1 row) + +-- check rounding when casting from float +--Testcase 109: +CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 110: +DELETE FROM FLOAT8_TMP; +--Testcase 111: +INSERT INTO FLOAT8_TMP VALUES + (-2.5::float8), + (-1.5::float8), + (-0.5::float8), + (0.0::float8), + (0.5::float8), + (1.5::float8), + (2.5::float8); +--Testcase 112: +SELECT f1 as x, f1::int4 as int4_value FROM FLOAT8_TMP; + x | int4_value +------+------------ + -2.5 | -2 + -1.5 | -2 + -0.5 | 0 + 0 | 0 + 0.5 | 0 + 1.5 | 2 + 2.5 | 2 +(7 rows) + +-- check rounding when casting from numeric +--Testcase 113: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 114: +DELETE FROM NUMERIC_TMP; +--Testcase 115: +INSERT INTO NUMERIC_TMP VALUES + (-2.5::numeric), + (-1.5::numeric), + (-0.5::numeric), + (0.0::numeric), + (0.5::numeric), + (1.5::numeric), + (2.5::numeric); +--Testcase 116: +SELECT f1 as x, f1::int4 as int4_value FROM NUMERIC_TMP; + x | int4_value +------+------------ + -2.5 | -3 + -1.5 | -2 + -0.5 | -1 + 0 | 0 + 0.5 | 1 + 1.5 | 2 + 2.5 | 3 +(7 rows) + +-- test gcd() +--Testcase 117: +DELETE FROM INT4_TMP; +--Testcase 118: +INSERT INTO INT4_TMP VALUES + (0::int4, 0::int4), + (0::int4, 6410818::int4), + (61866666::int4, 6410818::int4), + (-61866666::int4, 6410818::int4), + ((-2147483648)::int4, 1::int4), + ((-2147483648)::int4, 2147483647::int4), + ((-2147483648)::int4, 1073741824::int4); +--Testcase 119: +SELECT f1, f2, gcd(f1, f2), gcd(f1, -f2), gcd(f2, f1), gcd(-f2, f1) FROM INT4_TMP; + f1 | f2 | gcd | gcd | gcd | gcd +-------------+------------+------------+------------+------------+------------ + 0 | 0 | 0 | 0 | 0 | 0 + 0 | 6410818 | 6410818 | 6410818 | 6410818 | 6410818 + 61866666 | 6410818 | 1466 | 1466 | 1466 | 1466 + -61866666 | 6410818 | 1466 | 1466 | 1466 | 1466 + -2147483648 | 1 | 1 | 1 | 1 | 1 + -2147483648 | 2147483647 | 1 | 1 | 1 | 1 + -2147483648 | 1073741824 | 1073741824 | 1073741824 | 1073741824 | 1073741824 +(7 rows) + +--Testcase 120: +DELETE FROM INT4_TMP; +--Testcase 121: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 0::int4); +--Testcase 122: +SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow +ERROR: integer out of range +--Testcase 123: +DELETE FROM INT4_TMP; +--Testcase 124: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-2147483648)::int4); +--Testcase 125: +SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow +ERROR: integer out of range +-- test lcm() +--Testcase 126: +DELETE FROM INT4_TMP; +--Testcase 127: +INSERT INTO INT4_TMP VALUES + (0::int4, 0::int4), + (0::int4, 42::int4), + (42::int4, 42::int4), + (330::int4, 462::int4), + (-330::int4, 462::int4), + ((-2147483648)::int4, 0::int4); +--Testcase 128: +SELECT f1, f2, lcm(f1, f2), lcm(f1, -f2), lcm(f2, f1), lcm(-f2, f1) FROM INT4_TMP; + f1 | f2 | lcm | lcm | lcm | lcm +-------------+-----+------+------+------+------ + 0 | 0 | 0 | 0 | 0 | 0 + 0 | 42 | 0 | 0 | 0 | 0 + 42 | 42 | 42 | 42 | 42 | 42 + 330 | 462 | 2310 | 2310 | 2310 | 2310 + -330 | 462 | 2310 | 2310 | 2310 | 2310 + -2147483648 | 0 | 0 | 0 | 0 | 0 +(6 rows) + +--Testcase 129: +DELETE FROM INT4_TMP; +--Testcase 130: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 1::int4); +--Testcase 131: +SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow +ERROR: integer out of range +--Testcase 132: +DELETE FROM INT4_TMP; +--Testcase 133: +INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); +--Testcase 134: +SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow +ERROR: integer out of range +-- non-decimal literals +--Testcase 143: +CREATE FOREIGN TABLE special_case_int4 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 144: +INSERT INTO special_case_int4 VALUES ('0b100101'::int4); +--Testcase 145: +SELECT f1 FROM special_case_int4; + f1 +---- + 37 +(1 row) + +--Testcase 146: +DELETE FROM special_case_int4; +--Testcase 147: +INSERT INTO special_case_int4 VALUES ('0o273'::int4); +--Testcase 148: +SELECT f1 FROM special_case_int4; + f1 +----- + 187 +(1 row) + +--Testcase 149: +DELETE FROM special_case_int4; +--Testcase 150: +INSERT INTO special_case_int4 VALUES ('0x42F'::int4); +--Testcase 151: +SELECT f1 FROM special_case_int4; + f1 +------ + 1071 +(1 row) + +--Testcase 152: +DELETE FROM special_case_int4; +--Testcase 153: +INSERT INTO special_case_int4 VALUES ('0b'::int4); +ERROR: invalid input syntax for type integer: "0b" +LINE 1: INSERT INTO special_case_int4 VALUES ('0b'::int4); + ^ +--Testcase 154: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 155: +DELETE FROM special_case_int4; +--Testcase 156: +INSERT INTO special_case_int4 VALUES ('0x'::int4); +ERROR: invalid input syntax for type integer: "0x" +LINE 1: INSERT INTO special_case_int4 VALUES ('0x'::int4); + ^ +--Testcase 157: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 158: +DELETE FROM special_case_int4; +--Testcase 159: +INSERT INTO special_case_int4 VALUES ('0x'::int4); +ERROR: invalid input syntax for type integer: "0x" +LINE 1: INSERT INTO special_case_int4 VALUES ('0x'::int4); + ^ +--Testcase 160: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +-- cases near overflow +--Testcase 161: +DELETE FROM special_case_int4; +--Testcase 162: +INSERT INTO special_case_int4 VALUES ('0b1111111111111111111111111111111'::int4); +--Testcase 163: +SELECT f1 FROM special_case_int4; + f1 +------------ + 2147483647 +(1 row) + +--Testcase 164: +DELETE FROM special_case_int4; +--Testcase 165: +INSERT INTO special_case_int4 VALUES ('0b10000000000000000000000000000000'::int4); +ERROR: value "0b10000000000000000000000000000000" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('0b1000000000000000000... + ^ +--Testcase 166: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 167: +DELETE FROM special_case_int4; +--Testcase 168: +INSERT INTO special_case_int4 VALUES ('0o17777777777'::int4); +--Testcase 169: +SELECT f1 FROM special_case_int4; + f1 +------------ + 2147483647 +(1 row) + +--Testcase 170: +DELETE FROM special_case_int4; +--Testcase 171: +INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4); +ERROR: value "0o20000000000" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4)... + ^ +--Testcase 172: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 173: +DELETE FROM special_case_int4; +--Testcase 174: +INSERT INTO special_case_int4 VALUES ('0x7FFFFFFF'::int4); +--Testcase 175: +SELECT f1 FROM special_case_int4; + f1 +------------ + 2147483647 +(1 row) + +--Testcase 176: +DELETE FROM special_case_int4; +--Testcase 177: +INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); +ERROR: value "0x80000000" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); + ^ +--Testcase 178: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 179: +DELETE FROM special_case_int4; +--Testcase 180: +INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000000'::int4); +--Testcase 181: +SELECT f1 FROM special_case_int4; + f1 +------------- + -2147483648 +(1 row) + +--Testcase 182: +DELETE FROM special_case_int4; +--Testcase 183: +INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000001'::int4); +ERROR: value "-0b10000000000000000000000000000001" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('-0b100000000000000000... + ^ +--Testcase 184: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 185: +DELETE FROM special_case_int4; +--Testcase 186: +INSERT INTO special_case_int4 VALUES ('-0o20000000000'::int4); +--Testcase 187: +SELECT f1 FROM special_case_int4; + f1 +------------- + -2147483648 +(1 row) + +--Testcase 188: +DELETE FROM special_case_int4; +--Testcase 189: +INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4); +ERROR: value "-0o20000000001" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4... + ^ +--Testcase 190: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 191: +DELETE FROM special_case_int4; +--Testcase 192: +INSERT INTO special_case_int4 VALUES ('-0x80000000'::int4); +--Testcase 193: +SELECT f1 FROM special_case_int4; + f1 +------------- + -2147483648 +(1 row) + +--Testcase 194: +DELETE FROM special_case_int4; +--Testcase 195: +INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); +ERROR: value "-0x80000001" is out of range for type integer +LINE 1: INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); + ^ +--Testcase 196: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +-- underscores +--Testcase 197: +DELETE FROM special_case_int4; +--Testcase 198: +INSERT INTO special_case_int4 VALUES ('1_000_000'::int4); +--Testcase 199: +SELECT f1 FROM special_case_int4; + f1 +--------- + 1000000 +(1 row) + +--Testcase 200: +DELETE FROM special_case_int4; +--Testcase 201: +INSERT INTO special_case_int4 VALUES ('1_2_3'::int4); +--Testcase 202: +SELECT f1 FROM special_case_int4; + f1 +----- + 123 +(1 row) + +--Testcase 203: +DELETE FROM special_case_int4; +--Testcase 204: +INSERT INTO special_case_int4 VALUES ('0x1EEE_FFFF'::int4); +--Testcase 205: +SELECT f1 FROM special_case_int4; + f1 +----------- + 518979583 +(1 row) + +--Testcase 206: +DELETE FROM special_case_int4; +--Testcase 207: +INSERT INTO special_case_int4 VALUES ('0o2_73'::int4); +--Testcase 208: +SELECT f1 FROM special_case_int4; + f1 +----- + 187 +(1 row) + +--Testcase 209: +DELETE FROM special_case_int4; +--Testcase 210: +INSERT INTO special_case_int4 VALUES ('0b_10_0101'::int4); +--Testcase 211: +SELECT f1 FROM special_case_int4; + f1 +---- + 37 +(1 row) + +-- error cases +--Testcase 212: +DELETE FROM special_case_int4; +--Testcase 213: +INSERT INTO special_case_int4 VALUES ('_100'::int4); +ERROR: invalid input syntax for type integer: "_100" +LINE 1: INSERT INTO special_case_int4 VALUES ('_100'::int4); + ^ +--Testcase 214: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 215: +DELETE FROM special_case_int4; +--Testcase 216: +INSERT INTO special_case_int4 VALUES ('100_'::int4); +ERROR: invalid input syntax for type integer: "100_" +LINE 1: INSERT INTO special_case_int4 VALUES ('100_'::int4); + ^ +--Testcase 217: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 218: +DELETE FROM special_case_int4; +--Testcase 219: +INSERT INTO special_case_int4 VALUES ('100__000'::int4); +ERROR: invalid input syntax for type integer: "100__000" +LINE 1: INSERT INTO special_case_int4 VALUES ('100__000'::int4); + ^ +--Testcase 220: +SELECT f1 FROM special_case_int4; + f1 +---- +(0 rows) + +--Testcase 221: +DELETE FROM INT4_TBL; +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +--Testcase 135: +DROP SERVER sqlite_svr; +--Testcase 136: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/extra/int8.out b/expected/17.0/extra/int8.out new file mode 100644 index 00000000..0bbeaa41 --- /dev/null +++ b/expected/17.0/extra/int8.out @@ -0,0 +1,1679 @@ +-- +-- INT8 +-- Test int8 64-bit integers. +-- +--Testcase 140: +CREATE EXTENSION sqlite_fdw; +--Testcase 141: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 142: +CREATE FOREIGN TABLE INT8_TBL( + q1 int8 OPTIONS (key 'true'), + q2 int8 OPTIONS (key 'true') +) SERVER sqlite_svr; +--Testcase 143: +CREATE FOREIGN TABLE INT8_TMP( + q1 int8, + q2 int8, + q3 int4, + q4 int2, + q5 text, + id int options (key 'true') +) SERVER sqlite_svr; +--Testcase 1: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 2: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 3: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 4: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 5: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); +-- bad inputs +--Testcase 6: +INSERT INTO INT8_TBL(q1) VALUES (' '); +ERROR: invalid input syntax for type bigint: " " +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' '); + ^ +--Testcase 7: +INSERT INTO INT8_TBL(q1) VALUES ('xxx'); +ERROR: invalid input syntax for type bigint: "xxx" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx'); + ^ +--Testcase 8: +INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); +ERROR: value "3908203590239580293850293850329485" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938... + ^ +--Testcase 9: +INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); +ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340... + ^ +--Testcase 10: +INSERT INTO INT8_TBL(q1) VALUES ('- 123'); +ERROR: invalid input syntax for type bigint: "- 123" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123'); + ^ +--Testcase 11: +INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); +ERROR: invalid input syntax for type bigint: " 345 5" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); + ^ +--Testcase 12: +INSERT INTO INT8_TBL(q1) VALUES (''); +ERROR: invalid input syntax for type bigint: "" +LINE 1: INSERT INTO INT8_TBL(q1) VALUES (''); + ^ +--Testcase 13: +SELECT * FROM INT8_TBL; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(5 rows) + +-- Also try it with non-error-throwing API +--Testcase 251: +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 252: +INSERT INTO NON_ERROR_THROWING_API_INT8 VALUES ('34', 1), ('asdf', 2), ('10000000000000000000', 3); +--Testcase 253: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 1; + pg_input_is_valid +------------------- + t +(1 row) + +--Testcase 254: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 2; + pg_input_is_valid +------------------- + f +(1 row) + +--Testcase 255: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3; + pg_input_is_valid +------------------- + f +(1 row) + +--Testcase 256: +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3), 'int8'); + message | detail | hint | sql_error_code +--------------------------------------------------------------+--------+------+---------------- + value "10000000000000000000" is out of range for type bigint | | | 22003 +(1 row) + +-- int8/int8 cmp +--Testcase 14: +SELECT * FROM INT8_TBL WHERE q2 = 4567890123456789; + q1 | q2 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(2 rows) + +--Testcase 15: +SELECT * FROM INT8_TBL WHERE q2 <> 4567890123456789; + q1 | q2 +------------------+------------------- + 123 | 456 + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 16: +SELECT * FROM INT8_TBL WHERE q2 < 4567890123456789; + q1 | q2 +------------------+------------------- + 123 | 456 + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 17: +SELECT * FROM INT8_TBL WHERE q2 > 4567890123456789; + q1 | q2 +----+---- +(0 rows) + +--Testcase 18: +SELECT * FROM INT8_TBL WHERE q2 <= 4567890123456789; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(5 rows) + +--Testcase 19: +SELECT * FROM INT8_TBL WHERE q2 >= 4567890123456789; + q1 | q2 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(2 rows) + +-- int8/int4 cmp +--Testcase 20: +SELECT * FROM INT8_TBL WHERE q2 = 456; + q1 | q2 +-----+----- + 123 | 456 +(1 row) + +--Testcase 21: +SELECT * FROM INT8_TBL WHERE q2 <> 456; + q1 | q2 +------------------+------------------- + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(4 rows) + +--Testcase 22: +SELECT * FROM INT8_TBL WHERE q2 < 456; + q1 | q2 +------------------+------------------- + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(2 rows) + +--Testcase 23: +SELECT * FROM INT8_TBL WHERE q2 > 456; + q1 | q2 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(2 rows) + +--Testcase 24: +SELECT * FROM INT8_TBL WHERE q2 <= 456; + q1 | q2 +------------------+------------------- + 123 | 456 + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 25: +SELECT * FROM INT8_TBL WHERE q2 >= 456; + q1 | q2 +------------------+------------------ + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(3 rows) + +-- int4/int8 cmp +--Testcase 26: +SELECT * FROM INT8_TBL WHERE 123 = q1; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +--Testcase 27: +SELECT * FROM INT8_TBL WHERE 123 <> q1; + q1 | q2 +------------------+------------------- + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 28: +SELECT * FROM INT8_TBL WHERE 123 < q1; + q1 | q2 +------------------+------------------- + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(3 rows) + +--Testcase 29: +SELECT * FROM INT8_TBL WHERE 123 > q1; + q1 | q2 +----+---- +(0 rows) + +--Testcase 30: +SELECT * FROM INT8_TBL WHERE 123 <= q1; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(5 rows) + +--Testcase 31: +SELECT * FROM INT8_TBL WHERE 123 >= q1; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +-- int8/int2 cmp +--Testcase 32: +SELECT * FROM INT8_TBL WHERE q2 = '456'::int2; + q1 | q2 +-----+----- + 123 | 456 +(1 row) + +--Testcase 33: +SELECT * FROM INT8_TBL WHERE q2 <> '456'::int2; + q1 | q2 +------------------+------------------- + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(4 rows) + +--Testcase 34: +SELECT * FROM INT8_TBL WHERE q2 < '456'::int2; + q1 | q2 +------------------+------------------- + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(2 rows) + +--Testcase 35: +SELECT * FROM INT8_TBL WHERE q2 > '456'::int2; + q1 | q2 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(2 rows) + +--Testcase 36: +SELECT * FROM INT8_TBL WHERE q2 <= '456'::int2; + q1 | q2 +------------------+------------------- + 123 | 456 + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 37: +SELECT * FROM INT8_TBL WHERE q2 >= '456'::int2; + q1 | q2 +------------------+------------------ + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(3 rows) + +-- int2/int8 cmp +--Testcase 38: +SELECT * FROM INT8_TBL WHERE '123'::int2 = q1; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +--Testcase 39: +SELECT * FROM INT8_TBL WHERE '123'::int2 <> q1; + q1 | q2 +------------------+------------------- + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(3 rows) + +--Testcase 40: +SELECT * FROM INT8_TBL WHERE '123'::int2 < q1; + q1 | q2 +------------------+------------------- + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(3 rows) + +--Testcase 41: +SELECT * FROM INT8_TBL WHERE '123'::int2 > q1; + q1 | q2 +----+---- +(0 rows) + +--Testcase 42: +SELECT * FROM INT8_TBL WHERE '123'::int2 <= q1; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(5 rows) + +--Testcase 43: +SELECT * FROM INT8_TBL WHERE '123'::int2 >= q1; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +--Testcase 44: +SELECT q1 AS plus, -q1 AS minus FROM INT8_TBL; + plus | minus +------------------+------------------- + 123 | -123 + 123 | -123 + 4567890123456789 | -4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | -4567890123456789 +(5 rows) + +--Testcase 45: +SELECT q1, q2, q1 + q2 AS plus FROM INT8_TBL; + q1 | q2 | plus +------------------+-------------------+------------------ + 123 | 456 | 579 + 123 | 4567890123456789 | 4567890123456912 + 4567890123456789 | 123 | 4567890123456912 + 4567890123456789 | 4567890123456789 | 9135780246913578 + 4567890123456789 | -4567890123456789 | 0 +(5 rows) + +--Testcase 46: +SELECT q1, q2, q1 - q2 AS minus FROM INT8_TBL; + q1 | q2 | minus +------------------+-------------------+------------------- + 123 | 456 | -333 + 123 | 4567890123456789 | -4567890123456666 + 4567890123456789 | 123 | 4567890123456666 + 4567890123456789 | 4567890123456789 | 0 + 4567890123456789 | -4567890123456789 | 9135780246913578 +(5 rows) + +--Testcase 47: +SELECT q1, q2, q1 * q2 AS multiply FROM INT8_TBL; +ERROR: bigint out of range +--Testcase 48: +SELECT q1, q2, q1 * q2 AS multiply FROM INT8_TBL + WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); + q1 | q2 | multiply +------------------+------------------+-------------------- + 123 | 456 | 56088 + 123 | 4567890123456789 | 561850485185185047 + 4567890123456789 | 123 | 561850485185185047 +(3 rows) + +--Testcase 49: +SELECT q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL; + q1 | q2 | divide | mod +------------------+-------------------+----------------+----- + 123 | 456 | 0 | 123 + 123 | 4567890123456789 | 0 | 123 + 4567890123456789 | 123 | 37137318076884 | 57 + 4567890123456789 | 4567890123456789 | 1 | 0 + 4567890123456789 | -4567890123456789 | -1 | 0 +(5 rows) + +--Testcase 50: +SELECT q1, float8(q1) FROM INT8_TBL; + q1 | float8 +------------------+----------------------- + 123 | 123 + 123 | 123 + 4567890123456789 | 4.567890123456789e+15 + 4567890123456789 | 4.567890123456789e+15 + 4567890123456789 | 4.567890123456789e+15 +(5 rows) + +--Testcase 51: +SELECT q2, float8(q2) FROM INT8_TBL; + q2 | float8 +-------------------+------------------------ + 456 | 456 + 4567890123456789 | 4.567890123456789e+15 + 123 | 123 + 4567890123456789 | 4.567890123456789e+15 + -4567890123456789 | -4.567890123456789e+15 +(5 rows) + +--Testcase 52: +SELECT 37 + q1 AS plus4 FROM INT8_TBL; + plus4 +------------------ + 160 + 160 + 4567890123456826 + 4567890123456826 + 4567890123456826 +(5 rows) + +--Testcase 53: +SELECT 37 - q1 AS minus4 FROM INT8_TBL; + minus4 +------------------- + -86 + -86 + -4567890123456752 + -4567890123456752 + -4567890123456752 +(5 rows) + +--Testcase 54: +SELECT 2 * q1 AS "twice int4" FROM INT8_TBL; + twice int4 +------------------ + 246 + 246 + 9135780246913578 + 9135780246913578 + 9135780246913578 +(5 rows) + +--Testcase 55: +SELECT q1 * 2 AS "twice int4" FROM INT8_TBL; + twice int4 +------------------ + 246 + 246 + 9135780246913578 + 9135780246913578 + 9135780246913578 +(5 rows) + +-- int8 op int4 +--Testcase 56: +SELECT q1 + 42::int4 AS "8plus4", q1 - 42::int4 AS "8minus4", q1 * 42::int4 AS "8mul4", q1 / 42::int4 AS "8div4" FROM INT8_TBL; + 8plus4 | 8minus4 | 8mul4 | 8div4 +------------------+------------------+--------------------+----------------- + 165 | 81 | 5166 | 2 + 165 | 81 | 5166 | 2 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 +(5 rows) + +-- int4 op int8 +--Testcase 57: +SELECT 246::int4 + q1 AS "4plus8", 246::int4 - q1 AS "4minus8", 246::int4 * q1 AS "4mul8", 246::int4 / q1 AS "4div8" FROM INT8_TBL; + 4plus8 | 4minus8 | 4mul8 | 4div8 +------------------+-------------------+---------------------+------- + 369 | 123 | 30258 | 2 + 369 | 123 | 30258 | 2 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 +(5 rows) + +-- int8 op int2 +--Testcase 58: +SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "8mul2", q1 / 42::int2 AS "8div2" FROM INT8_TBL; + 8plus2 | 8minus2 | 8mul2 | 8div2 +------------------+------------------+--------------------+----------------- + 165 | 81 | 5166 | 2 + 165 | 81 | 5166 | 2 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 + 4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733 +(5 rows) + +-- int2 op int8 +--Testcase 59: +SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL; + 2plus8 | 2minus8 | 2mul8 | 2div8 +------------------+-------------------+---------------------+------- + 369 | 123 | 30258 | 2 + 369 | 123 | 30258 | 2 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 + 4567890123457035 | -4567890123456543 | 1123700970370370094 | 0 +(5 rows) + +--Testcase 60: +SELECT q2, abs(q2) FROM INT8_TBL; + q2 | abs +-------------------+------------------ + 456 | 456 + 4567890123456789 | 4567890123456789 + 123 | 123 + 4567890123456789 | 4567890123456789 + -4567890123456789 | 4567890123456789 +(5 rows) + +--Testcase 61: +SELECT min(q1), min(q2) FROM INT8_TBL; + min | min +-----+------------------- + 123 | -4567890123456789 +(1 row) + +--Testcase 62: +SELECT max(q1), max(q2) FROM INT8_TBL; + max | max +------------------+------------------ + 4567890123456789 | 4567890123456789 +(1 row) + +-- TO_CHAR() +-- +--Testcase 63: +SELECT to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999') + FROM INT8_TBL; + to_char | to_char +------------------------+------------------------ + 123 | 456 + 123 | 4,567,890,123,456,789 + 4,567,890,123,456,789 | 123 + 4,567,890,123,456,789 | 4,567,890,123,456,789 + 4,567,890,123,456,789 | -4,567,890,123,456,789 +(5 rows) + +--Testcase 64: +SELECT to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999') + FROM INT8_TBL; + to_char | to_char +--------------------------------+-------------------------------- + 123.000,000 | 456.000,000 + 123.000,000 | 4,567,890,123,456,789.000,000 + 4,567,890,123,456,789.000,000 | 123.000,000 + 4,567,890,123,456,789.000,000 | 4,567,890,123,456,789.000,000 + 4,567,890,123,456,789.000,000 | -4,567,890,123,456,789.000,000 +(5 rows) + +--Testcase 65: +SELECT to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR') + FROM INT8_TBL; + to_char | to_char +--------------------+------------------------ + <123> | <456.000> + <123> | <4567890123456789.000> + <4567890123456789> | <123.000> + <4567890123456789> | <4567890123456789.000> + <4567890123456789> | 4567890123456789.000 +(5 rows) + +--Testcase 66: +SELECT to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999') + FROM INT8_TBL; + to_char | to_char +-------------------+------------------- + 123- | -456 + 123- | -4567890123456789 + 4567890123456789- | -123 + 4567890123456789- | -4567890123456789 + 4567890123456789- | +4567890123456789 +(5 rows) + +--Testcase 67: +SELECT to_char(q2, 'MI9999999999999999') FROM INT8_TBL; + to_char +------------------- + 456 + 4567890123456789 + 123 + 4567890123456789 + -4567890123456789 +(5 rows) + +--Testcase 68: +SELECT to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; + to_char +------------------- + +456 + +4567890123456789 + +123 + +4567890123456789 + -4567890123456789 +(5 rows) + +--Testcase 69: +SELECT to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL; + to_char +-------------------- + 456TH + 4567890123456789TH + 123RD + 4567890123456789TH + <4567890123456789> +(5 rows) + +--Testcase 70: +SELECT to_char(q2, 'SG9999999999999999th') FROM INT8_TBL; + to_char +--------------------- + + 456th + +4567890123456789th + + 123rd + +4567890123456789th + -4567890123456789 +(5 rows) + +--Testcase 71: +SELECT to_char(q2, '0999999999999999') FROM INT8_TBL; + to_char +------------------- + 0000000000000456 + 4567890123456789 + 0000000000000123 + 4567890123456789 + -4567890123456789 +(5 rows) + +--Testcase 72: +SELECT to_char(q2, 'S0999999999999999') FROM INT8_TBL; + to_char +------------------- + +0000000000000456 + +4567890123456789 + +0000000000000123 + +4567890123456789 + -4567890123456789 +(5 rows) + +--Testcase 73: +SELECT to_char(q2, 'FM0999999999999999') FROM INT8_TBL; + to_char +------------------- + 0000000000000456 + 4567890123456789 + 0000000000000123 + 4567890123456789 + -4567890123456789 +(5 rows) + +--Testcase 74: +SELECT to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL; + to_char +----------------------- + 456.000 + 4567890123456789.000 + 123.000 + 4567890123456789.000 + -4567890123456789.000 +(5 rows) + +--Testcase 75: +SELECT to_char(q2, 'L9999999999999999.000') FROM INT8_TBL; + to_char +------------------------ + 456.000 + 4567890123456789.000 + 123.000 + 4567890123456789.000 + -4567890123456789.000 +(5 rows) + +--Testcase 76: +SELECT to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL; + to_char +-------------------- + 456. + 4567890123456789. + 123. + 4567890123456789. + -4567890123456789. +(5 rows) + +--Testcase 77: +SELECT to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL; + to_char +------------------------------------------- + +4 5 6 . 0 0 0 + +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 + +1 2 3 . 0 0 0 + +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 + -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0 +(5 rows) + +--Testcase 78: +SELECT to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; + to_char +----------------------------------------------------------- + text 9999 "text between quote marks" 456 + 45678 text 9012 9999 345 "text between quote marks" 6789 + text 9999 "text between quote marks" 123 + 45678 text 9012 9999 345 "text between quote marks" 6789 + -45678 text 9012 9999 345 "text between quote marks" 6789 +(5 rows) + +--Testcase 79: +SELECT to_char(q2, '999999SG9999999999') FROM INT8_TBL; + to_char +------------------- + + 456 + 456789+0123456789 + + 123 + 456789+0123456789 + 456789-0123456789 +(5 rows) + +-- check min/max values and overflow behavior +--Testcase 80: +DELETE FROM INT8_TMP; +--Testcase 144: +INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); +--Testcase 145: +SELECT q1 FROM INT8_TMP; + q1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 81: +DELETE FROM INT8_TMP; +--Testcase 146: +INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); +ERROR: value "-9223372036854775809" is out of range for type bigint +LINE 1: INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); + ^ +--Testcase 147: +SELECT q1 FROM INT8_TMP; + q1 +---- +(0 rows) + +--Testcase 82: +DELETE FROM INT8_TMP; +--Testcase 148: +INSERT INTO INT8_TMP VALUES ('9223372036854775807'::int8); +--Testcase 149: +SELECT q1 FROM INT8_TMP; + q1 +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 83: +DELETE FROM INT8_TMP; +--Testcase 150: +INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); +ERROR: value "9223372036854775808" is out of range for type bigint +LINE 1: INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); + ^ +--Testcase 151: +SELECT q1 FROM INT8_TMP; + q1 +---- +(0 rows) + +--Testcase 84: +DELETE FROM INT8_TMP; +--Testcase 152: +INSERT INTO INT8_TMP VALUES (-('-9223372036854775807'::int8)); +--Testcase 153: +SELECT q1 FROM INT8_TMP; + q1 +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 86: +DELETE FROM INT8_TMP; +--Testcase 154: +INSERT INTO INT8_TMP VALUES (-('-9223372036854775808'::int8)); +ERROR: bigint out of range +--Testcase 155: +SELECT q1 FROM INT8_TMP; + q1 +---- +(0 rows) + +--Testcase 257: +DELETE FROM INT8_TMP; +--Testcase 258: +INSERT INTO INT8_TMP VALUES (0::int8 , '-9223372036854775808'::int8); +--Testcase 259: +SELECT q1 - q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 87: +DELETE FROM INT8_TMP; +--Testcase 156: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 157: +SELECT q1 + q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 88: +DELETE FROM INT8_TMP; +--Testcase 158: +INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '-9223372036854775800'::int8); +--Testcase 159: +SELECT q1 + q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 89: +DELETE FROM INT8_TMP; +--Testcase 160: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '-9223372036854775800'::int8); +--Testcase 161: +SELECT q1-q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 90: +DELETE FROM INT8_TMP; +--Testcase 162: +INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 163: +SELECT q1 - q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 91: +DELETE FROM INT8_TMP; +--Testcase 164: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 165: +SELECT q1 * q2 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 92: +DELETE FROM INT8_TMP; +--Testcase 166: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); +--Testcase 167: +SELECT q1 / q2 FROM INT8_TMP; +ERROR: division by zero +--Testcase 93: +DELETE FROM INT8_TMP; +--Testcase 168: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); +--Testcase 169: +SELECT q1 % q2 FROM INT8_TMP; +ERROR: division by zero +--Testcase 94: +DELETE FROM INT8_TMP; +--Testcase 170: +INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); +--Testcase 171: +SELECT abs(q1) FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 95: +DELETE FROM INT8_TMP; +--Testcase 172: +INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); +--Testcase 173: +SELECT q1 + q3 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 96: +DELETE FROM INT8_TMP; +--Testcase 174: +INSERT INTO INT8_TMP(q1, q3) VALUES ('-9223372036854775800'::int8 , '100'::int4); +--Testcase 175: +SELECT q1 - q3 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 97: +DELETE FROM INT8_TMP; +--Testcase 176: +INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); +--Testcase 177: +SELECT q1 * q3 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 98: +DELETE FROM INT8_TMP; +--Testcase 178: +INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); +--Testcase 179: +SELECT q3 + q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 99: +DELETE FROM INT8_TMP; +--Testcase 180: +INSERT INTO INT8_TMP(q3, q1) VALUES ('-100'::int4 , '9223372036854775800'::int8); +--Testcase 181: +SELECT q3 - q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 100: +DELETE FROM INT8_TMP; +--Testcase 182: +INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); +--Testcase 183: +SELECT q3 * q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 101: +DELETE FROM INT8_TMP; +--Testcase 184: +INSERT INTO INT8_TMP(q1, q4) VALUES ('9223372036854775800'::int8 , '100'::int2); +--Testcase 185: +SELECT q1 + q4 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 102: +DELETE FROM INT8_TMP; +--Testcase 186: +INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775800'::int8 , '100'::int2); +--Testcase 187: +SELECT q1 - q4 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 103: +DELETE FROM INT8_TMP; +--Testcase 188: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '100'::int2); +--Testcase 189: +SELECT q1 * q4 FROM INT8_TMP; + ?column? +---------- + +(1 row) + +--Testcase 104: +DELETE FROM INT8_TMP; +--Testcase 190: +INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775808'::int8 , '0'::int2); +--Testcase 191: +SELECT q1 / q4 FROM INT8_TMP; +ERROR: division by zero +--Testcase 105: +DELETE FROM INT8_TMP; +--Testcase 192: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); +--Testcase 193: +SELECT q4 + q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 106: +DELETE FROM INT8_TMP; +--Testcase 194: +INSERT INTO INT8_TMP(q4, q1) VALUES ('-100'::int2 , '9223372036854775800'::int8); +--Testcase 195: +SELECT q4 - q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 107: +DELETE FROM INT8_TMP; +--Testcase 196: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); +--Testcase 197: +SELECT q4 * q1 FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 108: +DELETE FROM INT8_TMP; +--Testcase 198: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '0'::int8); +--Testcase 199: +SELECT q4 / q1 FROM INT8_TMP; +ERROR: division by zero +--Testcase 110: +SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 = 456; + q1 +----- + 123 +(1 row) + +--Testcase 111: +SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 <> 456; +ERROR: integer out of range +--Testcase 112: +SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 = 456; + q1 +----- + 123 +(1 row) + +--Testcase 113: +SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 <> 456; +ERROR: smallint out of range +--Testcase 200: +DELETE FROM INT8_TMP; +--Testcase 201: +INSERT INTO INT8_TMP(q5) VALUES ('42'), ('-37'); +--Testcase 202: +SELECT CAST(q5::int2 as int8) FROM INT8_TMP; + q5 +----- + 42 + -37 +(2 rows) + +--Testcase 114: +SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL; + q1 | q2 +-------------+------------------------ + 123 | 456 + 123 | 4.567890123456789e+15 + 4.56789e+15 | 123 + 4.56789e+15 | 4.567890123456789e+15 + 4.56789e+15 | -4.567890123456789e+15 +(5 rows) + +--Testcase 203: +DELETE FROM INT8_TMP; +--Testcase 204: +INSERT INTO INT8_TMP(q5) VALUES ('36854775807.0'); +--Testcase 205: +SELECT CAST(q5::float4 AS int8) FROM INT8_TMP; + q5 +------------- + 36854775808 +(1 row) + +--Testcase 206: +DELETE FROM INT8_TMP; +--Testcase 207: +INSERT INTO INT8_TMP(q5) VALUES ('922337203685477580700.0'); +--Testcase 208: +SELECT CAST(q5::float8 AS int8) FROM INT8_TMP; +ERROR: bigint out of range +--Testcase 115: +SELECT CAST(q1 AS oid) FROM INT8_TBL; +ERROR: OID out of range +--Testcase 209: +SELECT oid::int8 FROM pg_class WHERE relname = 'pg_class'; + oid +------ + 1259 +(1 row) + +-- bit operations +--Testcase 116: +SELECT q1, q2, q1 & q2 AS "and", q1 | q2 AS "or", q1 # q2 AS "xor", ~q1 AS "not" FROM INT8_TBL; + q1 | q2 | and | or | xor | not +------------------+-------------------+------------------+------------------+------------------+------------------- + 123 | 456 | 72 | 507 | 435 | -124 + 123 | 4567890123456789 | 17 | 4567890123456895 | 4567890123456878 | -124 + 4567890123456789 | 123 | 17 | 4567890123456895 | 4567890123456878 | -4567890123456790 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 0 | -4567890123456790 + 4567890123456789 | -4567890123456789 | 1 | -1 | -2 | -4567890123456790 +(5 rows) + +--Testcase 117: +SELECT q1, q1 << 2 AS "shl", q1 >> 3 AS "shr" FROM INT8_TBL; + q1 | shl | shr +------------------+-------------------+----------------- + 123 | 492 | 15 + 123 | 492 | 15 + 4567890123456789 | 18271560493827156 | 570986265432098 + 4567890123456789 | 18271560493827156 | 570986265432098 + 4567890123456789 | 18271560493827156 | 570986265432098 +(5 rows) + +-- generate_series +--Testcase 118: +DELETE FROM INT8_TMP; +--Testcase 210: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8) q1; +--Testcase 211: +SELECT q1 FROM INT8_TMP; + q1 +------------------ + 4567890123456789 + 4567890123456790 + 4567890123456791 + 4567890123456792 + 4567890123456793 + 4567890123456794 + 4567890123456795 + 4567890123456796 + 4567890123456797 + 4567890123456798 + 4567890123456799 +(11 rows) + +--Testcase 120: +DELETE FROM INT8_TMP; +--Testcase 212: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 0) q1; -- should error +ERROR: step size cannot equal zero +--Testcase 213: +SELECT q1 FROM INT8_TMP; + q1 +---- +(0 rows) + +--Testcase 122: +DELETE FROM INT8_TMP; +--Testcase 214: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 2) q1; +--Testcase 215: +SELECT q1 FROM INT8_TMP; + q1 +------------------ + 4567890123456789 + 4567890123456791 + 4567890123456793 + 4567890123456795 + 4567890123456797 + 4567890123456799 +(6 rows) + +-- corner case +--Testcase 216: +DELETE FROM INT8_TMP; +--Testcase 217: +INSERT INTO INT8_TMP VALUES (-1::int8<<63); +--Testcase 218: +SELECT q1::text FROM INT8_TMP; + q1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 219: +DELETE FROM INT8_TMP; +--Testcase 220: +INSERT INTO INT8_TMP VALUES ((-1::int8<<63)+1); +--Testcase 221: +SELECT q1::text FROM INT8_TMP; + q1 +---------------------- + -9223372036854775807 +(1 row) + +-- check sane handling of INT64_MIN overflow cases +--Testcase 125: +DELETE FROM INT8_TMP; +--Testcase 222: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int8, 888); +ERROR: bigint out of range +--Testcase 126: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int8, 888); +ERROR: bigint out of range +--Testcase 127: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int8, 888); +--Testcase 128: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; + q1 +---- + 0 +(1 row) + +--Testcase 129: +DELETE FROM INT8_TMP WHERE q2 = 888; +--Testcase 130: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int4, 888); +ERROR: bigint out of range +--Testcase 131: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int4, 888); +ERROR: bigint out of range +--Testcase 132: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int4, 888); +--Testcase 133: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; + q1 +---- + 0 +(1 row) + +--Testcase 134: +DELETE FROM INT8_TMP WHERE q2 = 888; +--Testcase 135: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int2, 888); +ERROR: bigint out of range +--Testcase 136: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int2, 888); +ERROR: bigint out of range +--Testcase 137: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int2, 888); +--Testcase 138: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; + q1 +---- + 0 +(1 row) + +--Testcase 139: +DELETE FROM INT8_TMP WHERE q2 = 888; +-- check rounding when casting from float +--Testcase 223: +CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 224: +DELETE FROM FLOAT8_TMP; +--Testcase 225: +INSERT INTO FLOAT8_TMP VALUES + (-2.5::float8), + (-1.5::float8), + (-0.5::float8), + (0.0::float8), + (0.5::float8), + (1.5::float8), + (2.5::float8); +--Testcase 226: +SELECT f1 as x, f1::int8 as int8_value FROM FLOAT8_TMP; + x | int8_value +------+------------ + -2.5 | -2 + -1.5 | -2 + -0.5 | 0 + 0 | 0 + 0.5 | 0 + 1.5 | 2 + 2.5 | 2 +(7 rows) + +-- check rounding when casting from numeric +--Testcase 227: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 228: +DELETE FROM NUMERIC_TMP; +--Testcase 229: +INSERT INTO NUMERIC_TMP VALUES + (-2.5::numeric), + (-1.5::numeric), + (-0.5::numeric), + (0.0::numeric), + (0.5::numeric), + (1.5::numeric), + (2.5::numeric); +--Testcase 230: +SELECT f1 as x, f1::int8 as int8_value FROM NUMERIC_TMP; + x | int8_value +------+------------ + -2.5 | -3 + -1.5 | -2 + -0.5 | -1 + 0 | 0 + 0.5 | 1 + 1.5 | 2 + 2.5 | 3 +(7 rows) + +-- test gcd() +--Testcase 231: +DELETE FROM INT8_TMP; +--Testcase 232: +INSERT INTO INT8_TMP VALUES + (0::int8, 0::int8), + (0::int8, 29893644334::int8), + (288484263558::int8, 29893644334::int8), + (-288484263558::int8, 29893644334::int8), + ((-9223372036854775808)::int8, 1::int8), + ((-9223372036854775808)::int8, 9223372036854775807::int8), + ((-9223372036854775808)::int8, 4611686018427387904::int8); +--Testcase 233: +SELECT q1, q2, gcd(q1, q2), gcd(q1, -q2), gcd(q2, q1), gcd(-q2, q1) FROM INT8_TMP; + q1 | q2 | gcd | gcd | gcd | gcd +----------------------+---------------------+---------------------+---------------------+---------------------+--------------------- + 0 | 0 | 0 | 0 | 0 | 0 + 0 | 29893644334 | 29893644334 | 29893644334 | 29893644334 | 29893644334 + 288484263558 | 29893644334 | 6835958 | 6835958 | 6835958 | 6835958 + -288484263558 | 29893644334 | 6835958 | 6835958 | 6835958 | 6835958 + -9223372036854775808 | 1 | 1 | 1 | 1 | 1 + -9223372036854775808 | 9223372036854775807 | 1 | 1 | 1 | 1 + -9223372036854775808 | 4611686018427387904 | 4611686018427387904 | 4611686018427387904 | 4611686018427387904 | 4611686018427387904 +(7 rows) + +--Testcase 234: +DELETE FROM INT8_TMP; +--Testcase 235: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 0::int8); +--Testcase 236: +SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow +ERROR: bigint out of range +--Testcase 237: +DELETE FROM INT8_TMP; +--Testcase 238: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, (-9223372036854775808)::int8); +--Testcase 239: +SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow +ERROR: bigint out of range +-- test lcm() +--Testcase 240: +DELETE FROM INT8_TMP; +--Testcase 241: +INSERT INTO INT8_TMP VALUES + (0::int8, 0::int8), + (0::int8, 29893644334::int8), + (29893644334::int8, 29893644334::int8), + (288484263558::int8, 29893644334::int8), + (-288484263558::int8, 29893644334::int8), + ((-9223372036854775808)::int8, 0::int8); +--Testcase 242: +SELECT q1, q2, lcm(q1, q2), lcm(q1, -q2), lcm(q2, q1), lcm(-q2, q1) FROM INT8_TMP; + q1 | q2 | lcm | lcm | lcm | lcm +----------------------+-------------+------------------+------------------+------------------+------------------ + 0 | 0 | 0 | 0 | 0 | 0 + 0 | 29893644334 | 0 | 0 | 0 | 0 + 29893644334 | 29893644334 | 29893644334 | 29893644334 | 29893644334 | 29893644334 + 288484263558 | 29893644334 | 1261541684539134 | 1261541684539134 | 1261541684539134 | 1261541684539134 + -288484263558 | 29893644334 | 1261541684539134 | 1261541684539134 | 1261541684539134 | 1261541684539134 + -9223372036854775808 | 0 | 0 | 0 | 0 | 0 +(6 rows) + +--Testcase 243: +DELETE FROM INT8_TMP; +--Testcase 244: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 1::int8); +--Testcase 245: +SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow +ERROR: bigint out of range +--Testcase 246: +DELETE FROM INT8_TMP; +--Testcase 247: +INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806)::int8); +--Testcase 248: +SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow +ERROR: bigint out of range +-- non-decimal literals +--Testcase 260: +CREATE FOREIGN TABLE special_case_int8 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 261: +INSERT INTO special_case_int8 VALUES ('0b100101'::int8); +--Testcase 262: +SELECT f1 FROM special_case_int8; + f1 +---- + 37 +(1 row) + +--Testcase 263: +DELETE FROM special_case_int8; +--Testcase 264: +INSERT INTO special_case_int8 VALUES ('0o273'::int8); +--Testcase 265: +SELECT f1 FROM special_case_int8; + f1 +----- + 187 +(1 row) + +--Testcase 266: +DELETE FROM special_case_int8; +--Testcase 267: +INSERT INTO special_case_int8 VALUES ('0x42F'::int8); +--Testcase 268: +SELECT f1 FROM special_case_int8; + f1 +------ + 1071 +(1 row) + +--Testcase 269: +DELETE FROM special_case_int8; +--Testcase 270: +INSERT INTO special_case_int8 VALUES ('0b'::int8); +ERROR: invalid input syntax for type bigint: "0b" +LINE 1: INSERT INTO special_case_int8 VALUES ('0b'::int8); + ^ +--Testcase 271: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 272: +DELETE FROM special_case_int8; +--Testcase 273: +INSERT INTO special_case_int8 VALUES ('0o'::int8); +ERROR: invalid input syntax for type bigint: "0o" +LINE 1: INSERT INTO special_case_int8 VALUES ('0o'::int8); + ^ +--Testcase 274: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 275: +DELETE FROM special_case_int8; +--Testcase 276: +INSERT INTO special_case_int8 VALUES ('0x'::int8); +ERROR: invalid input syntax for type bigint: "0x" +LINE 1: INSERT INTO special_case_int8 VALUES ('0x'::int8); + ^ +--Testcase 277: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +-- cases near overflow +--Testcase 278: +DELETE FROM special_case_int8; +--Testcase 279: +INSERT INTO special_case_int8 VALUES ('0b111111111111111111111111111111111111111111111111111111111111111'::int8); +--Testcase 280: +SELECT f1 FROM special_case_int8; + f1 +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 281: +DELETE FROM special_case_int8; +--Testcase 282: +INSERT INTO special_case_int8 VALUES ('0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +ERROR: value "0b1000000000000000000000000000000000000000000000000000000000000000" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('0b1000000000000000000... + ^ +--Testcase 283: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 284: +DELETE FROM special_case_int8; +--Testcase 285: +INSERT INTO special_case_int8 VALUES ('0o777777777777777777777'::int8); +--Testcase 286: +SELECT f1 FROM special_case_int8; + f1 +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 287: +DELETE FROM special_case_int8; +--Testcase 288: +INSERT INTO special_case_int8 VALUES ('0o1000000000000000000000'::int8); +ERROR: value "0o1000000000000000000000" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('0o1000000000000000000... + ^ +--Testcase 289: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 290: +DELETE FROM special_case_int8; +--Testcase 291: +INSERT INTO special_case_int8 VALUES ('0x7FFFFFFFFFFFFFFF'::int8); +--Testcase 292: +SELECT f1 FROM special_case_int8; + f1 +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 293: +DELETE FROM special_case_int8; +--Testcase 294: +INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::int8); +ERROR: value "0x8000000000000000" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::... + ^ +--Testcase 295: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 296: +DELETE FROM special_case_int8; +--Testcase 297: +INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 298: +SELECT f1 FROM special_case_int8; + f1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 299: +DELETE FROM special_case_int8; +--Testcase 300: +INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000001'::int8); +ERROR: value "-0b1000000000000000000000000000000000000000000000000000000000000001" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('-0b100000000000000000... + ^ +--Testcase 301: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 302: +DELETE FROM special_case_int8; +--Testcase 303: +INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000000'::int8); +--Testcase 304: +SELECT f1 FROM special_case_int8; + f1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 305: +DELETE FROM special_case_int8; +--Testcase 306: +INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000001'::int8); +ERROR: value "-0o1000000000000000000001" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('-0o100000000000000000... + ^ +--Testcase 307: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 308: +DELETE FROM special_case_int8; +--Testcase 309: +INSERT INTO special_case_int8 VALUES ('-0x8000000000000000'::int8); +--Testcase 310: +SELECT f1 FROM special_case_int8; + f1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 311: +DELETE FROM special_case_int8; +--Testcase 312: +INSERT INTO special_case_int8 VALUES ('-0x8000000000000001'::int8); +ERROR: value "-0x8000000000000001" is out of range for type bigint +LINE 1: INSERT INTO special_case_int8 VALUES ('-0x8000000000000001':... + ^ +--Testcase 313: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +-- underscores +--Testcase 314: +DELETE FROM special_case_int8; +--Testcase 315: +INSERT INTO special_case_int8 VALUES ('1_000_000'::int8); +--Testcase 316: +SELECT f1 FROM special_case_int8; + f1 +--------- + 1000000 +(1 row) + +--Testcase 317: +DELETE FROM special_case_int8; +--Testcase 318: +INSERT INTO special_case_int8 VALUES ('1_2_3'::int8); +--Testcase 319: +SELECT f1 FROM special_case_int8; + f1 +----- + 123 +(1 row) + +--Testcase 320: +DELETE FROM special_case_int8; +--Testcase 321: +INSERT INTO special_case_int8 VALUES ('0x1EEE_FFFF'::int8); +--Testcase 322: +SELECT f1 FROM special_case_int8; + f1 +----------- + 518979583 +(1 row) + +--Testcase 323: +DELETE FROM special_case_int8; +--Testcase 324: +INSERT INTO special_case_int8 VALUES ('0o2_73'::int8); +--Testcase 325: +SELECT f1 FROM special_case_int8; + f1 +----- + 187 +(1 row) + +--Testcase 326: +DELETE FROM special_case_int8; +--Testcase 327: +INSERT INTO special_case_int8 VALUES ('0b_10_0101'::int8); +--Testcase 328: +SELECT f1 FROM special_case_int8; + f1 +---- + 37 +(1 row) + +-- error cases +--Testcase 329: +DELETE FROM special_case_int8; +--Testcase 330: +INSERT INTO special_case_int8 VALUES ('_100'::int8); +ERROR: invalid input syntax for type bigint: "_100" +LINE 1: INSERT INTO special_case_int8 VALUES ('_100'::int8); + ^ +--Testcase 331: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 332: +DELETE FROM special_case_int8; +--Testcase 333: +INSERT INTO special_case_int8 VALUES ('100_'::int8); +ERROR: invalid input syntax for type bigint: "100_" +LINE 1: INSERT INTO special_case_int8 VALUES ('100_'::int8); + ^ +--Testcase 334: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 335: +DELETE FROM special_case_int8; +--Testcase 336: +INSERT INTO special_case_int8 VALUES ('100__000'::int8); +ERROR: invalid input syntax for type bigint: "100__000" +LINE 1: INSERT INTO special_case_int8 VALUES ('100__000'::int8); + ^ +--Testcase 337: +SELECT f1 FROM special_case_int8; + f1 +---- +(0 rows) + +--Testcase 338: +DELETE FROM INT8_TBL; +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +--Testcase 249: +DROP SERVER sqlite_svr; +--Testcase 250: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/extra/join.out b/expected/17.0/extra/join.out new file mode 100644 index 00000000..0194b7e6 --- /dev/null +++ b/expected/17.0/extra/join.out @@ -0,0 +1,8868 @@ +-- +-- JOIN +-- Test JOIN clauses +-- +--Testcase 360: +CREATE EXTENSION sqlite_fdw; +--Testcase 361: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 362: +CREATE FOREIGN TABLE J1_TBL ( + i integer, + j integer, + t text +) SERVER sqlite_svr; +--Testcase 363: +CREATE FOREIGN TABLE J2_TBL ( + i integer, + k integer +) SERVER sqlite_svr; +--Testcase 364: +CREATE FOREIGN TABLE tenk1 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 365: +CREATE FOREIGN TABLE tenk2 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 366: +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 641: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 642: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 643: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 644: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 645: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); +--Testcase 367: +CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 646: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 647: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 648: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 649: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 650: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); +--Testcase 368: +CREATE FOREIGN TABLE INT8_TBL( + q1 int8 OPTIONS (key 'true'), + q2 int8 OPTIONS (key 'true') +) SERVER sqlite_svr; +--Testcase 651: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 652: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 653: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 654: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 655: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); +--Testcase 369: +CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 1: +INSERT INTO J1_TBL VALUES (1, 4, 'one'); +--Testcase 2: +INSERT INTO J1_TBL VALUES (2, 3, 'two'); +--Testcase 3: +INSERT INTO J1_TBL VALUES (3, 2, 'three'); +--Testcase 4: +INSERT INTO J1_TBL VALUES (4, 1, 'four'); +--Testcase 5: +INSERT INTO J1_TBL VALUES (5, 0, 'five'); +--Testcase 6: +INSERT INTO J1_TBL VALUES (6, 6, 'six'); +--Testcase 7: +INSERT INTO J1_TBL VALUES (7, 7, 'seven'); +--Testcase 8: +INSERT INTO J1_TBL VALUES (8, 8, 'eight'); +--Testcase 9: +INSERT INTO J1_TBL VALUES (0, NULL, 'zero'); +--Testcase 10: +INSERT INTO J1_TBL VALUES (NULL, NULL, 'null'); +--Testcase 11: +INSERT INTO J1_TBL VALUES (NULL, 0, 'zero'); +--Testcase 12: +INSERT INTO J2_TBL VALUES (1, -1); +--Testcase 13: +INSERT INTO J2_TBL VALUES (2, 2); +--Testcase 14: +INSERT INTO J2_TBL VALUES (3, -3); +--Testcase 15: +INSERT INTO J2_TBL VALUES (2, 4); +--Testcase 16: +INSERT INTO J2_TBL VALUES (5, -5); +--Testcase 17: +INSERT INTO J2_TBL VALUES (5, -5); +--Testcase 18: +INSERT INTO J2_TBL VALUES (0, NULL); +--Testcase 19: +INSERT INTO J2_TBL VALUES (NULL, NULL); +--Testcase 20: +INSERT INTO J2_TBL VALUES (NULL, 0); +-- useful in some tests below +--Testcase 370: +create temp table onerow(); +--Testcase 371: +insert into onerow default values; +analyze onerow; +-- +-- CORRELATION NAMES +-- Make sure that table/column aliases are supported +-- before diving into more complex join syntax. +-- +--Testcase 21: +SELECT * + FROM J1_TBL AS tx; + i | j | t +---+---+------- + 1 | 4 | one + 2 | 3 | two + 3 | 2 | three + 4 | 1 | four + 5 | 0 | five + 6 | 6 | six + 7 | 7 | seven + 8 | 8 | eight + 0 | | zero + | | null + | 0 | zero +(11 rows) + +--Testcase 22: +SELECT * + FROM J1_TBL tx; + i | j | t +---+---+------- + 1 | 4 | one + 2 | 3 | two + 3 | 2 | three + 4 | 1 | four + 5 | 0 | five + 6 | 6 | six + 7 | 7 | seven + 8 | 8 | eight + 0 | | zero + | | null + | 0 | zero +(11 rows) + +--Testcase 23: +SELECT * + FROM J1_TBL AS t1 (a, b, c); + a | b | c +---+---+------- + 1 | 4 | one + 2 | 3 | two + 3 | 2 | three + 4 | 1 | four + 5 | 0 | five + 6 | 6 | six + 7 | 7 | seven + 8 | 8 | eight + 0 | | zero + | | null + | 0 | zero +(11 rows) + +--Testcase 24: +SELECT * + FROM J1_TBL t1 (a, b, c); + a | b | c +---+---+------- + 1 | 4 | one + 2 | 3 | two + 3 | 2 | three + 4 | 1 | four + 5 | 0 | five + 6 | 6 | six + 7 | 7 | seven + 8 | 8 | eight + 0 | | zero + | | null + | 0 | zero +(11 rows) + +--Testcase 25: +SELECT * + FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e); + a | b | c | d | e +---+---+-------+---+---- + 1 | 4 | one | 1 | -1 + 2 | 3 | two | 1 | -1 + 3 | 2 | three | 1 | -1 + 4 | 1 | four | 1 | -1 + 5 | 0 | five | 1 | -1 + 6 | 6 | six | 1 | -1 + 7 | 7 | seven | 1 | -1 + 8 | 8 | eight | 1 | -1 + 0 | | zero | 1 | -1 + | | null | 1 | -1 + | 0 | zero | 1 | -1 + 1 | 4 | one | 2 | 2 + 2 | 3 | two | 2 | 2 + 3 | 2 | three | 2 | 2 + 4 | 1 | four | 2 | 2 + 5 | 0 | five | 2 | 2 + 6 | 6 | six | 2 | 2 + 7 | 7 | seven | 2 | 2 + 8 | 8 | eight | 2 | 2 + 0 | | zero | 2 | 2 + | | null | 2 | 2 + | 0 | zero | 2 | 2 + 1 | 4 | one | 3 | -3 + 2 | 3 | two | 3 | -3 + 3 | 2 | three | 3 | -3 + 4 | 1 | four | 3 | -3 + 5 | 0 | five | 3 | -3 + 6 | 6 | six | 3 | -3 + 7 | 7 | seven | 3 | -3 + 8 | 8 | eight | 3 | -3 + 0 | | zero | 3 | -3 + | | null | 3 | -3 + | 0 | zero | 3 | -3 + 1 | 4 | one | 2 | 4 + 2 | 3 | two | 2 | 4 + 3 | 2 | three | 2 | 4 + 4 | 1 | four | 2 | 4 + 5 | 0 | five | 2 | 4 + 6 | 6 | six | 2 | 4 + 7 | 7 | seven | 2 | 4 + 8 | 8 | eight | 2 | 4 + 0 | | zero | 2 | 4 + | | null | 2 | 4 + | 0 | zero | 2 | 4 + 1 | 4 | one | 5 | -5 + 2 | 3 | two | 5 | -5 + 3 | 2 | three | 5 | -5 + 4 | 1 | four | 5 | -5 + 5 | 0 | five | 5 | -5 + 6 | 6 | six | 5 | -5 + 7 | 7 | seven | 5 | -5 + 8 | 8 | eight | 5 | -5 + 0 | | zero | 5 | -5 + | | null | 5 | -5 + | 0 | zero | 5 | -5 + 1 | 4 | one | 5 | -5 + 2 | 3 | two | 5 | -5 + 3 | 2 | three | 5 | -5 + 4 | 1 | four | 5 | -5 + 5 | 0 | five | 5 | -5 + 6 | 6 | six | 5 | -5 + 7 | 7 | seven | 5 | -5 + 8 | 8 | eight | 5 | -5 + 0 | | zero | 5 | -5 + | | null | 5 | -5 + | 0 | zero | 5 | -5 + 1 | 4 | one | 0 | + 2 | 3 | two | 0 | + 3 | 2 | three | 0 | + 4 | 1 | four | 0 | + 5 | 0 | five | 0 | + 6 | 6 | six | 0 | + 7 | 7 | seven | 0 | + 8 | 8 | eight | 0 | + 0 | | zero | 0 | + | | null | 0 | + | 0 | zero | 0 | + 1 | 4 | one | | + 2 | 3 | two | | + 3 | 2 | three | | + 4 | 1 | four | | + 5 | 0 | five | | + 6 | 6 | six | | + 7 | 7 | seven | | + 8 | 8 | eight | | + 0 | | zero | | + | | null | | + | 0 | zero | | + 1 | 4 | one | | 0 + 2 | 3 | two | | 0 + 3 | 2 | three | | 0 + 4 | 1 | four | | 0 + 5 | 0 | five | | 0 + 6 | 6 | six | | 0 + 7 | 7 | seven | | 0 + 8 | 8 | eight | | 0 + 0 | | zero | | 0 + | | null | | 0 + | 0 | zero | | 0 +(99 rows) + +--Testcase 26: +SELECT t1.a, t2.e + FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e) + WHERE t1.a = t2.d; + a | e +---+---- + 0 | + 1 | -1 + 2 | 2 + 2 | 4 + 3 | -3 + 5 | -5 + 5 | -5 +(7 rows) + +-- +-- CROSS JOIN +-- Qualifications are not allowed on cross joins, +-- which degenerate into a standard unqualified inner join. +-- +--Testcase 27: +SELECT * + FROM J1_TBL CROSS JOIN J2_TBL; + i | j | t | i | k +---+---+-------+---+---- + 1 | 4 | one | 1 | -1 + 2 | 3 | two | 1 | -1 + 3 | 2 | three | 1 | -1 + 4 | 1 | four | 1 | -1 + 5 | 0 | five | 1 | -1 + 6 | 6 | six | 1 | -1 + 7 | 7 | seven | 1 | -1 + 8 | 8 | eight | 1 | -1 + 0 | | zero | 1 | -1 + | | null | 1 | -1 + | 0 | zero | 1 | -1 + 1 | 4 | one | 2 | 2 + 2 | 3 | two | 2 | 2 + 3 | 2 | three | 2 | 2 + 4 | 1 | four | 2 | 2 + 5 | 0 | five | 2 | 2 + 6 | 6 | six | 2 | 2 + 7 | 7 | seven | 2 | 2 + 8 | 8 | eight | 2 | 2 + 0 | | zero | 2 | 2 + | | null | 2 | 2 + | 0 | zero | 2 | 2 + 1 | 4 | one | 3 | -3 + 2 | 3 | two | 3 | -3 + 3 | 2 | three | 3 | -3 + 4 | 1 | four | 3 | -3 + 5 | 0 | five | 3 | -3 + 6 | 6 | six | 3 | -3 + 7 | 7 | seven | 3 | -3 + 8 | 8 | eight | 3 | -3 + 0 | | zero | 3 | -3 + | | null | 3 | -3 + | 0 | zero | 3 | -3 + 1 | 4 | one | 2 | 4 + 2 | 3 | two | 2 | 4 + 3 | 2 | three | 2 | 4 + 4 | 1 | four | 2 | 4 + 5 | 0 | five | 2 | 4 + 6 | 6 | six | 2 | 4 + 7 | 7 | seven | 2 | 4 + 8 | 8 | eight | 2 | 4 + 0 | | zero | 2 | 4 + | | null | 2 | 4 + | 0 | zero | 2 | 4 + 1 | 4 | one | 5 | -5 + 2 | 3 | two | 5 | -5 + 3 | 2 | three | 5 | -5 + 4 | 1 | four | 5 | -5 + 5 | 0 | five | 5 | -5 + 6 | 6 | six | 5 | -5 + 7 | 7 | seven | 5 | -5 + 8 | 8 | eight | 5 | -5 + 0 | | zero | 5 | -5 + | | null | 5 | -5 + | 0 | zero | 5 | -5 + 1 | 4 | one | 5 | -5 + 2 | 3 | two | 5 | -5 + 3 | 2 | three | 5 | -5 + 4 | 1 | four | 5 | -5 + 5 | 0 | five | 5 | -5 + 6 | 6 | six | 5 | -5 + 7 | 7 | seven | 5 | -5 + 8 | 8 | eight | 5 | -5 + 0 | | zero | 5 | -5 + | | null | 5 | -5 + | 0 | zero | 5 | -5 + 1 | 4 | one | 0 | + 2 | 3 | two | 0 | + 3 | 2 | three | 0 | + 4 | 1 | four | 0 | + 5 | 0 | five | 0 | + 6 | 6 | six | 0 | + 7 | 7 | seven | 0 | + 8 | 8 | eight | 0 | + 0 | | zero | 0 | + | | null | 0 | + | 0 | zero | 0 | + 1 | 4 | one | | + 2 | 3 | two | | + 3 | 2 | three | | + 4 | 1 | four | | + 5 | 0 | five | | + 6 | 6 | six | | + 7 | 7 | seven | | + 8 | 8 | eight | | + 0 | | zero | | + | | null | | + | 0 | zero | | + 1 | 4 | one | | 0 + 2 | 3 | two | | 0 + 3 | 2 | three | | 0 + 4 | 1 | four | | 0 + 5 | 0 | five | | 0 + 6 | 6 | six | | 0 + 7 | 7 | seven | | 0 + 8 | 8 | eight | | 0 + 0 | | zero | | 0 + | | null | | 0 + | 0 | zero | | 0 +(99 rows) + +-- ambiguous column +--Testcase 28: +SELECT i, k, t + FROM J1_TBL CROSS JOIN J2_TBL; +ERROR: column reference "i" is ambiguous +LINE 1: SELECT i, k, t + ^ +-- resolve previous ambiguity by specifying the table name +--Testcase 29: +SELECT t1.i, k, t + FROM J1_TBL t1 CROSS JOIN J2_TBL t2; + i | k | t +---+----+------- + 1 | -1 | one + 2 | -1 | two + 3 | -1 | three + 4 | -1 | four + 5 | -1 | five + 6 | -1 | six + 7 | -1 | seven + 8 | -1 | eight + 0 | -1 | zero + | -1 | null + | -1 | zero + 1 | 2 | one + 2 | 2 | two + 3 | 2 | three + 4 | 2 | four + 5 | 2 | five + 6 | 2 | six + 7 | 2 | seven + 8 | 2 | eight + 0 | 2 | zero + | 2 | null + | 2 | zero + 1 | -3 | one + 2 | -3 | two + 3 | -3 | three + 4 | -3 | four + 5 | -3 | five + 6 | -3 | six + 7 | -3 | seven + 8 | -3 | eight + 0 | -3 | zero + | -3 | null + | -3 | zero + 1 | 4 | one + 2 | 4 | two + 3 | 4 | three + 4 | 4 | four + 5 | 4 | five + 6 | 4 | six + 7 | 4 | seven + 8 | 4 | eight + 0 | 4 | zero + | 4 | null + | 4 | zero + 1 | -5 | one + 2 | -5 | two + 3 | -5 | three + 4 | -5 | four + 5 | -5 | five + 6 | -5 | six + 7 | -5 | seven + 8 | -5 | eight + 0 | -5 | zero + | -5 | null + | -5 | zero + 1 | -5 | one + 2 | -5 | two + 3 | -5 | three + 4 | -5 | four + 5 | -5 | five + 6 | -5 | six + 7 | -5 | seven + 8 | -5 | eight + 0 | -5 | zero + | -5 | null + | -5 | zero + 1 | | one + 2 | | two + 3 | | three + 4 | | four + 5 | | five + 6 | | six + 7 | | seven + 8 | | eight + 0 | | zero + | | null + | | zero + 1 | | one + 2 | | two + 3 | | three + 4 | | four + 5 | | five + 6 | | six + 7 | | seven + 8 | | eight + 0 | | zero + | | null + | | zero + 1 | 0 | one + 2 | 0 | two + 3 | 0 | three + 4 | 0 | four + 5 | 0 | five + 6 | 0 | six + 7 | 0 | seven + 8 | 0 | eight + 0 | 0 | zero + | 0 | null + | 0 | zero +(99 rows) + +--Testcase 30: +SELECT ii, tt, kk + FROM (J1_TBL CROSS JOIN J2_TBL) + AS tx (ii, jj, tt, ii2, kk); + ii | tt | kk +----+-------+---- + 1 | one | -1 + 2 | two | -1 + 3 | three | -1 + 4 | four | -1 + 5 | five | -1 + 6 | six | -1 + 7 | seven | -1 + 8 | eight | -1 + 0 | zero | -1 + | null | -1 + | zero | -1 + 1 | one | 2 + 2 | two | 2 + 3 | three | 2 + 4 | four | 2 + 5 | five | 2 + 6 | six | 2 + 7 | seven | 2 + 8 | eight | 2 + 0 | zero | 2 + | null | 2 + | zero | 2 + 1 | one | -3 + 2 | two | -3 + 3 | three | -3 + 4 | four | -3 + 5 | five | -3 + 6 | six | -3 + 7 | seven | -3 + 8 | eight | -3 + 0 | zero | -3 + | null | -3 + | zero | -3 + 1 | one | 4 + 2 | two | 4 + 3 | three | 4 + 4 | four | 4 + 5 | five | 4 + 6 | six | 4 + 7 | seven | 4 + 8 | eight | 4 + 0 | zero | 4 + | null | 4 + | zero | 4 + 1 | one | -5 + 2 | two | -5 + 3 | three | -5 + 4 | four | -5 + 5 | five | -5 + 6 | six | -5 + 7 | seven | -5 + 8 | eight | -5 + 0 | zero | -5 + | null | -5 + | zero | -5 + 1 | one | -5 + 2 | two | -5 + 3 | three | -5 + 4 | four | -5 + 5 | five | -5 + 6 | six | -5 + 7 | seven | -5 + 8 | eight | -5 + 0 | zero | -5 + | null | -5 + | zero | -5 + 1 | one | + 2 | two | + 3 | three | + 4 | four | + 5 | five | + 6 | six | + 7 | seven | + 8 | eight | + 0 | zero | + | null | + | zero | + 1 | one | + 2 | two | + 3 | three | + 4 | four | + 5 | five | + 6 | six | + 7 | seven | + 8 | eight | + 0 | zero | + | null | + | zero | + 1 | one | 0 + 2 | two | 0 + 3 | three | 0 + 4 | four | 0 + 5 | five | 0 + 6 | six | 0 + 7 | seven | 0 + 8 | eight | 0 + 0 | zero | 0 + | null | 0 + | zero | 0 +(99 rows) + +--Testcase 31: +SELECT tx.ii, tx.jj, tx.kk + FROM (J1_TBL t1 (a, b, c) CROSS JOIN J2_TBL t2 (d, e)) + AS tx (ii, jj, tt, ii2, kk); + ii | jj | kk +----+----+---- + 1 | 4 | -1 + 2 | 3 | -1 + 3 | 2 | -1 + 4 | 1 | -1 + 5 | 0 | -1 + 6 | 6 | -1 + 7 | 7 | -1 + 8 | 8 | -1 + 0 | | -1 + | | -1 + | 0 | -1 + 1 | 4 | 2 + 2 | 3 | 2 + 3 | 2 | 2 + 4 | 1 | 2 + 5 | 0 | 2 + 6 | 6 | 2 + 7 | 7 | 2 + 8 | 8 | 2 + 0 | | 2 + | | 2 + | 0 | 2 + 1 | 4 | -3 + 2 | 3 | -3 + 3 | 2 | -3 + 4 | 1 | -3 + 5 | 0 | -3 + 6 | 6 | -3 + 7 | 7 | -3 + 8 | 8 | -3 + 0 | | -3 + | | -3 + | 0 | -3 + 1 | 4 | 4 + 2 | 3 | 4 + 3 | 2 | 4 + 4 | 1 | 4 + 5 | 0 | 4 + 6 | 6 | 4 + 7 | 7 | 4 + 8 | 8 | 4 + 0 | | 4 + | | 4 + | 0 | 4 + 1 | 4 | -5 + 2 | 3 | -5 + 3 | 2 | -5 + 4 | 1 | -5 + 5 | 0 | -5 + 6 | 6 | -5 + 7 | 7 | -5 + 8 | 8 | -5 + 0 | | -5 + | | -5 + | 0 | -5 + 1 | 4 | -5 + 2 | 3 | -5 + 3 | 2 | -5 + 4 | 1 | -5 + 5 | 0 | -5 + 6 | 6 | -5 + 7 | 7 | -5 + 8 | 8 | -5 + 0 | | -5 + | | -5 + | 0 | -5 + 1 | 4 | + 2 | 3 | + 3 | 2 | + 4 | 1 | + 5 | 0 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 0 | | + | | + | 0 | + 1 | 4 | + 2 | 3 | + 3 | 2 | + 4 | 1 | + 5 | 0 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 0 | | + | | + | 0 | + 1 | 4 | 0 + 2 | 3 | 0 + 3 | 2 | 0 + 4 | 1 | 0 + 5 | 0 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 0 | | 0 + | | 0 + | 0 | 0 +(99 rows) + +--Testcase 32: +SELECT * + FROM J1_TBL CROSS JOIN J2_TBL a CROSS JOIN J2_TBL b; + i | j | t | i | k | i | k +---+---+-------+---+----+---+---- + 1 | 4 | one | 1 | -1 | 1 | -1 + 1 | 4 | one | 1 | -1 | 2 | 2 + 1 | 4 | one | 1 | -1 | 3 | -3 + 1 | 4 | one | 1 | -1 | 2 | 4 + 1 | 4 | one | 1 | -1 | 5 | -5 + 1 | 4 | one | 1 | -1 | 5 | -5 + 1 | 4 | one | 1 | -1 | 0 | + 1 | 4 | one | 1 | -1 | | + 1 | 4 | one | 1 | -1 | | 0 + 2 | 3 | two | 1 | -1 | 1 | -1 + 2 | 3 | two | 1 | -1 | 2 | 2 + 2 | 3 | two | 1 | -1 | 3 | -3 + 2 | 3 | two | 1 | -1 | 2 | 4 + 2 | 3 | two | 1 | -1 | 5 | -5 + 2 | 3 | two | 1 | -1 | 5 | -5 + 2 | 3 | two | 1 | -1 | 0 | + 2 | 3 | two | 1 | -1 | | + 2 | 3 | two | 1 | -1 | | 0 + 3 | 2 | three | 1 | -1 | 1 | -1 + 3 | 2 | three | 1 | -1 | 2 | 2 + 3 | 2 | three | 1 | -1 | 3 | -3 + 3 | 2 | three | 1 | -1 | 2 | 4 + 3 | 2 | three | 1 | -1 | 5 | -5 + 3 | 2 | three | 1 | -1 | 5 | -5 + 3 | 2 | three | 1 | -1 | 0 | + 3 | 2 | three | 1 | -1 | | + 3 | 2 | three | 1 | -1 | | 0 + 4 | 1 | four | 1 | -1 | 1 | -1 + 4 | 1 | four | 1 | -1 | 2 | 2 + 4 | 1 | four | 1 | -1 | 3 | -3 + 4 | 1 | four | 1 | -1 | 2 | 4 + 4 | 1 | four | 1 | -1 | 5 | -5 + 4 | 1 | four | 1 | -1 | 5 | -5 + 4 | 1 | four | 1 | -1 | 0 | + 4 | 1 | four | 1 | -1 | | + 4 | 1 | four | 1 | -1 | | 0 + 5 | 0 | five | 1 | -1 | 1 | -1 + 5 | 0 | five | 1 | -1 | 2 | 2 + 5 | 0 | five | 1 | -1 | 3 | -3 + 5 | 0 | five | 1 | -1 | 2 | 4 + 5 | 0 | five | 1 | -1 | 5 | -5 + 5 | 0 | five | 1 | -1 | 5 | -5 + 5 | 0 | five | 1 | -1 | 0 | + 5 | 0 | five | 1 | -1 | | + 5 | 0 | five | 1 | -1 | | 0 + 6 | 6 | six | 1 | -1 | 1 | -1 + 6 | 6 | six | 1 | -1 | 2 | 2 + 6 | 6 | six | 1 | -1 | 3 | -3 + 6 | 6 | six | 1 | -1 | 2 | 4 + 6 | 6 | six | 1 | -1 | 5 | -5 + 6 | 6 | six | 1 | -1 | 5 | -5 + 6 | 6 | six | 1 | -1 | 0 | + 6 | 6 | six | 1 | -1 | | + 6 | 6 | six | 1 | -1 | | 0 + 7 | 7 | seven | 1 | -1 | 1 | -1 + 7 | 7 | seven | 1 | -1 | 2 | 2 + 7 | 7 | seven | 1 | -1 | 3 | -3 + 7 | 7 | seven | 1 | -1 | 2 | 4 + 7 | 7 | seven | 1 | -1 | 5 | -5 + 7 | 7 | seven | 1 | -1 | 5 | -5 + 7 | 7 | seven | 1 | -1 | 0 | + 7 | 7 | seven | 1 | -1 | | + 7 | 7 | seven | 1 | -1 | | 0 + 8 | 8 | eight | 1 | -1 | 1 | -1 + 8 | 8 | eight | 1 | -1 | 2 | 2 + 8 | 8 | eight | 1 | -1 | 3 | -3 + 8 | 8 | eight | 1 | -1 | 2 | 4 + 8 | 8 | eight | 1 | -1 | 5 | -5 + 8 | 8 | eight | 1 | -1 | 5 | -5 + 8 | 8 | eight | 1 | -1 | 0 | + 8 | 8 | eight | 1 | -1 | | + 8 | 8 | eight | 1 | -1 | | 0 + 0 | | zero | 1 | -1 | 1 | -1 + 0 | | zero | 1 | -1 | 2 | 2 + 0 | | zero | 1 | -1 | 3 | -3 + 0 | | zero | 1 | -1 | 2 | 4 + 0 | | zero | 1 | -1 | 5 | -5 + 0 | | zero | 1 | -1 | 5 | -5 + 0 | | zero | 1 | -1 | 0 | + 0 | | zero | 1 | -1 | | + 0 | | zero | 1 | -1 | | 0 + | | null | 1 | -1 | 1 | -1 + | | null | 1 | -1 | 2 | 2 + | | null | 1 | -1 | 3 | -3 + | | null | 1 | -1 | 2 | 4 + | | null | 1 | -1 | 5 | -5 + | | null | 1 | -1 | 5 | -5 + | | null | 1 | -1 | 0 | + | | null | 1 | -1 | | + | | null | 1 | -1 | | 0 + | 0 | zero | 1 | -1 | 1 | -1 + | 0 | zero | 1 | -1 | 2 | 2 + | 0 | zero | 1 | -1 | 3 | -3 + | 0 | zero | 1 | -1 | 2 | 4 + | 0 | zero | 1 | -1 | 5 | -5 + | 0 | zero | 1 | -1 | 5 | -5 + | 0 | zero | 1 | -1 | 0 | + | 0 | zero | 1 | -1 | | + | 0 | zero | 1 | -1 | | 0 + 1 | 4 | one | 2 | 2 | 1 | -1 + 1 | 4 | one | 2 | 2 | 2 | 2 + 1 | 4 | one | 2 | 2 | 3 | -3 + 1 | 4 | one | 2 | 2 | 2 | 4 + 1 | 4 | one | 2 | 2 | 5 | -5 + 1 | 4 | one | 2 | 2 | 5 | -5 + 1 | 4 | one | 2 | 2 | 0 | + 1 | 4 | one | 2 | 2 | | + 1 | 4 | one | 2 | 2 | | 0 + 2 | 3 | two | 2 | 2 | 1 | -1 + 2 | 3 | two | 2 | 2 | 2 | 2 + 2 | 3 | two | 2 | 2 | 3 | -3 + 2 | 3 | two | 2 | 2 | 2 | 4 + 2 | 3 | two | 2 | 2 | 5 | -5 + 2 | 3 | two | 2 | 2 | 5 | -5 + 2 | 3 | two | 2 | 2 | 0 | + 2 | 3 | two | 2 | 2 | | + 2 | 3 | two | 2 | 2 | | 0 + 3 | 2 | three | 2 | 2 | 1 | -1 + 3 | 2 | three | 2 | 2 | 2 | 2 + 3 | 2 | three | 2 | 2 | 3 | -3 + 3 | 2 | three | 2 | 2 | 2 | 4 + 3 | 2 | three | 2 | 2 | 5 | -5 + 3 | 2 | three | 2 | 2 | 5 | -5 + 3 | 2 | three | 2 | 2 | 0 | + 3 | 2 | three | 2 | 2 | | + 3 | 2 | three | 2 | 2 | | 0 + 4 | 1 | four | 2 | 2 | 1 | -1 + 4 | 1 | four | 2 | 2 | 2 | 2 + 4 | 1 | four | 2 | 2 | 3 | -3 + 4 | 1 | four | 2 | 2 | 2 | 4 + 4 | 1 | four | 2 | 2 | 5 | -5 + 4 | 1 | four | 2 | 2 | 5 | -5 + 4 | 1 | four | 2 | 2 | 0 | + 4 | 1 | four | 2 | 2 | | + 4 | 1 | four | 2 | 2 | | 0 + 5 | 0 | five | 2 | 2 | 1 | -1 + 5 | 0 | five | 2 | 2 | 2 | 2 + 5 | 0 | five | 2 | 2 | 3 | -3 + 5 | 0 | five | 2 | 2 | 2 | 4 + 5 | 0 | five | 2 | 2 | 5 | -5 + 5 | 0 | five | 2 | 2 | 5 | -5 + 5 | 0 | five | 2 | 2 | 0 | + 5 | 0 | five | 2 | 2 | | + 5 | 0 | five | 2 | 2 | | 0 + 6 | 6 | six | 2 | 2 | 1 | -1 + 6 | 6 | six | 2 | 2 | 2 | 2 + 6 | 6 | six | 2 | 2 | 3 | -3 + 6 | 6 | six | 2 | 2 | 2 | 4 + 6 | 6 | six | 2 | 2 | 5 | -5 + 6 | 6 | six | 2 | 2 | 5 | -5 + 6 | 6 | six | 2 | 2 | 0 | + 6 | 6 | six | 2 | 2 | | + 6 | 6 | six | 2 | 2 | | 0 + 7 | 7 | seven | 2 | 2 | 1 | -1 + 7 | 7 | seven | 2 | 2 | 2 | 2 + 7 | 7 | seven | 2 | 2 | 3 | -3 + 7 | 7 | seven | 2 | 2 | 2 | 4 + 7 | 7 | seven | 2 | 2 | 5 | -5 + 7 | 7 | seven | 2 | 2 | 5 | -5 + 7 | 7 | seven | 2 | 2 | 0 | + 7 | 7 | seven | 2 | 2 | | + 7 | 7 | seven | 2 | 2 | | 0 + 8 | 8 | eight | 2 | 2 | 1 | -1 + 8 | 8 | eight | 2 | 2 | 2 | 2 + 8 | 8 | eight | 2 | 2 | 3 | -3 + 8 | 8 | eight | 2 | 2 | 2 | 4 + 8 | 8 | eight | 2 | 2 | 5 | -5 + 8 | 8 | eight | 2 | 2 | 5 | -5 + 8 | 8 | eight | 2 | 2 | 0 | + 8 | 8 | eight | 2 | 2 | | + 8 | 8 | eight | 2 | 2 | | 0 + 0 | | zero | 2 | 2 | 1 | -1 + 0 | | zero | 2 | 2 | 2 | 2 + 0 | | zero | 2 | 2 | 3 | -3 + 0 | | zero | 2 | 2 | 2 | 4 + 0 | | zero | 2 | 2 | 5 | -5 + 0 | | zero | 2 | 2 | 5 | -5 + 0 | | zero | 2 | 2 | 0 | + 0 | | zero | 2 | 2 | | + 0 | | zero | 2 | 2 | | 0 + | | null | 2 | 2 | 1 | -1 + | | null | 2 | 2 | 2 | 2 + | | null | 2 | 2 | 3 | -3 + | | null | 2 | 2 | 2 | 4 + | | null | 2 | 2 | 5 | -5 + | | null | 2 | 2 | 5 | -5 + | | null | 2 | 2 | 0 | + | | null | 2 | 2 | | + | | null | 2 | 2 | | 0 + | 0 | zero | 2 | 2 | 1 | -1 + | 0 | zero | 2 | 2 | 2 | 2 + | 0 | zero | 2 | 2 | 3 | -3 + | 0 | zero | 2 | 2 | 2 | 4 + | 0 | zero | 2 | 2 | 5 | -5 + | 0 | zero | 2 | 2 | 5 | -5 + | 0 | zero | 2 | 2 | 0 | + | 0 | zero | 2 | 2 | | + | 0 | zero | 2 | 2 | | 0 + 1 | 4 | one | 3 | -3 | 1 | -1 + 1 | 4 | one | 3 | -3 | 2 | 2 + 1 | 4 | one | 3 | -3 | 3 | -3 + 1 | 4 | one | 3 | -3 | 2 | 4 + 1 | 4 | one | 3 | -3 | 5 | -5 + 1 | 4 | one | 3 | -3 | 5 | -5 + 1 | 4 | one | 3 | -3 | 0 | + 1 | 4 | one | 3 | -3 | | + 1 | 4 | one | 3 | -3 | | 0 + 2 | 3 | two | 3 | -3 | 1 | -1 + 2 | 3 | two | 3 | -3 | 2 | 2 + 2 | 3 | two | 3 | -3 | 3 | -3 + 2 | 3 | two | 3 | -3 | 2 | 4 + 2 | 3 | two | 3 | -3 | 5 | -5 + 2 | 3 | two | 3 | -3 | 5 | -5 + 2 | 3 | two | 3 | -3 | 0 | + 2 | 3 | two | 3 | -3 | | + 2 | 3 | two | 3 | -3 | | 0 + 3 | 2 | three | 3 | -3 | 1 | -1 + 3 | 2 | three | 3 | -3 | 2 | 2 + 3 | 2 | three | 3 | -3 | 3 | -3 + 3 | 2 | three | 3 | -3 | 2 | 4 + 3 | 2 | three | 3 | -3 | 5 | -5 + 3 | 2 | three | 3 | -3 | 5 | -5 + 3 | 2 | three | 3 | -3 | 0 | + 3 | 2 | three | 3 | -3 | | + 3 | 2 | three | 3 | -3 | | 0 + 4 | 1 | four | 3 | -3 | 1 | -1 + 4 | 1 | four | 3 | -3 | 2 | 2 + 4 | 1 | four | 3 | -3 | 3 | -3 + 4 | 1 | four | 3 | -3 | 2 | 4 + 4 | 1 | four | 3 | -3 | 5 | -5 + 4 | 1 | four | 3 | -3 | 5 | -5 + 4 | 1 | four | 3 | -3 | 0 | + 4 | 1 | four | 3 | -3 | | + 4 | 1 | four | 3 | -3 | | 0 + 5 | 0 | five | 3 | -3 | 1 | -1 + 5 | 0 | five | 3 | -3 | 2 | 2 + 5 | 0 | five | 3 | -3 | 3 | -3 + 5 | 0 | five | 3 | -3 | 2 | 4 + 5 | 0 | five | 3 | -3 | 5 | -5 + 5 | 0 | five | 3 | -3 | 5 | -5 + 5 | 0 | five | 3 | -3 | 0 | + 5 | 0 | five | 3 | -3 | | + 5 | 0 | five | 3 | -3 | | 0 + 6 | 6 | six | 3 | -3 | 1 | -1 + 6 | 6 | six | 3 | -3 | 2 | 2 + 6 | 6 | six | 3 | -3 | 3 | -3 + 6 | 6 | six | 3 | -3 | 2 | 4 + 6 | 6 | six | 3 | -3 | 5 | -5 + 6 | 6 | six | 3 | -3 | 5 | -5 + 6 | 6 | six | 3 | -3 | 0 | + 6 | 6 | six | 3 | -3 | | + 6 | 6 | six | 3 | -3 | | 0 + 7 | 7 | seven | 3 | -3 | 1 | -1 + 7 | 7 | seven | 3 | -3 | 2 | 2 + 7 | 7 | seven | 3 | -3 | 3 | -3 + 7 | 7 | seven | 3 | -3 | 2 | 4 + 7 | 7 | seven | 3 | -3 | 5 | -5 + 7 | 7 | seven | 3 | -3 | 5 | -5 + 7 | 7 | seven | 3 | -3 | 0 | + 7 | 7 | seven | 3 | -3 | | + 7 | 7 | seven | 3 | -3 | | 0 + 8 | 8 | eight | 3 | -3 | 1 | -1 + 8 | 8 | eight | 3 | -3 | 2 | 2 + 8 | 8 | eight | 3 | -3 | 3 | -3 + 8 | 8 | eight | 3 | -3 | 2 | 4 + 8 | 8 | eight | 3 | -3 | 5 | -5 + 8 | 8 | eight | 3 | -3 | 5 | -5 + 8 | 8 | eight | 3 | -3 | 0 | + 8 | 8 | eight | 3 | -3 | | + 8 | 8 | eight | 3 | -3 | | 0 + 0 | | zero | 3 | -3 | 1 | -1 + 0 | | zero | 3 | -3 | 2 | 2 + 0 | | zero | 3 | -3 | 3 | -3 + 0 | | zero | 3 | -3 | 2 | 4 + 0 | | zero | 3 | -3 | 5 | -5 + 0 | | zero | 3 | -3 | 5 | -5 + 0 | | zero | 3 | -3 | 0 | + 0 | | zero | 3 | -3 | | + 0 | | zero | 3 | -3 | | 0 + | | null | 3 | -3 | 1 | -1 + | | null | 3 | -3 | 2 | 2 + | | null | 3 | -3 | 3 | -3 + | | null | 3 | -3 | 2 | 4 + | | null | 3 | -3 | 5 | -5 + | | null | 3 | -3 | 5 | -5 + | | null | 3 | -3 | 0 | + | | null | 3 | -3 | | + | | null | 3 | -3 | | 0 + | 0 | zero | 3 | -3 | 1 | -1 + | 0 | zero | 3 | -3 | 2 | 2 + | 0 | zero | 3 | -3 | 3 | -3 + | 0 | zero | 3 | -3 | 2 | 4 + | 0 | zero | 3 | -3 | 5 | -5 + | 0 | zero | 3 | -3 | 5 | -5 + | 0 | zero | 3 | -3 | 0 | + | 0 | zero | 3 | -3 | | + | 0 | zero | 3 | -3 | | 0 + 1 | 4 | one | 2 | 4 | 1 | -1 + 1 | 4 | one | 2 | 4 | 2 | 2 + 1 | 4 | one | 2 | 4 | 3 | -3 + 1 | 4 | one | 2 | 4 | 2 | 4 + 1 | 4 | one | 2 | 4 | 5 | -5 + 1 | 4 | one | 2 | 4 | 5 | -5 + 1 | 4 | one | 2 | 4 | 0 | + 1 | 4 | one | 2 | 4 | | + 1 | 4 | one | 2 | 4 | | 0 + 2 | 3 | two | 2 | 4 | 1 | -1 + 2 | 3 | two | 2 | 4 | 2 | 2 + 2 | 3 | two | 2 | 4 | 3 | -3 + 2 | 3 | two | 2 | 4 | 2 | 4 + 2 | 3 | two | 2 | 4 | 5 | -5 + 2 | 3 | two | 2 | 4 | 5 | -5 + 2 | 3 | two | 2 | 4 | 0 | + 2 | 3 | two | 2 | 4 | | + 2 | 3 | two | 2 | 4 | | 0 + 3 | 2 | three | 2 | 4 | 1 | -1 + 3 | 2 | three | 2 | 4 | 2 | 2 + 3 | 2 | three | 2 | 4 | 3 | -3 + 3 | 2 | three | 2 | 4 | 2 | 4 + 3 | 2 | three | 2 | 4 | 5 | -5 + 3 | 2 | three | 2 | 4 | 5 | -5 + 3 | 2 | three | 2 | 4 | 0 | + 3 | 2 | three | 2 | 4 | | + 3 | 2 | three | 2 | 4 | | 0 + 4 | 1 | four | 2 | 4 | 1 | -1 + 4 | 1 | four | 2 | 4 | 2 | 2 + 4 | 1 | four | 2 | 4 | 3 | -3 + 4 | 1 | four | 2 | 4 | 2 | 4 + 4 | 1 | four | 2 | 4 | 5 | -5 + 4 | 1 | four | 2 | 4 | 5 | -5 + 4 | 1 | four | 2 | 4 | 0 | + 4 | 1 | four | 2 | 4 | | + 4 | 1 | four | 2 | 4 | | 0 + 5 | 0 | five | 2 | 4 | 1 | -1 + 5 | 0 | five | 2 | 4 | 2 | 2 + 5 | 0 | five | 2 | 4 | 3 | -3 + 5 | 0 | five | 2 | 4 | 2 | 4 + 5 | 0 | five | 2 | 4 | 5 | -5 + 5 | 0 | five | 2 | 4 | 5 | -5 + 5 | 0 | five | 2 | 4 | 0 | + 5 | 0 | five | 2 | 4 | | + 5 | 0 | five | 2 | 4 | | 0 + 6 | 6 | six | 2 | 4 | 1 | -1 + 6 | 6 | six | 2 | 4 | 2 | 2 + 6 | 6 | six | 2 | 4 | 3 | -3 + 6 | 6 | six | 2 | 4 | 2 | 4 + 6 | 6 | six | 2 | 4 | 5 | -5 + 6 | 6 | six | 2 | 4 | 5 | -5 + 6 | 6 | six | 2 | 4 | 0 | + 6 | 6 | six | 2 | 4 | | + 6 | 6 | six | 2 | 4 | | 0 + 7 | 7 | seven | 2 | 4 | 1 | -1 + 7 | 7 | seven | 2 | 4 | 2 | 2 + 7 | 7 | seven | 2 | 4 | 3 | -3 + 7 | 7 | seven | 2 | 4 | 2 | 4 + 7 | 7 | seven | 2 | 4 | 5 | -5 + 7 | 7 | seven | 2 | 4 | 5 | -5 + 7 | 7 | seven | 2 | 4 | 0 | + 7 | 7 | seven | 2 | 4 | | + 7 | 7 | seven | 2 | 4 | | 0 + 8 | 8 | eight | 2 | 4 | 1 | -1 + 8 | 8 | eight | 2 | 4 | 2 | 2 + 8 | 8 | eight | 2 | 4 | 3 | -3 + 8 | 8 | eight | 2 | 4 | 2 | 4 + 8 | 8 | eight | 2 | 4 | 5 | -5 + 8 | 8 | eight | 2 | 4 | 5 | -5 + 8 | 8 | eight | 2 | 4 | 0 | + 8 | 8 | eight | 2 | 4 | | + 8 | 8 | eight | 2 | 4 | | 0 + 0 | | zero | 2 | 4 | 1 | -1 + 0 | | zero | 2 | 4 | 2 | 2 + 0 | | zero | 2 | 4 | 3 | -3 + 0 | | zero | 2 | 4 | 2 | 4 + 0 | | zero | 2 | 4 | 5 | -5 + 0 | | zero | 2 | 4 | 5 | -5 + 0 | | zero | 2 | 4 | 0 | + 0 | | zero | 2 | 4 | | + 0 | | zero | 2 | 4 | | 0 + | | null | 2 | 4 | 1 | -1 + | | null | 2 | 4 | 2 | 2 + | | null | 2 | 4 | 3 | -3 + | | null | 2 | 4 | 2 | 4 + | | null | 2 | 4 | 5 | -5 + | | null | 2 | 4 | 5 | -5 + | | null | 2 | 4 | 0 | + | | null | 2 | 4 | | + | | null | 2 | 4 | | 0 + | 0 | zero | 2 | 4 | 1 | -1 + | 0 | zero | 2 | 4 | 2 | 2 + | 0 | zero | 2 | 4 | 3 | -3 + | 0 | zero | 2 | 4 | 2 | 4 + | 0 | zero | 2 | 4 | 5 | -5 + | 0 | zero | 2 | 4 | 5 | -5 + | 0 | zero | 2 | 4 | 0 | + | 0 | zero | 2 | 4 | | + | 0 | zero | 2 | 4 | | 0 + 1 | 4 | one | 5 | -5 | 1 | -1 + 1 | 4 | one | 5 | -5 | 2 | 2 + 1 | 4 | one | 5 | -5 | 3 | -3 + 1 | 4 | one | 5 | -5 | 2 | 4 + 1 | 4 | one | 5 | -5 | 5 | -5 + 1 | 4 | one | 5 | -5 | 5 | -5 + 1 | 4 | one | 5 | -5 | 0 | + 1 | 4 | one | 5 | -5 | | + 1 | 4 | one | 5 | -5 | | 0 + 2 | 3 | two | 5 | -5 | 1 | -1 + 2 | 3 | two | 5 | -5 | 2 | 2 + 2 | 3 | two | 5 | -5 | 3 | -3 + 2 | 3 | two | 5 | -5 | 2 | 4 + 2 | 3 | two | 5 | -5 | 5 | -5 + 2 | 3 | two | 5 | -5 | 5 | -5 + 2 | 3 | two | 5 | -5 | 0 | + 2 | 3 | two | 5 | -5 | | + 2 | 3 | two | 5 | -5 | | 0 + 3 | 2 | three | 5 | -5 | 1 | -1 + 3 | 2 | three | 5 | -5 | 2 | 2 + 3 | 2 | three | 5 | -5 | 3 | -3 + 3 | 2 | three | 5 | -5 | 2 | 4 + 3 | 2 | three | 5 | -5 | 5 | -5 + 3 | 2 | three | 5 | -5 | 5 | -5 + 3 | 2 | three | 5 | -5 | 0 | + 3 | 2 | three | 5 | -5 | | + 3 | 2 | three | 5 | -5 | | 0 + 4 | 1 | four | 5 | -5 | 1 | -1 + 4 | 1 | four | 5 | -5 | 2 | 2 + 4 | 1 | four | 5 | -5 | 3 | -3 + 4 | 1 | four | 5 | -5 | 2 | 4 + 4 | 1 | four | 5 | -5 | 5 | -5 + 4 | 1 | four | 5 | -5 | 5 | -5 + 4 | 1 | four | 5 | -5 | 0 | + 4 | 1 | four | 5 | -5 | | + 4 | 1 | four | 5 | -5 | | 0 + 5 | 0 | five | 5 | -5 | 1 | -1 + 5 | 0 | five | 5 | -5 | 2 | 2 + 5 | 0 | five | 5 | -5 | 3 | -3 + 5 | 0 | five | 5 | -5 | 2 | 4 + 5 | 0 | five | 5 | -5 | 5 | -5 + 5 | 0 | five | 5 | -5 | 5 | -5 + 5 | 0 | five | 5 | -5 | 0 | + 5 | 0 | five | 5 | -5 | | + 5 | 0 | five | 5 | -5 | | 0 + 6 | 6 | six | 5 | -5 | 1 | -1 + 6 | 6 | six | 5 | -5 | 2 | 2 + 6 | 6 | six | 5 | -5 | 3 | -3 + 6 | 6 | six | 5 | -5 | 2 | 4 + 6 | 6 | six | 5 | -5 | 5 | -5 + 6 | 6 | six | 5 | -5 | 5 | -5 + 6 | 6 | six | 5 | -5 | 0 | + 6 | 6 | six | 5 | -5 | | + 6 | 6 | six | 5 | -5 | | 0 + 7 | 7 | seven | 5 | -5 | 1 | -1 + 7 | 7 | seven | 5 | -5 | 2 | 2 + 7 | 7 | seven | 5 | -5 | 3 | -3 + 7 | 7 | seven | 5 | -5 | 2 | 4 + 7 | 7 | seven | 5 | -5 | 5 | -5 + 7 | 7 | seven | 5 | -5 | 5 | -5 + 7 | 7 | seven | 5 | -5 | 0 | + 7 | 7 | seven | 5 | -5 | | + 7 | 7 | seven | 5 | -5 | | 0 + 8 | 8 | eight | 5 | -5 | 1 | -1 + 8 | 8 | eight | 5 | -5 | 2 | 2 + 8 | 8 | eight | 5 | -5 | 3 | -3 + 8 | 8 | eight | 5 | -5 | 2 | 4 + 8 | 8 | eight | 5 | -5 | 5 | -5 + 8 | 8 | eight | 5 | -5 | 5 | -5 + 8 | 8 | eight | 5 | -5 | 0 | + 8 | 8 | eight | 5 | -5 | | + 8 | 8 | eight | 5 | -5 | | 0 + 0 | | zero | 5 | -5 | 1 | -1 + 0 | | zero | 5 | -5 | 2 | 2 + 0 | | zero | 5 | -5 | 3 | -3 + 0 | | zero | 5 | -5 | 2 | 4 + 0 | | zero | 5 | -5 | 5 | -5 + 0 | | zero | 5 | -5 | 5 | -5 + 0 | | zero | 5 | -5 | 0 | + 0 | | zero | 5 | -5 | | + 0 | | zero | 5 | -5 | | 0 + | | null | 5 | -5 | 1 | -1 + | | null | 5 | -5 | 2 | 2 + | | null | 5 | -5 | 3 | -3 + | | null | 5 | -5 | 2 | 4 + | | null | 5 | -5 | 5 | -5 + | | null | 5 | -5 | 5 | -5 + | | null | 5 | -5 | 0 | + | | null | 5 | -5 | | + | | null | 5 | -5 | | 0 + | 0 | zero | 5 | -5 | 1 | -1 + | 0 | zero | 5 | -5 | 2 | 2 + | 0 | zero | 5 | -5 | 3 | -3 + | 0 | zero | 5 | -5 | 2 | 4 + | 0 | zero | 5 | -5 | 5 | -5 + | 0 | zero | 5 | -5 | 5 | -5 + | 0 | zero | 5 | -5 | 0 | + | 0 | zero | 5 | -5 | | + | 0 | zero | 5 | -5 | | 0 + 1 | 4 | one | 5 | -5 | 1 | -1 + 1 | 4 | one | 5 | -5 | 2 | 2 + 1 | 4 | one | 5 | -5 | 3 | -3 + 1 | 4 | one | 5 | -5 | 2 | 4 + 1 | 4 | one | 5 | -5 | 5 | -5 + 1 | 4 | one | 5 | -5 | 5 | -5 + 1 | 4 | one | 5 | -5 | 0 | + 1 | 4 | one | 5 | -5 | | + 1 | 4 | one | 5 | -5 | | 0 + 2 | 3 | two | 5 | -5 | 1 | -1 + 2 | 3 | two | 5 | -5 | 2 | 2 + 2 | 3 | two | 5 | -5 | 3 | -3 + 2 | 3 | two | 5 | -5 | 2 | 4 + 2 | 3 | two | 5 | -5 | 5 | -5 + 2 | 3 | two | 5 | -5 | 5 | -5 + 2 | 3 | two | 5 | -5 | 0 | + 2 | 3 | two | 5 | -5 | | + 2 | 3 | two | 5 | -5 | | 0 + 3 | 2 | three | 5 | -5 | 1 | -1 + 3 | 2 | three | 5 | -5 | 2 | 2 + 3 | 2 | three | 5 | -5 | 3 | -3 + 3 | 2 | three | 5 | -5 | 2 | 4 + 3 | 2 | three | 5 | -5 | 5 | -5 + 3 | 2 | three | 5 | -5 | 5 | -5 + 3 | 2 | three | 5 | -5 | 0 | + 3 | 2 | three | 5 | -5 | | + 3 | 2 | three | 5 | -5 | | 0 + 4 | 1 | four | 5 | -5 | 1 | -1 + 4 | 1 | four | 5 | -5 | 2 | 2 + 4 | 1 | four | 5 | -5 | 3 | -3 + 4 | 1 | four | 5 | -5 | 2 | 4 + 4 | 1 | four | 5 | -5 | 5 | -5 + 4 | 1 | four | 5 | -5 | 5 | -5 + 4 | 1 | four | 5 | -5 | 0 | + 4 | 1 | four | 5 | -5 | | + 4 | 1 | four | 5 | -5 | | 0 + 5 | 0 | five | 5 | -5 | 1 | -1 + 5 | 0 | five | 5 | -5 | 2 | 2 + 5 | 0 | five | 5 | -5 | 3 | -3 + 5 | 0 | five | 5 | -5 | 2 | 4 + 5 | 0 | five | 5 | -5 | 5 | -5 + 5 | 0 | five | 5 | -5 | 5 | -5 + 5 | 0 | five | 5 | -5 | 0 | + 5 | 0 | five | 5 | -5 | | + 5 | 0 | five | 5 | -5 | | 0 + 6 | 6 | six | 5 | -5 | 1 | -1 + 6 | 6 | six | 5 | -5 | 2 | 2 + 6 | 6 | six | 5 | -5 | 3 | -3 + 6 | 6 | six | 5 | -5 | 2 | 4 + 6 | 6 | six | 5 | -5 | 5 | -5 + 6 | 6 | six | 5 | -5 | 5 | -5 + 6 | 6 | six | 5 | -5 | 0 | + 6 | 6 | six | 5 | -5 | | + 6 | 6 | six | 5 | -5 | | 0 + 7 | 7 | seven | 5 | -5 | 1 | -1 + 7 | 7 | seven | 5 | -5 | 2 | 2 + 7 | 7 | seven | 5 | -5 | 3 | -3 + 7 | 7 | seven | 5 | -5 | 2 | 4 + 7 | 7 | seven | 5 | -5 | 5 | -5 + 7 | 7 | seven | 5 | -5 | 5 | -5 + 7 | 7 | seven | 5 | -5 | 0 | + 7 | 7 | seven | 5 | -5 | | + 7 | 7 | seven | 5 | -5 | | 0 + 8 | 8 | eight | 5 | -5 | 1 | -1 + 8 | 8 | eight | 5 | -5 | 2 | 2 + 8 | 8 | eight | 5 | -5 | 3 | -3 + 8 | 8 | eight | 5 | -5 | 2 | 4 + 8 | 8 | eight | 5 | -5 | 5 | -5 + 8 | 8 | eight | 5 | -5 | 5 | -5 + 8 | 8 | eight | 5 | -5 | 0 | + 8 | 8 | eight | 5 | -5 | | + 8 | 8 | eight | 5 | -5 | | 0 + 0 | | zero | 5 | -5 | 1 | -1 + 0 | | zero | 5 | -5 | 2 | 2 + 0 | | zero | 5 | -5 | 3 | -3 + 0 | | zero | 5 | -5 | 2 | 4 + 0 | | zero | 5 | -5 | 5 | -5 + 0 | | zero | 5 | -5 | 5 | -5 + 0 | | zero | 5 | -5 | 0 | + 0 | | zero | 5 | -5 | | + 0 | | zero | 5 | -5 | | 0 + | | null | 5 | -5 | 1 | -1 + | | null | 5 | -5 | 2 | 2 + | | null | 5 | -5 | 3 | -3 + | | null | 5 | -5 | 2 | 4 + | | null | 5 | -5 | 5 | -5 + | | null | 5 | -5 | 5 | -5 + | | null | 5 | -5 | 0 | + | | null | 5 | -5 | | + | | null | 5 | -5 | | 0 + | 0 | zero | 5 | -5 | 1 | -1 + | 0 | zero | 5 | -5 | 2 | 2 + | 0 | zero | 5 | -5 | 3 | -3 + | 0 | zero | 5 | -5 | 2 | 4 + | 0 | zero | 5 | -5 | 5 | -5 + | 0 | zero | 5 | -5 | 5 | -5 + | 0 | zero | 5 | -5 | 0 | + | 0 | zero | 5 | -5 | | + | 0 | zero | 5 | -5 | | 0 + 1 | 4 | one | 0 | | 1 | -1 + 1 | 4 | one | 0 | | 2 | 2 + 1 | 4 | one | 0 | | 3 | -3 + 1 | 4 | one | 0 | | 2 | 4 + 1 | 4 | one | 0 | | 5 | -5 + 1 | 4 | one | 0 | | 5 | -5 + 1 | 4 | one | 0 | | 0 | + 1 | 4 | one | 0 | | | + 1 | 4 | one | 0 | | | 0 + 2 | 3 | two | 0 | | 1 | -1 + 2 | 3 | two | 0 | | 2 | 2 + 2 | 3 | two | 0 | | 3 | -3 + 2 | 3 | two | 0 | | 2 | 4 + 2 | 3 | two | 0 | | 5 | -5 + 2 | 3 | two | 0 | | 5 | -5 + 2 | 3 | two | 0 | | 0 | + 2 | 3 | two | 0 | | | + 2 | 3 | two | 0 | | | 0 + 3 | 2 | three | 0 | | 1 | -1 + 3 | 2 | three | 0 | | 2 | 2 + 3 | 2 | three | 0 | | 3 | -3 + 3 | 2 | three | 0 | | 2 | 4 + 3 | 2 | three | 0 | | 5 | -5 + 3 | 2 | three | 0 | | 5 | -5 + 3 | 2 | three | 0 | | 0 | + 3 | 2 | three | 0 | | | + 3 | 2 | three | 0 | | | 0 + 4 | 1 | four | 0 | | 1 | -1 + 4 | 1 | four | 0 | | 2 | 2 + 4 | 1 | four | 0 | | 3 | -3 + 4 | 1 | four | 0 | | 2 | 4 + 4 | 1 | four | 0 | | 5 | -5 + 4 | 1 | four | 0 | | 5 | -5 + 4 | 1 | four | 0 | | 0 | + 4 | 1 | four | 0 | | | + 4 | 1 | four | 0 | | | 0 + 5 | 0 | five | 0 | | 1 | -1 + 5 | 0 | five | 0 | | 2 | 2 + 5 | 0 | five | 0 | | 3 | -3 + 5 | 0 | five | 0 | | 2 | 4 + 5 | 0 | five | 0 | | 5 | -5 + 5 | 0 | five | 0 | | 5 | -5 + 5 | 0 | five | 0 | | 0 | + 5 | 0 | five | 0 | | | + 5 | 0 | five | 0 | | | 0 + 6 | 6 | six | 0 | | 1 | -1 + 6 | 6 | six | 0 | | 2 | 2 + 6 | 6 | six | 0 | | 3 | -3 + 6 | 6 | six | 0 | | 2 | 4 + 6 | 6 | six | 0 | | 5 | -5 + 6 | 6 | six | 0 | | 5 | -5 + 6 | 6 | six | 0 | | 0 | + 6 | 6 | six | 0 | | | + 6 | 6 | six | 0 | | | 0 + 7 | 7 | seven | 0 | | 1 | -1 + 7 | 7 | seven | 0 | | 2 | 2 + 7 | 7 | seven | 0 | | 3 | -3 + 7 | 7 | seven | 0 | | 2 | 4 + 7 | 7 | seven | 0 | | 5 | -5 + 7 | 7 | seven | 0 | | 5 | -5 + 7 | 7 | seven | 0 | | 0 | + 7 | 7 | seven | 0 | | | + 7 | 7 | seven | 0 | | | 0 + 8 | 8 | eight | 0 | | 1 | -1 + 8 | 8 | eight | 0 | | 2 | 2 + 8 | 8 | eight | 0 | | 3 | -3 + 8 | 8 | eight | 0 | | 2 | 4 + 8 | 8 | eight | 0 | | 5 | -5 + 8 | 8 | eight | 0 | | 5 | -5 + 8 | 8 | eight | 0 | | 0 | + 8 | 8 | eight | 0 | | | + 8 | 8 | eight | 0 | | | 0 + 0 | | zero | 0 | | 1 | -1 + 0 | | zero | 0 | | 2 | 2 + 0 | | zero | 0 | | 3 | -3 + 0 | | zero | 0 | | 2 | 4 + 0 | | zero | 0 | | 5 | -5 + 0 | | zero | 0 | | 5 | -5 + 0 | | zero | 0 | | 0 | + 0 | | zero | 0 | | | + 0 | | zero | 0 | | | 0 + | | null | 0 | | 1 | -1 + | | null | 0 | | 2 | 2 + | | null | 0 | | 3 | -3 + | | null | 0 | | 2 | 4 + | | null | 0 | | 5 | -5 + | | null | 0 | | 5 | -5 + | | null | 0 | | 0 | + | | null | 0 | | | + | | null | 0 | | | 0 + | 0 | zero | 0 | | 1 | -1 + | 0 | zero | 0 | | 2 | 2 + | 0 | zero | 0 | | 3 | -3 + | 0 | zero | 0 | | 2 | 4 + | 0 | zero | 0 | | 5 | -5 + | 0 | zero | 0 | | 5 | -5 + | 0 | zero | 0 | | 0 | + | 0 | zero | 0 | | | + | 0 | zero | 0 | | | 0 + 1 | 4 | one | | | 1 | -1 + 1 | 4 | one | | | 2 | 2 + 1 | 4 | one | | | 3 | -3 + 1 | 4 | one | | | 2 | 4 + 1 | 4 | one | | | 5 | -5 + 1 | 4 | one | | | 5 | -5 + 1 | 4 | one | | | 0 | + 1 | 4 | one | | | | + 1 | 4 | one | | | | 0 + 2 | 3 | two | | | 1 | -1 + 2 | 3 | two | | | 2 | 2 + 2 | 3 | two | | | 3 | -3 + 2 | 3 | two | | | 2 | 4 + 2 | 3 | two | | | 5 | -5 + 2 | 3 | two | | | 5 | -5 + 2 | 3 | two | | | 0 | + 2 | 3 | two | | | | + 2 | 3 | two | | | | 0 + 3 | 2 | three | | | 1 | -1 + 3 | 2 | three | | | 2 | 2 + 3 | 2 | three | | | 3 | -3 + 3 | 2 | three | | | 2 | 4 + 3 | 2 | three | | | 5 | -5 + 3 | 2 | three | | | 5 | -5 + 3 | 2 | three | | | 0 | + 3 | 2 | three | | | | + 3 | 2 | three | | | | 0 + 4 | 1 | four | | | 1 | -1 + 4 | 1 | four | | | 2 | 2 + 4 | 1 | four | | | 3 | -3 + 4 | 1 | four | | | 2 | 4 + 4 | 1 | four | | | 5 | -5 + 4 | 1 | four | | | 5 | -5 + 4 | 1 | four | | | 0 | + 4 | 1 | four | | | | + 4 | 1 | four | | | | 0 + 5 | 0 | five | | | 1 | -1 + 5 | 0 | five | | | 2 | 2 + 5 | 0 | five | | | 3 | -3 + 5 | 0 | five | | | 2 | 4 + 5 | 0 | five | | | 5 | -5 + 5 | 0 | five | | | 5 | -5 + 5 | 0 | five | | | 0 | + 5 | 0 | five | | | | + 5 | 0 | five | | | | 0 + 6 | 6 | six | | | 1 | -1 + 6 | 6 | six | | | 2 | 2 + 6 | 6 | six | | | 3 | -3 + 6 | 6 | six | | | 2 | 4 + 6 | 6 | six | | | 5 | -5 + 6 | 6 | six | | | 5 | -5 + 6 | 6 | six | | | 0 | + 6 | 6 | six | | | | + 6 | 6 | six | | | | 0 + 7 | 7 | seven | | | 1 | -1 + 7 | 7 | seven | | | 2 | 2 + 7 | 7 | seven | | | 3 | -3 + 7 | 7 | seven | | | 2 | 4 + 7 | 7 | seven | | | 5 | -5 + 7 | 7 | seven | | | 5 | -5 + 7 | 7 | seven | | | 0 | + 7 | 7 | seven | | | | + 7 | 7 | seven | | | | 0 + 8 | 8 | eight | | | 1 | -1 + 8 | 8 | eight | | | 2 | 2 + 8 | 8 | eight | | | 3 | -3 + 8 | 8 | eight | | | 2 | 4 + 8 | 8 | eight | | | 5 | -5 + 8 | 8 | eight | | | 5 | -5 + 8 | 8 | eight | | | 0 | + 8 | 8 | eight | | | | + 8 | 8 | eight | | | | 0 + 0 | | zero | | | 1 | -1 + 0 | | zero | | | 2 | 2 + 0 | | zero | | | 3 | -3 + 0 | | zero | | | 2 | 4 + 0 | | zero | | | 5 | -5 + 0 | | zero | | | 5 | -5 + 0 | | zero | | | 0 | + 0 | | zero | | | | + 0 | | zero | | | | 0 + | | null | | | 1 | -1 + | | null | | | 2 | 2 + | | null | | | 3 | -3 + | | null | | | 2 | 4 + | | null | | | 5 | -5 + | | null | | | 5 | -5 + | | null | | | 0 | + | | null | | | | + | | null | | | | 0 + | 0 | zero | | | 1 | -1 + | 0 | zero | | | 2 | 2 + | 0 | zero | | | 3 | -3 + | 0 | zero | | | 2 | 4 + | 0 | zero | | | 5 | -5 + | 0 | zero | | | 5 | -5 + | 0 | zero | | | 0 | + | 0 | zero | | | | + | 0 | zero | | | | 0 + 1 | 4 | one | | 0 | 1 | -1 + 1 | 4 | one | | 0 | 2 | 2 + 1 | 4 | one | | 0 | 3 | -3 + 1 | 4 | one | | 0 | 2 | 4 + 1 | 4 | one | | 0 | 5 | -5 + 1 | 4 | one | | 0 | 5 | -5 + 1 | 4 | one | | 0 | 0 | + 1 | 4 | one | | 0 | | + 1 | 4 | one | | 0 | | 0 + 2 | 3 | two | | 0 | 1 | -1 + 2 | 3 | two | | 0 | 2 | 2 + 2 | 3 | two | | 0 | 3 | -3 + 2 | 3 | two | | 0 | 2 | 4 + 2 | 3 | two | | 0 | 5 | -5 + 2 | 3 | two | | 0 | 5 | -5 + 2 | 3 | two | | 0 | 0 | + 2 | 3 | two | | 0 | | + 2 | 3 | two | | 0 | | 0 + 3 | 2 | three | | 0 | 1 | -1 + 3 | 2 | three | | 0 | 2 | 2 + 3 | 2 | three | | 0 | 3 | -3 + 3 | 2 | three | | 0 | 2 | 4 + 3 | 2 | three | | 0 | 5 | -5 + 3 | 2 | three | | 0 | 5 | -5 + 3 | 2 | three | | 0 | 0 | + 3 | 2 | three | | 0 | | + 3 | 2 | three | | 0 | | 0 + 4 | 1 | four | | 0 | 1 | -1 + 4 | 1 | four | | 0 | 2 | 2 + 4 | 1 | four | | 0 | 3 | -3 + 4 | 1 | four | | 0 | 2 | 4 + 4 | 1 | four | | 0 | 5 | -5 + 4 | 1 | four | | 0 | 5 | -5 + 4 | 1 | four | | 0 | 0 | + 4 | 1 | four | | 0 | | + 4 | 1 | four | | 0 | | 0 + 5 | 0 | five | | 0 | 1 | -1 + 5 | 0 | five | | 0 | 2 | 2 + 5 | 0 | five | | 0 | 3 | -3 + 5 | 0 | five | | 0 | 2 | 4 + 5 | 0 | five | | 0 | 5 | -5 + 5 | 0 | five | | 0 | 5 | -5 + 5 | 0 | five | | 0 | 0 | + 5 | 0 | five | | 0 | | + 5 | 0 | five | | 0 | | 0 + 6 | 6 | six | | 0 | 1 | -1 + 6 | 6 | six | | 0 | 2 | 2 + 6 | 6 | six | | 0 | 3 | -3 + 6 | 6 | six | | 0 | 2 | 4 + 6 | 6 | six | | 0 | 5 | -5 + 6 | 6 | six | | 0 | 5 | -5 + 6 | 6 | six | | 0 | 0 | + 6 | 6 | six | | 0 | | + 6 | 6 | six | | 0 | | 0 + 7 | 7 | seven | | 0 | 1 | -1 + 7 | 7 | seven | | 0 | 2 | 2 + 7 | 7 | seven | | 0 | 3 | -3 + 7 | 7 | seven | | 0 | 2 | 4 + 7 | 7 | seven | | 0 | 5 | -5 + 7 | 7 | seven | | 0 | 5 | -5 + 7 | 7 | seven | | 0 | 0 | + 7 | 7 | seven | | 0 | | + 7 | 7 | seven | | 0 | | 0 + 8 | 8 | eight | | 0 | 1 | -1 + 8 | 8 | eight | | 0 | 2 | 2 + 8 | 8 | eight | | 0 | 3 | -3 + 8 | 8 | eight | | 0 | 2 | 4 + 8 | 8 | eight | | 0 | 5 | -5 + 8 | 8 | eight | | 0 | 5 | -5 + 8 | 8 | eight | | 0 | 0 | + 8 | 8 | eight | | 0 | | + 8 | 8 | eight | | 0 | | 0 + 0 | | zero | | 0 | 1 | -1 + 0 | | zero | | 0 | 2 | 2 + 0 | | zero | | 0 | 3 | -3 + 0 | | zero | | 0 | 2 | 4 + 0 | | zero | | 0 | 5 | -5 + 0 | | zero | | 0 | 5 | -5 + 0 | | zero | | 0 | 0 | + 0 | | zero | | 0 | | + 0 | | zero | | 0 | | 0 + | | null | | 0 | 1 | -1 + | | null | | 0 | 2 | 2 + | | null | | 0 | 3 | -3 + | | null | | 0 | 2 | 4 + | | null | | 0 | 5 | -5 + | | null | | 0 | 5 | -5 + | | null | | 0 | 0 | + | | null | | 0 | | + | | null | | 0 | | 0 + | 0 | zero | | 0 | 1 | -1 + | 0 | zero | | 0 | 2 | 2 + | 0 | zero | | 0 | 3 | -3 + | 0 | zero | | 0 | 2 | 4 + | 0 | zero | | 0 | 5 | -5 + | 0 | zero | | 0 | 5 | -5 + | 0 | zero | | 0 | 0 | + | 0 | zero | | 0 | | + | 0 | zero | | 0 | | 0 +(891 rows) + +-- +-- +-- Inner joins (equi-joins) +-- +-- +-- +-- Inner joins (equi-joins) with USING clause +-- The USING syntax changes the shape of the resulting table +-- by including a column in the USING clause only once in the result. +-- +-- Inner equi-join on specified column +--Testcase 33: +SELECT * + FROM J1_TBL INNER JOIN J2_TBL USING (i); + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +-- Same as above, slightly different syntax +--Testcase 34: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i); + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +--Testcase 35: +SELECT * + FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a) + ORDER BY a, d; + a | b | c | d +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +--Testcase 36: +SELECT * + FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, b) USING (b) + ORDER BY b, t1.a; + b | a | c | a +---+---+-------+--- + 0 | 5 | five | + 0 | | zero | + 2 | 3 | three | 2 + 4 | 1 | one | 2 +(4 rows) + +-- test join using aliases +--Testcase 489: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) WHERE J1_TBL.t = 'one'; -- ok + i | j | t | k +---+---+-----+---- + 1 | 4 | one | -1 +(1 row) + +--Testcase 490: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; -- ok + i | j | t | k +---+---+-----+---- + 1 | 4 | one | -1 +(1 row) + +--Testcase 491: +SELECT * + FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t = 'one'; -- error +ERROR: invalid reference to FROM-clause entry for table "j1_tbl" +LINE 2: FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t = ... + ^ +DETAIL: There is an entry for table "j1_tbl", but it cannot be referenced from this part of the query. +--Testcase 492: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.i = 1; -- ok + i | j | t | k +---+---+-----+---- + 1 | 4 | one | -1 +(1 row) + +--Testcase 493: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one'; -- error +ERROR: column x.t does not exist +LINE 2: FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one'; + ^ +--Testcase 494: +SELECT * + FROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1; -- error (XXX could use better hint) +ERROR: missing FROM-clause entry for table "x" +LINE 2: ...ROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1; + ^ +--Testcase 495: +SELECT * + FROM J1_TBL a1 JOIN J2_TBL a2 USING (i) AS a1; -- error +ERROR: table name "a1" specified more than once +--Testcase 496: +SELECT x.* + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; + i +--- + 1 +(1 row) + +--Testcase 497: +SELECT ROW(x.*) + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; + row +----- + (1) +(1 row) + +--Testcase 498: +SELECT row_to_json(x.*) + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; + row_to_json +------------- + {"i":1} +(1 row) + +-- +-- NATURAL JOIN +-- Inner equi-join on all columns with the same name +-- +--Testcase 37: +SELECT * + FROM J1_TBL NATURAL JOIN J2_TBL; + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +--Testcase 38: +SELECT * + FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (a, d); + a | b | c | d +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +--Testcase 39: +SELECT * + FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (d, a); + a | b | c | d +---+---+------+--- + 0 | | zero | + 2 | 3 | two | 2 + 4 | 1 | four | 2 +(3 rows) + +-- mismatch number of columns +-- currently, Postgres will fill in with underlying names +--Testcase 40: +SELECT * + FROM J1_TBL t1 (a, b) NATURAL JOIN J2_TBL t2 (a); + a | b | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 +(7 rows) + +-- +-- Inner joins (equi-joins) +-- +--Testcase 41: +SELECT * + FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i); + i | j | t | i | k +---+---+-------+---+---- + 0 | | zero | 0 | + 1 | 4 | one | 1 | -1 + 2 | 3 | two | 2 | 2 + 2 | 3 | two | 2 | 4 + 3 | 2 | three | 3 | -3 + 5 | 0 | five | 5 | -5 + 5 | 0 | five | 5 | -5 +(7 rows) + +--Testcase 42: +SELECT * + FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k); + i | j | t | i | k +---+---+------+---+--- + 0 | | zero | | 0 + 2 | 3 | two | 2 | 2 + 4 | 1 | four | 2 | 4 +(3 rows) + +-- +-- Non-equi-joins +-- +--Testcase 43: +SELECT * + FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k); + i | j | t | i | k +---+---+-------+---+--- + 1 | 4 | one | 2 | 2 + 2 | 3 | two | 2 | 2 + 0 | | zero | 2 | 2 + 1 | 4 | one | 2 | 4 + 2 | 3 | two | 2 | 4 + 3 | 2 | three | 2 | 4 + 4 | 1 | four | 2 | 4 + 0 | | zero | 2 | 4 + 0 | | zero | | 0 +(9 rows) + +-- +-- Outer joins +-- Note that OUTER is a noise word +-- +--Testcase 44: +SELECT * + FROM J1_TBL LEFT OUTER JOIN J2_TBL USING (i) + ORDER BY i, k, t; + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 4 | 1 | four | + 5 | 0 | five | -5 + 5 | 0 | five | -5 + 6 | 6 | six | + 7 | 7 | seven | + 8 | 8 | eight | + | | null | + | 0 | zero | +(13 rows) + +--Testcase 45: +SELECT * + FROM J1_TBL LEFT JOIN J2_TBL USING (i) + ORDER BY i, k, t; + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 4 | 1 | four | + 5 | 0 | five | -5 + 5 | 0 | five | -5 + 6 | 6 | six | + 7 | 7 | seven | + 8 | 8 | eight | + | | null | + | 0 | zero | +(13 rows) + +--Testcase 46: +SELECT * + FROM J1_TBL RIGHT OUTER JOIN J2_TBL USING (i); + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 + | | | + | | | 0 +(9 rows) + +--Testcase 47: +SELECT * + FROM J1_TBL RIGHT JOIN J2_TBL USING (i); + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 5 | 0 | five | -5 + 5 | 0 | five | -5 + | | | + | | | 0 +(9 rows) + +--Testcase 48: +SELECT * + FROM J1_TBL FULL OUTER JOIN J2_TBL USING (i) + ORDER BY i, k, t; + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 4 | 1 | four | + 5 | 0 | five | -5 + 5 | 0 | five | -5 + 6 | 6 | six | + 7 | 7 | seven | + 8 | 8 | eight | + | | | 0 + | | null | + | 0 | zero | + | | | +(15 rows) + +--Testcase 49: +SELECT * + FROM J1_TBL FULL JOIN J2_TBL USING (i) + ORDER BY i, k, t; + i | j | t | k +---+---+-------+---- + 0 | | zero | + 1 | 4 | one | -1 + 2 | 3 | two | 2 + 2 | 3 | two | 4 + 3 | 2 | three | -3 + 4 | 1 | four | + 5 | 0 | five | -5 + 5 | 0 | five | -5 + 6 | 6 | six | + 7 | 7 | seven | + 8 | 8 | eight | + | | | 0 + | | null | + | 0 | zero | + | | | +(15 rows) + +--Testcase 50: +SELECT * + FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1); + i | j | t | k +---+---+---+--- +(0 rows) + +--Testcase 51: +SELECT * + FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (i = 1); + i | j | t | k +---+---+-----+---- + 1 | 4 | one | -1 +(1 row) + +-- +-- semijoin selectivity for <> +-- +--Testcase 52: +explain (costs off) +select * from int4_tbl i4, tenk1 a +where exists(select * from tenk1 b + where a.twothousand = b.twothousand and a.fivethous <> b.fivethous) + and i4.f1 = a.tenthous; + QUERY PLAN +---------------------------------------------------------- + Hash Join + Hash Cond: (i4.f1 = a.tenthous) + -> Foreign Scan on int4_tbl i4 + -> Hash + -> Hash Semi Join + Hash Cond: (a.twothousand = b.twothousand) + Join Filter: (a.fivethous <> b.fivethous) + -> Foreign Scan on tenk1 a + -> Hash + -> Foreign Scan on tenk1 b +(10 rows) + +-- +-- More complicated constructs +-- +-- +-- Multiway full join +-- +--Testcase 372: +CREATE FOREIGN TABLE t11 (name TEXT, n INTEGER) SERVER sqlite_svr; +--Testcase 373: +CREATE FOREIGN TABLE t21 (name TEXT, n INTEGER) SERVER sqlite_svr; +--Testcase 374: +CREATE FOREIGN TABLE t31 (name TEXT, n INTEGER) SERVER sqlite_svr; +--Testcase 483: +CREATE FOREIGN TABLE onek ( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 53: +INSERT INTO t11 VALUES ( 'bb', 11 ); +--Testcase 54: +INSERT INTO t21 VALUES ( 'bb', 12 ); +--Testcase 55: +INSERT INTO t21 VALUES ( 'cc', 22 ); +--Testcase 56: +INSERT INTO t21 VALUES ( 'ee', 42 ); +--Testcase 57: +INSERT INTO t31 VALUES ( 'bb', 13 ); +--Testcase 58: +INSERT INTO t31 VALUES ( 'cc', 23 ); +--Testcase 59: +INSERT INTO t31 VALUES ( 'dd', 33 ); +--Testcase 60: +SELECT * FROM t11 FULL JOIN t21 USING (name) FULL JOIN t31 USING (name); + name | n | n | n +------+----+----+---- + bb | 11 | 12 | 13 + cc | | 22 | 23 + dd | | | 33 + ee | | 42 | +(4 rows) + +-- +-- Test interactions of join syntax and subqueries +-- +-- Basic cases (we expect planner to pull up the subquery here) +--Testcase 61: +SELECT * FROM +(SELECT * FROM t21) as s2 +INNER JOIN +(SELECT * FROM t31) s3 +USING (name); + name | n | n +------+----+---- + bb | 12 | 13 + cc | 22 | 23 +(2 rows) + +--Testcase 62: +SELECT * FROM +(SELECT * FROM t21) as s2 +LEFT JOIN +(SELECT * FROM t31) s3 +USING (name); + name | n | n +------+----+---- + bb | 12 | 13 + cc | 22 | 23 + ee | 42 | +(3 rows) + +--Testcase 63: +SELECT * FROM +(SELECT * FROM t21) as s2 +FULL JOIN +(SELECT * FROM t31) s3 +USING (name); + name | n | n +------+----+---- + bb | 12 | 13 + cc | 22 | 23 + dd | | 33 + ee | 42 | +(4 rows) + +-- Cases with non-nullable expressions in subquery results; +-- make sure these go to null as expected +--Testcase 64: +SELECT * FROM +(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 +NATURAL INNER JOIN +(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; + name | s2_n | s2_2 | s3_n | s3_2 +------+------+------+------+------ + bb | 12 | 2 | 13 | 3 + cc | 22 | 2 | 23 | 3 +(2 rows) + +--Testcase 65: +SELECT * FROM +(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 +NATURAL LEFT JOIN +(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; + name | s2_n | s2_2 | s3_n | s3_2 +------+------+------+------+------ + bb | 12 | 2 | 13 | 3 + cc | 22 | 2 | 23 | 3 + ee | 42 | 2 | | +(3 rows) + +--Testcase 66: +SELECT * FROM +(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 +NATURAL FULL JOIN +(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; + name | s2_n | s2_2 | s3_n | s3_2 +------+------+------+------+------ + bb | 12 | 2 | 13 | 3 + cc | 22 | 2 | 23 | 3 + dd | | | 33 | 3 + ee | 42 | 2 | | +(4 rows) + +--Testcase 67: +SELECT * FROM +(SELECT name, n as s1_n, 1 as s1_1 FROM t11) as s1 +NATURAL INNER JOIN +(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 +NATURAL INNER JOIN +(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; + name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 +------+------+------+------+------+------+------ + bb | 11 | 1 | 12 | 2 | 13 | 3 +(1 row) + +--Testcase 68: +SELECT * FROM +(SELECT name, n as s1_n, 1 as s1_1 FROM t11) as s1 +NATURAL FULL JOIN +(SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 +NATURAL FULL JOIN +(SELECT name, n as s3_n, 3 as s3_2 FROM t31) s3; + name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 +------+------+------+------+------+------+------ + bb | 11 | 1 | 12 | 2 | 13 | 3 + cc | | | 22 | 2 | 23 | 3 + dd | | | | | 33 | 3 + ee | | | 42 | 2 | | +(4 rows) + +--Testcase 69: +SELECT * FROM +(SELECT name, n as s1_n FROM t11) as s1 +NATURAL FULL JOIN + (SELECT * FROM + (SELECT name, n as s2_n FROM t21) as s2 + NATURAL FULL JOIN + (SELECT name, n as s3_n FROM t31) as s3 + ) ss2; + name | s1_n | s2_n | s3_n +------+------+------+------ + bb | 11 | 12 | 13 + cc | | 22 | 23 + dd | | | 33 + ee | | 42 | +(4 rows) + +--Testcase 70: +SELECT * FROM +(SELECT name, n as s1_n FROM t11) as s1 +NATURAL FULL JOIN + (SELECT * FROM + (SELECT name, n as s2_n, 2 as s2_2 FROM t21) as s2 + NATURAL FULL JOIN + (SELECT name, n as s3_n FROM t31) as s3 + ) ss2; + name | s1_n | s2_n | s2_2 | s3_n +------+------+------+------+------ + bb | 11 | 12 | 2 | 13 + cc | | 22 | 2 | 23 + dd | | | | 33 + ee | | 42 | 2 | +(4 rows) + +-- Constants as join keys can also be problematic +--Testcase 375: +SELECT * FROM + (SELECT name, n as s1_n FROM t11) as s1 +FULL JOIN + (SELECT name, 2 as s2_n FROM t21) as s2 +ON (s1_n = s2_n); + name | s1_n | name | s2_n +------+------+------+------ + | | bb | 2 + | | cc | 2 + | | ee | 2 + bb | 11 | | +(4 rows) + +-- Test for propagation of nullability constraints into sub-joins +--Testcase 376: +create foreign table x (x1 int, x2 int) server sqlite_svr; +--Testcase 71: +insert into x values (1,11); +--Testcase 72: +insert into x values (2,22); +--Testcase 73: +insert into x values (3,null); +--Testcase 74: +insert into x values (4,44); +--Testcase 75: +insert into x values (5,null); +--Testcase 377: +create foreign table y (y1 int, y2 int) server sqlite_svr; +--Testcase 76: +insert into y values (1,111); +--Testcase 77: +insert into y values (2,222); +--Testcase 78: +insert into y values (3,333); +--Testcase 79: +insert into y values (4,null); +--Testcase 80: +select * from x; + x1 | x2 +----+---- + 1 | 11 + 2 | 22 + 3 | + 4 | 44 + 5 | +(5 rows) + +--Testcase 81: +select * from y; + y1 | y2 +----+----- + 1 | 111 + 2 | 222 + 3 | 333 + 4 | +(4 rows) + +--Testcase 82: +select * from x left join y on (x1 = y1 and x2 is not null); + x1 | x2 | y1 | y2 +----+----+----+----- + 1 | 11 | 1 | 111 + 2 | 22 | 2 | 222 + 3 | | | + 4 | 44 | 4 | + 5 | | | +(5 rows) + +--Testcase 83: +select * from x left join y on (x1 = y1 and y2 is not null); + x1 | x2 | y1 | y2 +----+----+----+----- + 1 | 11 | 1 | 111 + 2 | 22 | 2 | 222 + 3 | | 3 | 333 + 4 | 44 | | + 5 | | | +(5 rows) + +--Testcase 84: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 3 | | 3 | 333 | 3 | + 4 | 44 | 4 | | 4 | 44 + 5 | | | | 5 | +(5 rows) + +--Testcase 85: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1 and x2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 3 | | 3 | 333 | | + 4 | 44 | 4 | | 4 | 44 + 5 | | | | | +(5 rows) + +--Testcase 86: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1 and y2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 3 | | 3 | 333 | 3 | + 4 | 44 | 4 | | | + 5 | | | | | +(5 rows) + +--Testcase 87: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1 and xx2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 3 | | 3 | 333 | | + 4 | 44 | 4 | | 4 | 44 + 5 | | | | | +(5 rows) + +-- these should NOT give the same answers as above +--Testcase 88: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1) where (x2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 4 | 44 | 4 | | 4 | 44 +(3 rows) + +--Testcase 89: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1) where (y2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 3 | | 3 | 333 | 3 | +(3 rows) + +--Testcase 90: +select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) +on (x1 = xx1) where (xx2 is not null); + x1 | x2 | y1 | y2 | xx1 | xx2 +----+----+----+-----+-----+----- + 1 | 11 | 1 | 111 | 1 | 11 + 2 | 22 | 2 | 222 | 2 | 22 + 4 | 44 | 4 | | 4 | 44 +(3 rows) + +-- +-- regression test: check for bug with propagation of implied equality +-- to outside an IN +-- +--Testcase 91: +select count(*) from tenk1 a where unique1 in + (select unique1 from tenk1 b join tenk1 c using (unique1) + where b.unique2 = 42); + count +------- + 1 +(1 row) + +-- +-- regression test: check for failure to generate a plan with multiple +-- degenerate IN clauses +-- +--Testcase 92: +select count(*) from tenk1 x where + x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and + x.unique1 = 0 and + x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); + count +------- + 1 +(1 row) + +-- try that with GEQO too +begin; +--Testcase 499: +set geqo = on; +--Testcase 500: +set geqo_threshold = 2; +--Testcase 93: +select count(*) from tenk1 x where + x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and + x.unique1 = 0 and + x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); + count +------- + 1 +(1 row) + +rollback; +-- +-- regression test: be sure we cope with proven-dummy append rels +-- +--Testcase 378: +create table b (aa int, bb int); +--Testcase 379: +explain (costs off) +select aa, bb, unique1, unique1 + from tenk1 right join b on aa = unique1 + where bb < bb and bb is null; + QUERY PLAN +---------------------------------------------------- + Hash Right Join + Hash Cond: (tenk1.unique1 = b.aa) + -> Foreign Scan on tenk1 + -> Hash + -> Seq Scan on b + Filter: ((bb IS NULL) AND (bb < bb)) +(6 rows) + +--Testcase 380: +select aa, bb, unique1, unique1 + from tenk1 right join b on aa = unique1 + where bb < bb and bb is null; + aa | bb | unique1 | unique1 +----+----+---------+--------- +(0 rows) + +-- +-- regression test: check handling of empty-FROM subquery underneath outer join +-- +--Testcase 94: +explain (costs off) +select * from int8_tbl i1 left join (int8_tbl i2 join + (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 +order by 1, 2; + QUERY PLAN +----------------------------------------- + Nested Loop Left Join + Join Filter: (i1.q2 = i2.q2) + -> Foreign Scan on int8_tbl i1 + -> Materialize + -> Foreign Scan on int8_tbl i2 +(5 rows) + +--Testcase 95: +select * from int8_tbl i1 left join (int8_tbl i2 join + (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 +order by 1, 2; + q1 | q2 | q1 | q2 | x +------------------+-------------------+-----+------------------+----- + 123 | 456 | 123 | 456 | 123 + 123 | 4567890123456789 | 123 | 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 | | | + 4567890123456789 | 123 | | | + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 123 +(5 rows) + +-- +-- regression test: check a case where join_clause_is_movable_into() +-- used to give an imprecise result, causing an assertion failure +-- +--Testcase 96: +select count(*) +from + (select t31.tenthous as x1, coalesce(t11.stringu1, t21.stringu1) as x2 + from tenk1 t11 + left join tenk1 t21 on t11.unique1 = t21.unique1 + join tenk1 t31 on t11.unique2 = t31.unique2) ss, + tenk1 t4, + tenk1 t5 +where t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1; + count +------- + 1000 +(1 row) + +-- +-- regression test: check a case where we formerly missed including an EC +-- enforcement clause because it was expected to be handled at scan level +-- +--Testcase 97: +explain (costs off) +select a.f1, b.f1, t.thousand, t.tenthous from + tenk1 t, + (select sum(f1)+1 as f1 from int4_tbl i4a) a, + (select sum(f1) as f1 from int4_tbl i4b) b +where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; + QUERY PLAN +----------------------------------------------------------------------------- + Hash Join + Hash Cond: (t.thousand = (sum(i4b.f1))) + Join Filter: (((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999) = t.tenthous) + -> Hash Join + Hash Cond: (t.thousand = ((sum(i4a.f1) + 1))) + -> Foreign Scan on tenk1 t + -> Hash + -> Foreign Scan + -> Hash + -> Foreign Scan +(10 rows) + +--Testcase 98: +select a.f1, b.f1, t.thousand, t.tenthous from + tenk1 t, + (select sum(f1)+1 as f1 from int4_tbl i4a) a, + (select sum(f1) as f1 from int4_tbl i4b) b +where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; + f1 | f1 | thousand | tenthous +----+----+----------+---------- +(0 rows) + +-- +-- checks for correct handling of quals in multiway outer joins +-- +--Testcase 545: +explain (costs off) +select t1.f1 +from int4_tbl t1, int4_tbl t2 + left join int4_tbl t3 on t3.f1 > 0 + left join int4_tbl t4 on t3.f1 > 1 +where t4.f1 is null; + QUERY PLAN +----------------------------------------- + Nested Loop + -> Foreign Scan + -> Materialize + -> Foreign Scan on int4_tbl t1 +(4 rows) + +--Testcase 546: +select t1.f1 +from int4_tbl t1, int4_tbl t2 + left join int4_tbl t3 on t3.f1 > 0 + left join int4_tbl t4 on t3.f1 > 1 +where t4.f1 is null; + f1 +---- +(0 rows) + +--Testcase 547: +explain (costs off) +select * +from int4_tbl t1 left join int4_tbl t2 on true + left join int4_tbl t3 on t2.f1 > 0 + left join int4_tbl t4 on t3.f1 > 0; + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int4_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t3.f1 > 0) + -> Nested Loop Left Join + Join Filter: (t2.f1 > 0) + -> Foreign Scan on int4_tbl t2 + -> Materialize + -> Foreign Scan on int4_tbl t3 + -> Materialize + -> Foreign Scan on int4_tbl t4 +(12 rows) + +--Testcase 548: +explain (costs off) +select * from onek t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join onek t3 on t2.unique1 != t3.unique1 + left join onek t4 on t3.unique1 = t4.unique1; + QUERY PLAN +------------------------------------------- + Nested Loop Left Join + Join Filter: (t2.unique1 <> t3.unique1) + -> Foreign Scan + -> Materialize + -> Foreign Scan +(5 rows) + +--Testcase 549: +explain (costs off) +select * from int4_tbl t1 + left join (select now() from int4_tbl t2 + left join int4_tbl t3 on t2.f1 = t3.f1 + left join int4_tbl t4 on t3.f1 = t4.f1) s on true + inner join int4_tbl t5 on true; + QUERY PLAN +----------------------------------------------------------------------- + Nested Loop + -> Nested Loop Left Join + -> Foreign Scan on int4_tbl t1 + -> Materialize + -> Merge Left Join + Merge Cond: (t2.f1 = t3.f1) + -> Sort + Sort Key: t2.f1 + -> Foreign Scan on int4_tbl t2 + -> Materialize + -> Merge Left Join + Merge Cond: (t3.f1 = t4.f1) + -> Sort + Sort Key: t3.f1 + -> Foreign Scan on int4_tbl t3 + -> Sort + Sort Key: t4.f1 + -> Foreign Scan on int4_tbl t4 + -> Materialize + -> Foreign Scan on int4_tbl t5 +(20 rows) + +--Testcase 550: +explain (costs off) +select * from int4_tbl t1 + left join int4_tbl t2 on true + left join int4_tbl t3 on true + left join int4_tbl t4 on t2.f1 = t3.f1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 551: +explain (costs off) +select * from int4_tbl t1 + left join int4_tbl t2 on true + left join int4_tbl t3 on t2.f1 = t3.f1 + left join int4_tbl t4 on t3.f1 != t4.f1; + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int4_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t3.f1 <> t4.f1) + -> Merge Left Join + Merge Cond: (t2.f1 = t3.f1) + -> Sort + Sort Key: t2.f1 + -> Foreign Scan on int4_tbl t2 + -> Sort + Sort Key: t3.f1 + -> Foreign Scan on int4_tbl t3 + -> Materialize + -> Foreign Scan on int4_tbl t4 +(15 rows) + +--Testcase 552: +explain (costs off) +select * from int4_tbl t1 + left join (int4_tbl t2 left join int4_tbl t3 on t2.f1 > 0) on t2.f1 > 1 + left join int4_tbl t4 on t2.f1 > 2 and t3.f1 > 3 +where t1.f1 = coalesce(t2.f1, 1); + QUERY PLAN +----------------------------------------------- + Nested Loop Left Join + Join Filter: ((t2.f1 > 2) AND (t3.f1 > 3)) + -> Nested Loop Left Join + Join Filter: (t2.f1 > 0) + -> Foreign Scan + -> Materialize + -> Foreign Scan on int4_tbl t3 + -> Materialize + -> Foreign Scan on int4_tbl t4 +(9 rows) + +--Testcase 553: +explain (costs off) +select * from int4_tbl t1 + left join ((select t2.f1 from int4_tbl t2 + left join int4_tbl t3 on t2.f1 > 0 + where t3.f1 is null) s + left join tenk1 t4 on s.f1 > 1) + on s.f1 = t1.f1; + QUERY PLAN +-------------------------------------------- + Hash Right Join + Hash Cond: (t2.f1 = t1.f1) + -> Nested Loop Left Join + Join Filter: (t2.f1 > 1) + -> Foreign Scan + -> Materialize + -> Foreign Scan on tenk1 t4 + -> Hash + -> Foreign Scan on int4_tbl t1 +(9 rows) + +--Testcase 554: +explain (costs off) +select * from int4_tbl t1 + left join ((select t2.f1 from int4_tbl t2 + left join int4_tbl t3 on t2.f1 > 0 + where t2.f1 <> coalesce(t3.f1, -1)) s + left join tenk1 t4 on s.f1 > 1) + on s.f1 = t1.f1; + QUERY PLAN +----------------------------------------------------------------- + Hash Right Join + Hash Cond: (t2.f1 = t1.f1) + -> Nested Loop Left Join + Join Filter: (t2.f1 > 1) + -> Nested Loop Left Join + Join Filter: (t2.f1 > 0) + Filter: (t2.f1 <> COALESCE(t3.f1, '-1'::integer)) + -> Foreign Scan on int4_tbl t2 + -> Materialize + -> Foreign Scan on int4_tbl t3 + -> Materialize + -> Foreign Scan on tenk1 t4 + -> Hash + -> Foreign Scan on int4_tbl t1 +(14 rows) + +--Testcase 555: +explain (costs off) +select * from onek t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join onek t3 on t2.unique1 = t3.unique1 + left join onek t4 on t3.unique1 = t4.unique1 and t2.unique2 = t4.unique2; + QUERY PLAN +------------------------------------------------------------------------ + Hash Left Join + Hash Cond: ((t3.unique1 = t4.unique1) AND (t2.unique2 = t4.unique2)) + -> Hash Left Join + Hash Cond: (t2.unique1 = t3.unique1) + -> Foreign Scan + -> Hash + -> Foreign Scan on onek t3 + -> Hash + -> Foreign Scan on onek t4 +(9 rows) + +--Testcase 556: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 left join int8_tbl t3 full join int8_tbl t4 on false on false) + left join int8_tbl t5 on t2.q1 = t5.q1 +on t2.q2 = 123; + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int8_tbl t1 + -> Materialize + -> Hash Right Join + Hash Cond: (t5.q1 = t2.q1) + -> Foreign Scan on int8_tbl t5 + -> Hash + -> Nested Loop Left Join + Join Filter: false + -> Foreign Scan on int8_tbl t2 + -> Result + One-Time Filter: false +(12 rows) + +--Testcase 557: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select * from int8_tbl t3 where t3.q1 = t2.q1 offset 0) s + on t2.q1 = 1; + QUERY PLAN +----------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int8_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t2.q1 = 1) + -> Foreign Scan on int8_tbl t2 + -> Foreign Scan on int8_tbl t3 +(7 rows) + +--Testcase 558: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select * from generate_series(t2.q1, 100)) s + on t2.q1 = 1; + QUERY PLAN +---------------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int8_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t2.q1 = 1) + -> Foreign Scan on int8_tbl t2 + -> Function Scan on generate_series +(7 rows) + +--Testcase 559: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select t2.q1 from int8_tbl t3) s + on t2.q1 = 1; + QUERY PLAN +----------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int8_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t2.q1 = 1) + -> Foreign Scan on int8_tbl t2 + -> Foreign Scan on int8_tbl t3 +(7 rows) + +--Testcase 560: +explain (costs off) +select * from onek t1 + left join onek t2 on true + left join lateral + (select * from onek t3 where t3.two = t2.two offset 0) s + on t2.unique1 = 1; + QUERY PLAN +--------------------------------------------- + Nested Loop Left Join + -> Foreign Scan on onek t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t2.unique1 = 1) + -> Foreign Scan on onek t2 + -> Foreign Scan on onek t3 +(7 rows) + +-- +-- check a case where we formerly got confused by conflicting sort orders +-- in redundant merge join path keys +-- PS: Used ORDER BY to force SQLite and PG12 always order in the same way (NULLS FIRST/LAST default value for PG and Sqlite are different) +-- +--Testcase 99: +explain (costs off) +select * from + j1_tbl full join + (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl + on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k ORDER BY j1_tbl.i, j2_tbl.k; + QUERY PLAN +---------------------------------------------------------------------- + Sort + Sort Key: j1_tbl.i, j2_tbl.k + -> Hash Full Join + Hash Cond: ((j1_tbl.i = j2_tbl.i) AND (j1_tbl.i = j2_tbl.k)) + -> Foreign Scan on j1_tbl + -> Hash + -> Foreign Scan on j2_tbl +(7 rows) + +--Testcase 100: +select * from + j1_tbl full join + (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl + on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k ORDER BY j1_tbl.i, j2_tbl.k; + i | j | t | i | k +---+---+-------+---+---- + 0 | | zero | | + 1 | 4 | one | | + 2 | 3 | two | 2 | 2 + 3 | 2 | three | | + 4 | 1 | four | | + 5 | 0 | five | | + 6 | 6 | six | | + 7 | 7 | seven | | + 8 | 8 | eight | | + | | | 5 | -5 + | | | 5 | -5 + | | | 3 | -3 + | | | 1 | -1 + | | | | 0 + | | | 2 | 4 + | | | | + | | | 0 | + | 0 | zero | | + | | null | | +(19 rows) + +-- +-- a different check for handling of redundant sort keys in merge joins +-- +--Testcase 101: +explain (costs off) +select count(*) from + (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x + left join + (select * from tenk1 y order by y.unique2) y + on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; + QUERY PLAN +---------------------------------------------------------------------------------- + Aggregate + -> Merge Left Join + Merge Cond: (x.thousand = y.unique2) + Join Filter: ((x.twothousand = y.hundred) AND (x.fivethous = y.unique2)) + -> Foreign Scan on tenk1 x + -> Materialize + -> Foreign Scan on tenk1 y +(7 rows) + +--Testcase 102: +select count(*) from + (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x + left join + (select * from tenk1 y order by y.unique2) y + on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; + count +------- + 10000 +(1 row) + +set enable_hashjoin = 0; +set enable_nestloop = 0; +set enable_hashagg = 0; +-- +-- Check that we use the pathkeys from a prefix of the group by / order by +-- clause for the join pathkeys when that prefix covers all join quals. We +-- expect this to lead to an incremental sort for the group by / order by. +-- +--Testcase 561: +explain (costs off) +select x.thousand, x.twothousand, count(*) +from tenk1 x inner join tenk1 y on x.thousand = y.thousand +group by x.thousand, x.twothousand +order by x.thousand desc, x.twothousand; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +reset enable_hashagg; +reset enable_nestloop; +reset enable_hashjoin; +-- +-- Clean up +-- +--Testcase 381: +DROP FOREIGN TABLE t11; +--Testcase 382: +DROP FOREIGN TABLE t21; +--Testcase 383: +DROP FOREIGN TABLE t31; +--Testcase 384: +DROP FOREIGN TABLE J1_TBL; +--Testcase 385: +DROP FOREIGN TABLE J2_TBL; +-- Both DELETE and UPDATE allow the specification of additional tables +-- to "join" against to determine which rows should be modified. +--Testcase 386: +CREATE FOREIGN TABLE t12 (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; +--Testcase 387: +CREATE FOREIGN TABLE t22 (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; +--Testcase 388: +CREATE FOREIGN TABLE t32 (x int OPTIONS (key 'true'), y int) SERVER sqlite_svr; +--Testcase 103: +INSERT INTO t12 VALUES (5, 10); +--Testcase 104: +INSERT INTO t12 VALUES (15, 20); +--Testcase 105: +INSERT INTO t12 VALUES (100, 100); +--Testcase 106: +INSERT INTO t12 VALUES (200, 1000); +--Testcase 107: +INSERT INTO t22 VALUES (200, 2000); +--Testcase 108: +INSERT INTO t32 VALUES (5, 20); +--Testcase 109: +INSERT INTO t32 VALUES (6, 7); +--Testcase 110: +INSERT INTO t32 VALUES (7, 8); +--Testcase 111: +INSERT INTO t32 VALUES (500, 100); +--Testcase 112: +DELETE FROM t32 USING t12 table1 WHERE t32.x = table1.a; +--Testcase 113: +SELECT * FROM t32; + x | y +-----+----- + 6 | 7 + 7 | 8 + 500 | 100 +(3 rows) + +--Testcase 114: +DELETE FROM t32 USING t12 JOIN t22 USING (a) WHERE t32.x > t12.a; +--Testcase 115: +SELECT * FROM t32; + x | y +---+--- + 6 | 7 + 7 | 8 +(2 rows) + +--Testcase 116: +DELETE FROM t32 USING t32 t3_other WHERE t32.x = t3_other.x AND t32.y = t3_other.y; +--Testcase 117: +SELECT * FROM t32; + x | y +---+--- +(0 rows) + +-- Test join against inheritance tree +--Testcase 389: +create temp table t2a () inherits (t22); +--Testcase 118: +insert into t2a values (200, 2001); +--Testcase 119: +select * from t12 left join t22 on (t12.a = t22.a); + a | b | a | b +-----+------+-----+------ + 5 | 10 | | + 15 | 20 | | + 100 | 100 | | + 200 | 1000 | 200 | 2000 + 200 | 1000 | 200 | 2001 +(5 rows) + +-- Test matching of column name with wrong alias +--Testcase 120: +select t12.x from t12 join t32 on (t12.a = t32.x); +ERROR: column t12.x does not exist +LINE 1: select t12.x from t12 join t32 on (t12.a = t32.x); + ^ +HINT: Perhaps you meant to reference the column "t32.x". +-- Test matching of locking clause with wrong alias +--Testcase 540: +select t12.*, t22.*, unnamed_join.* from + t12 join t22 on (t12.a = t22.a), t32 as unnamed_join + for update of unnamed_join; + a | b | a | b | x | y +---+---+---+---+---+--- +(0 rows) + +--Testcase 541: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of unnamed_join; + a | x | y +---+---+--- +(0 rows) + +--Testcase 542: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of foo; +ERROR: FOR UPDATE cannot be applied to a join +LINE 3: for update of foo; + ^ +--Testcase 543: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of foo; +ERROR: relation "foo" in FOR UPDATE clause not found in FROM clause +LINE 3: for update of foo; + ^ +--Testcase 544: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of bar; +ERROR: FOR UPDATE cannot be applied to a join +LINE 3: for update of bar; + ^ +--Testcase 536: +drop table t2a; +-- +-- regression test for 8.1 merge right join bug +-- +--Testcase 390: +CREATE FOREIGN TABLE tt1 ( tt1_id int4, joincol int4 ) SERVER sqlite_svr; +--Testcase 121: +INSERT INTO tt1 VALUES (1, 11); +--Testcase 122: +INSERT INTO tt1 VALUES (2, NULL); +--Testcase 391: +CREATE FOREIGN TABLE tt2 ( tt2_id int4, joincol int4 ) SERVER sqlite_svr; +--Testcase 123: +INSERT INTO tt2 VALUES (21, 11); +--Testcase 124: +INSERT INTO tt2 VALUES (22, 11); +--Testcase 501: +set enable_hashjoin to off; +--Testcase 502: +set enable_nestloop to off; +-- these should give the same results +--Testcase 125: +select tt1.*, tt2.* from tt1 left join tt2 on tt1.joincol = tt2.joincol; + tt1_id | joincol | tt2_id | joincol +--------+---------+--------+--------- + 1 | 11 | 21 | 11 + 1 | 11 | 22 | 11 + 2 | | | +(3 rows) + +--Testcase 126: +select tt1.*, tt2.* from tt2 right join tt1 on tt1.joincol = tt2.joincol; + tt1_id | joincol | tt2_id | joincol +--------+---------+--------+--------- + 1 | 11 | 21 | 11 + 1 | 11 | 22 | 11 + 2 | | | +(3 rows) + +--Testcase 503: +reset enable_hashjoin; +--Testcase 504: +reset enable_nestloop; +-- +-- regression test for bug #18522 (merge-right-anti-join in inner_unique cases) +-- +--Testcase 637: +create foreign table tbl_ra(a int options (key 'true'), b int) server sqlite_svr; +--Testcase 638: +insert into tbl_ra select i, i%100 from generate_series(1,1000)i; +-- CREATE INDEX, ANALYZE are not supported for foreign tables. +-- create index on tbl_ra (b); +-- analyze tbl_ra; +set enable_hashjoin to off; +set enable_nestloop to off; +-- Because CREATE INDEX is not supported for foreign tables, +-- we cannot use this index to create a merge right anti join plan +-- ensure we get a merge right anti join +--Testcase 639: +explain (costs off) +select * from tbl_ra t1 +where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; + QUERY PLAN +--------------------------------------- + Merge Anti Join + Merge Cond: (t1.a = t2.b) + -> Sort + Sort Key: t1.a + -> Foreign Scan on tbl_ra t1 + -> Sort + Sort Key: t2.b + -> Foreign Scan on tbl_ra t2 +(8 rows) + +-- and check we get the expected results +--Testcase 640: +select * from tbl_ra t1 +where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; + a | b +------+--- + 100 | 0 + 101 | 1 + 200 | 0 + 201 | 1 + 300 | 0 + 301 | 1 + 400 | 0 + 401 | 1 + 500 | 0 + 501 | 1 + 600 | 0 + 601 | 1 + 700 | 0 + 701 | 1 + 800 | 0 + 801 | 1 + 900 | 0 + 901 | 1 + 1000 | 0 +(19 rows) + +reset enable_hashjoin; +reset enable_nestloop; +-- +-- regression test for bug #13908 (hash join with skew tuples & nbatch increase) +-- +--Testcase 505: +set work_mem to '64kB'; +--Testcase 506: +set enable_mergejoin to off; +--Testcase 507: +set enable_memoize to off; +--Testcase 127: +explain (costs off) +select count(*) from tenk1 a, tenk1 b + where a.hundred = b.thousand and (b.fivethous % 10) < 10; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 128: +select count(*) from tenk1 a, tenk1 b + where a.hundred = b.thousand and (b.fivethous % 10) < 10; + count +-------- + 100000 +(1 row) + +--Testcase 508: +reset work_mem; +--Testcase 509: +reset enable_mergejoin; +--Testcase 510: +reset enable_memoize; +-- +-- regression test for 8.2 bug with improper re-ordering of left joins +-- +--Testcase 392: +create foreign table tt3(f1 int, f2 text) server sqlite_svr; +--Testcase 129: +insert into tt3 select x, repeat('xyzzy', 100) from generate_series(1,10000) x; +--Testcase 393: +create foreign table tt4(f1 int) server sqlite_svr; +--Testcase 130: +insert into tt4 values (0),(1),(9999); +set enable_nestloop to off; +--Testcase 562: +EXPLAIN (COSTS OFF) +SELECT a.f1 +FROM tt4 a +LEFT JOIN ( + SELECT b.f1 + FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) + WHERE COALESCE(c.f1, 0) = 0 +) AS d ON (a.f1 = d.f1) +WHERE COALESCE(d.f1, 0) = 0 +ORDER BY 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 563: +SELECT a.f1 +FROM tt4 a +LEFT JOIN ( + SELECT b.f1 + FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) + WHERE COALESCE(c.f1, 0) = 0 +) AS d ON (a.f1 = d.f1) +WHERE COALESCE(d.f1, 0) = 0 +ORDER BY 1; + f1 +------ + 0 + 1 + 9999 +(3 rows) + +reset enable_nestloop; +-- +-- basic semijoin and antijoin recognition tests +-- +--Testcase 564: +explain (costs off) +select a.* from tenk1 a +where unique1 in (select unique2 from tenk1 b); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +-- sadly, this is not an antijoin +--Testcase 565: +explain (costs off) +select a.* from tenk1 a +where unique1 not in (select unique2 from tenk1 b); + QUERY PLAN +----------------------------------------------------------- + Foreign Scan on tenk1 a + Filter: (NOT (ANY (unique1 = (hashed SubPlan 1).col1))) + SubPlan 1 + -> Foreign Scan on tenk1 b +(4 rows) + +--Testcase 566: +explain (costs off) +select a.* from tenk1 a +where exists (select 1 from tenk1 b where a.unique1 = b.unique2); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 567: +explain (costs off) +select a.* from tenk1 a +where not exists (select 1 from tenk1 b where a.unique1 = b.unique2); + QUERY PLAN +-------------------------------------- + Hash Anti Join + Hash Cond: (a.unique1 = b.unique2) + -> Foreign Scan on tenk1 a + -> Hash + -> Foreign Scan on tenk1 b +(5 rows) + +--Testcase 568: +explain (costs off) +select a.* from tenk1 a left join tenk1 b on a.unique1 = b.unique2 +where b.unique2 is null; + QUERY PLAN +-------------------------------------- + Hash Anti Join + Hash Cond: (a.unique1 = b.unique2) + -> Foreign Scan on tenk1 a + -> Hash + -> Foreign Scan on tenk1 b +(5 rows) + +-- +-- regression test for proper handling of outer joins within antijoins +-- +--Testcase 394: +create foreign table tt4x(c1 int, c2 int, c3 int) server sqlite_svr; +--Testcase 132: +explain (costs off) +select * from tt4x t1 +where not exists ( + select 1 from tt4x t2 + left join tt4x t3 on t2.c3 = t3.c1 + left join ( select t5.c1 as c1 + from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1 + ) a1 on t3.c2 = a1.c1 + where t1.c1 = t2.c2 +); + QUERY PLAN +------------------------------------------------------------- + Hash Anti Join + Hash Cond: (t1.c1 = t2.c2) + -> Foreign Scan on tt4x t1 + -> Hash + -> Merge Right Join + Merge Cond: (t5.c1 = t3.c2) + -> Merge Join + Merge Cond: (t4.c2 = t5.c1) + -> Sort + Sort Key: t4.c2 + -> Foreign Scan on tt4x t4 + -> Sort + Sort Key: t5.c1 + -> Foreign Scan on tt4x t5 + -> Sort + Sort Key: t3.c2 + -> Merge Left Join + Merge Cond: (t2.c3 = t3.c1) + -> Sort + Sort Key: t2.c3 + -> Foreign Scan on tt4x t2 + -> Sort + Sort Key: t3.c1 + -> Foreign Scan on tt4x t3 +(24 rows) + +-- +-- regression test for problems of the sort depicted in bug #3494 +-- +--Testcase 395: +create foreign table tt5(f1 int, f2 int) server sqlite_svr; +--Testcase 396: +create foreign table tt6(f1 int, f2 int) server sqlite_svr; +--Testcase 133: +insert into tt5 values(1, 10); +--Testcase 134: +insert into tt5 values(1, 11); +--Testcase 135: +insert into tt6 values(1, 9); +--Testcase 136: +insert into tt6 values(1, 2); +--Testcase 137: +insert into tt6 values(2, 9); +--Testcase 138: +select * from tt5,tt6 where tt5.f1 = tt6.f1 and tt5.f1 = tt5.f2 - tt6.f2; + f1 | f2 | f1 | f2 +----+----+----+---- + 1 | 10 | 1 | 9 +(1 row) + +-- +-- regression test for problems of the sort depicted in bug #3588 +-- +--Testcase 397: +create foreign table xx (pkxx int) server sqlite_svr; +--Testcase 398: +create foreign table yy (pkyy int, pkxx int) server sqlite_svr; +--Testcase 139: +insert into xx values (1); +--Testcase 140: +insert into xx values (2); +--Testcase 141: +insert into xx values (3); +--Testcase 142: +insert into yy values (101, 1); +--Testcase 143: +insert into yy values (201, 2); +--Testcase 144: +insert into yy values (301, NULL); +--Testcase 145: +select yy.pkyy as yy_pkyy, yy.pkxx as yy_pkxx, yya.pkyy as yya_pkyy, + xxa.pkxx as xxa_pkxx, xxb.pkxx as xxb_pkxx +from yy + left join (SELECT * FROM yy where pkyy = 101) as yya ON yy.pkyy = yya.pkyy + left join xx xxa on yya.pkxx = xxa.pkxx + left join xx xxb on coalesce (xxa.pkxx, 1) = xxb.pkxx; + yy_pkyy | yy_pkxx | yya_pkyy | xxa_pkxx | xxb_pkxx +---------+---------+----------+----------+---------- + 101 | 1 | 101 | 1 | 1 + 201 | 2 | | | 1 + 301 | | | | 1 +(3 rows) + +-- +-- regression test for improper pushing of constants across outer-join clauses +-- (as seen in early 8.2.x releases) +-- +--Testcase 399: +create foreign table zt1 (f1 int OPTIONS(key 'true')) server sqlite_svr; +--Testcase 400: +create foreign table zt2 (f2 int OPTIONS(key 'true')) server sqlite_svr; +--Testcase 401: +create foreign table zt3 (f3 int OPTIONS(key 'true')) server sqlite_svr; +--Testcase 146: +insert into zt1 values(53); +--Testcase 147: +insert into zt2 values(53); +--Testcase 148: +select * from + zt2 left join zt3 on (f2 = f3) + left join zt1 on (f3 = f1) +where f2 = 53; + f2 | f3 | f1 +----+----+---- + 53 | | +(1 row) + +--Testcase 402: +create temp view zv1 as select *,'dummy'::text AS junk from zt1; +--Testcase 149: +select * from + zt2 left join zt3 on (f2 = f3) + left join zv1 on (f3 = f1) +where f2 = 53; + f2 | f3 | f1 | junk +----+----+----+------ + 53 | | | +(1 row) + +--Testcase 537: +drop view zv1; +-- +-- regression test for improper extraction of OR indexqual conditions +-- (as seen in early 8.3.x releases) +-- +--Testcase 150: +select a.unique2, a.ten, b.tenthous, b.unique2, b.hundred +from tenk1 a left join tenk1 b on a.unique2 = b.tenthous +where a.unique1 = 42 and + ((b.unique2 is null and a.ten = 2) or b.hundred = 3); + unique2 | ten | tenthous | unique2 | hundred +---------+-----+----------+---------+--------- +(0 rows) + +-- +-- test proper positioning of one-time quals in EXISTS (8.4devel bug) +-- +--Testcase 151: +prepare foo(bool) as + select count(*) from tenk1 a left join tenk1 b + on (a.unique2 = b.unique1 and exists + (select 1 from tenk1 c where c.thousand = b.unique2 and $1)); +--Testcase 152: +execute foo(true); + count +------- + 10000 +(1 row) + +--Testcase 153: +execute foo(false); + count +------- + 10000 +(1 row) + +-- +-- test for sane behavior with noncanonical merge clauses, per bug #4926 +-- +begin; +--Testcase 511: +set enable_mergejoin = 1; +--Testcase 512: +set enable_hashjoin = 0; +--Testcase 513: +set enable_nestloop = 0; +--Testcase 403: +create foreign table a1 (i integer) server sqlite_svr; +--Testcase 404: +create foreign table b1 (x integer, y integer) server sqlite_svr; +--Testcase 154: +select * from a1 left join b1 on i = x and i = y and x = i; + i | x | y +---+---+--- +(0 rows) + +rollback; +-- skip this test, sqlite fdw does not support customized type +-- test handling of merge clauses using record_ops +-- +--begin; +--create type mycomptype as (id int, v bigint); +--create foreign table tidv (idv mycomptype) server sqlite_svr; +--create index on tidv (idv); +--explain (costs off) +--select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; +--set enable_mergejoin = 0; +--explain (costs off) +--select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; +--rollback; +-- +-- test NULL behavior of whole-row Vars, per bug #5025 +-- +--Testcase 155: +select t1.q2, count(t2.*) +from int8_tbl t1 left join int8_tbl t2 on (t1.q2 = t2.q1) +group by t1.q2 order by 1; + q2 | count +-------------------+------- + -4567890123456789 | 0 + 123 | 2 + 456 | 0 + 4567890123456789 | 6 +(4 rows) + +--Testcase 156: +select t1.q2, count(t2.*) +from int8_tbl t1 left join (select * from int8_tbl) t2 on (t1.q2 = t2.q1) +group by t1.q2 order by 1; + q2 | count +-------------------+------- + -4567890123456789 | 0 + 123 | 2 + 456 | 0 + 4567890123456789 | 6 +(4 rows) + +--Testcase 157: +select t1.q2, count(t2.*) +from int8_tbl t1 left join (select * from int8_tbl offset 0) t2 on (t1.q2 = t2.q1) +group by t1.q2 order by 1; + q2 | count +-------------------+------- + -4567890123456789 | 0 + 123 | 2 + 456 | 0 + 4567890123456789 | 6 +(4 rows) + +--Testcase 158: +select t1.q2, count(t2.*) +from int8_tbl t1 left join + (select q1, case when q2=1 then 1 else q2 end as q2 from int8_tbl) t2 + on (t1.q2 = t2.q1) +group by t1.q2 order by 1; + q2 | count +-------------------+------- + -4567890123456789 | 0 + 123 | 2 + 456 | 0 + 4567890123456789 | 6 +(4 rows) + +-- +-- test incorrect failure to NULL pulled-up subexpressions +-- +begin; +--Testcase 405: +create foreign table a2 ( + code char OPTIONS (key 'true') +) server sqlite_svr; +--Testcase 406: +create foreign table b2 ( + a char OPTIONS (key 'true'), + num integer OPTIONS (key 'true') +) server sqlite_svr; +--Testcase 407: +create foreign table c2 ( + name char OPTIONS (key 'true'), + a char +) server sqlite_svr; +--Testcase 159: +insert into a2 (code) values ('p'); +--Testcase 160: +insert into a2 (code) values ('q'); +--Testcase 161: +insert into b2 (a, num) values ('p', 1); +--Testcase 162: +insert into b2 (a, num) values ('p', 2); +--Testcase 163: +insert into c2 (name, a) values ('A', 'p'); +--Testcase 164: +insert into c2 (name, a) values ('B', 'q'); +--Testcase 165: +insert into c2 (name, a) values ('C', null); +--Testcase 166: +select c2.name, ss.code, ss.b_cnt, ss.const +from c2 left join + (select a2.code, coalesce(b_grp.cnt, 0) as b_cnt, -1 as const + from a2 left join + (select count(1) as cnt, b2.a from b2 group by b2.a) as b_grp + on a2.code = b_grp.a + ) as ss + on (c2.a = ss.code) +order by c2.name; + name | code | b_cnt | const +------+------+-------+------- + A | p | 2 | -1 + B | q | 0 | -1 + C | | | +(3 rows) + +rollback; +-- +-- test incorrect handling of placeholders that only appear in targetlists, +-- per bug #6154 +-- +--Testcase 408: +create foreign table sub_tbl (key1 int, key3 int, key5 int, key6 int, value1 int, id int options (key 'true')) server sqlite_svr; +--Testcase 409: +insert into sub_tbl values (1, 1, 1, 2, 42); +--Testcase 410: +SELECT * FROM +( SELECT key1 from sub_tbl) sub1 +LEFT JOIN +( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM + ( SELECT key3 from sub_tbl) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT key5 from sub_tbl) sub5 + LEFT JOIN + ( SELECT key6, value1 from sub_tbl ) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + key1 | key3 | value2 | value3 +------+------+--------+-------- + 1 | 1 | 1 | 1 +(1 row) + +-- test the path using join aliases, too +--Testcase 411: +SELECT * FROM +( SELECT key1 from sub_tbl ) sub1 +LEFT JOIN +( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM + ( SELECT key3 from sub_tbl ) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT key5 from sub_tbl ) sub5 + LEFT JOIN + ( SELECT key6, value1 from sub_tbl) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + key1 | key3 | value2 | value3 +------+------+--------+-------- + 1 | 1 | 1 | 1 +(1 row) + +-- +-- test case where a PlaceHolderVar is used as a nestloop parameter +-- +--Testcase 167: +EXPLAIN (COSTS OFF) +SELECT qq, unique1 + FROM + ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 + FULL OUTER JOIN + ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 + USING (qq) + INNER JOIN tenk1 c ON qq = unique2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (c.unique2 = (COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))) + -> Sort + Sort Key: c.unique2 + -> Foreign Scan on tenk1 c + -> Sort + Sort Key: (COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint)))) + -> Merge Full Join + Merge Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint))) + -> Sort + Sort Key: (COALESCE(a.q1, '0'::bigint)) + -> Foreign Scan on int8_tbl a + -> Sort + Sort Key: (COALESCE(b.q2, '-1'::bigint)) + -> Foreign Scan on int8_tbl b +(15 rows) + +--Testcase 168: +SELECT qq, unique1 + FROM + ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 + FULL OUTER JOIN + ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 + USING (qq) + INNER JOIN tenk1 c ON qq = unique2; + qq | unique1 +-----+--------- + 123 | 4596 + 123 | 4596 + 456 | 7318 +(3 rows) + +-- +-- nested nestloops can require nested PlaceHolderVars +-- +--Testcase 412: +create foreign table nt1 ( + id int OPTIONS (key 'true'), + a1 boolean, + a2 boolean +) server sqlite_svr; +--Testcase 413: +create foreign table nt2 ( + id int OPTIONS (key 'true'), + nt1_id int, + b1 boolean, + b2 boolean +) server sqlite_svr; +--Testcase 414: +create foreign table nt3 ( + id int OPTIONS (key 'true'), + nt2_id int, + c1 boolean +) server sqlite_svr; +--Testcase 169: +insert into nt1 values (1,true,true); +--Testcase 170: +insert into nt1 values (2,true,false); +--Testcase 171: +insert into nt1 values (3,false,false); +--Testcase 172: +insert into nt2 values (1,1,true,true); +--Testcase 173: +insert into nt2 values (2,2,true,false); +--Testcase 174: +insert into nt2 values (3,3,false,false); +--Testcase 175: +insert into nt3 values (1,1,true); +--Testcase 176: +insert into nt3 values (2,2,false); +--Testcase 177: +insert into nt3 values (3,3,true); +--Testcase 178: +explain (costs off) +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + QUERY PLAN +---------------------------------------------------- + Hash Join + Hash Cond: (nt1.id = nt2.nt1_id) + Join Filter: (nt2.b1 AND ((nt1.id IS NOT NULL))) + -> Foreign Scan on nt1 + -> Hash + -> Foreign Scan +(6 rows) + +--Testcase 179: +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + id +---- + 1 +(1 row) + +-- +-- test case where a PlaceHolderVar is propagated into a subquery +-- +--Testcase 180: +explain (costs off) +select * from + int8_tbl t1 left join + (select q1 as x, 42 as y from int8_tbl t2) ss + on t1.q2 = ss.x +where + 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) +order by 1,2; + QUERY PLAN +----------------------------------------------------- + Sort + Sort Key: t1.q1, t1.q2 + -> Hash Right Join + Hash Cond: (t2.q1 = t1.q2) + Filter: (1 = (SubPlan 1)) + -> Foreign Scan on int8_tbl t2 + -> Hash + -> Foreign Scan on int8_tbl t1 + SubPlan 1 + -> Result + One-Time Filter: ((42) IS NOT NULL) + -> Foreign Scan on int8_tbl t3 +(12 rows) + +--Testcase 181: +select * from + int8_tbl t1 left join + (select q1 as x, 42 as y from int8_tbl t2) ss + on t1.q2 = ss.x +where + 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) +order by 1,2; + q1 | q2 | x | y +------------------+------------------+------------------+---- + 123 | 4567890123456789 | 4567890123456789 | 42 + 123 | 4567890123456789 | 4567890123456789 | 42 + 123 | 4567890123456789 | 4567890123456789 | 42 + 4567890123456789 | 123 | 123 | 42 + 4567890123456789 | 123 | 123 | 42 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 +(8 rows) + +-- +-- variant where a PlaceHolderVar is needed at a join, but not above the join +-- +--Testcase 514: +explain (costs off) +select * from + int4_tbl as i41, + lateral + (select 1 as x from + (select i41.f1 as lat, + i42.f1 as loc from + int8_tbl as i81, int4_tbl as i42) as ss1 + right join int4_tbl as i43 on (i43.f1 > 1) + where ss1.loc = ss1.lat) as ss2 +where i41.f1 > 0; + QUERY PLAN +------------------------------------------------------ + Nested Loop + -> Nested Loop + -> Foreign Scan on int4_tbl i41 + -> Nested Loop + Join Filter: (i42.f1 = i41.f1) + -> Foreign Scan on int8_tbl i81 + -> Materialize + -> Foreign Scan on int4_tbl i42 + -> Materialize + -> Foreign Scan on int4_tbl i43 +(10 rows) + +--Testcase 515: +select * from + int4_tbl as i41, + lateral + (select 1 as x from + (select i41.f1 as lat, + i42.f1 as loc from + int8_tbl as i81, int4_tbl as i42) as ss1 + right join int4_tbl as i43 on (i43.f1 > 1) + where ss1.loc = ss1.lat) as ss2 +where i41.f1 > 0; + f1 | x +------------+--- + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 123456 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 + 2147483647 | 1 +(20 rows) + +-- +-- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE +-- +--Testcase 182: +select * from int4_tbl a full join int4_tbl b on true; + f1 | f1 +-------------+------------- + 0 | 0 + 0 | 123456 + 0 | -123456 + 0 | 2147483647 + 0 | -2147483647 + 123456 | 0 + 123456 | 123456 + 123456 | -123456 + 123456 | 2147483647 + 123456 | -2147483647 + -123456 | 0 + -123456 | 123456 + -123456 | -123456 + -123456 | 2147483647 + -123456 | -2147483647 + 2147483647 | 0 + 2147483647 | 123456 + 2147483647 | -123456 + 2147483647 | 2147483647 + 2147483647 | -2147483647 + -2147483647 | 0 + -2147483647 | 123456 + -2147483647 | -123456 + -2147483647 | 2147483647 + -2147483647 | -2147483647 +(25 rows) + +--Testcase 183: +select * from int4_tbl a full join int4_tbl b on false; + f1 | f1 +-------------+------------- + | 0 + | 123456 + | -123456 + | 2147483647 + | -2147483647 + 0 | + 123456 | + -123456 | + 2147483647 | + -2147483647 | +(10 rows) + +-- +-- test for ability to use a cartesian join when necessary +-- +--Testcase 415: +create foreign table q1(i int) server sqlite_svr; +--Testcase 416: +insert into q1 values (1); +--Testcase 417: +create foreign table q2(i int) server sqlite_svr; +--Testcase 418: +insert into q2 values (0); +--Testcase 184: +explain (costs off) +select * from + tenk1 join int4_tbl on f1 = twothousand, + q1, q2 +where q1.i = thousand or q2.i = thousand; + QUERY PLAN +------------------------------------------------ + Hash Join + Hash Cond: (tenk1.twothousand = int4_tbl.f1) + -> Foreign Scan + -> Hash + -> Foreign Scan on int4_tbl +(5 rows) + +--Testcase 185: +explain (costs off) +select * from + tenk1 join int4_tbl on f1 = twothousand, + q1, q2 +where thousand = (q1.i + q2.i); + QUERY PLAN +-------------------------------------------------- + Merge Join + Merge Cond: (tenk1.thousand = ((q1.i + q2.i))) + -> Sort + Sort Key: tenk1.thousand + -> Foreign Scan + -> Materialize + -> Sort + Sort Key: ((q1.i + q2.i)) + -> Nested Loop + -> Foreign Scan on q1 + -> Materialize + -> Foreign Scan on q2 +(12 rows) + +-- +-- test ability to generate a suitable plan for a star-schema query +-- +--Testcase 186: +explain (costs off) +select * from + tenk1, int8_tbl a, int8_tbl b +where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2; + QUERY PLAN +---------------------------------------- + Hash Join + Hash Cond: (tenk1.tenthous = b.q1) + -> Foreign Scan + -> Hash + -> Foreign Scan on int8_tbl b +(5 rows) + +-- +-- test a corner case in which we shouldn't apply the star-schema optimization +-- +--Testcase 187: +explain (costs off) +select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from + tenk1 t1 + inner join int4_tbl i1 + left join (select v1.x2, v2.y1, 11 AS d1 + from (select 1,0 from onerow) v1(x1,x2) + left join (select 3,1 from onerow) v2(y1,y2) + on v1.x1 = v2.y2) subq1 + on (i1.f1 = subq1.x2) + on (t1.unique2 = subq1.d1) + left join tenk1 t2 + on (subq1.y1 = t2.unique1) +where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop + -> Nested Loop + Join Filter: ((t1.stringu1 > t2.stringu2) AND ((3) = t2.unique1)) + -> Nested Loop + Join Filter: ((11) = t1.unique2) + -> Nested Loop + -> Seq Scan on onerow + -> Seq Scan on onerow onerow_1 + -> Foreign Scan on tenk1 t1 + -> Foreign Scan on tenk1 t2 + -> Foreign Scan on int4_tbl i1 +(11 rows) + +--Testcase 188: +select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from + tenk1 t1 + inner join int4_tbl i1 + left join (select v1.x2, v2.y1, 11 AS d1 + from (select 1,0 from onerow) v1(x1,x2) + left join (select 3,1 from onerow) v2(y1,y2) + on v1.x1 = v2.y2) subq1 + on (i1.f1 = subq1.x2) + on (t1.unique2 = subq1.d1) + left join tenk1 t2 + on (subq1.y1 = t2.unique1) +where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; + unique2 | stringu1 | unique1 | stringu2 +---------+----------+---------+---------- + 11 | WFAAAA | 3 | LKIAAA +(1 row) + +-- variant that isn't quite a star-schema case +--Testcase 189: +select ss1.d1 from + tenk1 as t1 + inner join tenk1 as t2 + on t1.tenthous = t2.ten + inner join + int8_tbl as i8 + left join int4_tbl as i4 + inner join (select 64::information_schema.cardinal_number as d1 + from tenk1 t3, + lateral (select abs(t3.unique1) + random()) ss0(x) + where t3.fivethous < 0) as ss1 + on i4.f1 = ss1.d1 + on i8.q1 = i4.f1 + on t1.tenthous = ss1.d1 +where t1.unique1 < i4.f1; + d1 +---- +(0 rows) + +-- this variant is foldable by the remove-useless-RESULT-RTEs code +--Testcase 419: +explain (costs off) +select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from + tenk1 t1 + inner join int4_tbl i1 + left join (select v1.x2, v2.y1, 11 AS d1 + from (values(1,0)) v1(x1,x2) + left join (values(3,1)) v2(y1,y2) + on v1.x1 = v2.y2) subq1 + on (i1.f1 = subq1.x2) + on (t1.unique2 = subq1.d1) + left join tenk1 t2 + on (subq1.y1 = t2.unique1) +where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; + QUERY PLAN +----------------------------------------------------- + Hash Join + Hash Cond: (t2.unique1 = (3)) + Join Filter: (t1.stringu1 > t2.stringu2) + -> Foreign Scan on tenk1 t2 + -> Hash + -> Hash Join + Hash Cond: (t1.unique2 = (11)) + -> Foreign Scan on tenk1 t1 + -> Hash + -> Foreign Scan on int4_tbl i1 +(10 rows) + +--Testcase 420: +select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from + tenk1 t1 + inner join int4_tbl i1 + left join (select v1.x2, v2.y1, 11 AS d1 + from (values(1,0)) v1(x1,x2) + left join (values(3,1)) v2(y1,y2) + on v1.x1 = v2.y2) subq1 + on (i1.f1 = subq1.x2) + on (t1.unique2 = subq1.d1) + left join tenk1 t2 + on (subq1.y1 = t2.unique1) +where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; + unique2 | stringu1 | unique1 | stringu2 +---------+----------+---------+---------- + 11 | WFAAAA | 3 | LKIAAA +(1 row) + +-- Here's a variant that we can't fold too aggressively, though, +-- or we end up with noplace to evaluate the lateral PHV +--Testcase 421: +explain (verbose, costs off) +select * from + (select key1 as x from sub_tbl) ss1 left join (select key6 as y from sub_tbl) ss2 on (true), + lateral (select ss2.y as z limit 1) ss3; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Nested Loop + Output: sub_tbl.key1, sub_tbl_1.key6, (sub_tbl_1.key6) + -> Nested Loop Left Join + Output: sub_tbl.key1, sub_tbl_1.key6 + -> Foreign Scan on public.sub_tbl + Output: sub_tbl.key1, sub_tbl.key3, sub_tbl.key5, sub_tbl.key6, sub_tbl.value1, sub_tbl.id + SQLite query: SELECT `key1` FROM main."sub_tbl" + -> Materialize + Output: sub_tbl_1.key6 + -> Foreign Scan on public.sub_tbl sub_tbl_1 + Output: sub_tbl_1.key6 + SQLite query: SELECT `key6` FROM main."sub_tbl" + -> Limit + Output: (sub_tbl_1.key6) + -> Result + Output: sub_tbl_1.key6 +(16 rows) + +--Testcase 422: +select * from + (select key1 as x from sub_tbl as x) ss1 left join (select key6 as y from sub_tbl) ss2 on (true), + lateral (select ss2.y as z limit 1) ss3; + x | y | z +---+---+--- + 1 | 2 | 2 +(1 row) + +-- Test proper handling of appendrel PHVs during useless-RTE removal +--Testcase 516: +explain (costs off) +select * from + (select 0 as z) as t1 + left join + (select true as a) as t2 + on true, + lateral (select true as b + union all + select a as b) as t3 +where b; + QUERY PLAN +--------------------------------------- + Nested Loop + -> Result + -> Append + -> Result + -> Result + One-Time Filter: (true) +(6 rows) + +--Testcase 517: +select * from + (select 0 as z) as t1 + left join + (select true as a) as t2 + on true, + lateral (select true as b + union all + select a as b) as t3 +where b; + z | a | b +---+---+--- + 0 | t | t + 0 | t | t +(2 rows) + +-- Test PHV in a semijoin qual, which confused useless-RTE removal (bug #17700) +--Testcase 569: +explain (verbose, costs off) +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + QUERY PLAN +---------------------------- + Result + Output: 1 + One-Time Filter: (1 = 1) +(3 rows) + +--Testcase 570: +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + f1 +---- + 1 +(1 row) + +-- Test PHV that winds up in a Result node, despite having nonempty nullingrels +--Testcase 571: +explain (verbose, costs off) +select table_catalog, table_name +from int4_tbl t1 + inner join (int8_tbl t2 + left join information_schema.column_udt_usage on null) + on null; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Result + Output: (current_database())::information_schema.sql_identifier, (c.relname)::information_schema.sql_identifier + One-Time Filter: false +(3 rows) + +-- Test handling of qual pushdown to appendrel members with non-Var outputs +--Testcase 572: +explain (verbose, costs off) +select * from int4_tbl left join ( + select text 'foo' union all select text 'bar' +) ss(x) on true +where ss.x is null; + QUERY PLAN +-------------------------------------------------------- + Nested Loop Left Join + Output: int4_tbl.f1, ('foo'::text) + Filter: (('foo'::text) IS NULL) + -> Foreign Scan on public.int4_tbl + Output: int4_tbl.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: ('foo'::text) + -> Append + -> Result + Output: 'foo'::text + -> Result + Output: 'bar'::text +(13 rows) + +-- +-- test inlining of immutable functions +-- +--Testcase 423: +create function f_immutable_int4(i integer) returns integer as +$$ begin return i; end; $$ language plpgsql immutable; +-- check optimization of function scan with join +--Testcase 424: +explain (costs off) +select unique1 from tenk1, (select * from f_immutable_int4(1) x) x +where x = unique1; + QUERY PLAN +----------------------- + Foreign Scan on tenk1 +(1 row) + +--Testcase 425: +explain (verbose, costs off) +select unique1, x.* +from tenk1, (select *, random() from f_immutable_int4(1) x) x +where x = unique1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Hash Join + Output: tenk1.unique1, (1), (random()) + Hash Cond: (tenk1.unique1 = (1)) + -> Foreign Scan on public.tenk1 + Output: tenk1.unique1, tenk1.unique2, tenk1.two, tenk1.four, tenk1.ten, tenk1.twenty, tenk1.hundred, tenk1.thousand, tenk1.twothousand, tenk1.fivethous, tenk1.tenthous, tenk1.odd, tenk1.even, tenk1.stringu1, tenk1.stringu2, tenk1.string4 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Hash + Output: (1), (random()) + -> Result + Output: 1, random() +(10 rows) + +--Testcase 426: +explain (costs off) +select unique1 from tenk1, f_immutable_int4(1) x where x = unique1; + QUERY PLAN +----------------------- + Foreign Scan on tenk1 +(1 row) + +--Testcase 427: +explain (costs off) +select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1; + QUERY PLAN +----------------------- + Foreign Scan on tenk1 +(1 row) + +--Testcase 538: +explain (costs off) +select unique1 from tenk1, lateral f_immutable_int4(1) x where x in (select 17); + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +--Testcase 428: +explain (costs off) +select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x; + QUERY PLAN +----------------------- + Foreign Scan on tenk1 +(1 row) + +--Testcase 429: +explain (costs off) +select unique1, x from tenk1 left join f_immutable_int4(1) x on unique1 = x; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + Join Filter: (tenk1.unique1 = 1) + -> Foreign Scan on tenk1 + -> Materialize + -> Result +(5 rows) + +--Testcase 430: +explain (costs off) +select unique1, x from tenk1 right join f_immutable_int4(1) x on unique1 = x; + QUERY PLAN +----------------------------- + Nested Loop Left Join + -> Result + -> Foreign Scan on tenk1 +(3 rows) + +--Testcase 431: +explain (costs off) +select unique1, x from tenk1 full join f_immutable_int4(1) x on unique1 = x; + QUERY PLAN +------------------------------------ + Hash Full Join + Hash Cond: (tenk1.unique1 = (1)) + -> Foreign Scan on tenk1 + -> Hash + -> Result +(5 rows) + +-- check that pullup of a const function allows further const-folding +--Testcase 432: +explain (costs off) +select unique1 from tenk1, f_immutable_int4(1) x where x = 42; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +-- test inlining of immutable functions with PlaceHolderVars +--Testcase 433: +explain (costs off) +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 or i4 = 42) AS b3 + from nt2 as nt2 + left join + f_immutable_int4(0) i4 + on i4 = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + QUERY PLAN +--------------------------------------- + Hash Right Join + Hash Cond: (nt2.id = nt3.nt2_id) + Filter: ((nt2.b1 OR ((0) = 42))) + -> Nested Loop Left Join + Join Filter: (0 = nt2.nt1_id) + -> Foreign Scan on nt2 + -> Materialize + -> Result + -> Hash + -> Foreign Scan on nt3 +(10 rows) + +--Testcase 434: +drop function f_immutable_int4(int); +-- test inlining when function returns composite +--Testcase 435: +create function mki8(bigint, bigint) returns int8_tbl as +$$select row($1,$2)::int8_tbl$$ language sql; +--Testcase 436: +create function mki4(int) returns int4_tbl as +$$select row($1)::int4_tbl$$ language sql; +--Testcase 437: +explain (verbose, costs off) +select * from mki8(1,2); + QUERY PLAN +------------------------------------ + Function Scan on mki8 + Output: q1, q2 + Function Call: '(1,2)'::int8_tbl +(3 rows) + +--Testcase 438: +select * from mki8(1,2); + q1 | q2 +----+---- + 1 | 2 +(1 row) + +--Testcase 439: +explain (verbose, costs off) +select * from mki4(42); + QUERY PLAN +----------------------------------- + Function Scan on mki4 + Output: f1 + Function Call: '(42)'::int4_tbl +(3 rows) + +--Testcase 440: +select * from mki4(42); + f1 +---- + 42 +(1 row) + +--Testcase 441: +drop function mki8(bigint, bigint); +--Testcase 442: +drop function mki4(int); +-- test const-folding of a whole-row Var into a per-field Var +-- (need to inline a function to reach this case, else parser does it) +--Testcase 632: +create function f_field_select(t onek) returns int4 as +$$ select t.unique2; $$ language sql immutable; +--Testcase 633: +explain (verbose, costs off) +select (t2.*).unique1, f_field_select(t2) from tenk1 t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join int8_tbl t3 on true; + QUERY PLAN +-------------------------------------------------------------------------------- + Nested Loop Left Join + Output: t2.unique1, t2.unique2 + -> Merge Right Join + Output: t2.unique1, t2.unique2 + Merge Cond: (t2.unique1 = t1.unique1) + -> Sort + Output: t2.unique1, t2.unique2 + Sort Key: t2.unique1 + -> Foreign Scan on public.onek t2 + Output: t2.unique1, t2.unique2 + SQLite query: SELECT `unique1`, `unique2` FROM main."onek" + -> Sort + Output: t1.unique1 + Sort Key: t1.unique1 + -> Foreign Scan on public.tenk1 t1 + Output: t1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" + -> Materialize + -> Foreign Scan on public.int8_tbl t3 + SQLite query: SELECT NULL FROM main."int8_tbl" +(20 rows) + +--Testcase 634: +drop function f_field_select(t onek); +-- +-- test extraction of restriction OR clauses from join OR clause +-- (we used to only do this for indexable clauses) +-- +--Testcase 190: +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.hundred = 4); + QUERY PLAN +------------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.hundred = 4))) + -> Foreign Scan on tenk1 a + -> Materialize + -> Foreign Scan on tenk1 b +(5 rows) + +--Testcase 191: +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.ten = 4); + QUERY PLAN +--------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.ten = 4))) + -> Foreign Scan on tenk1 a + -> Materialize + -> Foreign Scan on tenk1 b +(5 rows) + +--Testcase 192: +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 = 1 and b.unique1 = 2) or + ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4))) + -> Foreign Scan on tenk1 a + -> Materialize + -> Foreign Scan on tenk1 b +(5 rows) + +-- +-- test placement of movable quals in a parameterized join tree +-- +--Testcase 193: +explain (costs off) +select * from tenk1 t1 left join + (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) + on t1.hundred = t2.hundred and t1.ten = t3.ten +where t1.unique1 = 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 194: +explain (costs off) +select * from tenk1 t1 left join + (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) + on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten +where t1.unique1 = 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 195: +explain (costs off) +select count(*) from + tenk1 a join tenk1 b on a.unique1 = b.unique2 + left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand + join int4_tbl on b.thousand = f1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 196: +select count(*) from + tenk1 a join tenk1 b on a.unique1 = b.unique2 + left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand + join int4_tbl on b.thousand = f1; + count +------- + 10 +(1 row) + +--Testcase 197: +explain (costs off) +select b.unique1 from + tenk1 a join tenk1 b on a.unique1 = b.unique2 + left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand + join int4_tbl i1 on b.thousand = f1 + right join int4_tbl i2 on i2.f1 = b.tenthous + order by 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 198: +select b.unique1 from + tenk1 a join tenk1 b on a.unique1 = b.unique2 + left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand + join int4_tbl i1 on b.thousand = f1 + right join int4_tbl i2 on i2.f1 = b.tenthous + order by 1; + unique1 +--------- + 0 + + + + +(5 rows) + +--Testcase 199: +explain (costs off) +select * from +( + select unique1, q1, coalesce(unique1, -1) + q1 as fault + from int8_tbl left join tenk1 on (q2 = unique2) +) ss +where fault = 122 +order by fault; + QUERY PLAN +-------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (int8_tbl.q2 = tenk1.unique2) + Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122) + -> Sort + Sort Key: int8_tbl.q2 + -> Foreign Scan on int8_tbl + -> Sort + Sort Key: tenk1.unique2 + -> Foreign Scan on tenk1 +(9 rows) + +--Testcase 200: +select * from +( + select unique1, q1, coalesce(unique1, -1) + q1 as fault + from int8_tbl left join tenk1 on (q2 = unique2) +) ss +where fault = 122 +order by fault; + unique1 | q1 | fault +---------+-----+------- + | 123 | 122 +(1 row) + +--Testcase 201: +explain (costs off) +select * from +(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) +left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x +left join unnest(v1ys) as u1(u1y) on u1y = v2y; + QUERY PLAN +------------------------------------------------------------- + Nested Loop Left Join + -> Values Scan on "*VALUES*" + -> Hash Right Join + Hash Cond: (u1.u1y = "*VALUES*_1".column2) + Filter: ("*VALUES*_1".column1 = "*VALUES*".column1) + -> Function Scan on unnest u1 + -> Hash + -> Values Scan on "*VALUES*_1" +(8 rows) + +--Testcase 202: +select * from +(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) +left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x +left join unnest(v1ys) as u1(u1y) on u1y = v2y; + v1x | v1ys | v2x | v2y | u1y +-----+---------+-----+-----+----- + 1 | {10,20} | 1 | 10 | 10 + 2 | {20,30} | 2 | 20 | 20 +(2 rows) + +-- +-- test handling of potential equivalence clauses above outer joins +-- +--Testcase 203: +explain (costs off) +select q1, unique2, thousand, hundred + from int8_tbl a left join tenk1 b on q1 = unique2 + where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Merge Right Join + Merge Cond: (b.unique2 = a.q1) + Filter: ((COALESCE(b.thousand, 123) = COALESCE(b.hundred, 123)) AND (a.q1 = COALESCE(b.hundred, 123))) + -> Sort + Sort Key: b.unique2 + -> Foreign Scan on tenk1 b + -> Sort + Sort Key: a.q1 + -> Foreign Scan on int8_tbl a +(9 rows) + +--Testcase 204: +select q1, unique2, thousand, hundred + from int8_tbl a left join tenk1 b on q1 = unique2 + where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); + q1 | unique2 | thousand | hundred +----+---------+----------+--------- +(0 rows) + +--Testcase 205: +explain (costs off) +select f1, unique2, case when unique2 is null then f1 else 0 end + from int4_tbl a left join tenk1 b on f1 = unique2 + where (case when unique2 is null then f1 else 0 end) = 0; + QUERY PLAN +-------------------------------------------------------------------- + Merge Left Join + Merge Cond: (a.f1 = b.unique2) + Filter: (CASE WHEN (b.unique2 IS NULL) THEN a.f1 ELSE 0 END = 0) + -> Sort + Sort Key: a.f1 + -> Foreign Scan on int4_tbl a + -> Sort + Sort Key: b.unique2 + -> Foreign Scan on tenk1 b +(9 rows) + +--Testcase 206: +select f1, unique2, case when unique2 is null then f1 else 0 end + from int4_tbl a left join tenk1 b on f1 = unique2 + where (case when unique2 is null then f1 else 0 end) = 0; + f1 | unique2 | case +----+---------+------ + 0 | 0 | 0 +(1 row) + +-- +-- another case with equivalence clauses above outer joins (bug #8591) +-- +--Testcase 207: +explain (costs off) +select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) + from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) + where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; + QUERY PLAN +--------------------------------------------------------------- + Nested Loop Left Join + -> Merge Left Join + Merge Cond: (a.unique1 = b.thousand) + Filter: (COALESCE(b.twothousand, a.twothousand) = 44) + -> Sort + Sort Key: a.unique1 + -> Foreign Scan on tenk1 a + -> Sort + Sort Key: b.thousand + -> Foreign Scan on tenk1 b + -> Materialize + -> Foreign Scan on tenk1 c +(12 rows) + +--Testcase 208: +select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) + from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) + where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; + unique1 | unique1 | unique1 | coalesce +---------+---------+---------+---------- +(0 rows) + +-- related case +--Testcase 573: +explain (costs off) +select * from int8_tbl t1 left join int8_tbl t2 on t1.q2 = t2.q1, + lateral (select * from int8_tbl t3 where t2.q1 = t2.q2) ss; + QUERY PLAN +----------------------------------------------------- + Nested Loop + -> Foreign Scan on int8_tbl t3 + -> Materialize + -> Merge Left Join + Merge Cond: (t1.q2 = t2.q1) + Filter: (t2.q1 = t2.q2) + -> Sort + Sort Key: t1.q2 + -> Foreign Scan on int8_tbl t1 + -> Sort + Sort Key: t2.q1 + -> Foreign Scan on int8_tbl t2 +(12 rows) + +--Testcase 574: +select * from int8_tbl t1 left join int8_tbl t2 on t1.q2 = t2.q1, + lateral (select * from int8_tbl t3 where t2.q1 = t2.q2) ss; + q1 | q2 | q1 | q2 | q1 | q2 +------------------+------------------+------------------+------------------+------------------+------------------- + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 456 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 456 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 +(10 rows) + +-- +-- check handling of join aliases when flattening multiple levels of subquery +-- +--Testcase 209: +explain (verbose, costs off) +select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from + (values (0),(1)) foo1(join_key) +left join + (select join_key, bug_field from + (select ss1.join_key, ss1.bug_field from + (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 + ) foo2 + left join + (select unique2 as join_key from tenk1 i2) ss2 + using (join_key) + ) foo3 +using (join_key); + QUERY PLAN +---------------------------------------------------------------------- + Merge Right Join + Output: "*VALUES*".column1, i1.f1, (666) + Merge Cond: (i1.f1 = "*VALUES*".column1) + -> Merge Left Join + Output: i1.f1, 666 + Merge Cond: (i1.f1 = i2.unique2) + -> Sort + Output: i1.f1 + Sort Key: i1.f1 + -> Foreign Scan on public.int4_tbl i1 + Output: i1.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Sort + Output: i2.unique2 + Sort Key: i2.unique2 + -> Foreign Scan on public.tenk1 i2 + Output: i2.unique2 + SQLite query: SELECT `unique2` FROM main."tenk1" + -> Sort + Output: "*VALUES*".column1 + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1 +(23 rows) + +--Testcase 210: +select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from + (values (0),(1)) foo1(join_key) +left join + (select join_key, bug_field from + (select ss1.join_key, ss1.bug_field from + (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 + ) foo2 + left join + (select unique2 as join_key from tenk1 i2) ss2 + using (join_key) + ) foo3 +using (join_key); + foo1_id | foo3_id | bug_field +---------+---------+----------- + 0 | 0 | 666 + 1 | | +(2 rows) + +-- +-- check handling of a variable-free join alias +-- +--Testcase 575: +explain (verbose, costs off) +select * from +int4_tbl i0 left join +( (select *, 123 as x from int4_tbl i1) ss1 + left join + (select *, q2 as x from int8_tbl i2) ss2 + using (x) +) ss0 +on (i0.f1 = ss0.f1) +order by i0.f1, x; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Incremental Sort + Output: i0.f1, ('123'::bigint), i1.f1, i2.q1, i2.q2 + Sort Key: i0.f1, ('123'::bigint) + Presorted Key: i0.f1 + -> Merge Left Join + Output: i0.f1, ('123'::bigint), i1.f1, i2.q1, i2.q2 + Merge Cond: (i0.f1 = i1.f1) + -> Sort + Output: i0.f1 + Sort Key: i0.f1 + -> Foreign Scan on public.int4_tbl i0 + Output: i0.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Sort + Output: i1.f1, i2.q1, i2.q2, ('123'::bigint) + Sort Key: i1.f1 + -> Nested Loop Left Join + Output: i1.f1, i2.q1, i2.q2, '123'::bigint + -> Foreign Scan on public.int4_tbl i1 + Output: i1.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: i2.q1, i2.q2 + -> Foreign Scan on public.int8_tbl i2 + Output: i2.q1, i2.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((123 = `q2`)) +(26 rows) + +--Testcase 576: +select * from +int4_tbl i0 left join +( (select *, 123 as x from int4_tbl i1) ss1 + left join + (select *, q2 as x from int8_tbl i2) ss2 + using (x) +) ss0 +on (i0.f1 = ss0.f1) +order by i0.f1, x; + f1 | x | f1 | q1 | q2 +-------------+-----+-------------+------------------+----- + -2147483647 | 123 | -2147483647 | 4567890123456789 | 123 + -123456 | 123 | -123456 | 4567890123456789 | 123 + 0 | 123 | 0 | 4567890123456789 | 123 + 123456 | 123 | 123456 | 4567890123456789 | 123 + 2147483647 | 123 | 2147483647 | 4567890123456789 | 123 +(5 rows) + +-- +-- test successful handling of nested outer joins with degenerate join quals +-- +--Testcase 443: +create foreign table text_tbl(f1 text) server sqlite_svr; +--Testcase 211: +explain (verbose, costs off) +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Merge Right Join + Output: t1.f1 + Merge Cond: (i4.f1 = i8.q2) + -> Sort + Output: i4.f1 + Sort Key: i4.f1 + -> Foreign Scan on public.int4_tbl i4 + Output: i4.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: t1.f1, i8.q2 + -> Sort + Output: t1.f1, i8.q2 + Sort Key: i8.q2 + -> Nested Loop Left Join + Output: t1.f1, i8.q2 + Join Filter: (t1.f1 = '***'::text) + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q2 + -> Merge Left Join + Output: i8.q2 + Merge Cond: (i8b1.q2 = (NULL::integer)) + -> Sort + Output: i8b1.q2 + Sort Key: i8b1.q2 + -> Foreign Scan on public.int8_tbl i8b1 + Output: i8b1.q2 + SQLite query: SELECT `q2` FROM main."int8_tbl" + -> Sort + Output: i8.q2, (NULL::integer) + Sort Key: (NULL::integer) + -> Merge Join + Output: i8.q2, (NULL::integer) + Merge Cond: (i8.q1 = i8b2.q1) + -> Sort + Output: i8.q1, i8.q2 + Sort Key: i8.q1 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Sort + Output: i8b2.q1, (NULL::integer) + Sort Key: i8b2.q1 + -> Foreign Scan on public.int8_tbl i8b2 + Output: i8b2.q1, NULL::integer + SQLite query: SELECT `q1` FROM main."int8_tbl" +(49 rows) + +--Testcase 212: +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + f1 +------------------- + doh! + hi de ho neighbor +(2 rows) + +--Testcase 213: +explain (verbose, costs off) +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Hash Left Join + Output: t1.f1 + Hash Cond: (i8.q2 = i4.f1) + -> Nested Loop Left Join + Output: t1.f1, i8.q2 + Join Filter: (t1.f1 = '***'::text) + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q2 + -> Merge Left Join + Output: i8.q2 + Merge Cond: (i8b1.q2 = (NULL::integer)) + -> Sort + Output: i8b1.q2 + Sort Key: i8b1.q2 + -> Foreign Scan on public.int8_tbl i8b1 + Output: i8b1.q2 + SQLite query: SELECT `q2` FROM main."int8_tbl" + -> Materialize + Output: i8.q2, (NULL::integer) + -> Sort + Output: i8.q2, (NULL::integer) + Sort Key: (NULL::integer) + -> Merge Left Join + Output: i8.q2, (NULL::integer) + Merge Cond: (i8.q1 = i8b2.q1) + -> Sort + Output: i8.q1, i8.q2 + Sort Key: i8.q1 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Materialize + Output: i8b2.q1, (NULL::integer) + -> Sort + Output: i8b2.q1, (NULL::integer) + Sort Key: i8b2.q1 + -> Nested Loop + Output: i8b2.q1, NULL::integer + -> Foreign Scan on public.int4_tbl i4b2 + Output: i4b2.f1 + SQLite query: SELECT NULL FROM main."int4_tbl" + -> Materialize + Output: i8b2.q1 + -> Foreign Scan on public.int8_tbl i8b2 + Output: i8b2.q1 + SQLite query: SELECT `q1` FROM main."int8_tbl" + -> Hash + Output: i4.f1 + -> Foreign Scan on public.int4_tbl i4 + Output: i4.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" +(54 rows) + +--Testcase 214: +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + f1 +------------------- + doh! + hi de ho neighbor +(2 rows) + +--Testcase 215: +explain (verbose, costs off) +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 + where q1 = f1) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Merge Right Join + Output: t1.f1 + Merge Cond: (i4.f1 = i8.q2) + -> Sort + Output: i4.f1 + Sort Key: i4.f1 + -> Foreign Scan on public.int4_tbl i4 + Output: i4.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: t1.f1, i8.q2 + -> Sort + Output: t1.f1, i8.q2 + Sort Key: i8.q2 + -> Nested Loop Left Join + Output: t1.f1, i8.q2 + Join Filter: (t1.f1 = '***'::text) + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q2 + -> Merge Left Join + Output: i8.q2 + Merge Cond: (i8b1.q2 = (NULL::integer)) + -> Sort + Output: i8b1.q2 + Sort Key: i8b1.q2 + -> Foreign Scan on public.int8_tbl i8b1 + Output: i8b1.q2 + SQLite query: SELECT `q2` FROM main."int8_tbl" + -> Materialize + Output: i8.q2, (NULL::integer) + -> Sort + Output: i8.q2, (NULL::integer) + Sort Key: (NULL::integer) + -> Merge Left Join + Output: i8.q2, (NULL::integer) + Merge Cond: (i8.q1 = i8b2.q1) + -> Sort + Output: i8.q1, i8.q2 + Sort Key: i8.q1 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Materialize + Output: i8b2.q1, (NULL::integer) + -> Merge Join + Output: i8b2.q1, NULL::integer + Merge Cond: (i8b2.q1 = i4b2.f1) + -> Sort + Output: i8b2.q1 + Sort Key: i8b2.q1 + -> Foreign Scan on public.int8_tbl i8b2 + Output: i8b2.q1 + SQLite query: SELECT `q1` FROM main."int8_tbl" + -> Sort + Output: i4b2.f1 + Sort Key: i4b2.f1 + -> Foreign Scan on public.int4_tbl i4b2 + Output: i4b2.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" +(62 rows) + +--Testcase 216: +select t1.* from + text_tbl t1 + left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 + left join int8_tbl i8 + left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 + where q1 = f1) b2 + on (i8.q1 = b2.q1) + on (b2.d2 = b1.q2) + on (t1.f1 = b1.d1) + left join int4_tbl i4 + on (i8.q2 = i4.f1); + f1 +------------------- + doh! + hi de ho neighbor +(2 rows) + +--Testcase 217: +explain (verbose, costs off) +select * from + text_tbl t1 + inner join int8_tbl i8 + on i8.q2 = 456 + right join text_tbl t2 + on t1.f1 = 'doh!' + left join int4_tbl i4 + on i8.q1 = i4.f1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Nested Loop Left Join + Output: t1.f1, i8.q1, i8.q2, t2.f1, i4.f1 + -> Foreign Scan on public.text_tbl t2 + Output: t2.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q1, i8.q2, i4.f1, t1.f1 + -> Nested Loop + Output: i8.q1, i8.q2, i4.f1, t1.f1 + -> Foreign Scan + Output: i8.q1, i8.q2, i4.f1 + SQLite query: SELECT r2.`q1`, r2.`q2`, r6.`f1` FROM (main."int8_tbl" r2 LEFT JOIN main."int4_tbl" r6 ON (((r2.`q1` = r6.`f1`)))) WHERE ((r2.`q2` = 456)) + -> Materialize + Output: t1.f1 + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'doh!')) +(17 rows) + +--Testcase 218: +select * from + text_tbl t1 + inner join int8_tbl i8 + on i8.q2 = 456 + right join text_tbl t2 + on t1.f1 = 'doh!' + left join int4_tbl i4 + on i8.q1 = i4.f1; + f1 | q1 | q2 | f1 | f1 +------+-----+-----+-------------------+---- + doh! | 123 | 456 | doh! | + doh! | 123 | 456 | hi de ho neighbor | +(2 rows) + +-- check handling of a variable-free qual for a non-commutable outer join +--Testcase 577: +explain (costs off) +select nspname +from (select 1 as x) ss1 +left join +( select n.nspname, c.relname + from pg_class c left join pg_namespace n on n.oid = c.relnamespace + where c.relkind = 'r' +) ss2 on false; + QUERY PLAN +-------------------------------- + Nested Loop Left Join + Join Filter: false + -> Result + -> Result + One-Time Filter: false +(5 rows) + +-- check handling of apparently-commutable outer joins with non-commutable +-- joins between them +--Testcase 578: +explain (costs off) +select 1 from + int4_tbl i4 + left join int8_tbl i8 on i4.f1 is not null + left join (select 1 as a) ss1 on null + join int4_tbl i42 on ss1.a is null or i8.q1 <> i8.q2 + right join (select 2 as b) ss2 + on ss2.b < i4.f1; + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + -> Result + -> Nested Loop + -> Nested Loop Left Join + Join Filter: NULL::boolean + Filter: (((1) IS NULL) OR (i8.q1 <> i8.q2)) + -> Nested Loop Left Join + Join Filter: (i4.f1 IS NOT NULL) + -> Foreign Scan on int4_tbl i4 + -> Materialize + -> Foreign Scan on int8_tbl i8 + -> Result + One-Time Filter: false + -> Materialize + -> Foreign Scan on int4_tbl i42 +(15 rows) + +-- +-- test for appropriate join order in the presence of lateral references +-- +--Testcase 219: +explain (verbose, costs off) +select * from + text_tbl t1 + left join int8_tbl i8 + on i8.q2 = 123, + lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss +where t1.f1 = ss.f1; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Nested Loop + Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 + Join Filter: (t1.f1 = t2.f1) + -> Nested Loop Left Join + Output: t1.f1, i8.q1, i8.q2 + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q1, i8.q2 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((`q2` = 123)) + -> Foreign Scan on public.text_tbl t2 + Output: i8.q1, t2.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" LIMIT 1 +(16 rows) + +--Testcase 220: +select * from + text_tbl t1 + left join int8_tbl i8 + on i8.q2 = 123, + lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss +where t1.f1 = ss.f1; + f1 | q1 | q2 | q1 | f1 +------+------------------+-----+------------------+------ + doh! | 4567890123456789 | 123 | 4567890123456789 | doh! +(1 row) + +--Testcase 221: +explain (verbose, costs off) +select * from + text_tbl t1 + left join int8_tbl i8 + on i8.q2 = 123, + lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, + lateral (select ss1.* from text_tbl t3 limit 1) as ss2 +where t1.f1 = ss2.f1; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Nested Loop + Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1, ((i8.q1)), (t2.f1) + Join Filter: (t1.f1 = (t2.f1)) + -> Nested Loop + Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 + -> Nested Loop Left Join + Output: t1.f1, i8.q1, i8.q2 + -> Foreign Scan on public.text_tbl t1 + Output: t1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" + -> Materialize + Output: i8.q1, i8.q2 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((`q2` = 123)) + -> Foreign Scan on public.text_tbl t2 + Output: i8.q1, t2.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" LIMIT 1 + -> Memoize + Output: ((i8.q1)), (t2.f1) + Cache Key: (i8.q1), t2.f1 + Cache Mode: binary + -> Foreign Scan on public.text_tbl t3 + Output: (i8.q1), t2.f1 + SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 +(25 rows) + +--Testcase 222: +select * from + text_tbl t1 + left join int8_tbl i8 + on i8.q2 = 123, + lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, + lateral (select ss1.* from text_tbl t3 limit 1) as ss2 +where t1.f1 = ss2.f1; + f1 | q1 | q2 | q1 | f1 | q1 | f1 +------+------------------+-----+------------------+------+------------------+------ + doh! | 4567890123456789 | 123 | 4567890123456789 | doh! | 4567890123456789 | doh! +(1 row) + +--Testcase 223: +explain (verbose, costs off) +select 1 from + text_tbl as tt1 + inner join text_tbl as tt2 on (tt1.f1 = 'foo') + left join text_tbl as tt3 on (tt3.f1 = 'foo') + left join text_tbl as tt4 on (tt3.f1 = tt4.f1), + lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 +where tt1.f1 = ss1.c0; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Nested Loop + Output: 1 + -> Hash Left Join + Output: tt1.f1, tt4.f1 + Hash Cond: (tt3.f1 = tt4.f1) + -> Nested Loop Left Join + Output: tt1.f1, tt3.f1 + -> Nested Loop + Output: tt1.f1 + -> Foreign Scan on public.text_tbl tt2 + Output: tt2.f1 + SQLite query: SELECT NULL FROM main."text_tbl" + -> Materialize + Output: tt1.f1 + -> Foreign Scan on public.text_tbl tt1 + Output: tt1.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'foo')) + -> Materialize + Output: tt3.f1 + -> Foreign Scan on public.text_tbl tt3 + Output: tt3.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'foo')) + -> Hash + Output: tt4.f1 + -> Foreign Scan on public.text_tbl tt4 + Output: tt4.f1 + SQLite query: SELECT `f1` FROM main."text_tbl" WHERE ((`f1` = 'foo')) + -> Subquery Scan on ss1 + Output: ss1.c0 + Filter: (ss1.c0 = 'foo'::text) + -> Foreign Scan on public.text_tbl tt5 + Output: tt4.f1 + SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 +(33 rows) + +--Testcase 224: +select 1 from + text_tbl as tt1 + inner join text_tbl as tt2 on (tt1.f1 = 'foo') + left join text_tbl as tt3 on (tt3.f1 = 'foo') + left join text_tbl as tt4 on (tt3.f1 = tt4.f1), + lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 +where tt1.f1 = ss1.c0; + ?column? +---------- +(0 rows) + +--Testcase 579: +explain (verbose, costs off) +select 1 from + int4_tbl as i4 + inner join + ((select 42 as n from int4_tbl x1 left join int8_tbl x2 on f1 = q1) as ss1 + right join (select 1 as z) as ss2 on true) + on false, + lateral (select i4.f1, ss1.n from int8_tbl as i8 limit 1) as ss3; + QUERY PLAN +-------------------------- + Result + Output: 1 + One-Time Filter: false +(3 rows) + +--Testcase 580: +select 1 from + int4_tbl as i4 + inner join + ((select 42 as n from int4_tbl x1 left join int8_tbl x2 on f1 = q1) as ss1 + right join (select 1 as z) as ss2 on true) + on false, + lateral (select i4.f1, ss1.n from int8_tbl as i8 limit 1) as ss3; + ?column? +---------- +(0 rows) + +-- +-- check a case where we formerly generated invalid parameterized paths +-- +begin; +--Testcase 630: +CREATE FOREIGN TABLE t (a int options (key 'true')) SERVER sqlite_svr; +--Testcase 631: +explain (costs off) +select 1 from t t1 + join lateral (select t1.a from (select 1) foo offset 0) as s1 on true + join + (select 1 from t t2 + inner join (t t3 + left join (t t4 left join t t5 on t4.a = 1) + on t3.a = t4.a) + on false + where t3.a = coalesce(t5.a,1)) as s2 + on true; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +rollback; +-- +-- check a case in which a PlaceHolderVar forces join order +-- +--Testcase 225: +explain (verbose, costs off) +select ss2.* from + int4_tbl i41 + left join int8_tbl i8 + join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 + from int4_tbl i42, int4_tbl i43) ss1 + on i8.q1 = ss1.c2 + on i41.f1 = ss1.c1, + lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 +where ss1.c2 = 0; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Nested Loop + Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42)) + -> Nested Loop + Output: i41.f1, i42.f1, i8.q1, i8.q2, i43.f1, 42 + -> Nested Loop + Output: i41.f1, i42.f1, i8.q1, i8.q2 + -> Merge Join + Output: i41.f1, i42.f1 + Merge Cond: (i41.f1 = i42.f1) + -> Sort + Output: i41.f1 + Sort Key: i41.f1 + -> Foreign Scan on public.int4_tbl i41 + Output: i41.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Sort + Output: i42.f1 + Sort Key: i42.f1 + -> Foreign Scan on public.int4_tbl i42 + Output: i42.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: i8.q1, i8.q2 + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((`q1` = 0)) + -> Materialize + Output: i43.f1 + -> Foreign Scan on public.int4_tbl i43 + Output: i43.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" WHERE ((`f1` = 0)) + -> Foreign Scan on public.text_tbl + Output: i41.f1, i8.q1, i8.q2, i42.f1, i43.f1, (42) + SQLite query: SELECT NULL FROM main."text_tbl" LIMIT 1 +(34 rows) + +--Testcase 226: +select ss2.* from + int4_tbl i41 + left join int8_tbl i8 + join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 + from int4_tbl i42, int4_tbl i43) ss1 + on i8.q1 = ss1.c2 + on i41.f1 = ss1.c1, + lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 +where ss1.c2 = 0; + f1 | q1 | q2 | c1 | c2 | c3 +----+----+----+----+----+---- +(0 rows) + +-- +-- test successful handling of full join underneath left join (bug #14105) +-- +--Testcase 227: +explain (costs off) +select * from + (select 1 as id) as xx + left join + (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) + on (xx.id = coalesce(yy.id)); + QUERY PLAN +--------------------------------------- + Nested Loop Left Join + -> Result + -> Hash Full Join + Hash Cond: (a1.unique1 = (1)) + Filter: (1 = COALESCE((1))) + -> Foreign Scan on tenk1 a1 + -> Hash + -> Result +(8 rows) + +--Testcase 228: +select * from + (select 1 as id) as xx + left join + (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) + on (xx.id = coalesce(yy.id)); + id | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | id +----+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---- + 1 | 1 | 2838 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | BAAAAA | EFEAAA | OOOOxx | 1 +(1 row) + +-- +-- test ability to push constants through outer join clauses +-- +--Testcase 229: +explain (costs off) + select * from int4_tbl a left join tenk1 b on f1 = unique2 where f1 = 0; + QUERY PLAN +------------------------------------- + Nested Loop Left Join + -> Foreign Scan on int4_tbl a + -> Materialize + -> Foreign Scan on tenk1 b +(4 rows) + +--Testcase 230: +explain (costs off) + select * from tenk1 a full join tenk1 b using(unique2) where unique2 = 42; + QUERY PLAN +------------------------------------- + Merge Full Join + -> Foreign Scan on tenk1 a + -> Materialize + -> Foreign Scan on tenk1 b +(4 rows) + +-- +-- test that quals attached to an outer join have correct semantics, +-- specifically that they don't re-use expressions computed below the join; +-- we force a mergejoin so that coalesce(b.q1, 1) appears as a join input +-- +--Testcase 518: +set enable_hashjoin to off; +--Testcase 519: +set enable_nestloop to off; +--Testcase 231: +explain (verbose, costs off) + select a.q2, b.q1 + from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) + where coalesce(b.q1, 1) > 0; + QUERY PLAN +-------------------------------------------------------------- + Merge Left Join + Output: a.q2, b.q1 + Merge Cond: (a.q2 = (COALESCE(b.q1, '1'::bigint))) + Filter: (COALESCE(b.q1, '1'::bigint) > 0) + -> Sort + Output: a.q2 + Sort Key: a.q2 + -> Foreign Scan on public.int8_tbl a + Output: a.q2 + SQLite query: SELECT `q2` FROM main."int8_tbl" + -> Sort + Output: b.q1, (COALESCE(b.q1, '1'::bigint)) + Sort Key: (COALESCE(b.q1, '1'::bigint)) + -> Foreign Scan on public.int8_tbl b + Output: b.q1, COALESCE(b.q1, '1'::bigint) + SQLite query: SELECT `q1` FROM main."int8_tbl" +(16 rows) + +--Testcase 232: +select a.q2, b.q1 + from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) + where coalesce(b.q1, 1) > 0; + q2 | q1 +-------------------+------------------ + -4567890123456789 | + 123 | 123 + 123 | 123 + 456 | + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(10 rows) + +--Testcase 520: +reset enable_hashjoin; +--Testcase 521: +reset enable_nestloop; +-- +-- test join strength reduction with a SubPlan providing the proof +-- +--Testcase 581: +explain (costs off) +select a.unique1, b.unique2 + from onek a left join onek b on a.unique1 = b.unique2 + where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Merge Join + Merge Cond: (b.unique2 = a.unique1) + -> Sort + Sort Key: b.unique2 + -> Foreign Scan on onek b + Filter: (ANY ((unique2 = (SubPlan 1).col1) AND ((random() > '0'::double precision) = (SubPlan 1).col2))) + SubPlan 1 + -> Foreign Scan on int8_tbl c + -> Sort + Sort Key: a.unique1 + -> Foreign Scan on onek a +(11 rows) + +--Testcase 582: +select a.unique1, b.unique2 + from onek a left join onek b on a.unique1 = b.unique2 + where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1); + unique1 | unique2 +---------+--------- + 123 | 123 +(1 row) + +-- +-- test full-join strength reduction +-- +--Testcase 583: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + -> Foreign Scan on onek a + -> Materialize + -> Foreign Scan on onek b +(4 rows) + +--Testcase 584: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42; + unique1 | unique2 +---------+--------- + 42 | 42 +(1 row) + +--Testcase 585: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where b.unique2 = 43; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + -> Foreign Scan on onek b + -> Materialize + -> Foreign Scan on onek a +(4 rows) + +--Testcase 586: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where b.unique2 = 43; + unique1 | unique2 +---------+--------- + 43 | 43 +(1 row) + +--Testcase 587: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42 and b.unique2 = 42; + QUERY PLAN +------------------------------------ + Nested Loop + -> Foreign Scan on onek a + -> Materialize + -> Foreign Scan on onek b +(4 rows) + +--Testcase 588: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42 and b.unique2 = 42; + unique1 | unique2 +---------+--------- + 42 | 42 +(1 row) + +-- +-- test result-RTE removal underneath a full join +-- +--Testcase 589: +explain (costs off) +select * from + (select * from int8_tbl i81 join (values(123,2)) v(v1,v2) on q2=v1) ss1 +full join + (select * from (values(456,2)) w(v1,v2) join int8_tbl i82 on q2=v1) ss2 +on true; + QUERY PLAN +------------------------------------------ + Merge Full Join + -> Foreign Scan on int8_tbl i81 + -> Materialize + -> Foreign Scan on int8_tbl i82 +(4 rows) + +--Testcase 590: +select * from + (select * from int8_tbl i81 join (values(123,2)) v(v1,v2) on q2=v1) ss1 +full join + (select * from (values(456,2)) w(v1,v2) join int8_tbl i82 on q2=v1) ss2 +on true; + q1 | q2 | v1 | v2 | v1 | v2 | q1 | q2 +------------------+-----+-----+----+-----+----+-----+----- + 4567890123456789 | 123 | 123 | 2 | 456 | 2 | 123 | 456 +(1 row) + +-- +-- test join removal +-- +begin; +--Testcase 444: +CREATE FOREIGN TABLE a3 (id int OPTIONS (key 'true'), b_id int) SERVER sqlite_svr; +--Testcase 445: +CREATE FOREIGN TABLE b3 (id int OPTIONS (key 'true'), c_id int) SERVER sqlite_svr; +--Testcase 446: +CREATE FOREIGN TABLE c3 (id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 447: +CREATE FOREIGN TABLE d3 (a int, b int) SERVER sqlite_svr; +--Testcase 233: +INSERT INTO a3 VALUES (0, 0), (1, NULL); +--Testcase 234: +INSERT INTO b3 VALUES (0, 0), (1, NULL); +--Testcase 235: +INSERT INTO c3 VALUES (0), (1); +--Testcase 236: +INSERT INTO d3 VALUES (1,3), (2,2), (3,1); +-- all three cases should be optimizable into a3 simple seqscan +--Testcase 237: +explain (costs off) SELECT a3.* FROM a3 LEFT JOIN b3 ON a3.b_id = b3.id; + QUERY PLAN +--------------------------------- + Merge Left Join + Merge Cond: (a3.b_id = b3.id) + -> Sort + Sort Key: a3.b_id + -> Foreign Scan on a3 + -> Sort + Sort Key: b3.id + -> Foreign Scan on b3 +(8 rows) + +--Testcase 238: +explain (costs off) SELECT b3.* FROM b3 LEFT JOIN c3 ON b3.c_id = c3.id; + QUERY PLAN +--------------------------------- + Merge Left Join + Merge Cond: (b3.c_id = c3.id) + -> Sort + Sort Key: b3.c_id + -> Foreign Scan on b3 + -> Sort + Sort Key: c3.id + -> Foreign Scan on c3 +(8 rows) + +--Testcase 239: +explain (costs off) + SELECT a3.* FROM a3 LEFT JOIN (b3 left join c3 on b3.c_id = c3.id) + ON (a3.b_id = b3.id); + QUERY PLAN +--------------------------------------------- + Merge Right Join + Merge Cond: (c3.id = b3.c_id) + -> Sort + Sort Key: c3.id + -> Foreign Scan on c3 + -> Sort + Sort Key: b3.c_id + -> Merge Left Join + Merge Cond: (a3.b_id = b3.id) + -> Sort + Sort Key: a3.b_id + -> Foreign Scan on a3 + -> Sort + Sort Key: b3.id + -> Foreign Scan on b3 +(15 rows) + +-- check optimization of outer join within another special join +--Testcase 240: +explain (costs off) +select id from a3 where id in ( + select b3.id from b3 left join c3 on b3.id = c3.id +); + QUERY PLAN +-------------------------------------------------- + Hash Join + Hash Cond: (a3.id = b3.id) + -> Foreign Scan on a3 + -> Hash + -> HashAggregate + Group Key: b3.id + -> Merge Left Join + Merge Cond: (b3.id = c3.id) + -> Sort + Sort Key: b3.id + -> Foreign Scan on b3 + -> Sort + Sort Key: c3.id + -> Foreign Scan on c3 +(14 rows) + +-- check optimization with oddly-nested outer joins +--Testcase 591: +explain (costs off) +select a31.id from + (a3 a31 left join a3 a32 on true) + left join + (a3 a33 left join a3 a34 on a33.id = a34.id) + on a32.id = a33.id; + QUERY PLAN +------------------------------------------------------------ + Nested Loop Left Join + -> Foreign Scan on a3 a31 + -> Materialize + -> Merge Left Join + Merge Cond: (a32.id = a33.id) + -> Sort + Sort Key: a32.id + -> Foreign Scan on a3 a32 + -> Materialize + -> Merge Left Join + Merge Cond: (a33.id = a34.id) + -> Sort + Sort Key: a33.id + -> Foreign Scan on a3 a33 + -> Sort + Sort Key: a34.id + -> Foreign Scan on a3 a34 +(17 rows) + +--Testcase 592: +explain (costs off) +select a31.id from + (a3 a31 left join a3 a32 on a31.id = a32.id) + left join + (a3 a33 left join a3 a34 on a33.id = a34.id) + on a32.id = a33.id; + QUERY PLAN +------------------------------------------------ + Merge Right Join + Merge Cond: (a33.id = a32.id) + -> Merge Left Join + Merge Cond: (a33.id = a34.id) + -> Sort + Sort Key: a33.id + -> Foreign Scan on a3 a33 + -> Sort + Sort Key: a34.id + -> Foreign Scan on a3 a34 + -> Sort + Sort Key: a32.id + -> Merge Left Join + Merge Cond: (a31.id = a32.id) + -> Sort + Sort Key: a31.id + -> Foreign Scan on a3 a31 + -> Sort + Sort Key: a32.id + -> Foreign Scan on a3 a32 +(20 rows) + +--Testcase 593: +explain (costs off) +select 1 from a3 t1 + left join a3 t2 on true + inner join a3 t3 on true + left join a3 t4 on t2.id = t4.id and t2.id = t3.id; + QUERY PLAN +----------------------------------------------------- + Merge Left Join + Merge Cond: (t2.id = t4.id) + Join Filter: (t2.id = t3.id) + -> Sort + Sort Key: t2.id + -> Nested Loop + -> Nested Loop Left Join + -> Foreign Scan on a3 t1 + -> Materialize + -> Foreign Scan on a3 t2 + -> Materialize + -> Foreign Scan on a3 t3 + -> Sort + Sort Key: t4.id + -> Foreign Scan on a3 t4 +(15 rows) + +-- another example (bug #17781) +--Testcase 594: +explain (costs off) +select ss1.f1 +from int4_tbl as t1 + left join (int4_tbl as t2 + right join int4_tbl as t3 on null + left join (int4_tbl as t4 + right join int8_tbl as t5 on null) + on t2.f1 = t4.f1 + left join ((select null as f1 from int4_tbl as t6) as ss1 + inner join int8_tbl as t7 on null) + on t5.q1 = t7.q2) + on false; + QUERY PLAN +----------------------------------- + Nested Loop Left Join + Join Filter: false + -> Foreign Scan on int4_tbl t1 + -> Result + One-Time Filter: false +(5 rows) + +-- variant with Var rather than PHV coming from t6 +--Testcase 595: +explain (costs off) +select ss1.f1 +from int4_tbl as t1 + left join (int4_tbl as t2 + right join int4_tbl as t3 on null + left join (int4_tbl as t4 + right join int8_tbl as t5 on null) + on t2.f1 = t4.f1 + left join ((select f1 from int4_tbl as t6) as ss1 + inner join int8_tbl as t7 on null) + on t5.q1 = t7.q2) + on false; + QUERY PLAN +----------------------------------- + Nested Loop Left Join + Join Filter: false + -> Foreign Scan on int4_tbl t1 + -> Result + One-Time Filter: false +(5 rows) + +-- per further discussion of bug #17781 +--Testcase 596: +explain (costs off) +select ss1.x +from (select f1/2 as x from int4_tbl i4 left join a3 on a3.id = i4.f1) ss1 + right join int8_tbl i8 on true +where current_user is not null; -- this is to add a Result node + QUERY PLAN +----------------------------------------------------------- + Result + One-Time Filter: (CURRENT_USER IS NOT NULL) + -> Nested Loop Left Join + -> Foreign Scan on int8_tbl i8 + -> Materialize + -> Merge Left Join + Merge Cond: (i4.f1 = a3.id) + -> Sort + Sort Key: i4.f1 + -> Foreign Scan on int4_tbl i4 + -> Sort + Sort Key: a3.id + -> Foreign Scan on a3 +(13 rows) + +-- and further discussion of bug #17781 +--Testcase 597: +explain (costs off) +select * +from int8_tbl t1 + left join (int8_tbl t2 left join onek t3 on t2.q1 > t3.unique1) + on t1.q2 = t2.q2 + left join onek t4 + on t2.q2 < t3.unique2; + QUERY PLAN +------------------------------------------------- + Hash Right Join + Hash Cond: (t2.q2 = t1.q2) + -> Nested Loop Left Join + Join Filter: (t2.q2 < t3.unique2) + -> Nested Loop Left Join + Join Filter: (t2.q1 > t3.unique1) + -> Foreign Scan on int8_tbl t2 + -> Materialize + -> Foreign Scan on onek t3 + -> Materialize + -> Foreign Scan on onek t4 + -> Hash + -> Foreign Scan on int8_tbl t1 +(13 rows) + +-- More tests of correct placement of pseudoconstant quals +-- simple constant-false condition +--Testcase 598: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on false + left join int8_tbl t4 on t2.q2 = t4.q2) +on t1.q1 = t2.q1; + QUERY PLAN +-------------------------------------- + Hash Left Join + Hash Cond: (t1.q1 = q1) + -> Foreign Scan on int8_tbl t1 + -> Hash + -> Result + One-Time Filter: false +(6 rows) + +-- deduce constant-false from an EquivalenceClass +--Testcase 599: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on (t2.q1-t3.q2) = 0 and (t2.q1-t3.q2) = 1 + left join int8_tbl t4 on t2.q2 = t4.q2) +on t1.q1 = t2.q1; + QUERY PLAN +-------------------------------------- + Hash Left Join + Hash Cond: (t1.q1 = q1) + -> Foreign Scan on int8_tbl t1 + -> Hash + -> Result + One-Time Filter: false +(6 rows) + +-- pseudoconstant based on an outer-level Param +--Testcase 600: +explain (costs off) +select exists( + select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on x0.f1 = 1 + left join int8_tbl t4 on t2.q2 = t4.q2) + on t1.q1 = t2.q1 +) from int4_tbl x0; + QUERY PLAN +------------------------------------------------------------------------- + Foreign Scan on int4_tbl x0 + SubPlan 1 + -> Nested Loop Left Join + Join Filter: (t2.q2 = t4.q2) + -> Nested Loop Left Join + Join Filter: (t1.q1 = t2.q1) + -> Foreign Scan on int8_tbl t1 + -> Materialize + -> Result + One-Time Filter: (x0.f1 = 1) + -> Nested Loop + -> Foreign Scan on int8_tbl t3 + -> Materialize + -> Foreign Scan on int8_tbl t2 + -> Materialize + -> Foreign Scan on int8_tbl t4 +(16 rows) + +-- check that join removal works for a left join when joining a subquery +-- that is guaranteed to be unique by its GROUP BY clause +--Testcase 241: +explain (costs off) +select d3.* from d3 left join (select * from b3 group by b3.id, b3.c_id) s + on d3.a = s.id and d3.b = s.c_id; + QUERY PLAN +-------------------- + Foreign Scan on d3 +(1 row) + +-- similarly, but keying off a DISTINCT clause +--Testcase 242: +explain (costs off) +select d3.* from d3 left join (select distinct * from b3) s + on d3.a = s.id and d3.b = s.c_id; + QUERY PLAN +-------------------- + Foreign Scan on d3 +(1 row) + +-- join removal is not possible when the GROUP BY contains a column that is +-- not in the join condition. (Note: as of 9.6, we notice that b3.id is a +-- primary key and so drop b3.c_id from the GROUP BY of the resulting plan; +-- but this happens too late for join removal in the outer plan level.) +--Testcase 243: +explain (costs off) +select d3.* from d3 left join (select * from b3 group by b3.id, b3.c_id) s + on d3.a = s.id; + QUERY PLAN +-------------------------------- + Hash Left Join + Hash Cond: (d3.a = s.id) + -> Foreign Scan on d3 + -> Hash + -> Subquery Scan on s + -> Foreign Scan +(6 rows) + +-- similarly, but keying off a DISTINCT clause +--Testcase 244: +explain (costs off) +select d3.* from d3 left join (select distinct * from b3) s + on d3.a = s.id; + QUERY PLAN +-------------------------------------------- + Hash Left Join + Hash Cond: (d3.a = s.id) + -> Foreign Scan on d3 + -> Hash + -> Subquery Scan on s + -> Unique + -> Foreign Scan on b3 +(7 rows) + +-- join removal is not possible here +--Testcase 601: +explain (costs off) +select 1 from a3 t1 + left join (a3 t2 left join a3 t3 on t2.id = 1) on t2.id = 1; + QUERY PLAN +----------------------------- + Nested Loop Left Join + -> Foreign Scan on a3 t1 + -> Materialize + -> Foreign Scan +(4 rows) + +-- check join removal works when uniqueness of the join condition is enforced +-- by a UNION +--Testcase 245: +explain (costs off) +select d3.* from d3 left join (select id from a3 union select id from b3) s + on d3.a = s.id; + QUERY PLAN +-------------------- + Foreign Scan on d3 +(1 row) + +-- check join removal with a cross-type comparison operator +--Testcase 246: +explain (costs off) +select i8.* from int8_tbl i8 left join (select f1 from int4_tbl group by f1) i4 + on i8.q1 = i4.f1; + QUERY PLAN +----------------------------- + Foreign Scan on int8_tbl i8 +(1 row) + +-- check join removal with lateral references +--Testcase 247: +explain (costs off) +select 1 from (select a3.id FROM a3 left join b3 on a3.b_id = b3.id) q, + lateral generate_series(1, q.id) gs(i) where q.id = gs.i; + QUERY PLAN +------------------------------------------------------- + Merge Right Join + Merge Cond: (b3.id = a3.b_id) + -> Sort + Sort Key: b3.id + -> Foreign Scan on b3 + -> Sort + Sort Key: a3.b_id + -> Nested Loop + -> Foreign Scan on a3 + -> Function Scan on generate_series gs + Filter: (a3.id = i) +(11 rows) + +-- check join removal within RHS of an outer join +--Testcase 602: +explain (costs off) +select c3.id, ss.a from c3 + left join (select d3.a from onerow, d3 left join b3 on d3.a = b3.id) ss + on c3.id = ss.a; + QUERY PLAN +-------------------------------------------------- + Merge Left Join + Merge Cond: (c3.id = d3.a) + -> Sort + Sort Key: c3.id + -> Foreign Scan on c3 + -> Materialize + -> Merge Left Join + Merge Cond: (d3.a = b3.id) + -> Sort + Sort Key: d3.a + -> Nested Loop + -> Seq Scan on onerow + -> Foreign Scan on d3 + -> Sort + Sort Key: b3.id + -> Foreign Scan on b3 +(16 rows) + +--Testcase 603: +CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); +--Testcase 604: +CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10); +-- test join removals on a partitioned table +--Testcase 605: +explain (costs off) +select a3.* from a3 left join parted_b pb on a3.b_id = pb.id; + QUERY PLAN +-------------------- + Foreign Scan on a3 +(1 row) + +rollback; +--Testcase 448: +create foreign table parent (k int options (key 'true'), pd int) server sqlite_svr; +--Testcase 449: +create foreign table child (k int options (key 'true'), cd int) server sqlite_svr; +--Testcase 248: +insert into parent values (1, 10), (2, 20), (3, 30); +--Testcase 249: +insert into child values (1, 100), (4, 400); +-- this case is optimizable +--Testcase 250: +select p.* from parent p left join child c on (p.k = c.k); + k | pd +---+---- + 1 | 10 + 2 | 20 + 3 | 30 +(3 rows) + +--Testcase 251: +explain (costs off) + select p.* from parent p left join child c on (p.k = c.k); + QUERY PLAN +-------------------------------------- + Merge Left Join + Merge Cond: (p.k = c.k) + -> Sort + Sort Key: p.k + -> Foreign Scan on parent p + -> Sort + Sort Key: c.k + -> Foreign Scan on child c +(8 rows) + +-- this case is not +--Testcase 252: +select p.*, linked from parent p + left join (select c.*, true as linked from child c) as ss + on (p.k = ss.k); + k | pd | linked +---+----+-------- + 1 | 10 | t + 2 | 20 | + 3 | 30 | +(3 rows) + +--Testcase 253: +explain (costs off) + select p.*, linked from parent p + left join (select c.*, true as linked from child c) as ss + on (p.k = ss.k); + QUERY PLAN +-------------------------------------- + Merge Left Join + Merge Cond: (p.k = c.k) + -> Sort + Sort Key: p.k + -> Foreign Scan on parent p + -> Sort + Sort Key: c.k + -> Foreign Scan on child c +(8 rows) + +-- check for a 9.0rc1 bug: join removal breaks pseudoconstant qual handling +--Testcase 254: +select p.* from + parent p left join child c on (p.k = c.k) + where p.k = 1 and p.k = 2; + k | pd +---+---- +(0 rows) + +--Testcase 255: +explain (costs off) +select p.* from + parent p left join child c on (p.k = c.k) + where p.k = 1 and p.k = 2; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +--Testcase 256: +select p.* from + (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k + where p.k = 1 and p.k = 2; + k | pd +---+---- +(0 rows) + +--Testcase 257: +explain (costs off) +select p.* from + (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k + where p.k = 1 and p.k = 2; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +-- bug 5255: this is not optimizable by join removal +begin; +--Testcase 450: +CREATE FOREIGN TABLE a4 (id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 451: +CREATE FOREIGN TABLE b4 (id int OPTIONS (key 'true'), a_id int) SERVER sqlite_svr; +--Testcase 258: +INSERT INTO a4 VALUES (0), (1); +--Testcase 259: +INSERT INTO b4 VALUES (0, 0), (1, NULL); +--Testcase 260: +SELECT * FROM b4 LEFT JOIN a4 ON (b4.a_id = a4.id) WHERE (a4.id IS NULL OR a4.id > 0); + id | a_id | id +----+------+---- + 1 | | +(1 row) + +--Testcase 261: +SELECT b4.* FROM b4 LEFT JOIN a4 ON (b4.a_id = a4.id) WHERE (a4.id IS NULL OR a4.id > 0); + id | a_id +----+------ + 1 | +(1 row) + +rollback; +-- another join removal bug: this is not optimizable, either +begin; +--Testcase 452: +create foreign table innertab (id int8 options (key 'true'), dat1 int8) server sqlite_svr; +--Testcase 262: +insert into innertab values(123, 42); +--Testcase 263: +SELECT * FROM + (SELECT 1 AS x) ss1 + LEFT JOIN + (SELECT q1, q2, COALESCE(dat1, q1) AS y + FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss2 + ON true; + x | q1 | q2 | y +---+------------------+-------------------+------------------ + 1 | 4567890123456789 | -4567890123456789 | 4567890123456789 + 1 | 4567890123456789 | 123 | 42 + 1 | 123 | 456 | 123 + 1 | 123 | 4567890123456789 | 123 + 1 | 4567890123456789 | 4567890123456789 | 4567890123456789 +(5 rows) + +-- join removal bug #17769: can't remove if there's a pushed-down reference +--Testcase 606: +EXPLAIN (COSTS OFF) +SELECT q2 FROM + (SELECT * + FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss + WHERE COALESCE(dat1, 0) = q1; + QUERY PLAN +---------------------------------------------------------------- + Merge Left Join + Merge Cond: (int8_tbl.q2 = innertab.id) + Filter: (COALESCE(innertab.dat1, '0'::bigint) = int8_tbl.q1) + -> Sort + Sort Key: int8_tbl.q2 + -> Foreign Scan on int8_tbl + -> Sort + Sort Key: innertab.id + -> Foreign Scan on innertab +(9 rows) + +-- join removal bug #17773: otherwise-removable PHV appears in a qual condition +--Testcase 607: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT q2 FROM + (SELECT q2, 'constant'::text AS x + FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss + RIGHT JOIN int4_tbl ON NULL + WHERE x >= x; + QUERY PLAN +-------------------------------------------------------- + Nested Loop Left Join + Output: q2 + Join Filter: NULL::boolean + Filter: (('constant'::text) >= ('constant'::text)) + -> Foreign Scan on public.int4_tbl + Output: int4_tbl.f1 + SQLite query: SELECT NULL FROM main."int4_tbl" + -> Result + Output: q2, 'constant'::text + One-Time Filter: false +(10 rows) + +-- join removal bug #17786: check that OR conditions are cleaned up +--Testcase 608: +EXPLAIN (COSTS OFF) +SELECT f1, x +FROM int4_tbl + JOIN ((SELECT 42 AS x FROM int8_tbl LEFT JOIN innertab ON q1 = id) AS ss1 + RIGHT JOIN tenk1 ON NULL) + ON tenk1.unique1 = ss1.x OR tenk1.unique2 = ss1.x; + QUERY PLAN +-------------------------------------------------------------------------- + Nested Loop + -> Foreign Scan on int4_tbl + -> Materialize + -> Nested Loop Left Join + Join Filter: NULL::boolean + Filter: ((tenk1.unique1 = (42)) OR (tenk1.unique2 = (42))) + -> Foreign Scan on tenk1 + -> Result + One-Time Filter: false +(9 rows) + +rollback; +-- another join removal bug: we must clean up correctly when removing a PHV +begin; +--Testcase 453: +create foreign table uniquetbl (f1 text) server sqlite_svr; +--Testcase 264: +explain (costs off) +select t1.* from + uniquetbl as t1 + left join (select *, '***'::text as d1 from uniquetbl) t2 + on t1.f1 = t2.f1 + left join uniquetbl t3 + on t2.d1 = t3.f1; + QUERY PLAN +--------------------------------------------------- + Merge Right Join + Merge Cond: (t3.f1 = ('***'::text)) + -> Sort + Sort Key: t3.f1 + -> Foreign Scan on uniquetbl t3 + -> Sort + Sort Key: ('***'::text) + -> Hash Left Join + Hash Cond: (t1.f1 = uniquetbl.f1) + -> Foreign Scan on uniquetbl t1 + -> Hash + -> Foreign Scan on uniquetbl +(12 rows) + +--Testcase 265: +explain (costs off) +select t0.* +from + text_tbl t0 + left join + (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, + t1.stringu2 + from tenk1 t1 + join int4_tbl i4 ON i4.f1 = t1.unique2 + left join uniquetbl u1 ON u1.f1 = t1.string4) ss + on t0.f1 = ss.case1 +where ss.stringu2 !~* ss.case1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (i4.f1 = t1.unique2) + -> Sort + Sort Key: i4.f1 + -> Foreign Scan on int4_tbl i4 + -> Sort + Sort Key: t1.unique2 + -> Merge Right Join + Merge Cond: (u1.f1 = t1.string4) + -> Sort + Sort Key: u1.f1 COLLATE "C" + -> Foreign Scan on uniquetbl u1 + -> Sort + Sort Key: t1.string4 + -> Merge Join + Merge Cond: ((CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) = t0.f1) + -> Sort + Sort Key: (CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) + -> Foreign Scan on tenk1 t1 + Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) + -> Sort + Sort Key: t0.f1 + -> Foreign Scan on text_tbl t0 +(23 rows) + +--Testcase 266: +select t0.* +from + text_tbl t0 + left join + (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, + t1.stringu2 + from tenk1 t1 + join int4_tbl i4 ON i4.f1 = t1.unique2 + left join uniquetbl u1 ON u1.f1 = t1.string4) ss + on t0.f1 = ss.case1 +where ss.stringu2 !~* ss.case1; + f1 +------ + doh! +(1 row) + +rollback; +-- another join removal bug: we must clean up EquivalenceClasses too +begin; +--Testcase 609: +create temp table t (a int unique); +--Testcase 610: +insert into t values (1); +--Testcase 611: +explain (costs off) +select 1 +from t t1 + left join (select 2 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true +where t1.a = s.c; + QUERY PLAN +------------------------------ + Nested Loop Left Join + Filter: (t1.a = (2)) + -> Seq Scan on t t1 + -> Materialize + -> Seq Scan on t t2 +(5 rows) + +--Testcase 612: +select 1 +from t t1 + left join (select 2 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true +where t1.a = s.c; + ?column? +---------- +(0 rows) + +rollback; +-- test cases where we can remove a join, but not a PHV computed at it +begin; +--Testcase 613: +create temp table t (a int unique, b int); +--Testcase 614: +insert into t values (1,1), (2,2); +--Testcase 615: +explain (costs off) +select 1 +from t t1 + left join (select t2.a, 1 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + QUERY PLAN +------------------------------------- + Nested Loop Left Join + -> Nested Loop + -> Seq Scan on t t1 + -> Materialize + -> Seq Scan on t t2 + Filter: (a < 1) + -> Materialize + -> Seq Scan on t t4 +(8 rows) + +--Testcase 616: +explain (costs off) +select t1.a, s.* +from t t1 + left join lateral (select t2.a, coalesce(t1.a, 1) as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + QUERY PLAN +----------------------------------------------- + Nested Loop Left Join + -> Nested Loop + -> Seq Scan on t t1 + -> Seq Scan on t t2 + Filter: (a < COALESCE(t1.a, 1)) + -> Materialize + -> Seq Scan on t t4 +(7 rows) + +--Testcase 617: +select t1.a, s.* +from t t1 + left join lateral (select t2.a, coalesce(t1.a, 1) as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + a | a | c +---+---+--- + 2 | 1 | 2 + 2 | 1 | 2 +(2 rows) + +rollback; +-- test case to expose miscomputation of required relid set for a PHV +--Testcase 522: +explain (verbose, costs off) +select i8.*, ss.v, t.unique2 + from int8_tbl i8 + left join int4_tbl i4 on i4.f1 = 1 + left join lateral (select i4.f1 + 1 as v) as ss on true + left join tenk1 t on t.unique2 = ss.v +where q2 = 456; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Hash Right Join + Output: i8.q1, i8.q2, ((i4.f1 + 1)), t.unique2 + Hash Cond: (t.unique2 = ((i4.f1 + 1))) + -> Foreign Scan on public.tenk1 t + Output: t.unique1, t.unique2, t.two, t.four, t.ten, t.twenty, t.hundred, t.thousand, t.twothousand, t.fivethous, t.tenthous, t.odd, t.even, t.stringu1, t.stringu2, t.string4 + SQLite query: SELECT `unique2` FROM main."tenk1" + -> Hash + Output: i8.q1, i8.q2, ((i4.f1 + 1)) + -> Nested Loop Left Join + Output: i8.q1, i8.q2, (i4.f1 + 1) + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((`q2` = 456)) + -> Materialize + Output: i4.f1 + -> Foreign Scan on public.int4_tbl i4 + Output: i4.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" WHERE ((`f1` = 1)) +(18 rows) + +--Testcase 523: +select i8.*, ss.v, t.unique2 + from int8_tbl i8 + left join int4_tbl i4 on i4.f1 = 1 + left join lateral (select i4.f1 + 1 as v) as ss on true + left join tenk1 t on t.unique2 = ss.v +where q2 = 456; + q1 | q2 | v | unique2 +-----+-----+---+--------- + 123 | 456 | | +(1 row) + +-- -- and check a related issue where we miscompute required relids for +-- -- a PHV that's been translated to a child rel +-- create temp table parttbl (a integer primary key) partition by range (a); +-- create temp table parttbl1 partition of parttbl for values from (1) to (100); +-- insert into parttbl values (11), (12); +-- explain (costs off) +-- select * from +-- (select *, 12 as phv from parttbl) as ss +-- right join int4_tbl on true +-- where ss.a = ss.phv and f1 = 0; +-- select * from +-- (select *, 12 as phv from parttbl) as ss +-- right join int4_tbl on true +-- where ss.a = ss.phv and f1 = 0; +-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs +--Testcase 267: +select * from + int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error +ERROR: column reference "f1" is ambiguous +LINE 2: ..._tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; + ^ +--Testcase 268: +select * from + int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; -- error +ERROR: invalid reference to FROM-clause entry for table "y" +LINE 2: ...bl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; + ^ +DETAIL: There is an entry for table "y", but it cannot be referenced from this part of the query. +--Testcase 269: +select * from + int8_tbl x join (int4_tbl x cross join int4_tbl y(ff)) j on q1 = f1; -- ok + q1 | q2 | f1 | ff +----+----+----+---- +(0 rows) + +-- +-- Test hints given on incorrect column references are useful +-- +--Testcase 270: +select t1.uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion +ERROR: column t1.uunique1 does not exist +LINE 1: select t1.uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t1.unique1". +--Testcase 271: +select t2.uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion +ERROR: column t2.uunique1 does not exist +LINE 1: select t2.uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t2.unique1". +--Testcase 272: +select uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once +ERROR: column "uunique1" does not exist +LINE 1: select uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1". +--Testcase 618: +select ctid from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, need qualification +ERROR: column "ctid" does not exist +LINE 1: select ctid from + ^ +DETAIL: There are columns named "ctid", but they are in tables that cannot be referenced from this part of the query. +HINT: Try using a table-qualified name. +-- +-- Take care to reference the correct RTE +-- +--Testcase 454: +select atts.relid::regclass, s.* from pg_stats s join + pg_attribute a on s.attname = a.attname and s.tablename = + a.attrelid::regclass::text join (select unnest(indkey) attnum, + indexrelid from pg_index i) atts on atts.attnum = a.attnum where + schemaname != 'pg_catalog'; +ERROR: column atts.relid does not exist +LINE 1: select atts.relid::regclass, s.* from pg_stats s join + ^ +-- Test bug in rangetable flattening +--Testcase 619: +explain (verbose, costs off) +select 1 from + (select * from int8_tbl where q1 <> (select 42) offset 0) ss +where false; + QUERY PLAN +-------------------------- + Result + Output: 1 + One-Time Filter: false +(3 rows) + +-- +-- Test LATERAL +-- +--Testcase 273: +select unique2, x.* +from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; + unique2 | f1 +---------+---- + 9998 | 0 +(1 row) + +--Testcase 274: +explain (costs off) + select unique2, x.* + from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; + QUERY PLAN +---------------------------------------- + Merge Join + Merge Cond: (a.unique1 = b.f1) + -> Sort + Sort Key: a.unique1 + -> Foreign Scan on tenk1 a + -> Sort + Sort Key: b.f1 + -> Foreign Scan on int4_tbl b +(8 rows) + +--Testcase 275: +select unique2, x.* +from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; + unique2 | f1 +---------+---- + 9998 | 0 +(1 row) + +--Testcase 276: +explain (costs off) + select unique2, x.* + from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; + QUERY PLAN +---------------------------------------- + Merge Join + Merge Cond: (tenk1.unique1 = x.f1) + -> Sort + Sort Key: tenk1.unique1 + -> Foreign Scan on tenk1 + -> Sort + Sort Key: x.f1 + -> Foreign Scan on int4_tbl x +(8 rows) + +--Testcase 277: +explain (costs off) + select unique2, x.* + from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss; + QUERY PLAN +---------------------------------------- + Merge Join + Merge Cond: (tenk1.unique1 = x.f1) + -> Sort + Sort Key: tenk1.unique1 + -> Foreign Scan on tenk1 + -> Sort + Sort Key: x.f1 + -> Foreign Scan on int4_tbl x +(8 rows) + +--Testcase 278: +select unique2, x.* +from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; + unique2 | f1 +---------+------------- + | -2147483647 + | -123456 + 9998 | 0 + | 123456 + | 2147483647 +(5 rows) + +--Testcase 279: +explain (costs off) + select unique2, x.* + from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; + QUERY PLAN +---------------------------------------- + Merge Right Join + Merge Cond: (tenk1.unique1 = x.f1) + -> Sort + Sort Key: tenk1.unique1 + -> Foreign Scan on tenk1 + -> Sort + Sort Key: x.f1 + -> Foreign Scan on int4_tbl x +(8 rows) + +-- check scoping of lateral versus parent references +-- the first of these should return int8_tbl.q2, the second int8_tbl.q1 +--Testcase 280: +select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl; + q1 | q2 | r +------------------+-------------------+------------------- + 123 | 456 | 456 + 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | -4567890123456789 +(5 rows) + +--Testcase 281: +select *, (select r from (select q1 as q2) x, lateral (select q2 as r) y) from int8_tbl; + q1 | q2 | r +------------------+-------------------+------------------ + 123 | 456 | 123 + 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 +(5 rows) + +-- lateral with function in FROM +--Testcase 282: +select count(*) from tenk1 a, lateral generate_series(1,two) g; + count +------- + 5000 +(1 row) + +--Testcase 283: +explain (costs off) + select count(*) from tenk1 a, lateral generate_series(1,two) g; + QUERY PLAN +------------------------------------------------ + Aggregate + -> Nested Loop + -> Foreign Scan on tenk1 a + -> Function Scan on generate_series g +(4 rows) + +--Testcase 284: +explain (costs off) + select count(*) from tenk1 a cross join lateral generate_series(1,two) g; + QUERY PLAN +------------------------------------------------ + Aggregate + -> Nested Loop + -> Foreign Scan on tenk1 a + -> Function Scan on generate_series g +(4 rows) + +-- don't need the explicit LATERAL keyword for functions +--Testcase 285: +explain (costs off) + select count(*) from tenk1 a, generate_series(1,two) g; + QUERY PLAN +------------------------------------------------ + Aggregate + -> Nested Loop + -> Foreign Scan on tenk1 a + -> Function Scan on generate_series g +(4 rows) + +-- lateral with UNION ALL subselect +--Testcase 286: +explain (costs off) + select * from generate_series(100,200) g, + lateral (select * from int8_tbl a where g = q1 union all + select * from int8_tbl b where g = q2) ss; + QUERY PLAN +------------------------------------------ + Nested Loop + -> Function Scan on generate_series g + -> Append + -> Foreign Scan on int8_tbl a + -> Foreign Scan on int8_tbl b +(5 rows) + +--Testcase 287: +select * from generate_series(100,200) g, + lateral (select * from int8_tbl a where g = q1 union all + select * from int8_tbl b where g = q2) ss; + g | q1 | q2 +-----+------------------+------------------ + 123 | 123 | 456 + 123 | 123 | 4567890123456789 + 123 | 4567890123456789 | 123 +(3 rows) + +-- lateral with VALUES +--Testcase 288: +explain (costs off) + select count(*) from tenk1 a, + tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 289: +select count(*) from tenk1 a, + tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; + count +------- + 10000 +(1 row) + +-- lateral with VALUES, no flattening possible +--Testcase 290: +explain (costs off) + select count(*) from tenk1 a, + tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; + QUERY PLAN +------------------------------------------------------ + Aggregate + -> Merge Join + Merge Cond: (b.unique2 = "*VALUES*".column1) + -> Sort + Sort Key: b.unique2 + -> Foreign Scan on tenk1 b + -> Sort + Sort Key: "*VALUES*".column1 + -> Nested Loop + -> Foreign Scan on tenk1 a + -> Values Scan on "*VALUES*" +(11 rows) + +--Testcase 291: +select count(*) from tenk1 a, + tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; + count +------- + 10000 +(1 row) + +-- lateral injecting a strange outer join condition +--Testcase 292: +explain (costs off) + select * from int8_tbl a, + int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) + on x.q2 = ss.z + order by a.q1, a.q2, x.q1, x.q2, ss.z; + QUERY PLAN +---------------------------------------------------- + Sort + Sort Key: a.q1, a.q2, x.q1, x.q2, (a.q1) + -> Nested Loop + -> Foreign Scan on int8_tbl a + -> Merge Left Join + Merge Cond: (x.q2 = (a.q1)) + -> Sort + Sort Key: x.q2 + -> Foreign Scan on int8_tbl x + -> Sort + Sort Key: (a.q1) + -> Foreign Scan on int4_tbl y +(12 rows) + +--Testcase 293: +select * from int8_tbl a, + int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) + on x.q2 = ss.z + order by a.q1, a.q2, x.q1, x.q2, ss.z; + q1 | q2 | q1 | q2 | z +------------------+-------------------+------------------+-------------------+------------------ + 123 | 456 | 123 | 456 | + 123 | 456 | 123 | 4567890123456789 | + 123 | 456 | 4567890123456789 | -4567890123456789 | + 123 | 456 | 4567890123456789 | 123 | 123 + 123 | 456 | 4567890123456789 | 123 | 123 + 123 | 456 | 4567890123456789 | 123 | 123 + 123 | 456 | 4567890123456789 | 123 | 123 + 123 | 456 | 4567890123456789 | 123 | 123 + 123 | 456 | 4567890123456789 | 4567890123456789 | + 123 | 4567890123456789 | 123 | 456 | + 123 | 4567890123456789 | 123 | 4567890123456789 | + 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | + 4567890123456789 | -4567890123456789 | 123 | 456 | + 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 | + 4567890123456789 | -4567890123456789 | 4567890123456789 | 123 | + 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 456 | + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 4567890123456789 | -4567890123456789 | + 4567890123456789 | 123 | 4567890123456789 | 123 | + 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 123 | 456 | + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 +(57 rows) + +-- lateral reference to a join alias variable +--Testcase 294: +select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, + lateral (select x) ss2(y); + x | f1 | y +---+----+--- + 0 | 0 | 0 +(1 row) + +--Testcase 295: +select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, + lateral (values(x)) ss2(y); + x | f1 | y +-------------+-------------+------------- + -2147483647 | -2147483647 | -2147483647 + -123456 | -123456 | -123456 + 0 | 0 | 0 + 123456 | 123456 | 123456 + 2147483647 | 2147483647 | 2147483647 +(5 rows) + +--Testcase 296: +select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j, + lateral (select x) ss2(y); + x | f1 | y +---+----+--- + 0 | 0 | 0 +(1 row) + +-- lateral references requiring pullup +--Testcase 297: +select * from (values(1)) x(lb), + lateral generate_series(lb,4) x4; + lb | x4 +----+---- + 1 | 1 + 1 | 2 + 1 | 3 + 1 | 4 +(4 rows) + +--Testcase 298: +select * from (select f1/1000000000 from int4_tbl) x(lb), + lateral generate_series(lb,4) x4; + lb | x4 +----+---- + 0 | 0 + 0 | 1 + 0 | 2 + 0 | 3 + 0 | 4 + 0 | 0 + 0 | 1 + 0 | 2 + 0 | 3 + 0 | 4 + 0 | 0 + 0 | 1 + 0 | 2 + 0 | 3 + 0 | 4 + 2 | 2 + 2 | 3 + 2 | 4 + -2 | -2 + -2 | -1 + -2 | 0 + -2 | 1 + -2 | 2 + -2 | 3 + -2 | 4 +(25 rows) + +--Testcase 299: +select * from (values(1)) x(lb), + lateral (values(lb)) y(lbcopy); + lb | lbcopy +----+-------- + 1 | 1 +(1 row) + +--Testcase 300: +select * from (values(1)) x(lb), + lateral (select lb from int4_tbl) y(lbcopy); + lb | lbcopy +----+-------- + 1 | 1 + 1 | 1 + 1 | 1 + 1 | 1 + 1 | 1 +(5 rows) + +--Testcase 301: +select * from + int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, + lateral (values(x.q1,y.q1,y.q2)) v(xq1,yq1,yq2); + q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 +------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- + 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | + 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 123 | 456 | | | 123 | | + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 +(10 rows) + +--Testcase 302: +select * from + int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, + lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); + q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 +------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- + 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | + 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 + 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 123 | 456 | | | 123 | | + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 +(10 rows) + +--Testcase 303: +select x.* from + int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, + lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); + q1 | q2 +------------------+------------------- + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 123 + 123 | 456 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(10 rows) + +--Testcase 304: +select v.* from + (int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1) + left join int4_tbl z on z.f1 = x.q2, + lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); + vx | vy +-------------------+------------------- + 4567890123456789 | + -4567890123456789 | + 4567890123456789 | 123 + 123 | 456 + 4567890123456789 | 123 + 123 | 4567890123456789 + 123 | + 456 | + 123 | 4567890123456789 + 4567890123456789 | 123 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(20 rows) + +--Testcase 305: +select v.* from + (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) + left join int4_tbl z on z.f1 = x.q2, + lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); + vx | vy +-------------------+------------------- + 4567890123456789 | + -4567890123456789 | + 4567890123456789 | 123 + 123 | 456 + 4567890123456789 | 123 + 123 | 4567890123456789 + 123 | + 456 | + 123 | 4567890123456789 + 4567890123456789 | 123 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(20 rows) + +--Testcase 307: +select v.* from + (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) + left join int4_tbl z on z.f1 = x.q2, + lateral (select x.q1,y.q1 from onerow union all select x.q2,y.q2 from onerow) v(vx,vy); + vx | vy +-------------------+------------------- + 4567890123456789 | + -4567890123456789 | + 4567890123456789 | 123 + 123 | 456 + 4567890123456789 | 123 + 123 | 4567890123456789 + 123 | + 456 | + 123 | 4567890123456789 + 4567890123456789 | 123 + 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(20 rows) + +-- Error when using sub-query with multi instances of table, this issue is fixed on PostgreSQL-12 +--Testcase 455: +explain (verbose, costs off) +select * from + int8_tbl a left join + lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; + QUERY PLAN +--------------------------------------------------------------------------------- + Nested Loop Left Join + Output: a.q1, a.q2, b.q1, b.q2, (a.q2) + -> Foreign Scan on public.int8_tbl a + Output: a.q1, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Foreign Scan on public.int8_tbl b + Output: b.q1, b.q2, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((? = `q1`)) +(8 rows) + +--Testcase 456: +select * from + int8_tbl a left join + lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; + q1 | q2 | q1 | q2 | x +------------------+-------------------+------------------+-------------------+------------------ + 123 | 456 | | | + 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 456 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | | | +(10 rows) + +--Testcase 457: +explain (verbose, costs off) +select * from + int8_tbl a left join + lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; + QUERY PLAN +--------------------------------------------------------------------------------- + Nested Loop Left Join + Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, '42'::bigint)) + -> Foreign Scan on public.int8_tbl a + Output: a.q1, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Foreign Scan on public.int8_tbl b + Output: b.q1, b.q2, COALESCE(a.q2, '42'::bigint) + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" WHERE ((? = `q1`)) +(8 rows) + +--Testcase 458: +select * from + int8_tbl a left join + lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; + q1 | q2 | q1 | q2 | x +------------------+-------------------+------------------+-------------------+------------------ + 123 | 456 | | | + 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 | 456 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | | | +(10 rows) + +-- lateral can result in join conditions appearing below their +-- real semantic level +--Testcase 308: +explain (verbose, costs off) +select * from int4_tbl i left join + lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; + QUERY PLAN +-------------------------------------------------------------- + Merge Left Join + Output: i.f1, j.f1 + Merge Cond: (i.f1 = j.f1) + -> Sort + Output: i.f1 + Sort Key: i.f1 + -> Foreign Scan on public.int4_tbl i + Output: i.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Sort + Output: j.f1 + Sort Key: j.f1 + -> Foreign Scan on public.int2_tbl j + Output: j.f1 + SQLite query: SELECT `f1` FROM main."int2_tbl" +(15 rows) + +--Testcase 309: +select * from int4_tbl i left join + lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; + f1 | f1 +-------------+---- + -2147483647 | + -123456 | + 0 | 0 + 123456 | + 2147483647 | +(5 rows) + +--Testcase 310: +explain (verbose, costs off) +select * from int4_tbl i left join + lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop Left Join + Output: i.f1, (COALESCE(i.*)) + -> Foreign Scan on public.int4_tbl i + Output: i.f1, i.* + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Foreign Scan on public.int2_tbl j + Output: j.f1, COALESCE(i.*) + SQLite query: SELECT `f1` FROM main."int2_tbl" WHERE ((? = `f1`)) +(8 rows) + +--Testcase 311: +select * from int4_tbl i left join + lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; + f1 | coalesce +-------------+---------- + 0 | (0) + 123456 | + -123456 | + 2147483647 | + -2147483647 | +(5 rows) + +--Testcase 312: +explain (verbose, costs off) +select * from int4_tbl a, + lateral ( + select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) + ) ss; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: a.f1, b.f1, c.q1, c.q2 + -> Foreign Scan on public.int4_tbl a + Output: a.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Foreign Scan + Output: b.f1, c.q1, c.q2 + SQLite query: SELECT r1.`f1`, r2.`q1`, r2.`q2` FROM (main."int4_tbl" r1 LEFT JOIN main."int8_tbl" r2 ON (((r1.`f1` = r2.`q1`)) AND ((? = r2.`q2`)))) +(8 rows) + +--Testcase 313: +select * from int4_tbl a, + lateral ( + select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) + ) ss; + f1 | f1 | q1 | q2 +-------------+-------------+----+---- + 0 | 0 | | + 0 | 123456 | | + 0 | -123456 | | + 0 | 2147483647 | | + 0 | -2147483647 | | + 123456 | 0 | | + 123456 | 123456 | | + 123456 | -123456 | | + 123456 | 2147483647 | | + 123456 | -2147483647 | | + -123456 | 0 | | + -123456 | 123456 | | + -123456 | -123456 | | + -123456 | 2147483647 | | + -123456 | -2147483647 | | + 2147483647 | 0 | | + 2147483647 | 123456 | | + 2147483647 | -123456 | | + 2147483647 | 2147483647 | | + 2147483647 | -2147483647 | | + -2147483647 | 0 | | + -2147483647 | 123456 | | + -2147483647 | -123456 | | + -2147483647 | 2147483647 | | + -2147483647 | -2147483647 | | +(25 rows) + +-- lateral reference in a PlaceHolderVar evaluated at join level +-- Error when using sub-query with multi instances of table, this issue is fixed on PostgreSQL-12 +--Testcase 459: +explain (verbose, costs off) +select * from + int8_tbl a left join lateral + (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from + int8_tbl b cross join int8_tbl c) ss + on a.q2 = ss.bq1; + QUERY PLAN +--------------------------------------------------------------------------------- + Nested Loop Left Join + Output: a.q1, a.q2, b.q1, c.q1, (LEAST(a.q1, b.q1, c.q1)) + -> Foreign Scan on public.int8_tbl a + Output: a.q1, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Nested Loop + Output: b.q1, c.q1, LEAST(a.q1, b.q1, c.q1) + -> Foreign Scan on public.int8_tbl b + Output: b.q1, b.q2 + SQLite query: SELECT `q1` FROM main."int8_tbl" WHERE ((? = `q1`)) + -> Materialize + Output: c.q1 + -> Foreign Scan on public.int8_tbl c + Output: c.q1 + SQLite query: SELECT `q1` FROM main."int8_tbl" +(15 rows) + +--Testcase 460: +select * from + int8_tbl a left join lateral + (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from + int8_tbl b cross join int8_tbl c) ss + on a.q2 = ss.bq1; + q1 | q2 | bq1 | cq1 | least +------------------+-------------------+------------------+------------------+------------------ + 123 | 456 | | | + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 123 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 123 | 123 + 4567890123456789 | 123 | 123 | 123 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 123 | 123 + 4567890123456789 | 123 | 123 | 123 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 123 | 123 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | | | +(42 rows) + +-- case requiring nested PlaceHolderVars +--Testcase 461: +explain (verbose, costs off) +select * from + int8_tbl c left join ( + int8_tbl a left join (select q1, coalesce(q2,42) as x from int8_tbl b) ss1 + on a.q2 = ss1.q1 + cross join + lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 + ) on c.q2 = ss2.q1, + lateral (select ss2.y offset 0) ss3; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Nested Loop + Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)), ((COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))) + -> Hash Right Join + Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) + Hash Cond: (d.q1 = c.q2) + -> Nested Loop + Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) + -> Merge Left Join + Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)) + Merge Cond: (a.q2 = b.q1) + -> Sort + Output: a.q1, a.q2 + Sort Key: a.q2 + -> Foreign Scan on public.int8_tbl a + Output: a.q1, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Sort + Output: b.q1, (COALESCE(b.q2, '42'::bigint)) + Sort Key: b.q1 + -> Foreign Scan on public.int8_tbl b + Output: b.q1, COALESCE(b.q2, '42'::bigint) + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Foreign Scan on public.int8_tbl d + Output: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2) + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Hash + Output: c.q1, c.q2 + -> Foreign Scan on public.int8_tbl c + Output: c.q1, c.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Result + Output: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) +(32 rows) + +-- another case requiring nested PlaceHolderVars +--Testcase 635: +explain (verbose, costs off) +select * from + (select 0 as val0 FROM int8_tbl LIMIT 1) as ss0 + left join (select 1 as val FROM int8_tbl LIMIT 1) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + QUERY PLAN +---------------------------------------------------------------------- + Nested Loop Left Join + Output: (0), (1), ((1)) + Join Filter: false + -> Nested Loop Left Join + Output: (0), (1) + -> Foreign Scan on public.int8_tbl + Output: 0 + SQLite query: SELECT NULL FROM main."int8_tbl" LIMIT 1 + -> Foreign Scan on public.int8_tbl int8_tbl_1 + Output: 1 + SQLite query: SELECT NULL FROM main."int8_tbl" LIMIT 1 + -> Result + Output: (1) + One-Time Filter: false +(14 rows) + +--Testcase 636: +select * from + (select 0 as val0 FROM int8_tbl LIMIT 1) as ss0 + left join (select 1 as val FROM int8_tbl LIMIT 1) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + val0 | val | val_filtered +------+-----+-------------- + 0 | 1 | +(1 row) + +-- case that breaks the old ph_may_need optimization +--Testcase 462: +explain (verbose, costs off) +select c.*,a.*,ss1.q1,ss2.q1,ss3.* from + int8_tbl c left join ( + int8_tbl a left join + (select q1, coalesce(q2,f1) as x from int8_tbl b, int4_tbl b2 + where q1 < f1) ss1 + on a.q2 = ss1.q1 + cross join + lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 + ) on c.q2 = ss2.q1, + lateral (select * from int4_tbl i where ss2.y > f1) ss3; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Nested Loop + Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, i.f1 + Join Filter: ((COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) > i.f1) + -> Hash Right Join + Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) + Hash Cond: (d.q1 = c.q2) + -> Nested Loop + Output: a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) + -> Merge Left Join + Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) + Merge Cond: (a.q2 = b.q1) + -> Sort + Output: a.q1, a.q2 + Sort Key: a.q2 + -> Foreign Scan on public.int8_tbl a + Output: a.q1, a.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Materialize + Output: b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) + -> Sort + Output: b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) + Sort Key: b.q1 + -> Nested Loop + Output: b.q1, COALESCE(b.q2, (b2.f1)::bigint) + Join Filter: (b.q1 < b2.f1) + -> Foreign Scan on public.int4_tbl b2 + Output: b2.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Materialize + Output: b.q1, b.q2 + -> Foreign Scan on public.int8_tbl b + Output: b.q1, b.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Foreign Scan on public.int8_tbl d + Output: d.q1, COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2) + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Hash + Output: c.q1, c.q2 + -> Foreign Scan on public.int8_tbl c + Output: c.q1, c.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Materialize + Output: i.f1 + -> Foreign Scan on public.int4_tbl i + Output: i.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" +(46 rows) + +-- check processing of postponed quals (bug #9041) +--Testcase 463: +delete from sub_tbl; +--Testcase 464: +insert into sub_tbl values (1, 2, 3, 4, 5); +--Testcase 465: +explain (verbose, costs off) +select * from + (select key1 as x from sub_tbl offset 0) x cross join (select key3 as y from sub_tbl offset 0) y + left join lateral ( + select * from (select key5 as z from sub_tbl offset 0) z where z.z = x.x + ) zz on zz.z = y.y; + QUERY PLAN +--------------------------------------------------------------------------------------- + Merge Left Join + Output: sub_tbl.key1, sub_tbl_1.key3, sub_tbl_2.key5 + Merge Cond: ((sub_tbl.key1 = sub_tbl_2.key5) AND (sub_tbl_1.key3 = sub_tbl_2.key5)) + -> Sort + Output: sub_tbl.key1, sub_tbl_1.key3 + Sort Key: sub_tbl.key1, sub_tbl_1.key3 + -> Nested Loop + Output: sub_tbl.key1, sub_tbl_1.key3 + -> Foreign Scan on public.sub_tbl + Output: sub_tbl.key1 + SQLite query: SELECT `key1` FROM main."sub_tbl" + -> Materialize + Output: sub_tbl_1.key3 + -> Foreign Scan on public.sub_tbl sub_tbl_1 + Output: sub_tbl_1.key3 + SQLite query: SELECT `key3` FROM main."sub_tbl" + -> Sort + Output: sub_tbl_2.key5 + Sort Key: sub_tbl_2.key5 + -> Foreign Scan on public.sub_tbl sub_tbl_2 + Output: sub_tbl_2.key5 + SQLite query: SELECT `key5` FROM main."sub_tbl" +(22 rows) + +-- a new postponed-quals issue (bug #17768) +--Testcase 620: +explain (costs off) +select * from int4_tbl t1, + lateral (select * from int4_tbl t2 inner join int4_tbl t3 on t1.f1 = 1 + inner join (int4_tbl t4 left join int4_tbl t5 on true) on true) ss; + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + -> Nested Loop + -> Nested Loop + -> Nested Loop + -> Foreign Scan on int4_tbl t2 + -> Materialize + -> Foreign Scan on int4_tbl t1 + -> Materialize + -> Foreign Scan on int4_tbl t3 + -> Materialize + -> Foreign Scan on int4_tbl t4 + -> Materialize + -> Foreign Scan on int4_tbl t5 +(13 rows) + +-- check dummy rels with lateral references (bug #15694) +--Testcase 466: +explain (verbose, costs off) +select * from int8_tbl i8 left join lateral + (select *, i8.q2 from int4_tbl where false) ss on true; + QUERY PLAN +-------------------------------------------------------------- + Nested Loop Left Join + Output: i8.q1, i8.q2, f1, (i8.q2) + Join Filter: false + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Result + Output: f1, i8.q2 + One-Time Filter: false +(9 rows) + +--Testcase 467: +explain (verbose, costs off) +select * from int8_tbl i8 left join lateral + (select *, i8.q2 from int4_tbl i1, int4_tbl i2 where false) ss on true; + QUERY PLAN +-------------------------------------------------------------- + Nested Loop Left Join + Output: i8.q1, i8.q2, f1, f1, (i8.q2) + -> Foreign Scan on public.int8_tbl i8 + Output: i8.q1, i8.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Result + Output: f1, f1, i8.q2 + One-Time Filter: false +(8 rows) + +-- check handling of nested appendrels inside LATERAL +--Testcase 468: +select * from + ((select key3 as v from sub_tbl) union all (select key5 as v from sub_tbl)) as q1 + cross join lateral + ((select * from + ((select key6 as v from sub_tbl) union all (select value1 as v from sub_tbl)) as q3) + union all + (select q1.v) + ) as q2; + v | v +---+--- + 2 | 4 + 2 | 5 + 2 | 2 + 3 | 4 + 3 | 5 + 3 | 3 +(6 rows) + +-- check the number of columns specified +--Testcase 539: +SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d); +ERROR: join expression "ss" has 3 columns available but 4 columns specified +-- check we don't try to do a unique-ified semijoin with LATERAL +--Testcase 314: +explain (verbose, costs off) +select * from + (values (0,9998), (1,1000)) v(id,x), + lateral (select f1 from int4_tbl + where f1 = any (select unique1 from tenk1 + where unique2 = v.x offset 0)) ss; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Nested Loop + Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2 + -> Hash Semi Join + Output: int4_tbl.f1 + Hash Cond: (int4_tbl.f1 = tenk1.unique1) + -> Foreign Scan on public.int4_tbl + Output: int4_tbl.f1 + SQLite query: SELECT `f1` FROM main."int4_tbl" + -> Hash + Output: tenk1.unique1 + -> Foreign Scan on public.tenk1 + Output: tenk1.unique1 + SQLite query: SELECT `unique1` FROM main."tenk1" WHERE ((`unique2` = ?)) +(15 rows) + +--Testcase 315: +select * from + (values (0,9998), (1,1000)) v(id,x), + lateral (select f1 from int4_tbl + where f1 = any (select unique1 from tenk1 + where unique2 = v.x offset 0)) ss; + id | x | f1 +----+------+---- + 0 | 9998 | 0 +(1 row) + +-- check proper extParam/allParam handling (this isn't exactly a LATERAL issue, +-- but we can make the test case much more compact with LATERAL) +--Testcase 316: +explain (verbose, costs off) +select * from (values (0), (1)) v(id), +lateral (select * from int8_tbl t1, + lateral (select * from + (select * from int8_tbl t2 + where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3 + where q2 = (select greatest(t1.q1,t2.q2)) + and (select v.id=0)) offset 0) ss2) ss + where t1.q1 = ss.q2) ss0; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2 + -> Foreign Scan on public.int8_tbl t1 + Output: t1.q1, t1.q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + -> Nested Loop + Output: "*VALUES*".column1, ss2.q1, ss2.q2 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1 + -> Subquery Scan on ss2 + Output: ss2.q1, ss2.q2 + Filter: (t1.q1 = ss2.q2) + -> Foreign Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + Filter: (ANY ((t2.q1 = (SubPlan 3).col1) AND ((random() > '0'::double precision) = (SubPlan 3).col2))) + SQLite query: SELECT `q1`, `q2` FROM main."int8_tbl" + SubPlan 3 + -> Result + Output: t3.q2, (random() > '0'::double precision) + One-Time Filter: (InitPlan 2).col1 + InitPlan 1 + -> Result + Output: GREATEST(t1.q1, t2.q2) + InitPlan 2 + -> Result + Output: ("*VALUES*".column1 = 0) + -> Foreign Scan on public.int8_tbl t3 + Output: t3.q1, t3.q2 + SQLite query: SELECT `q2` FROM main."int8_tbl" WHERE ((`q2` = ?)) +(29 rows) + +--Testcase 317: +select * from (values (0), (1)) v(id), +lateral (select * from int8_tbl t1, + lateral (select * from + (select * from int8_tbl t2 + where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3 + where q2 = (select greatest(t1.q1,t2.q2)) + and (select v.id=0)) offset 0) ss2) ss + where t1.q1 = ss.q2) ss0; + id | q1 | q2 | q1 | q2 +----+------------------+-------------------+------------------+------------------ + 0 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 + 0 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 + 0 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 +(3 rows) + +-- test some error cases where LATERAL should have been used but wasn't +--Testcase 318: +select f1,g from int4_tbl a, (select f1 as g) ss; +ERROR: column "f1" does not exist +LINE 1: select f1,g from int4_tbl a, (select f1 as g) ss; + ^ +DETAIL: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. +HINT: To reference that column, you must mark this subquery with LATERAL. +--Testcase 319: +select f1,g from int4_tbl a, (select a.f1 as g) ss; +ERROR: invalid reference to FROM-clause entry for table "a" +LINE 1: select f1,g from int4_tbl a, (select a.f1 as g) ss; + ^ +DETAIL: There is an entry for table "a", but it cannot be referenced from this part of the query. +HINT: To reference that table, you must mark this subquery with LATERAL. +--Testcase 320: +select f1,g from int4_tbl a cross join (select f1 as g) ss; +ERROR: column "f1" does not exist +LINE 1: select f1,g from int4_tbl a cross join (select f1 as g) ss; + ^ +DETAIL: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. +HINT: To reference that column, you must mark this subquery with LATERAL. +--Testcase 321: +select f1,g from int4_tbl a cross join (select a.f1 as g) ss; +ERROR: invalid reference to FROM-clause entry for table "a" +LINE 1: select f1,g from int4_tbl a cross join (select a.f1 as g) ss... + ^ +DETAIL: There is an entry for table "a", but it cannot be referenced from this part of the query. +HINT: To reference that table, you must mark this subquery with LATERAL. +-- SQL:2008 says the left table is in scope but illegal to access here +--Testcase 322: +select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true; +ERROR: invalid reference to FROM-clause entry for table "a" +LINE 1: ... int4_tbl a right join lateral generate_series(0, a.f1) g on... + ^ +DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. +--Testcase 323: +select f1,g from int4_tbl a full join lateral generate_series(0, a.f1) g on true; +ERROR: invalid reference to FROM-clause entry for table "a" +LINE 1: ...m int4_tbl a full join lateral generate_series(0, a.f1) g on... + ^ +DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. +-- check we complain about ambiguous table references +--Testcase 324: +select * from + int8_tbl x cross join (int4_tbl x cross join lateral (select x.f1) ss); +ERROR: table reference "x" is ambiguous +LINE 2: ...cross join (int4_tbl x cross join lateral (select x.f1) ss); + ^ +-- LATERAL can be used to put an aggregate into the FROM clause of its query +--Testcase 325: +select 1 from tenk1 a, lateral (select max(a.unique1) from int4_tbl b) ss; +ERROR: aggregate functions are not allowed in FROM clause of their own query level +LINE 1: select 1 from tenk1 a, lateral (select max(a.unique1) from i... + ^ +-- check behavior of LATERAL in UPDATE/DELETE +--Testcase 469: +create temp table xx1 as select f1 as x1, -f1 as x2 from int4_tbl; +-- error, can't do this: +--Testcase 326: +update xx1 set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; +ERROR: column "x1" does not exist +LINE 1: ... set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; + ^ +DETAIL: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. +--Testcase 327: +update xx1 set x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss; +ERROR: invalid reference to FROM-clause entry for table "xx1" +LINE 1: ...t x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss... + ^ +DETAIL: There is an entry for table "xx1", but it cannot be referenced from this part of the query. +-- can't do it even with LATERAL: +--Testcase 328: +update xx1 set x2 = f1 from lateral (select * from int4_tbl where f1 = x1) ss; +ERROR: invalid reference to FROM-clause entry for table "xx1" +LINE 1: ...= f1 from lateral (select * from int4_tbl where f1 = x1) ss; + ^ +HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. +-- we might in future allow something like this, but for now it's an error: +--Testcase 329: +update xx1 set x2 = f1 from xx1, lateral (select * from int4_tbl where f1 = x1) ss; +ERROR: table name "xx1" specified more than once +-- also errors: +--Testcase 330: +delete from xx1 using (select * from int4_tbl where f1 = x1) ss; +ERROR: column "x1" does not exist +LINE 1: ...te from xx1 using (select * from int4_tbl where f1 = x1) ss; + ^ +DETAIL: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. +--Testcase 331: +delete from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss; +ERROR: invalid reference to FROM-clause entry for table "xx1" +LINE 1: ...from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss... + ^ +DETAIL: There is an entry for table "xx1", but it cannot be referenced from this part of the query. +--Testcase 332: +delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss; +ERROR: invalid reference to FROM-clause entry for table "xx1" +LINE 1: ...xx1 using lateral (select * from int4_tbl where f1 = x1) ss; + ^ +HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. +-- Skip this test, sqlite fdw does not support to create partition table +-- test LATERAL reference propagation down a multi-level inheritance hierarchy +-- produced for a multi-level partitioned table hierarchy. +-- +--create table join_pt1 (a int, b int, c varchar) partition by range(a); +--create table join_pt1p1 partition of join_pt1 for values from (0) to (100) partition by range(b); +--create table join_pt1p2 partition of join_pt1 for values from (100) to (200); +--create table join_pt1p1p1 partition of join_pt1p1 for values from (0) to (100); +--insert into join_pt1 values (1, 1, 'x'), (101, 101, 'y'); +--create table join_ut1 (a int, b int, c varchar); +--insert into join_ut1 values (101, 101, 'y'), (2, 2, 'z'); +--explain (verbose, costs off) +--select t1.b, ss.phv from join_ut1 t1 left join lateral +-- (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv +-- from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss +-- on t1.a = ss.t2a order by t1.a; +--select t1.b, ss.phv from join_ut1 t1 left join lateral +-- (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv +-- from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss +-- on t1.a = ss.t2a order by t1.a; +--drop table join_pt1; +--drop table join_ut1; +-- +-- test estimation behavior with multi-column foreign key and constant qual +-- +begin; +--Testcase 524: +create table fkest (x integer, x10 integer, x10b integer, x100 integer); +--Testcase 525: +insert into fkest select x, x/10, x/10, x/100 from generate_series(1,1000) x; +--Testcase 526: +create unique index on fkest(x, x10, x100); +analyze fkest; +--Testcase 527: +explain (costs off) +select * from fkest f1 + join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100) + join fkest f3 on f1.x = f3.x + where f1.x100 = 2; + QUERY PLAN +----------------------------------------------------------- + Nested Loop + -> Hash Join + Hash Cond: ((f2.x = f1.x) AND (f2.x10b = f1.x10)) + -> Seq Scan on fkest f2 + Filter: (x100 = 2) + -> Hash + -> Seq Scan on fkest f1 + Filter: (x100 = 2) + -> Index Scan using fkest_x_x10_x100_idx on fkest f3 + Index Cond: (x = f1.x) +(10 rows) + +--Testcase 528: +alter table fkest add constraint fk + foreign key (x, x10b, x100) references fkest (x, x10, x100); +--Testcase 529: +explain (costs off) +select * from fkest f1 + join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100) + join fkest f3 on f1.x = f3.x + where f1.x100 = 2; + QUERY PLAN +----------------------------------------------------- + Hash Join + Hash Cond: ((f2.x = f1.x) AND (f2.x10b = f1.x10)) + -> Hash Join + Hash Cond: (f3.x = f2.x) + -> Seq Scan on fkest f3 + -> Hash + -> Seq Scan on fkest f2 + Filter: (x100 = 2) + -> Hash + -> Seq Scan on fkest f1 + Filter: (x100 = 2) +(11 rows) + +rollback; +-- +-- test that foreign key join estimation performs sanely for outer joins +-- +begin; +--Testcase 470: +create foreign table fkest (a int options (key 'true'), b int options (key 'true'), c int) server sqlite_svr; +--Testcase 471: +create foreign table fkest1 (a int options (key 'true'), b int options (key 'true')) server sqlite_svr; +--Testcase 333: +insert into fkest select x/10, x%10, x from generate_series(1,1000) x; +--Testcase 334: +insert into fkest1 select x/10, x%10 from generate_series(1,1000) x; +--alter table fkest1 +-- add constraint fkest1_a_b_fkey foreign key (a,b) references fkest; +--analyze fkest; +--analyze fkest1; +--Testcase 335: +explain (costs off) +select * +from fkest f + left join fkest1 f1 on f.a = f1.a and f.b = f1.b + left join fkest1 f2 on f.a = f2.a and f.b = f2.b + left join fkest1 f3 on f.a = f3.a and f.b = f3.b +where f.c = 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +rollback; +-- +-- test planner's ability to mark joins as unique +-- +--Testcase 472: +create foreign table j11 (id int options (key 'true')) server sqlite_svr; +--Testcase 473: +create foreign table j21 (id int options (key 'true')) server sqlite_svr; +--Testcase 474: +create foreign table j31 (id int) server sqlite_svr; +--Testcase 336: +insert into j11 values(1),(2),(3); +--Testcase 337: +insert into j21 values(1),(2),(3); +--Testcase 338: +insert into j31 values(1),(1); +-- ensure join is properly marked as unique +--Testcase 339: +explain (verbose, costs off) +select * from j11 inner join j21 on j11.id = j21.id; + QUERY PLAN +--------------------------------------------------------- + Merge Join + Output: j11.id, j21.id + Merge Cond: (j11.id = j21.id) + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Sort + Output: j21.id + Sort Key: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(15 rows) + +-- ensure join is not unique when not an equi-join +--Testcase 340: +explain (verbose, costs off) +select * from j11 inner join j21 on j11.id > j21.id; + QUERY PLAN +--------------------------------------------------------- + Nested Loop + Output: j11.id, j21.id + Join Filter: (j11.id > j21.id) + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Materialize + Output: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(11 rows) + +-- ensure non-unique rel is not chosen as inner +--Testcase 341: +explain (verbose, costs off) +select * from j11 inner join j31 on j11.id = j31.id; + QUERY PLAN +--------------------------------------------------------- + Merge Join + Output: j11.id, j31.id + Merge Cond: (j11.id = j31.id) + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Sort + Output: j31.id + Sort Key: j31.id + -> Foreign Scan on public.j31 + Output: j31.id + SQLite query: SELECT `id` FROM main."j31" +(15 rows) + +-- ensure left join is marked as unique +--Testcase 342: +explain (verbose, costs off) +select * from j11 left join j21 on j11.id = j21.id; + QUERY PLAN +--------------------------------------------------------- + Merge Left Join + Output: j11.id, j21.id + Merge Cond: (j11.id = j21.id) + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Sort + Output: j21.id + Sort Key: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(15 rows) + +-- ensure right join is marked as unique +--Testcase 343: +explain (verbose, costs off) +select * from j11 right join j21 on j11.id = j21.id; + QUERY PLAN +--------------------------------------------------------- + Merge Left Join + Output: j11.id, j21.id + Merge Cond: (j21.id = j11.id) + -> Sort + Output: j21.id + Sort Key: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" +(15 rows) + +-- ensure full join is marked as unique +--Testcase 344: +explain (verbose, costs off) +select * from j11 full join j21 on j11.id = j21.id; + QUERY PLAN +--------------------------------------------------------- + Merge Full Join + Output: j11.id, j21.id + Merge Cond: (j11.id = j21.id) + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Sort + Output: j21.id + Sort Key: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(15 rows) + +-- a clauseless (cross) join can't be unique +--Testcase 345: +explain (verbose, costs off) +select * from j11 cross join j21; + QUERY PLAN +--------------------------------------------------------- + Nested Loop + Output: j11.id, j21.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Materialize + Output: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(10 rows) + +-- ensure a natural join is marked as unique +--Testcase 346: +explain (verbose, costs off) +select * from j11 natural join j21; + QUERY PLAN +--------------------------------------------------------- + Merge Join + Output: j11.id + Merge Cond: (j11.id = j21.id) + -> Sort + Output: j11.id + Sort Key: j11.id + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Sort + Output: j21.id + Sort Key: j21.id + -> Foreign Scan on public.j21 + Output: j21.id + SQLite query: SELECT `id` FROM main."j21" +(15 rows) + +-- ensure a distinct clause allows the inner to become unique +--Testcase 347: +explain (verbose, costs off) +select * from j11 +inner join (select distinct id from j31) j31 on j11.id = j31.id; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Hash Join + Output: j11.id, j31.id + Inner Unique: true + Hash Cond: (j11.id = j31.id) + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Hash + Output: j31.id + -> Unique + Output: j31.id + -> Foreign Scan on public.j31 + Output: j31.id + SQLite query: SELECT `id` FROM main."j31" ORDER BY `id` ASC NULLS LAST +(14 rows) + +-- ensure group by clause allows the inner to become unique +--Testcase 348: +explain (verbose, costs off) +select * from j11 +inner join (select id from j31 group by id) j31 on j11.id = j31.id; + QUERY PLAN +-------------------------------------------------------------------- + Hash Join + Output: j11.id, j31.id + Inner Unique: true + Hash Cond: (j11.id = j31.id) + -> Foreign Scan on public.j11 + Output: j11.id + SQLite query: SELECT `id` FROM main."j11" + -> Hash + Output: j31.id + -> Foreign Scan + Output: j31.id + SQLite query: SELECT `id` FROM main."j31" GROUP BY 1 +(12 rows) + +--drop table j1; +--drop table j2; +--drop table j3; +-- test more complex permutations of unique joins +--Testcase 475: +create foreign table j12 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; +--Testcase 476: +create foreign table j22 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; +--Testcase 477: +create foreign table j32 (id1 int options (key 'true'), id2 int options (key 'true')) server sqlite_svr; +--Testcase 349: +insert into j12 values(1,1),(1,2); +--Testcase 350: +insert into j22 values(1,1); +--Testcase 351: +insert into j32 values(1,1); +--analyze j1; +--analyze j2; +--analyze j3; +-- ensure there's no unique join when not all columns which are part of the +-- unique index are seen in the join clause +--Testcase 352: +explain (verbose, costs off) +select * from j12 +inner join j22 on j12.id1 = j22.id1; + QUERY PLAN +----------------------------------------------------------------- + Merge Join + Output: j12.id1, j12.id2, j22.id1, j22.id2 + Merge Cond: (j12.id1 = j22.id1) + -> Sort + Output: j12.id1, j12.id2 + Sort Key: j12.id1 + -> Foreign Scan on public.j12 + Output: j12.id1, j12.id2 + SQLite query: SELECT `id1`, `id2` FROM main."j12" + -> Sort + Output: j22.id1, j22.id2 + Sort Key: j22.id1 + -> Foreign Scan on public.j22 + Output: j22.id1, j22.id2 + SQLite query: SELECT `id1`, `id2` FROM main."j22" +(15 rows) + +-- ensure proper unique detection with multiple join quals +--Testcase 353: +explain (verbose, costs off) +select * from j12 +inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2; + QUERY PLAN +----------------------------------------------------------------- + Merge Join + Output: j12.id1, j12.id2, j22.id1, j22.id2 + Merge Cond: ((j12.id1 = j22.id1) AND (j12.id2 = j22.id2)) + -> Sort + Output: j12.id1, j12.id2 + Sort Key: j12.id1, j12.id2 + -> Foreign Scan on public.j12 + Output: j12.id1, j12.id2 + SQLite query: SELECT `id1`, `id2` FROM main."j12" + -> Sort + Output: j22.id1, j22.id2 + Sort Key: j22.id1, j22.id2 + -> Foreign Scan on public.j22 + Output: j22.id1, j22.id2 + SQLite query: SELECT `id1`, `id2` FROM main."j22" +(15 rows) + +-- ensure we don't detect the join to be unique when quals are not part of the +-- join condition +--Testcase 354: +explain (verbose, costs off) +select * from j12 +inner join j22 on j12.id1 = j22.id1 where j12.id2 = 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: j12.id1, j12.id2, j22.id1, j22.id2 + SQLite query: SELECT r1.`id1`, r1.`id2`, r2.`id1`, r2.`id2` FROM (main."j12" r1 INNER JOIN main."j22" r2 ON (((r1.`id1` = r2.`id1`)) AND ((r1.`id2` = 1)))) +(3 rows) + +-- as above, but for left joins. +--Testcase 355: +explain (verbose, costs off) +select * from j12 +left join j22 on j12.id1 = j22.id1 where j12.id2 = 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: j12.id1, j12.id2, j22.id1, j22.id2 + SQLite query: SELECT r1.`id1`, r1.`id2`, r2.`id1`, r2.`id2` FROM (main."j12" r1 LEFT JOIN main."j22" r2 ON (((r1.`id1` = r2.`id1`)))) WHERE ((r1.`id2` = 1)) +(3 rows) + +-- create unique index command does not work with foreign table +-- Add these normal tables for it. +--Testcase 624: +create table j1 (id1 int, id2 int, primary key(id1,id2)); +--Testcase 625: +create table j2 (id1 int, id2 int, primary key(id1,id2)); +--Testcase 626: +insert into j1 values(1,1),(1,2); +--Testcase 627: +insert into j2 values(1,1); +analyze j1; +analyze j2; +--Testcase 621: +create unique index j1_id2_idx on j1(id2) where id2 is not null; +-- ensure we don't use a partial unique index as unique proofs +--Testcase 622: +explain (verbose, costs off) +select * from j1 +inner join j2 on j1.id2 = j2.id2; + QUERY PLAN +------------------------------------------ + Nested Loop + Output: j1.id1, j1.id2, j2.id1, j2.id2 + Join Filter: (j2.id2 = j1.id2) + -> Seq Scan on public.j2 + Output: j2.id1, j2.id2 + -> Seq Scan on public.j1 + Output: j1.id1, j1.id2 +(7 rows) + +--Testcase 623: +drop index j1_id2_idx; +--Testcase 628: +drop table j1; +--Testcase 629: +drop table j2; +-- validate logic in merge joins which skips mark and restore. +-- it should only do this if all quals which were used to detect the unique +-- are present as join quals, and not plain quals. +--Testcase 530: +set enable_nestloop to 0; +--Testcase 531: +set enable_hashjoin to 0; +--Testcase 532: +set enable_sort to 0; +-- skip, cannot create index on foreign table +-- create indexes that will be preferred over the PKs to perform the join +--create index j1_id1_idx on j1 (id1) where id1 % 1000 = 1; +--create index j2_id1_idx on j2 (id1) where id1 % 1000 = 1; +-- need an additional row in j2, if we want j2_id1_idx to be preferred +--Testcase 478: +insert into j22 values(1,2); +--analyze j2; +--Testcase 356: +explain (costs off) select * from j12 j12 +inner join j12 j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 357: +select * from j12 j12 +inner join j12 j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1; + id1 | id2 | id1 | id2 +-----+-----+-----+----- + 1 | 1 | 1 | 1 + 1 | 2 | 1 | 2 +(2 rows) + +-- Exercise array keys mark/restore B-Tree code +--Testcase 479: +explain (costs off) select * from j12 +inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 = any (array[1]); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 480: +select * from j12 +inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 = any (array[1]); + id1 | id2 | id1 | id2 +-----+-----+-----+----- + 1 | 1 | 1 | 1 + 1 | 2 | 1 | 2 +(2 rows) + +-- Exercise array keys "find extreme element" B-Tree code +--Testcase 481: +explain (costs off) select * from j12 +inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 >= any (array[1,5]); + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 482: +select * from j12 +inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 +where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 >= any (array[1,5]); + id1 | id2 | id1 | id2 +-----+-----+-----+----- + 1 | 1 | 1 | 1 + 1 | 2 | 1 | 2 +(2 rows) + +--Testcase 533: +reset enable_nestloop; +--Testcase 534: +reset enable_hashjoin; +--Testcase 535: +reset enable_sort; +--drop table j1; +--drop table j2; +--drop table j3; +-- check that semijoin inner is not seen as unique for a portion of the outerrel +--Testcase 358: +explain (verbose, costs off) +select t1.unique1, t2.hundred +from onek t1, tenk1 t2 +where exists (select 1 from tenk1 t3 + where t3.thousand = t1.unique1 and t3.tenthous = t2.hundred) + and t1.unique1 < 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Hash Join + Output: t1.unique1, t2.hundred + Hash Cond: (t2.hundred = t3.tenthous) + -> Foreign Scan on public.tenk1 t2 + Output: t2.unique1, t2.unique2, t2.two, t2.four, t2.ten, t2.twenty, t2.hundred, t2.thousand, t2.twothousand, t2.fivethous, t2.tenthous, t2.odd, t2.even, t2.stringu1, t2.stringu2, t2.string4 + SQLite query: SELECT `hundred` FROM main."tenk1" + -> Hash + Output: t1.unique1, t3.tenthous + -> Hash Join + Output: t1.unique1, t3.tenthous + Hash Cond: (t1.unique1 = t3.thousand) + -> Foreign Scan on public.onek t1 + Output: t1.unique1, t1.unique2, t1.two, t1.four, t1.ten, t1.twenty, t1.hundred, t1.thousand, t1.twothousand, t1.fivethous, t1.tenthous, t1.odd, t1.even, t1.stringu1, t1.stringu2, t1.string4 + SQLite query: SELECT `unique1` FROM main."onek" WHERE ((`unique1` < 1)) + -> Hash + Output: t3.thousand, t3.tenthous + -> HashAggregate + Output: t3.thousand, t3.tenthous + Group Key: t3.thousand, t3.tenthous + -> Foreign Scan on public.tenk1 t3 + Output: t3.thousand, t3.tenthous + SQLite query: SELECT `thousand`, `tenthous` FROM main."tenk1" +(22 rows) + +-- ... unless it actually is unique +--Testcase 484: +create table j3 as select unique1, tenthous from onek; +vacuum analyze j3; +--Testcase 485: +create unique index on j3(unique1, tenthous); +--Testcase 359: +explain (verbose, costs off) +select t1.unique1, t2.hundred +from onek t1, tenk1 t2 +where exists (select 1 from j3 + where j3.unique1 = t1.unique1 and j3.tenthous = t2.hundred) + and t1.unique1 < 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Hash Join + Output: t1.unique1, t2.hundred + Hash Cond: (t2.hundred = j3.tenthous) + -> Foreign Scan on public.tenk1 t2 + Output: t2.unique1, t2.unique2, t2.two, t2.four, t2.ten, t2.twenty, t2.hundred, t2.thousand, t2.twothousand, t2.fivethous, t2.tenthous, t2.odd, t2.even, t2.stringu1, t2.stringu2, t2.string4 + SQLite query: SELECT `hundred` FROM main."tenk1" + -> Hash + Output: t1.unique1, j3.tenthous + -> Hash Join + Output: t1.unique1, j3.tenthous + Hash Cond: (t1.unique1 = j3.unique1) + -> Foreign Scan on public.onek t1 + Output: t1.unique1, t1.unique2, t1.two, t1.four, t1.ten, t1.twenty, t1.hundred, t1.thousand, t1.twothousand, t1.fivethous, t1.tenthous, t1.odd, t1.even, t1.stringu1, t1.stringu2, t1.string4 + SQLite query: SELECT `unique1` FROM main."onek" WHERE ((`unique1` < 1)) + -> Hash + Output: j3.unique1, j3.tenthous + -> Seq Scan on public.j3 + Output: j3.unique1, j3.tenthous +(18 rows) + +--Testcase 486: +drop table j3; +-- sqlite_fdw is not supported WITH fillfactor, INDEX, VACUM, ANALYZE with foreign table. +-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate +-- tuples are discarded. This may occur when: +-- 1. A join doesn't require all inner tuples to be scanned for each outer +-- tuple, and +-- 2. The inner side is scanned using a bitmap heap scan, and +-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization. +-- This optimization is usable when no data from the underlying table is +-- needed. Use a temp table so it is only visible to this backend and +-- vacuum may reliably mark all blocks in the table all visible in the +-- visibility map. +-- CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10); +-- INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i; +-- CREATE INDEX ON skip_fetch(a); +-- VACUUM (ANALYZE) skip_fetch; +-- SET enable_indexonlyscan = off; +-- SET enable_seqscan = off; +-- EXPLAIN (COSTS OFF) +-- SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; +-- SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; +-- RESET enable_indexonlyscan; +-- RESET enable_seqscan; +--Testcase 656: +DELETE FROM INT4_TBL; +--Testcase 657: +DELETE FROM FLOAT8_TBL; +--Testcase 658: +DELETE FROM INT8_TBL; +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +--Testcase 487: +DROP SERVER sqlite_svr; +--Testcase 488: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/extra/limit.out b/expected/17.0/extra/limit.out new file mode 100644 index 00000000..71fcb283 --- /dev/null +++ b/expected/17.0/extra/limit.out @@ -0,0 +1,1078 @@ +-- +-- LIMIT +-- Check the LIMIT/OFFSET feature of SELECT +-- +--Testcase 27: +CREATE EXTENSION sqlite_fdw; +--Testcase 28: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 29: +CREATE FOREIGN TABLE onek( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 30: +CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); +--Testcase 31: +CREATE FOREIGN TABLE INT8_TMP( + q1 int8, + q2 int8, + q3 int4, + q4 int2, + q5 text, + id int options (key 'true') +) SERVER sqlite_svr; +--Testcase 32: +CREATE FOREIGN TABLE tenk1 ( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; +--Testcase 88: +CREATE TABLE parent_table ( + unique1 int4 PRIMARY KEY, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +); +--Testcase 89: +CREATE FOREIGN table inherited_table () +INHERITS (parent_table) +SERVER sqlite_svr options (table 'tenk1'); +--Testcase 1: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 50 + ORDER BY unique1 LIMIT 2; + two | unique1 | unique2 | stringu1 +-----+---------+---------+---------- + | 51 | 76 | ZBAAAA + | 52 | 985 | ACAAAA +(2 rows) + +--Testcase 2: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 60 + ORDER BY unique1 LIMIT 5; + five | unique1 | unique2 | stringu1 +------+---------+---------+---------- + | 61 | 560 | JCAAAA + | 62 | 633 | KCAAAA + | 63 | 296 | LCAAAA + | 64 | 479 | MCAAAA + | 65 | 64 | NCAAAA +(5 rows) + +--Testcase 3: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 60 AND unique1 < 63 + ORDER BY unique1 LIMIT 5; + two | unique1 | unique2 | stringu1 +-----+---------+---------+---------- + | 61 | 560 | JCAAAA + | 62 | 633 | KCAAAA +(2 rows) + +--Testcase 4: +SELECT ''::text AS three, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 100 + ORDER BY unique1 LIMIT 3 OFFSET 20; + three | unique1 | unique2 | stringu1 +-------+---------+---------+---------- + | 121 | 700 | REAAAA + | 122 | 519 | SEAAAA + | 123 | 777 | TEAAAA +(3 rows) + +--Testcase 5: +SELECT ''::text AS zero, unique1, unique2, stringu1 + FROM onek WHERE unique1 < 50 + ORDER BY unique1 DESC LIMIT 8 OFFSET 99; + zero | unique1 | unique2 | stringu1 +------+---------+---------+---------- +(0 rows) + +--Testcase 6: +SELECT ''::text AS eleven, unique1, unique2, stringu1 + FROM onek WHERE unique1 < 50 + ORDER BY unique1 DESC LIMIT 20 OFFSET 39; + eleven | unique1 | unique2 | stringu1 +--------+---------+---------+---------- + | 10 | 520 | KAAAAA + | 9 | 49 | JAAAAA + | 8 | 653 | IAAAAA + | 7 | 647 | HAAAAA + | 6 | 978 | GAAAAA + | 5 | 541 | FAAAAA + | 4 | 833 | EAAAAA + | 3 | 431 | DAAAAA + | 2 | 326 | CAAAAA + | 1 | 214 | BAAAAA + | 0 | 998 | AAAAAA +(11 rows) + +--Testcase 7: +SELECT ''::text AS ten, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 OFFSET 990; + ten | unique1 | unique2 | stringu1 +-----+---------+---------+---------- + | 990 | 369 | CMAAAA + | 991 | 426 | DMAAAA + | 992 | 363 | EMAAAA + | 993 | 661 | FMAAAA + | 994 | 695 | GMAAAA + | 995 | 144 | HMAAAA + | 996 | 258 | IMAAAA + | 997 | 21 | JMAAAA + | 998 | 549 | KMAAAA + | 999 | 152 | LMAAAA +(10 rows) + +--Testcase 8: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 OFFSET 990 LIMIT 5; + five | unique1 | unique2 | stringu1 +------+---------+---------+---------- + | 990 | 369 | CMAAAA + | 991 | 426 | DMAAAA + | 992 | 363 | EMAAAA + | 993 | 661 | FMAAAA + | 994 | 695 | GMAAAA +(5 rows) + +--Testcase 9: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 LIMIT 5 OFFSET 900; + five | unique1 | unique2 | stringu1 +------+---------+---------+---------- + | 900 | 913 | QIAAAA + | 901 | 931 | RIAAAA + | 902 | 702 | SIAAAA + | 903 | 641 | TIAAAA + | 904 | 793 | UIAAAA +(5 rows) + +-- Test null limit and offset. The planner would discard a simple null +-- constant, so to ensure executor is exercised, do this: +--Testcase 10: +select * from int8_tbl limit (case when random() < 0.5 then null::bigint end); + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(5 rows) + +--Testcase 11: +select * from int8_tbl offset (case when random() < 0.5 then null::bigint end); + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(5 rows) + +-- Test assorted cases involving backwards fetch from a LIMIT plan node +begin; +declare c1 scroll cursor for select * from int8_tbl order by q1 limit 10; +--Testcase 12: +fetch all in c1; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(5 rows) + +--Testcase 13: +fetch 1 in c1; + q1 | q2 +----+---- +(0 rows) + +--Testcase 14: +fetch backward 1 in c1; + q1 | q2 +------------------+------------------ + 4567890123456789 | 4567890123456789 +(1 row) + +--Testcase 33: +fetch backward all in c1; + q1 | q2 +------------------+------------------- + 4567890123456789 | 123 + 4567890123456789 | -4567890123456789 + 123 | 4567890123456789 + 123 | 456 +(4 rows) + +--Testcase 34: +fetch backward 1 in c1; + q1 | q2 +----+---- +(0 rows) + +--Testcase 35: +fetch all in c1; + q1 | q2 +------------------+------------------- + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | -4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(5 rows) + +declare c2 scroll cursor for select * from int8_tbl limit 3; +--Testcase 36: +fetch all in c2; + q1 | q2 +------------------+------------------ + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 +(3 rows) + +--Testcase 37: +fetch 1 in c2; + q1 | q2 +----+---- +(0 rows) + +--Testcase 38: +fetch backward 1 in c2; + q1 | q2 +------------------+----- + 4567890123456789 | 123 +(1 row) + +--Testcase 39: +fetch backward all in c2; + q1 | q2 +-----+------------------ + 123 | 4567890123456789 + 123 | 456 +(2 rows) + +--Testcase 40: +fetch backward 1 in c2; + q1 | q2 +----+---- +(0 rows) + +--Testcase 41: +fetch all in c2; + q1 | q2 +------------------+------------------ + 123 | 456 + 123 | 4567890123456789 + 4567890123456789 | 123 +(3 rows) + +declare c3 scroll cursor for select * from int8_tbl offset 3; +--Testcase 42: +fetch all in c3; + q1 | q2 +------------------+------------------- + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(2 rows) + +--Testcase 43: +fetch 1 in c3; + q1 | q2 +----+---- +(0 rows) + +--Testcase 44: +fetch backward 1 in c3; + q1 | q2 +------------------+------------------- + 4567890123456789 | -4567890123456789 +(1 row) + +--Testcase 45: +fetch backward all in c3; + q1 | q2 +------------------+------------------ + 4567890123456789 | 4567890123456789 +(1 row) + +--Testcase 46: +fetch backward 1 in c3; + q1 | q2 +----+---- +(0 rows) + +--Testcase 47: +fetch all in c3; + q1 | q2 +------------------+------------------- + 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 +(2 rows) + +declare c4 scroll cursor for select * from int8_tbl offset 10; +--Testcase 48: +fetch all in c4; + q1 | q2 +----+---- +(0 rows) + +--Testcase 49: +fetch 1 in c4; + q1 | q2 +----+---- +(0 rows) + +--Testcase 50: +fetch backward 1 in c4; + q1 | q2 +----+---- +(0 rows) + +--Testcase 51: +fetch backward all in c4; + q1 | q2 +----+---- +(0 rows) + +--Testcase 52: +fetch backward 1 in c4; + q1 | q2 +----+---- +(0 rows) + +--Testcase 53: +fetch all in c4; + q1 | q2 +----+---- +(0 rows) + +declare c5 scroll cursor for select * from int8_tbl order by q1 fetch first 2 rows with ties; +--Testcase 54: +fetch all in c5; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +--Testcase 55: +fetch 1 in c5; + q1 | q2 +----+---- +(0 rows) + +--Testcase 56: +fetch backward 1 in c5; + q1 | q2 +-----+------------------ + 123 | 4567890123456789 +(1 row) + +--Testcase 57: +fetch backward 1 in c5; + q1 | q2 +-----+----- + 123 | 456 +(1 row) + +--Testcase 58: +fetch all in c5; + q1 | q2 +-----+------------------ + 123 | 4567890123456789 +(1 row) + +--Testcase 59: +fetch backward all in c5; + q1 | q2 +-----+------------------ + 123 | 4567890123456789 + 123 | 456 +(2 rows) + +--Testcase 60: +fetch all in c5; + q1 | q2 +-----+------------------ + 123 | 456 + 123 | 4567890123456789 +(2 rows) + +--Testcase 61: +fetch backward all in c5; + q1 | q2 +-----+------------------ + 123 | 4567890123456789 + 123 | 456 +(2 rows) + +rollback; +-- Stress test for variable LIMIT in conjunction with bounded-heap sorting +--Testcase 62: +DELETE FROM INT8_TMP; +--Testcase 63: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series(1,10) q1; +--Testcase 64: +SELECT + (SELECT s.q1 + FROM (VALUES (1)) AS x, + (SELECT q1 FROM INT8_TMP as n + ORDER BY q1 LIMIT 1 OFFSET s.q1-1) AS y) AS z + FROM INT8_TMP AS s; + z +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +(10 rows) + +-- +-- Test behavior of volatile and set-returning functions in conjunction +-- with ORDER BY and LIMIT. +-- +--Testcase 65: +create temp sequence testseq; +--Testcase 15: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass) + SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 16: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10; + unique1 | unique2 | nextval +---------+---------+--------- + 8800 | 0 | 1 + 1891 | 1 | 2 + 3420 | 2 | 3 + 9850 | 3 | 4 + 7164 | 4 | 5 + 8009 | 5 | 6 + 5057 | 6 | 7 + 6701 | 7 | 8 + 4321 | 8 | 9 + 3043 | 9 | 10 +(10 rows) + +--Testcase 90: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10 offset 5; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass) + SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST LIMIT 10 OFFSET 5 +(3 rows) + +--Testcase 91: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10 offset 5; + unique1 | unique2 | nextval +---------+---------+--------- + 8009 | 5 | 11 + 5057 | 6 | 12 + 6701 | 7 | 13 + 4321 | 8 | 14 + 3043 | 9 | 15 + 1314 | 10 | 16 + 1504 | 11 | 17 + 5222 | 12 | 18 + 6243 | 13 | 19 + 5471 | 14 | 20 +(10 rows) + +--Testcase 17: +select currval('testseq'); + currval +--------- + 20 +(1 row) + +--Testcase 92: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass) + SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` DESC NULLS FIRST LIMIT 10 +(3 rows) + +--Testcase 93: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10; + unique1 | unique2 | nextval +---------+---------+--------- + 2968 | 9999 | 21 + 0 | 9998 | 22 + 2992 | 9997 | 23 + 1783 | 9996 | 24 + 5780 | 9995 | 25 + 429 | 9994 | 26 + 6093 | 9993 | 27 + 6587 | 9992 | 28 + 4093 | 9991 | 29 + 4773 | 9990 | 30 +(10 rows) + +--Testcase 94: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10 offset 5; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass) + SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` DESC NULLS FIRST LIMIT 10 OFFSET 5 +(3 rows) + +--Testcase 95: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10 offset 5; + unique1 | unique2 | nextval +---------+---------+--------- + 429 | 9994 | 31 + 6093 | 9993 | 32 + 6587 | 9992 | 33 + 4093 | 9991 | 34 + 4773 | 9990 | 35 + 8592 | 9989 | 36 + 858 | 9988 | 37 + 9194 | 9987 | 38 + 1384 | 9986 | 39 + 2406 | 9985 | 40 +(10 rows) + +--Testcase 96: +select currval('testseq'); + currval +--------- + 40 +(1 row) + +--Testcase 18: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass), tenthous + SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 19: +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10; + unique1 | unique2 | nextval +---------+---------+--------- + 0 | 9998 | 41 + 1 | 2838 | 42 + 2 | 2716 | 43 + 3 | 5679 | 44 + 4 | 1621 | 45 + 5 | 5557 | 46 + 6 | 2855 | 47 + 7 | 8518 | 48 + 8 | 5435 | 49 + 9 | 4463 | 50 +(10 rows) + +--Testcase 97: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10 offset 5; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.tenk1 + Output: unique1, unique2, nextval('testseq'::regclass), tenthous + SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 OFFSET 5 +(3 rows) + +--Testcase 98: +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10 offset 5; + unique1 | unique2 | nextval +---------+---------+--------- + 5 | 5557 | 51 + 6 | 2855 | 52 + 7 | 8518 | 53 + 8 | 5435 | 54 + 9 | 4463 | 55 + 10 | 8788 | 56 + 11 | 8396 | 57 + 12 | 6605 | 58 + 13 | 5696 | 59 + 14 | 4341 | 60 +(10 rows) + +--Testcase 20: +select currval('testseq'); + currval +--------- + 60 +(1 row) + +-- test for limit and offset when querying table and foreign table inherited +--Testcase 99: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: parent_table.unique1, parent_table.unique2, (nextval('testseq'::regclass)), parent_table.tenthous + -> Result + Output: parent_table.unique1, parent_table.unique2, nextval('testseq'::regclass), parent_table.tenthous + -> Merge Append + Sort Key: parent_table.tenthous + -> Sort + Output: parent_table_1.unique1, parent_table_1.unique2, parent_table_1.tenthous + Sort Key: parent_table_1.tenthous + -> Seq Scan on public.parent_table parent_table_1 + Output: parent_table_1.unique1, parent_table_1.unique2, parent_table_1.tenthous + -> Foreign Scan on public.inherited_table parent_table_2 + Output: parent_table_2.unique1, parent_table_2.unique2, parent_table_2.tenthous + SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST LIMIT 10 +(14 rows) + +--Testcase 100: +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10; + unique1 | unique2 | nextval +---------+---------+--------- + 0 | 9998 | 61 + 1 | 2838 | 62 + 2 | 2716 | 63 + 3 | 5679 | 64 + 4 | 1621 | 65 + 5 | 5557 | 66 + 6 | 2855 | 67 + 7 | 8518 | 68 + 8 | 5435 | 69 + 9 | 4463 | 70 +(10 rows) + +-- when querying regular tables with inherited tables, only limit is pushed-down when no offset is specified +--Testcase 101: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10 offset 5; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: parent_table.unique1, parent_table.unique2, (nextval('testseq'::regclass)), parent_table.tenthous + -> Result + Output: parent_table.unique1, parent_table.unique2, nextval('testseq'::regclass), parent_table.tenthous + -> Merge Append + Sort Key: parent_table.tenthous + -> Sort + Output: parent_table_1.unique1, parent_table_1.unique2, parent_table_1.tenthous + Sort Key: parent_table_1.tenthous + -> Seq Scan on public.parent_table parent_table_1 + Output: parent_table_1.unique1, parent_table_1.unique2, parent_table_1.tenthous + -> Foreign Scan on public.inherited_table parent_table_2 + Output: parent_table_2.unique1, parent_table_2.unique2, parent_table_2.tenthous + SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST +(14 rows) + +--Testcase 102: +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10 offset 5; + unique1 | unique2 | nextval +---------+---------+--------- + 5 | 5557 | 76 + 6 | 2855 | 77 + 7 | 8518 | 78 + 8 | 5435 | 79 + 9 | 4463 | 80 + 10 | 8788 | 81 + 11 | 8396 | 82 + 12 | 6605 | 83 + 13 | 5696 | 84 + 14 | 4341 | 85 +(10 rows) + +--Testcase 103: +select currval('testseq'); + currval +--------- + 85 +(1 row) + +--Testcase 21: +explain (verbose, costs off) +select unique1, unique2, generate_series(1,10) + from tenk1 order by unique2 limit 7; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: unique1, unique2, (generate_series(1, 10)) + -> ProjectSet + Output: unique1, unique2, generate_series(1, 10) + -> Foreign Scan on public.tenk1 + Output: unique1, unique2, two, four, ten, twenty, hundred, thousand, twothousand, fivethous, tenthous, odd, even, stringu1, stringu2, string4 + SQLite query: SELECT `unique1`, `unique2` FROM main."tenk1" ORDER BY `unique2` ASC NULLS LAST +(7 rows) + +--Testcase 22: +select unique1, unique2, generate_series(1,10) + from tenk1 order by unique2 limit 7; + unique1 | unique2 | generate_series +---------+---------+----------------- + 8800 | 0 | 1 + 8800 | 0 | 2 + 8800 | 0 | 3 + 8800 | 0 | 4 + 8800 | 0 | 5 + 8800 | 0 | 6 + 8800 | 0 | 7 +(7 rows) + +--Testcase 23: +explain (verbose, costs off) +select unique1, unique2, generate_series(1,10) + from tenk1 order by tenthous limit 7; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: unique1, unique2, (generate_series(1, 10)), tenthous + -> ProjectSet + Output: unique1, unique2, generate_series(1, 10), tenthous + -> Foreign Scan on public.tenk1 + Output: unique1, unique2, two, four, ten, twenty, hundred, thousand, twothousand, fivethous, tenthous, odd, even, stringu1, stringu2, string4 + SQLite query: SELECT `unique1`, `unique2`, `tenthous` FROM main."tenk1" ORDER BY `tenthous` ASC NULLS LAST +(7 rows) + +--Testcase 24: +select unique1, unique2, generate_series(1,10) + from tenk1 order by tenthous limit 7; + unique1 | unique2 | generate_series +---------+---------+----------------- + 0 | 9998 | 1 + 0 | 9998 | 2 + 0 | 9998 | 3 + 0 | 9998 | 4 + 0 | 9998 | 5 + 0 | 9998 | 6 + 0 | 9998 | 7 +(7 rows) + +-- use of random() is to keep planner from folding the expressions together +--Testcase 66: +DELETE FROM INT8_TMP; +--Testcase 67: +INSERT INTO INT8_TMP VALUES (generate_series(0,2), generate_series((random()*.1)::int,2)); +--Testcase 68: +explain (verbose, costs off) +select q1, q2 from int8_tmp; + QUERY PLAN +-------------------------------------------------------- + Foreign Scan on public.int8_tmp + Output: q1, q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tmp" +(3 rows) + +--Testcase 69: +select q1, q2 from int8_tmp; + q1 | q2 +----+---- + 0 | 0 + 1 | 1 + 2 | 2 +(3 rows) + +--Testcase 70: +explain (verbose, costs off) +select q1, q2 from int8_tmp order by q2 desc; + QUERY PLAN +--------------------------------------------------------------------------------------- + Foreign Scan on public.int8_tmp + Output: q1, q2 + SQLite query: SELECT `q1`, `q2` FROM main."int8_tmp" ORDER BY `q2` DESC NULLS FIRST +(3 rows) + +--Testcase 71: +select q1, q2 from int8_tmp order by q2 desc; + q1 | q2 +----+---- + 2 | 2 + 1 | 1 + 0 | 0 +(3 rows) + +-- test for failure to set all aggregates' aggtranstype +--Testcase 25: +explain (verbose, costs off) +select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 + from tenk1 group by thousand order by thousand limit 3; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Limit + Output: (sum(tenthous)), ((((sum(tenthous)))::double precision + (random() * '0'::double precision))), thousand + -> Foreign Scan + Output: (sum(tenthous)), (((sum(tenthous)))::double precision + (random() * '0'::double precision)), thousand + SQLite query: SELECT sum(`tenthous`), `thousand` FROM main."tenk1" GROUP BY 2 ORDER BY `thousand` ASC NULLS LAST +(5 rows) + +--Testcase 26: +select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 + from tenk1 group by thousand order by thousand limit 3; + s1 | s2 +-------+------- + 45000 | 45000 + 45010 | 45010 + 45020 | 45020 +(3 rows) + +-- +-- FETCH FIRST +-- Check the WITH TIES clause +-- +--Testcase 72: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 2 ROW WITH TIES; + thousand +---------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(10 rows) + +--Testcase 73: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST ROWS WITH TIES; + thousand +---------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(10 rows) + +--Testcase 74: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES; + thousand +---------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(10 rows) + +--Testcase 75: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 2 ROW ONLY; + thousand +---------- + 0 + 0 +(2 rows) + +-- SKIP LOCKED and WITH TIES are incompatible +--Testcase 104: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; +ERROR: SKIP LOCKED and WITH TIES options cannot be used together +-- should fail +--Testcase 76: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 50 + FETCH FIRST 2 ROW WITH TIES; +ERROR: WITH TIES cannot be specified without ORDER BY clause +-- test ruleutils +--Testcase 77: +CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; +--Testcase 78: +\d+ limit_thousand_v_1 + View "public.limit_thousand_v_1" + Column | Type | Collation | Nullable | Default | Storage | Description +----------+---------+-----------+----------+---------+---------+------------- + thousand | integer | | | | plain | +View definition: + SELECT thousand + FROM onek + WHERE thousand < 995 + ORDER BY thousand + OFFSET 10 + FETCH FIRST 5 ROWS WITH TIES; + +--Testcase 79: +CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY; +--Testcase 80: +\d+ limit_thousand_v_2 + View "public.limit_thousand_v_2" + Column | Type | Collation | Nullable | Default | Storage | Description +----------+---------+-----------+----------+---------+---------+------------- + thousand | integer | | | | plain | +View definition: + SELECT thousand + FROM onek + WHERE thousand < 995 + ORDER BY thousand + OFFSET 10 + LIMIT 5; + +--Testcase 81: +CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS WITH TIES; -- fails +ERROR: row count cannot be null in FETCH FIRST ... WITH TIES clause +--Testcase 82: +CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; +--Testcase 83: +\d+ limit_thousand_v_3 + View "public.limit_thousand_v_3" + Column | Type | Collation | Nullable | Default | Storage | Description +----------+---------+-----------+----------+---------+---------+------------- + thousand | integer | | | | plain | +View definition: + SELECT thousand + FROM onek + WHERE thousand < 995 + ORDER BY thousand + FETCH FIRST (NULL::integer + 1) ROWS WITH TIES; + +--Testcase 84: +CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS ONLY; +--Testcase 85: +\d+ limit_thousand_v_4 + View "public.limit_thousand_v_4" + Column | Type | Collation | Nullable | Default | Storage | Description +----------+---------+-----------+----------+---------+---------+------------- + thousand | integer | | | | plain | +View definition: + SELECT thousand + FROM onek + WHERE thousand < 995 + ORDER BY thousand + LIMIT ALL; + +-- leave these views +--Testcase 110: +DELETE FROM int8_tbl; +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +NOTICE: drop cascades to 4 other objects +DETAIL: drop cascades to view limit_thousand_v_1 +drop cascades to view limit_thousand_v_2 +drop cascades to view limit_thousand_v_3 +drop cascades to view limit_thousand_v_4 +--Testcase 86: +DROP SERVER sqlite_svr; +--Testcase 87: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/extra/numeric.out b/expected/17.0/extra/numeric.out new file mode 100644 index 00000000..5b48f181 --- /dev/null +++ b/expected/17.0/extra/numeric.out @@ -0,0 +1,5840 @@ +-- +-- NUMERIC +-- +--Testcase 567: +CREATE EXTENSION sqlite_fdw; +--Testcase 568: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 569: +CREATE FOREIGN TABLE num_data (id int4 OPTIONS (key 'true'), val numeric(210,10)) SERVER sqlite_svr; +--Testcase 570: +CREATE FOREIGN TABLE num_exp_add (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 571: +CREATE FOREIGN TABLE num_exp_sub (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 572: +CREATE FOREIGN TABLE num_exp_div (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 573: +CREATE FOREIGN TABLE num_exp_mul (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 574: +CREATE FOREIGN TABLE num_exp_sqrt (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 575: +CREATE FOREIGN TABLE num_exp_ln (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 576: +CREATE FOREIGN TABLE num_exp_log10 (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 577: +CREATE FOREIGN TABLE num_exp_power_10_ln (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 1556: +CREATE FOREIGN TABLE num_variance (a numeric) SERVER sqlite_svr; +--Testcase 578: +CREATE FOREIGN TABLE num_result (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), result numeric(210,10)) SERVER sqlite_svr; +-- ****************************** +-- * The following EXPECTED results are computed by bc(1) +-- * with a scale of 200 +-- ****************************** +BEGIN TRANSACTION; +--Testcase 1: +INSERT INTO num_exp_add VALUES (0,0,'0'); +--Testcase 2: +INSERT INTO num_exp_sub VALUES (0,0,'0'); +--Testcase 3: +INSERT INTO num_exp_mul VALUES (0,0,'0'); +--Testcase 4: +INSERT INTO num_exp_div VALUES (0,0,'NaN'); +--Testcase 5: +INSERT INTO num_exp_add VALUES (0,1,'0'); +--Testcase 6: +INSERT INTO num_exp_sub VALUES (0,1,'0'); +--Testcase 7: +INSERT INTO num_exp_mul VALUES (0,1,'0'); +--Testcase 8: +INSERT INTO num_exp_div VALUES (0,1,'NaN'); +--Testcase 9: +INSERT INTO num_exp_add VALUES (0,2,'-34338492.215397047'); +--Testcase 10: +INSERT INTO num_exp_sub VALUES (0,2,'34338492.215397047'); +--Testcase 11: +INSERT INTO num_exp_mul VALUES (0,2,'0'); +--Testcase 12: +INSERT INTO num_exp_div VALUES (0,2,'0'); +--Testcase 13: +INSERT INTO num_exp_add VALUES (0,3,'4.31'); +--Testcase 14: +INSERT INTO num_exp_sub VALUES (0,3,'-4.31'); +--Testcase 15: +INSERT INTO num_exp_mul VALUES (0,3,'0'); +--Testcase 16: +INSERT INTO num_exp_div VALUES (0,3,'0'); +--Testcase 17: +INSERT INTO num_exp_add VALUES (0,4,'7799461.4119'); +--Testcase 18: +INSERT INTO num_exp_sub VALUES (0,4,'-7799461.4119'); +--Testcase 19: +INSERT INTO num_exp_mul VALUES (0,4,'0'); +--Testcase 20: +INSERT INTO num_exp_div VALUES (0,4,'0'); +--Testcase 21: +INSERT INTO num_exp_add VALUES (0,5,'16397.038491'); +--Testcase 22: +INSERT INTO num_exp_sub VALUES (0,5,'-16397.038491'); +--Testcase 23: +INSERT INTO num_exp_mul VALUES (0,5,'0'); +--Testcase 24: +INSERT INTO num_exp_div VALUES (0,5,'0'); +--Testcase 25: +INSERT INTO num_exp_add VALUES (0,6,'93901.57763026'); +--Testcase 26: +INSERT INTO num_exp_sub VALUES (0,6,'-93901.57763026'); +--Testcase 27: +INSERT INTO num_exp_mul VALUES (0,6,'0'); +--Testcase 28: +INSERT INTO num_exp_div VALUES (0,6,'0'); +--Testcase 29: +INSERT INTO num_exp_add VALUES (0,7,'-83028485'); +--Testcase 30: +INSERT INTO num_exp_sub VALUES (0,7,'83028485'); +--Testcase 31: +INSERT INTO num_exp_mul VALUES (0,7,'0'); +--Testcase 32: +INSERT INTO num_exp_div VALUES (0,7,'0'); +--Testcase 33: +INSERT INTO num_exp_add VALUES (0,8,'74881'); +--Testcase 34: +INSERT INTO num_exp_sub VALUES (0,8,'-74881'); +--Testcase 35: +INSERT INTO num_exp_mul VALUES (0,8,'0'); +--Testcase 36: +INSERT INTO num_exp_div VALUES (0,8,'0'); +--Testcase 37: +INSERT INTO num_exp_add VALUES (0,9,'-24926804.045047420'); +--Testcase 38: +INSERT INTO num_exp_sub VALUES (0,9,'24926804.045047420'); +--Testcase 39: +INSERT INTO num_exp_mul VALUES (0,9,'0'); +--Testcase 40: +INSERT INTO num_exp_div VALUES (0,9,'0'); +--Testcase 41: +INSERT INTO num_exp_add VALUES (1,0,'0'); +--Testcase 42: +INSERT INTO num_exp_sub VALUES (1,0,'0'); +--Testcase 43: +INSERT INTO num_exp_mul VALUES (1,0,'0'); +--Testcase 44: +INSERT INTO num_exp_div VALUES (1,0,'NaN'); +--Testcase 45: +INSERT INTO num_exp_add VALUES (1,1,'0'); +--Testcase 46: +INSERT INTO num_exp_sub VALUES (1,1,'0'); +--Testcase 47: +INSERT INTO num_exp_mul VALUES (1,1,'0'); +--Testcase 48: +INSERT INTO num_exp_div VALUES (1,1,'NaN'); +--Testcase 49: +INSERT INTO num_exp_add VALUES (1,2,'-34338492.215397047'); +--Testcase 50: +INSERT INTO num_exp_sub VALUES (1,2,'34338492.215397047'); +--Testcase 51: +INSERT INTO num_exp_mul VALUES (1,2,'0'); +--Testcase 52: +INSERT INTO num_exp_div VALUES (1,2,'0'); +--Testcase 53: +INSERT INTO num_exp_add VALUES (1,3,'4.31'); +--Testcase 54: +INSERT INTO num_exp_sub VALUES (1,3,'-4.31'); +--Testcase 55: +INSERT INTO num_exp_mul VALUES (1,3,'0'); +--Testcase 56: +INSERT INTO num_exp_div VALUES (1,3,'0'); +--Testcase 57: +INSERT INTO num_exp_add VALUES (1,4,'7799461.4119'); +--Testcase 58: +INSERT INTO num_exp_sub VALUES (1,4,'-7799461.4119'); +--Testcase 59: +INSERT INTO num_exp_mul VALUES (1,4,'0'); +--Testcase 60: +INSERT INTO num_exp_div VALUES (1,4,'0'); +--Testcase 61: +INSERT INTO num_exp_add VALUES (1,5,'16397.038491'); +--Testcase 62: +INSERT INTO num_exp_sub VALUES (1,5,'-16397.038491'); +--Testcase 63: +INSERT INTO num_exp_mul VALUES (1,5,'0'); +--Testcase 64: +INSERT INTO num_exp_div VALUES (1,5,'0'); +--Testcase 65: +INSERT INTO num_exp_add VALUES (1,6,'93901.57763026'); +--Testcase 66: +INSERT INTO num_exp_sub VALUES (1,6,'-93901.57763026'); +--Testcase 67: +INSERT INTO num_exp_mul VALUES (1,6,'0'); +--Testcase 68: +INSERT INTO num_exp_div VALUES (1,6,'0'); +--Testcase 69: +INSERT INTO num_exp_add VALUES (1,7,'-83028485'); +--Testcase 70: +INSERT INTO num_exp_sub VALUES (1,7,'83028485'); +--Testcase 71: +INSERT INTO num_exp_mul VALUES (1,7,'0'); +--Testcase 72: +INSERT INTO num_exp_div VALUES (1,7,'0'); +--Testcase 73: +INSERT INTO num_exp_add VALUES (1,8,'74881'); +--Testcase 74: +INSERT INTO num_exp_sub VALUES (1,8,'-74881'); +--Testcase 75: +INSERT INTO num_exp_mul VALUES (1,8,'0'); +--Testcase 76: +INSERT INTO num_exp_div VALUES (1,8,'0'); +--Testcase 77: +INSERT INTO num_exp_add VALUES (1,9,'-24926804.045047420'); +--Testcase 78: +INSERT INTO num_exp_sub VALUES (1,9,'24926804.045047420'); +--Testcase 79: +INSERT INTO num_exp_mul VALUES (1,9,'0'); +--Testcase 80: +INSERT INTO num_exp_div VALUES (1,9,'0'); +--Testcase 81: +INSERT INTO num_exp_add VALUES (2,0,'-34338492.215397047'); +--Testcase 82: +INSERT INTO num_exp_sub VALUES (2,0,'-34338492.215397047'); +--Testcase 83: +INSERT INTO num_exp_mul VALUES (2,0,'0'); +--Testcase 84: +INSERT INTO num_exp_div VALUES (2,0,'NaN'); +--Testcase 85: +INSERT INTO num_exp_add VALUES (2,1,'-34338492.215397047'); +--Testcase 86: +INSERT INTO num_exp_sub VALUES (2,1,'-34338492.215397047'); +--Testcase 87: +INSERT INTO num_exp_mul VALUES (2,1,'0'); +--Testcase 88: +INSERT INTO num_exp_div VALUES (2,1,'NaN'); +--Testcase 89: +INSERT INTO num_exp_add VALUES (2,2,'-68676984.430794094'); +--Testcase 90: +INSERT INTO num_exp_sub VALUES (2,2,'0'); +--Testcase 91: +INSERT INTO num_exp_mul VALUES (2,2,'1179132047626883.596862135856320209'); +--Testcase 92: +INSERT INTO num_exp_div VALUES (2,2,'1.00000000000000000000'); +--Testcase 93: +INSERT INTO num_exp_add VALUES (2,3,'-34338487.905397047'); +--Testcase 94: +INSERT INTO num_exp_sub VALUES (2,3,'-34338496.525397047'); +--Testcase 95: +INSERT INTO num_exp_mul VALUES (2,3,'-147998901.44836127257'); +--Testcase 96: +INSERT INTO num_exp_div VALUES (2,3,'-7967167.56737750510440835266'); +--Testcase 97: +INSERT INTO num_exp_add VALUES (2,4,'-26539030.803497047'); +--Testcase 98: +INSERT INTO num_exp_sub VALUES (2,4,'-42137953.627297047'); +--Testcase 99: +INSERT INTO num_exp_mul VALUES (2,4,'-267821744976817.8111137106593'); +--Testcase 100: +INSERT INTO num_exp_div VALUES (2,4,'-4.40267480046830116685'); +--Testcase 101: +INSERT INTO num_exp_add VALUES (2,5,'-34322095.176906047'); +--Testcase 102: +INSERT INTO num_exp_sub VALUES (2,5,'-34354889.253888047'); +--Testcase 103: +INSERT INTO num_exp_mul VALUES (2,5,'-563049578578.769242506736077'); +--Testcase 104: +INSERT INTO num_exp_div VALUES (2,5,'-2094.18866914563535496429'); +--Testcase 105: +INSERT INTO num_exp_add VALUES (2,6,'-34244590.637766787'); +--Testcase 106: +INSERT INTO num_exp_sub VALUES (2,6,'-34432393.793027307'); +--Testcase 107: +INSERT INTO num_exp_mul VALUES (2,6,'-3224438592470.18449811926184222'); +--Testcase 108: +INSERT INTO num_exp_div VALUES (2,6,'-365.68599891479766440940'); +--Testcase 109: +INSERT INTO num_exp_add VALUES (2,7,'-117366977.215397047'); +--Testcase 110: +INSERT INTO num_exp_sub VALUES (2,7,'48689992.784602953'); +--Testcase 111: +INSERT INTO num_exp_mul VALUES (2,7,'2851072985828710.485883795'); +--Testcase 112: +INSERT INTO num_exp_div VALUES (2,7,'.41357483778485235518'); +--Testcase 113: +INSERT INTO num_exp_add VALUES (2,8,'-34263611.215397047'); +--Testcase 114: +INSERT INTO num_exp_sub VALUES (2,8,'-34413373.215397047'); +--Testcase 115: +INSERT INTO num_exp_mul VALUES (2,8,'-2571300635581.146276407'); +--Testcase 116: +INSERT INTO num_exp_div VALUES (2,8,'-458.57416721727870888476'); +--Testcase 117: +INSERT INTO num_exp_add VALUES (2,9,'-59265296.260444467'); +--Testcase 118: +INSERT INTO num_exp_sub VALUES (2,9,'-9411688.170349627'); +--Testcase 119: +INSERT INTO num_exp_mul VALUES (2,9,'855948866655588.453741509242968740'); +--Testcase 120: +INSERT INTO num_exp_div VALUES (2,9,'1.37757299946438931811'); +--Testcase 121: +INSERT INTO num_exp_add VALUES (3,0,'4.31'); +--Testcase 122: +INSERT INTO num_exp_sub VALUES (3,0,'4.31'); +--Testcase 123: +INSERT INTO num_exp_mul VALUES (3,0,'0'); +--Testcase 124: +INSERT INTO num_exp_div VALUES (3,0,'NaN'); +--Testcase 125: +INSERT INTO num_exp_add VALUES (3,1,'4.31'); +--Testcase 126: +INSERT INTO num_exp_sub VALUES (3,1,'4.31'); +--Testcase 127: +INSERT INTO num_exp_mul VALUES (3,1,'0'); +--Testcase 128: +INSERT INTO num_exp_div VALUES (3,1,'NaN'); +--Testcase 129: +INSERT INTO num_exp_add VALUES (3,2,'-34338487.905397047'); +--Testcase 130: +INSERT INTO num_exp_sub VALUES (3,2,'34338496.525397047'); +--Testcase 131: +INSERT INTO num_exp_mul VALUES (3,2,'-147998901.44836127257'); +--Testcase 132: +INSERT INTO num_exp_div VALUES (3,2,'-.00000012551512084352'); +--Testcase 133: +INSERT INTO num_exp_add VALUES (3,3,'8.62'); +--Testcase 134: +INSERT INTO num_exp_sub VALUES (3,3,'0'); +--Testcase 135: +INSERT INTO num_exp_mul VALUES (3,3,'18.5761'); +--Testcase 136: +INSERT INTO num_exp_div VALUES (3,3,'1.00000000000000000000'); +--Testcase 137: +INSERT INTO num_exp_add VALUES (3,4,'7799465.7219'); +--Testcase 138: +INSERT INTO num_exp_sub VALUES (3,4,'-7799457.1019'); +--Testcase 139: +INSERT INTO num_exp_mul VALUES (3,4,'33615678.685289'); +--Testcase 140: +INSERT INTO num_exp_div VALUES (3,4,'.00000055260225961552'); +--Testcase 141: +INSERT INTO num_exp_add VALUES (3,5,'16401.348491'); +--Testcase 142: +INSERT INTO num_exp_sub VALUES (3,5,'-16392.728491'); +--Testcase 143: +INSERT INTO num_exp_mul VALUES (3,5,'70671.23589621'); +--Testcase 144: +INSERT INTO num_exp_div VALUES (3,5,'.00026285234387695504'); +--Testcase 145: +INSERT INTO num_exp_add VALUES (3,6,'93905.88763026'); +--Testcase 146: +INSERT INTO num_exp_sub VALUES (3,6,'-93897.26763026'); +--Testcase 147: +INSERT INTO num_exp_mul VALUES (3,6,'404715.7995864206'); +--Testcase 148: +INSERT INTO num_exp_div VALUES (3,6,'.00004589912234457595'); +--Testcase 149: +INSERT INTO num_exp_add VALUES (3,7,'-83028480.69'); +--Testcase 150: +INSERT INTO num_exp_sub VALUES (3,7,'83028489.31'); +--Testcase 151: +INSERT INTO num_exp_mul VALUES (3,7,'-357852770.35'); +--Testcase 152: +INSERT INTO num_exp_div VALUES (3,7,'-.00000005190989574240'); +--Testcase 153: +INSERT INTO num_exp_add VALUES (3,8,'74885.31'); +--Testcase 154: +INSERT INTO num_exp_sub VALUES (3,8,'-74876.69'); +--Testcase 155: +INSERT INTO num_exp_mul VALUES (3,8,'322737.11'); +--Testcase 156: +INSERT INTO num_exp_div VALUES (3,8,'.00005755799201399553'); +--Testcase 157: +INSERT INTO num_exp_add VALUES (3,9,'-24926799.735047420'); +--Testcase 158: +INSERT INTO num_exp_sub VALUES (3,9,'24926808.355047420'); +--Testcase 159: +INSERT INTO num_exp_mul VALUES (3,9,'-107434525.43415438020'); +--Testcase 160: +INSERT INTO num_exp_div VALUES (3,9,'-.00000017290624149854'); +--Testcase 161: +INSERT INTO num_exp_add VALUES (4,0,'7799461.4119'); +--Testcase 162: +INSERT INTO num_exp_sub VALUES (4,0,'7799461.4119'); +--Testcase 163: +INSERT INTO num_exp_mul VALUES (4,0,'0'); +--Testcase 164: +INSERT INTO num_exp_div VALUES (4,0,'NaN'); +--Testcase 165: +INSERT INTO num_exp_add VALUES (4,1,'7799461.4119'); +--Testcase 166: +INSERT INTO num_exp_sub VALUES (4,1,'7799461.4119'); +--Testcase 167: +INSERT INTO num_exp_mul VALUES (4,1,'0'); +--Testcase 168: +INSERT INTO num_exp_div VALUES (4,1,'NaN'); +--Testcase 169: +INSERT INTO num_exp_add VALUES (4,2,'-26539030.803497047'); +--Testcase 170: +INSERT INTO num_exp_sub VALUES (4,2,'42137953.627297047'); +--Testcase 171: +INSERT INTO num_exp_mul VALUES (4,2,'-267821744976817.8111137106593'); +--Testcase 172: +INSERT INTO num_exp_div VALUES (4,2,'-.22713465002993920385'); +--Testcase 173: +INSERT INTO num_exp_add VALUES (4,3,'7799465.7219'); +--Testcase 174: +INSERT INTO num_exp_sub VALUES (4,3,'7799457.1019'); +--Testcase 175: +INSERT INTO num_exp_mul VALUES (4,3,'33615678.685289'); +--Testcase 176: +INSERT INTO num_exp_div VALUES (4,3,'1809619.81714617169373549883'); +--Testcase 177: +INSERT INTO num_exp_add VALUES (4,4,'15598922.8238'); +--Testcase 178: +INSERT INTO num_exp_sub VALUES (4,4,'0'); +--Testcase 179: +INSERT INTO num_exp_mul VALUES (4,4,'60831598315717.14146161'); +--Testcase 180: +INSERT INTO num_exp_div VALUES (4,4,'1.00000000000000000000'); +--Testcase 181: +INSERT INTO num_exp_add VALUES (4,5,'7815858.450391'); +--Testcase 182: +INSERT INTO num_exp_sub VALUES (4,5,'7783064.373409'); +--Testcase 183: +INSERT INTO num_exp_mul VALUES (4,5,'127888068979.9935054429'); +--Testcase 184: +INSERT INTO num_exp_div VALUES (4,5,'475.66281046305802686061'); +--Testcase 185: +INSERT INTO num_exp_add VALUES (4,6,'7893362.98953026'); +--Testcase 186: +INSERT INTO num_exp_sub VALUES (4,6,'7705559.83426974'); +--Testcase 187: +INSERT INTO num_exp_mul VALUES (4,6,'732381731243.745115764094'); +--Testcase 188: +INSERT INTO num_exp_div VALUES (4,6,'83.05996138436129499606'); +--Testcase 189: +INSERT INTO num_exp_add VALUES (4,7,'-75229023.5881'); +--Testcase 190: +INSERT INTO num_exp_sub VALUES (4,7,'90827946.4119'); +--Testcase 191: +INSERT INTO num_exp_mul VALUES (4,7,'-647577464846017.9715'); +--Testcase 192: +INSERT INTO num_exp_div VALUES (4,7,'-.09393717604145131637'); +--Testcase 193: +INSERT INTO num_exp_add VALUES (4,8,'7874342.4119'); +--Testcase 194: +INSERT INTO num_exp_sub VALUES (4,8,'7724580.4119'); +--Testcase 195: +INSERT INTO num_exp_mul VALUES (4,8,'584031469984.4839'); +--Testcase 196: +INSERT INTO num_exp_div VALUES (4,8,'104.15808298366741897143'); +--Testcase 197: +INSERT INTO num_exp_add VALUES (4,9,'-17127342.633147420'); +--Testcase 198: +INSERT INTO num_exp_sub VALUES (4,9,'32726265.456947420'); +--Testcase 199: +INSERT INTO num_exp_mul VALUES (4,9,'-194415646271340.1815956522980'); +--Testcase 200: +INSERT INTO num_exp_div VALUES (4,9,'-.31289456112403769409'); +--Testcase 201: +INSERT INTO num_exp_add VALUES (5,0,'16397.038491'); +--Testcase 202: +INSERT INTO num_exp_sub VALUES (5,0,'16397.038491'); +--Testcase 203: +INSERT INTO num_exp_mul VALUES (5,0,'0'); +--Testcase 204: +INSERT INTO num_exp_div VALUES (5,0,'NaN'); +--Testcase 205: +INSERT INTO num_exp_add VALUES (5,1,'16397.038491'); +--Testcase 206: +INSERT INTO num_exp_sub VALUES (5,1,'16397.038491'); +--Testcase 207: +INSERT INTO num_exp_mul VALUES (5,1,'0'); +--Testcase 208: +INSERT INTO num_exp_div VALUES (5,1,'NaN'); +--Testcase 209: +INSERT INTO num_exp_add VALUES (5,2,'-34322095.176906047'); +--Testcase 210: +INSERT INTO num_exp_sub VALUES (5,2,'34354889.253888047'); +--Testcase 211: +INSERT INTO num_exp_mul VALUES (5,2,'-563049578578.769242506736077'); +--Testcase 212: +INSERT INTO num_exp_div VALUES (5,2,'-.00047751189505192446'); +--Testcase 213: +INSERT INTO num_exp_add VALUES (5,3,'16401.348491'); +--Testcase 214: +INSERT INTO num_exp_sub VALUES (5,3,'16392.728491'); +--Testcase 215: +INSERT INTO num_exp_mul VALUES (5,3,'70671.23589621'); +--Testcase 216: +INSERT INTO num_exp_div VALUES (5,3,'3804.41728329466357308584'); +--Testcase 217: +INSERT INTO num_exp_add VALUES (5,4,'7815858.450391'); +--Testcase 218: +INSERT INTO num_exp_sub VALUES (5,4,'-7783064.373409'); +--Testcase 219: +INSERT INTO num_exp_mul VALUES (5,4,'127888068979.9935054429'); +--Testcase 220: +INSERT INTO num_exp_div VALUES (5,4,'.00210232958726897192'); +--Testcase 221: +INSERT INTO num_exp_add VALUES (5,5,'32794.076982'); +--Testcase 222: +INSERT INTO num_exp_sub VALUES (5,5,'0'); +--Testcase 223: +INSERT INTO num_exp_mul VALUES (5,5,'268862871.275335557081'); +--Testcase 224: +INSERT INTO num_exp_div VALUES (5,5,'1.00000000000000000000'); +--Testcase 225: +INSERT INTO num_exp_add VALUES (5,6,'110298.61612126'); +--Testcase 226: +INSERT INTO num_exp_sub VALUES (5,6,'-77504.53913926'); +--Testcase 227: +INSERT INTO num_exp_mul VALUES (5,6,'1539707782.76899778633766'); +--Testcase 228: +INSERT INTO num_exp_div VALUES (5,6,'.17461941433576102689'); +--Testcase 229: +INSERT INTO num_exp_add VALUES (5,7,'-83012087.961509'); +--Testcase 230: +INSERT INTO num_exp_sub VALUES (5,7,'83044882.038491'); +--Testcase 231: +INSERT INTO num_exp_mul VALUES (5,7,'-1361421264394.416135'); +--Testcase 232: +INSERT INTO num_exp_div VALUES (5,7,'-.00019748690453643710'); +--Testcase 233: +INSERT INTO num_exp_add VALUES (5,8,'91278.038491'); +--Testcase 234: +INSERT INTO num_exp_sub VALUES (5,8,'-58483.961509'); +--Testcase 235: +INSERT INTO num_exp_mul VALUES (5,8,'1227826639.244571'); +--Testcase 236: +INSERT INTO num_exp_div VALUES (5,8,'.21897461960978085228'); +--Testcase 237: +INSERT INTO num_exp_add VALUES (5,9,'-24910407.006556420'); +--Testcase 238: +INSERT INTO num_exp_sub VALUES (5,9,'24943201.083538420'); +--Testcase 239: +INSERT INTO num_exp_mul VALUES (5,9,'-408725765384.257043660243220'); +--Testcase 240: +INSERT INTO num_exp_div VALUES (5,9,'-.00065780749354660427'); +--Testcase 241: +INSERT INTO num_exp_add VALUES (6,0,'93901.57763026'); +--Testcase 242: +INSERT INTO num_exp_sub VALUES (6,0,'93901.57763026'); +--Testcase 243: +INSERT INTO num_exp_mul VALUES (6,0,'0'); +--Testcase 244: +INSERT INTO num_exp_div VALUES (6,0,'NaN'); +--Testcase 245: +INSERT INTO num_exp_add VALUES (6,1,'93901.57763026'); +--Testcase 246: +INSERT INTO num_exp_sub VALUES (6,1,'93901.57763026'); +--Testcase 247: +INSERT INTO num_exp_mul VALUES (6,1,'0'); +--Testcase 248: +INSERT INTO num_exp_div VALUES (6,1,'NaN'); +--Testcase 249: +INSERT INTO num_exp_add VALUES (6,2,'-34244590.637766787'); +--Testcase 250: +INSERT INTO num_exp_sub VALUES (6,2,'34432393.793027307'); +--Testcase 251: +INSERT INTO num_exp_mul VALUES (6,2,'-3224438592470.18449811926184222'); +--Testcase 252: +INSERT INTO num_exp_div VALUES (6,2,'-.00273458651128995823'); +--Testcase 253: +INSERT INTO num_exp_add VALUES (6,3,'93905.88763026'); +--Testcase 254: +INSERT INTO num_exp_sub VALUES (6,3,'93897.26763026'); +--Testcase 255: +INSERT INTO num_exp_mul VALUES (6,3,'404715.7995864206'); +--Testcase 256: +INSERT INTO num_exp_div VALUES (6,3,'21786.90896293735498839907'); +--Testcase 257: +INSERT INTO num_exp_add VALUES (6,4,'7893362.98953026'); +--Testcase 258: +INSERT INTO num_exp_sub VALUES (6,4,'-7705559.83426974'); +--Testcase 259: +INSERT INTO num_exp_mul VALUES (6,4,'732381731243.745115764094'); +--Testcase 260: +INSERT INTO num_exp_div VALUES (6,4,'.01203949512295682469'); +--Testcase 261: +INSERT INTO num_exp_add VALUES (6,5,'110298.61612126'); +--Testcase 262: +INSERT INTO num_exp_sub VALUES (6,5,'77504.53913926'); +--Testcase 263: +INSERT INTO num_exp_mul VALUES (6,5,'1539707782.76899778633766'); +--Testcase 264: +INSERT INTO num_exp_div VALUES (6,5,'5.72674008674192359679'); +--Testcase 265: +INSERT INTO num_exp_add VALUES (6,6,'187803.15526052'); +--Testcase 266: +INSERT INTO num_exp_sub VALUES (6,6,'0'); +--Testcase 267: +INSERT INTO num_exp_mul VALUES (6,6,'8817506281.4517452372676676'); +--Testcase 268: +INSERT INTO num_exp_div VALUES (6,6,'1.00000000000000000000'); +--Testcase 269: +INSERT INTO num_exp_add VALUES (6,7,'-82934583.42236974'); +--Testcase 270: +INSERT INTO num_exp_sub VALUES (6,7,'83122386.57763026'); +--Testcase 271: +INSERT INTO num_exp_mul VALUES (6,7,'-7796505729750.37795610'); +--Testcase 272: +INSERT INTO num_exp_div VALUES (6,7,'-.00113095617281538980'); +--Testcase 273: +INSERT INTO num_exp_add VALUES (6,8,'168782.57763026'); +--Testcase 274: +INSERT INTO num_exp_sub VALUES (6,8,'19020.57763026'); +--Testcase 275: +INSERT INTO num_exp_mul VALUES (6,8,'7031444034.53149906'); +--Testcase 276: +INSERT INTO num_exp_div VALUES (6,8,'1.25401073209839612184'); +--Testcase 277: +INSERT INTO num_exp_add VALUES (6,9,'-24832902.467417160'); +--Testcase 278: +INSERT INTO num_exp_sub VALUES (6,9,'25020705.622677680'); +--Testcase 279: +INSERT INTO num_exp_mul VALUES (6,9,'-2340666225110.29929521292692920'); +--Testcase 280: +INSERT INTO num_exp_div VALUES (6,9,'-.00376709254265256789'); +--Testcase 281: +INSERT INTO num_exp_add VALUES (7,0,'-83028485'); +--Testcase 282: +INSERT INTO num_exp_sub VALUES (7,0,'-83028485'); +--Testcase 283: +INSERT INTO num_exp_mul VALUES (7,0,'0'); +--Testcase 284: +INSERT INTO num_exp_div VALUES (7,0,'NaN'); +--Testcase 285: +INSERT INTO num_exp_add VALUES (7,1,'-83028485'); +--Testcase 286: +INSERT INTO num_exp_sub VALUES (7,1,'-83028485'); +--Testcase 287: +INSERT INTO num_exp_mul VALUES (7,1,'0'); +--Testcase 288: +INSERT INTO num_exp_div VALUES (7,1,'NaN'); +--Testcase 289: +INSERT INTO num_exp_add VALUES (7,2,'-117366977.215397047'); +--Testcase 290: +INSERT INTO num_exp_sub VALUES (7,2,'-48689992.784602953'); +--Testcase 291: +INSERT INTO num_exp_mul VALUES (7,2,'2851072985828710.485883795'); +--Testcase 292: +INSERT INTO num_exp_div VALUES (7,2,'2.41794207151503385700'); +--Testcase 293: +INSERT INTO num_exp_add VALUES (7,3,'-83028480.69'); +--Testcase 294: +INSERT INTO num_exp_sub VALUES (7,3,'-83028489.31'); +--Testcase 295: +INSERT INTO num_exp_mul VALUES (7,3,'-357852770.35'); +--Testcase 296: +INSERT INTO num_exp_div VALUES (7,3,'-19264149.65197215777262180974'); +--Testcase 297: +INSERT INTO num_exp_add VALUES (7,4,'-75229023.5881'); +--Testcase 298: +INSERT INTO num_exp_sub VALUES (7,4,'-90827946.4119'); +--Testcase 299: +INSERT INTO num_exp_mul VALUES (7,4,'-647577464846017.9715'); +--Testcase 300: +INSERT INTO num_exp_div VALUES (7,4,'-10.64541262725136247686'); +--Testcase 301: +INSERT INTO num_exp_add VALUES (7,5,'-83012087.961509'); +--Testcase 302: +INSERT INTO num_exp_sub VALUES (7,5,'-83044882.038491'); +--Testcase 303: +INSERT INTO num_exp_mul VALUES (7,5,'-1361421264394.416135'); +--Testcase 304: +INSERT INTO num_exp_div VALUES (7,5,'-5063.62688881730941836574'); +--Testcase 305: +INSERT INTO num_exp_add VALUES (7,6,'-82934583.42236974'); +--Testcase 306: +INSERT INTO num_exp_sub VALUES (7,6,'-83122386.57763026'); +--Testcase 307: +INSERT INTO num_exp_mul VALUES (7,6,'-7796505729750.37795610'); +--Testcase 308: +INSERT INTO num_exp_div VALUES (7,6,'-884.20756174009028770294'); +--Testcase 309: +INSERT INTO num_exp_add VALUES (7,7,'-166056970'); +--Testcase 310: +INSERT INTO num_exp_sub VALUES (7,7,'0'); +--Testcase 311: +INSERT INTO num_exp_mul VALUES (7,7,'6893729321395225'); +--Testcase 312: +INSERT INTO num_exp_div VALUES (7,7,'1.00000000000000000000'); +--Testcase 313: +INSERT INTO num_exp_add VALUES (7,8,'-82953604'); +--Testcase 314: +INSERT INTO num_exp_sub VALUES (7,8,'-83103366'); +--Testcase 315: +INSERT INTO num_exp_mul VALUES (7,8,'-6217255985285'); +--Testcase 316: +INSERT INTO num_exp_div VALUES (7,8,'-1108.80577182462841041118'); +--Testcase 317: +INSERT INTO num_exp_add VALUES (7,9,'-107955289.045047420'); +--Testcase 318: +INSERT INTO num_exp_sub VALUES (7,9,'-58101680.954952580'); +--Testcase 319: +INSERT INTO num_exp_mul VALUES (7,9,'2069634775752159.035758700'); +--Testcase 320: +INSERT INTO num_exp_div VALUES (7,9,'3.33089171198810413382'); +--Testcase 321: +INSERT INTO num_exp_add VALUES (8,0,'74881'); +--Testcase 322: +INSERT INTO num_exp_sub VALUES (8,0,'74881'); +--Testcase 323: +INSERT INTO num_exp_mul VALUES (8,0,'0'); +--Testcase 324: +INSERT INTO num_exp_div VALUES (8,0,'NaN'); +--Testcase 325: +INSERT INTO num_exp_add VALUES (8,1,'74881'); +--Testcase 326: +INSERT INTO num_exp_sub VALUES (8,1,'74881'); +--Testcase 327: +INSERT INTO num_exp_mul VALUES (8,1,'0'); +--Testcase 328: +INSERT INTO num_exp_div VALUES (8,1,'NaN'); +--Testcase 329: +INSERT INTO num_exp_add VALUES (8,2,'-34263611.215397047'); +--Testcase 330: +INSERT INTO num_exp_sub VALUES (8,2,'34413373.215397047'); +--Testcase 331: +INSERT INTO num_exp_mul VALUES (8,2,'-2571300635581.146276407'); +--Testcase 332: +INSERT INTO num_exp_div VALUES (8,2,'-.00218067233500788615'); +--Testcase 333: +INSERT INTO num_exp_add VALUES (8,3,'74885.31'); +--Testcase 334: +INSERT INTO num_exp_sub VALUES (8,3,'74876.69'); +--Testcase 335: +INSERT INTO num_exp_mul VALUES (8,3,'322737.11'); +--Testcase 336: +INSERT INTO num_exp_div VALUES (8,3,'17373.78190255220417633410'); +--Testcase 337: +INSERT INTO num_exp_add VALUES (8,4,'7874342.4119'); +--Testcase 338: +INSERT INTO num_exp_sub VALUES (8,4,'-7724580.4119'); +--Testcase 339: +INSERT INTO num_exp_mul VALUES (8,4,'584031469984.4839'); +--Testcase 340: +INSERT INTO num_exp_div VALUES (8,4,'.00960079113741758956'); +--Testcase 341: +INSERT INTO num_exp_add VALUES (8,5,'91278.038491'); +--Testcase 342: +INSERT INTO num_exp_sub VALUES (8,5,'58483.961509'); +--Testcase 343: +INSERT INTO num_exp_mul VALUES (8,5,'1227826639.244571'); +--Testcase 344: +INSERT INTO num_exp_div VALUES (8,5,'4.56673929509287019456'); +--Testcase 345: +INSERT INTO num_exp_add VALUES (8,6,'168782.57763026'); +--Testcase 346: +INSERT INTO num_exp_sub VALUES (8,6,'-19020.57763026'); +--Testcase 347: +INSERT INTO num_exp_mul VALUES (8,6,'7031444034.53149906'); +--Testcase 348: +INSERT INTO num_exp_div VALUES (8,6,'.79744134113322314424'); +--Testcase 349: +INSERT INTO num_exp_add VALUES (8,7,'-82953604'); +--Testcase 350: +INSERT INTO num_exp_sub VALUES (8,7,'83103366'); +--Testcase 351: +INSERT INTO num_exp_mul VALUES (8,7,'-6217255985285'); +--Testcase 352: +INSERT INTO num_exp_div VALUES (8,7,'-.00090187120721280172'); +--Testcase 353: +INSERT INTO num_exp_add VALUES (8,8,'149762'); +--Testcase 354: +INSERT INTO num_exp_sub VALUES (8,8,'0'); +--Testcase 355: +INSERT INTO num_exp_mul VALUES (8,8,'5607164161'); +--Testcase 356: +INSERT INTO num_exp_div VALUES (8,8,'1.00000000000000000000'); +--Testcase 357: +INSERT INTO num_exp_add VALUES (8,9,'-24851923.045047420'); +--Testcase 358: +INSERT INTO num_exp_sub VALUES (8,9,'25001685.045047420'); +--Testcase 359: +INSERT INTO num_exp_mul VALUES (8,9,'-1866544013697.195857020'); +--Testcase 360: +INSERT INTO num_exp_div VALUES (8,9,'-.00300403532938582735'); +--Testcase 361: +INSERT INTO num_exp_add VALUES (9,0,'-24926804.045047420'); +--Testcase 362: +INSERT INTO num_exp_sub VALUES (9,0,'-24926804.045047420'); +--Testcase 363: +INSERT INTO num_exp_mul VALUES (9,0,'0'); +--Testcase 364: +INSERT INTO num_exp_div VALUES (9,0,'NaN'); +--Testcase 365: +INSERT INTO num_exp_add VALUES (9,1,'-24926804.045047420'); +--Testcase 366: +INSERT INTO num_exp_sub VALUES (9,1,'-24926804.045047420'); +--Testcase 367: +INSERT INTO num_exp_mul VALUES (9,1,'0'); +--Testcase 368: +INSERT INTO num_exp_div VALUES (9,1,'NaN'); +--Testcase 369: +INSERT INTO num_exp_add VALUES (9,2,'-59265296.260444467'); +--Testcase 370: +INSERT INTO num_exp_sub VALUES (9,2,'9411688.170349627'); +--Testcase 371: +INSERT INTO num_exp_mul VALUES (9,2,'855948866655588.453741509242968740'); +--Testcase 372: +INSERT INTO num_exp_div VALUES (9,2,'.72591434384152961526'); +--Testcase 373: +INSERT INTO num_exp_add VALUES (9,3,'-24926799.735047420'); +--Testcase 374: +INSERT INTO num_exp_sub VALUES (9,3,'-24926808.355047420'); +--Testcase 375: +INSERT INTO num_exp_mul VALUES (9,3,'-107434525.43415438020'); +--Testcase 376: +INSERT INTO num_exp_div VALUES (9,3,'-5783481.21694835730858468677'); +--Testcase 377: +INSERT INTO num_exp_add VALUES (9,4,'-17127342.633147420'); +--Testcase 378: +INSERT INTO num_exp_sub VALUES (9,4,'-32726265.456947420'); +--Testcase 379: +INSERT INTO num_exp_mul VALUES (9,4,'-194415646271340.1815956522980'); +--Testcase 380: +INSERT INTO num_exp_div VALUES (9,4,'-3.19596478892958416484'); +--Testcase 381: +INSERT INTO num_exp_add VALUES (9,5,'-24910407.006556420'); +--Testcase 382: +INSERT INTO num_exp_sub VALUES (9,5,'-24943201.083538420'); +--Testcase 383: +INSERT INTO num_exp_mul VALUES (9,5,'-408725765384.257043660243220'); +--Testcase 384: +INSERT INTO num_exp_div VALUES (9,5,'-1520.20159364322004505807'); +--Testcase 385: +INSERT INTO num_exp_add VALUES (9,6,'-24832902.467417160'); +--Testcase 386: +INSERT INTO num_exp_sub VALUES (9,6,'-25020705.622677680'); +--Testcase 387: +INSERT INTO num_exp_mul VALUES (9,6,'-2340666225110.29929521292692920'); +--Testcase 388: +INSERT INTO num_exp_div VALUES (9,6,'-265.45671195426965751280'); +--Testcase 389: +INSERT INTO num_exp_add VALUES (9,7,'-107955289.045047420'); +--Testcase 390: +INSERT INTO num_exp_sub VALUES (9,7,'58101680.954952580'); +--Testcase 391: +INSERT INTO num_exp_mul VALUES (9,7,'2069634775752159.035758700'); +--Testcase 392: +INSERT INTO num_exp_div VALUES (9,7,'.30021990699995814689'); +--Testcase 393: +INSERT INTO num_exp_add VALUES (9,8,'-24851923.045047420'); +--Testcase 394: +INSERT INTO num_exp_sub VALUES (9,8,'-25001685.045047420'); +--Testcase 395: +INSERT INTO num_exp_mul VALUES (9,8,'-1866544013697.195857020'); +--Testcase 396: +INSERT INTO num_exp_div VALUES (9,8,'-332.88556569820675471748'); +--Testcase 397: +INSERT INTO num_exp_add VALUES (9,9,'-49853608.090094840'); +--Testcase 398: +INSERT INTO num_exp_sub VALUES (9,9,'0'); +--Testcase 399: +INSERT INTO num_exp_mul VALUES (9,9,'621345559900192.420120630048656400'); +--Testcase 400: +INSERT INTO num_exp_div VALUES (9,9,'1.00000000000000000000'); +COMMIT TRANSACTION; +BEGIN TRANSACTION; +--Testcase 401: +INSERT INTO num_exp_sqrt VALUES (0,'0'); +--Testcase 402: +INSERT INTO num_exp_sqrt VALUES (1,'0'); +--Testcase 403: +INSERT INTO num_exp_sqrt VALUES (2,'5859.90547836712524903505'); +--Testcase 404: +INSERT INTO num_exp_sqrt VALUES (3,'2.07605394920266944396'); +--Testcase 405: +INSERT INTO num_exp_sqrt VALUES (4,'2792.75158435189147418923'); +--Testcase 406: +INSERT INTO num_exp_sqrt VALUES (5,'128.05092147657509145473'); +--Testcase 407: +INSERT INTO num_exp_sqrt VALUES (6,'306.43364311096782703406'); +--Testcase 408: +INSERT INTO num_exp_sqrt VALUES (7,'9111.99676251039939975230'); +--Testcase 409: +INSERT INTO num_exp_sqrt VALUES (8,'273.64392922189960397542'); +--Testcase 410: +INSERT INTO num_exp_sqrt VALUES (9,'4992.67503899937593364766'); +COMMIT TRANSACTION; +BEGIN TRANSACTION; +--Testcase 411: +INSERT INTO num_exp_ln VALUES (0,'NaN'); +--Testcase 412: +INSERT INTO num_exp_ln VALUES (1,'NaN'); +--Testcase 413: +INSERT INTO num_exp_ln VALUES (2,'17.35177750493897715514'); +--Testcase 414: +INSERT INTO num_exp_ln VALUES (3,'1.46093790411565641971'); +--Testcase 415: +INSERT INTO num_exp_ln VALUES (4,'15.86956523951936572464'); +--Testcase 416: +INSERT INTO num_exp_ln VALUES (5,'9.70485601768871834038'); +--Testcase 417: +INSERT INTO num_exp_ln VALUES (6,'11.45000246622944403127'); +--Testcase 418: +INSERT INTO num_exp_ln VALUES (7,'18.23469429965478772991'); +--Testcase 419: +INSERT INTO num_exp_ln VALUES (8,'11.22365546576315513668'); +--Testcase 420: +INSERT INTO num_exp_ln VALUES (9,'17.03145425013166006962'); +COMMIT TRANSACTION; +BEGIN TRANSACTION; +--Testcase 421: +INSERT INTO num_exp_log10 VALUES (0,'NaN'); +--Testcase 422: +INSERT INTO num_exp_log10 VALUES (1,'NaN'); +--Testcase 423: +INSERT INTO num_exp_log10 VALUES (2,'7.53578122160797276459'); +--Testcase 424: +INSERT INTO num_exp_log10 VALUES (3,'.63447727016073160075'); +--Testcase 425: +INSERT INTO num_exp_log10 VALUES (4,'6.89206461372691743345'); +--Testcase 426: +INSERT INTO num_exp_log10 VALUES (5,'4.21476541614777768626'); +--Testcase 427: +INSERT INTO num_exp_log10 VALUES (6,'4.97267288886207207671'); +--Testcase 428: +INSERT INTO num_exp_log10 VALUES (7,'7.91922711353275546914'); +--Testcase 429: +INSERT INTO num_exp_log10 VALUES (8,'4.87437163556421004138'); +--Testcase 430: +INSERT INTO num_exp_log10 VALUES (9,'7.39666659961986567059'); +COMMIT TRANSACTION; +BEGIN TRANSACTION; +--Testcase 431: +INSERT INTO num_exp_power_10_ln VALUES (0,'NaN'); +--Testcase 432: +INSERT INTO num_exp_power_10_ln VALUES (1,'NaN'); +--Testcase 433: +INSERT INTO num_exp_power_10_ln VALUES (2,'224790267919917955.13261618583642653184'); +--Testcase 434: +INSERT INTO num_exp_power_10_ln VALUES (3,'28.90266599445155957393'); +--Testcase 435: +INSERT INTO num_exp_power_10_ln VALUES (4,'7405685069594999.07733999469386277636'); +--Testcase 436: +INSERT INTO num_exp_power_10_ln VALUES (5,'5068226527.32127265408584640098'); +--Testcase 437: +INSERT INTO num_exp_power_10_ln VALUES (6,'281839893606.99372343357047819067'); +--Testcase 438: +INSERT INTO num_exp_power_10_ln VALUES (7,'1716699575118597095.42330819910640247627'); +--Testcase 439: +INSERT INTO num_exp_power_10_ln VALUES (8,'167361463828.07491320069016125952'); +--Testcase 440: +INSERT INTO num_exp_power_10_ln VALUES (9,'107511333880052007.04141124673540337457'); +COMMIT TRANSACTION; +BEGIN TRANSACTION; +--Testcase 441: +INSERT INTO num_data VALUES (0, '0'); +--Testcase 442: +INSERT INTO num_data VALUES (1, '0'); +--Testcase 443: +INSERT INTO num_data VALUES (2, '-34338492.215397047'); +--Testcase 444: +INSERT INTO num_data VALUES (3, '4.31'); +--Testcase 445: +INSERT INTO num_data VALUES (4, '7799461.4119'); +--Testcase 446: +INSERT INTO num_data VALUES (5, '16397.038491'); +--Testcase 447: +INSERT INTO num_data VALUES (6, '93901.57763026'); +--Testcase 448: +INSERT INTO num_data VALUES (7, '-83028485'); +--Testcase 449: +INSERT INTO num_data VALUES (8, '74881'); +--Testcase 450: +INSERT INTO num_data VALUES (9, '-24926804.045047420'); +COMMIT TRANSACTION; +-- ****************************** +-- * Create indices for faster checks +-- ****************************** +-- Skip these setting, creating foreign table with primary key already covered. +--CREATE UNIQUE INDEX num_exp_add_idx ON num_exp_add (id1, id2); +--CREATE UNIQUE INDEX num_exp_sub_idx ON num_exp_sub (id1, id2); +--CREATE UNIQUE INDEX num_exp_div_idx ON num_exp_div (id1, id2); +--CREATE UNIQUE INDEX num_exp_mul_idx ON num_exp_mul (id1, id2); +--CREATE UNIQUE INDEX num_exp_sqrt_idx ON num_exp_sqrt (id); +--CREATE UNIQUE INDEX num_exp_ln_idx ON num_exp_ln (id); +--CREATE UNIQUE INDEX num_exp_log10_idx ON num_exp_log10 (id); +--CREATE UNIQUE INDEX num_exp_power_10_ln_idx ON num_exp_power_10_ln (id); +--VACUUM ANALYZE num_exp_add; +--VACUUM ANALYZE num_exp_sub; +--VACUUM ANALYZE num_exp_div; +--VACUUM ANALYZE num_exp_mul; +--VACUUM ANALYZE num_exp_sqrt; +--VACUUM ANALYZE num_exp_ln; +--VACUUM ANALYZE num_exp_log10; +--VACUUM ANALYZE num_exp_power_10_ln; +-- ****************************** +-- * Now check the behaviour of the NUMERIC type +-- ****************************** +-- ****************************** +-- * Addition check +-- ****************************** +--Testcase 451: +DELETE FROM num_result; +--Testcase 452: +INSERT INTO num_result SELECT t1.id, t2.id, t1.val + t2.val + FROM num_data t1, num_data t2; +--Testcase 453: +SELECT t1.id1, t1.id2, t1.result, t2.expected + FROM num_result t1, num_exp_add t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != t2.expected; + id1 | id2 | result | expected +-----+-----+----------------------+---------------------- + 2 | 3 | -34338487.9053970400 | -34338487.9053970500 + 2 | 5 | -34322095.1769060400 | -34322095.1769060500 + 2 | 9 | -59265296.2604444600 | -59265296.2604444700 + 3 | 2 | -34338487.9053970400 | -34338487.9053970500 + 5 | 2 | -34322095.1769060400 | -34322095.1769060500 + 9 | 2 | -59265296.2604444600 | -59265296.2604444700 +(6 rows) + +--Testcase 454: +DELETE FROM num_result; +--Testcase 455: +INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val + t2.val, 10) + FROM num_data t1, num_data t2; +--Testcase 456: +SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 10) as expected + FROM num_result t1, num_exp_add t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != round(t2.expected, 10); + id1 | id2 | result | expected +-----+-----+----------------------+---------------------- + 2 | 3 | -34338487.9053970400 | -34338487.9053970500 + 2 | 5 | -34322095.1769060400 | -34322095.1769060500 + 2 | 9 | -59265296.2604444600 | -59265296.2604444700 + 3 | 2 | -34338487.9053970400 | -34338487.9053970500 + 5 | 2 | -34322095.1769060400 | -34322095.1769060500 + 9 | 2 | -59265296.2604444600 | -59265296.2604444700 +(6 rows) + +-- ****************************** +-- * Subtraction check +-- ****************************** +--Testcase 457: +DELETE FROM num_result; +--Testcase 458: +INSERT INTO num_result SELECT t1.id, t2.id, t1.val - t2.val + FROM num_data t1, num_data t2; +--Testcase 459: +SELECT t1.id1, t1.id2, t1.result, t2.expected + FROM num_result t1, num_exp_sub t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != t2.expected; + id1 | id2 | result | expected +-----+-----+---------------------+--------------------- + 2 | 9 | -9411688.1703496260 | -9411688.1703496280 + 9 | 2 | 9411688.1703496260 | 9411688.1703496280 +(2 rows) + +--Testcase 460: +DELETE FROM num_result; +--Testcase 461: +INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val - t2.val, 40) + FROM num_data t1, num_data t2; +--Testcase 462: +SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 40) + FROM num_result t1, num_exp_sub t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != round(t2.expected, 40); + id1 | id2 | result | round +-----+-----+---------------------+--------------------------------------------------- + 2 | 9 | -9411688.1703496260 | -9411688.1703496280000000000000000000000000000000 + 9 | 2 | 9411688.1703496260 | 9411688.1703496280000000000000000000000000000000 +(2 rows) + +-- ****************************** +-- * Multiply check +-- ****************************** +--Testcase 463: +DELETE FROM num_result; +--Testcase 464: +INSERT INTO num_result SELECT t1.id, t2.id, t1.val * t2.val + FROM num_data t1, num_data t2; +--Testcase 465: +SELECT t1.id1, t1.id2, t1.result, t2.expected + FROM num_result t1, num_exp_mul t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != t2.expected; + id1 | id2 | result | expected +-----+-----+-----------------------------+----------------------------- + 2 | 4 | -267821744976817.7800000000 | -267821744976817.8000000000 + 2 | 5 | -563049578578.7692000000 | -563049578578.7693000000 + 2 | 6 | -3224438592470.1840000000 | -3224438592470.1846000000 + 2 | 8 | -2571300635581.1460000000 | -2571300635581.1465000000 + 2 | 9 | 855948866655588.4000000000 | 855948866655588.5000000000 + 4 | 2 | -267821744976817.7800000000 | -267821744976817.8000000000 + 5 | 2 | -563049578578.7692000000 | -563049578578.7693000000 + 6 | 2 | -3224438592470.1840000000 | -3224438592470.1846000000 + 8 | 2 | -2571300635581.1460000000 | -2571300635581.1465000000 + 9 | 2 | 855948866655588.4000000000 | 855948866655588.5000000000 +(10 rows) + +--Testcase 466: +DELETE FROM num_result; +--Testcase 467: +INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val * t2.val, 30) + FROM num_data t1, num_data t2; +--Testcase 468: +SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 30) as expected + FROM num_result t1, num_exp_mul t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != round(t2.expected, 30); + id1 | id2 | result | expected +-----+-----+-----------------------------+------------------------------------------------- + 2 | 4 | -267821744976817.7800000000 | -267821744976817.800000000000000000000000000000 + 2 | 5 | -563049578578.7692000000 | -563049578578.769300000000000000000000000000 + 2 | 6 | -3224438592470.1840000000 | -3224438592470.184600000000000000000000000000 + 2 | 8 | -2571300635581.1460000000 | -2571300635581.146500000000000000000000000000 + 2 | 9 | 855948866655588.4000000000 | 855948866655588.500000000000000000000000000000 + 4 | 2 | -267821744976817.7800000000 | -267821744976817.800000000000000000000000000000 + 5 | 2 | -563049578578.7692000000 | -563049578578.769300000000000000000000000000 + 6 | 2 | -3224438592470.1840000000 | -3224438592470.184600000000000000000000000000 + 8 | 2 | -2571300635581.1460000000 | -2571300635581.146500000000000000000000000000 + 9 | 2 | 855948866655588.4000000000 | 855948866655588.500000000000000000000000000000 +(10 rows) + +-- ****************************** +-- * Division check +-- ****************************** +--Testcase 469: +DELETE FROM num_result; +--Testcase 470: +INSERT INTO num_result SELECT t1.id, t2.id, t1.val / t2.val + FROM num_data t1, num_data t2 + WHERE t2.val != '0.0'; +--Testcase 471: +SELECT t1.id1, t1.id2, t1.result, t2.expected + FROM num_result t1, num_exp_div t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != t2.expected; + id1 | id2 | result | expected +-----+-----+--------+---------- +(0 rows) + +--Testcase 472: +DELETE FROM num_result; +--Testcase 473: +INSERT INTO num_result SELECT t1.id, t2.id, round(t1.val / t2.val, 80) + FROM num_data t1, num_data t2 + WHERE t2.val != '0.0'; +--Testcase 474: +SELECT t1.id1, t1.id2, t1.result, round(t2.expected, 80) as expected + FROM num_result t1, num_exp_div t2 + WHERE t1.id1 = t2.id1 AND t1.id2 = t2.id2 + AND t1.result != round(t2.expected, 80); + id1 | id2 | result | expected +-----+-----+--------+---------- +(0 rows) + +-- ****************************** +-- * Square root check +-- ****************************** +--Testcase 475: +DELETE FROM num_result; +--Testcase 476: +INSERT INTO num_result SELECT id, 0, SQRT(ABS(val)) + FROM num_data; +--Testcase 477: +SELECT t1.id1, t1.result, t2.expected + FROM num_result t1, num_exp_sqrt t2 + WHERE t1.id1 = t2.id + AND t1.result != t2.expected; + id1 | result | expected +-----+--------+---------- +(0 rows) + +-- ****************************** +-- * Natural logarithm check +-- ****************************** +--Testcase 478: +DELETE FROM num_result; +--Testcase 479: +INSERT INTO num_result SELECT id, 0, LN(ABS(val)) + FROM num_data + WHERE val != '0.0'; +--Testcase 480: +SELECT t1.id1, t1.result, t2.expected + FROM num_result t1, num_exp_ln t2 + WHERE t1.id1 = t2.id + AND t1.result != t2.expected; + id1 | result | expected +-----+--------+---------- +(0 rows) + +-- ****************************** +-- * Logarithm base 10 check +-- ****************************** +--Testcase 481: +DELETE FROM num_result; +--Testcase 482: +INSERT INTO num_result SELECT id, 0, LOG(numeric '10', ABS(val)) + FROM num_data + WHERE val != '0.0'; +--Testcase 483: +SELECT t1.id1, t1.result, t2.expected + FROM num_result t1, num_exp_log10 t2 + WHERE t1.id1 = t2.id + AND t1.result != t2.expected; + id1 | result | expected +-----+--------+---------- +(0 rows) + +-- ****************************** +-- * POWER(10, LN(value)) check +-- ****************************** +--Testcase 484: +DELETE FROM num_result; +--Testcase 485: +INSERT INTO num_result SELECT id, 0, POWER(numeric '10', LN(ABS(round(val,200)))) + FROM num_data + WHERE val != '0.0'; +--Testcase 486: +SELECT t1.id1, t1.result, t2.expected + FROM num_result t1, num_exp_power_10_ln t2 + WHERE t1.id1 = t2.id + AND t1.result != t2.expected; + id1 | result | expected +-----+-------------------------------+------------------------------- + 2 | 224790267919917920.0000000000 | 224790267919917950.0000000000 +(1 row) + +-- ****************************** +-- * Check behavior with Inf and NaN inputs. It's easiest to handle these +-- * separately from the num_data framework used above, because some input +-- * combinations will throw errors. +-- ****************************** +--Testcase 1451: +CREATE FOREIGN TABLE v (id int4 OPTIONS (key 'true'), x numeric, val float8) SERVER sqlite_svr; +BEGIN; +--Testcase 1452: +DELETE FROM v; +--Testcase 1453: +INSERT INTO v(x) VALUES ('0'::float8),('1'),('-1'),('4.2'),('inf'),('-inf'),('nan'); +--Testcase 1454: +SELECT x1, x2, + x1::numeric + x2::numeric AS sum, + x1::numeric - x2::numeric AS diff, + x1::numeric * x2::numeric AS prod +FROM v AS v1(id, x1), v AS v2(id, x2); + x1 | x2 | sum | diff | prod +-----------+-----------+-----------+-----------+----------- + 0 | 0 | 0 | 0 | 0 + 0 | 1 | 1 | -1 | 0 + 0 | -1 | -1 | 1 | 0 + 0 | 4.2 | 4.2 | -4.2 | 0.0 + 0 | Infinity | Infinity | -Infinity | NaN + 0 | -Infinity | -Infinity | Infinity | NaN + 0 | | | | + 1 | 0 | 1 | 1 | 0 + 1 | 1 | 2 | 0 | 1 + 1 | -1 | 0 | 2 | -1 + 1 | 4.2 | 5.2 | -3.2 | 4.2 + 1 | Infinity | Infinity | -Infinity | Infinity + 1 | -Infinity | -Infinity | Infinity | -Infinity + 1 | | | | + -1 | 0 | -1 | -1 | 0 + -1 | 1 | 0 | -2 | -1 + -1 | -1 | -2 | 0 | 1 + -1 | 4.2 | 3.2 | -5.2 | -4.2 + -1 | Infinity | Infinity | -Infinity | -Infinity + -1 | -Infinity | -Infinity | Infinity | Infinity + -1 | | | | + 4.2 | 0 | 4.2 | 4.2 | 0.0 + 4.2 | 1 | 5.2 | 3.2 | 4.2 + 4.2 | -1 | 3.2 | 5.2 | -4.2 + 4.2 | 4.2 | 8.4 | 0.0 | 17.64 + 4.2 | Infinity | Infinity | -Infinity | Infinity + 4.2 | -Infinity | -Infinity | Infinity | -Infinity + 4.2 | | | | + Infinity | 0 | Infinity | Infinity | NaN + Infinity | 1 | Infinity | Infinity | Infinity + Infinity | -1 | Infinity | Infinity | -Infinity + Infinity | 4.2 | Infinity | Infinity | Infinity + Infinity | Infinity | Infinity | NaN | Infinity + Infinity | -Infinity | NaN | Infinity | -Infinity + Infinity | | | | + -Infinity | 0 | -Infinity | -Infinity | NaN + -Infinity | 1 | -Infinity | -Infinity | -Infinity + -Infinity | -1 | -Infinity | -Infinity | Infinity + -Infinity | 4.2 | -Infinity | -Infinity | -Infinity + -Infinity | Infinity | NaN | -Infinity | -Infinity + -Infinity | -Infinity | -Infinity | NaN | Infinity + -Infinity | | | | + | 0 | | | + | 1 | | | + | -1 | | | + | 4.2 | | | + | Infinity | | | + | -Infinity | | | + | | | | +(49 rows) + +--Testcase 1455: +SELECT x1, x2, + x1::numeric / x2::numeric AS quot, + x1::numeric % x2::numeric AS mod, + div(x1::numeric, x2::numeric) AS div +FROM v AS v1(id, x1), v AS v2(id, x2) WHERE x2 != 0; + x1 | x2 | quot | mod | div +-----------+-----------+-------------------------+------+----------- + 0 | 1 | 0.00000000000000000000 | 0 | 0 + 0 | -1 | 0.00000000000000000000 | 0 | 0 + 0 | 4.2 | 0.00000000000000000000 | 0.0 | 0 + 0 | Infinity | 0 | 0 | 0 + 0 | -Infinity | 0 | 0 | 0 + 1 | 1 | 1.00000000000000000000 | 0 | 1 + 1 | -1 | -1.00000000000000000000 | 0 | -1 + 1 | 4.2 | 0.23809523809523809524 | 1.0 | 0 + 1 | Infinity | 0 | 1 | 0 + 1 | -Infinity | 0 | 1 | 0 + -1 | 1 | -1.00000000000000000000 | 0 | -1 + -1 | -1 | 1.00000000000000000000 | 0 | 1 + -1 | 4.2 | -0.23809523809523809524 | -1.0 | 0 + -1 | Infinity | 0 | -1 | 0 + -1 | -Infinity | 0 | -1 | 0 + 4.2 | 1 | 4.2000000000000000 | 0.2 | 4 + 4.2 | -1 | -4.2000000000000000 | 0.2 | -4 + 4.2 | 4.2 | 1.00000000000000000000 | 0.0 | 1 + 4.2 | Infinity | 0 | 4.2 | 0 + 4.2 | -Infinity | 0 | 4.2 | 0 + Infinity | 1 | Infinity | NaN | Infinity + Infinity | -1 | -Infinity | NaN | -Infinity + Infinity | 4.2 | Infinity | NaN | Infinity + Infinity | Infinity | NaN | NaN | NaN + Infinity | -Infinity | NaN | NaN | NaN + -Infinity | 1 | -Infinity | NaN | -Infinity + -Infinity | -1 | Infinity | NaN | Infinity + -Infinity | 4.2 | -Infinity | NaN | -Infinity + -Infinity | Infinity | NaN | NaN | NaN + -Infinity | -Infinity | NaN | NaN | NaN + | 1 | | | + | -1 | | | + | 4.2 | | | + | Infinity | | | + | -Infinity | | | +(35 rows) + +ROLLBACK; +BEGIN; +--Testcase 1286: +DELETE FROM v; +--Testcase 1287: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1288: +SELECT x::numeric / '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1289: +DELETE FROM v; +--Testcase 1290: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1291: +SELECT x::numeric / '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1292: +DELETE FROM v; +--Testcase 1293: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1294: +SELECT x::numeric / '0' FROM v; + ?column? +---------- + +(1 row) + +ROLLBACK; +BEGIN; +--Testcase 1295: +DELETE FROM v; +--Testcase 1296: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1297: +SELECT x::numeric / '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1298: +DELETE FROM v; +--Testcase 1299: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1300: +SELECT x::numeric % '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1301: +DELETE FROM v; +--Testcase 1302: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1303: +SELECT x::numeric % '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1304: +DELETE FROM v; +--Testcase 1305: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1306: +SELECT x::numeric % '0' FROM v; + ?column? +---------- + +(1 row) + +ROLLBACK; +BEGIN; +--Testcase 1307: +DELETE FROM v; +--Testcase 1308: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1309: +SELECT x::numeric % '0' FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1310: +DELETE FROM v; +--Testcase 1311: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1312: +SELECT div(x::numeric, '0') FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1313: +DELETE FROM v; +--Testcase 1314: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1315: +SELECT div(x::numeric, '0') FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1316: +DELETE FROM v; +--Testcase 1317: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1318: +SELECT div(x::numeric, '0') FROM v; + div +----- + +(1 row) + +ROLLBACK; +BEGIN; +--Testcase 1319: +DELETE FROM v; +--Testcase 1320: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1321: +SELECT div(x::numeric, '0') FROM v; +ERROR: division by zero +ROLLBACK; +BEGIN; +--Testcase 1456: +DELETE FROM v; +--Testcase 1457: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('-1'),('4.2'),('-7.777'),('inf'),('-inf'),('nan'); +--Testcase 1458: +SELECT x, -x as minusx, abs(x::numeric), floor(x::numeric), ceil(x::numeric), sign(x::numeric), numeric_inc(x::numeric) as inc +FROM v; + x | minusx | abs | floor | ceil | sign | inc +-----------+-----------+----------+-----------+-----------+------+----------- + 0 | 0 | 0 | 0 | 0 | 0 | 1 + 1 | -1 | 1 | 1 | 1 | 1 | 2 + -1 | 1 | 1 | -1 | -1 | -1 | 0 + 4.2 | -4.2 | 4.2 | 4 | 5 | 1 | 5.2 + -7.777 | 7.777 | 7.777 | -8 | -7 | -1 | -6.777 + Infinity | -Infinity | Infinity | Infinity | Infinity | 1 | Infinity + -Infinity | Infinity | Infinity | -Infinity | -Infinity | -1 | -Infinity + | | | | | | +(8 rows) + +ROLLBACK; +BEGIN; +--Testcase 1459: +DELETE FROM v; +--Testcase 1460: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('-1'),('4.2'),('-7.777'),('inf'),('-inf'),('nan'); +--Testcase 1461: +SELECT x, round(x::numeric), round(x::numeric,1) as round1, trunc(x::numeric), trunc(x::numeric,1) as trunc1 +FROM v; + x | round | round1 | trunc | trunc1 +-----------+-----------+-----------+-----------+----------- + 0 | 0 | 0.0 | 0 | 0.0 + 1 | 1 | 1.0 | 1 | 1.0 + -1 | -1 | -1.0 | -1 | -1.0 + 4.2 | 4 | 4.2 | 4 | 4.2 + -7.777 | -8 | -7.8 | -7 | -7.7 + Infinity | Infinity | Infinity | Infinity | Infinity + -Infinity | -Infinity | -Infinity | -Infinity | -Infinity + | | | | +(8 rows) + +ROLLBACK; +-- the large values fall into the numeric abbreviation code's maximal classes +BEGIN; +--Testcase 1462: +INSERT INTO v(x) VALUES ('0'::numeric),('1'),('-1'),('4.2'),('-7.777'), + ('inf'),('-inf'),('nan'), + ('inf'),('-inf'),('nan'); +--Testcase 1463: +SELECT substring(x::text, 1, 32) FROM v ORDER BY x; + substring +----------- + -Infinity + -Infinity + -Infinity + -7.777 + -1 + 0 + 1 + 4.2 + Infinity + Infinity + Infinity + + +(13 rows) + +ROLLBACK; +--Testcase 1464: +DELETE FROM v; +--Testcase 1465: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('4.2'),('inf'),('nan'); +--Testcase 1466: +SELECT x, sqrt(x) FROM v; + x | sqrt +----------+------------------- + 0 | 0.000000000000000 + 1 | 1.000000000000000 + 4.2 | 2.049390153191920 + Infinity | Infinity + | +(5 rows) + +--Testcase 1333: +DELETE FROM v; +--Testcase 1334: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1335: +SELECT sqrt(x::numeric) FROM v; +ERROR: cannot take square root of a negative number +--Testcase 1336: +DELETE FROM v; +--Testcase 1337: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1338: +SELECT sqrt(x::numeric) FROM v; +ERROR: cannot take square root of a negative number +--Testcase 1467: +DELETE FROM v; +--Testcase 1468: +INSERT INTO v(x) VALUES ('1'::numeric),('4.2'),('inf'),('nan'); +--Testcase 1469: +SELECT x, + log(x::numeric), + log10(x::numeric), + ln(x::numeric) +FROM v; + x | log | log10 | ln +----------+--------------------+--------------------+-------------------- + 1 | 0.0000000000000000 | 0.0000000000000000 | 0.0000000000000000 + 4.2 | 0.6232492903979005 | 0.6232492903979005 | 1.4350845252893226 + Infinity | Infinity | Infinity | Infinity + | | | +(4 rows) + +--Testcase 1342: +DELETE FROM v; +--Testcase 1343: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1344: +SELECT ln(x::numeric) FROM v; +ERROR: cannot take logarithm of zero +--Testcase 1345: +DELETE FROM v; +--Testcase 1346: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1347: +SELECT ln(x::numeric) FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1348: +DELETE FROM v; +--Testcase 1349: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1350: +SELECT ln(x::numeric) FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1470: +DELETE FROM v; +--Testcase 1471: +INSERT INTO v(x) VALUES ('2'::numeric),('4.2'),('inf'),('nan'); +--Testcase 1472: +SELECT x1, x2, + log(x1::numeric, x2::numeric) +FROM v AS v1(id, x1), v AS v2(id, x2); + x1 | x2 | log +----------+----------+-------------------- + 2 | 2 | 1.0000000000000000 + 2 | 4.2 | 2.0703893278913979 + 2 | Infinity | Infinity + 2 | | + 4.2 | 2 | 0.4830009440873890 + 4.2 | 4.2 | 1.0000000000000000 + 4.2 | Infinity | Infinity + 4.2 | | + Infinity | 2 | 0 + Infinity | 4.2 | 0 + Infinity | Infinity | NaN + Infinity | | + | 2 | + | 4.2 | + | Infinity | + | | +(16 rows) + +--Testcase 1354: +DELETE FROM v; +--Testcase 1355: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1356: +SELECT log(x::numeric, '10') FROM v; +ERROR: cannot take logarithm of zero +--Testcase 1357: +DELETE FROM v; +--Testcase 1358: +INSERT INTO v(x) VALUES ('10'::float8); +--Testcase 1359: +SELECT log(x::numeric, '0') FROM v; +ERROR: cannot take logarithm of zero +--Testcase 1360: +DELETE FROM v; +--Testcase 1361: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1362: +SELECT log(x::numeric, '10') FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1363: +DELETE FROM v; +--Testcase 1364: +INSERT INTO v(x) VALUES ('10'::float8); +--Testcase 1365: +SELECT log(x::numeric, '-inf') FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1366: +DELETE FROM v; +--Testcase 1367: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1368: +SELECT log(x::numeric, '0') FROM v; +ERROR: cannot take logarithm of zero +--Testcase 1369: +DELETE FROM v; +--Testcase 1370: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1371: +SELECT log(x::numeric, '-inf') FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1372: +DELETE FROM v; +--Testcase 1373: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1374: +SELECT log(x::numeric, 'inf') FROM v; +ERROR: cannot take logarithm of a negative number +--Testcase 1473: +DELETE FROM v; +--Testcase 1474: +INSERT INTO v(x) VALUES ('0'::numeric),('1'),('2'),('4.2'),('inf'),('nan'); +--Testcase 1475: +SELECT x1, x2, + power(x1::numeric, x2::numeric) +FROM v AS v1(id, x1), v AS v2(id, x2) WHERE x1 != 0 OR x2 >= 0; + x1 | x2 | power +----------+----------+-------------------- + 0 | 0 | 1.0000000000000000 + 0 | 1 | 0.0000000000000000 + 0 | 2 | 0.0000000000000000 + 0 | 4.2 | 0.0000000000000000 + 0 | Infinity | 0 + 1 | 0 | 1.0000000000000000 + 1 | 1 | 1.0000000000000000 + 1 | 2 | 1.0000000000000000 + 1 | 4.2 | 1.0000000000000000 + 1 | Infinity | 1 + 1 | | + 2 | 0 | 1.0000000000000000 + 2 | 1 | 2.0000000000000000 + 2 | 2 | 4.0000000000000000 + 2 | 4.2 | 18.379173679952560 + 2 | Infinity | Infinity + 2 | | + 4.2 | 0 | 1.0000000000000000 + 4.2 | 1 | 4.2000000000000000 + 4.2 | 2 | 17.640000000000000 + 4.2 | 4.2 | 414.61691860129675 + 4.2 | Infinity | Infinity + 4.2 | | + Infinity | 0 | 1 + Infinity | 1 | Infinity + Infinity | 2 | Infinity + Infinity | 4.2 | Infinity + Infinity | Infinity | Infinity + Infinity | | + | 0 | + | 1 | + | 2 | + | 4.2 | + | Infinity | +(34 rows) + +--Testcase 1378: +DELETE FROM v; +--Testcase 1379: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1380: +SELECT power(x::numeric, '-1') FROM v; +ERROR: zero raised to a negative power is undefined +--Testcase 1381: +DELETE FROM v; +--Testcase 1382: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1383: +SELECT power(x::numeric, '-inf') FROM v; +ERROR: zero raised to a negative power is undefined +--Testcase 1384: +DELETE FROM v; +--Testcase 1385: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1386: +SELECT power(x::numeric, 'inf') FROM v; + power +------- + 1 +(1 row) + +--Testcase 1387: +DELETE FROM v; +--Testcase 1388: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1389: +SELECT power(x::numeric, '3') FROM v; + power +--------------------- + -8.0000000000000000 +(1 row) + +--Testcase 1390: +DELETE FROM v; +--Testcase 1391: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1392: +SELECT power(x::numeric, '3.3') FROM v; +ERROR: a negative number raised to a non-integer power yields a complex result +--Testcase 1393: +DELETE FROM v; +--Testcase 1394: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1395: +SELECT power(x::numeric, '-1') FROM v; + power +--------------------- + -0.5000000000000000 +(1 row) + +--Testcase 1396: +DELETE FROM v; +--Testcase 1397: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1398: +SELECT power(x::numeric, '-1.5') FROM v; +ERROR: a negative number raised to a non-integer power yields a complex result +--Testcase 1399: +DELETE FROM v; +--Testcase 1400: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1401: +SELECT power(x::numeric, 'inf') FROM v; + power +---------- + Infinity +(1 row) + +--Testcase 1402: +DELETE FROM v; +--Testcase 1403: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1404: +SELECT power(x::numeric, '-inf') FROM v; + power +------- + 0 +(1 row) + +--Testcase 1405: +DELETE FROM v; +--Testcase 1406: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1407: +SELECT power(x::numeric, '-2') FROM v; + power +------- + 0 +(1 row) + +--Testcase 1408: +DELETE FROM v; +--Testcase 1409: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1410: +SELECT power(x::numeric, '-inf') FROM v; + power +------- + 0 +(1 row) + +--Testcase 1411: +DELETE FROM v; +--Testcase 1412: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1413: +SELECT power(x::numeric, '2') FROM v; + power +---------- + Infinity +(1 row) + +--Testcase 1414: +DELETE FROM v; +--Testcase 1415: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1416: +SELECT power(x::numeric, '3') FROM v; + power +----------- + -Infinity +(1 row) + +--Testcase 1417: +DELETE FROM v; +--Testcase 1418: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1419: +SELECT power(x::numeric, '4.5') FROM v; +ERROR: a negative number raised to a non-integer power yields a complex result +--Testcase 1420: +DELETE FROM v; +--Testcase 1421: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1422: +SELECT power(x::numeric, '-2') FROM v; + power +------- + 0 +(1 row) + +--Testcase 1423: +DELETE FROM v; +--Testcase 1424: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1425: +SELECT power(x::numeric, '-3') FROM v; + power +------- + 0 +(1 row) + +--Testcase 1426: +DELETE FROM v; +--Testcase 1427: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1428: +SELECT power(x::numeric, '0') FROM v; + power +------- + 1 +(1 row) + +--Testcase 1429: +DELETE FROM v; +--Testcase 1430: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1431: +SELECT power(x::numeric, 'inf') FROM v; + power +---------- + Infinity +(1 row) + +--Testcase 1432: +DELETE FROM v; +--Testcase 1433: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1434: +SELECT power(x::numeric, '-inf') FROM v; + power +------- + 0 +(1 row) + +-- ****************************** +-- * miscellaneous checks for things that have been broken in the past... +-- ****************************** +-- numeric AVG used to fail on some platforms +--Testcase 487: +SELECT AVG(val) FROM num_data; + avg +--------------------- + -13430913.592242321 +(1 row) + +--Testcase 1137: +SELECT MAX(val) FROM num_data; + max +-------------- + 7799461.4119 +(1 row) + +--Testcase 1138: +SELECT MIN(val) FROM num_data; + min +----------- + -83028485 +(1 row) + +--Testcase 488: +SELECT STDDEV(val) FROM num_data; + stddev +------------------------------- + 27791203.28758835313087634596 +(1 row) + +--Testcase 489: +SELECT VARIANCE(val) FROM num_data; + variance +-------------------------------------- + 772350980172061.68729880105331209139 +(1 row) + +-- Check for appropriate rounding and overflow +--Testcase 579: +CREATE FOREIGN TABLE fract_only (id int, val numeric(4,4)) SERVER sqlite_svr; +--Testcase 490: +INSERT INTO fract_only VALUES (1, '0.0'); +--Testcase 491: +INSERT INTO fract_only VALUES (2, '0.1'); +--Testcase 492: +INSERT INTO fract_only VALUES (3, '1.0'); -- should fail +ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. +--Testcase 493: +INSERT INTO fract_only VALUES (4, '-0.9999'); +--Testcase 494: +INSERT INTO fract_only VALUES (5, '0.99994'); +--Testcase 495: +INSERT INTO fract_only VALUES (6, '0.99995'); -- should fail +ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. +--Testcase 496: +INSERT INTO fract_only VALUES (7, '0.00001'); +--Testcase 497: +INSERT INTO fract_only VALUES (8, '0.00017'); +--Testcase 1139: +INSERT INTO fract_only VALUES (9, 'NaN'); +--Testcase 1140: +INSERT INTO fract_only VALUES (10, 'Inf'); -- should fail +ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 cannot hold an infinite value. +--Testcase 1141: +INSERT INTO fract_only VALUES (11, '-Inf'); -- should fail +ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 cannot hold an infinite value. +--Testcase 498: +SELECT * FROM fract_only; + id | val +----+--------- + 1 | 0.0000 + 2 | 0.1000 + 4 | -0.9999 + 5 | 0.9999 + 7 | 0.0000 + 8 | 0.0002 + 9 | +(7 rows) + +--Testcase 580: +DROP FOREIGN TABLE fract_only; +-- Check conversion to integers +-- SQLite promises to preserve the first 15 significant decimal digits of the floating point value. +-- However, it makes no guarantees about the accuracy of computations on floating point values, as no such guarantees are possible. +-- A floating-point value as written in an SQL statement may not be the same as the value represented internally. +-- Actual result is different from expected result. +--Testcase 1485: +CREATE FOREIGN TABLE num_tmp (n1 numeric, n2 numeric, id int options (key 'true')) SERVER sqlite_svr; +--Testcase 1486: +DELETE FROM num_tmp; +--Testcase 1487: +INSERT INTO num_tmp(n1) VALUES (-9223372036854775808.5); +--Testcase 1488: +SELECT n1::int8 FROM num_tmp; -- should fail +ERROR: bigint out of range +--Testcase 1489: +DELETE FROM num_tmp; +--Testcase 1490: +INSERT INTO num_tmp(n1) VALUES (-9223372036854775808.4); +--Testcase 1491: +SELECT n1::int8 FROM num_tmp; -- should fail +ERROR: bigint out of range +--Testcase 1492: +DELETE FROM num_tmp; +--Testcase 1493: +INSERT INTO num_tmp(n1) VALUES (9223372036854775807.4); +--Testcase 1494: +SELECT n1::int8 FROM num_tmp; -- should fail +ERROR: bigint out of range +--Testcase 1495: +DELETE FROM num_tmp; +--Testcase 1496: +INSERT INTO num_tmp(n1) VALUES (9223372036854775807.5); +--Testcase 1497: +SELECT n1::int8 FROM num_tmp; -- should fail +ERROR: bigint out of range +--Testcase 1498: +DELETE FROM num_tmp; +--Testcase 1499: +INSERT INTO num_tmp(n1) VALUES (-2147483648.5); +--Testcase 1500: +SELECT n1::int4 FROM num_tmp; -- should fail +ERROR: integer out of range +--Testcase 1501: +DELETE FROM num_tmp; +--Testcase 1502: +INSERT INTO num_tmp(n1) VALUES (-2147483648.4); +--Testcase 1503: +SELECT n1::int4 FROM num_tmp; -- ok + n1 +------------- + -2147483648 +(1 row) + +--Testcase 1504: +DELETE FROM num_tmp; +--Testcase 1505: +INSERT INTO num_tmp(n1) VALUES (2147483647.4); +--Testcase 1506: +SELECT n1::int4 FROM num_tmp; -- ok + n1 +------------ + 2147483647 +(1 row) + +--Testcase 1507: +DELETE FROM num_tmp; +--Testcase 1508: +INSERT INTO num_tmp(n1) VALUES (2147483647.5); +--Testcase 1509: +SELECT n1::int4 FROM num_tmp; -- should fail +ERROR: integer out of range +--Testcase 1510: +DELETE FROM num_tmp; +--Testcase 1511: +INSERT INTO num_tmp(n1) VALUES (-32768.5); +--Testcase 1512: +SELECT n1::int2 FROM num_tmp; -- should fail +ERROR: smallint out of range +--Testcase 1513: +DELETE FROM num_tmp; +--Testcase 1514: +INSERT INTO num_tmp(n1) VALUES (-32768.4); +--Testcase 1515: +SELECT n1::int2 FROM num_tmp; -- ok + n1 +-------- + -32768 +(1 row) + +--Testcase 1516: +DELETE FROM num_tmp; +--Testcase 1517: +INSERT INTO num_tmp(n1) VALUES (32767.4); +--Testcase 1518: +SELECT n1::int2 FROM num_tmp; -- ok + n1 +------- + 32767 +(1 row) + +--Testcase 1519: +DELETE FROM num_tmp; +--Testcase 1520: +INSERT INTO num_tmp(n1) VALUES (32767.5); +--Testcase 1521: +SELECT n1::int2 FROM num_tmp; -- should fail +ERROR: smallint out of range +--Testcase 1555: +DELETE FROM num_tmp; +--Testcase 1555: +DROP FOREIGN TABLE num_tmp; +-- Check inf/nan conversion behavior +--Testcase 581: +CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, f2 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 582: +DELETE FROM FLOAT8_TMP; +--Testcase 583: +INSERT INTO FLOAT8_TMP VALUES ('NaN'); +--Testcase 584: +SELECT f1::numeric FROM FLOAT8_TMP; + f1 +---- + +(1 row) + +--Testcase 585: +DELETE FROM FLOAT8_TMP; +--Testcase 586: +INSERT INTO FLOAT8_TMP VALUES ('Infinity'); +--Testcase 587: +SELECT f1::numeric FROM FLOAT8_TMP; + f1 +---------- + Infinity +(1 row) + +--Testcase 588: +DELETE FROM FLOAT8_TMP; +--Testcase 589: +INSERT INTO FLOAT8_TMP VALUES ('-Infinity'); +--Testcase 590: +SELECT f1::numeric FROM FLOAT8_TMP; + f1 +----------- + -Infinity +(1 row) + +--Testcase 1142: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, f2 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 1143: +DELETE FROM NUMERIC_TMP; +--Testcase 1144: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1145: +SELECT f1::float8 FROM NUMERIC_TMP; + f1 +---- + +(1 row) + +--Testcase 1146: +DELETE FROM NUMERIC_TMP; +--Testcase 1147: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1148: +SELECT f1::float8 FROM NUMERIC_TMP; + f1 +---------- + Infinity +(1 row) + +--Testcase 1149: +DELETE FROM NUMERIC_TMP; +--Testcase 1150: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1151: +SELECT f1::float8 FROM NUMERIC_TMP; + f1 +----------- + -Infinity +(1 row) + +--Testcase 591: +CREATE FOREIGN TABLE FLOAT4_TMP(f1 float4, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 592: +DELETE FROM FLOAT4_TMP; +--Testcase 593: +INSERT INTO FLOAT4_TMP VALUES ('NaN'); +--Testcase 594: +SELECT f1::numeric FROM FLOAT4_TMP; + f1 +---- + +(1 row) + +--Testcase 595: +DELETE FROM FLOAT4_TMP; +--Testcase 596: +INSERT INTO FLOAT4_TMP VALUES ('Infinity'); +--Testcase 597: +SELECT f1::numeric FROM FLOAT4_TMP; + f1 +---------- + Infinity +(1 row) + +--Testcase 598: +DELETE FROM FLOAT4_TMP; +--Testcase 599: +INSERT INTO FLOAT4_TMP VALUES ('-Infinity'); +--Testcase 600: +SELECT f1::numeric FROM FLOAT4_TMP; + f1 +----------- + -Infinity +(1 row) + +--Testcase 1152: +DELETE FROM NUMERIC_TMP; +--Testcase 1153: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1154: +SELECT f1::float4 FROM NUMERIC_TMP; + f1 +---- + +(1 row) + +--Testcase 1155: +DELETE FROM NUMERIC_TMP; +--Testcase 1156: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1157: +SELECT f1::float4 FROM NUMERIC_TMP; + f1 +---------- + Infinity +(1 row) + +--Testcase 1158: +DELETE FROM NUMERIC_TMP; +--Testcase 1159: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1160: +SELECT f1::float4 FROM NUMERIC_TMP; + f1 +----------- + -Infinity +(1 row) + +--Testcase 1161: +DELETE FROM NUMERIC_TMP; +--Testcase 1162: +INSERT INTO NUMERIC_TMP VALUES ('42'::int2); +--Testcase 1163: +SELECT f1::numeric FROM NUMERIC_TMP; + f1 +---- + 42 +(1 row) + +--Testcase 1164: +DELETE FROM NUMERIC_TMP; +--Testcase 1165: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1166: +SELECT f1::int2 FROM NUMERIC_TMP; + f1 +---- + +(1 row) + +--Testcase 1167: +DELETE FROM NUMERIC_TMP; +--Testcase 1168: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1169: +SELECT f1::int2 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to smallint +--Testcase 1170: +DELETE FROM NUMERIC_TMP; +--Testcase 1171: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1172: +SELECT f1::int2 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to smallint +--Testcase 1173: +DELETE FROM NUMERIC_TMP; +--Testcase 1174: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1175: +SELECT f1::int4 FROM NUMERIC_TMP; + f1 +---- + +(1 row) + +--Testcase 1176: +DELETE FROM NUMERIC_TMP; +--Testcase 1177: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1178: +SELECT f1::int4 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to integer +--Testcase 1179: +DELETE FROM NUMERIC_TMP; +--Testcase 1180: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1181: +SELECT f1::int4 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to integer +--Testcase 1182: +DELETE FROM NUMERIC_TMP; +--Testcase 1183: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1184: +SELECT f1::int8 FROM NUMERIC_TMP; + f1 +---- + +(1 row) + +--Testcase 1185: +DELETE FROM NUMERIC_TMP; +--Testcase 1186: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1187: +SELECT f1::int8 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to bigint +--Testcase 1188: +DELETE FROM NUMERIC_TMP; +--Testcase 1189: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1190: +SELECT f1::int8 FROM NUMERIC_TMP; +ERROR: cannot convert infinity to bigint +-- Simple check that ceil(), floor(), and round() work correctly +--Testcase 601: +CREATE FOREIGN TABLE ceil_floor_round (a numeric OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 499: +INSERT INTO ceil_floor_round VALUES ('-5.5'); +--Testcase 500: +INSERT INTO ceil_floor_round VALUES ('-5.499999'); +--Testcase 501: +INSERT INTO ceil_floor_round VALUES ('9.5'); +--Testcase 502: +INSERT INTO ceil_floor_round VALUES ('9.4999999'); +--Testcase 503: +INSERT INTO ceil_floor_round VALUES ('0.0'); +--Testcase 504: +INSERT INTO ceil_floor_round VALUES ('0.0000001'); +--Testcase 505: +INSERT INTO ceil_floor_round VALUES ('-0.000001'); +--Testcase 506: +SELECT a, ceil(a), ceiling(a), floor(a), round(a) FROM ceil_floor_round ORDER BY a; + a | ceil | ceiling | floor | round +-----------+------+---------+-------+------- + -5.5 | -5 | -5 | -6 | -6 + -5.499999 | -5 | -5 | -6 | -5 + -0.000001 | 0 | 0 | -1 | 0 + 0 | 0 | 0 | 0 | 0 + 0.0000001 | 1 | 1 | 0 | 0 + 9.4999999 | 10 | 10 | 9 | 9 + 9.5 | 10 | 10 | 9 | 10 +(7 rows) + +-- Check rounding, it should round ties away from zero. +--Testcase 602: +CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 603: +DELETE FROM INT4_TMP; +--Testcase 604: +INSERT INTO INT4_TMP SELECT a FROM generate_series(-5,5) a; +--Testcase 605: +SELECT f1 as pow, + round((-2.5 * 10 ^ f1)::numeric, -f1), + round((-1.5 * 10 ^ f1)::numeric, -f1), + round((-0.5 * 10 ^ f1)::numeric, -f1), + round((0.5 * 10 ^ f1)::numeric, -f1), + round((1.5 * 10 ^ f1)::numeric, -f1), + round((2.5 * 10 ^ f1)::numeric, -f1) +FROM INT4_TMP; + pow | round | round | round | round | round | round +-----+----------+----------+----------+---------+---------+--------- + -5 | -0.00003 | -0.00002 | -0.00001 | 0.00001 | 0.00002 | 0.00003 + -4 | -0.0003 | -0.0002 | -0.0001 | 0.0001 | 0.0002 | 0.0003 + -3 | -0.003 | -0.002 | -0.001 | 0.001 | 0.002 | 0.003 + -2 | -0.03 | -0.02 | -0.01 | 0.01 | 0.02 | 0.03 + -1 | -0.3 | -0.2 | -0.1 | 0.1 | 0.2 | 0.3 + 0 | -3 | -2 | -1 | 1 | 2 | 3 + 1 | -30 | -20 | -10 | 10 | 20 | 30 + 2 | -300 | -200 | -100 | 100 | 200 | 300 + 3 | -3000 | -2000 | -1000 | 1000 | 2000 | 3000 + 4 | -30000 | -20000 | -10000 | 10000 | 20000 | 30000 + 5 | -300000 | -200000 | -100000 | 100000 | 200000 | 300000 +(11 rows) + +-- These cases contain out of range value for type double precision, cannot insert into foreign table. +-- -- Check limits of rounding before the decimal point +-- SELECT round(4.4e131071, -131071) = 4e131071; +-- SELECT round(4.5e131071, -131071) = 5e131071; +-- SELECT round(4.5e131071, -131072); -- loses all digits +-- SELECT round(5.5e131071, -131072); -- rounds up and overflows +-- SELECT round(5.5e131071, -131073); -- loses all digits +-- SELECT round(5.5e131071, -1000000); -- loses all digits +-- -- Check limits of rounding after the decimal point +-- SELECT round(5e-16383, 1000000) = 5e-16383; +-- SELECT round(5e-16383, 16383) = 5e-16383; +-- SELECT round(5e-16383, 16382) = 1e-16382; +-- SELECT round(5e-16383, 16381) = 0; +-- -- Check limits of trunc() before the decimal point +-- SELECT trunc(9.9e131071, -131071) = 9e131071; +-- SELECT trunc(9.9e131071, -131072); -- loses all digits +-- SELECT trunc(9.9e131071, -131073); -- loses all digits +-- SELECT trunc(9.9e131071, -1000000); -- loses all digits +-- -- Check limits of trunc() after the decimal point +-- SELECT trunc(5e-16383, 1000000) = 5e-16383; +-- SELECT trunc(5e-16383, 16383) = 5e-16383; +-- SELECT trunc(5e-16383, 16382) = 0; +-- Testing for width_bucket(). For convenience, we test both the +-- numeric and float8 versions of the function in this file. +-- errors +--Testcase 606: +CREATE FOREIGN TABLE width_bucket_tbl ( + id1 numeric, + id2 numeric, + id3 numeric, + id4 int, + id int OPTIONS (key 'true') +) SERVER sqlite_svr; +--Testcase 607: +DELETE FROM width_bucket_tbl; +--Testcase 608: +INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, 0); +--Testcase 609: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; +ERROR: count must be greater than zero +--Testcase 610: +DELETE FROM width_bucket_tbl; +--Testcase 611: +INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, -5); +--Testcase 612: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; +ERROR: count must be greater than zero +--Testcase 613: +DELETE FROM width_bucket_tbl; +--Testcase 614: +INSERT INTO width_bucket_tbl VALUES (3.5, 3.0, 3.0, 888); +--Testcase 615: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; +ERROR: lower bound cannot equal upper bound +--Testcase 616: +DELETE FROM width_bucket_tbl; +--Testcase 617: +INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, 0); +--Testcase 618: +SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; +ERROR: count must be greater than zero +--Testcase 619: +DELETE FROM width_bucket_tbl; +--Testcase 620: +INSERT INTO width_bucket_tbl VALUES (5.0, 3.0, 4.0, -5); +--Testcase 621: +SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; +ERROR: count must be greater than zero +--Testcase 622: +DELETE FROM width_bucket_tbl; +--Testcase 623: +INSERT INTO width_bucket_tbl VALUES (3.5, 3.0, 3.0, 888); +--Testcase 624: +SELECT width_bucket(id1::float8, id2::float8, id3::float8, id4) FROM width_bucket_tbl; +ERROR: lower bound cannot equal upper bound +--Testcase 625: +DELETE FROM width_bucket_tbl; +--Testcase 626: +INSERT INTO width_bucket_tbl VALUES ('NaN'::numeric, 3.0, 4.0, 888); +--Testcase 627: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + +(1 row) + +--Testcase 628: +DELETE FROM width_bucket_tbl; +--Testcase 629: +INSERT INTO width_bucket_tbl VALUES (0, 'NaN'::numeric, 4.0, 888); +--Testcase 630: +SELECT width_bucket(id1::float8, id2, id3::float8, id4) FROM width_bucket_tbl; + width_bucket +-------------- + +(1 row) + +--Testcase 1191: +DELETE FROM width_bucket_tbl; +--Testcase 1192: +INSERT INTO width_bucket_tbl VALUES (2.0, 3.0, '-inf'::numeric, 888); +--Testcase 1193: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; +ERROR: lower and upper bounds must be finite +--Testcase 1194: +DELETE FROM width_bucket_tbl; +--Testcase 1195: +INSERT INTO width_bucket_tbl VALUES (0, '-inf'::numeric, 4.0 , 888); +--Testcase 1196: +SELECT width_bucket(id1::float8, id2, id3::float8, id4) FROM width_bucket_tbl; +ERROR: lower and upper bounds must be finite +-- normal operation +--Testcase 631: +CREATE FOREIGN TABLE width_bucket_test ( + operand_num numeric OPTIONS (key 'true'), + operand_f8 float8 +) SERVER sqlite_svr; +--COPY width_bucket_test (operand_num) FROM stdin; +--Testcase 507: +INSERT INTO width_bucket_test (operand_num) VALUES +(-5.2), +(-0.0000000001), +(0.000000000001), +(1), +(1.99999999999999), +(2), +(2.00000000000001), +(3), +(4), +(4.5), +(5), +(5.5), +(6), +(7), +(8), +(9), +(9.99999999999999), +(10), +(10.0000000000001); +--Testcase 508: +UPDATE width_bucket_test SET operand_f8 = operand_num::float8; +--Testcase 509: +SELECT + operand_num, + width_bucket(operand_num, 0, 10, 5) AS wb_1, + width_bucket(operand_f8, 0, 10, 5) AS wb_1f, + width_bucket(operand_num, 10, 0, 5) AS wb_2, + width_bucket(operand_f8, 10, 0, 5) AS wb_2f, + width_bucket(operand_num, 2, 8, 4) AS wb_3, + width_bucket(operand_f8, 2, 8, 4) AS wb_3f, + width_bucket(operand_num, 5.0, 5.5, 20) AS wb_4, + width_bucket(operand_f8, 5.0, 5.5, 20) AS wb_4f, + width_bucket(operand_num, -25, 25, 10) AS wb_5, + width_bucket(operand_f8, -25, 25, 10) AS wb_5f + FROM width_bucket_test; + operand_num | wb_1 | wb_1f | wb_2 | wb_2f | wb_3 | wb_3f | wb_4 | wb_4f | wb_5 | wb_5f +------------------+------+-------+------+-------+------+-------+------+-------+------+------- + -5.2 | 0 | 0 | 6 | 6 | 0 | 0 | 0 | 0 | 4 | 4 + -0.0000000001 | 0 | 0 | 6 | 6 | 0 | 0 | 0 | 0 | 5 | 5 + 0.000000000001 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 + 1 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 + 1.99999999999999 | 1 | 1 | 5 | 5 | 0 | 0 | 0 | 0 | 6 | 6 + 2 | 2 | 2 | 5 | 5 | 1 | 1 | 0 | 0 | 6 | 6 + 2.00000000000001 | 2 | 2 | 4 | 4 | 1 | 1 | 0 | 0 | 6 | 6 + 3 | 2 | 2 | 4 | 4 | 1 | 1 | 0 | 0 | 6 | 6 + 4 | 3 | 3 | 4 | 4 | 2 | 2 | 0 | 0 | 6 | 6 + 4.5 | 3 | 3 | 3 | 3 | 2 | 2 | 0 | 0 | 6 | 6 + 5 | 3 | 3 | 3 | 3 | 3 | 3 | 1 | 1 | 7 | 7 + 5.5 | 3 | 3 | 3 | 3 | 3 | 3 | 21 | 21 | 7 | 7 + 6 | 4 | 4 | 3 | 3 | 3 | 3 | 21 | 21 | 7 | 7 + 7 | 4 | 4 | 2 | 2 | 4 | 4 | 21 | 21 | 7 | 7 + 8 | 5 | 5 | 2 | 2 | 5 | 5 | 21 | 21 | 7 | 7 + 9 | 5 | 5 | 1 | 1 | 5 | 5 | 21 | 21 | 7 | 7 + 9.99999999999999 | 5 | 5 | 1 | 1 | 5 | 5 | 21 | 21 | 7 | 7 + 10 | 6 | 6 | 1 | 1 | 5 | 5 | 21 | 21 | 8 | 8 + 10.0000000000001 | 6 | 6 | 0 | 0 | 5 | 5 | 21 | 21 | 8 | 8 +(19 rows) + +-- Check positive and negative infinity: we require +-- finite bucket bounds, but allow an infinite operand +--Testcase 1197: +DELETE FROM width_bucket_tbl; +--Testcase 1198: +INSERT INTO width_bucket_tbl VALUES (0.0, 'Infinity'::numeric , 5, 10); +--Testcase 1199: +SELECT width_bucket(id1::numeric, 'Infinity'::numeric, id3, id4) FROM width_bucket_tbl; -- error +ERROR: lower and upper bounds must be finite +--Testcase 1200: +DELETE FROM width_bucket_tbl; +--Testcase 1201: +INSERT INTO width_bucket_tbl VALUES (0.0, 5, '-Infinity'::numeric, 20); +--Testcase 1202: +SELECT width_bucket(id1::numeric, id2, '-Infinity'::numeric, id4) FROM width_bucket_tbl; -- error +ERROR: lower and upper bounds must be finite +--Testcase 1203: +DELETE FROM width_bucket_tbl; +--Testcase 1204: +INSERT INTO width_bucket_tbl VALUES ('Infinity'::numeric, 1, 10, 10), ('-Infinity'::numeric, 1, 10, 10); +--Testcase 1205: +SELECT width_bucket(id1::numeric, id2, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + 11 + 0 +(2 rows) + +--Testcase 510: +DELETE FROM width_bucket_tbl; +-- postgres does not support insert 'Infinity' and '-Infinity' as numeric. +--Testcase 632: +INSERT INTO width_bucket_tbl VALUES (0.0, 0.0, 5, 10); +--Testcase 633: +SELECT width_bucket(id1::float8, 'Infinity'::float8, id3, id4) FROM width_bucket_tbl; -- error +ERROR: lower and upper bounds must be finite +--Testcase 511: +DELETE FROM width_bucket_tbl; +--Testcase 634: +INSERT INTO width_bucket_tbl VALUES (0.0, 5, 0.0, 20); +--Testcase 635: +SELECT width_bucket(id1::float8, id2, 'Infinity'::float8, id4) FROM width_bucket_tbl; -- error +ERROR: lower and upper bounds must be finite +--Testcase 512: +DELETE FROM width_bucket_tbl; +--Testcase 636: +INSERT INTO width_bucket_tbl VALUES (0.0, 1, 10, 10); +--Testcase 637: +SELECT width_bucket('Infinity'::float8, id2, id3, id4), width_bucket('-Infinity'::float8, id2, id3, id4) FROM width_bucket_tbl; + width_bucket | width_bucket +--------------+-------------- + 11 | 0 +(1 row) + +-- Simple test for roundoff error when results should be exact +--Testcase 1445: +DELETE FROM width_bucket_tbl; +--Testcase 1446: +INSERT INTO width_bucket_tbl SELECT x, 10, 100, 9 FROM generate_series(0, 110, 10) x; +--Testcase 1447: +SELECT id1, width_bucket(id1::float8, id2, id3, id4) as flt, + width_bucket(id1::numeric, id2, id3, id4) as num FROM width_bucket_tbl; + id1 | flt | num +-----+-----+----- + 0 | 0 | 0 + 10 | 1 | 1 + 20 | 2 | 2 + 30 | 3 | 3 + 40 | 4 | 4 + 50 | 5 | 5 + 60 | 6 | 6 + 70 | 7 | 7 + 80 | 8 | 8 + 90 | 9 | 9 + 100 | 10 | 10 + 110 | 10 | 10 +(12 rows) + +--Testcase 1448: +DELETE FROM width_bucket_tbl; +--Testcase 1449: +INSERT INTO width_bucket_tbl SELECT x, 100, 10, 9 FROM generate_series(0, 110, 10) x; +--Testcase 1450: +SELECT id1, width_bucket(id1::float8, 100, 10, 9) as flt, + width_bucket(id1::numeric, id2, id3, id4) as num FROM width_bucket_tbl; + id1 | flt | num +-----+-----+----- + 0 | 10 | 10 + 10 | 10 | 10 + 20 | 9 | 9 + 30 | 8 | 8 + 40 | 7 | 7 + 50 | 6 | 6 + 60 | 5 | 5 + 70 | 4 | 4 + 80 | 3 | 3 + 90 | 2 | 2 + 100 | 1 | 1 + 110 | 0 | 0 +(12 rows) + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(0, -1e100::numeric, 1, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + 10 +(1 row) + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(0, -1e100::float8, 1, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + 10 +(1 row) + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(1, 1e100::numeric, 0, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + 10 +(1 row) + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(1, 1e100::float8, 0, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + width_bucket +-------------- + 10 +(1 row) + +-- Check cases that could trigger overflow or underflow within the calculation +SELECT oper, low, high, cnt, width_bucket(oper, low, high, cnt) +FROM + (SELECT 1.797e+308::float8 AS big, 5e-324::float8 AS tiny) as v, + LATERAL (VALUES + (10.5::float8, -big, big, 1), + (10.5::float8, -big, big, 2), + (10.5::float8, -big, big, 3), + (big / 4, -big / 2, big / 2, 10), + (10.5::float8, big, -big, 1), + (10.5::float8, big, -big, 2), + (10.5::float8, big, -big, 3), + (big / 4, big / 2, -big / 2, 10), + (0, 0, tiny, 4), + (tiny, 0, tiny, 4), + (0, 0, 1, 2147483647), + (1, 1, 0, 2147483647) + ) as sample(oper, low, high, cnt); + oper | low | high | cnt | width_bucket +-------------+-------------+-------------+------------+-------------- + 10.5 | -1.797e+308 | 1.797e+308 | 1 | 1 + 10.5 | -1.797e+308 | 1.797e+308 | 2 | 2 + 10.5 | -1.797e+308 | 1.797e+308 | 3 | 2 + 4.4925e+307 | -8.985e+307 | 8.985e+307 | 10 | 8 + 10.5 | 1.797e+308 | -1.797e+308 | 1 | 1 + 10.5 | 1.797e+308 | -1.797e+308 | 2 | 2 + 10.5 | 1.797e+308 | -1.797e+308 | 3 | 2 + 4.4925e+307 | 8.985e+307 | -8.985e+307 | 10 | 3 + 0 | 0 | 5e-324 | 4 | 1 + 5e-324 | 0 | 5e-324 | 4 | 5 + 0 | 0 | 1 | 2147483647 | 1 + 1 | 1 | 0 | 2147483647 | 1 +(12 rows) + +-- These fail because the result would be out of int32 range: +-- Do not convert to check right. +SELECT width_bucket(1::float8, 0, 1, 2147483647); +ERROR: integer out of range +SELECT width_bucket(0::float8, 1, 0, 2147483647); +ERROR: integer out of range +--Testcase 638: +DROP FOREIGN TABLE width_bucket_test; +-- TO_CHAR() +-- +--Testcase 513: +SELECT to_char(val, '9G999G999G999G999G999') + FROM num_data; + to_char +------------------------ + 0 + 0 + -34,338,492 + 4 + 7,799,461 + 16,397 + 93,902 + -83,028,485 + 74,881 + -24,926,804 +(10 rows) + +--Testcase 514: +SELECT to_char(val, '9G999G999G999G999G999D999G999G999G999G999') + FROM num_data; + to_char +-------------------------------------------- + .000,000,000,000,000 + .000,000,000,000,000 + -34,338,492.215,397,045,000,000 + 4.310,000,000,000,000 + 7,799,461.411,900,000,000,000 + 16,397.038,491,000,000,000 + 93,901.577,630,260,000,000 + -83,028,485.000,000,000,000,000 + 74,881.000,000,000,000,000 + -24,926,804.045,047,420,000,000 +(10 rows) + +--Testcase 515: +SELECT to_char(val, '9999999999999999.999999999999999PR') + FROM num_data; + to_char +------------------------------------ + .000000000000000 + .000000000000000 + <34338492.215397045000000> + 4.310000000000000 + 7799461.411900000000000 + 16397.038491000000000 + 93901.577630260000000 + <83028485.000000000000000> + 74881.000000000000000 + <24926804.045047420000000> +(10 rows) + +--Testcase 516: +SELECT to_char(val, '9999999999999999.999999999999999S') + FROM num_data; + to_char +----------------------------------- + .000000000000000+ + .000000000000000+ + 34338492.215397045000000- + 4.310000000000000+ + 7799461.411900000000000+ + 16397.038491000000000+ + 93901.577630260000000+ + 83028485.000000000000000- + 74881.000000000000000+ + 24926804.045047420000000- +(10 rows) + +--Testcase 517: +SELECT to_char(val, 'MI9999999999999999.999999999999999') FROM num_data; + to_char +----------------------------------- + .000000000000000 + .000000000000000 + - 34338492.215397045000000 + 4.310000000000000 + 7799461.411900000000000 + 16397.038491000000000 + 93901.577630260000000 + - 83028485.000000000000000 + 74881.000000000000000 + - 24926804.045047420000000 +(10 rows) + +--Testcase 518: +SELECT to_char(val, 'FMS9999999999999999.999999999999999') FROM num_data; + to_char +--------------------- + +0. + +0. + -34338492.215397045 + +4.31 + +7799461.4119 + +16397.038491 + +93901.57763026 + -83028485. + +74881. + -24926804.04504742 +(10 rows) + +--Testcase 519: +SELECT to_char(val, 'FM9999999999999999.999999999999999THPR') FROM num_data; + to_char +---------------------- + 0. + 0. + <34338492.215397045> + 4.31 + 7799461.4119 + 16397.038491 + 93901.57763026 + <83028485.> + 74881. + <24926804.04504742> +(10 rows) + +--Testcase 520: +SELECT to_char(val, 'SG9999999999999999.999999999999999th') FROM num_data; + to_char +----------------------------------- + + .000000000000000 + + .000000000000000 + - 34338492.215397045000000 + + 4.310000000000000 + + 7799461.411900000000000 + + 16397.038491000000000 + + 93901.577630260000000 + - 83028485.000000000000000 + + 74881.000000000000000 + - 24926804.045047420000000 +(10 rows) + +--Testcase 521: +SELECT to_char(val, '0999999999999999.999999999999999') FROM num_data; + to_char +----------------------------------- + 0000000000000000.000000000000000 + 0000000000000000.000000000000000 + -0000000034338492.215397045000000 + 0000000000000004.310000000000000 + 0000000007799461.411900000000000 + 0000000000016397.038491000000000 + 0000000000093901.577630260000000 + -0000000083028485.000000000000000 + 0000000000074881.000000000000000 + -0000000024926804.045047420000000 +(10 rows) + +--Testcase 522: +SELECT to_char(val, 'S0999999999999999.999999999999999') FROM num_data; + to_char +----------------------------------- + +0000000000000000.000000000000000 + +0000000000000000.000000000000000 + -0000000034338492.215397045000000 + +0000000000000004.310000000000000 + +0000000007799461.411900000000000 + +0000000000016397.038491000000000 + +0000000000093901.577630260000000 + -0000000083028485.000000000000000 + +0000000000074881.000000000000000 + -0000000024926804.045047420000000 +(10 rows) + +--Testcase 523: +SELECT to_char(val, 'FM0999999999999999.999999999999999') FROM num_data; + to_char +----------------------------- + 0000000000000000. + 0000000000000000. + -0000000034338492.215397045 + 0000000000000004.31 + 0000000007799461.4119 + 0000000000016397.038491 + 0000000000093901.57763026 + -0000000083028485. + 0000000000074881. + -0000000024926804.04504742 +(10 rows) + +--Testcase 524: +SELECT to_char(val, 'FM9999999999999999.099999999999999') FROM num_data; + to_char +--------------------- + .0 + .0 + -34338492.215397045 + 4.31 + 7799461.4119 + 16397.038491 + 93901.57763026 + -83028485.0 + 74881.0 + -24926804.04504742 +(10 rows) + +--Testcase 525: +SELECT to_char(val, 'FM9999999999990999.990999999999999') FROM num_data; + to_char +--------------------- + 0000.000 + 0000.000 + -34338492.215397045 + 0004.310 + 7799461.4119 + 16397.038491 + 93901.57763026 + -83028485.000 + 74881.000 + -24926804.04504742 +(10 rows) + +--Testcase 526: +SELECT to_char(val, 'FM0999999999999999.999909999999999') FROM num_data; + to_char +----------------------------- + 0000000000000000.00000 + 0000000000000000.00000 + -0000000034338492.215397045 + 0000000000000004.31000 + 0000000007799461.41190 + 0000000000016397.038491 + 0000000000093901.57763026 + -0000000083028485.00000 + 0000000000074881.00000 + -0000000024926804.04504742 +(10 rows) + +--Testcase 527: +SELECT to_char(val, 'FM9999999990999999.099999999999999') FROM num_data; + to_char +--------------------- + 0000000.0 + 0000000.0 + -34338492.215397045 + 0000004.31 + 7799461.4119 + 0016397.038491 + 0093901.57763026 + -83028485.0 + 0074881.0 + -24926804.04504742 +(10 rows) + +--Testcase 528: +SELECT to_char(val, 'L9999999999999999.099999999999999') FROM num_data; + to_char +------------------------------------ + .000000000000000 + .000000000000000 + -34338492.215397045000000 + 4.310000000000000 + 7799461.411900000000000 + 16397.038491000000000 + 93901.577630260000000 + -83028485.000000000000000 + 74881.000000000000000 + -24926804.045047420000000 +(10 rows) + +--Testcase 529: +SELECT to_char(val, 'FM9999999999999999.99999999999999') FROM num_data; + to_char +--------------------- + 0. + 0. + -34338492.215397045 + 4.31 + 7799461.4119 + 16397.038491 + 93901.57763026 + -83028485. + 74881. + -24926804.04504742 +(10 rows) + +--Testcase 530: +SELECT to_char(val, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; + to_char +----------------------------------------------------------------------- + +. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -3 4 3 3 8 4 9 2 . 2 1 5 3 9 7 0 4 5 0 0 0 0 0 0 0 0 + +4 . 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +7 7 9 9 4 6 1 . 4 1 1 9 0 0 0 0 0 0 0 0 0 0 0 0 0 + +1 6 3 9 7 . 0 3 8 4 9 1 0 0 0 0 0 0 0 0 0 0 0 + +9 3 9 0 1 . 5 7 7 6 3 0 2 6 0 0 0 0 0 0 0 0 0 + -8 3 0 2 8 4 8 5 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +7 4 8 8 1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -2 4 9 2 6 8 0 4 . 0 4 5 0 4 7 4 2 0 0 0 0 0 0 0 0 0 +(10 rows) + +--Testcase 531: +SELECT to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; + to_char +------------------------------------------------------- + +0 . + +0 . + -3 4 3 3 8 4 9 2 . 2 1 5 3 9 7 0 4 5 + +4 . 3 1 + +7 7 9 9 4 6 1 . 4 1 1 9 + +1 6 3 9 7 . 0 3 8 4 9 1 + +9 3 9 0 1 . 5 7 7 6 3 0 2 6 + -8 3 0 2 8 4 8 5 . + +7 4 8 8 1 . + -2 4 9 2 6 8 0 4 . 0 4 5 0 4 7 4 2 +(10 rows) + +--Testcase 532: +SELECT to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data; + to_char +----------------------------------------------------------- + text 9999 "text between quote marks" 0 + text 9999 "text between quote marks" 0 + text -3 9999 433 "text between quote marks" 8492 + text 9999 "text between quote marks" 4 + text 9999 779 "text between quote marks" 9461 + text 9999 1 "text between quote marks" 6397 + text 9999 9 "text between quote marks" 3902 + text -8 9999 302 "text between quote marks" 8485 + text 9999 7 "text between quote marks" 4881 + text -2 9999 492 "text between quote marks" 6804 +(10 rows) + +--Testcase 533: +SELECT to_char(val, '999999SG9999999999') FROM num_data; + to_char +------------------- + + 0 + + 0 + - 34338492 + + 4 + + 7799461 + + 16397 + + 93902 + - 83028485 + + 74881 + - 24926804 +(10 rows) + +--Testcase 534: +SELECT to_char(val, 'FM9999999999999999.999999999999999') FROM num_data; + to_char +--------------------- + 0. + 0. + -34338492.215397045 + 4.31 + 7799461.4119 + 16397.038491 + 93901.57763026 + -83028485. + 74881. + -24926804.04504742 +(10 rows) + +--Testcase 535: +SELECT to_char(val, '9.999EEEE') FROM num_data; + to_char +------------ + 0.000e+00 + 0.000e+00 + -3.434e+07 + 4.310e+00 + 7.799e+06 + 1.640e+04 + 9.390e+04 + -8.303e+07 + 7.488e+04 + -2.493e+07 +(10 rows) + +--Testcase 1476: +DELETE FROM v; +--Testcase 1477: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1478: +SELECT x, + to_char(x, '9.999EEEE') as numeric, + to_char(x::float8, '9.999EEEE') as float8, + to_char(x::float4, '9.999EEEE') as float4 +FROM v; + x | numeric | float8 | float4 +------------+------------+------------+------------ + 0 | 0.000e+00 | 0.000e+00 | 0.000e+00 + -4.2 | -4.200e+00 | -4.200e+00 | -4.200e+00 + 4200000000 | 4.200e+09 | 4.200e+09 | 4.200e+09 + 0.000012 | 1.200e-05 | 1.200e-05 | 1.200e-05 + Infinity | #.####### | #.####### | #.####### + -Infinity | #.####### | #.####### | #.####### + | | | +(7 rows) + +--Testcase 1522: +DELETE FROM v; +--Testcase 1523: +INSERT INTO v(x) VALUES (-16379),(-16378),(-1234),(-789),(-45),(-5),(-4),(-3),(-2),(-1),(0), + (1),(2),(3),(4),(5),(38),(275),(2345),(45678),(131070),(131071); +--Testcase 1524: +SELECT x, + to_char(('1.2345e'||x)::numeric, '9.999EEEE') as numeric +FROM v; + x | numeric +--------+---------------- + -16379 | 1.235e-16379 + -16378 | 1.235e-16378 + -1234 | 1.235e-1234 + -789 | 1.235e-789 + -45 | 1.235e-45 + -5 | 1.235e-05 + -4 | 1.235e-04 + -3 | 1.235e-03 + -2 | 1.235e-02 + -1 | 1.235e-01 + 0 | 1.235e+00 + 1 | 1.235e+01 + 2 | 1.235e+02 + 3 | 1.235e+03 + 4 | 1.235e+04 + 5 | 1.235e+05 + 38 | 1.235e+38 + 275 | 1.235e+275 + 2345 | 1.235e+2345 + 45678 | 1.235e+45678 + 131070 | 1.235e+131070 + 131071 | 1.235e+131071 +(22 rows) + +--Testcase 1479: +DELETE FROM v; +--Testcase 1480: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1481: +SELECT x, + to_char(x, 'MI9999999999.99') as numeric, + to_char(x::float8, 'MI9999999999.99') as float8, + to_char(x::float4, 'MI9999999999.99') as float4 +FROM v; + x | numeric | float8 | float4 +------------+----------------+----------------+---------------- + 0 | .00 | .00 | .00 + -4.2 | - 4.20 | - 4.20 | - 4.20 + 4200000000 | 4200000000.00 | 4200000000.00 | 4200000000 + 0.000012 | .00 | .00 | .00 + Infinity | Infinity | Infinity | Infinity + -Infinity | - Infinity | - Infinity | - Infinity + | | | +(7 rows) + +--Testcase 1482: +DELETE FROM v; +--Testcase 1483: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1484: +SELECT x, + to_char(x, 'MI99.99') as numeric, + to_char(x::float8, 'MI99.99') as float8, + to_char(x::float4, 'MI99.99') as float4 +FROM v; + x | numeric | float8 | float4 +------------+---------+--------+-------- + 0 | .00 | .00 | .00 + -4.2 | - 4.20 | - 4.20 | - 4.20 + 4200000000 | ##.## | ##.## | ##. + 0.000012 | .00 | .00 | .00 + Infinity | ##.## | ##.## | ##. + -Infinity | -##.## | -##.## | -##. + | | | +(7 rows) + +--Testcase 536: +DELETE FROM ceil_floor_round; +--Testcase 537: +INSERT INTO ceil_floor_round VALUES ('100'::numeric); +--Testcase 538: +SELECT to_char(a, 'FM999.9') FROM ceil_floor_round; + to_char +--------- + 100. +(1 row) + +--Testcase 539: +SELECT to_char(a, 'FM999.') FROM ceil_floor_round; + to_char +--------- + 100 +(1 row) + +--Testcase 540: +SELECT to_char(a, 'FM999') FROM ceil_floor_round; + to_char +--------- + 100 +(1 row) + +CREATE FOREIGN TABLE ceil_round_float8(a float8) SERVER sqlite_svr; +INSERT INTO ceil_round_float8 VALUES ('12345678901'::float8); +SELECT to_char(a, 'FM9999999999D9999900000000000000000') FROM ceil_round_float8; + to_char +----------------- + ##########.#### +(1 row) + +-- Check parsing of literal text in a format string +--Testcase 541: +SELECT to_char(a, 'foo999') FROM ceil_floor_round; + to_char +--------- + foo 100 +(1 row) + +--Testcase 542: +SELECT to_char(a, 'f\oo999') FROM ceil_floor_round; + to_char +---------- + f\oo 100 +(1 row) + +--Testcase 543: +SELECT to_char(a, 'f\\oo999') FROM ceil_floor_round; + to_char +----------- + f\\oo 100 +(1 row) + +--Testcase 544: +SELECT to_char(a, 'f\"oo999') FROM ceil_floor_round; + to_char +---------- + f"oo 100 +(1 row) + +--Testcase 545: +SELECT to_char(a, 'f\\"oo999') FROM ceil_floor_round; + to_char +----------- + f\"oo 100 +(1 row) + +--Testcase 546: +SELECT to_char(a, 'f"ool"999') FROM ceil_floor_round; + to_char +---------- + fool 100 +(1 row) + +--Testcase 547: +SELECT to_char(a, 'f"\ool"999') FROM ceil_floor_round; + to_char +---------- + fool 100 +(1 row) + +--Testcase 548: +SELECT to_char(a, 'f"\\ool"999') FROM ceil_floor_round; + to_char +----------- + f\ool 100 +(1 row) + +--Testcase 549: +SELECT to_char(a, 'f"ool\"999') FROM ceil_floor_round; + to_char +---------- + fool"999 +(1 row) + +--Testcase 550: +SELECT to_char(a, 'f"ool\\"999') FROM ceil_floor_round; + to_char +----------- + fool\ 100 +(1 row) + +-- TO_NUMBER() +-- +--Testcase 639: +create foreign table to_number_tbl (a text, id int options (key 'true')) server sqlite_svr; +--Testcase 1211: +SET lc_numeric = 'C'; +--Testcase 640: +DELETE FROM to_number_tbl; +--Testcase 641: +INSERT INTO to_number_tbl VALUES ('-34,338,492'); +--Testcase 642: +SELECT to_number(a, '99G999G999') FROM to_number_tbl; + to_number +----------- + -34338492 +(1 row) + +--Testcase 643: +DELETE FROM to_number_tbl; +--Testcase 644: +INSERT INTO to_number_tbl VALUES ('-34,338,492.654,878'); +--Testcase 645: +SELECT to_number(a, '99G999G999D999G999') FROM to_number_tbl; + to_number +------------------ + -34338492.654878 +(1 row) + +--Testcase 646: +DELETE FROM to_number_tbl; +--Testcase 647: +INSERT INTO to_number_tbl VALUES ('<564646.654564>'); +--Testcase 648: +SELECT to_number(a, '999999.999999PR') FROM to_number_tbl; + to_number +---------------- + -564646.654564 +(1 row) + +--Testcase 649: +DELETE FROM to_number_tbl; +--Testcase 650: +INSERT INTO to_number_tbl VALUES ('0.00001-'); +--Testcase 651: +SELECT to_number(a, '9.999999S') FROM to_number_tbl; + to_number +----------- + -0.00001 +(1 row) + +--Testcase 652: +DELETE FROM to_number_tbl; +--Testcase 653: +INSERT INTO to_number_tbl VALUES ('5.01-'); +--Testcase 654: +SELECT to_number(a, 'FM9.999999S') FROM to_number_tbl; + to_number +----------- + -5.01 +(1 row) + +--Testcase 655: +DELETE FROM to_number_tbl; +--Testcase 656: +INSERT INTO to_number_tbl VALUES ('5.01-'); +--Testcase 657: +SELECT to_number(a, 'FM9.999999MI') FROM to_number_tbl; + to_number +----------- + -5.01 +(1 row) + +--Testcase 658: +DELETE FROM to_number_tbl; +--Testcase 659: +INSERT INTO to_number_tbl VALUES ('5 4 4 4 4 8 . 7 8'); +--Testcase 660: +SELECT to_number(a, '9 9 9 9 9 9 . 9 9') FROM to_number_tbl; + to_number +----------- + 544448.78 +(1 row) + +--Testcase 661: +DELETE FROM to_number_tbl; +--Testcase 662: +INSERT INTO to_number_tbl VALUES ('.01'); +--Testcase 663: +SELECT to_number(a, 'FM9.99') FROM to_number_tbl; + to_number +----------- + 0.01 +(1 row) + +--Testcase 664: +DELETE FROM to_number_tbl; +--Testcase 665: +INSERT INTO to_number_tbl VALUES ('.0'); +--Testcase 666: +SELECT to_number(a, '99999999.99999999') FROM to_number_tbl; + to_number +----------- + 0.0 +(1 row) + +--Testcase 667: +DELETE FROM to_number_tbl; +--Testcase 668: +INSERT INTO to_number_tbl VALUES ('0'); +--Testcase 669: +SELECT to_number(a, '99.99') FROM to_number_tbl; + to_number +----------- + 0 +(1 row) + +--Testcase 670: +DELETE FROM to_number_tbl; +--Testcase 671: +INSERT INTO to_number_tbl VALUES ('.-01'); +--Testcase 672: +SELECT to_number(a, 'S99.99') FROM to_number_tbl; + to_number +----------- + -0.01 +(1 row) + +--Testcase 673: +DELETE FROM to_number_tbl; +--Testcase 674: +INSERT INTO to_number_tbl VALUES ('.01-'); +--Testcase 675: +SELECT to_number(a, '99.99S') FROM to_number_tbl; + to_number +----------- + -0.01 +(1 row) + +--Testcase 676: +DELETE FROM to_number_tbl; +--Testcase 677: +INSERT INTO to_number_tbl VALUES (' . 0 1-'); +--Testcase 678: +SELECT to_number(a, ' 9 9 . 9 9 S') FROM to_number_tbl; + to_number +----------- + -0.01 +(1 row) + +--Testcase 679: +DELETE FROM to_number_tbl; +--Testcase 680: +INSERT INTO to_number_tbl VALUES ('34,50'); +--Testcase 681: +SELECT to_number(a,'999,99') FROM to_number_tbl; + to_number +----------- + 3450 +(1 row) + +--Testcase 682: +DELETE FROM to_number_tbl; +--Testcase 683: +INSERT INTO to_number_tbl VALUES ('123,000'); +--Testcase 684: +SELECT to_number(a,'999G') FROM to_number_tbl; + to_number +----------- + 123 +(1 row) + +--Testcase 685: +DELETE FROM to_number_tbl; +--Testcase 686: +INSERT INTO to_number_tbl VALUES ('123456'); +--Testcase 687: +SELECT to_number(a,'999G999') FROM to_number_tbl; + to_number +----------- + 123456 +(1 row) + +--Testcase 688: +DELETE FROM to_number_tbl; +--Testcase 689: +INSERT INTO to_number_tbl VALUES ('$1234.56'); +--Testcase 690: +SELECT to_number(a,'L9,999.99') FROM to_number_tbl; + to_number +----------- + 1234.56 +(1 row) + +--Testcase 691: +DELETE FROM to_number_tbl; +--Testcase 692: +INSERT INTO to_number_tbl VALUES ('$1234.56'); +--Testcase 693: +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; + to_number +----------- + 1234.56 +(1 row) + +--Testcase 694: +DELETE FROM to_number_tbl; +--Testcase 695: +INSERT INTO to_number_tbl VALUES ('$1,234.56'); +--Testcase 696: +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; + to_number +----------- + 1234.56 +(1 row) + +--Testcase 697: +DELETE FROM to_number_tbl; +--Testcase 698: +INSERT INTO to_number_tbl VALUES ('1234.56'); +--Testcase 699: +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; + to_number +----------- + 1234.56 +(1 row) + +--Testcase 700: +DELETE FROM to_number_tbl; +--Testcase 701: +INSERT INTO to_number_tbl VALUES ('1,234.56'); +--Testcase 702: +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; + to_number +----------- + 1234.56 +(1 row) + +--Testcase 703: +DELETE FROM to_number_tbl; +--Testcase 704: +INSERT INTO to_number_tbl VALUES ('42nd'); +--Testcase 705: +SELECT to_number(a, '99th') FROM to_number_tbl; + to_number +----------- + 42 +(1 row) + +--Testcase 1212: +RESET lc_numeric; +-- +-- Input syntax +-- +--Testcase 706: +CREATE FOREIGN TABLE num_input_test (n1 numeric) SERVER sqlite_svr; +-- good inputs +--Testcase 551: +INSERT INTO num_input_test(n1) VALUES (' 123'); +--Testcase 552: +INSERT INTO num_input_test(n1) VALUES (' 3245874 '); +--Testcase 553: +INSERT INTO num_input_test(n1) VALUES (' -93853'); +--Testcase 554: +INSERT INTO num_input_test(n1) VALUES ('555.50'); +--Testcase 555: +INSERT INTO num_input_test(n1) VALUES ('-555.50'); +--Testcase 556: +INSERT INTO num_input_test(n1) VALUES ('NaN '); +--Testcase 557: +INSERT INTO num_input_test(n1) VALUES (' nan'); +--Testcase 1213: +INSERT INTO num_input_test(n1) VALUES (' inf '); +--Testcase 1214: +INSERT INTO num_input_test(n1) VALUES (' +inf '); +--Testcase 1215: +INSERT INTO num_input_test(n1) VALUES (' -inf '); +--Testcase 1216: +INSERT INTO num_input_test(n1) VALUES (' Infinity '); +--Testcase 1217: +INSERT INTO num_input_test(n1) VALUES (' +inFinity '); +--Testcase 1218: +INSERT INTO num_input_test(n1) VALUES (' -INFINITY '); +INSERT INTO num_input_test(n1) VALUES ('12_000_000_000'); +INSERT INTO num_input_test(n1) VALUES ('12_000.123_456'); +INSERT INTO num_input_test(n1) VALUES ('23_000_000_000e-1_0'); +INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e1_0'); +INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e+1_1'); +INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010'); +INSERT INTO num_input_test(n1) VALUES (' -0B_1010_1011_0101_0100_1010_1001_1000_1100_1110_1011_0001_1111_0000_1010_1101_0010 '); +INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 '); +INSERT INTO num_input_test(n1) VALUES ('-0O0012_5524_5230_6334_3167_0261'); +INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef'); +INSERT INTO num_input_test(n1) VALUES (' 0X_30b1_F33a_6DF0_bD4E_64DF_9BdA_7D15 '); +-- bad inputs +--Testcase 558: +INSERT INTO num_input_test(n1) VALUES (' '); +ERROR: invalid input syntax for type numeric: " " +LINE 1: INSERT INTO num_input_test(n1) VALUES (' '); + ^ +--Testcase 559: +INSERT INTO num_input_test(n1) VALUES (' 1234 %'); +ERROR: invalid input syntax for type numeric: " 1234 %" +LINE 1: INSERT INTO num_input_test(n1) VALUES (' 1234 %'); + ^ +--Testcase 560: +INSERT INTO num_input_test(n1) VALUES ('xyz'); +ERROR: invalid input syntax for type numeric: "xyz" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('xyz'); + ^ +--Testcase 561: +INSERT INTO num_input_test(n1) VALUES ('- 1234'); +ERROR: invalid input syntax for type numeric: "- 1234" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('- 1234'); + ^ +--Testcase 562: +INSERT INTO num_input_test(n1) VALUES ('5 . 0'); +ERROR: invalid input syntax for type numeric: "5 . 0" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('5 . 0'); + ^ +--Testcase 563: +INSERT INTO num_input_test(n1) VALUES ('5. 0 '); +ERROR: invalid input syntax for type numeric: "5. 0 " +LINE 1: INSERT INTO num_input_test(n1) VALUES ('5. 0 '); + ^ +--Testcase 564: +INSERT INTO num_input_test(n1) VALUES (''); +ERROR: invalid input syntax for type numeric: "" +LINE 1: INSERT INTO num_input_test(n1) VALUES (''); + ^ +--Testcase 565: +INSERT INTO num_input_test(n1) VALUES (' N aN '); +ERROR: invalid input syntax for type numeric: " N aN " +LINE 1: INSERT INTO num_input_test(n1) VALUES (' N aN '); + ^ +INSERT INTO num_input_test(n1) VALUES ('+NaN'); +ERROR: invalid input syntax for type numeric: "+NaN" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('+NaN'); + ^ +INSERT INTO num_input_test(n1) VALUES ('-NaN'); +ERROR: invalid input syntax for type numeric: "-NaN" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('-NaN'); + ^ +--Testcase 1219: +INSERT INTO num_input_test(n1) VALUES ('+ infinity'); +ERROR: invalid input syntax for type numeric: "+ infinity" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('+ infinity'); + ^ +INSERT INTO num_input_test(n1) VALUES ('_123'); +ERROR: invalid input syntax for type numeric: "_123" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('_123'); + ^ +INSERT INTO num_input_test(n1) VALUES ('123_'); +ERROR: invalid input syntax for type numeric: "123_" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('123_'); + ^ +INSERT INTO num_input_test(n1) VALUES ('12__34'); +ERROR: invalid input syntax for type numeric: "12__34" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('12__34'); + ^ +INSERT INTO num_input_test(n1) VALUES ('123_.456'); +ERROR: invalid input syntax for type numeric: "123_.456" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('123_.456'); + ^ +INSERT INTO num_input_test(n1) VALUES ('123._456'); +ERROR: invalid input syntax for type numeric: "123._456" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('123._456'); + ^ +INSERT INTO num_input_test(n1) VALUES ('1.2e_34'); +ERROR: invalid input syntax for type numeric: "1.2e_34" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e_34'); + ^ +INSERT INTO num_input_test(n1) VALUES ('1.2e34_'); +ERROR: invalid input syntax for type numeric: "1.2e34_" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e34_'); + ^ +INSERT INTO num_input_test(n1) VALUES ('1.2e3__4'); +ERROR: invalid input syntax for type numeric: "1.2e3__4" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('1.2e3__4'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0b1112'); +ERROR: invalid input syntax for type numeric: "0b1112" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0b1112'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0c1112'); +ERROR: invalid input syntax for type numeric: "0c1112" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0c1112'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0o12345678'); +ERROR: invalid input syntax for type numeric: "0o12345678" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0o12345678'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0x1eg'); +ERROR: invalid input syntax for type numeric: "0x1eg" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x1eg'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0x12.34'); +ERROR: invalid input syntax for type numeric: "0x12.34" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x12.34'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0x__1234'); +ERROR: invalid input syntax for type numeric: "0x__1234" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x__1234'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0x1234_'); +ERROR: invalid input syntax for type numeric: "0x1234_" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x1234_'); + ^ +INSERT INTO num_input_test(n1) VALUES ('0x12__34'); +ERROR: invalid input syntax for type numeric: "0x12__34" +LINE 1: INSERT INTO num_input_test(n1) VALUES ('0x12__34'); + ^ +--Testcase 566: +SELECT * FROM num_input_test; + n1 +----------------------------------- + 123 + 3245874 + -93853 + 555.5 + -555.5 + + + Infinity + Infinity + -Infinity + Infinity + Infinity + -Infinity + 12000000000 + 12000.123456 + 2.3 + 1.23 + 12.3 + 299792458 + -12345678901234567000 + 9999999999 + -12345678900987654000 + -3735928559 + 987654321234568000000000000000000 +(24 rows) + +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4_NUMERIC(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_INT4_NUMERIC VALUES ('34.5', 1), ('34xyz', 2), ('1e400000', 3); +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 1; + pg_input_is_valid +------------------- + t +(1 row) + +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 2; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 3; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 3), 'numeric'); + message | detail | hint | sql_error_code +--------------------------------+--------+------+---------------- + value overflows numeric format | | | 22003 +(1 row) + +INSERT INTO NON_ERROR_THROWING_API_INT4_NUMERIC VALUES ('1234.567', 4), ('0x1234.567', 5); +SELECT pg_input_is_valid(f1, 'numeric(8,4)') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4; + pg_input_is_valid +------------------- + t +(1 row) + +SELECT pg_input_is_valid(f1, 'numeric(7,4)') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4; + pg_input_is_valid +------------------- + f +(1 row) + +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4), 'numeric(7,4)'); + message | detail | hint | sql_error_code +------------------------+-----------------------------------------------------------------------------------+------+---------------- + numeric field overflow | A field with precision 7, scale 4 must round to an absolute value less than 10^3. | | 22003 +(1 row) + +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 5), 'numeric'); + message | detail | hint | sql_error_code +-----------------------------------------------------+--------+------+---------------- + invalid input syntax for type numeric: "0x1234.567" | | | 22P02 +(1 row) + +-- +-- Test precision and scale typemods +-- +--Testcase 1557: +CREATE FOREIGN TABLE num_typemod_test ( + millions numeric(3, -6), + thousands numeric(3, -3), + units numeric(3, 0), + thousandths numeric(3, 3), + millionths numeric(3, 6) +) SERVER sqlite_svr; +--Testcase 1558: +\d num_typemod_test + Foreign table "public.num_typemod_test" + Column | Type | Collation | Nullable | Default | FDW options +-------------+---------------+-----------+----------+---------+------------- + millions | numeric(3,-6) | | | | + thousands | numeric(3,-3) | | | | + units | numeric(3,0) | | | | + thousandths | numeric(3,3) | | | | + millionths | numeric(3,6) | | | | +Server: sqlite_svr + +-- rounding of valid inputs +--Testcase 1559: +INSERT INTO num_typemod_test VALUES (123456, 123, 0.123, 0.000123, 0.000000123); +--Testcase 1560: +INSERT INTO num_typemod_test VALUES (654321, 654, 0.654, 0.000654, 0.000000654); +--Testcase 1561: +INSERT INTO num_typemod_test VALUES (2345678, 2345, 2.345, 0.002345, 0.000002345); +--Testcase 1562: +INSERT INTO num_typemod_test VALUES (7654321, 7654, 7.654, 0.007654, 0.000007654); +--Testcase 1563: +INSERT INTO num_typemod_test VALUES (12345678, 12345, 12.345, 0.012345, 0.000012345); +--Testcase 1564: +INSERT INTO num_typemod_test VALUES (87654321, 87654, 87.654, 0.087654, 0.000087654); +--Testcase 1565: +INSERT INTO num_typemod_test VALUES (123456789, 123456, 123.456, 0.123456, 0.000123456); +--Testcase 1566: +INSERT INTO num_typemod_test VALUES (987654321, 987654, 987.654, 0.987654, 0.000987654); +--Testcase 1567: +INSERT INTO num_typemod_test VALUES ('NaN', 'NaN', 'NaN', 'NaN', 'NaN'); +--Testcase 1568: +SELECT scale(millions), * FROM num_typemod_test ORDER BY millions; + scale | millions | thousands | units | thousandths | millionths +-------+-----------+-----------+-------+-------------+------------ + 0 | 0 | 0 | 0 | 0.000 | 0.000000 + 0 | 1000000 | 1000 | 1 | 0.001 | 0.000001 + 0 | 2000000 | 2000 | 2 | 0.002 | 0.000002 + 0 | 8000000 | 8000 | 8 | 0.008 | 0.000008 + 0 | 12000000 | 12000 | 12 | 0.012 | 0.000012 + 0 | 88000000 | 88000 | 88 | 0.088 | 0.000088 + 0 | 123000000 | 123000 | 123 | 0.123 | 0.000123 + 0 | 988000000 | 988000 | 988 | 0.988 | 0.000988 + | | | | | +(9 rows) + +-- invalid inputs +--Testcase 1569: +INSERT INTO num_typemod_test (millions) VALUES ('inf'); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale -6 cannot hold an infinite value. +--Testcase 1570: +INSERT INTO num_typemod_test (millions) VALUES (999500000); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale -6 must round to an absolute value less than 10^9. +--Testcase 1571: +INSERT INTO num_typemod_test (thousands) VALUES (999500); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale -3 must round to an absolute value less than 10^6. +--Testcase 1572: +INSERT INTO num_typemod_test (units) VALUES (999.5); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale 0 must round to an absolute value less than 10^3. +--Testcase 1573: +INSERT INTO num_typemod_test (thousandths) VALUES (0.9995); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale 3 must round to an absolute value less than 1. +--Testcase 1574: +INSERT INTO num_typemod_test (millionths) VALUES (0.0009995); +ERROR: numeric field overflow +DETAIL: A field with precision 3, scale 6 must round to an absolute value less than 10^-3. +-- +-- Test some corner cases for multiplication +-- +--Testcase 707: +CREATE FOREIGN TABLE num_tmp (n1 numeric, n2 numeric, id int options (key 'true')) SERVER sqlite_svr; +--Testcase 708: +INSERT INTO num_tmp VALUES (4790999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +--Testcase 709: +SELECT n1 * n2 FROM num_tmp; + ?column? +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 47910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 710: +DELETE FROM num_tmp; +--Testcase 711: +INSERT INTO num_tmp VALUES (4789999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +--Testcase 712: +SELECT n1 * n2 FROM num_tmp; + ?column? +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 47900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 713: +DELETE FROM num_tmp; +--Testcase 714: +INSERT INTO num_tmp VALUES (4770999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +--Testcase 715: +SELECT n1 * n2 FROM num_tmp; + ?column? +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 47710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 716: +DELETE FROM num_tmp; +--Testcase 717: +INSERT INTO num_tmp VALUES (4769999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +--Testcase 718: +SELECT n1 * n2 FROM num_tmp; + ?column? +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 47700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 1525: +DELETE FROM num_tmp; +--Testcase 1526: +INSERT INTO num_tmp VALUES ((0.1 - 2e-16383), (0.1 - 3e-16383)); +--Testcase 1527: +SELECT trim_scale(n1 * n2) FROM num_tmp; + trim_scale +------------ + 0.01 +(1 row) + +-- +-- Test some corner cases for division +-- +--Testcase 719: +DELETE FROM num_tmp; +--Testcase 720: +INSERT INTO num_tmp VALUES (999999999999999999999, 1000000000000000000000); +--Testcase 721: +SELECT n1::numeric / n2 FROM num_tmp; + ?column? +------------------------ + 1.00000000000000000000 +(1 row) + +--Testcase 722: +DELETE FROM num_tmp; +--Testcase 723: +INSERT INTO num_tmp VALUES (999999999999999999999, 1000000000000000000000); +--Testcase 724: +SELECT div(n1::numeric, n2) FROM num_tmp; + div +----- + 1 +(1 row) + +--Testcase 725: +SELECT mod(n1::numeric, n2) FROM num_tmp; + mod +----- + 0 +(1 row) + +--Testcase 726: +SELECT div(-n1::numeric, n2) FROM num_tmp; + div +----- + -1 +(1 row) + +--Testcase 727: +SELECT mod(-n1::numeric, n2) FROM num_tmp; + mod +----- + 0 +(1 row) + +--Testcase 728: +select div(-n1::numeric,n2)*n2 + mod(-n1::numeric,n2) FROM num_tmp; + ?column? +------------------------- + -1000000000000000000000 +(1 row) + +--Testcase 729: +DELETE FROM num_tmp; +--Testcase 730: +INSERT INTO num_tmp VALUES (70.0,70); +--Testcase 731: +select mod (n1, n2) FROM num_tmp; + mod +----- + 0 +(1 row) + +--Testcase 732: +select div (n1, n2) FROM num_tmp; + div +----- + 1 +(1 row) + +--Testcase 733: +select n1 / n2 FROM num_tmp; + ?column? +------------------------ + 1.00000000000000000000 +(1 row) + +--Testcase 734: +DELETE FROM num_tmp; +--Testcase 735: +INSERT INTO num_tmp VALUES (12345678901234567890, 123); +--Testcase 736: +select n1 % n2 FROM num_tmp; + ?column? +---------- + 49 +(1 row) + +--Testcase 737: +select n1 / n2 FROM num_tmp; + ?column? +-------------------- + 100371373180768837 +(1 row) + +--Testcase 738: +select div(n1, n2) FROM num_tmp; + div +-------------------- + 100371373180768837 +(1 row) + +--Testcase 739: +select div(n1, n2) * n2 + n1 % n2 FROM num_tmp; + ?column? +---------------------- + 12345678901234567000 +(1 row) + +-- +-- Test some corner cases for square root +-- +--Testcase 740: +DELETE FROM num_tmp; +--Testcase 741: +INSERT INTO num_tmp VALUES (1.000000000000003::numeric); +--Testcase 742: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 1.000000000000001 +(1 row) + +--Testcase 743: +DELETE FROM num_tmp; +--Testcase 744: +INSERT INTO num_tmp VALUES (1.000000000000004::numeric); +--Testcase 745: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 1.000000000000002 +(1 row) + +--Testcase 746: +DELETE FROM num_tmp; +--Testcase 747: +INSERT INTO num_tmp VALUES (96627521408608.56340355805::numeric); +--Testcase 748: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 9829929.878112486 +(1 row) + +--Testcase 749: +DELETE FROM num_tmp; +--Testcase 750: +INSERT INTO num_tmp VALUES (96627521408608.56340355806::numeric); +--Testcase 751: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 9829929.878112486 +(1 row) + +--Testcase 752: +DELETE FROM num_tmp; +--Testcase 753: +INSERT INTO num_tmp VALUES (515549506212297735.073688290367::numeric); +--Testcase 754: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 718017761.7665859 +(1 row) + +--Testcase 755: +DELETE FROM num_tmp; +--Testcase 756: +INSERT INTO num_tmp VALUES (515549506212297735.073688290368::numeric); +--Testcase 757: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 718017761.7665859 +(1 row) + +--Testcase 758: +DELETE FROM num_tmp; +--Testcase 759: +INSERT INTO num_tmp VALUES (8015491789940783531003294973900306::numeric); +--Testcase 760: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 89529278953540020 +(1 row) + +--Testcase 761: +DELETE FROM num_tmp; +--Testcase 762: +INSERT INTO num_tmp VALUES (8015491789940783531003294973900307::numeric); +--Testcase 763: +SELECT sqrt(n1) FROM num_tmp; + sqrt +------------------- + 89529278953540020 +(1 row) + +-- +-- Test code path for raising to integer powers +-- +--Testcase 764: +DELETE FROM num_tmp; +--Testcase 765: +INSERT INTO num_tmp VALUES (10.0, -2147483648); +--Testcase 766: +SELECT n1 ^ n2 as rounds_to_zero FROM num_tmp; + rounds_to_zero +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 767: +DELETE FROM num_tmp; +--Testcase 768: +INSERT INTO num_tmp VALUES (10.0, -2147483647); +--Testcase 769: +SELECT n1 ^ n2 as rounds_to_zero FROM num_tmp; + rounds_to_zero +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +--Testcase 770: +DELETE FROM num_tmp; +--Testcase 771: +INSERT INTO num_tmp VALUES (10.0, 2147483647); +--Testcase 772: +SELECT n1 ^ n2 as overflows FROM num_tmp; +ERROR: value overflows numeric format +--Testcase 773: +DELETE FROM num_tmp; +--Testcase 774: +INSERT INTO num_tmp VALUES (117743296169.0, -1000000000); +--Testcase 775: +SELECT n1 ^ n2 as overflows FROM num_tmp; + overflows +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +-- cases that used to return inaccurate results +--Testcase 776: +DELETE FROM num_tmp; +--Testcase 777: +INSERT INTO num_tmp VALUES (3.789, 21.0000000000000000); +--Testcase 778: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1409343026052.8716 +(1 row) + +--Testcase 779: +DELETE FROM num_tmp; +--Testcase 780: +INSERT INTO num_tmp VALUES (3.789, 35.0000000000000000); +--Testcase 781: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +--------------------------- + 177158169650516670809.382 +(1 row) + +--Testcase 782: +DELETE FROM num_tmp; +--Testcase 783: +INSERT INTO num_tmp VALUES (1.2, 345); +--Testcase 784: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------------------- + 2077446682327378559843444695.6 +(1 row) + +--Testcase 785: +DELETE FROM num_tmp; +--Testcase 786: +INSERT INTO num_tmp VALUES (0.12, (-20)); +--Testcase 787: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +------------------------ + 2608405330458882702.55 +(1 row) + +--Testcase 1220: +DELETE FROM num_tmp; +--Testcase 1221: +INSERT INTO num_tmp VALUES (1.000000000123, (-2147483648)); +--Testcase 1222: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 0.7678656556403084 +(1 row) + +--Testcase 1528: +DELETE FROM num_tmp; +--Testcase 1529: +INSERT INTO num_tmp VALUES (0.9999999999, 23300000000000); +--Testcase 1530: +SELECT coalesce(nullif(n1 ^ n2, 0), 0) FROM num_tmp; + coalesce +---------- + 0 +(1 row) + +--Testcase 1575: +DELETE FROM num_tmp; +--Testcase 1576: +INSERT INTO num_tmp VALUES ((1 - 1.500012345678e-1000), 1.45e1003); +ERROR: "14500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" is out of range for type double precision +--Testcase 1577: +SELECT round(((1 - 1.500012345678e-1000) ^ 1.45e1003) * 1e1000) FROM num_tmp; + round +------- +(0 rows) + +-- cases that used to error out +--Testcase 788: +DELETE FROM num_tmp; +--Testcase 789: +INSERT INTO num_tmp VALUES (0.12, (-25)); +--Testcase 790: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +----------------------------- + 104825960103961013959336.50 +(1 row) + +--Testcase 791: +DELETE FROM num_tmp; +--Testcase 792: +INSERT INTO num_tmp VALUES (0.5678, (-85)); +--Testcase 793: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +---------------------------- + 782333637740774446257.7719 +(1 row) + +--Testcase 1531: +DELETE FROM num_tmp; +--Testcase 1532: +INSERT INTO num_tmp VALUES (0.9999999999, 70000000000000); +--Testcase 1533: +SELECT coalesce(nullif(n1 ^ n2, 0), 0) FROM num_tmp; + coalesce +---------- + 0 +(1 row) + +-- negative base to integer powers +--Testcase 1534: +DELETE FROM num_tmp; +--Testcase 1535: +INSERT INTO num_tmp VALUES ((-1.0), 2147483646); +--Testcase 1536: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 1537: +DELETE FROM num_tmp; +--Testcase 1538: +INSERT INTO num_tmp VALUES ((-1.0), 2147483647); +--Testcase 1539: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +--------------------- + -1.0000000000000000 +(1 row) + +--Testcase 1540: +DELETE FROM num_tmp; +--Testcase 1541: +INSERT INTO num_tmp VALUES ((-1.0), 2147483648); +--Testcase 1542: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 1543: +DELETE FROM num_tmp; +--Testcase 1544: +INSERT INTO num_tmp VALUES ((-1.0), 1000000000000000); +--Testcase 1545: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 1546: +DELETE FROM num_tmp; +--Testcase 1547: +INSERT INTO num_tmp VALUES ((-1.0), 1000000000000001); +--Testcase 1548: +SELECT n1 ^ n2 FROM num_tmp; + ?column? +--------------------- + -1.0000000000000000 +(1 row) + +-- integer powers of 10 +DELETE FROM num_tmp; +INSERT INTO num_tmp(n1) SELECT n FROM generate_series(-20,20) n; +SELECT n1, 10.0 ^ n1 as "10^n", (10.0 ^ n1) * (10.0 ^ (-n1)) = 1 as ok FROM num_tmp; + n1 | 10^n | ok +-----+----------------------------------------+---- + -20 | 0.000000000000000000010000000000000000 | t + -19 | 0.00000000000000000010000000000000000 | t + -18 | 0.0000000000000000010000000000000000 | t + -17 | 0.000000000000000010000000000000000 | t + -16 | 0.00000000000000010000000000000000 | t + -15 | 0.0000000000000010000000000000000 | t + -14 | 0.000000000000010000000000000000 | t + -13 | 0.00000000000010000000000000000 | t + -12 | 0.0000000000010000000000000000 | t + -11 | 0.000000000010000000000000000 | t + -10 | 0.00000000010000000000000000 | t + -9 | 0.0000000010000000000000000 | t + -8 | 0.000000010000000000000000 | t + -7 | 0.00000010000000000000000 | t + -6 | 0.0000010000000000000000 | t + -5 | 0.000010000000000000000 | t + -4 | 0.00010000000000000000 | t + -3 | 0.0010000000000000000 | t + -2 | 0.010000000000000000 | t + -1 | 0.10000000000000000 | t + 0 | 1.0000000000000000 | t + 1 | 10.000000000000000 | t + 2 | 100.00000000000000 | t + 3 | 1000.0000000000000 | t + 4 | 10000.000000000000 | t + 5 | 100000.00000000000 | t + 6 | 1000000.0000000000 | t + 7 | 10000000.000000000 | t + 8 | 100000000.00000000 | t + 9 | 1000000000.0000000 | t + 10 | 10000000000.000000 | t + 11 | 100000000000.00000 | t + 12 | 1000000000000.0000 | t + 13 | 10000000000000.000 | t + 14 | 100000000000000.00 | t + 15 | 1000000000000000.0 | t + 16 | 10000000000000000.0 | t + 17 | 100000000000000000.0 | t + 18 | 1000000000000000000.0 | t + 19 | 10000000000000000000.0 | t + 20 | 100000000000000000000.0 | t +(41 rows) + +-- +-- Tests for raising to non-integer powers +-- +-- special cases +--Testcase 794: +DELETE FROM num_tmp; +--Testcase 795: +INSERT INTO num_tmp VALUES (0.0, 0.0); +--Testcase 796: +select n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 797: +DELETE FROM num_tmp; +--Testcase 798: +INSERT INTO num_tmp VALUES ((-12.34), 0.0); +--Testcase 799: +select n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 800: +DELETE FROM num_tmp; +--Testcase 801: +INSERT INTO num_tmp VALUES (12.34, 0.0); +--Testcase 802: +select n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 803: +DELETE FROM num_tmp; +--Testcase 804: +INSERT INTO num_tmp VALUES (0.0, 12.34); +--Testcase 805: +select n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 0.0000000000000000 +(1 row) + +-- NaNs +--Testcase 806: +DELETE FROM num_tmp; +--Testcase 807: +INSERT INTO num_tmp VALUES ('NaN'::numeric, 'NaN'::numeric); +--Testcase 808: +select n1 ^ n2 FROM num_tmp; + ?column? +---------- + +(1 row) + +--Testcase 809: +DELETE FROM num_tmp; +--Testcase 810: +INSERT INTO num_tmp VALUES ('NaN'::numeric, 0); +--Testcase 811: +select n1 ^ n2 FROM num_tmp; + ?column? +---------- + +(1 row) + +--Testcase 812: +DELETE FROM num_tmp; +--Testcase 813: +INSERT INTO num_tmp VALUES ('NaN'::numeric, 1); +--Testcase 814: +select n1 ^ n2 FROM num_tmp; + ?column? +---------- + +(1 row) + +--Testcase 815: +DELETE FROM num_tmp; +--Testcase 816: +INSERT INTO num_tmp VALUES (0, 'NaN'::numeric); +--Testcase 817: +select n1 ^ n2 FROM num_tmp; + ?column? +---------- + +(1 row) + +--Testcase 818: +DELETE FROM num_tmp; +--Testcase 819: +INSERT INTO num_tmp VALUES (1, 'NaN'::numeric); +--Testcase 820: +select n1 ^ n2 FROM num_tmp; + ?column? +---------- + +(1 row) + +-- invalid inputs +--Testcase 821: +DELETE FROM num_tmp; +--Testcase 822: +INSERT INTO num_tmp VALUES (0.0, (-12.34)); +--Testcase 823: +select n1 ^ n2 FROM num_tmp; +ERROR: zero raised to a negative power is undefined +--Testcase 824: +DELETE FROM num_tmp; +--Testcase 825: +INSERT INTO num_tmp VALUES ((-12.34), 1.2); +--Testcase 826: +select n1 ^ n2 FROM num_tmp; +ERROR: a negative number raised to a non-integer power yields a complex result +-- cases that used to generate inaccurate results +--Testcase 827: +DELETE FROM num_tmp; +--Testcase 828: +INSERT INTO num_tmp VALUES (32.1, 9.8); +--Testcase 829: +select n1 ^ n2 FROM num_tmp; + ?column? +-------------------- + 580429286790711.10 +(1 row) + +--Testcase 830: +DELETE FROM num_tmp; +--Testcase 831: +INSERT INTO num_tmp VALUES (32.1, (-9.8)); +--Testcase 832: +select n1 ^ n2 FROM num_tmp; + ?column? +---------------------------------- + 0.000000000000001722862754788209 +(1 row) + +--Testcase 833: +DELETE FROM num_tmp; +--Testcase 834: +INSERT INTO num_tmp VALUES (12.3, 45.6); +--Testcase 835: +select n1 ^ n2 FROM num_tmp; + ?column? +------------------------------------------------------ + 50081010321492803393171165777624533697036806969694.9 +(1 row) + +--Testcase 836: +DELETE FROM num_tmp; +--Testcase 837: +INSERT INTO num_tmp VALUES (12.3, (-45.6)); +--Testcase 838: +select n1 ^ n2 FROM num_tmp; + ?column? +--------------------------------------------------------------------- + 0.00000000000000000000000000000000000000000000000001996764828785491 +(1 row) + +-- big test +--Testcase 839: +DELETE FROM num_tmp; +--Testcase 840: +INSERT INTO num_tmp VALUES (1.234, 5678); +--Testcase 841: +select n1 ^ n2 FROM num_tmp; + ?column? +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 307239295662090741644584872593956173493568238595074141254349565406661439636598896798876823220904084953233015553994854875890890858118656468658643918169805277399402542281777901029346337707622181574346585989613344285010764501017625366742865066948856161360224801370482171458030533346309750557140549621313515752078638620714732831815297168231790779296290266207315344008883935010274044001522606235576584215999260117523114297033944018699691024106823438431754073086813382242140602291215149759520833200152654884259619588924545324.597 +(1 row) + +-- +-- Tests for EXP() +-- +-- special cases +--Testcase 842: +DELETE FROM num_tmp; +--Testcase 843: +INSERT INTO num_tmp VALUES (0.0); +--Testcase 844: +select exp(n1) from num_tmp; + exp +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 845: +DELETE FROM num_tmp; +--Testcase 846: +INSERT INTO num_tmp VALUES (1.0); +--Testcase 847: +select exp(n1) from num_tmp; + exp +-------------------- + 2.7182818284590452 +(1 row) + +--Testcase 848: +DELETE FROM num_tmp; +--Testcase 849: +INSERT INTO num_tmp VALUES (1.0::numeric(71,70)); +--Testcase 850: +select exp(n1) from num_tmp; + exp +-------------------- + 2.7182818284590452 +(1 row) + +--Testcase 1223: +DELETE FROM num_tmp; +--Testcase 1224: +INSERT INTO num_tmp VALUES ('nan'::numeric); +--Testcase 1225: +select exp(n1) from num_tmp; + exp +----- + +(1 row) + +--Testcase 1226: +DELETE FROM num_tmp; +--Testcase 1227: +INSERT INTO num_tmp VALUES ('inf'::numeric); +--Testcase 1228: +select exp(n1) from num_tmp; + exp +---------- + Infinity +(1 row) + +--Testcase 1229: +DELETE FROM num_tmp; +--Testcase 1230: +INSERT INTO num_tmp VALUES ('-inf'::numeric); +--Testcase 1231: +select exp(n1) from num_tmp; + exp +----- + 0 +(1 row) + +--Testcase 1549: +DELETE FROM num_tmp; +--Testcase 1550: +INSERT INTO num_tmp VALUES ('-5000'::numeric); +--Testcase 1551: +select coalesce(nullif(exp(n1), 0), 0) from num_tmp; + coalesce +---------- + 0 +(1 row) + +--Testcase 1552: +DELETE FROM num_tmp; +--Testcase 1553: +INSERT INTO num_tmp VALUES ('-10000'::numeric); +--Testcase 1554: +select coalesce(nullif(exp(n1), 0), 0) from num_tmp; + coalesce +---------- + 0 +(1 row) + +-- cases that used to generate inaccurate results +--Testcase 851: +DELETE FROM num_tmp; +--Testcase 852: +INSERT INTO num_tmp VALUES (32.999); +--Testcase 853: +select exp(n1) from num_tmp; + exp +--------------------- + 214429043492155.053 +(1 row) + +--Testcase 854: +DELETE FROM num_tmp; +--Testcase 855: +INSERT INTO num_tmp VALUES (-32.999); +--Testcase 856: +select exp(n1) from num_tmp; + exp +---------------------------------- + 0.000000000000004663547361468248 +(1 row) + +--Testcase 857: +DELETE FROM num_tmp; +--Testcase 858: +INSERT INTO num_tmp VALUES (123.456); +--Testcase 859: +select exp(n1) from num_tmp; + exp +------------------------------------------------------------ + 413294435277809344957685441227343146614594393746575438.725 +(1 row) + +--Testcase 860: +DELETE FROM num_tmp; +--Testcase 861: +INSERT INTO num_tmp VALUES (-123.456); +--Testcase 862: +select exp(n1) from num_tmp; + exp +------------------------------------------------------------------------- + 0.000000000000000000000000000000000000000000000000000002419582541264601 +(1 row) + +-- big test +--Testcase 863: +DELETE FROM num_tmp; +--Testcase 864: +INSERT INTO num_tmp VALUES (1234.5678); +--Testcase 865: +select exp(n1) from num_tmp; + exp +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 146549072930959479983482138503979804217622199675223653966270157446954995433819741094410764947112047906012815540251009949604426069672532417736057033099274204598385314594846509975629046864798765888104789074984927709616261452461385220475510438783429612447831614003668421849727379202555580791042606170523016207262965336641214601082882495255771621327088265411334088968112458492660609809762865582162764292604697957813514621259353683899630997077707406305730694385703091201347848855199354307506425820147289848677003277208302716466011827836279231.9667 +(1 row) + +-- +-- Tests for generate_series +-- +--Testcase 866: +DELETE FROM num_tmp; +--Testcase 867: +INSERT INTO num_tmp select * from generate_series(0.0::numeric, 4.0::numeric); +--Testcase 868: +SELECT n1 FROM num_tmp; + n1 +---- + 0 + 1 + 2 + 3 + 4 +(5 rows) + +--Testcase 869: +DELETE FROM num_tmp; +--Testcase 870: +INSERT INTO num_tmp select * from generate_series(0.1::numeric, 4.0::numeric, 1.3::numeric); +--Testcase 871: +SELECT n1 FROM num_tmp; + n1 +----- + 0.1 + 1.4 + 2.7 + 4 +(4 rows) + +--Testcase 872: +DELETE FROM num_tmp; +--Testcase 873: +INSERT INTO num_tmp select * from generate_series(4.0::numeric, -1.5::numeric, -2.2::numeric); +--Testcase 874: +SELECT n1 FROM num_tmp; + n1 +------ + 4 + 1.8 + -0.4 +(3 rows) + +-- Trigger errors +--Testcase 875: +DELETE FROM num_tmp; +--Testcase 876: +INSERT INTO num_tmp select * from generate_series(-100::numeric, 100::numeric, 0::numeric); +ERROR: step size cannot equal zero +--Testcase 877: +SELECT n1 FROM num_tmp; + n1 +---- +(0 rows) + +--Testcase 878: +DELETE FROM num_tmp; +--Testcase 879: +INSERT INTO num_tmp select * from generate_series(-100::numeric, 100::numeric, 'nan'::numeric); +ERROR: step size cannot be NaN +--Testcase 880: +SELECT n1 FROM num_tmp; + n1 +---- +(0 rows) + +--Testcase 881: +DELETE FROM num_tmp; +--Testcase 882: +INSERT INTO num_tmp select * from generate_series('nan'::numeric, 100::numeric, 10::numeric); +ERROR: start value cannot be NaN +--Testcase 883: +SELECT n1 FROM num_tmp; + n1 +---- +(0 rows) + +--Testcase 884: +DELETE FROM num_tmp; +--Testcase 885: +INSERT INTO num_tmp select * from generate_series(0::numeric, 'nan'::numeric, 10::numeric); +ERROR: stop value cannot be NaN +--Testcase 886: +SELECT n2 FROM num_tmp; + n2 +---- +(0 rows) + +--Testcase 1232: +DELETE FROM num_tmp; +--Testcase 1233: +INSERT INTO num_tmp select * from generate_series('inf'::numeric, 'inf'::numeric, 10::numeric); +ERROR: start value cannot be infinity +--Testcase 1234: +SELECT n2 FROM num_tmp; + n2 +---- +(0 rows) + +--Testcase 1235: +DELETE FROM num_tmp; +--Testcase 1236: +INSERT INTO num_tmp select * from generate_series(0::numeric, 'inf'::numeric, 10::numeric); +ERROR: stop value cannot be infinity +--Testcase 1237: +SELECT n2 FROM num_tmp; + n2 +---- +(0 rows) + +--Testcase 1238: +DELETE FROM num_tmp; +--Testcase 1239: +INSERT INTO num_tmp select * from generate_series(0::numeric, '42'::numeric, '-inf'::numeric); +ERROR: step size cannot be infinity +--Testcase 1240: +SELECT n2 FROM num_tmp; + n2 +---- +(0 rows) + +-- Checks maximum, output is truncated +--Testcase 887: +DELETE FROM num_tmp; +--Testcase 888: +INSERT INTO num_tmp select (i / (10::numeric ^ 131071))::numeric(1,0) + from generate_series(6 * (10::numeric ^ 131071), + 9 * (10::numeric ^ 131071), + 10::numeric ^ 131071) i; +--Testcase 889: +SELECT n1 FROM num_tmp; + n1 +---- + 6 + 7 + 8 + 9 +(4 rows) + + +-- Check usage with variables +--Testcase 890: +DELETE FROM num_tmp; +--Testcase 891: +INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j; +--Testcase 892: +SELECT n1, n2 FROM num_tmp; + n1 | n2 +----+---- + 1 | 1 + 1 | 2 + 1 | 3 + 2 | 2 + 2 | 3 + 3 | 3 +(6 rows) + +--Testcase 893: +DELETE FROM num_tmp; +--Testcase 894: +INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j; +--Testcase 895: +SELECT n1, n2 FROM num_tmp; + n1 | n2 +----+---- + 1 | 1 + 2 | 1 + 2 | 2 + 3 | 1 + 3 | 2 + 3 | 3 +(6 rows) + +--Testcase 896: +DELETE FROM num_tmp; +--Testcase 897: +INSERT INTO num_tmp select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j; +--Testcase 898: +SELECT n1, n2 FROM num_tmp; + n1 | n2 +----+---- + 1 | 1 + 1 | 2 + 1 | 3 + 1 | 4 + 1 | 5 + 2 | 1 + 2 | 3 + 2 | 5 + 3 | 1 + 3 | 4 +(10 rows) + +-- +-- Tests for LN() +-- +-- Invalid inputs +--Testcase 899: +DELETE FROM num_tmp; +--Testcase 900: +INSERT INTO num_tmp VALUES (-12.34); +--Testcase 901: +select ln(n1) from num_tmp; +ERROR: cannot take logarithm of a negative number +--Testcase 902: +DELETE FROM num_tmp; +--Testcase 903: +INSERT INTO num_tmp VALUES (0.0); +--Testcase 904: +select ln(n1) from num_tmp; +ERROR: cannot take logarithm of zero +-- Some random tests +--Testcase 905: +DELETE FROM num_tmp; +--Testcase 906: +INSERT INTO num_tmp VALUES (1.2345678e-28); +--Testcase 907: +select ln(n1) from num_tmp; + ln +----------------------------------------- + -64.26166165451762991204894255882820859 +(1 row) + +--Testcase 908: +DELETE FROM num_tmp; +--Testcase 909: +INSERT INTO num_tmp VALUES (0.0456789); +--Testcase 910: +select ln(n1) from num_tmp; + ln +--------------------- + -3.0861187944847439 +(1 row) + +--Testcase 911: +DELETE FROM num_tmp; +--Testcase 912: +INSERT INTO num_tmp VALUES (0.349873948359354029493948309745709580730482050975); +--Testcase 913: +select ln(n1) from num_tmp; + ln +---------------------- + -1.05018233691208275 +(1 row) + +--Testcase 914: +DELETE FROM num_tmp; +--Testcase 915: +INSERT INTO num_tmp VALUES (0.99949452); +--Testcase 916: +select ln(n1) from num_tmp; + ln +------------------------- + -0.00050560779808326467 +(1 row) + +--Testcase 917: +DELETE FROM num_tmp; +--Testcase 918: +INSERT INTO num_tmp VALUES (1.00049687395); +--Testcase 919: +select ln(n1) from num_tmp; + ln +------------------------ + 0.00049675054901370394 +(1 row) + +--Testcase 920: +DELETE FROM num_tmp; +--Testcase 921: +INSERT INTO num_tmp VALUES (1234.567890123456789); +--Testcase 922: +select ln(n1) from num_tmp; + ln +-------------------- + 7.1184763012977898 +(1 row) + +--Testcase 923: +DELETE FROM num_tmp; +--Testcase 924: +INSERT INTO num_tmp VALUES (5.80397490724e5); +--Testcase 925: +select ln(n1) from num_tmp; + ln +-------------------- + 13.271468476626518 +(1 row) + +--Testcase 926: +DELETE FROM num_tmp; +--Testcase 927: +INSERT INTO num_tmp VALUES (9.342536355e34); +--Testcase 928: +select ln(n1) from num_tmp; + ln +-------------------- + 80.522470935524187 +(1 row) + +-- +-- Tests for LOG() (base 10) +-- +-- invalid inputs +--Testcase 929: +DELETE FROM num_tmp; +--Testcase 930: +INSERT INTO num_tmp VALUES (-12.34); +--Testcase 931: +select log(n1) from num_tmp; +ERROR: cannot take logarithm of a negative number +--Testcase 932: +DELETE FROM num_tmp; +--Testcase 933: +INSERT INTO num_tmp VALUES (0.0); +--Testcase 934: +select log(n1) from num_tmp; +ERROR: cannot take logarithm of zero +-- some random tests +--Testcase 935: +DELETE FROM num_tmp; +--Testcase 936: +INSERT INTO num_tmp VALUES (1.234567e-89); +--Testcase 937: +select log(n1) from num_tmp; + log +----------------------------------------------------------------------------------------------------- + -88.90848533591373725637496492944925187293052336306443143312825869985819779294142441287021741054275 +(1 row) + +--Testcase 938: +DELETE FROM num_tmp; +--Testcase 939: +INSERT INTO num_tmp VALUES (3.4634998359873254962349856073435545); +--Testcase 940: +select log(n1) from num_tmp; + log +-------------------- + 0.5395151714070135 +(1 row) + +--Testcase 941: +DELETE FROM num_tmp; +--Testcase 942: +INSERT INTO num_tmp VALUES (9.999999999999999999); +--Testcase 943: +select log(n1) from num_tmp; + log +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 944: +DELETE FROM num_tmp; +--Testcase 945: +INSERT INTO num_tmp VALUES (10.00000000000000000); +--Testcase 946: +select log(n1) from num_tmp; + log +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 947: +DELETE FROM num_tmp; +--Testcase 948: +INSERT INTO num_tmp VALUES (10.00000000000000001); +--Testcase 949: +select log(n1) from num_tmp; + log +-------------------- + 1.0000000000000000 +(1 row) + +--Testcase 950: +DELETE FROM num_tmp; +--Testcase 951: +INSERT INTO num_tmp VALUES (590489.45235237); +--Testcase 952: +select log(n1) from num_tmp; + log +------------------- + 5.771212144411727 +(1 row) + +-- +-- Tests for LOG() (arbitrary base) +-- +-- invalid inputs +--Testcase 953: +DELETE FROM num_tmp; +--Testcase 954: +INSERT INTO num_tmp VALUES (-12.34, 56.78); +--Testcase 955: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of a negative number +--Testcase 956: +DELETE FROM num_tmp; +--Testcase 957: +INSERT INTO num_tmp VALUES (-12.34, -56.78); +--Testcase 958: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of a negative number +--Testcase 959: +DELETE FROM num_tmp; +--Testcase 960: +INSERT INTO num_tmp VALUES (12.34, -56.78); +--Testcase 961: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of a negative number +--Testcase 962: +DELETE FROM num_tmp; +--Testcase 963: +INSERT INTO num_tmp VALUES (0.0, 12.34); +--Testcase 964: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of zero +--Testcase 965: +DELETE FROM num_tmp; +--Testcase 966: +INSERT INTO num_tmp VALUES (12.34, 0.0); +--Testcase 967: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of zero +--Testcase 968: +DELETE FROM num_tmp; +--Testcase 969: +INSERT INTO num_tmp VALUES (.0, 12.34); +--Testcase 970: +select log(n1, n2) from num_tmp; +ERROR: cannot take logarithm of zero +-- some random tests +--Testcase 971: +DELETE FROM num_tmp; +--Testcase 972: +INSERT INTO num_tmp VALUES (1.23e-89, 6.4689e45); +--Testcase 973: +select log(n1, n2) from num_tmp; + log +------------------------------------------------------------------------------------------------ + -0.5152489207781856983977054971756484879653568168479201885425588841094788842469115325262329756 +(1 row) + +--Testcase 974: +DELETE FROM num_tmp; +--Testcase 975: +INSERT INTO num_tmp VALUES (0.99923, 4.58934e34); +--Testcase 976: +select log(n1, n2) from num_tmp; + log +--------------------- + -103611.55579544132 +(1 row) + +--Testcase 977: +DELETE FROM num_tmp; +--Testcase 978: +INSERT INTO num_tmp VALUES (1.000016, 8.452010e18); +--Testcase 979: +select log(n1, n2) from num_tmp; + log +-------------------- + 2723830.2877097365 +(1 row) + +--Testcase 980: +DELETE FROM num_tmp; +--Testcase 981: +INSERT INTO num_tmp VALUES (3.1954752e47, 9.4792021e-73); +--Testcase 982: +select log(n1, n2) from num_tmp; + log +------------------------------------------------------------------------------------- + -1.51613372350688302142917386143459361608600157692779164475351842333265418126982165 +(1 row) + +-- +-- Tests for scale() +-- +--Testcase 983: +DELETE FROM num_tmp; +--Testcase 984: +INSERT INTO num_tmp VALUES (numeric 'NaN'); +--Testcase 985: +select scale(n1) from num_tmp; + scale +------- + +(1 row) + +--Testcase 1241: +DELETE FROM num_tmp; +--Testcase 1242: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1243: +select scale(n1) from num_tmp; + scale +------- + +(1 row) + +--Testcase 986: +DELETE FROM num_tmp; +--Testcase 987: +INSERT INTO num_tmp VALUES (NULL::numeric); +--Testcase 988: +select scale(n1) from num_tmp; + scale +------- + +(1 row) + +--Testcase 989: +DELETE FROM num_tmp; +--Testcase 990: +INSERT INTO num_tmp VALUES (1.12); +--Testcase 991: +select scale(n1) from num_tmp; + scale +------- + 2 +(1 row) + +--Testcase 992: +DELETE FROM num_tmp; +--Testcase 993: +INSERT INTO num_tmp VALUES (0); +--Testcase 994: +select scale(n1) from num_tmp; + scale +------- + 0 +(1 row) + +--Testcase 995: +DELETE FROM num_tmp; +--Testcase 996: +INSERT INTO num_tmp VALUES (0.00); +--Testcase 997: +select scale(n1) from num_tmp; + scale +------- + 0 +(1 row) + +--Testcase 998: +DELETE FROM num_tmp; +--Testcase 999: +INSERT INTO num_tmp VALUES (1.12345); +--Testcase 1000: +select scale(n1) from num_tmp; + scale +------- + 5 +(1 row) + +--Testcase 1001: +DELETE FROM num_tmp; +--Testcase 1002: +INSERT INTO num_tmp VALUES (110123.12475871856128); +--Testcase 1003: +select scale(n1) from num_tmp; + scale +------- + 11 +(1 row) + +--Testcase 1004: +DELETE FROM num_tmp; +--Testcase 1005: +INSERT INTO num_tmp VALUES (-1123.12471856128); +--Testcase 1006: +select scale(n1) from num_tmp; + scale +------- + 11 +(1 row) + +--Testcase 1007: +DELETE FROM num_tmp; +--Testcase 1008: +INSERT INTO num_tmp VALUES (-13.000000000000000); +--Testcase 1009: +select scale(n1) from num_tmp; + scale +------- + 0 +(1 row) + +-- +-- Tests for min_scale() +-- +--Testcase 1010: +DELETE FROM num_tmp; +--Testcase 1011: +INSERT INTO num_tmp VALUES (numeric 'NaN'); +--Testcase 1012: +select min_scale(n1) is NULL from num_tmp; -- should be true + ?column? +---------- + t +(1 row) + +--Testcase 1244: +DELETE FROM num_tmp; +--Testcase 1245: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1246: +select min_scale(n1) is NULL from num_tmp; -- should be true + ?column? +---------- + t +(1 row) + +--Testcase 1013: +DELETE FROM num_tmp; +--Testcase 1014: +INSERT INTO num_tmp VALUES (0); +--Testcase 1015: +select min_scale(n1) from num_tmp; -- no digits + min_scale +----------- + 0 +(1 row) + +--Testcase 1016: +DELETE FROM num_tmp; +--Testcase 1017: +INSERT INTO num_tmp VALUES (0.00); +--Testcase 1018: +select min_scale(n1) from num_tmp; -- no digits again + min_scale +----------- + 0 +(1 row) + +--Testcase 1019: +DELETE FROM num_tmp; +--Testcase 1020: +INSERT INTO num_tmp VALUES (1.0); +--Testcase 1021: +select min_scale(n1) from num_tmp; -- no scale + min_scale +----------- + 0 +(1 row) + +--Testcase 1022: +DELETE FROM num_tmp; +--Testcase 1023: +INSERT INTO num_tmp VALUES (1.1); +--Testcase 1024: +select min_scale(n1) from num_tmp; -- scale 1 + min_scale +----------- + 1 +(1 row) + +--Testcase 1025: +DELETE FROM num_tmp; +--Testcase 1026: +INSERT INTO num_tmp VALUES (1.12); +--Testcase 1027: +select min_scale(n1) from num_tmp; -- scale 2 + min_scale +----------- + 2 +(1 row) + +--Testcase 1028: +DELETE FROM num_tmp; +--Testcase 1029: +INSERT INTO num_tmp VALUES (1.123); +--Testcase 1030: +select min_scale(n1) from num_tmp; -- scale 3 + min_scale +----------- + 3 +(1 row) + +--Testcase 1031: +DELETE FROM num_tmp; +--Testcase 1032: +INSERT INTO num_tmp VALUES (1.1234); +--Testcase 1033: +select min_scale(n1) from num_tmp; -- scale 4, filled digit + min_scale +----------- + 4 +(1 row) + +--Testcase 1034: +DELETE FROM num_tmp; +--Testcase 1035: +INSERT INTO num_tmp VALUES (1.12345); +--Testcase 1036: +select min_scale(n1) from num_tmp; -- scale 5, 2 NDIGITS + min_scale +----------- + 5 +(1 row) + +--Testcase 1037: +DELETE FROM num_tmp; +--Testcase 1038: +INSERT INTO num_tmp VALUES (1.1000); +--Testcase 1039: +select min_scale(n1) from num_tmp; -- 1 pos in NDIGITS + min_scale +----------- + 1 +(1 row) + +--Testcase 1040: +DELETE FROM num_tmp; +--Testcase 1041: +INSERT INTO num_tmp VALUES (1e100); +--Testcase 1042: +select min_scale(n1) from num_tmp; -- very big number + min_scale +----------- + 0 +(1 row) + +-- +-- Tests for trim_scale() +-- +--Testcase 1043: +DELETE FROM num_tmp; +--Testcase 1044: +INSERT INTO num_tmp VALUES (numeric 'NaN'); +--Testcase 1045: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + +(1 row) + +--Testcase 1247: +DELETE FROM num_tmp; +--Testcase 1248: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1249: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + Infinity +(1 row) + +--Testcase 1046: +DELETE FROM num_tmp; +--Testcase 1047: +INSERT INTO num_tmp VALUES (1.120); +--Testcase 1048: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + 1.12 +(1 row) + +--Testcase 1049: +DELETE FROM num_tmp; +--Testcase 1050: +INSERT INTO num_tmp VALUES (0); +--Testcase 1051: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + 0 +(1 row) + +--Testcase 1052: +DELETE FROM num_tmp; +--Testcase 1053: +INSERT INTO num_tmp VALUES (0.00); +--Testcase 1054: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + 0 +(1 row) + +--Testcase 1055: +DELETE FROM num_tmp; +--Testcase 1056: +INSERT INTO num_tmp VALUES (1.1234500); +--Testcase 1057: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + 1.12345 +(1 row) + +--Testcase 1058: +DELETE FROM num_tmp; +--Testcase 1059: +INSERT INTO num_tmp VALUES (110123.12475871856128000); +--Testcase 1060: +select trim_scale(n1) from num_tmp; + trim_scale +-------------------- + 110123.12475871856 +(1 row) + +--Testcase 1061: +DELETE FROM num_tmp; +--Testcase 1062: +INSERT INTO num_tmp VALUES (-123.124718561280000000); +--Testcase 1063: +select trim_scale(n1) from num_tmp; + trim_scale +------------------ + -123.12471856128 +(1 row) + +--Testcase 1064: +DELETE FROM num_tmp; +--Testcase 1065: +INSERT INTO num_tmp VALUES (-13.00000000000000000000); +--Testcase 1066: +select trim_scale(n1) from num_tmp; + trim_scale +------------ + -13 +(1 row) + +--Testcase 1067: +DELETE FROM num_tmp; +--Testcase 1068: +INSERT INTO num_tmp VALUES (1e100); +--Testcase 1069: +select trim_scale(n1) from num_tmp; + trim_scale +------------------------------------------------------------------------------------------------------- + 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +-- +-- Tests for SUM() +-- +-- cases that need carry propagation +--Testcase 1070: +DELETE FROM num_tmp; +--Testcase 1071: +INSERT INTO num_tmp SELECT * FROM generate_series(1, 100000); +--Testcase 1072: +SELECT SUM(9999::numeric) FROM num_tmp; + sum +----------- + 999900000 +(1 row) + +--Testcase 1073: +SELECT SUM((-9999)::numeric) FROM num_tmp; + sum +------------ + -999900000 +(1 row) + +-- +-- Tests for VARIANCE() +-- +--Testcase 1578: +INSERT INTO num_variance VALUES (0); +--Testcase 1579: +INSERT INTO num_variance VALUES (3e-500); +ERROR: "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003" is out of range for type double precision +--Testcase 1580: +INSERT INTO num_variance VALUES (-3e-500); +ERROR: "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003" is out of range for type double precision +--Testcase 1581: +INSERT INTO num_variance VALUES (4e-500 - 1e-16383); +ERROR: "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" is out of range for type double precision +--Testcase 1582: +INSERT INTO num_variance VALUES (-4e-500 + 1e-16383); +ERROR: "-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" is out of range for type double precision +-- variance is just under 12.5e-1000 and so should round down to 12e-1000 +--Testcase 1583: +SELECT trim_scale(variance(a) * 1e1000) FROM num_variance; + trim_scale +------------ + +(1 row) + +-- check that parallel execution produces the same result +BEGIN; +-- ALTER TABLE num_variance SET (parallel_workers = 4); +SET LOCAL parallel_setup_cost = 0; +SET LOCAL max_parallel_workers_per_gather = 4; +--Testcase 1584: +SELECT trim_scale(variance(a) * 1e1000) FROM num_variance; + trim_scale +------------ + +(1 row) + +ROLLBACK; +-- case where sum of squares would overflow but variance does not +--Testcase 1585: +DELETE FROM num_variance; +ERROR: no primary key column specified for foreign table +DETAIL: For UPDATE or DELETE, at least one foreign table column must be marked as primary key column. +HINT: Set the option "key" on the columns that belong to the primary key. +--Testcase 1586: +INSERT INTO num_variance SELECT 9e131071 + x FROM generate_series(1, 5) x; +ERROR: "90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" is out of range for type double precision +--Testcase 1587: +SELECT variance(a) FROM num_variance; + variance +---------- + +(1 row) + +-- check that parallel execution produces the same result +BEGIN; +-- ALTER TABLE num_variance SET (parallel_workers = 4); +SET LOCAL parallel_setup_cost = 0; +SET LOCAL max_parallel_workers_per_gather = 4; +--Testcase 1588: +SELECT variance(a) FROM num_variance; + variance +---------- + +(1 row) + +ROLLBACK; +-- +-- Tests for GCD() +-- +--Testcase 1074: +DELETE FROM num_tmp; +--Testcase 1075: +INSERT INTO num_tmp VALUES + (0::numeric, 0::numeric), + (0::numeric, numeric 'NaN'), + (0::numeric, 46375::numeric), + (433125::numeric, 46375::numeric), + (43312.5::numeric, 4637.5::numeric), + (4331.250::numeric, 463.75000::numeric), + ('Infinity', '0'), + ('Infinity', '42'), + ('Infinity', 'Infinity'); +--Testcase 1076: +SELECT n1 as a, n2 as b, gcd(n1, n2), gcd(n1, -n2), gcd(-n2, n1), gcd(-n2, -n1) FROM num_tmp; + a | b | gcd | gcd | gcd | gcd +----------+----------+-------+-------+-------+------- + 0 | 0 | 0 | 0 | 0 | 0 + 0 | | | | | + 0 | 46375 | 46375 | 46375 | 46375 | 46375 + 433125 | 46375 | 875 | 875 | 875 | 875 + 43312.5 | 4637.5 | 87.5 | 87.5 | 87.5 | 87.5 + 4331.25 | 463.75 | 8.75 | 8.75 | 8.75 | 8.75 + Infinity | 0 | NaN | NaN | NaN | NaN + Infinity | 42 | NaN | NaN | NaN | NaN + Infinity | Infinity | NaN | NaN | NaN | NaN +(9 rows) + +-- +-- Tests for LCM() +-- +--Testcase 1077: +DELETE FROM num_tmp; +--Testcase 1078: +INSERT INTO num_tmp VALUES + (0::numeric, 0::numeric), + (0::numeric, numeric 'NaN'), + (0::numeric, 13272::numeric), + (13272::numeric, 13272::numeric), + (423282::numeric, 13272::numeric), + (42328.2::numeric, 1327.2::numeric), + (4232.820::numeric, 132.72000::numeric), + ('Infinity', '0'), + ('Infinity', '42'), + ('Infinity', 'Infinity'); +--Testcase 1079: +SELECT n1 as a, n2 as b, lcm(n1, n2), lcm(n1, -n2), lcm(-n2, n1), lcm(-n2, -n1) FROM num_tmp; + a | b | lcm | lcm | lcm | lcm +----------+----------+-----------+-----------+-----------+----------- + 0 | 0 | 0 | 0 | 0 | 0 + 0 | | | | | + 0 | 13272 | 0 | 0 | 0 | 0 + 13272 | 13272 | 13272 | 13272 | 13272 | 13272 + 423282 | 13272 | 11851896 | 11851896 | 11851896 | 11851896 + 42328.2 | 1327.2 | 1185189.6 | 1185189.6 | 1185189.6 | 1185189.6 + 4232.82 | 132.72 | 118518.96 | 118518.96 | 118518.96 | 118518.96 + Infinity | 0 | NaN | NaN | NaN | NaN + Infinity | 42 | NaN | NaN | NaN | NaN + Infinity | Infinity | NaN | NaN | NaN | NaN +(10 rows) + +--Testcase 1080: +DELETE FROM num_tmp; +--Testcase 1081: +INSERT INTO num_tmp VALUES (10::numeric, 131068); +--Testcase 1082: +SELECT lcm(9999 * (n1)^n2 + (n1^n2 - 1), 2) FROM num_tmp; -- overflow +ERROR: value overflows numeric format +-- +-- Tests for factorial +-- +--Testcase 1250: +DELETE FROM num_tmp; +--Testcase 1251: +INSERT INTO num_tmp VALUES (4); +--Testcase 1252: +SELECT factorial(n1::int4) FROM num_tmp; + factorial +----------- + 24 +(1 row) + +--Testcase 1253: +DELETE FROM num_tmp; +--Testcase 1254: +INSERT INTO num_tmp VALUES (15); +--Testcase 1255: +SELECT factorial(n1::int4) FROM num_tmp; + factorial +--------------- + 1307674368000 +(1 row) + +--Testcase 1256: +DELETE FROM num_tmp; +--Testcase 1257: +INSERT INTO num_tmp VALUES (100000); +--Testcase 1258: +SELECT factorial(n1::int4) FROM num_tmp; +ERROR: value overflows numeric format +--Testcase 1259: +DELETE FROM num_tmp; +--Testcase 1260: +INSERT INTO num_tmp VALUES (0); +--Testcase 1261: +SELECT factorial(n1::int4) FROM num_tmp; + factorial +----------- + 1 +(1 row) + +--Testcase 1262: +DELETE FROM num_tmp; +--Testcase 1263: +INSERT INTO num_tmp VALUES (-4); +--Testcase 1264: +SELECT factorial(n1::int4) FROM num_tmp; +ERROR: factorial of a negative number is undefined +-- +-- Tests for pg_lsn() +-- +--Testcase 1265: +DELETE FROM num_tmp; +--Testcase 1266: +INSERT INTO num_tmp VALUES (23783416::numeric); +--Testcase 1267: +SELECT pg_lsn(n1) FROM num_tmp; + pg_lsn +----------- + 0/16AE7F8 +(1 row) + +--Testcase 1268: +DELETE FROM num_tmp; +--Testcase 1269: +INSERT INTO num_tmp VALUES (0::numeric); +--Testcase 1270: +SELECT pg_lsn(n1) FROM num_tmp; + pg_lsn +-------- + 0/0 +(1 row) + +--Testcase 1271: +DELETE FROM num_tmp; +--Testcase 1272: +INSERT INTO num_tmp VALUES (18446744073709551615::numeric); +--Testcase 1273: +SELECT pg_lsn(n1) FROM num_tmp; +ERROR: pg_lsn out of range +--Testcase 1274: +DELETE FROM num_tmp; +--Testcase 1275: +INSERT INTO num_tmp VALUES (-1::numeric); +--Testcase 1276: +SELECT pg_lsn(n1) FROM num_tmp; +ERROR: pg_lsn out of range +--Testcase 1277: +DELETE FROM num_tmp; +--Testcase 1278: +INSERT INTO num_tmp VALUES (18446744073709551616::numeric); +--Testcase 1279: +SELECT pg_lsn(n1) FROM num_tmp; +ERROR: pg_lsn out of range +--Testcase 1280: +DELETE FROM num_tmp; +--Testcase 1281: +INSERT INTO num_tmp VALUES ('NaN'::numeric); +--Testcase 1282: +SELECT pg_lsn(n1) FROM num_tmp; + pg_lsn +-------- + +(1 row) + +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; +--Testcase 1083: +DROP SERVER sqlite_svr; +--Testcase 1084: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/extra/out_of_range.out b/expected/17.0/extra/out_of_range.out new file mode 100644 index 00000000..be2f8256 --- /dev/null +++ b/expected/17.0/extra/out_of_range.out @@ -0,0 +1,162 @@ +-- +-- INT4 + INT2 +-- +--Testcase 001: +CREATE EXTENSION sqlite_fdw; +--Testcase 002: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 01: +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 02: +CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 03: +DELETE FROM INT4_TMP; +--Testcase 04: +ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int8; +--Testcase 05: +INSERT INTO INT4_TMP VALUES (x'7FFFFFFF'::int8 + 1, 0); +--Testcase 06: +ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int4; +--Testcase 07: +SELECT * FROM INT4_TMP; -- overflow +ERROR: integer out of range +HINT: SQLite value with "integer" affinity : 2147483648 +CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 08: +SELECT f1 FROM INT4_TMP; -- overflow +ERROR: integer out of range +HINT: SQLite value with "integer" affinity : 2147483648 +CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 09: +DELETE FROM INT4_TMP; +--Testcase 10: +ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int8; +--Testcase 11: +INSERT INTO INT4_TMP VALUES (-(x'7FFFFFFF'::int8) - 2, 0); +--Testcase 12: +ALTER FOREIGN TABLE INT4_TMP ALTER COLUMN f1 TYPE int4; +--Testcase 13: +SELECT * FROM INT4_TMP; -- overflow +ERROR: integer out of range +HINT: SQLite value with "integer" affinity : -2147483649 +CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 14: +SELECT f1 FROM INT4_TMP; -- overflow +ERROR: integer out of range +HINT: SQLite value with "integer" affinity : -2147483649 +CONTEXT: foreign table "int4_tmp" foreign column "f1" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 15: +CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 16: +CREATE FOREIGN TABLE INT2_TMP(f1 int2, f2 int2, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 17: +DELETE FROM INT2_TMP; +--Testcase 18: +ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int4; +--Testcase 19: +INSERT INTO INT2_TMP VALUES (x'7FFF'::int8 + 1, 0); +--Testcase 20: +ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int2; +--Testcase 21: +SELECT * FROM INT2_TMP; -- overflow +ERROR: smallint out of range +HINT: SQLite value with "integer" affinity : 32768 +CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 22: +SELECT f1 FROM INT2_TMP; -- overflow +ERROR: smallint out of range +HINT: SQLite value with "integer" affinity : 32768 +CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 23: +DELETE FROM INT2_TMP; +--Testcase 24: +ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int4; +--Testcase 25: +INSERT INTO INT2_TMP VALUES (-(x'7FFF'::int8) - 2, 0); +--Testcase 26: +ALTER FOREIGN TABLE INT2_TMP ALTER COLUMN f1 TYPE int2; +--Testcase 27: +SELECT * FROM INT2_TMP; -- overflow +ERROR: smallint out of range +HINT: SQLite value with "integer" affinity : -32769 +CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 28: +SELECT f1 FROM INT2_TMP; -- overflow +ERROR: smallint out of range +HINT: SQLite value with "integer" affinity : -32769 +CONTEXT: foreign table "int2_tmp" foreign column "f1" have data type "smallint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 29: +CREATE FOREIGN TABLE INT8_TBL(q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 31: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; +--Testcase 32: +INSERT INTO INT8_TBL VALUES (-9223372036854775810, 0); +--Testcase 33: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; +--Testcase 34: +SELECT * FROM INT8_TBL; -- NO overflow + q1 | q2 +----------------------+---- + -9223372036854775808 | 0 +(1 row) + +--Testcase 35: +SELECT q1 FROM INT8_TBL; -- NO overflow + q1 +---------------------- + -9223372036854775808 +(1 row) + +--Testcase 36: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; +--Testcase 37: +DELETE FROM INT8_TBL WHERE q1 = -9223372036854775810; +--Testcase 38: +INSERT INTO INT8_TBL VALUES (9223372036854775809, 0); +--Testcase 39: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; +--Testcase 40: +SELECT * FROM INT8_TBL; -- overflow +ERROR: bigint out of range +HINT: SQLite value with "real" affinity : 9.22337203685478e+18 +CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 41: +SELECT q1 FROM INT8_TBL; -- overflow +ERROR: bigint out of range +HINT: SQLite value with "real" affinity : 9.22337203685478e+18 +CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 42: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; +--Testcase 43: +DELETE FROM INT8_TBL WHERE q1 = 9223372036854775809; +--Testcase 44: +INSERT INTO INT8_TBL VALUES (10 * -9223372036854775810, 0); +--Testcase 45: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; +--Testcase 46: +SELECT * FROM INT8_TBL; -- overflow +ERROR: bigint out of range +HINT: SQLite value with "real" affinity : -9.22337203685478e+19 +CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 47: +SELECT q1 FROM INT8_TBL; -- overflow +ERROR: bigint out of range +HINT: SQLite value with "real" affinity : -9.22337203685478e+19 +CONTEXT: foreign table "int8_tbl" foreign column "q1" have data type "bigint" (usual affinity "integer"), in query there is whole-row reference to foreign table +--Testcase 48: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE double precision; +--Testcase 49: +DELETE FROM INT8_TBL WHERE q1 = 10 * -9223372036854775810; +--Testcase 50: +ALTER FOREIGN TABLE INT8_TBL ALTER COLUMN q1 TYPE int8; +--Testcase 003: +DROP SERVER sqlite_svr CASCADE; +NOTICE: drop cascades to 5 other objects +DETAIL: drop cascades to foreign table int4_tbl +drop cascades to foreign table int4_tmp +drop cascades to foreign table int2_tbl +drop cascades to foreign table int2_tmp +drop cascades to foreign table int8_tbl +--Testcase 004: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/12.16/extra/prepare.out b/expected/17.0/extra/prepare.out similarity index 80% rename from expected/12.16/extra/prepare.out rename to expected/17.0/extra/prepare.out index 4bd94a0b..8d7941a8 100644 --- a/expected/12.16/extra/prepare.out +++ b/expected/17.0/extra/prepare.out @@ -35,9 +35,9 @@ create foreign table road_tmp (a int, b int, id int options (key 'true')) server --Testcase 31: insert into road_tmp values (1, 2); --Testcase 1: -SELECT name, statement, parameter_types FROM pg_prepared_statements; - name | statement | parameter_types -------+-----------+----------------- +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; + name | statement | parameter_types | result_types +------+-----------+-----------------+-------------- (0 rows) --Testcase 2: @@ -50,10 +50,10 @@ EXECUTE q1; (1 row) --Testcase 4: -SELECT name, statement, parameter_types FROM pg_prepared_statements; - name | statement | parameter_types -------+---------------------------------------+----------------- - q1 | PREPARE q1 AS SELECT a FROM road_tmp; | {} +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; + name | statement | parameter_types | result_types +------+---------------------------------------+-----------------+-------------- + q1 | PREPARE q1 AS SELECT a FROM road_tmp; | {} | {integer} (1 row) -- should fail @@ -74,28 +74,28 @@ EXECUTE q1; --Testcase 8: PREPARE q2 AS SELECT b FROM road_tmp; --Testcase 9: -SELECT name, statement, parameter_types FROM pg_prepared_statements; - name | statement | parameter_types -------+---------------------------------------+----------------- - q1 | PREPARE q1 AS SELECT b FROM road_tmp; | {} - q2 | PREPARE q2 AS SELECT b FROM road_tmp; | {} +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; + name | statement | parameter_types | result_types +------+---------------------------------------+-----------------+-------------- + q1 | PREPARE q1 AS SELECT b FROM road_tmp; | {} | {integer} + q2 | PREPARE q2 AS SELECT b FROM road_tmp; | {} | {integer} (2 rows) -- sql92 syntax DEALLOCATE PREPARE q1; --Testcase 10: -SELECT name, statement, parameter_types FROM pg_prepared_statements; - name | statement | parameter_types -------+---------------------------------------+----------------- - q2 | PREPARE q2 AS SELECT b FROM road_tmp; | {} +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; + name | statement | parameter_types | result_types +------+---------------------------------------+-----------------+-------------- + q2 | PREPARE q2 AS SELECT b FROM road_tmp; | {} | {integer} (1 row) DEALLOCATE PREPARE q2; -- the view should return the empty set again --Testcase 11: -SELECT name, statement, parameter_types FROM pg_prepared_statements; - name | statement | parameter_types -------+-----------+----------------- +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; + name | statement | parameter_types | result_types +------+-----------+-----------------+-------------- (0 rows) -- parameterized queries @@ -164,6 +164,8 @@ DETAIL: Expected 5 parameters but got 6. --Testcase 18: EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'bytea'); ERROR: parameter $3 of type boolean cannot be coerced to the expected type double precision +LINE 1: EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'byte... + ^ HINT: You will need to rewrite or cast the expression. -- invalid type --Testcase 19: @@ -216,26 +218,31 @@ PREPARE q6 AS --Testcase 23: PREPARE q7(unknown) AS SELECT * FROM road WHERE thepath = $1; +-- DML statements +PREPARE q8 AS + UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1; --Testcase 24: -SELECT name, statement, parameter_types FROM pg_prepared_statements +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements ORDER BY name; - name | statement | parameter_types -------+------------------------------------------------------------------+---------------------------------------------------- - q2 | PREPARE q2(text) AS +| {text} - | SELECT datname, datistemplate, datallowconn +| - | FROM pg_database WHERE datname = $1; | - q3 | PREPARE q3(text, int, float, boolean, smallint) AS +| {text,integer,"double precision",boolean,smallint} - | SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+| - | ten = $3::bigint OR true = $4 OR odd = $5::int) +| - | ORDER BY unique1; | - q5 | PREPARE q5(int, text) AS +| {integer,text} - | SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +| - | ORDER BY unique1; | - q6 | PREPARE q6 AS +| {integer,name} - | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | - q7 | PREPARE q7(unknown) AS +| {path} - | SELECT * FROM road WHERE thepath = $1; | -(5 rows) + name | statement | parameter_types | result_types +------+------------------------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------- + q2 | PREPARE q2(text) AS +| {text} | {name,boolean,boolean} + | SELECT datname, datistemplate, datallowconn +| | + | FROM pg_database WHERE datname = $1; | | + q3 | PREPARE q3(text, int, float, boolean, smallint) AS +| {text,integer,"double precision",boolean,smallint} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name} + | SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+| | + | ten = $3::bigint OR true = $4 OR odd = $5::int) +| | + | ORDER BY unique1; | | + q5 | PREPARE q5(int, text) AS +| {integer,text} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name} + | SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +| | + | ORDER BY unique1; | | + q6 | PREPARE q6 AS +| {integer,name} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name} + | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | | + q7 | PREPARE q7(unknown) AS +| {path} | {text,path} + | SELECT * FROM road WHERE thepath = $1; | | + q8 | PREPARE q8 AS +| {integer,name} | + | UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1; | | +(6 rows) -- test DEALLOCATE ALL; DEALLOCATE ALL; diff --git a/expected/14.9/extra/select.out b/expected/17.0/extra/select.out similarity index 97% rename from expected/14.9/extra/select.out rename to expected/17.0/extra/select.out index 86567108..7dddc119 100644 --- a/expected/14.9/extra/select.out +++ b/expected/17.0/extra/select.out @@ -49,6 +49,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -356,10 +366,6 @@ SELECT onek2.unique1, onek2.stringu1 FROM onek2 RESET enable_seqscan; RESET enable_bitmapscan; RESET enable_sort; ---Testcase 11: -SELECT two, stringu1, ten, string4 - INTO TABLE tmp - FROM onek; -- -- awk '{print $1,$2;}' person.data | -- awk '{if(NF!=2){print $3,$2;}else{print;}}' - emp.data | @@ -576,6 +582,10 @@ TABLE int8_tbl; 4567890123456789 | -4567890123456789 (9 rows) +-- corner case: VALUES with no columns +-- CREATE TEMP TABLE nocols(); +-- INSERT INTO nocols DEFAULT VALUES; +-- SELECT * FROM nocols n, LATERAL (VALUES(n.*)) v; -- -- Test ORDER BY options -- @@ -912,6 +922,8 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/expected/16.0/extra/select_having.out b/expected/17.0/extra/select_having.out similarity index 100% rename from expected/16.0/extra/select_having.out rename to expected/17.0/extra/select_having.out diff --git a/expected/17.0/extra/sqlite_fdw_post.out b/expected/17.0/extra/sqlite_fdw_post.out new file mode 100644 index 00000000..517ae19a --- /dev/null +++ b/expected/17.0/extra/sqlite_fdw_post.out @@ -0,0 +1,12490 @@ +-- =================================================================== +-- create FDW objects +-- =================================================================== +--Testcase 483: +CREATE EXTENSION sqlite_fdw; +DO $d$ + BEGIN + EXECUTE $$CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + EXECUTE $$CREATE SERVER sqlite_svr2 FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + EXECUTE $$CREATE SERVER sqlite_svr3 FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; +-- SQLite FDW does not need User and User Mapping. +--Testcase 484: +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +--Testcase 485: +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +--Testcase 756: +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- =================================================================== +-- create objects used through FDW sqlite server +-- =================================================================== +--Testcase 486: +CREATE SCHEMA "S 1"; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO "S 1"; +--Testcase 1: +INSERT INTO "S 1"."T 1" + SELECT id, + id % 10, + to_char(id, 'FM00000'), + '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, + '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, + id % 10, + id % 10, + 'foo' + FROM generate_series(1, 1000) id; +--Testcase 2: +INSERT INTO "S 1"."T 2" + SELECT id, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 3: +INSERT INTO "S 1"."T 3" + SELECT id, + id + 1, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 487: +DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests +--Testcase 4: +INSERT INTO "S 1"."T 4" + SELECT id, + id + 1, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 488: +DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests +/*ANALYZE "S 1"."T 1"; +ANALYZE "S 1"."T 2"; +ANALYZE "S 1"."T 3"; +ANALYZE "S 1"."T 4";*/ +-- =================================================================== +-- create foreign tables +-- =================================================================== +--Testcase 489: +CREATE FOREIGN TABLE ft1 ( + c0 int, + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_svr; +--Testcase 757: +ALTER FOREIGN TABLE ft1 DROP COLUMN c0; +--Testcase 490: +CREATE FOREIGN TABLE ft2 ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + cx int, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft2', + c8 text +) SERVER sqlite_svr; +--Testcase 758: +ALTER FOREIGN TABLE ft2 DROP COLUMN cx; +--Testcase 491: +CREATE FOREIGN TABLE ft4 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr OPTIONS (table 'T 3'); +--Testcase 492: +CREATE FOREIGN TABLE ft5 ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr OPTIONS (table 'T 4'); +--Testcase 493: +CREATE FOREIGN TABLE ft6 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr2 OPTIONS (table 'T 4'); +--Testcase 759: +CREATE FOREIGN TABLE ft7 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr3 OPTIONS (table 'T 4'); +--Testcase 760: +ALTER FOREIGN TABLE ft1 OPTIONS (table 'T 1'); +--Testcase 761: +ALTER FOREIGN TABLE ft2 OPTIONS (table 'T 1'); +--Testcase 762: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); +--Testcase 763: +ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); +--Testcase 5: +\det+ + List of foreign tables + Schema | Table | Server | FDW options | Description +--------+-------+-------------+-----------------+------------- + public | ft1 | sqlite_svr | ("table" 'T 1') | + public | ft2 | sqlite_svr | ("table" 'T 1') | + public | ft4 | sqlite_svr | ("table" 'T 3') | + public | ft5 | sqlite_svr | ("table" 'T 4') | + public | ft6 | sqlite_svr2 | ("table" 'T 4') | + public | ft7 | sqlite_svr3 | ("table" 'T 4') | +(6 rows) + +-- Test that alteration of server options causes reconnection +-- Remote's errors might be non-English, so hide them to ensure stable results +\set VERBOSITY terse +--Testcase 6: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work + c3 | c4 +-------+------------------------------ + 00001 | Fri Jan 02 00:00:00 1970 PST +(1 row) + +--Testcase 764: +ALTER SERVER sqlite_svr OPTIONS (SET database 'no such database'); +--Testcase 7: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail +ERROR: Failed to open SQLite DB, file 'no such database', result code 14 +DO $d$ + BEGIN + EXECUTE $$ALTER SERVER sqlite_svr + OPTIONS (SET database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; +--Testcase 8: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again + c3 | c4 +-------+------------------------------ + 00001 | Fri Jan 02 00:00:00 1970 PST +(1 row) + +\set VERBOSITY default +-- Now we should be able to run ANALYZE. +-- To exercise multiple code paths, we use local stats on ft1 +-- and remote-estimate mode on ft2. +--ANALYZE ft1; +--ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true'); +-- =================================================================== +-- test error case for create publication on foreign table +-- =================================================================== +--Testcase 955: +CREATE PUBLICATION testpub_ftbl FOR TABLE ft1; -- should fail +ERROR: cannot add relation "ft1" to publication +DETAIL: This operation is not supported for foreign tables. +-- =================================================================== +-- simple queries +-- =================================================================== +-- single table without alias +--Testcase 9: +EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; + QUERY PLAN +--------------------- + Foreign Scan on ft1 +(1 row) + +--Testcase 10: +SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo + 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo + 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo +(10 rows) + +-- single table with alias - also test that tableoid sort is not pushed to remote side +--Testcase 11: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------- + Limit + Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid + -> Sort + Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid + Sort Key: t1.c3, t1.c1, t1.tableoid + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(8 rows) + +--Testcase 12: +SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo + 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo + 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo +(10 rows) + +-- whole-row reference +--Testcase 13: +EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: t1.*, c3, c1 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 14: +SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + t1 +-------------------------------------------------------------------------------------------- + (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1 ",foo) + (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2 ",foo) + (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3 ",foo) + (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4 ",foo) + (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5 ",foo) + (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6 ",foo) + (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7 ",foo) + (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8 ",foo) + (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9 ",foo) + (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0 ",foo) +(10 rows) + +-- empty result +--Testcase 15: +SELECT * FROM ft1 WHERE false; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+----+----+----+----+----+---- +(0 rows) + +-- with WHERE clause +--Testcase 16: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c7` >= '1')) AND ((`C 1` = 101)) AND ((`c6` = '1')) +(3 rows) + +--Testcase 17: +SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- with FOR UPDATE/SHARE +--Testcase 18: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + LockRows + Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 101)) +(5 rows) + +--Testcase 19: +SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +--Testcase 20: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + LockRows + Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 102)) +(5 rows) + +--Testcase 21: +SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo +(1 row) + +-- aggregate +--Testcase 22: +SELECT COUNT(*) FROM ft1 t1; + count +------- + 1000 +(1 row) + +-- subquery +--Testcase 23: +SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo + 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo + 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo +(10 rows) + +-- subquery+MAX +--Testcase 24: +SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+----+-------+------------------------------+--------------------------+----+------------+----- + 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo +(1 row) + +-- used in CTE +--Testcase 25: +WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1; + c1 | c2 | c3 | c4 +----+----+-------+------------------------------ + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST + 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST + 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST + 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST + 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST + 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST +(10 rows) + +-- fixed values +--Testcase 26: +SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1; + ?column? | ?column? +----------+---------- + fixed | +(1 row) + +-- Test forcing the remote server to produce sorted data for a merge join. +--Testcase 765: +SET enable_hashjoin TO false; +--Testcase 766: +SET enable_nestloop TO false; +-- inner join; expressions in the clauses appear in the equivalence class list +--Testcase 27: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2."C 1" + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 28: +SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; + c1 | C 1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- outer join; expressions in the clauses do not appear in equivalence class +-- list but no output change as compared to the previous query +--Testcase 29: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2."C 1" + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 30: +SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; + c1 | C 1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- A join between local table and foreign join. ORDER BY clause is added to the +-- foreign join so that the local table can be joined using merge join strategy. +--Testcase 31: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1."C 1" + SQLite query: SELECT r1.`C 1` FROM (main."T 1" r1 LEFT JOIN (main."T 1" r2 INNER JOIN main."T 1" r3 ON (((r2.`C 1` = r3.`C 1`)))) ON (((r3.`C 1` = r1.`C 1`)))) LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 32: +SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + C 1 +----- + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 +(10 rows) + +-- Test similar to above, except that the full join prevents any equivalence +-- classes from being merged. This produces single relation equivalence classes +-- included in join restrictions. +--Testcase 33: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1."C 1", t2.c1, t3.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r3.`C 1` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r3 ON (((r3.`C 1` = r1.`C 1`)))) LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r3.`C 1`)))) LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 34: +SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + C 1 | c1 | c1 +-----+-----+----- + 101 | 101 | 101 + 102 | 102 | 102 + 103 | 103 | 103 + 104 | 104 | 104 + 105 | 105 | 105 + 106 | 106 | 106 + 107 | 107 | 107 + 108 | 108 | 108 + 109 | 109 | 109 + 110 | 110 | 110 +(10 rows) + +-- Test similar to above with all full outer joins +--Testcase 35: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------- + Limit + Output: t1."C 1", t2.c1, t3.c1 + -> Merge Full Join + Output: t1."C 1", t2.c1, t3.c1 + Merge Cond: (t1."C 1" = t3.c1) + -> Sort + Output: t1."C 1" + Sort Key: t1."C 1" + -> Foreign Scan on "S 1"."T 1" t1 + Output: t1."C 1" + SQLite query: SELECT `C 1` FROM main."T 1" + -> Sort + Output: t2.c1, t3.c1 + Sort Key: t3.c1 + -> Merge Full Join + Output: t2.c1, t3.c1 + Merge Cond: (t2.c1 = t3.c1) + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft1 t2 + Output: t2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Sort + Output: t3.c1 + Sort Key: t3.c1 + -> Foreign Scan on public.ft2 t3 + Output: t3.c1 + SQLite query: SELECT `C 1` FROM main."T 1" +(29 rows) + +--Testcase 36: +SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; + C 1 | c1 | c1 +-----+-----+----- + 101 | 101 | 101 + 102 | 102 | 102 + 103 | 103 | 103 + 104 | 104 | 104 + 105 | 105 | 105 + 106 | 106 | 106 + 107 | 107 | 107 + 108 | 108 | 108 + 109 | 109 | 109 + 110 | 110 | 110 +(10 rows) + +--Testcase 767: +RESET enable_hashjoin; +--Testcase 768: +RESET enable_nestloop; +-- Test executing assertion in estimate_path_cost_size() that makes sure that +-- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is +-- a sensible value even when the rel has tuples=0 +-- CREATE TABLE loct_empty (c1 int NOT NULL, c2 text); +--Testcase 769: +CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text) + SERVER sqlite_svr OPTIONS (table 'loct_empty'); +--Testcase 770: +INSERT INTO "S 1".loct_empty + SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; +--Testcase 771: +DELETE FROM "S 1".loct_empty; +-- ANALYZE ft_empty; +--Testcase 772: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1; + QUERY PLAN +--------------------------------------------------------------------------------------- + Foreign Scan on public.ft_empty + Output: c1, c2 + SQLite query: SELECT `c1`, `c2` FROM main."loct_empty" ORDER BY `c1` ASC NULLS LAST +(3 rows) + +-- test restriction on non-system foreign tables. +SET restrict_nonsystem_relation_kind TO 'foreign-table'; +--Testcase 1029: +SELECT * from ft1 where c1 < 1; -- ERROR +ERROR: access to non-system foreign table is restricted +--Testcase 1030: +INSERT INTO ft1 (c1) VALUES (1); -- ERROR +ERROR: access to non-system foreign table is restricted +--Testcase 1031: +DELETE FROM ft1 WHERE c1 = 1; -- ERROR +ERROR: access to non-system foreign table is restricted +TRUNCATE ft1; -- ERROR +ERROR: access to non-system foreign table is restricted +RESET restrict_nonsystem_relation_kind; +-- =================================================================== +-- WHERE with remotely-executable conditions +-- =================================================================== +--Testcase 37: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +--Testcase 38: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 100)) AND ((`c2` = 0)) +(3 rows) + +--Testcase 39: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NULL; -- NullTest + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c3` IS NULL)) +(3 rows) + +--Testcase 40: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NOT NULL; -- NullTest + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c3` IS NOT NULL)) +(3 rows) + +--Testcase 41: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((round(abs(`C 1`), 0) = 1)) +(3 rows) + +--Testcase 42: +--Testcase 956: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = (- `C 1`))) +(3 rows) + +--Testcase 44: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: ((t1.c1 IS NOT NULL) IS DISTINCT FROM (t1.c1 IS NOT NULL)) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(4 rows) + +--Testcase 45: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (`C 1` IN (`c2`, 1, (`C 1` + 0))) +(3 rows) + +--Testcase 46: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (t1.c1 = (ARRAY[t1.c1, t1.c2, 3])[1]) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(4 rows) + +--Testcase 47: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c6` = 'foo''s\\bar')) +(3 rows) + +--Testcase 48: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) +(3 rows) + +-- parameterized remote path for foreign table +--Testcase 49: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND ((r1.`C 1` = 47)))) +(3 rows) + +--Testcase 50: +SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; + C 1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+----- + 47 | 7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo | 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo +(1 row) + +-- check both safe and unsafe join conditions +--Testcase 51: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 a, ft2 b + WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 + Filter: (upper((a.c7)::text) = (b.c7)::text) + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = 6)) AND ((r1.`c8` = 'foo')))) +(4 rows) + +--Testcase 52: +SELECT * FROM ft2 a, ft2 b +WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+----- + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo + 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo + 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo + 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo + 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo + 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo + 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo + 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo + 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo +(100 rows) + +-- bug before 9.3.5 due to sloppy handling of remote-estimate parameters +--Testcase 53: +SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5)); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo +(4 rows) + +--Testcase 54: +SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5)); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo +(4 rows) + +-- user-defined operator/function +--Testcase 494: +CREATE FUNCTION sqlite_fdw_abs(int) RETURNS int AS $$ +BEGIN +RETURN abs($1); +END +$$ LANGUAGE plpgsql IMMUTABLE; +--Testcase 495: +CREATE OPERATOR === ( + LEFTARG = int, + RIGHTARG = int, + PROCEDURE = int4eq, + COMMUTATOR = === +); +-- built-in operators and functions can be shipped for remote execution +--Testcase 57: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan + Output: (count(c3)) + SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = abs(`c2`))) +(3 rows) + +--Testcase 58: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); + count +------- + 9 +(1 row) + +--Testcase 59: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (count(c3)) + SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = `c2`)) +(3 rows) + +--Testcase 60: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; + count +------- + 9 +(1 row) + +-- by default, user-defined ones cannot +--Testcase 61: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--Testcase 62: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); + count +------- + 9 +(1 row) + +--Testcase 63: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--Testcase 64: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + count +------- + 9 +(1 row) + +-- ORDER BY can be shipped, though +--Testcase 496: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Limit + Output: c1, c2, c3, c4, c5, c6, c7, c8 + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(6 rows) + +--Testcase 497: +SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- but let's put them in an extension ... +--Testcase 773: +ALTER EXTENSION sqlite_fdw ADD FUNCTION sqlite_fdw_abs(int); +--Testcase 774: +ALTER EXTENSION sqlite_fdw ADD OPERATOR === (int, int); +--ALTER SERVER sqlite_svr2 OPTIONS (ADD extensions 'sqlite_fdw'); +-- ... now they can be shipped +--Testcase 498: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--Testcase 499: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); + count +------- + 9 +(1 row) + +--Testcase 500: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--Testcase 501: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + count +------- + 9 +(1 row) + +-- and both ORDER BY and LIMIT can be shipped +--Testcase 502: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Limit + Output: c1, c2, c3, c4, c5, c6, c7, c8 + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(6 rows) + +--Testcase 503: +SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- Ensure we don't ship FETCH FIRST .. WITH TIES +--Testcase 1027: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Limit + Output: c2 + -> Foreign Scan on public.ft1 t1 + Output: c2 + SQLite query: SELECT `c2` FROM main."T 1" WHERE ((`C 1` > 960)) ORDER BY `c2` ASC NULLS LAST +(5 rows) + +--Testcase 1028: +SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES; + c2 +---- + 0 + 0 + 0 + 0 +(4 rows) + +-- Test CASE pushdown +--Testcase 957: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft2 + Output: c1, c2, c3 + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" WHERE ((CASE WHEN (`C 1` > 990) THEN `C 1` ELSE NULL END < 1000)) ORDER BY `C 1` ASC NULLS LAST +(3 rows) + +--Testcase 958: +SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1; + c1 | c2 | c3 +-----+----+------- + 991 | 1 | 00991 + 992 | 2 | 00992 + 993 | 3 | 00993 + 994 | 4 | 00994 + 995 | 5 | 00995 + 996 | 6 | 00996 + 997 | 7 | 00997 + 998 | 8 | 00998 + 999 | 9 | 00999 +(9 rows) + +-- Nested CASE +--Testcase 959: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft2 + Output: c1, c2, c3 + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" WHERE ((CASE CASE WHEN (`c2` > 0) THEN `c2` ELSE NULL END WHEN 100 THEN 601 WHEN `c2` THEN `c2` ELSE 0 END > 600)) ORDER BY `C 1` ASC NULLS LAST +(3 rows) + +--Testcase 960: +SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1; + c1 | c2 | c3 +----+----+---- +(0 rows) + +-- CASE arg WHEN +--Testcase 961: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > CASE mod(`C 1`, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)) +(3 rows) + +-- CASE cannot be pushed down because of unshippable arg clause +--Testcase 962: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c1 > (CASE random()::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + QUERY PLAN +----------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (ft1.c1 > CASE (random())::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(4 rows) + +-- these are shippable +--Testcase 963: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (CASE `c6` WHEN 'foo' THEN 1 ELSE (`c3` < 'bar') END) +(3 rows) + +--Testcase 964: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (CASE `c3` WHEN `c6` THEN 1 ELSE (`c3` < 'bar') END) +(3 rows) + +-- but this is not because of collation +--Testcase 965: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END; + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: CASE (ft1.c3)::text WHEN ft1.c6 THEN true ELSE (ft1.c3 < 'bar'::text) END + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(4 rows) + +-- a regconfig constant referring to this text search configuration +-- is initially unshippable--Testcase 984: +CREATE TEXT SEARCH CONFIGURATION public.custom_search + (COPY = pg_catalog.english); +--Testcase 985: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + QUERY PLAN +-------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, to_tsvector('custom_search'::regconfig, c3) + Filter: (length(to_tsvector('custom_search'::regconfig, ft1.c3)) > 0) + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" WHERE ((`C 1` = 642)) +(4 rows) + +--Testcase 986: +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + c1 | to_tsvector +-----+------------- + 642 | '00642':1 +(1 row) + +-- but if it's in a shippable extension, it can be shipped +ALTER EXTENSION sqlite_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search; +-- however, that doesn't flush the shippability cache, so do a quick reconnect +\c - +--Testcase 995: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + QUERY PLAN +-------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, to_tsvector('custom_search'::regconfig, c3) + Filter: (length(to_tsvector('custom_search'::regconfig, ft1.c3)) > 0) + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" WHERE ((`C 1` = 642)) +(4 rows) + +--Testcase 996: +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + c1 | to_tsvector +-----+------------- + 642 | '00642':1 +(1 row) + +-- =================================================================== +-- ORDER BY queries +-- =================================================================== +-- we should not push order by clause with volatile expressions or unsafe +-- collations +--Testcase 1006: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 ORDER BY ft2.c1, random(); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: c1, c2, c3, c4, c5, c6, c7, c8, (random()) + Sort Key: ft2.c1, (random()) + -> Foreign Scan on public.ft2 + Output: c1, c2, c3, c4, c5, c6, c7, c8, random() + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(6 rows) + +--Testcase 1007: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C"; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text) + Sort Key: ft2.c1, ft2.c3 COLLATE "C" + -> Foreign Scan on public.ft2 + Output: c1, c2, c3, c4, c5, c6, c7, c8, c3 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(6 rows) + +-- Ensure we don't push ORDER BY expressions which are Consts at the UNION +-- child level to the foreign server. +--Testcase 1008: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ( + SELECT 1 AS type,c1 FROM ft1 + UNION ALL + SELECT 2 AS type,c1 FROM ft2 +) a ORDER BY type,c1; + QUERY PLAN +---------------------------------------------------------------------------------- + Merge Append + Sort Key: (1), ft1.c1 + -> Foreign Scan on public.ft1 + Output: 1, ft1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST + -> Foreign Scan on public.ft2 + Output: 2, ft2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST +(8 rows) + +--Testcase 1009: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ( + SELECT 1 AS type,c1 FROM ft1 + UNION ALL + SELECT 2 AS type,c1 FROM ft2 +) a ORDER BY type; + QUERY PLAN +---------------------------------------------------- + Merge Append + Sort Key: (1) + -> Foreign Scan on public.ft1 + Output: 1, ft1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Foreign Scan on public.ft2 + Output: 2, ft2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" +(8 rows) + +-- =================================================================== +-- JOIN queries +-- =================================================================== +-- Analyze ft4 and ft5 so that we have better statistics. These tables do not +-- have use_remote_estimate set. +--ANALYZE ft4; +--ANALYZE ft5; +-- join two tables +--Testcase 65: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2.c1, t1.c3 + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 66: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- join three tables +--Testcase 67: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c2, t3.c3, t1.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3`, r1.`c3` FROM ((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) INNER JOIN main."T 3" r4 ON (((r1.`C 1` = r4.`c1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 68: +SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 22 | 2 | AAA022 + 24 | 4 | AAA024 + 26 | 6 | AAA026 + 28 | 8 | AAA028 + 30 | 0 | AAA030 + 32 | 2 | AAA032 + 34 | 4 | AAA034 + 36 | 6 | AAA036 + 38 | 8 | AAA038 + 40 | 0 | AAA040 +(10 rows) + +-- left outer join +--Testcase 69: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 LEFT JOIN main."T 4" r2 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r1.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 70: +SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c1 +----+---- + 22 | + 24 | 24 + 26 | + 28 | + 30 | 30 + 32 | + 34 | + 36 | 36 + 38 | + 40 | +(10 rows) + +-- left outer join three tables +--Testcase 71: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2.c2, t3.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 72: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +-- left outer join + placement of clauses. +-- clauses within the nullable side are not pulled up, but top level clause on +-- non-nullable side is pushed into non-nullable side +--Testcase 73: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; + QUERY PLAN +----------------------------------------------------------------------------------- + Hash Left Join + Output: t1.c1, t1.c2, ft5.c1, ft5.c2 + Hash Cond: (t1.c1 = ft5.c1) + -> Foreign Scan on public.ft4 t1 + Output: t1.c1, t1.c2, t1.c3 + SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) + -> Hash + Output: ft5.c1, ft5.c2 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.c2 + SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) +(11 rows) + +--Testcase 74: +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; + c1 | c2 | c1 | c2 +----+----+----+---- + 2 | 3 | | + 4 | 5 | | + 6 | 7 | 6 | 7 + 8 | 9 | | +(4 rows) + +-- clauses within the nullable side are not pulled up, but the top level clause +-- on nullable side is not pushed down into nullable side +--Testcase 75: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) + WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; + QUERY PLAN +----------------------------------------------------------------------------------- + Hash Left Join + Output: t1.c1, t1.c2, ft5.c1, ft5.c2 + Hash Cond: (t1.c1 = ft5.c1) + Filter: ((ft5.c1 < 10) OR (ft5.c1 IS NULL)) + -> Foreign Scan on public.ft4 t1 + Output: t1.c1, t1.c2, t1.c3 + SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) + -> Hash + Output: ft5.c1, ft5.c2 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.c2 + SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) +(12 rows) + +--Testcase 76: +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) + WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; + c1 | c2 | c1 | c2 +----+----+----+---- + 2 | 3 | | + 4 | 5 | | + 6 | 7 | 6 | 7 + 8 | 9 | | +(4 rows) + +-- right outer join +--Testcase 77: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r2 LEFT JOIN main."T 4" r1 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r2.`c1` ASC NULLS LAST, r1.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 78: +SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; + c1 | c1 +----+---- + | 22 + 24 | 24 + | 26 + | 28 + 30 | 30 + | 32 + | 34 + 36 | 36 + | 38 + | 40 +(10 rows) + +-- right outer join three tables +--Testcase 79: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2.c2, t3.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 80: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 22 | 2 | AAA022 + 24 | 4 | AAA024 + 26 | 6 | AAA026 + 28 | 8 | AAA028 + 30 | 0 | AAA030 + 32 | 2 | AAA032 + 34 | 4 | AAA034 + 36 | 6 | AAA036 + 38 | 8 | AAA038 + 40 | 0 | AAA040 +(10 rows) + +-- full outer join +--Testcase 81: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Sort + Output: t1.c1, t2.c1 + Sort Key: t1.c1, t2.c1 + -> Merge Full Join + Output: t1.c1, t2.c1 + Merge Cond: (t1.c1 = t2.c1) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(20 rows) + +--Testcase 82: +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; + c1 | c1 +-----+---- + 92 | + 94 | + 96 | 96 + 98 | + 100 | + | 3 + | 9 + | 15 + | 21 + | 27 +(10 rows) + +-- full outer join with restrictions on the joining relations +-- a. the joining relations are both base relations +--Testcase 83: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: ft4.c1, ft5.c1 + Sort Key: ft4.c1, ft5.c1 + -> Hash Full Join + Output: ft4.c1, ft5.c1 + Hash Cond: (ft4.c1 = ft5.c1) + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Hash + Output: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1 + SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(14 rows) + +--Testcase 84: +SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; + c1 | c1 +----+---- + 50 | + 52 | + 54 | 54 + 56 | + 58 | + 60 | 60 + | 51 + | 57 +(8 rows) + +--Testcase 85: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Limit + Output: 1 + -> Merge Full Join + Output: 1 + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT NULL FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Materialize + Output: ft5.c1, ft5.c2, ft5.c3 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.c2, ft5.c3 + SQLite query: SELECT NULL FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(12 rows) + +--Testcase 86: +SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; + ?column? +---------- + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +(10 rows) + +-- b. one of the joining relations is a base relation and the other is a join +-- relation +--Testcase 87: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: ft4.c1, t2.c1, t3.c1 + Sort Key: ft4.c1, t2.c1, t3.c1 + -> Hash Full Join + Output: ft4.c1, t2.c1, t3.c1 + Hash Cond: (t2.c1 = ft4.c1) + -> Foreign Scan + Output: t2.c1, t3.c1 + SQLite query: SELECT r5.`c1`, r6.`c1` FROM (main."T 3" r5 LEFT JOIN main."T 4" r6 ON (((r5.`c1` = r6.`c1`)))) WHERE ((r5.`c1` >= 50)) AND ((r5.`c1` <= 60)) + -> Hash + Output: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(14 rows) + +--Testcase 88: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; + c1 | a | b +----+----+---- + 50 | 50 | + 52 | 52 | + 54 | 54 | 54 + 56 | 56 | + 58 | 58 | + 60 | 60 | 60 +(6 rows) + +-- c. test deparsing the remote query as nested subqueries +--Testcase 89: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Sort + Output: ft4.c1, ft4_1.c1, ft5.c1 + Sort Key: ft4.c1, ft4_1.c1, ft5.c1 + -> Hash Full Join + Output: ft4.c1, ft4_1.c1, ft5.c1 + Hash Cond: (ft4_1.c1 = ft4.c1) + -> Hash Full Join + Output: ft4_1.c1, ft5.c1 + Hash Cond: (ft4_1.c1 = ft5.c1) + Filter: ((ft4_1.c1 IS NULL) OR (ft4_1.c1 IS NOT NULL)) + -> Foreign Scan on public.ft4 ft4_1 + Output: ft4_1.c1, ft4_1.c2, ft4_1.c3 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Hash + Output: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1 + SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Hash + Output: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(23 rows) + +--Testcase 90: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; + c1 | a | b +----+----+---- + 50 | 50 | + 52 | 52 | + 54 | 54 | 54 + 56 | 56 | + 58 | 58 | + 60 | 60 | 60 + | | 51 + | | 57 +(8 rows) + +-- d. test deparsing rowmarked relations as subqueries +--Testcase 91: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + LockRows + Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* + -> Sort + Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* + Sort Key: ft4.c1, ft5.c1 + -> Nested Loop + Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* + -> Foreign Scan on "S 1"."T 3" + Output: "T 3".c1, "T 3".* + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` = 50)) + -> Materialize + Output: ft4.c1, ft4.*, ft5.c1, ft5.* + -> Merge Full Join + Output: ft4.c1, ft4.*, ft5.c1, ft5.* + Merge Cond: (ft4.c1 = ft5.c1) + Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL)) + -> Sort + Output: ft4.c1, ft4.* + Sort Key: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.* + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Sort + Output: ft5.c1, ft5.* + Sort Key: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.* + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(28 rows) + +--Testcase 92: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; + c1 | a | b +----+----+---- + 50 | 50 | + 50 | 52 | + 50 | 54 | 54 + 50 | 56 | + 50 | 58 | + 50 | 60 | 60 + 50 | | 51 + 50 | | 57 +(8 rows) + +-- full outer join + inner join +--Testcase 93: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t3.c1 + -> Sort + Output: t1.c1, t2.c1, t3.c1 + Sort Key: t1.c1, t2.c1, t3.c1 + -> Hash Full Join + Output: t1.c1, t2.c1, t3.c1 + Hash Cond: (t3.c1 = t2.c1) + -> Foreign Scan on public.ft4 t3 + Output: t3.c1, t3.c2, t3.c3 + SQLite query: SELECT `c1` FROM main."T 3" + -> Hash + Output: t1.c1, t2.c1 + -> Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 INNER JOIN main."T 4" r2 ON (((r1.`c1` = (r2.`c1` + 1))) AND ((r1.`c1` >= 50)) AND ((r1.`c1` <= 60)))) +(16 rows) + +--Testcase 94: +SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; + c1 | c1 | c1 +----+----+---- + 52 | 51 | + 58 | 57 | + | | 2 + | | 4 + | | 6 + | | 8 + | | 10 + | | 12 + | | 14 + | | 16 +(10 rows) + +-- full outer join three tables +--Testcase 95: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t3.c3 + -> Hash Full Join + Output: t1.c1, t2.c2, t3.c3 + Hash Cond: (t2.c1 = t3.c1) + -> Hash Full Join + Output: t1.c1, t2.c2, t2.c1 + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft2 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Hash + Output: t2.c2, t2.c1 + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Hash + Output: t3.c3, t3.c1 + -> Foreign Scan on public.ft4 t3 + Output: t3.c3, t3.c1 + SQLite query: SELECT `c1`, `c3` FROM main."T 3" +(21 rows) + +--Testcase 96: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +-- full outer join + right outer join +--Testcase 97: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2.c2, t3.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 98: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 22 | 2 | AAA022 + 24 | 4 | AAA024 + 26 | 6 | AAA026 + 28 | 8 | AAA028 + 30 | 0 | AAA030 + 32 | 2 | AAA032 + 34 | 4 | AAA034 + 36 | 6 | AAA036 + 38 | 8 | AAA038 + 40 | 0 | AAA040 +(10 rows) + +-- right outer join + full outer join +--Testcase 99: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t3.c3 + -> Hash Full Join + Output: t1.c1, t2.c2, t3.c3 + Hash Cond: (t2.c1 = t3.c1) + -> Nested Loop Left Join + Output: t2.c2, t2.c1, t1.c1 + Join Filter: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Materialize + Output: t1.c1 + -> Foreign Scan on public.ft2 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Hash + Output: t3.c3, t3.c1 + -> Foreign Scan on public.ft4 t3 + Output: t3.c3, t3.c1 + SQLite query: SELECT `c1`, `c3` FROM main."T 3" +(21 rows) + +--Testcase 100: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +-- full outer join + left outer join +--Testcase 101: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t3.c3 + -> Nested Loop Left Join + Output: t1.c1, t2.c2, t3.c3 + Join Filter: (t2.c1 = t3.c1) + -> Hash Full Join + Output: t1.c1, t2.c2, t2.c1 + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft2 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Hash + Output: t2.c2, t2.c1 + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Materialize + Output: t3.c3, t3.c1 + -> Foreign Scan on public.ft4 t3 + Output: t3.c3, t3.c1 + SQLite query: SELECT `c1`, `c3` FROM main."T 3" +(21 rows) + +--Testcase 102: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +-- left outer join + full outer join +--Testcase 103: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t3.c3 + -> Hash Full Join + Output: t1.c1, t2.c2, t3.c3 + Hash Cond: (t2.c1 = t3.c1) + -> Nested Loop Left Join + Output: t1.c1, t2.c2, t2.c1 + Join Filter: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft2 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Materialize + Output: t2.c2, t2.c1 + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Hash + Output: t3.c3, t3.c1 + -> Foreign Scan on public.ft4 t3 + Output: t3.c3, t3.c1 + SQLite query: SELECT `c1`, `c3` FROM main."T 3" +(21 rows) + +--Testcase 104: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +--Testcase 775: +SET enable_memoize TO off; +-- right outer join + left outer join +--Testcase 105: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, t2.c2, t3.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 106: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 11 | 1 | + 12 | 2 | AAA012 + 13 | 3 | + 14 | 4 | AAA014 + 15 | 5 | + 16 | 6 | AAA016 + 17 | 7 | + 18 | 8 | AAA018 + 19 | 9 | + 20 | 0 | AAA020 +(10 rows) + +--Testcase 776: +RESET enable_memoize; +-- left outer join + right outer join +--Testcase 107: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c2, t3.c3 + SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM (main."T 3" r4 LEFT JOIN (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 108: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; + c1 | c2 | c3 +----+----+-------- + 22 | 2 | AAA022 + 24 | 4 | AAA024 + 26 | 6 | AAA026 + 28 | 8 | AAA028 + 30 | 0 | AAA030 + 32 | 2 | AAA032 + 34 | 4 | AAA034 + 36 | 6 | AAA036 + 38 | 8 | AAA038 + 40 | 0 | AAA040 +(10 rows) + +-- full outer join + WHERE clause, only matched rows +--Testcase 109: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Sort + Output: t1.c1, t2.c1 + Sort Key: t1.c1, t2.c1 + -> Merge Full Join + Output: t1.c1, t2.c1 + Merge Cond: (t1.c1 = t2.c1) + Filter: ((t1.c1 = t2.c1) OR (t1.c1 IS NULL)) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(21 rows) + +--Testcase 110: +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c1 +----+---- + 66 | 66 + 72 | 72 + 78 | 78 + 84 | 84 + 90 | 90 + 96 | 96 + | 3 + | 9 + | 15 + | 21 +(10 rows) + +-- full outer join + WHERE clause with shippable extensions set +--Testcase 504: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t1.c3 + -> Hash Full Join + Output: t1.c1, t2.c2, t1.c3 + Hash Cond: (t2.c1 = t1.c1) + Filter: (sqlite_fdw_abs(t1.c1) > 0) + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Hash + Output: t1.c1, t1.c3 + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3 + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" +(14 rows) + +--ALTER SERVER sqlite_svr2 OPTIONS (DROP extensions); +-- full outer join + WHERE clause with shippable extensions not set +--Testcase 505: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c2, t1.c3 + -> Hash Full Join + Output: t1.c1, t2.c2, t1.c3 + Hash Cond: (t2.c1 = t1.c1) + Filter: (sqlite_fdw_abs(t1.c1) > 0) + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Hash + Output: t1.c1, t1.c3 + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3 + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" +(14 rows) + +--Testcase 777: +-- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +-- join two tables with FOR UPDATE clause +-- tests whole-row reference for row marks +--Testcase 111: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> LockRows + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> Foreign Scan + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST + -> Sort + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 + -> Hash Join + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST + -> Hash + Output: t2.c1, t2.* + -> Foreign Scan on public.ft2 t2 + Output: t2.c1, t2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(21 rows) + +--Testcase 112: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +--Testcase 113: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> LockRows + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> Foreign Scan + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST + -> Sort + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 + -> Hash Join + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST + -> Hash + Output: t2.c1, t2.* + -> Foreign Scan on public.ft2 t2 + Output: t2.c1, t2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(21 rows) + +--Testcase 114: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- join two tables with FOR SHARE clause +--Testcase 115: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> LockRows + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> Foreign Scan + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST + -> Sort + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 + -> Hash Join + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST + -> Hash + Output: t2.c1, t2.* + -> Foreign Scan on public.ft2 t2 + Output: t2.c1, t2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(21 rows) + +--Testcase 116: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +--Testcase 117: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> LockRows + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + -> Foreign Scan + Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST + -> Sort + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 + -> Hash Join + Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3, t1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST + -> Hash + Output: t2.c1, t2.* + -> Foreign Scan on public.ft2 t2 + Output: t2.c1, t2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(21 rows) + +--Testcase 118: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- join in CTE +--Testcase 119: +EXPLAIN (VERBOSE, COSTS OFF) +WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------ + Limit + Output: t.c1_1, t.c2_1, t.c1_3 + CTE t + -> Merge Join + Output: t1.c1, t1.c3, t2.c1 + Merge Cond: (t1.c1 = t2.c1) + -> Sort + Output: t1.c1, t1.c3 + Sort Key: t1.c1 + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c3 + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft2 t2 + Output: t2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Sort + Output: t.c1_1, t.c2_1, t.c1_3 + Sort Key: t.c1_3, t.c1_1 + -> CTE Scan on t + Output: t.c1_1, t.c2_1, t.c1_3 +(23 rows) + +--Testcase 120: +WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; + c1_1 | c2_1 +------+------ + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- ctid with whole-row reference +--Testcase 121: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3 + SQLite query: SELECT r1.`ctid`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r1.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +-- SEMI JOIN +--Testcase 122: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1 + SQLite query: SELECT r1.`C 1` FROM main."T 1" r1 WHERE EXISTS (SELECT NULL FROM main."T 1" r2 WHERE ((r1.`C 1` = r2.`C 1`))) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 123: +SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; + c1 +----- + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 +(10 rows) + +-- ANTI JOIN, not pushed down +--Testcase 124: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------- + Limit + Output: t1.c1 + -> Nested Loop Anti Join + Output: t1.c1 + Join Filter: (t1.c1 = t2.c2) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST + -> Materialize + Output: t2.c2 + -> Foreign Scan on public.ft2 t2 + Output: t2.c2 + SQLite query: SELECT `c2` FROM main."T 1" +(13 rows) + +--Testcase 125: +SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; + c1 +----- + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 +(10 rows) + +-- CROSS JOIN can be pushed down +--Testcase 126: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (TRUE)) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 127: +SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + c1 | c1 +----+----- + 1 | 101 + 1 | 102 + 1 | 103 + 1 | 104 + 1 | 105 + 1 | 106 + 1 | 107 + 1 | 108 + 1 | 109 + 1 | 110 +(10 rows) + +-- different server, not pushed down. No result expected. +--Testcase 128: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Merge Join + Output: t1.c1, t2.c1 + Merge Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft5 t1 + Output: t1.c1, t1.c2, t1.c3 + SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST + -> Materialize + Output: t2.c1, t2.c2, t2.c3 + -> Foreign Scan on public.ft6 t2 + Output: t2.c1, t2.c2, t2.c3 + SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST +(13 rows) + +--Testcase 129: +SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + c1 | c1 +----+---- +(0 rows) + +-- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS +-- JOIN since c8 in both tables has same value. +--Testcase 130: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`c8` = r2.`c8`)))) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 131: +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; + c1 | c1 +----+----- + 1 | 101 + 1 | 102 + 1 | 103 + 1 | 104 + 1 | 105 + 1 | 106 + 1 | 107 + 1 | 108 + 1 | 109 + 1 | 110 +(10 rows) + +-- unsafe conditions on one side (c8 has a UDT), not pushed down. +--Testcase 132: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1, t1.c3 + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) WHERE ((r1.`c8` = 'foo')) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 133: +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- join where unsafe to pushdown condition in WHERE clause has a column not +-- in the SELECT clause. In this test unsafe clause needs to have column +-- references from both joining sides so that the clause is not pushed down +-- into one of the joining sides. +--Testcase 134: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1, t1.c3 + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c8` = r2.`c8`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 +(3 rows) + +--Testcase 135: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + c1 | c1 +-----+----- + 101 | 101 + 102 | 102 + 103 | 103 + 104 | 104 + 105 | 105 + 106 | 106 + 107 | 107 + 108 | 108 + 109 | 109 + 110 | 110 +(10 rows) + +-- Aggregate after UNION, for testing setrefs +--Testcase 136: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, (avg((t1.c1 + t2.c1))) + -> GroupAggregate + Output: t1.c1, avg((t1.c1 + t2.c1)) + Group Key: t1.c1 + -> Unique + Output: t1.c1, t2.c1 + -> Sort + Output: t1.c1, t2.c1 + Sort Key: t1.c1, t2.c1 + -> Append + -> Foreign Scan + Output: t1.c1, t2.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`C 1` ASC NULLS LAST + -> Foreign Scan + Output: t1_1.c1, t2_1.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`C 1` ASC NULLS LAST +(17 rows) + +--Testcase 137: +SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; + t1c1 | avg +------+---------------------- + 101 | 202.0000000000000000 + 102 | 204.0000000000000000 + 103 | 206.0000000000000000 + 104 | 208.0000000000000000 + 105 | 210.0000000000000000 + 106 | 212.0000000000000000 + 107 | 214.0000000000000000 + 108 | 216.0000000000000000 + 109 | 218.0000000000000000 + 110 | 220.0000000000000000 +(10 rows) + +-- join with lateral reference +--Testcase 138: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1."C 1" + -> Nested Loop + Output: t1."C 1" + -> Foreign Scan on "S 1"."T 1" t1 + Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST + -> Unique + Output: t2.c1, t3.c1 + -> Foreign Scan + Output: t2.c1, t3.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = ?)))) ORDER BY r1.`C 1` ASC NULLS LAST +(12 rows) + +--Testcase 139: +SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; + C 1 +----- + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +(10 rows) + +-- join with pseudoconstant quals +--Testcase 997: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1, t1.c3 + -> Result + Output: t1.c1, t2.c1, t1.c3 + One-Time Filter: (CURRENT_USER = SESSION_USER) + -> Foreign Scan + Output: t1.c1, t1.c3, t2.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST +(8 rows) + +-- non-Var items in targetlist of the nullable rel of a join preventing +-- push-down in some cases +-- unable to push {ft1, ft2} +--Testcase 140: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Nested Loop Left Join + Output: (13), ft2.c1 + Join Filter: (13 = ft2.c1) + -> Foreign Scan on public.ft2 + Output: ft2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` >= 10)) AND ((`C 1` <= 15)) + -> Materialize + Output: (13) + -> Foreign Scan on public.ft1 + Output: 13 + SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 13)) +(11 rows) + +--Testcase 141: +SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; + a | c1 +----+---- + | 10 + | 11 + | 12 + 13 | 13 + | 14 + | 15 +(6 rows) + +-- ok to push {ft1, ft2} but not {ft1, ft2, ft4} +--Testcase 142: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; + QUERY PLAN +------------------------------------------------------------------------------------------------- + Hash Right Join + Output: ft4.c1, (13), ft1.c1, ft2.c1 + Hash Cond: (ft1.c1 = ft4.c1) + -> Nested Loop + Output: ft1.c1, ft2.c1, 13 + -> Foreign Scan on public.ft1 + Output: ft1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) + -> Materialize + Output: ft2.c1 + -> Foreign Scan on public.ft2 + Output: ft2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) + -> Hash + Output: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 10)) AND ((`c1` <= 15)) +(18 rows) + +--Testcase 143: +SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; + c1 | a | b | c +----+----+----+---- + 12 | 13 | 12 | 12 + 10 | | | + 14 | | | +(3 rows) + +-- join with nullable side with some columns with null values +--Testcase 144: +UPDATE ft5 SET c3 = null where c1 % 9 = 0; +--Testcase 145: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 + SQLite query: SELECT CASE WHEN ( r1.`c1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) THEN ("(" || COALESCE(r1.`c1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '')|| ")") END, r1.`c1`, r1.`c2`, r1.`c3`, r2.`c1`, r2.`c2` FROM (main."T 4" r1 INNER JOIN main."T 3" r2 ON (((r1.`c1` = r2.`c1`)) AND ((r2.`c1` >= 10)) AND ((r2.`c1` <= 30)))) ORDER BY r1.`c1` ASC NULLS LAST +(3 rows) + +--Testcase 146: +SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; + ft5 | c1 | c2 | c3 | c1 | c2 +----------------+----+----+--------+----+---- + (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13 + (18,19,) | 18 | 19 | | 18 | 19 + (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25 + (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31 +(4 rows) + +-- multi-way join involving multiple merge joins +-- (this case used to have EPQ-related planning problems) +--Testcase 506: +CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1)); +--Testcase 507: +INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; +ANALYZE local_tbl; +--Testcase 778: +SET enable_nestloop TO false; +--Testcase 779: +SET enable_hashjoin TO false; +--Testcase 147: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 + AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + LockRows + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid + Merge Cond: (local_tbl.c1 = ft1.c2) + -> Index Scan using local_tbl_pkey on public.local_tbl + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + Sort Key: ft1.c2 + -> Foreign Scan + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r3.`c1`, r3.`c2`, r3.`c3`, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END, r4.`c1`, r4.`c2`, r4.`c3`, CASE WHEN ( r4.`c1` IS NOT NULL) OR ( r4.`c2` IS NOT NULL) OR ( r4.`c3` IS NOT NULL) THEN ("(" || COALESCE(r4.`c1`, '') || "," || COALESCE(r4.`c2`, '') || "," || COALESCE(r4.`c3`, '')|| ")") END FROM (((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r2.`C 1` < 100)) AND ((r1.`C 1` < 100)))) INNER JOIN main."T 3" r3 ON (((r1.`c2` = r3.`c1`)))) INNER JOIN main."T 4" r4 ON (((r1.`c2` = r4.`c1`)))) + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + Merge Cond: (ft1.c2 = ft5.c1) + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* + Sort Key: ft1.c2 + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* + Merge Cond: (ft1.c2 = ft4.c1) + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* + Sort Key: ft1.c2 + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* + Merge Cond: (ft1.c1 = ft2.c1) + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + Sort Key: ft1.c1 + -> Foreign Scan on public.ft1 + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) + -> Sort + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* + Sort Key: ft2.c1 + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) + -> Sort + Output: ft4.c1, ft4.c2, ft4.c3, ft4.* + Sort Key: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3, ft4.* + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" + -> Sort + Output: ft5.c1, ft5.c2, ft5.c3, ft5.* + Sort Key: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.c2, ft5.c3, ft5.* + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" +(52 rows) + +--Testcase 148: +SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 + AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 ORDER BY ft1.c1 FOR UPDATE; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 | c1 | c2 | c3 +----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------ + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 +(10 rows) + +--Testcase 780: +RESET enable_nestloop; +--Testcase 781: +RESET enable_hashjoin; +-- test that add_paths_with_pathkeys_for_rel() arranges for the epq_path to +-- return columns needed by the parent ForeignScan node +-- This does not work as SQLite FDW does not support use_remote_estimate +--Testcase 987: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.*, COALESCE(ft1.c3 || ft2.c3, 'foobar') FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100)) ss ON (local_tbl.c1 = ss.c1) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + LockRows + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)), local_tbl.ctid, ft1.*, ft2.* + -> Merge Left Join + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)), local_tbl.ctid, ft1.*, ft2.* + Merge Cond: (local_tbl.c1 = ft1.c1) + -> Index Scan using local_tbl_pkey on public.local_tbl + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)) + Sort Key: ft1.c1 + -> Foreign Scan + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, COALESCE((ft1.c3 || ft2.c3), 'foobar'::text) + SQLite query: SELECT r4.`C 1`, r4.`c2`, r4.`c3`, r4.`c4`, r4.`c5`, r4.`c6`, r4.`c7`, r4.`c8`, CASE WHEN ( r4.`C 1` IS NOT NULL) OR ( r4.`c2` IS NOT NULL) OR ( r4.`c3` IS NOT NULL) OR ( r4.`c4` IS NOT NULL) OR ( r4.`c5` IS NOT NULL) OR ( r4.`c6` IS NOT NULL) OR ( r4.`c7` IS NOT NULL) OR ( r4.`c8` IS NOT NULL) THEN ("(" || COALESCE(r4.`C 1`, '') || "," || COALESCE(r4.`c2`, '') || "," || COALESCE(r4.`c3`, '') || "," || COALESCE(r4.`c4`, '') || "," || COALESCE(r4.`c5`, '') || "," || COALESCE(r4.`c6`, '') || "," || COALESCE(r4.`c7`, '') || "," || COALESCE(r4.`c8`, '')|| ")") END, CASE WHEN ( r5.`C 1` IS NOT NULL) OR ( r5.`c2` IS NOT NULL) OR ( r5.`c3` IS NOT NULL) OR ( r5.`c4` IS NOT NULL) OR ( r5.`c5` IS NOT NULL) OR ( r5.`c6` IS NOT NULL) OR ( r5.`c7` IS NOT NULL) OR ( r5.`c8` IS NOT NULL) THEN ("(" || COALESCE(r5.`C 1`, '') || "," || COALESCE(r5.`c2`, '') || "," || COALESCE(r5.`c3`, '') || "," || COALESCE(r5.`c4`, '') || "," || COALESCE(r5.`c5`, '') || "," || COALESCE(r5.`c6`, '') || "," || COALESCE(r5.`c7`, '') || "," || COALESCE(r5.`c8`, '')|| ")") END, r5.`c3` FROM (main."T 1" r4 INNER JOIN main."T 1" r5 ON (((r4.`C 1` = r5.`C 1`)) AND ((r4.`C 1` < 100)))) + -> Hash Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c3 + Hash Cond: (ft1.c1 = ft2.c1) + -> Foreign Scan on public.ft1 + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) + -> Hash + Output: ft2.*, ft2.c1, ft2.c3 + -> Foreign Scan on public.ft2 + Output: ft2.*, ft2.c1, ft2.c3 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(24 rows) + +-- ALTER SERVER loopback OPTIONS (DROP extensions); +-- ALTER SERVER loopback OPTIONS (ADD fdw_startup_cost '10000.0'); +--Testcase 988: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100 AND (ft1.c1 - sqlite_fdw_abs(ft2.c2)) = 0)) ss ON (local_tbl.c3 = ss.c3) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + LockRows + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, local_tbl.ctid, ft1.*, ft2.* + -> Nested Loop Left Join + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, local_tbl.ctid, ft1.*, ft2.* + Join Filter: (local_tbl.c3 = ft1.c3) + -> Index Scan using local_tbl_pkey on public.local_tbl + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid + -> Materialize + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.* + -> Foreign Scan + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.* + Filter: ((ft1.c1 - sqlite_fdw_abs(ft2.c2)) = 0) + SQLite query: SELECT r4.`C 1`, r4.`c2`, r4.`c3`, r4.`c4`, r4.`c5`, r4.`c6`, r4.`c7`, r4.`c8`, CASE WHEN ( r4.`C 1` IS NOT NULL) OR ( r4.`c2` IS NOT NULL) OR ( r4.`c3` IS NOT NULL) OR ( r4.`c4` IS NOT NULL) OR ( r4.`c5` IS NOT NULL) OR ( r4.`c6` IS NOT NULL) OR ( r4.`c7` IS NOT NULL) OR ( r4.`c8` IS NOT NULL) THEN ("(" || COALESCE(r4.`C 1`, '') || "," || COALESCE(r4.`c2`, '') || "," || COALESCE(r4.`c3`, '') || "," || COALESCE(r4.`c4`, '') || "," || COALESCE(r4.`c5`, '') || "," || COALESCE(r4.`c6`, '') || "," || COALESCE(r4.`c7`, '') || "," || COALESCE(r4.`c8`, '')|| ")") END, CASE WHEN ( r5.`C 1` IS NOT NULL) OR ( r5.`c2` IS NOT NULL) OR ( r5.`c3` IS NOT NULL) OR ( r5.`c4` IS NOT NULL) OR ( r5.`c5` IS NOT NULL) OR ( r5.`c6` IS NOT NULL) OR ( r5.`c7` IS NOT NULL) OR ( r5.`c8` IS NOT NULL) THEN ("(" || COALESCE(r5.`C 1`, '') || "," || COALESCE(r5.`c2`, '') || "," || COALESCE(r5.`c3`, '') || "," || COALESCE(r5.`c4`, '') || "," || COALESCE(r5.`c5`, '') || "," || COALESCE(r5.`c6`, '') || "," || COALESCE(r5.`c7`, '') || "," || COALESCE(r5.`c8`, '')|| ")") END, r5.`c2` FROM (main."T 1" r4 INNER JOIN main."T 1" r5 ON (((r4.`C 1` = r5.`C 1`)) AND ((r4.`C 1` < 100)))) + -> Hash Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c2 + Hash Cond: (ft1.c1 = ft2.c1) + -> Foreign Scan on public.ft1 + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) + -> Hash + Output: ft2.*, ft2.c1, ft2.c2 + -> Foreign Scan on public.ft2 + Output: ft2.*, ft2.c1, ft2.c2 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(24 rows) + +-- ALTER SERVER loopback OPTIONS (DROP fdw_startup_cost); +-- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +--DROP TABLE local_tbl; +-- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. +--Testcase 508: +CREATE ROLE regress_view_owner SUPERUSER; +--Testcase 509: +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +GRANT SELECT ON ft4 TO regress_view_owner; +GRANT SELECT ON ft5 TO regress_view_owner; +--Testcase 510: +CREATE VIEW v4 AS SELECT * FROM ft4; +--Testcase 511: +CREATE VIEW v5 AS SELECT * FROM ft5; +--Testcase 782: +ALTER VIEW v5 OWNER TO regress_view_owner; +--Testcase 149: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, different view owners + QUERY PLAN +--------------------------------------------------------------------------- + Limit + Output: ft4.c1, ft5.c2, ft5.c1 + -> Incremental Sort + Output: ft4.c1, ft5.c2, ft5.c1 + Sort Key: ft4.c1, ft5.c1 + Presorted Key: ft4.c1 + -> Merge Left Join + Output: ft4.c1, ft5.c2, ft5.c1 + Merge Cond: (ft4.c1 = ft5.c1) + -> Sort + Output: ft4.c1 + Sort Key: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: ft5.c2, ft5.c1 + Sort Key: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c2, ft5.c1 + SQLite query: SELECT `c1`, `c2` FROM main."T 4" +(21 rows) + +--Testcase 150: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c2 +----+---- + 22 | + 24 | 25 + 26 | + 28 | + 30 | 31 + 32 | + 34 | + 36 | 37 + 38 | + 40 | +(10 rows) + +--Testcase 783: +ALTER VIEW v4 OWNER TO regress_view_owner; +--Testcase 151: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft4.c1, ft5.c2, ft5.c1 + SQLite query: SELECT r4.`c1`, r5.`c2`, r5.`c1` FROM (main."T 3" r4 LEFT JOIN main."T 4" r5 ON (((r4.`c1` = r5.`c1`)))) ORDER BY r4.`c1` ASC NULLS LAST, r5.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 152: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c2 +----+---- + 22 | + 24 | 25 + 26 | + 28 | + 30 | 31 + 32 | + 34 | + 36 | 37 + 38 | + 40 | +(10 rows) + +--Testcase 153: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, view owner not current user + QUERY PLAN +--------------------------------------------------------------------------- + Limit + Output: ft4.c1, t2.c2, t2.c1 + -> Incremental Sort + Output: ft4.c1, t2.c2, t2.c1 + Sort Key: ft4.c1, t2.c1 + Presorted Key: ft4.c1 + -> Merge Left Join + Output: ft4.c1, t2.c2, t2.c1 + Merge Cond: (ft4.c1 = t2.c1) + -> Sort + Output: ft4.c1 + Sort Key: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c2, t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `c1`, `c2` FROM main."T 4" +(21 rows) + +--Testcase 154: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c2 +----+---- + 22 | + 24 | 25 + 26 | + 28 | + 30 | 31 + 32 | + 34 | + 36 | 37 + 38 | + 40 | +(10 rows) + +--Testcase 784: +ALTER VIEW v4 OWNER TO CURRENT_USER; +--Testcase 155: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft4.c1, t2.c2, t2.c1 + SQLite query: SELECT r4.`c1`, r2.`c2`, r2.`c1` FROM (main."T 3" r4 LEFT JOIN main."T 4" r2 ON (((r4.`c1` = r2.`c1`)))) ORDER BY r4.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 +(3 rows) + +--Testcase 156: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + c1 | c2 +----+---- + 22 | + 24 | 25 + 26 | + 28 | + 30 | 31 + 32 | + 34 | + 36 | 37 + 38 | + 40 | +(10 rows) + +--Testcase 785: +ALTER VIEW v4 OWNER TO regress_view_owner; +-- Comment out these test cases. +-- sqlite_fdw does not need to getUserMapping in planning phase, +-- so it is unable to check userid to use when querying the remote table is correctly propagated into foreign rels. +-- -- ==================================================================== +-- -- Check that userid to use when querying the remote table is correctly +-- -- propagated into foreign rels present in subqueries under an UNION ALL +-- -- ==================================================================== +-- CREATE ROLE regress_view_owner_another; +-- ALTER VIEW v4 OWNER TO regress_view_owner_another; +-- GRANT SELECT ON ft4 TO regress_view_owner_another; +-- ALTER FOREIGN TABLE ft4 OPTIONS (ADD use_remote_estimate 'true'); +-- -- The following should query the remote backing table of ft4 as user +-- -- regress_view_owner_another, the view owner, though it fails as expected +-- -- due to the lack of a user mapping for that user. +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4; +-- -- Likewise, but with the query under an UNION ALL +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4); +-- -- Should not get that error once a user mapping is created +-- CREATE USER MAPPING FOR regress_view_owner_another SERVER loopback OPTIONS (password_required 'false'); +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4; +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4); +-- DROP USER MAPPING FOR regress_view_owner_another SERVER loopback; +-- DROP OWNED BY regress_view_owner_another; +-- DROP ROLE regress_view_owner_another; +-- ALTER FOREIGN TABLE ft4 OPTIONS (SET use_remote_estimate 'false'); +-- cleanup +--Testcase 512: +DROP OWNED BY regress_view_owner; +--Testcase 513: +DROP ROLE regress_view_owner; +-- =================================================================== +-- Aggregate and grouping queries +-- =================================================================== +-- Simple aggregates +--Testcase 157: +explain (verbose, costs off) +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------- + Result + Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 + -> Sort + Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 + Sort Key: (count(ft1.c6)), (sum(ft1.c1)) + -> GroupAggregate + Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c6, c1, c2 + SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST +(11 rows) + +--Testcase 158: +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; + count | sum | avg | min | max | stddev | sum2 +-------+-------+----------------------+-----+------+--------+------- + 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 + 100 | 49700 | 497.0000000000000000 | 2 | 992 | 0 | 49700 + 100 | 49800 | 498.0000000000000000 | 3 | 993 | 0 | 49800 + 100 | 49900 | 499.0000000000000000 | 4 | 994 | 0 | 49900 + 100 | 50500 | 505.0000000000000000 | 0 | 1000 | 0 | 50500 +(5 rows) + +--Testcase 514: +explain (verbose, costs off) +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), (((sum(c1)) * ((random() <= '1'::double precision))::integer)), c2 + -> Result + Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 + -> Sort + Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 + Sort Key: (count(ft1.c6)), (sum(ft1.c1)) + -> GroupAggregate + Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c6, c1, c2 + SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST +(13 rows) + +--Testcase 515: +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; + count | sum | avg | min | max | stddev | sum2 +-------+-------+----------------------+-----+-----+--------+------- + 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 +(1 row) + +-- Aggregate is not pushed down as aggregation contains random() +--Testcase 159: +explain (verbose, costs off) +select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1; + QUERY PLAN +------------------------------------------------------------------------------- + Aggregate + Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1) + -> Foreign Scan on public.ft1 + Output: c1 + SQLite query: SELECT `C 1` FROM main."T 1" +(5 rows) + +-- Aggregate over join query +--Testcase 160: +explain (verbose, costs off) +select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: (count(*)), (sum(t1.c1)), (avg(t2.c1)) + SQLite query: SELECT count(*), sum(r1.`C 1`), avg(r2.`C 1`) FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r2.`c2` = 6)) AND ((r1.`c2` = 6)))) +(3 rows) + +--Testcase 161: +select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; + count | sum | avg +-------+---------+----- + 10000 | 5010000 | 501 +(1 row) + +-- Not pushed down due to local conditions present in underneath input rel +--Testcase 162: +explain (verbose, costs off) +select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: sum(t1.c1), count(t2.c1) + -> Merge Join + Output: t1.c1, t2.c1 + Merge Cond: (t1.c1 = t2.c1) + Join Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft1 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft2 t2 + Output: t2.c1 + SQLite query: SELECT `C 1` FROM main."T 1" +(18 rows) + +-- GROUP BY clause having expressions +--Testcase 163: +explain (verbose, costs off) +select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ((c2 / 2)), ((sum(c2) * (c2 / 2))) + SQLite query: SELECT (`c2` / 2), (sum(`c2`) * (`c2` / 2)) FROM main."T 1" GROUP BY 1 ORDER BY (`c2` / 2) ASC NULLS LAST +(3 rows) + +--Testcase 164: +select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; + ?column? | ?column? +----------+---------- + 0 | 0 + 1 | 500 + 2 | 1800 + 3 | 3900 + 4 | 6800 +(5 rows) + +-- Aggregates in subquery are pushed down. +set enable_incremental_sort = off; +--Testcase 165: +explain (verbose, costs off) +select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; + QUERY PLAN +------------------------------------------------------------------------------- + Aggregate + Output: count(ft1.c2), sum(ft1.c2) + -> Sort + Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision)) + Sort Key: ft1.c2, (sum(ft1.c1)) + -> HashAggregate + Output: ft1.c2, sum(ft1.c1), (sqrt((ft1.c1)::double precision)) + Group Key: ft1.c2, sqrt((ft1.c1)::double precision) + -> Foreign Scan on public.ft1 + Output: ft1.c2, sqrt((ft1.c1)::double precision), ft1.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" +(11 rows) + +--Testcase 166: +select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; + count | sum +-------+------ + 1000 | 4500 +(1 row) + +reset enable_incremental_sort; +-- Aggregate is still pushed down by taking unshippable expression out +--Testcase 167: +explain (verbose, costs off) +select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Sort + Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2 + Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2)) + -> Foreign Scan + Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2 + SQLite query: SELECT (sum(`C 1`) * `c2`), `c2` FROM main."T 1" GROUP BY 2 +(6 rows) + +--Testcase 168: +select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; + sum1 | sum2 +------+-------- + 0 | 0 + 1 | 49600 + 2 | 99400 + 3 | 149400 + 4 | 199600 + 5 | 250000 + 6 | 300600 + 7 | 351400 + 8 | 402400 + 9 | 453600 +(10 rows) + +-- Aggregate with unshippable GROUP BY clause are not pushed +--Testcase 169: +explain (verbose, costs off) +select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1; + QUERY PLAN +------------------------------------------------------------------------------ + Sort + Output: ((c2 * ((random() <= '1'::double precision))::integer)) + Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer)) + -> HashAggregate + Output: ((c2 * ((random() <= '1'::double precision))::integer)) + Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer) + -> Foreign Scan on public.ft2 + Output: (c2 * ((random() <= '1'::double precision))::integer) + SQLite query: SELECT `c2` FROM main."T 1" +(9 rows) + +-- GROUP BY clause in various forms, cardinal, alias and constant expression +--Testcase 516: +explain (verbose, costs off) +select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (count(c2)), c2, 5, 7.0, 9 + SQLite query: SELECT count(`c2`), `c2`, 5, 7.0, 9 FROM main."T 1" GROUP BY 2, 3, 5 ORDER BY `c2` ASC NULLS LAST +(3 rows) + +--Testcase 517: +select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; + w | x | y | z +-----+---+---+----- + 100 | 0 | 5 | 7.0 + 100 | 1 | 5 | 7.0 + 100 | 2 | 5 | 7.0 + 100 | 3 | 5 | 7.0 + 100 | 4 | 5 | 7.0 + 100 | 5 | 5 | 7.0 + 100 | 6 | 5 | 7.0 + 100 | 7 | 5 | 7.0 + 100 | 8 | 5 | 7.0 + 100 | 9 | 5 | 7.0 +(10 rows) + +-- GROUP BY clause referring to same column multiple times +-- Also, ORDER BY contains an aggregate function +--Testcase 170: +--Testcase 966: +explain (verbose, costs off) +select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: c2, c2, (sum(c1)) + SQLite query: SELECT `c2`, `c2`, sum(`C 1`) FROM main."T 1" WHERE ((`c2` > 6)) GROUP BY 1, 2 ORDER BY sum(`C 1`) ASC NULLS LAST +(3 rows) + +--Testcase 171: +select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); + c2 | c2 +----+---- + 7 | 7 + 8 | 8 + 9 | 9 +(3 rows) + +-- Testing HAVING clause shippability +--Testcase 172: +explain (verbose, costs off) +select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: c2, (sum(c1)) + SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 HAVING ((avg(`C 1`) < 500)) AND ((sum(`C 1`) < 49800)) ORDER BY `c2` ASC NULLS LAST +(3 rows) + +--Testcase 173: +select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; + c2 | sum +----+------- + 1 | 49600 + 2 | 49700 +(2 rows) + +-- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down +--Testcase 174: +explain (verbose, costs off) +select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*) + -> HashAggregate + Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision)) + Group Key: ft1.c5, sqrt((ft1.c2)::double precision) + Filter: ((avg(ft1.c1) < '500'::numeric) AND ((((avg(ft1.c1) / avg(ft1.c1)))::double precision * random()) <= '1'::double precision)) + -> Foreign Scan on public.ft1 + Output: ft1.c5, sqrt((ft1.c2)::double precision), ft1.c1 + SQLite query: SELECT `C 1`, `c2`, `c5` FROM main."T 1" +(9 rows) + +--Testcase 175: +select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; + count +------- + 49 +(1 row) + +-- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down +--Testcase 176: +explain (verbose, costs off) +select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Sort + Output: (sum(c1)), c2 + Sort Key: (sum(ft1.c1)) + -> GroupAggregate + Output: sum(c1), c2 + Group Key: ft1.c2 + Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric) + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(10 rows) + +-- Remote aggregate in combination with a local Param (for the output +-- of an initplan) can be trouble, per bug #15781 +--Testcase 518: +explain (verbose, costs off) +select exists(select 1 from pg_enum), sum(c1) from ft1; + QUERY PLAN +--------------------------------------------------- + Foreign Scan + Output: (InitPlan 1).col1, (sum(ft1.c1)) + SQLite query: SELECT sum(`C 1`) FROM main."T 1" + InitPlan 1 + -> Seq Scan on pg_catalog.pg_enum +(5 rows) + +--Testcase 519: +select exists(select 1 from pg_enum), sum(c1) from ft1; + exists | sum +--------+-------- + f | 500500 +(1 row) + +--Testcase 520: +explain (verbose, costs off) +select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; + QUERY PLAN +---------------------------------------------------- + GroupAggregate + Output: (InitPlan 1).col1, sum(ft1.c1) + InitPlan 1 + -> Seq Scan on pg_catalog.pg_enum + -> Foreign Scan on public.ft1 + Output: ft1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" +(7 rows) + +--Testcase 521: +select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; + exists | sum +--------+-------- + f | 500500 +(1 row) + +-- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates +-- ORDER BY within aggregate, same column used to order +--Testcase 177: +explain (verbose, costs off) +select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: (array_agg(c1 ORDER BY c1)), c2 + Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1)) + -> GroupAggregate + Output: array_agg(c1 ORDER BY c1), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST, `C 1` ASC NULLS LAST +(9 rows) + +--Testcase 178: +select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; + array_agg +-------------------------------- + {1,11,21,31,41,51,61,71,81,91} + {2,12,22,32,42,52,62,72,82,92} + {3,13,23,33,43,53,63,73,83,93} + {4,14,24,34,44,54,64,74,84,94} + {5,15,25,35,45,55,65,75,85,95} + {6,16,26,36,46,56,66,76,86,96} + {7,17,27,37,47,57,67,77,87,97} + {8,18,28,38,48,58,68,78,88,98} + {9,19,29,39,49,59,69,79,89,99} + {10,20,30,40,50,60,70,80,90} +(10 rows) + +-- ORDER BY within aggregate, different column used to order also using DESC +--Testcase 179: +explain (verbose, costs off) +select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Aggregate + Output: array_agg(c5 ORDER BY c1 DESC) + -> Sort + Output: c5, c1 + Sort Key: ft2.c1 DESC + -> Foreign Scan on public.ft2 + Output: c5, c1 + SQLite query: SELECT `C 1`, `c5` FROM main."T 1" WHERE ((`C 1` < 50)) AND ((`c2` = 6)) +(8 rows) + +--Testcase 180: +select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; + array_agg +------------------------------------------------------------------------------------------------------------------------------------------ + {"Mon Feb 16 00:00:00 1970","Fri Feb 06 00:00:00 1970","Tue Jan 27 00:00:00 1970","Sat Jan 17 00:00:00 1970","Wed Jan 07 00:00:00 1970"} +(1 row) + +-- DISTINCT within aggregate +--Testcase 181: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: (array_agg(DISTINCT ((t1.c1 % 5)))), ((t2.c1 % 3)) + Sort Key: (array_agg(DISTINCT ((t1.c1 % 5)))) + -> GroupAggregate + Output: array_agg(DISTINCT ((t1.c1 % 5))), ((t2.c1 % 3)) + Group Key: ((t2.c1 % 3)) + -> Sort + Output: ((t2.c1 % 3)), t1.c1, ((t1.c1 % 5)) + Sort Key: ((t2.c1 % 3)), ((t1.c1 % 5)) + -> Merge Full Join + Output: (t2.c1 % 3), t1.c1, (t1.c1 % 5) + Merge Cond: (t1.c1 = t2.c1) + Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(25 rows) + +--Testcase 182: +select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + array_agg +-------------- + {0,1,2,3,4} + {1,2,3,NULL} +(2 rows) + +-- DISTINCT combined with ORDER BY within aggregate +--Testcase 183: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + QUERY PLAN +----------------------------------------------------------------------------------------- + Sort + Output: (array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5)))), ((t2.c1 % 3)) + Sort Key: (array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5)))) + -> GroupAggregate + Output: array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5))), ((t2.c1 % 3)) + Group Key: ((t2.c1 % 3)) + -> Sort + Output: ((t2.c1 % 3)), t1.c1, ((t1.c1 % 5)) + Sort Key: ((t2.c1 % 3)), ((t1.c1 % 5)) + -> Merge Full Join + Output: (t2.c1 % 3), t1.c1, (t1.c1 % 5) + Merge Cond: (t1.c1 = t2.c1) + Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(25 rows) + +--Testcase 184: +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + array_agg +-------------- + {0,1,2,3,4} + {1,2,3,NULL} +(2 rows) + +--Testcase 185: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Sort + Output: (array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5)) DESC NULLS LAST)), ((t2.c1 % 3)) + Sort Key: (array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5)) DESC NULLS LAST)) + -> GroupAggregate + Output: array_agg(DISTINCT ((t1.c1 % 5)) ORDER BY ((t1.c1 % 5)) DESC NULLS LAST), ((t2.c1 % 3)) + Group Key: ((t2.c1 % 3)) + -> Sort + Output: ((t2.c1 % 3)), t1.c1, ((t1.c1 % 5)) + Sort Key: ((t2.c1 % 3)), ((t1.c1 % 5)) DESC NULLS LAST + -> Merge Full Join + Output: (t2.c1 % 3), t1.c1, (t1.c1 % 5) + Merge Cond: (t1.c1 = t2.c1) + Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(25 rows) + +--Testcase 186: +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + array_agg +-------------- + {3,2,1,NULL} + {4,3,2,1,0} +(2 rows) + +-- FILTER within aggregate +--Testcase 187: +explain (verbose, costs off) +select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Sort + Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2 + Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5)))) + -> GroupAggregate + Output: sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5))), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(9 rows) + +--Testcase 188: +select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; + sum +----- + 510 + 520 + 530 + 540 + + + + + + +(10 rows) + +-- DISTINCT, ORDER BY and FILTER within aggregate +--Testcase 189: +explain (verbose, costs off) +select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: sum((c1 % 3)), sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2)), c2 + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` = 6)) ORDER BY (`C 1` % 3) ASC NULLS LAST +(5 rows) + +--Testcase 190: +select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; + sum | sum | c2 +-----+-----+---- + 99 | 1 | 6 +(1 row) + +-- Outer query is aggregation query +--Testcase 191: +explain (verbose, costs off) +select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Unique + Output: ((SubPlan 1)) + -> Sort + Output: ((SubPlan 1)) + Sort Key: ((SubPlan 1)) + -> Aggregate + Output: (SubPlan 1) + -> Foreign Scan on public.ft2 t2 + Output: t2.c2, t2.c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) + SubPlan 1 + -> Foreign Scan on public.ft1 t1 + Output: count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) + SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 6)) +(14 rows) + +--Testcase 192: +select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; + count +------- + 1 +(1 row) + +-- Inner query is aggregation query +--Testcase 193: +explain (verbose, costs off) +select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Unique + Output: ((SubPlan 1)) + -> Sort + Output: ((SubPlan 1)) + Sort Key: ((SubPlan 1)) + -> Foreign Scan on public.ft2 t2 + Output: (SubPlan 1) + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) + SubPlan 1 + -> Aggregate + Output: count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1 + SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 6)) +(14 rows) + +--Testcase 194: +select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; + count +------- + 0 + 1 +(2 rows) + +-- Aggregate not pushed down as FILTER condition is not pushable +--Testcase 195: +explain (verbose, costs off) +select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Sort + Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2 + Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision))) + -> GroupAggregate + Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(9 rows) + +--Testcase 196: +explain (verbose, costs off) +select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; + QUERY PLAN +------------------------------------------------------------------------------- + Aggregate + Output: sum(ft1.c2) FILTER (WHERE (ANY (ft1.c2 = (hashed SubPlan 1).col1))) + -> Foreign Scan on public.ft1 + Output: ft1.c2 + SQLite query: SELECT `c2` FROM main."T 1" + SubPlan 1 + -> Foreign Scan on public.ft1 ft1_1 + Output: ft1_1.c2 + SQLite query: SELECT `c2` FROM main."T 1" WHERE ((`c2` < 5)) +(9 rows) + +-- Ordered-sets within aggregate +--Testcase 197: +explain (verbose, costs off) +select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, rank('10'::character varying) WITHIN GROUP (ORDER BY c6), percentile_cont((((c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)) + Group Key: ft1.c2 + Filter: (percentile_cont((((ft1.c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((ft1.c1)::double precision)) < '500'::double precision) + -> Foreign Scan on public.ft1 + Output: c2, c6, c1 + SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 10)) ORDER BY `c2` ASC NULLS LAST +(7 rows) + +--Testcase 198: +select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; + c2 | rank | percentile_cont +----+------+----------------- + 0 | 101 | 10 + 1 | 101 | 100 + 2 | 1 | 200 + 3 | 1 | 300 + 4 | 1 | 400 +(5 rows) + +-- Using multiple arguments within aggregates +--Testcase 199: +explain (verbose, costs off) +select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c1, rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2), c2 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` = 6)) ORDER BY `c2` ASC NULLS LAST +(6 rows) + +--Testcase 200: +select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; + c1 | rank +----+------ + 6 | 1 +(1 row) + +-- User defined function for user defined aggregate, VARIADIC +--Testcase 522: +create function least_accum(anyelement, variadic anyarray) +returns anyelement language sql as + 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; +--Testcase 523: +create aggregate least_agg(variadic items anyarray) ( + stype = anyelement, sfunc = least_accum +); +-- Disable hash aggregation for plan stability. +--Testcase 786: +set enable_hashagg to false; +-- Not pushed down due to user defined aggregate +--Testcase 524: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 group by c2 order by c2; + QUERY PLAN +--------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, least_agg(VARIADIC ARRAY[c1]) + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(6 rows) + +-- Add function and aggregate into extension +--alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray); +--alter extension postgres_fdw add aggregate least_agg(variadic items anyarray); +--alter server loopback options (set extensions 'postgres_fdw'); +-- Now aggregate will be pushed. Aggregate will display VARIADIC argument. +--Testcase 525: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + GroupAggregate + Output: c2, least_agg(VARIADIC ARRAY[c1]) + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 100)) ORDER BY `c2` ASC NULLS LAST +(6 rows) + +--Testcase 526: +select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; + c2 | least_agg +----+----------- + 0 | 10 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Remove function and aggregate from extension +--alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray); +--alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray); +--alter server loopback options (set extensions 'postgres_fdw'); +-- Not pushed down as we have dropped objects from extension. +--Testcase 527: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 group by c2 order by c2; + QUERY PLAN +--------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, least_agg(VARIADIC ARRAY[c1]) + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST +(6 rows) + +-- Cleanup +--Testcase 787: +reset enable_hashagg; +--Testcase 528: +drop aggregate least_agg(variadic items anyarray); +--Testcase 529: +drop function least_accum(anyelement, variadic anyarray); +-- Testing USING OPERATOR() in ORDER BY within aggregate. +-- For this, we need user defined operators along with operator family and +-- operator class. Create those and then add them in extension. Note that +-- user defined objects are considered unshippable unless they are part of +-- the extension. +--Testcase 530: +create operator public.<^ ( + leftarg = int4, + rightarg = int4, + procedure = int4eq +); +--Testcase 531: +create operator public.=^ ( + leftarg = int4, + rightarg = int4, + procedure = int4lt +); +--Testcase 532: +create operator public.>^ ( + leftarg = int4, + rightarg = int4, + procedure = int4gt +); +--Testcase 533: +create operator family my_op_family using btree; +--Testcase 534: +create function my_op_cmp(a int, b int) returns int as + $$begin return btint4cmp(a, b); end $$ language plpgsql; +--Testcase 535: +create operator class my_op_class for type int using btree family my_op_family as + operator 1 public.<^, + operator 3 public.=^, + operator 5 public.>^, + function 1 my_op_cmp(int, int); +-- This will not be pushed as user defined sort operator is not part of the +-- extension yet. +--Testcase 536: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 + -> Sort + Output: c1, c2 + Sort Key: ft2.c1 USING <^ + -> Foreign Scan on public.ft2 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) +(8 rows) + +-- This should not be pushed either. +--Testcase 967: +explain (verbose, costs off) +select * from ft2 order by c1 using operator(public.<^); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Sort Key: ft2.c1 USING <^ + -> Foreign Scan on public.ft2 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(6 rows) + +-- Update local stats on ft2 +--ANALYZE ft2; +-- Add into extension +--Testcase 788: +alter extension sqlite_fdw add operator class my_op_class using btree; +--Testcase 789: +alter extension sqlite_fdw add function my_op_cmp(a int, b int); +--Testcase 790: +alter extension sqlite_fdw add operator family my_op_family using btree; +--Testcase 791: +alter extension sqlite_fdw add operator public.<^(int, int); +--Testcase 792: +alter extension sqlite_fdw add operator public.=^(int, int); +--Testcase 793: +alter extension sqlite_fdw add operator public.>^(int, int); +--alter server loopback options (set extensions 'postgres_fdw'); +--alter server loopback options (add fdw_tuple_cost '0.5'); +-- Now this will be pushed as sort operator is part of the extension. +--Testcase 537: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 + -> Sort + Output: c1, c2 + Sort Key: ft2.c1 USING <^ + -> Foreign Scan on public.ft2 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) +(8 rows) + +--Testcase 538: +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + array_agg +-------------------------------- + {6,16,26,36,46,56,66,76,86,96} +(1 row) + +--alter server loopback options (drop fdw_tuple_cost); +-- This should be pushed too. +-- Sqlite not support pushdown user defined operators +--Testcase 968: +explain (verbose, costs off) +select * from ft2 order by c1 using operator(public.<^); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Sort + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Sort Key: ft2.c1 USING <^ + -> Foreign Scan on public.ft2 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(6 rows) + +-- Remove from extension +--Testcase 794: +alter extension sqlite_fdw drop operator class my_op_class using btree; +--Testcase 795: +alter extension sqlite_fdw drop function my_op_cmp(a int, b int); +--Testcase 796: +alter extension sqlite_fdw drop operator family my_op_family using btree; +--Testcase 797: +alter extension sqlite_fdw drop operator public.<^(int, int); +--Testcase 798: +alter extension sqlite_fdw drop operator public.=^(int, int); +--Testcase 799: +alter extension sqlite_fdw drop operator public.>^(int, int); +--alter server loopback options (set extensions 'postgres_fdw'); +-- This will not be pushed as sort operator is now removed from the extension. +--Testcase 539: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 + -> Sort + Output: c1, c2 + Sort Key: ft2.c1 USING <^ + -> Foreign Scan on public.ft2 + Output: c1, c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) +(8 rows) + +-- Cleanup +--Testcase 540: +drop operator class my_op_class using btree; +--Testcase 541: +drop function my_op_cmp(a int, b int); +--Testcase 542: +drop operator family my_op_family using btree; +--Testcase 543: +drop operator public.>^(int, int); +--Testcase 544: +drop operator public.=^(int, int); +--Testcase 545: +drop operator public.<^(int, int); +-- Input relation to aggregate push down hook is not safe to pushdown and thus +-- the aggregate cannot be pushed down to foreign server. +--Testcase 201: +explain (verbose, costs off) +select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2); + QUERY PLAN +------------------------------------------------------------------------------------------- + Aggregate + Output: count(t1.c3) + -> Nested Loop Left Join + Output: t1.c3 + Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision)) + -> Foreign Scan on public.ft2 t1 + Output: t1.c3, t1.c1 + SQLite query: SELECT `C 1`, `c3` FROM main."T 1" + -> Materialize + Output: t2.c2 + -> Foreign Scan on public.ft2 t2 + Output: t2.c2 + SQLite query: SELECT `c2` FROM main."T 1" +(13 rows) + +-- Subquery in FROM clause having aggregate +--Testcase 202: +explain (verbose, costs off) +select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Output: (count(*)), x.b + Sort Key: (count(*)), x.b + -> GroupAggregate + Output: count(*), x.b + Group Key: x.b + -> Sort + Output: x.b + Sort Key: x.b + -> Hash Join + Output: x.b + Inner Unique: true + Hash Cond: (ft1.c2 = x.a) + -> Foreign Scan on public.ft1 + Output: ft1.c2 + SQLite query: SELECT `c2` FROM main."T 1" + -> Hash + Output: x.b, x.a + -> Subquery Scan on x + Output: x.b, x.a + -> Foreign Scan + Output: ft1_1.c2, (sum(ft1_1.c1)) + SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 +(23 rows) + +--Testcase 203: +select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; + count | b +-------+------- + 100 | 49600 + 100 | 49700 + 100 | 49800 + 100 | 49900 + 100 | 50000 + 100 | 50100 + 100 | 50200 + 100 | 50300 + 100 | 50400 + 100 | 50500 +(10 rows) + +-- FULL join with IS NULL check in HAVING +--Testcase 204: +explain (verbose, costs off) +select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; + QUERY PLAN +---------------------------------------------------------------------------------------- + Sort + Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1 + Sort Key: (avg(t1.c1)), (sum(t2.c1)) + -> HashAggregate + Output: avg(t1.c1), sum(t2.c1), t2.c1 + Group Key: t2.c1 + Filter: (((avg(t1.c1) IS NULL) AND (sum(t2.c1) < 10)) OR (sum(t2.c1) IS NULL)) + -> Merge Full Join + Output: t2.c1, t1.c1 + Merge Cond: (t1.c1 = t2.c1) + -> Sort + Output: t1.c1 + Sort Key: t1.c1 + -> Foreign Scan on public.ft4 t1 + Output: t1.c1 + SQLite query: SELECT `c1` FROM main."T 3" + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + SQLite query: SELECT `c1` FROM main."T 4" +(22 rows) + +--Testcase 205: +select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; + avg | sum +---------------------+----- + 51.0000000000000000 | + | 3 + | 9 +(3 rows) + +-- Aggregate over FULL join needing to deparse the joining relations as +-- subqueries. +--Testcase 206: +explain (verbose, costs off) +select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*), sum(ft4.c1), avg(ft5.c1) + -> Hash Full Join + Output: ft4.c1, ft5.c1 + Hash Cond: (ft4.c1 = ft5.c1) + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) + -> Hash + Output: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1 + SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) +(13 rows) + +--Testcase 207: +select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); + count | sum | avg +-------+-----+--------------------- + 8 | 330 | 55.5000000000000000 +(1 row) + +-- ORDER BY expression is part of the target list but not pushed down to +-- foreign server. +--Testcase 208: +explain (verbose, costs off) +select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; + QUERY PLAN +-------------------------------------------------------------------------------- + Sort + Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer)) + Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer)) + -> Foreign Scan + Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer) + SQLite query: SELECT sum(`c2`) FROM main."T 1" +(6 rows) + +--Testcase 209: +select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; + sum +------ + 4500 +(1 row) + +-- LATERAL join, with parameterization +--Testcase 800: +set enable_hashagg to false; +--Testcase 210: +explain (verbose, costs off) +select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Nested Loop + Output: t1.c2, qry.sum + -> Foreign Scan on "S 1"."T 1" t1 + Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) AND ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST + -> Subquery Scan on qry + Output: qry.sum, t2.c1 + Filter: (((t1.c2 * 2))::numeric = qry.sum) + -> Foreign Scan + Output: (sum((t2.c1 + t1."C 1"))), t2.c1 + SQLite query: SELECT sum((`C 1` + ?)), `C 1` FROM main."T 1" GROUP BY 2 +(11 rows) + +--Testcase 211: +select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; + c2 | sum +----+----- + 1 | 2 + 2 | 4 +(2 rows) + +--Testcase 801: +reset enable_hashagg; +-- bug #15613: bad plan for foreign table scan with lateral reference +--Testcase 546: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ref_0.c2, subq_1.* +FROM + "S 1"."T 1" AS ref_0, + LATERAL ( + SELECT ref_0."C 1" c1, subq_0.* + FROM (SELECT ref_0.c2, ref_1.c3 + FROM ft1 AS ref_1) AS subq_0 + RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) + ) AS subq_1 +WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' +ORDER BY ref_0."C 1"; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1" + -> Foreign Scan on "S 1"."T 1" ref_0 + Output: ref_0."C 1", ref_0.c2, ref_0.c3, ref_0.c4, ref_0.c5, ref_0.c6, ref_0.c7, ref_0.c8 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 10)) ORDER BY `C 1` ASC NULLS LAST + -> Nested Loop + Output: ref_1.c3, (ref_0.c2) + -> Foreign Scan on public.ft2 ref_3 + Output: ref_3.c3 + SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) + -> Materialize + Output: ref_1.c3, (ref_0.c2) + -> Foreign Scan on public.ft1 ref_1 + Output: ref_1.c3, ref_0.c2 + SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) +(15 rows) + +--Testcase 547: +SELECT ref_0.c2, subq_1.* +FROM + "S 1"."T 1" AS ref_0, + LATERAL ( + SELECT ref_0."C 1" c1, subq_0.* + FROM (SELECT ref_0.c2, ref_1.c3 + FROM ft1 AS ref_1) AS subq_0 + RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) + ) AS subq_1 +WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' +ORDER BY ref_0."C 1"; + c2 | c1 | c2 | c3 +----+----+----+------- + 1 | 1 | 1 | 00001 + 2 | 2 | 2 | 00001 + 3 | 3 | 3 | 00001 + 4 | 4 | 4 | 00001 + 5 | 5 | 5 | 00001 + 6 | 6 | 6 | 00001 + 7 | 7 | 7 | 00001 + 8 | 8 | 8 | 00001 + 9 | 9 | 9 | 00001 +(9 rows) + +-- Check with placeHolderVars +--Testcase 212: +explain (verbose, costs off) +select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: sum(q.a), count(q.b) + -> Nested Loop Left Join + Output: q.a, q.b + Inner Unique: true + Join Filter: ((ft4.c1)::numeric <= q.b) + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT `c1` FROM main."T 3" + -> Materialize + Output: q.a, q.b + -> Subquery Scan on q + Output: q.a, q.b + -> Foreign Scan + Output: 13, (avg(ft1.c1)), NULL::bigint + SQLite query: SELECT 13, avg(r1.`C 1`), NULL FROM (main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) +(16 rows) + +--Testcase 213: +select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); + sum | count +-----+------- + 650 | 50 +(1 row) + +-- Not supported cases +-- Grouping sets +--Testcase 214: +explain (verbose, costs off) +select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, sum(c1) + Group Key: ft1.c2 + Group Key: () + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST +(7 rows) + +--Testcase 215: +select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; + c2 | sum +----+-------- + 0 | 50500 + 1 | 49600 + 2 | 49700 + | 149800 +(4 rows) + +--Testcase 216: +explain (verbose, costs off) +select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, sum(c1) + Group Key: ft1.c2 + Group Key: () + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST +(7 rows) + +--Testcase 217: +select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; + c2 | sum +----+-------- + 0 | 50500 + 1 | 49600 + 2 | 49700 + | 149800 +(4 rows) + +--Testcase 218: +explain (verbose, costs off) +select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Sort + Output: c2, c6, (sum(c1)) + Sort Key: ft1.c2, ft1.c6 + -> MixedAggregate + Output: c2, c6, sum(c1) + Hash Key: ft1.c6 + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c2, c6, c1 + SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST +(10 rows) + +--Testcase 219: +select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; + c2 | c6 | sum +----+----+------- + 0 | | 50500 + 1 | | 49600 + 2 | | 49700 + | 0 | 50500 + | 1 | 49600 + | 2 | 49700 +(6 rows) + +--Testcase 220: +explain (verbose, costs off) +select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c2, sum(c1), GROUPING(c2) + Group Key: ft1.c2 + -> Foreign Scan on public.ft1 + Output: c2, c1 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST +(6 rows) + +--Testcase 221: +select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; + c2 | sum | grouping +----+-------+---------- + 0 | 50500 | 0 + 1 | 49600 | 0 + 2 | 49700 | 0 +(3 rows) + +-- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed +--Testcase 222: +explain (verbose, costs off) +select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Unique + Output: ((sum(c1) / 1000)), c2 + -> Sort + Output: ((sum(c1) / 1000)), c2 + Sort Key: ((sum(ft2.c1) / 1000)) + -> Foreign Scan + Output: ((sum(c1) / 1000)), c2 + SQLite query: SELECT (sum(`C 1`) / 1000), `c2` FROM main."T 1" WHERE ((`c2` < 6)) GROUP BY 2 +(8 rows) + +--Testcase 223: +select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; + s +---- + 49 + 50 +(2 rows) + +-- WindowAgg +--Testcase 224: +explain (verbose, costs off) +select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Sort + Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2)) + Sort Key: ft2.c2 + -> WindowAgg + Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2)) + -> Sort + Output: c2, ((c2 % 2)), (sum(c2)) + Sort Key: ((ft2.c2 % 2)) + -> Foreign Scan + Output: c2, ((c2 % 2)), (sum(c2)) + SQLite query: SELECT `c2`, (`c2` % 2), sum(`c2`) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 +(11 rows) + +--Testcase 225: +select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; + c2 | sum | count +----+-----+------- + 0 | 0 | 5 + 1 | 100 | 5 + 2 | 200 | 5 + 3 | 300 | 5 + 4 | 400 | 5 + 5 | 500 | 5 + 6 | 600 | 5 + 7 | 700 | 5 + 8 | 800 | 5 + 9 | 900 | 5 +(10 rows) + +--Testcase 226: +explain (verbose, costs off) +select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Sort + Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) + Sort Key: ft1.c2 + -> WindowAgg + Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) + -> Sort + Output: c2, ((c2 % 2)) + Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC + -> Foreign Scan + Output: c2, ((c2 % 2)) + SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 +(11 rows) + +--Testcase 227: +select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; + c2 | array_agg +----+------------- + 0 | {8,6,4,2,0} + 1 | {9,7,5,3,1} + 2 | {8,6,4,2} + 3 | {9,7,5,3} + 4 | {8,6,4} + 5 | {9,7,5} + 6 | {8,6} + 7 | {9,7} + 8 | {8} + 9 | {9} +(10 rows) + +--Testcase 228: +explain (verbose, costs off) +select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Sort + Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) + Sort Key: ft1.c2 + -> WindowAgg + Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) + -> Sort + Output: c2, ((c2 % 2)) + Sort Key: ((ft1.c2 % 2)), ft1.c2 + -> Foreign Scan + Output: c2, ((c2 % 2)) + SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 +(11 rows) + +--Testcase 229: +select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; + c2 | array_agg +----+------------- + 0 | {0,2,4,6,8} + 1 | {1,3,5,7,9} + 2 | {2,4,6,8} + 3 | {3,5,7,9} + 4 | {4,6,8} + 5 | {5,7,9} + 6 | {6,8} + 7 | {7,9} + 8 | {8} + 9 | {9} +(10 rows) + +-- =================================================================== +-- parameterized queries +-- =================================================================== +-- simple join +--Testcase 230: +PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2; +--Testcase 231: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2); + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop + Output: t1.c3, t2.c3 + -> Foreign Scan on public.ft1 t1 + Output: t1.c3 + SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 1)) + -> Materialize + Output: t2.c3 + -> Foreign Scan on public.ft2 t2 + Output: t2.c3 + SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 2)) +(10 rows) + +--Testcase 232: +EXECUTE st1(1, 1); + c3 | c3 +-------+------- + 00001 | 00001 +(1 row) + +--Testcase 233: +EXECUTE st1(101, 101); + c3 | c3 +-------+------- + 00101 | 00101 +(1 row) + +SET enable_hashjoin TO off; +SET enable_sort TO off; +-- subquery using stable function (can't be sent to remote) +--Testcase 234: +PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1; +--Testcase 235: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop Semi Join + Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Join Filter: (t1.c3 = t2.c3) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST + -> Materialize + Output: t2.c3 + -> Foreign Scan on public.ft2 t2 + Output: t2.c3 + Filter: (date(t2.c4) = '01-17-1970'::date) + SQLite query: SELECT `c3`, `c4` FROM main."T 1" WHERE ((`C 1` > 10)) +(12 rows) + +--Testcase 236: +EXECUTE st2(10, 20); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo +(1 row) + +--Testcase 237: +EXECUTE st2(101, 121); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo +(1 row) + +RESET enable_hashjoin; +RESET enable_sort; +-- subquery using immutable function (can be sent to remote) +--Testcase 238: +PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1; +--Testcase 239: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Sort Key: t1.c1 + -> Hash Semi Join + Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Hash Cond: (t1.c3 = t2.c3) + -> Foreign Scan on public.ft1 t1 + Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST + -> Hash + Output: t2.c3 + -> Foreign Scan on public.ft2 t2 + Output: t2.c3 + Filter: (date(t2.c5) = '01-17-1970'::date) + SQLite query: SELECT `c3`, `c5` FROM main."T 1" WHERE ((`C 1` > 10)) +(15 rows) + +--Testcase 240: +EXECUTE st3(10, 20); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo +(1 row) + +--Testcase 241: +EXECUTE st3(20, 30); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+----+----+----+----+----+---- +(0 rows) + +-- custom plan should be chosen initially +--Testcase 242: +PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1; +--Testcase 243: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +--Testcase 244: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +--Testcase 245: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +--Testcase 246: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +--Testcase 247: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) +(3 rows) + +-- once we try it enough times, should switch to generic plan +--Testcase 248: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = ?)) +(3 rows) + +-- value of $1 should not be sent to remote +--Testcase 249: +PREPARE st5(text,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2; +--Testcase 250: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) +(3 rows) + +--Testcase 251: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) +(3 rows) + +--Testcase 252: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) +(3 rows) + +--Testcase 253: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) +(3 rows) + +--Testcase 254: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) +(3 rows) + +--Testcase 255: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = ?)) AND ((`C 1` = ?)) +(3 rows) + +--Testcase 256: +EXECUTE st5('foo', 1); + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- altering FDW options requires replanning +--Testcase 257: +PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2; +--Testcase 258: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = `c2`)) +(3 rows) + +--Testcase 259: +PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); +--Testcase 260: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on public.ft1 + Batch Size: 1 + -> Result + Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text +(4 rows) + +--Testcase 548: +INSERT INTO "S 1"."T 0" SELECT * FROM "S 1"."T 1"; +--Testcase 802: +ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 0'); +--Testcase 261: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 0" WHERE ((`C 1` = `c2`)) +(3 rows) + +--Testcase 262: +EXECUTE st6; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo + 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo + 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo +(9 rows) + +--Testcase 263: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on public.ft1 + Batch Size: 1 + -> Result + Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text +(4 rows) + +--Testcase 803: +ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 1'); +--Testcase 549: +PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; +--Testcase 550: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--ALTER SERVER loopback OPTIONS (DROP extensions); +--Testcase 551: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; + QUERY PLAN +---------------------------------------------------------------- + Aggregate + Output: count(c3) + -> Foreign Scan on public.ft1 t1 + Output: c3 + Filter: (t1.c1 === t1.c2) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" +(6 rows) + +--Testcase 552: +EXECUTE st8; + count +------- + 9 +(1 row) + +--ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +-- cleanup +DEALLOCATE st1; +DEALLOCATE st2; +DEALLOCATE st3; +DEALLOCATE st4; +DEALLOCATE st5; +DEALLOCATE st6; +DEALLOCATE st7; +DEALLOCATE st8; +-- System columns, except ctid and oid, should not be sent to remote +--Testcase 264: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Limit + Output: c1, c2, c3, c4, c5, c6, c7, c8 + -> Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (t1.tableoid = '1259'::oid) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(6 rows) + +--Testcase 265: +SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +--Testcase 266: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 +(3 rows) + +--Testcase 267: +SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; + tableoid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----------+----+----+-------+------------------------------+--------------------------+----+------------+----- + ft1 | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +--Testcase 268: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 t1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + Filter: (t1.ctid = '(0,2)'::tid) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(4 rows) + +--Testcase 553: +SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+----+----+----+----+----+---- +(0 rows) + +--Testcase 554: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ctid, * FROM ft1 t1 LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan on public.ft1 t1 + Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 +(3 rows) + +--Testcase 271: +SELECT ctid, * FROM ft1 t1 LIMIT 1; + ctid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----------------+----+----+-------+------------------------------+--------------------------+----+------------+----- + (4294967295,0) | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- =================================================================== +-- used in PL/pgSQL function +-- =================================================================== +--Testcase 555: +CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$ +DECLARE + v_c1 int; +BEGIN +--Testcase 556: + SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1; + PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1; + RETURN v_c1; +END; +$$ LANGUAGE plpgsql; +--Testcase 272: +SELECT f_test(100); + f_test +-------- + 100 +(1 row) + +--Testcase 557: +DROP FUNCTION f_test(int); +-- =================================================================== +-- REINDEX +-- =================================================================== +-- remote table is not created here +--Testcase 804: +CREATE FOREIGN TABLE reindex_foreign (c1 int, c2 int) + SERVER sqlite_svr2 OPTIONS (table 'reindex_local'); +REINDEX TABLE reindex_foreign; -- error +ERROR: "reindex_foreign" is not a table or materialized view +REINDEX TABLE CONCURRENTLY reindex_foreign; -- error +ERROR: "reindex_foreign" is not a table or materialized view +--Testcase 805: +DROP FOREIGN TABLE reindex_foreign; +-- partitions and foreign tables +--Testcase 806: +CREATE TABLE reind_fdw_parent (c1 int) PARTITION BY RANGE (c1); +--Testcase 807: +CREATE TABLE reind_fdw_0_10 PARTITION OF reind_fdw_parent + FOR VALUES FROM (0) TO (10); +--Testcase 808: +CREATE FOREIGN TABLE reind_fdw_10_20 PARTITION OF reind_fdw_parent + FOR VALUES FROM (10) TO (20) + SERVER sqlite_svr OPTIONS (table 'reind_local_10_20'); +REINDEX TABLE reind_fdw_parent; -- ok +REINDEX TABLE CONCURRENTLY reind_fdw_parent; -- ok +--Testcase 809: +DROP TABLE reind_fdw_parent; +-- =================================================================== +-- conversion error +-- =================================================================== +--Testcase 810: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int; +--Testcase 273: +SELECT * FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8) WHERE x1 = 1; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (3 bytes) : 'foo' +CONTEXT: foreign table "ftx" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column +--Testcase 274: +SELECT ftx.x1, ft2.c2, ftx.x8 FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (3 bytes) : 'foo' +CONTEXT: foreign table "ftx" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column +--Testcase 275: +SELECT ftx.x1, ft2.c2, ftx FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (3 bytes) : 'foo' +CONTEXT: foreign table "ftx" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column +--Testcase 276: +SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (3 bytes) : 'foo' +CONTEXT: foreign table "ft1" foreign column "c8" have data type "integer" (usual affinity "integer"), in query there is reference to foreign column +-- ANALYZE ft1; -- ERROR +-- =================================================================== +-- local type can be different from remote type in some cases, +-- in particular if similarly-named operators do equivalent things +-- =================================================================== +--Testcase 811: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text; +--Testcase 969: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) LIMIT 1 +(3 rows) + +--Testcase 970: +SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +--Testcase 971: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (('foo' = `c8`)) LIMIT 1 +(3 rows) + +--Testcase 972: +SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- we declared c8 to be text locally, but it's still the same type on +-- the remote which will balk if we try to do anything incompatible +-- with that remote type +-- Can not create user define type in SqliteDB. +-- Type c8 of foreign table ft1 and remote table T1 are +-- match. These case below not error with sqlite_fdw. +-- with that remote type +--Testcase 973: +SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +--Testcase 974: +SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +-- =================================================================== +-- subtransaction +-- + local/remote error doesn't break cursor +-- =================================================================== +BEGIN; +DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1; +--Testcase 277: +FETCH c; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +SAVEPOINT s; +ERROR OUT; -- ERROR +ERROR: syntax error at or near "ERROR" +LINE 1: ERROR OUT; + ^ +ROLLBACK TO s; +--Testcase 278: +FETCH c; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo +(1 row) + +SAVEPOINT s; +--Testcase 279: +SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo +(1 row) + +ROLLBACK TO s; +--Testcase 280: +FETCH c; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo +(1 row) + +--Testcase 281: +SELECT * FROM ft1 ORDER BY c1 LIMIT 1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+----+-------+------------------------------+--------------------------+----+------------+----- + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo +(1 row) + +COMMIT; +-- =================================================================== +-- test handling of collations +-- =================================================================== +--Testcase 558: +create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10)) server sqlite_svr; +-- can be sent to remote +--Testcase 559: +explain (verbose, costs off) select * from ft3 where f1 = 'foo'; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) +(3 rows) + +--Testcase 560: +explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo'; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) +(3 rows) + +--Testcase 561: +explain (verbose, costs off) select * from ft3 where f2 = 'foo'; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f2` = 'foo')) +(3 rows) + +--Testcase 562: +explain (verbose, costs off) select * from ft3 where f3 = 'foo'; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f3` = 'foo')) +(3 rows) + +--Testcase 563: +explain (verbose, costs off) select * from ft3 f, loct3 l + where f.f3 = l.f3 and l.f1 = 'foo'; +ERROR: relation "loct3" does not exist +LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l + ^ +-- can't be sent to remote +--Testcase 564: +explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo'; + QUERY PLAN +--------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + Filter: ((ft3.f1)::text = 'foo'::text) + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" +(4 rows) + +--Testcase 565: +explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C"; + QUERY PLAN +--------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + Filter: (ft3.f1 = 'foo'::text COLLATE "C") + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" +(4 rows) + +--Testcase 566: +explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo'; + QUERY PLAN +--------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + Filter: ((ft3.f2)::text = 'foo'::text) + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" +(4 rows) + +--Testcase 567: +explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C"; + QUERY PLAN +--------------------------------------------------------- + Foreign Scan on public.ft3 + Output: f1, f2, f3 + Filter: (ft3.f2 = 'foo'::text COLLATE "C") + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" +(4 rows) + +--Testcase 568: +explain (verbose, costs off) select * from ft3 f, loct3 l + where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo'; +ERROR: relation "loct3" does not exist +LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l + ^ +-- =================================================================== +-- test SEMI-JOIN pushdown +-- =================================================================== +--Testcase 1012: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1) + ORDER BY ft2.c1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`c1`, r2.`c2`, r2.`c3` FROM (main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 900)))) WHERE EXISTS (SELECT NULL FROM main."T 4" r4 WHERE ((r1.`c2` = r4.`c1`))) ORDER BY r1.`C 1` ASC NULLS LAST +(3 rows) + +--Testcase 1013: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1) + ORDER BY ft2.c1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------- + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 +(10 rows) + +-- The same query, different join order +--Testcase 1014: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r4.`c1`, r4.`c2`, r4.`c3` FROM (main."T 1" r1 INNER JOIN main."T 3" r4 ON (((r1.`c2` = r4.`c1`)) AND ((r1.`C 1` > 900)))) WHERE EXISTS (SELECT NULL FROM main."T 4" r5 WHERE ((r4.`c1` = r5.`c1`))) ORDER BY r1.`C 1` ASC NULLS LAST +(3 rows) + +--Testcase 1015: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------- + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 +(10 rows) + +-- Left join +--Testcase 1016: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, s6.c1, s6.c2, s6.c3 FROM (main."T 1" r1 LEFT JOIN (SELECT r4.`c1` AS c1, r4.`c2` AS c2, r4.`c3` AS c3 FROM main."T 3" r4 WHERE EXISTS (SELECT NULL FROM main."T 4" r5 WHERE ((r4.`c1` = r5.`c1`)))) s6 ON (((r1.`c2` = s6.c1)))) WHERE ((r1.`C 1` > 900)) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 1017: +SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------- + 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo | | | + 902 | 2 | 00902 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo | | | + 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo | | | + 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo | | | + 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo | | | + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo | | | + 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo | | | + 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo | | | + 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo | | | +(10 rows) + +-- Several semi-joins per upper level join +--Testcase 1018: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN (SELECT * FROM ft5 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5 + ON ft2.c2 <= ft5.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r6.`c1`, r6.`c2`, r6.`c3` FROM ((main."T 1" r1 INNER JOIN main."T 3" r6 ON (((r1.`c2` = r6.`c1`)) AND ((r1.`C 1` > 900)))) INNER JOIN main."T 4" r8 ON (((r1.`c2` <= r8.`c1`)))) WHERE EXISTS (SELECT NULL FROM main."T 3" r9 WHERE ((r8.`c1` = r9.`c1`))) AND EXISTS (SELECT NULL FROM main."T 4" r7 WHERE ((r6.`c1` = r7.`c1`))) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 1019: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN (SELECT * FROM ft5 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5 + ON ft2.c2 <= ft5.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 +-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------- + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 +(10 rows) + +-- Semi-join below Semi-join +--Testcase 1020: +EXPLAIN (verbose, costs off) +SELECT ft2.* FROM ft2 WHERE + c1 = ANY ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2)) + AND ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8` FROM main."T 1" r1 WHERE ((r1.`C 1` > 900)) AND EXISTS (SELECT NULL FROM main."T 1" r3 WHERE ((r1.`C 1` = r3.`C 1`)) AND EXISTS (SELECT NULL FROM main."T 3" r4 WHERE ((r3.`c2` = r4.`c2`)))) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 1021: +SELECT ft2.* FROM ft2 WHERE + c1 = ANY ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2)) + AND ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo + 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo + 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo + 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo + 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo + 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo +(10 rows) + +-- Upper level relations shouldn't refer EXISTS() subqueries +--Testcase 1022: +EXPLAIN (verbose, costs off) +SELECT * FROM ft2 ftupper WHERE + EXISTS ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 ) + AND ftupper.c1 > 900 + ORDER BY ftupper.c1 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ftupper.c1, ftupper.c2, ftupper.c3, ftupper.c4, ftupper.c5, ftupper.c6, ftupper.c7, ftupper.c8 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8` FROM main."T 1" r1 WHERE ((r1.`C 1` > 900)) AND EXISTS (SELECT NULL FROM main."T 1" r2 WHERE ((r1.`C 1` = r2.`C 1`)) AND EXISTS (SELECT NULL FROM main."T 3" r3 WHERE ((r2.`c2` = r3.`c2`)))) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 1023: +SELECT * FROM ft2 ftupper WHERE + EXISTS ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 ) + AND ftupper.c1 > 900 + ORDER BY ftupper.c1 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+----+-------+------------------------------+--------------------------+----+------------+----- + 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo + 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo + 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo + 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo + 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo + 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo + 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo + 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo +(10 rows) + +-- EXISTS should be propagated to the highest upper inner join +--Testcase 1024: +EXPLAIN (verbose, costs off) + SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE EXISTS ( + SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN + (SELECT * FROM ft2 WHERE EXISTS ( + SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21 + ON ft2.c2 = ft21.c2 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3 + SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r6.`c1`, r6.`c2`, r6.`c3` FROM ((main."T 1" r1 INNER JOIN main."T 3" r6 ON (((r1.`c2` = r6.`c1`)) AND ((r1.`C 1` > 900)))) INNER JOIN main."T 1" r8 ON (((r1.`c2` = r8.`c2`)))) WHERE EXISTS (SELECT NULL FROM main."T 3" r9 WHERE ((r1.`c2` = r9.`c2`))) AND EXISTS (SELECT NULL FROM main."T 1" r7 WHERE ((r6.`c2` = r7.`c2`))) ORDER BY r1.`C 1` ASC NULLS LAST LIMIT 10 +(3 rows) + +--Testcase 1025: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE EXISTS ( + SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN + (SELECT * FROM ft2 WHERE EXISTS ( + SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21 + ON ft2.c2 = ft21.c2 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 +----+----+----+----+----+----+----+----+----+----+---- +(0 rows) + +-- Can't push down semi-join with inner rel vars in targetlist +--Testcase 1026: +EXPLAIN (verbose, costs off) +SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE + ft1.c1 IN ( + SELECT ft2.c1 FROM ft2 JOIN ft4 ON ft2.c1 = ft4.c1) + ORDER BY ft1.c1 LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: ft1.c1 + -> Merge Semi Join + Output: ft1.c1 + Merge Cond: (ft1.c1 = ft2_1.c1) + -> Foreign Scan + Output: ft1.c1, ft2.c1 + SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`C 1` ASC NULLS LAST + -> Foreign Scan + Output: ft2_1.c1, ft4.c1 + SQLite query: SELECT r5.`C 1`, r6.`c1` FROM (main."T 1" r5 INNER JOIN main."T 3" r6 ON (((r5.`C 1` = r6.`c1`)))) ORDER BY r5.`C 1` ASC NULLS LAST +(11 rows) + +-- =================================================================== +-- test writable foreign table stuff +-- =================================================================== +--Testcase 282: +EXPLAIN (verbose, costs off) +INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on public.ft2 + Batch Size: 1 + -> Subquery Scan on "*SELECT*" + Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text + -> Foreign Scan on public.ft2 ft2_1 + Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3) + SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" LIMIT 20 +(7 rows) + +--Testcase 283: +INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; +--Testcase 284: +INSERT INTO ft2 (c1,c2,c3) VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc'); +--Testcase 285: +SELECT * FROM ft2 WHERE c1 >= 1101; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+-----+----+----+----+------------+---- + 1101 | 201 | aaa | | | | ft2 | + 1102 | 202 | bbb | | | | ft2 | + 1103 | 203 | ccc | | | | ft2 | +(3 rows) + +--Testcase 286: +INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); +--Testcase 287: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Foreign Update on public.ft2 + SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 300), `c3` = (`c3` || '_update3') WHERE (((`C 1` % 10) = 3)) +(3 rows) + +--Testcase 288: +UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; +--Testcase 289: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; -- can be pushed down + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Foreign Update on public.ft2 + SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 400), `c3` = (`c3` || '_update7') WHERE (((`C 1` % 10) = 7)) +(3 rows) + +--Testcase 290: +UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; +--Testcase 291: +SELECT * FROM ft2 WHERE c1 % 10 = 7; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+--------------------+------------------------------+--------------------------+----+------------+----- + 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo + 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo + 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo + 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo + 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo + 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo + 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo + 1007 | 507 | 0000700007_update7 | | | | ft2 | + 1017 | 507 | 0001700017_update7 | | | | ft2 | +(102 rows) + +--Testcase 292: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT + FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Foreign Scan + Output: (ft2.c2 + 500), (ft2.c3 || '_update9'::text), 'ft2 '::character(10), ft2.c1, ft2.*, ft1.* + SQLite query: SELECT r1.`c2`, r1.`c3`, r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 9)))) + -> Hash Join + Output: ft2.c2, ft2.c3, ft2.c1, ft2.*, ft1.* + Hash Cond: (ft2.c2 = ft1.c1) + -> Foreign Scan on public.ft2 + Output: ft2.c2, ft2.c3, ft2.c1, ft2.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" + -> Hash + Output: ft1.*, ft1.c1 + -> Foreign Scan on public.ft1 + Output: ft1.*, ft1.c1 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 9)) +(15 rows) + +--Testcase 293: +UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT + FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; +--Testcase 294: +EXPLAIN (verbose, costs off) + DELETE FROM ft2 WHERE c1 % 10 = 5; -- can be pushed down + QUERY PLAN +------------------------------------------------------------------------- + Delete on public.ft2 + -> Foreign Delete on public.ft2 + SQLite query: DELETE FROM main."T 1" WHERE (((`C 1` % 10) = 5)) +(3 rows) + +--Testcase 295: +SELECT c1, c4 FROM ft2 WHERE c1 % 10 = 5; + c1 | c4 +------+------------------------------ + 5 | Tue Jan 06 00:00:00 1970 PST + 15 | Fri Jan 16 00:00:00 1970 PST + 25 | Mon Jan 26 00:00:00 1970 PST + 35 | Thu Feb 05 00:00:00 1970 PST + 45 | Sun Feb 15 00:00:00 1970 PST + 55 | Wed Feb 25 00:00:00 1970 PST + 65 | Sat Mar 07 00:00:00 1970 PST + 75 | Tue Mar 17 00:00:00 1970 PST + 85 | Fri Mar 27 00:00:00 1970 PST + 95 | Mon Apr 06 00:00:00 1970 PST + 105 | Tue Jan 06 00:00:00 1970 PST + 115 | Fri Jan 16 00:00:00 1970 PST + 125 | Mon Jan 26 00:00:00 1970 PST + 135 | Thu Feb 05 00:00:00 1970 PST + 145 | Sun Feb 15 00:00:00 1970 PST + 155 | Wed Feb 25 00:00:00 1970 PST + 165 | Sat Mar 07 00:00:00 1970 PST + 175 | Tue Mar 17 00:00:00 1970 PST + 185 | Fri Mar 27 00:00:00 1970 PST + 195 | Mon Apr 06 00:00:00 1970 PST + 205 | Tue Jan 06 00:00:00 1970 PST + 215 | Fri Jan 16 00:00:00 1970 PST + 225 | Mon Jan 26 00:00:00 1970 PST + 235 | Thu Feb 05 00:00:00 1970 PST + 245 | Sun Feb 15 00:00:00 1970 PST + 255 | Wed Feb 25 00:00:00 1970 PST + 265 | Sat Mar 07 00:00:00 1970 PST + 275 | Tue Mar 17 00:00:00 1970 PST + 285 | Fri Mar 27 00:00:00 1970 PST + 295 | Mon Apr 06 00:00:00 1970 PST + 305 | Tue Jan 06 00:00:00 1970 PST + 315 | Fri Jan 16 00:00:00 1970 PST + 325 | Mon Jan 26 00:00:00 1970 PST + 335 | Thu Feb 05 00:00:00 1970 PST + 345 | Sun Feb 15 00:00:00 1970 PST + 355 | Wed Feb 25 00:00:00 1970 PST + 365 | Sat Mar 07 00:00:00 1970 PST + 375 | Tue Mar 17 00:00:00 1970 PST + 385 | Fri Mar 27 00:00:00 1970 PST + 395 | Mon Apr 06 00:00:00 1970 PST + 405 | Tue Jan 06 00:00:00 1970 PST + 415 | Fri Jan 16 00:00:00 1970 PST + 425 | Mon Jan 26 00:00:00 1970 PST + 435 | Thu Feb 05 00:00:00 1970 PST + 445 | Sun Feb 15 00:00:00 1970 PST + 455 | Wed Feb 25 00:00:00 1970 PST + 465 | Sat Mar 07 00:00:00 1970 PST + 475 | Tue Mar 17 00:00:00 1970 PST + 485 | Fri Mar 27 00:00:00 1970 PST + 495 | Mon Apr 06 00:00:00 1970 PST + 505 | Tue Jan 06 00:00:00 1970 PST + 515 | Fri Jan 16 00:00:00 1970 PST + 525 | Mon Jan 26 00:00:00 1970 PST + 535 | Thu Feb 05 00:00:00 1970 PST + 545 | Sun Feb 15 00:00:00 1970 PST + 555 | Wed Feb 25 00:00:00 1970 PST + 565 | Sat Mar 07 00:00:00 1970 PST + 575 | Tue Mar 17 00:00:00 1970 PST + 585 | Fri Mar 27 00:00:00 1970 PST + 595 | Mon Apr 06 00:00:00 1970 PST + 605 | Tue Jan 06 00:00:00 1970 PST + 615 | Fri Jan 16 00:00:00 1970 PST + 625 | Mon Jan 26 00:00:00 1970 PST + 635 | Thu Feb 05 00:00:00 1970 PST + 645 | Sun Feb 15 00:00:00 1970 PST + 655 | Wed Feb 25 00:00:00 1970 PST + 665 | Sat Mar 07 00:00:00 1970 PST + 675 | Tue Mar 17 00:00:00 1970 PST + 685 | Fri Mar 27 00:00:00 1970 PST + 695 | Mon Apr 06 00:00:00 1970 PST + 705 | Tue Jan 06 00:00:00 1970 PST + 715 | Fri Jan 16 00:00:00 1970 PST + 725 | Mon Jan 26 00:00:00 1970 PST + 735 | Thu Feb 05 00:00:00 1970 PST + 745 | Sun Feb 15 00:00:00 1970 PST + 755 | Wed Feb 25 00:00:00 1970 PST + 765 | Sat Mar 07 00:00:00 1970 PST + 775 | Tue Mar 17 00:00:00 1970 PST + 785 | Fri Mar 27 00:00:00 1970 PST + 795 | Mon Apr 06 00:00:00 1970 PST + 805 | Tue Jan 06 00:00:00 1970 PST + 815 | Fri Jan 16 00:00:00 1970 PST + 825 | Mon Jan 26 00:00:00 1970 PST + 835 | Thu Feb 05 00:00:00 1970 PST + 845 | Sun Feb 15 00:00:00 1970 PST + 855 | Wed Feb 25 00:00:00 1970 PST + 865 | Sat Mar 07 00:00:00 1970 PST + 875 | Tue Mar 17 00:00:00 1970 PST + 885 | Fri Mar 27 00:00:00 1970 PST + 895 | Mon Apr 06 00:00:00 1970 PST + 905 | Tue Jan 06 00:00:00 1970 PST + 915 | Fri Jan 16 00:00:00 1970 PST + 925 | Mon Jan 26 00:00:00 1970 PST + 935 | Thu Feb 05 00:00:00 1970 PST + 945 | Sun Feb 15 00:00:00 1970 PST + 955 | Wed Feb 25 00:00:00 1970 PST + 965 | Sat Mar 07 00:00:00 1970 PST + 975 | Tue Mar 17 00:00:00 1970 PST + 985 | Fri Mar 27 00:00:00 1970 PST + 995 | Mon Apr 06 00:00:00 1970 PST + 1005 | + 1015 | + 1105 | +(103 rows) + +--Testcase 569: +DELETE FROM ft2 WHERE c1 % 10 = 5; +--Testcase 297: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Delete on public.ft2 + -> Foreign Scan + Output: ft2.c1, ft1.* + SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 2)))) + -> Hash Join + Output: ft2.c1, ft1.* + Hash Cond: (ft2.c2 = ft1.c1) + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" + -> Hash + Output: ft1.*, ft1.c1 + -> Foreign Scan on public.ft1 + Output: ft1.*, ft1.c1 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 2)) +(15 rows) + +--Testcase 298: +DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; +--Testcase 299: +SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; + c1 | c2 | c3 | c4 +------+-----+--------------------+------------------------------ + 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST + 3 | 303 | 00003_update3 | Sun Jan 04 00:00:00 1970 PST + 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST + 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST + 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST + 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST + 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST + 11 | 1 | 00011 | Mon Jan 12 00:00:00 1970 PST + 13 | 303 | 00013_update3 | Wed Jan 14 00:00:00 1970 PST + 14 | 4 | 00014 | Thu Jan 15 00:00:00 1970 PST + 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST + 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST + 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST + 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST + 20 | 0 | 00020 | Wed Jan 21 00:00:00 1970 PST + 21 | 1 | 00021 | Thu Jan 22 00:00:00 1970 PST + 23 | 303 | 00023_update3 | Sat Jan 24 00:00:00 1970 PST + 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST + 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST + 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST + 28 | 8 | 00028 | Thu Jan 29 00:00:00 1970 PST + 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST + 30 | 0 | 00030 | Sat Jan 31 00:00:00 1970 PST + 31 | 1 | 00031 | Sun Feb 01 00:00:00 1970 PST + 33 | 303 | 00033_update3 | Tue Feb 03 00:00:00 1970 PST + 34 | 4 | 00034 | Wed Feb 04 00:00:00 1970 PST + 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST + 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST + 38 | 8 | 00038 | Sun Feb 08 00:00:00 1970 PST + 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST + 40 | 0 | 00040 | Tue Feb 10 00:00:00 1970 PST + 41 | 1 | 00041 | Wed Feb 11 00:00:00 1970 PST + 43 | 303 | 00043_update3 | Fri Feb 13 00:00:00 1970 PST + 44 | 4 | 00044 | Sat Feb 14 00:00:00 1970 PST + 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST + 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST + 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST + 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST + 50 | 0 | 00050 | Fri Feb 20 00:00:00 1970 PST + 51 | 1 | 00051 | Sat Feb 21 00:00:00 1970 PST + 53 | 303 | 00053_update3 | Mon Feb 23 00:00:00 1970 PST + 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST + 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST + 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST + 58 | 8 | 00058 | Sat Feb 28 00:00:00 1970 PST + 59 | 509 | 00059_update9 | Sun Mar 01 00:00:00 1970 PST + 60 | 0 | 00060 | Mon Mar 02 00:00:00 1970 PST + 61 | 1 | 00061 | Tue Mar 03 00:00:00 1970 PST + 63 | 303 | 00063_update3 | Thu Mar 05 00:00:00 1970 PST + 64 | 4 | 00064 | Fri Mar 06 00:00:00 1970 PST + 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST + 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST + 68 | 8 | 00068 | Tue Mar 10 00:00:00 1970 PST + 69 | 509 | 00069_update9 | Wed Mar 11 00:00:00 1970 PST + 70 | 0 | 00070 | Thu Mar 12 00:00:00 1970 PST + 71 | 1 | 00071 | Fri Mar 13 00:00:00 1970 PST + 73 | 303 | 00073_update3 | Sun Mar 15 00:00:00 1970 PST + 74 | 4 | 00074 | Mon Mar 16 00:00:00 1970 PST + 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST + 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST + 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST + 79 | 509 | 00079_update9 | Sat Mar 21 00:00:00 1970 PST + 80 | 0 | 00080 | Sun Mar 22 00:00:00 1970 PST + 81 | 1 | 00081 | Mon Mar 23 00:00:00 1970 PST + 83 | 303 | 00083_update3 | Wed Mar 25 00:00:00 1970 PST + 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST + 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST + 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST + 88 | 8 | 00088 | Mon Mar 30 00:00:00 1970 PST + 89 | 509 | 00089_update9 | Tue Mar 31 00:00:00 1970 PST + 90 | 0 | 00090 | Wed Apr 01 00:00:00 1970 PST + 91 | 1 | 00091 | Thu Apr 02 00:00:00 1970 PST + 93 | 303 | 00093_update3 | Sat Apr 04 00:00:00 1970 PST + 94 | 4 | 00094 | Sun Apr 05 00:00:00 1970 PST + 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST + 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST + 98 | 8 | 00098 | Thu Apr 09 00:00:00 1970 PST + 99 | 509 | 00099_update9 | Fri Apr 10 00:00:00 1970 PST + 100 | 0 | 00100 | Thu Jan 01 00:00:00 1970 PST + 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST + 103 | 303 | 00103_update3 | Sun Jan 04 00:00:00 1970 PST + 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST + 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST + 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST + 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST + 109 | 509 | 00109_update9 | Sat Jan 10 00:00:00 1970 PST + 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST + 111 | 1 | 00111 | Mon Jan 12 00:00:00 1970 PST + 113 | 303 | 00113_update3 | Wed Jan 14 00:00:00 1970 PST + 114 | 4 | 00114 | Thu Jan 15 00:00:00 1970 PST + 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST + 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST + 118 | 8 | 00118 | Mon Jan 19 00:00:00 1970 PST + 119 | 509 | 00119_update9 | Tue Jan 20 00:00:00 1970 PST + 120 | 0 | 00120 | Wed Jan 21 00:00:00 1970 PST + 121 | 1 | 00121 | Thu Jan 22 00:00:00 1970 PST + 123 | 303 | 00123_update3 | Sat Jan 24 00:00:00 1970 PST + 124 | 4 | 00124 | Sun Jan 25 00:00:00 1970 PST + 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST + 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST + 128 | 8 | 00128 | Thu Jan 29 00:00:00 1970 PST + 129 | 509 | 00129_update9 | Fri Jan 30 00:00:00 1970 PST + 130 | 0 | 00130 | Sat Jan 31 00:00:00 1970 PST + 131 | 1 | 00131 | Sun Feb 01 00:00:00 1970 PST + 133 | 303 | 00133_update3 | Tue Feb 03 00:00:00 1970 PST + 134 | 4 | 00134 | Wed Feb 04 00:00:00 1970 PST + 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST + 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST + 138 | 8 | 00138 | Sun Feb 08 00:00:00 1970 PST + 139 | 509 | 00139_update9 | Mon Feb 09 00:00:00 1970 PST + 140 | 0 | 00140 | Tue Feb 10 00:00:00 1970 PST + 141 | 1 | 00141 | Wed Feb 11 00:00:00 1970 PST + 143 | 303 | 00143_update3 | Fri Feb 13 00:00:00 1970 PST + 144 | 4 | 00144 | Sat Feb 14 00:00:00 1970 PST + 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST + 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST + 148 | 8 | 00148 | Wed Feb 18 00:00:00 1970 PST + 149 | 509 | 00149_update9 | Thu Feb 19 00:00:00 1970 PST + 150 | 0 | 00150 | Fri Feb 20 00:00:00 1970 PST + 151 | 1 | 00151 | Sat Feb 21 00:00:00 1970 PST + 153 | 303 | 00153_update3 | Mon Feb 23 00:00:00 1970 PST + 154 | 4 | 00154 | Tue Feb 24 00:00:00 1970 PST + 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST + 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST + 158 | 8 | 00158 | Sat Feb 28 00:00:00 1970 PST + 159 | 509 | 00159_update9 | Sun Mar 01 00:00:00 1970 PST + 160 | 0 | 00160 | Mon Mar 02 00:00:00 1970 PST + 161 | 1 | 00161 | Tue Mar 03 00:00:00 1970 PST + 163 | 303 | 00163_update3 | Thu Mar 05 00:00:00 1970 PST + 164 | 4 | 00164 | Fri Mar 06 00:00:00 1970 PST + 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST + 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST + 168 | 8 | 00168 | Tue Mar 10 00:00:00 1970 PST + 169 | 509 | 00169_update9 | Wed Mar 11 00:00:00 1970 PST + 170 | 0 | 00170 | Thu Mar 12 00:00:00 1970 PST + 171 | 1 | 00171 | Fri Mar 13 00:00:00 1970 PST + 173 | 303 | 00173_update3 | Sun Mar 15 00:00:00 1970 PST + 174 | 4 | 00174 | Mon Mar 16 00:00:00 1970 PST + 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST + 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST + 178 | 8 | 00178 | Fri Mar 20 00:00:00 1970 PST + 179 | 509 | 00179_update9 | Sat Mar 21 00:00:00 1970 PST + 180 | 0 | 00180 | Sun Mar 22 00:00:00 1970 PST + 181 | 1 | 00181 | Mon Mar 23 00:00:00 1970 PST + 183 | 303 | 00183_update3 | Wed Mar 25 00:00:00 1970 PST + 184 | 4 | 00184 | Thu Mar 26 00:00:00 1970 PST + 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST + 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST + 188 | 8 | 00188 | Mon Mar 30 00:00:00 1970 PST + 189 | 509 | 00189_update9 | Tue Mar 31 00:00:00 1970 PST + 190 | 0 | 00190 | Wed Apr 01 00:00:00 1970 PST + 191 | 1 | 00191 | Thu Apr 02 00:00:00 1970 PST + 193 | 303 | 00193_update3 | Sat Apr 04 00:00:00 1970 PST + 194 | 4 | 00194 | Sun Apr 05 00:00:00 1970 PST + 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST + 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST + 198 | 8 | 00198 | Thu Apr 09 00:00:00 1970 PST + 199 | 509 | 00199_update9 | Fri Apr 10 00:00:00 1970 PST + 200 | 0 | 00200 | Thu Jan 01 00:00:00 1970 PST + 201 | 1 | 00201 | Fri Jan 02 00:00:00 1970 PST + 203 | 303 | 00203_update3 | Sun Jan 04 00:00:00 1970 PST + 204 | 4 | 00204 | Mon Jan 05 00:00:00 1970 PST + 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST + 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST + 208 | 8 | 00208 | Fri Jan 09 00:00:00 1970 PST + 209 | 509 | 00209_update9 | Sat Jan 10 00:00:00 1970 PST + 210 | 0 | 00210 | Sun Jan 11 00:00:00 1970 PST + 211 | 1 | 00211 | Mon Jan 12 00:00:00 1970 PST + 213 | 303 | 00213_update3 | Wed Jan 14 00:00:00 1970 PST + 214 | 4 | 00214 | Thu Jan 15 00:00:00 1970 PST + 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST + 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST + 218 | 8 | 00218 | Mon Jan 19 00:00:00 1970 PST + 219 | 509 | 00219_update9 | Tue Jan 20 00:00:00 1970 PST + 220 | 0 | 00220 | Wed Jan 21 00:00:00 1970 PST + 221 | 1 | 00221 | Thu Jan 22 00:00:00 1970 PST + 223 | 303 | 00223_update3 | Sat Jan 24 00:00:00 1970 PST + 224 | 4 | 00224 | Sun Jan 25 00:00:00 1970 PST + 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST + 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST + 228 | 8 | 00228 | Thu Jan 29 00:00:00 1970 PST + 229 | 509 | 00229_update9 | Fri Jan 30 00:00:00 1970 PST + 230 | 0 | 00230 | Sat Jan 31 00:00:00 1970 PST + 231 | 1 | 00231 | Sun Feb 01 00:00:00 1970 PST + 233 | 303 | 00233_update3 | Tue Feb 03 00:00:00 1970 PST + 234 | 4 | 00234 | Wed Feb 04 00:00:00 1970 PST + 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST + 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST + 238 | 8 | 00238 | Sun Feb 08 00:00:00 1970 PST + 239 | 509 | 00239_update9 | Mon Feb 09 00:00:00 1970 PST + 240 | 0 | 00240 | Tue Feb 10 00:00:00 1970 PST + 241 | 1 | 00241 | Wed Feb 11 00:00:00 1970 PST + 243 | 303 | 00243_update3 | Fri Feb 13 00:00:00 1970 PST + 244 | 4 | 00244 | Sat Feb 14 00:00:00 1970 PST + 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST + 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST + 248 | 8 | 00248 | Wed Feb 18 00:00:00 1970 PST + 249 | 509 | 00249_update9 | Thu Feb 19 00:00:00 1970 PST + 250 | 0 | 00250 | Fri Feb 20 00:00:00 1970 PST + 251 | 1 | 00251 | Sat Feb 21 00:00:00 1970 PST + 253 | 303 | 00253_update3 | Mon Feb 23 00:00:00 1970 PST + 254 | 4 | 00254 | Tue Feb 24 00:00:00 1970 PST + 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST + 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST + 258 | 8 | 00258 | Sat Feb 28 00:00:00 1970 PST + 259 | 509 | 00259_update9 | Sun Mar 01 00:00:00 1970 PST + 260 | 0 | 00260 | Mon Mar 02 00:00:00 1970 PST + 261 | 1 | 00261 | Tue Mar 03 00:00:00 1970 PST + 263 | 303 | 00263_update3 | Thu Mar 05 00:00:00 1970 PST + 264 | 4 | 00264 | Fri Mar 06 00:00:00 1970 PST + 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST + 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST + 268 | 8 | 00268 | Tue Mar 10 00:00:00 1970 PST + 269 | 509 | 00269_update9 | Wed Mar 11 00:00:00 1970 PST + 270 | 0 | 00270 | Thu Mar 12 00:00:00 1970 PST + 271 | 1 | 00271 | Fri Mar 13 00:00:00 1970 PST + 273 | 303 | 00273_update3 | Sun Mar 15 00:00:00 1970 PST + 274 | 4 | 00274 | Mon Mar 16 00:00:00 1970 PST + 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST + 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST + 278 | 8 | 00278 | Fri Mar 20 00:00:00 1970 PST + 279 | 509 | 00279_update9 | Sat Mar 21 00:00:00 1970 PST + 280 | 0 | 00280 | Sun Mar 22 00:00:00 1970 PST + 281 | 1 | 00281 | Mon Mar 23 00:00:00 1970 PST + 283 | 303 | 00283_update3 | Wed Mar 25 00:00:00 1970 PST + 284 | 4 | 00284 | Thu Mar 26 00:00:00 1970 PST + 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST + 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST + 288 | 8 | 00288 | Mon Mar 30 00:00:00 1970 PST + 289 | 509 | 00289_update9 | Tue Mar 31 00:00:00 1970 PST + 290 | 0 | 00290 | Wed Apr 01 00:00:00 1970 PST + 291 | 1 | 00291 | Thu Apr 02 00:00:00 1970 PST + 293 | 303 | 00293_update3 | Sat Apr 04 00:00:00 1970 PST + 294 | 4 | 00294 | Sun Apr 05 00:00:00 1970 PST + 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST + 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST + 298 | 8 | 00298 | Thu Apr 09 00:00:00 1970 PST + 299 | 509 | 00299_update9 | Fri Apr 10 00:00:00 1970 PST + 300 | 0 | 00300 | Thu Jan 01 00:00:00 1970 PST + 301 | 1 | 00301 | Fri Jan 02 00:00:00 1970 PST + 303 | 303 | 00303_update3 | Sun Jan 04 00:00:00 1970 PST + 304 | 4 | 00304 | Mon Jan 05 00:00:00 1970 PST + 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST + 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST + 308 | 8 | 00308 | Fri Jan 09 00:00:00 1970 PST + 309 | 509 | 00309_update9 | Sat Jan 10 00:00:00 1970 PST + 310 | 0 | 00310 | Sun Jan 11 00:00:00 1970 PST + 311 | 1 | 00311 | Mon Jan 12 00:00:00 1970 PST + 313 | 303 | 00313_update3 | Wed Jan 14 00:00:00 1970 PST + 314 | 4 | 00314 | Thu Jan 15 00:00:00 1970 PST + 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST + 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST + 318 | 8 | 00318 | Mon Jan 19 00:00:00 1970 PST + 319 | 509 | 00319_update9 | Tue Jan 20 00:00:00 1970 PST + 320 | 0 | 00320 | Wed Jan 21 00:00:00 1970 PST + 321 | 1 | 00321 | Thu Jan 22 00:00:00 1970 PST + 323 | 303 | 00323_update3 | Sat Jan 24 00:00:00 1970 PST + 324 | 4 | 00324 | Sun Jan 25 00:00:00 1970 PST + 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST + 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST + 328 | 8 | 00328 | Thu Jan 29 00:00:00 1970 PST + 329 | 509 | 00329_update9 | Fri Jan 30 00:00:00 1970 PST + 330 | 0 | 00330 | Sat Jan 31 00:00:00 1970 PST + 331 | 1 | 00331 | Sun Feb 01 00:00:00 1970 PST + 333 | 303 | 00333_update3 | Tue Feb 03 00:00:00 1970 PST + 334 | 4 | 00334 | Wed Feb 04 00:00:00 1970 PST + 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST + 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST + 338 | 8 | 00338 | Sun Feb 08 00:00:00 1970 PST + 339 | 509 | 00339_update9 | Mon Feb 09 00:00:00 1970 PST + 340 | 0 | 00340 | Tue Feb 10 00:00:00 1970 PST + 341 | 1 | 00341 | Wed Feb 11 00:00:00 1970 PST + 343 | 303 | 00343_update3 | Fri Feb 13 00:00:00 1970 PST + 344 | 4 | 00344 | Sat Feb 14 00:00:00 1970 PST + 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST + 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST + 348 | 8 | 00348 | Wed Feb 18 00:00:00 1970 PST + 349 | 509 | 00349_update9 | Thu Feb 19 00:00:00 1970 PST + 350 | 0 | 00350 | Fri Feb 20 00:00:00 1970 PST + 351 | 1 | 00351 | Sat Feb 21 00:00:00 1970 PST + 353 | 303 | 00353_update3 | Mon Feb 23 00:00:00 1970 PST + 354 | 4 | 00354 | Tue Feb 24 00:00:00 1970 PST + 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST + 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST + 358 | 8 | 00358 | Sat Feb 28 00:00:00 1970 PST + 359 | 509 | 00359_update9 | Sun Mar 01 00:00:00 1970 PST + 360 | 0 | 00360 | Mon Mar 02 00:00:00 1970 PST + 361 | 1 | 00361 | Tue Mar 03 00:00:00 1970 PST + 363 | 303 | 00363_update3 | Thu Mar 05 00:00:00 1970 PST + 364 | 4 | 00364 | Fri Mar 06 00:00:00 1970 PST + 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST + 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST + 368 | 8 | 00368 | Tue Mar 10 00:00:00 1970 PST + 369 | 509 | 00369_update9 | Wed Mar 11 00:00:00 1970 PST + 370 | 0 | 00370 | Thu Mar 12 00:00:00 1970 PST + 371 | 1 | 00371 | Fri Mar 13 00:00:00 1970 PST + 373 | 303 | 00373_update3 | Sun Mar 15 00:00:00 1970 PST + 374 | 4 | 00374 | Mon Mar 16 00:00:00 1970 PST + 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST + 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST + 378 | 8 | 00378 | Fri Mar 20 00:00:00 1970 PST + 379 | 509 | 00379_update9 | Sat Mar 21 00:00:00 1970 PST + 380 | 0 | 00380 | Sun Mar 22 00:00:00 1970 PST + 381 | 1 | 00381 | Mon Mar 23 00:00:00 1970 PST + 383 | 303 | 00383_update3 | Wed Mar 25 00:00:00 1970 PST + 384 | 4 | 00384 | Thu Mar 26 00:00:00 1970 PST + 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST + 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST + 388 | 8 | 00388 | Mon Mar 30 00:00:00 1970 PST + 389 | 509 | 00389_update9 | Tue Mar 31 00:00:00 1970 PST + 390 | 0 | 00390 | Wed Apr 01 00:00:00 1970 PST + 391 | 1 | 00391 | Thu Apr 02 00:00:00 1970 PST + 393 | 303 | 00393_update3 | Sat Apr 04 00:00:00 1970 PST + 394 | 4 | 00394 | Sun Apr 05 00:00:00 1970 PST + 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST + 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST + 398 | 8 | 00398 | Thu Apr 09 00:00:00 1970 PST + 399 | 509 | 00399_update9 | Fri Apr 10 00:00:00 1970 PST + 400 | 0 | 00400 | Thu Jan 01 00:00:00 1970 PST + 401 | 1 | 00401 | Fri Jan 02 00:00:00 1970 PST + 403 | 303 | 00403_update3 | Sun Jan 04 00:00:00 1970 PST + 404 | 4 | 00404 | Mon Jan 05 00:00:00 1970 PST + 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST + 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST + 408 | 8 | 00408 | Fri Jan 09 00:00:00 1970 PST + 409 | 509 | 00409_update9 | Sat Jan 10 00:00:00 1970 PST + 410 | 0 | 00410 | Sun Jan 11 00:00:00 1970 PST + 411 | 1 | 00411 | Mon Jan 12 00:00:00 1970 PST + 413 | 303 | 00413_update3 | Wed Jan 14 00:00:00 1970 PST + 414 | 4 | 00414 | Thu Jan 15 00:00:00 1970 PST + 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST + 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST + 418 | 8 | 00418 | Mon Jan 19 00:00:00 1970 PST + 419 | 509 | 00419_update9 | Tue Jan 20 00:00:00 1970 PST + 420 | 0 | 00420 | Wed Jan 21 00:00:00 1970 PST + 421 | 1 | 00421 | Thu Jan 22 00:00:00 1970 PST + 423 | 303 | 00423_update3 | Sat Jan 24 00:00:00 1970 PST + 424 | 4 | 00424 | Sun Jan 25 00:00:00 1970 PST + 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST + 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST + 428 | 8 | 00428 | Thu Jan 29 00:00:00 1970 PST + 429 | 509 | 00429_update9 | Fri Jan 30 00:00:00 1970 PST + 430 | 0 | 00430 | Sat Jan 31 00:00:00 1970 PST + 431 | 1 | 00431 | Sun Feb 01 00:00:00 1970 PST + 433 | 303 | 00433_update3 | Tue Feb 03 00:00:00 1970 PST + 434 | 4 | 00434 | Wed Feb 04 00:00:00 1970 PST + 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST + 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST + 438 | 8 | 00438 | Sun Feb 08 00:00:00 1970 PST + 439 | 509 | 00439_update9 | Mon Feb 09 00:00:00 1970 PST + 440 | 0 | 00440 | Tue Feb 10 00:00:00 1970 PST + 441 | 1 | 00441 | Wed Feb 11 00:00:00 1970 PST + 443 | 303 | 00443_update3 | Fri Feb 13 00:00:00 1970 PST + 444 | 4 | 00444 | Sat Feb 14 00:00:00 1970 PST + 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST + 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST + 448 | 8 | 00448 | Wed Feb 18 00:00:00 1970 PST + 449 | 509 | 00449_update9 | Thu Feb 19 00:00:00 1970 PST + 450 | 0 | 00450 | Fri Feb 20 00:00:00 1970 PST + 451 | 1 | 00451 | Sat Feb 21 00:00:00 1970 PST + 453 | 303 | 00453_update3 | Mon Feb 23 00:00:00 1970 PST + 454 | 4 | 00454 | Tue Feb 24 00:00:00 1970 PST + 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST + 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST + 458 | 8 | 00458 | Sat Feb 28 00:00:00 1970 PST + 459 | 509 | 00459_update9 | Sun Mar 01 00:00:00 1970 PST + 460 | 0 | 00460 | Mon Mar 02 00:00:00 1970 PST + 461 | 1 | 00461 | Tue Mar 03 00:00:00 1970 PST + 463 | 303 | 00463_update3 | Thu Mar 05 00:00:00 1970 PST + 464 | 4 | 00464 | Fri Mar 06 00:00:00 1970 PST + 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST + 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST + 468 | 8 | 00468 | Tue Mar 10 00:00:00 1970 PST + 469 | 509 | 00469_update9 | Wed Mar 11 00:00:00 1970 PST + 470 | 0 | 00470 | Thu Mar 12 00:00:00 1970 PST + 471 | 1 | 00471 | Fri Mar 13 00:00:00 1970 PST + 473 | 303 | 00473_update3 | Sun Mar 15 00:00:00 1970 PST + 474 | 4 | 00474 | Mon Mar 16 00:00:00 1970 PST + 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST + 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST + 478 | 8 | 00478 | Fri Mar 20 00:00:00 1970 PST + 479 | 509 | 00479_update9 | Sat Mar 21 00:00:00 1970 PST + 480 | 0 | 00480 | Sun Mar 22 00:00:00 1970 PST + 481 | 1 | 00481 | Mon Mar 23 00:00:00 1970 PST + 483 | 303 | 00483_update3 | Wed Mar 25 00:00:00 1970 PST + 484 | 4 | 00484 | Thu Mar 26 00:00:00 1970 PST + 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST + 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST + 488 | 8 | 00488 | Mon Mar 30 00:00:00 1970 PST + 489 | 509 | 00489_update9 | Tue Mar 31 00:00:00 1970 PST + 490 | 0 | 00490 | Wed Apr 01 00:00:00 1970 PST + 491 | 1 | 00491 | Thu Apr 02 00:00:00 1970 PST + 493 | 303 | 00493_update3 | Sat Apr 04 00:00:00 1970 PST + 494 | 4 | 00494 | Sun Apr 05 00:00:00 1970 PST + 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST + 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST + 498 | 8 | 00498 | Thu Apr 09 00:00:00 1970 PST + 499 | 509 | 00499_update9 | Fri Apr 10 00:00:00 1970 PST + 500 | 0 | 00500 | Thu Jan 01 00:00:00 1970 PST + 501 | 1 | 00501 | Fri Jan 02 00:00:00 1970 PST + 503 | 303 | 00503_update3 | Sun Jan 04 00:00:00 1970 PST + 504 | 4 | 00504 | Mon Jan 05 00:00:00 1970 PST + 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST + 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST + 508 | 8 | 00508 | Fri Jan 09 00:00:00 1970 PST + 509 | 509 | 00509_update9 | Sat Jan 10 00:00:00 1970 PST + 510 | 0 | 00510 | Sun Jan 11 00:00:00 1970 PST + 511 | 1 | 00511 | Mon Jan 12 00:00:00 1970 PST + 513 | 303 | 00513_update3 | Wed Jan 14 00:00:00 1970 PST + 514 | 4 | 00514 | Thu Jan 15 00:00:00 1970 PST + 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST + 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST + 518 | 8 | 00518 | Mon Jan 19 00:00:00 1970 PST + 519 | 509 | 00519_update9 | Tue Jan 20 00:00:00 1970 PST + 520 | 0 | 00520 | Wed Jan 21 00:00:00 1970 PST + 521 | 1 | 00521 | Thu Jan 22 00:00:00 1970 PST + 523 | 303 | 00523_update3 | Sat Jan 24 00:00:00 1970 PST + 524 | 4 | 00524 | Sun Jan 25 00:00:00 1970 PST + 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST + 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST + 528 | 8 | 00528 | Thu Jan 29 00:00:00 1970 PST + 529 | 509 | 00529_update9 | Fri Jan 30 00:00:00 1970 PST + 530 | 0 | 00530 | Sat Jan 31 00:00:00 1970 PST + 531 | 1 | 00531 | Sun Feb 01 00:00:00 1970 PST + 533 | 303 | 00533_update3 | Tue Feb 03 00:00:00 1970 PST + 534 | 4 | 00534 | Wed Feb 04 00:00:00 1970 PST + 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST + 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST + 538 | 8 | 00538 | Sun Feb 08 00:00:00 1970 PST + 539 | 509 | 00539_update9 | Mon Feb 09 00:00:00 1970 PST + 540 | 0 | 00540 | Tue Feb 10 00:00:00 1970 PST + 541 | 1 | 00541 | Wed Feb 11 00:00:00 1970 PST + 543 | 303 | 00543_update3 | Fri Feb 13 00:00:00 1970 PST + 544 | 4 | 00544 | Sat Feb 14 00:00:00 1970 PST + 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST + 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST + 548 | 8 | 00548 | Wed Feb 18 00:00:00 1970 PST + 549 | 509 | 00549_update9 | Thu Feb 19 00:00:00 1970 PST + 550 | 0 | 00550 | Fri Feb 20 00:00:00 1970 PST + 551 | 1 | 00551 | Sat Feb 21 00:00:00 1970 PST + 553 | 303 | 00553_update3 | Mon Feb 23 00:00:00 1970 PST + 554 | 4 | 00554 | Tue Feb 24 00:00:00 1970 PST + 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST + 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST + 558 | 8 | 00558 | Sat Feb 28 00:00:00 1970 PST + 559 | 509 | 00559_update9 | Sun Mar 01 00:00:00 1970 PST + 560 | 0 | 00560 | Mon Mar 02 00:00:00 1970 PST + 561 | 1 | 00561 | Tue Mar 03 00:00:00 1970 PST + 563 | 303 | 00563_update3 | Thu Mar 05 00:00:00 1970 PST + 564 | 4 | 00564 | Fri Mar 06 00:00:00 1970 PST + 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST + 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST + 568 | 8 | 00568 | Tue Mar 10 00:00:00 1970 PST + 569 | 509 | 00569_update9 | Wed Mar 11 00:00:00 1970 PST + 570 | 0 | 00570 | Thu Mar 12 00:00:00 1970 PST + 571 | 1 | 00571 | Fri Mar 13 00:00:00 1970 PST + 573 | 303 | 00573_update3 | Sun Mar 15 00:00:00 1970 PST + 574 | 4 | 00574 | Mon Mar 16 00:00:00 1970 PST + 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST + 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST + 578 | 8 | 00578 | Fri Mar 20 00:00:00 1970 PST + 579 | 509 | 00579_update9 | Sat Mar 21 00:00:00 1970 PST + 580 | 0 | 00580 | Sun Mar 22 00:00:00 1970 PST + 581 | 1 | 00581 | Mon Mar 23 00:00:00 1970 PST + 583 | 303 | 00583_update3 | Wed Mar 25 00:00:00 1970 PST + 584 | 4 | 00584 | Thu Mar 26 00:00:00 1970 PST + 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST + 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST + 588 | 8 | 00588 | Mon Mar 30 00:00:00 1970 PST + 589 | 509 | 00589_update9 | Tue Mar 31 00:00:00 1970 PST + 590 | 0 | 00590 | Wed Apr 01 00:00:00 1970 PST + 591 | 1 | 00591 | Thu Apr 02 00:00:00 1970 PST + 593 | 303 | 00593_update3 | Sat Apr 04 00:00:00 1970 PST + 594 | 4 | 00594 | Sun Apr 05 00:00:00 1970 PST + 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST + 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST + 598 | 8 | 00598 | Thu Apr 09 00:00:00 1970 PST + 599 | 509 | 00599_update9 | Fri Apr 10 00:00:00 1970 PST + 600 | 0 | 00600 | Thu Jan 01 00:00:00 1970 PST + 601 | 1 | 00601 | Fri Jan 02 00:00:00 1970 PST + 603 | 303 | 00603_update3 | Sun Jan 04 00:00:00 1970 PST + 604 | 4 | 00604 | Mon Jan 05 00:00:00 1970 PST + 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST + 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST + 608 | 8 | 00608 | Fri Jan 09 00:00:00 1970 PST + 609 | 509 | 00609_update9 | Sat Jan 10 00:00:00 1970 PST + 610 | 0 | 00610 | Sun Jan 11 00:00:00 1970 PST + 611 | 1 | 00611 | Mon Jan 12 00:00:00 1970 PST + 613 | 303 | 00613_update3 | Wed Jan 14 00:00:00 1970 PST + 614 | 4 | 00614 | Thu Jan 15 00:00:00 1970 PST + 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST + 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST + 618 | 8 | 00618 | Mon Jan 19 00:00:00 1970 PST + 619 | 509 | 00619_update9 | Tue Jan 20 00:00:00 1970 PST + 620 | 0 | 00620 | Wed Jan 21 00:00:00 1970 PST + 621 | 1 | 00621 | Thu Jan 22 00:00:00 1970 PST + 623 | 303 | 00623_update3 | Sat Jan 24 00:00:00 1970 PST + 624 | 4 | 00624 | Sun Jan 25 00:00:00 1970 PST + 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST + 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST + 628 | 8 | 00628 | Thu Jan 29 00:00:00 1970 PST + 629 | 509 | 00629_update9 | Fri Jan 30 00:00:00 1970 PST + 630 | 0 | 00630 | Sat Jan 31 00:00:00 1970 PST + 631 | 1 | 00631 | Sun Feb 01 00:00:00 1970 PST + 633 | 303 | 00633_update3 | Tue Feb 03 00:00:00 1970 PST + 634 | 4 | 00634 | Wed Feb 04 00:00:00 1970 PST + 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST + 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST + 638 | 8 | 00638 | Sun Feb 08 00:00:00 1970 PST + 639 | 509 | 00639_update9 | Mon Feb 09 00:00:00 1970 PST + 640 | 0 | 00640 | Tue Feb 10 00:00:00 1970 PST + 641 | 1 | 00641 | Wed Feb 11 00:00:00 1970 PST + 643 | 303 | 00643_update3 | Fri Feb 13 00:00:00 1970 PST + 644 | 4 | 00644 | Sat Feb 14 00:00:00 1970 PST + 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST + 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST + 648 | 8 | 00648 | Wed Feb 18 00:00:00 1970 PST + 649 | 509 | 00649_update9 | Thu Feb 19 00:00:00 1970 PST + 650 | 0 | 00650 | Fri Feb 20 00:00:00 1970 PST + 651 | 1 | 00651 | Sat Feb 21 00:00:00 1970 PST + 653 | 303 | 00653_update3 | Mon Feb 23 00:00:00 1970 PST + 654 | 4 | 00654 | Tue Feb 24 00:00:00 1970 PST + 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST + 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST + 658 | 8 | 00658 | Sat Feb 28 00:00:00 1970 PST + 659 | 509 | 00659_update9 | Sun Mar 01 00:00:00 1970 PST + 660 | 0 | 00660 | Mon Mar 02 00:00:00 1970 PST + 661 | 1 | 00661 | Tue Mar 03 00:00:00 1970 PST + 663 | 303 | 00663_update3 | Thu Mar 05 00:00:00 1970 PST + 664 | 4 | 00664 | Fri Mar 06 00:00:00 1970 PST + 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST + 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST + 668 | 8 | 00668 | Tue Mar 10 00:00:00 1970 PST + 669 | 509 | 00669_update9 | Wed Mar 11 00:00:00 1970 PST + 670 | 0 | 00670 | Thu Mar 12 00:00:00 1970 PST + 671 | 1 | 00671 | Fri Mar 13 00:00:00 1970 PST + 673 | 303 | 00673_update3 | Sun Mar 15 00:00:00 1970 PST + 674 | 4 | 00674 | Mon Mar 16 00:00:00 1970 PST + 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST + 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST + 678 | 8 | 00678 | Fri Mar 20 00:00:00 1970 PST + 679 | 509 | 00679_update9 | Sat Mar 21 00:00:00 1970 PST + 680 | 0 | 00680 | Sun Mar 22 00:00:00 1970 PST + 681 | 1 | 00681 | Mon Mar 23 00:00:00 1970 PST + 683 | 303 | 00683_update3 | Wed Mar 25 00:00:00 1970 PST + 684 | 4 | 00684 | Thu Mar 26 00:00:00 1970 PST + 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST + 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST + 688 | 8 | 00688 | Mon Mar 30 00:00:00 1970 PST + 689 | 509 | 00689_update9 | Tue Mar 31 00:00:00 1970 PST + 690 | 0 | 00690 | Wed Apr 01 00:00:00 1970 PST + 691 | 1 | 00691 | Thu Apr 02 00:00:00 1970 PST + 693 | 303 | 00693_update3 | Sat Apr 04 00:00:00 1970 PST + 694 | 4 | 00694 | Sun Apr 05 00:00:00 1970 PST + 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST + 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST + 698 | 8 | 00698 | Thu Apr 09 00:00:00 1970 PST + 699 | 509 | 00699_update9 | Fri Apr 10 00:00:00 1970 PST + 700 | 0 | 00700 | Thu Jan 01 00:00:00 1970 PST + 701 | 1 | 00701 | Fri Jan 02 00:00:00 1970 PST + 703 | 303 | 00703_update3 | Sun Jan 04 00:00:00 1970 PST + 704 | 4 | 00704 | Mon Jan 05 00:00:00 1970 PST + 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST + 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST + 708 | 8 | 00708 | Fri Jan 09 00:00:00 1970 PST + 709 | 509 | 00709_update9 | Sat Jan 10 00:00:00 1970 PST + 710 | 0 | 00710 | Sun Jan 11 00:00:00 1970 PST + 711 | 1 | 00711 | Mon Jan 12 00:00:00 1970 PST + 713 | 303 | 00713_update3 | Wed Jan 14 00:00:00 1970 PST + 714 | 4 | 00714 | Thu Jan 15 00:00:00 1970 PST + 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST + 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST + 718 | 8 | 00718 | Mon Jan 19 00:00:00 1970 PST + 719 | 509 | 00719_update9 | Tue Jan 20 00:00:00 1970 PST + 720 | 0 | 00720 | Wed Jan 21 00:00:00 1970 PST + 721 | 1 | 00721 | Thu Jan 22 00:00:00 1970 PST + 723 | 303 | 00723_update3 | Sat Jan 24 00:00:00 1970 PST + 724 | 4 | 00724 | Sun Jan 25 00:00:00 1970 PST + 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST + 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST + 728 | 8 | 00728 | Thu Jan 29 00:00:00 1970 PST + 729 | 509 | 00729_update9 | Fri Jan 30 00:00:00 1970 PST + 730 | 0 | 00730 | Sat Jan 31 00:00:00 1970 PST + 731 | 1 | 00731 | Sun Feb 01 00:00:00 1970 PST + 733 | 303 | 00733_update3 | Tue Feb 03 00:00:00 1970 PST + 734 | 4 | 00734 | Wed Feb 04 00:00:00 1970 PST + 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST + 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST + 738 | 8 | 00738 | Sun Feb 08 00:00:00 1970 PST + 739 | 509 | 00739_update9 | Mon Feb 09 00:00:00 1970 PST + 740 | 0 | 00740 | Tue Feb 10 00:00:00 1970 PST + 741 | 1 | 00741 | Wed Feb 11 00:00:00 1970 PST + 743 | 303 | 00743_update3 | Fri Feb 13 00:00:00 1970 PST + 744 | 4 | 00744 | Sat Feb 14 00:00:00 1970 PST + 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST + 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST + 748 | 8 | 00748 | Wed Feb 18 00:00:00 1970 PST + 749 | 509 | 00749_update9 | Thu Feb 19 00:00:00 1970 PST + 750 | 0 | 00750 | Fri Feb 20 00:00:00 1970 PST + 751 | 1 | 00751 | Sat Feb 21 00:00:00 1970 PST + 753 | 303 | 00753_update3 | Mon Feb 23 00:00:00 1970 PST + 754 | 4 | 00754 | Tue Feb 24 00:00:00 1970 PST + 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST + 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST + 758 | 8 | 00758 | Sat Feb 28 00:00:00 1970 PST + 759 | 509 | 00759_update9 | Sun Mar 01 00:00:00 1970 PST + 760 | 0 | 00760 | Mon Mar 02 00:00:00 1970 PST + 761 | 1 | 00761 | Tue Mar 03 00:00:00 1970 PST + 763 | 303 | 00763_update3 | Thu Mar 05 00:00:00 1970 PST + 764 | 4 | 00764 | Fri Mar 06 00:00:00 1970 PST + 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST + 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST + 768 | 8 | 00768 | Tue Mar 10 00:00:00 1970 PST + 769 | 509 | 00769_update9 | Wed Mar 11 00:00:00 1970 PST + 770 | 0 | 00770 | Thu Mar 12 00:00:00 1970 PST + 771 | 1 | 00771 | Fri Mar 13 00:00:00 1970 PST + 773 | 303 | 00773_update3 | Sun Mar 15 00:00:00 1970 PST + 774 | 4 | 00774 | Mon Mar 16 00:00:00 1970 PST + 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST + 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST + 778 | 8 | 00778 | Fri Mar 20 00:00:00 1970 PST + 779 | 509 | 00779_update9 | Sat Mar 21 00:00:00 1970 PST + 780 | 0 | 00780 | Sun Mar 22 00:00:00 1970 PST + 781 | 1 | 00781 | Mon Mar 23 00:00:00 1970 PST + 783 | 303 | 00783_update3 | Wed Mar 25 00:00:00 1970 PST + 784 | 4 | 00784 | Thu Mar 26 00:00:00 1970 PST + 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST + 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST + 788 | 8 | 00788 | Mon Mar 30 00:00:00 1970 PST + 789 | 509 | 00789_update9 | Tue Mar 31 00:00:00 1970 PST + 790 | 0 | 00790 | Wed Apr 01 00:00:00 1970 PST + 791 | 1 | 00791 | Thu Apr 02 00:00:00 1970 PST + 793 | 303 | 00793_update3 | Sat Apr 04 00:00:00 1970 PST + 794 | 4 | 00794 | Sun Apr 05 00:00:00 1970 PST + 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST + 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST + 798 | 8 | 00798 | Thu Apr 09 00:00:00 1970 PST + 799 | 509 | 00799_update9 | Fri Apr 10 00:00:00 1970 PST + 800 | 0 | 00800 | Thu Jan 01 00:00:00 1970 PST + 801 | 1 | 00801 | Fri Jan 02 00:00:00 1970 PST + 803 | 303 | 00803_update3 | Sun Jan 04 00:00:00 1970 PST + 804 | 4 | 00804 | Mon Jan 05 00:00:00 1970 PST + 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST + 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST + 808 | 8 | 00808 | Fri Jan 09 00:00:00 1970 PST + 809 | 509 | 00809_update9 | Sat Jan 10 00:00:00 1970 PST + 810 | 0 | 00810 | Sun Jan 11 00:00:00 1970 PST + 811 | 1 | 00811 | Mon Jan 12 00:00:00 1970 PST + 813 | 303 | 00813_update3 | Wed Jan 14 00:00:00 1970 PST + 814 | 4 | 00814 | Thu Jan 15 00:00:00 1970 PST + 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST + 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST + 818 | 8 | 00818 | Mon Jan 19 00:00:00 1970 PST + 819 | 509 | 00819_update9 | Tue Jan 20 00:00:00 1970 PST + 820 | 0 | 00820 | Wed Jan 21 00:00:00 1970 PST + 821 | 1 | 00821 | Thu Jan 22 00:00:00 1970 PST + 823 | 303 | 00823_update3 | Sat Jan 24 00:00:00 1970 PST + 824 | 4 | 00824 | Sun Jan 25 00:00:00 1970 PST + 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST + 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST + 828 | 8 | 00828 | Thu Jan 29 00:00:00 1970 PST + 829 | 509 | 00829_update9 | Fri Jan 30 00:00:00 1970 PST + 830 | 0 | 00830 | Sat Jan 31 00:00:00 1970 PST + 831 | 1 | 00831 | Sun Feb 01 00:00:00 1970 PST + 833 | 303 | 00833_update3 | Tue Feb 03 00:00:00 1970 PST + 834 | 4 | 00834 | Wed Feb 04 00:00:00 1970 PST + 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST + 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST + 838 | 8 | 00838 | Sun Feb 08 00:00:00 1970 PST + 839 | 509 | 00839_update9 | Mon Feb 09 00:00:00 1970 PST + 840 | 0 | 00840 | Tue Feb 10 00:00:00 1970 PST + 841 | 1 | 00841 | Wed Feb 11 00:00:00 1970 PST + 843 | 303 | 00843_update3 | Fri Feb 13 00:00:00 1970 PST + 844 | 4 | 00844 | Sat Feb 14 00:00:00 1970 PST + 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST + 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST + 848 | 8 | 00848 | Wed Feb 18 00:00:00 1970 PST + 849 | 509 | 00849_update9 | Thu Feb 19 00:00:00 1970 PST + 850 | 0 | 00850 | Fri Feb 20 00:00:00 1970 PST + 851 | 1 | 00851 | Sat Feb 21 00:00:00 1970 PST + 853 | 303 | 00853_update3 | Mon Feb 23 00:00:00 1970 PST + 854 | 4 | 00854 | Tue Feb 24 00:00:00 1970 PST + 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST + 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST + 858 | 8 | 00858 | Sat Feb 28 00:00:00 1970 PST + 859 | 509 | 00859_update9 | Sun Mar 01 00:00:00 1970 PST + 860 | 0 | 00860 | Mon Mar 02 00:00:00 1970 PST + 861 | 1 | 00861 | Tue Mar 03 00:00:00 1970 PST + 863 | 303 | 00863_update3 | Thu Mar 05 00:00:00 1970 PST + 864 | 4 | 00864 | Fri Mar 06 00:00:00 1970 PST + 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST + 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST + 868 | 8 | 00868 | Tue Mar 10 00:00:00 1970 PST + 869 | 509 | 00869_update9 | Wed Mar 11 00:00:00 1970 PST + 870 | 0 | 00870 | Thu Mar 12 00:00:00 1970 PST + 871 | 1 | 00871 | Fri Mar 13 00:00:00 1970 PST + 873 | 303 | 00873_update3 | Sun Mar 15 00:00:00 1970 PST + 874 | 4 | 00874 | Mon Mar 16 00:00:00 1970 PST + 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST + 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST + 878 | 8 | 00878 | Fri Mar 20 00:00:00 1970 PST + 879 | 509 | 00879_update9 | Sat Mar 21 00:00:00 1970 PST + 880 | 0 | 00880 | Sun Mar 22 00:00:00 1970 PST + 881 | 1 | 00881 | Mon Mar 23 00:00:00 1970 PST + 883 | 303 | 00883_update3 | Wed Mar 25 00:00:00 1970 PST + 884 | 4 | 00884 | Thu Mar 26 00:00:00 1970 PST + 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST + 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST + 888 | 8 | 00888 | Mon Mar 30 00:00:00 1970 PST + 889 | 509 | 00889_update9 | Tue Mar 31 00:00:00 1970 PST + 890 | 0 | 00890 | Wed Apr 01 00:00:00 1970 PST + 891 | 1 | 00891 | Thu Apr 02 00:00:00 1970 PST + 893 | 303 | 00893_update3 | Sat Apr 04 00:00:00 1970 PST + 894 | 4 | 00894 | Sun Apr 05 00:00:00 1970 PST + 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST + 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST + 898 | 8 | 00898 | Thu Apr 09 00:00:00 1970 PST + 899 | 509 | 00899_update9 | Fri Apr 10 00:00:00 1970 PST + 900 | 0 | 00900 | Thu Jan 01 00:00:00 1970 PST + 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST + 903 | 303 | 00903_update3 | Sun Jan 04 00:00:00 1970 PST + 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST + 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST + 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST + 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST + 909 | 509 | 00909_update9 | Sat Jan 10 00:00:00 1970 PST + 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST + 911 | 1 | 00911 | Mon Jan 12 00:00:00 1970 PST + 913 | 303 | 00913_update3 | Wed Jan 14 00:00:00 1970 PST + 914 | 4 | 00914 | Thu Jan 15 00:00:00 1970 PST + 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST + 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST + 918 | 8 | 00918 | Mon Jan 19 00:00:00 1970 PST + 919 | 509 | 00919_update9 | Tue Jan 20 00:00:00 1970 PST + 920 | 0 | 00920 | Wed Jan 21 00:00:00 1970 PST + 921 | 1 | 00921 | Thu Jan 22 00:00:00 1970 PST + 923 | 303 | 00923_update3 | Sat Jan 24 00:00:00 1970 PST + 924 | 4 | 00924 | Sun Jan 25 00:00:00 1970 PST + 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST + 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST + 928 | 8 | 00928 | Thu Jan 29 00:00:00 1970 PST + 929 | 509 | 00929_update9 | Fri Jan 30 00:00:00 1970 PST + 930 | 0 | 00930 | Sat Jan 31 00:00:00 1970 PST + 931 | 1 | 00931 | Sun Feb 01 00:00:00 1970 PST + 933 | 303 | 00933_update3 | Tue Feb 03 00:00:00 1970 PST + 934 | 4 | 00934 | Wed Feb 04 00:00:00 1970 PST + 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST + 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST + 938 | 8 | 00938 | Sun Feb 08 00:00:00 1970 PST + 939 | 509 | 00939_update9 | Mon Feb 09 00:00:00 1970 PST + 940 | 0 | 00940 | Tue Feb 10 00:00:00 1970 PST + 941 | 1 | 00941 | Wed Feb 11 00:00:00 1970 PST + 943 | 303 | 00943_update3 | Fri Feb 13 00:00:00 1970 PST + 944 | 4 | 00944 | Sat Feb 14 00:00:00 1970 PST + 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST + 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST + 948 | 8 | 00948 | Wed Feb 18 00:00:00 1970 PST + 949 | 509 | 00949_update9 | Thu Feb 19 00:00:00 1970 PST + 950 | 0 | 00950 | Fri Feb 20 00:00:00 1970 PST + 951 | 1 | 00951 | Sat Feb 21 00:00:00 1970 PST + 953 | 303 | 00953_update3 | Mon Feb 23 00:00:00 1970 PST + 954 | 4 | 00954 | Tue Feb 24 00:00:00 1970 PST + 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST + 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST + 958 | 8 | 00958 | Sat Feb 28 00:00:00 1970 PST + 959 | 509 | 00959_update9 | Sun Mar 01 00:00:00 1970 PST + 960 | 0 | 00960 | Mon Mar 02 00:00:00 1970 PST + 961 | 1 | 00961 | Tue Mar 03 00:00:00 1970 PST + 963 | 303 | 00963_update3 | Thu Mar 05 00:00:00 1970 PST + 964 | 4 | 00964 | Fri Mar 06 00:00:00 1970 PST + 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST + 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST + 968 | 8 | 00968 | Tue Mar 10 00:00:00 1970 PST + 969 | 509 | 00969_update9 | Wed Mar 11 00:00:00 1970 PST + 970 | 0 | 00970 | Thu Mar 12 00:00:00 1970 PST + 971 | 1 | 00971 | Fri Mar 13 00:00:00 1970 PST + 973 | 303 | 00973_update3 | Sun Mar 15 00:00:00 1970 PST + 974 | 4 | 00974 | Mon Mar 16 00:00:00 1970 PST + 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST + 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST + 978 | 8 | 00978 | Fri Mar 20 00:00:00 1970 PST + 979 | 509 | 00979_update9 | Sat Mar 21 00:00:00 1970 PST + 980 | 0 | 00980 | Sun Mar 22 00:00:00 1970 PST + 981 | 1 | 00981 | Mon Mar 23 00:00:00 1970 PST + 983 | 303 | 00983_update3 | Wed Mar 25 00:00:00 1970 PST + 984 | 4 | 00984 | Thu Mar 26 00:00:00 1970 PST + 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST + 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST + 988 | 8 | 00988 | Mon Mar 30 00:00:00 1970 PST + 989 | 509 | 00989_update9 | Tue Mar 31 00:00:00 1970 PST + 990 | 0 | 00990 | Wed Apr 01 00:00:00 1970 PST + 991 | 1 | 00991 | Thu Apr 02 00:00:00 1970 PST + 993 | 303 | 00993_update3 | Sat Apr 04 00:00:00 1970 PST + 994 | 4 | 00994 | Sun Apr 05 00:00:00 1970 PST + 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST + 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST + 998 | 8 | 00998 | Thu Apr 09 00:00:00 1970 PST + 999 | 509 | 00999_update9 | Fri Apr 10 00:00:00 1970 PST + 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST + 1001 | 101 | 0000100001 | + 1003 | 403 | 0000300003_update3 | + 1004 | 104 | 0000400004 | + 1006 | 106 | 0000600006 | + 1007 | 507 | 0000700007_update7 | + 1008 | 108 | 0000800008 | + 1009 | 609 | 0000900009_update9 | + 1010 | 100 | 0001000010 | + 1011 | 101 | 0001100011 | + 1013 | 403 | 0001300013_update3 | + 1014 | 104 | 0001400014 | + 1016 | 106 | 0001600016 | + 1017 | 507 | 0001700017_update7 | + 1018 | 108 | 0001800018 | + 1019 | 609 | 0001900019_update9 | + 1020 | 100 | 0002000020 | + 1101 | 201 | aaa | + 1103 | 503 | ccc_update3 | + 1104 | 204 | ddd | +(819 rows) + +--Testcase 300: +EXPLAIN (verbose, costs off) +INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on public.ft2 + Batch Size: 1 + -> Result + Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text +(4 rows) + +--Testcase 301: +INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); +--Testcase 302: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; -- can be pushed down + QUERY PLAN +--------------------------------------------------------------------------------- + Update on public.ft2 + -> Foreign Update on public.ft2 + SQLite query: UPDATE main."T 1" SET `c3` = 'bar' WHERE ((`C 1` = 1200)) +(3 rows) + +--Testcase 303: +UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; +--Testcase 304: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 WHERE c1 = 1200; -- can be pushed down + QUERY PLAN +--------------------------------------------------------------------- + Delete on public.ft2 + -> Foreign Delete on public.ft2 + SQLite query: DELETE FROM main."T 1" WHERE ((`C 1` = 1200)) +(3 rows) + +--Testcase 305: +DELETE FROM ft2 WHERE c1 = 1200; +-- Test UPDATE/DELETE on a three-table join +--Testcase 306: +INSERT INTO ft2 (c1,c2,c3) + SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id; +--Testcase 307: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'foo' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; -- can be pushed down + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Hash Join + Output: 'foo'::text, ft2.c1, ft2.*, ft4.*, ft5.* + Hash Cond: (ft5.c1 = ft4.c1) + -> Foreign Scan on public.ft5 + Output: ft5.*, ft5.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" + -> Hash + Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 + -> Foreign Scan + Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 + SQLite query: SELECT r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, r1.`c2`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, r2.`c1` FROM (main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)))) + -> Hash Join + Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 + Hash Cond: (ft2.c2 = ft4.c1) + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.*, ft2.c2 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1200)) + -> Hash + Output: ft4.*, ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.*, ft4.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" +(23 rows) + +--Testcase 308: +UPDATE ft2 SET c3 = 'foo' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; +--Testcase 309: +SELECT ft2, ft2.*, ft4, ft4.* + FROM ft2 INNER JOIN ft4 ON (ft2.c1 > 1200 AND ft2.c2 = ft4.c1) + INNER JOIN ft5 ON (ft4.c1 = ft5.c1); + ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3 +--------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+-------- + (1206,6,foo,,,,"ft2 ",) | 1206 | 6 | foo | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006 + (1212,12,foo,,,,"ft2 ",) | 1212 | 12 | foo | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012 + (1218,18,foo,,,,"ft2 ",) | 1218 | 18 | foo | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018 + (1224,24,foo,,,,"ft2 ",) | 1224 | 24 | foo | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024 + (1230,30,foo,,,,"ft2 ",) | 1230 | 30 | foo | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030 + (1236,36,foo,,,,"ft2 ",) | 1236 | 36 | foo | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036 + (1242,42,foo,,,,"ft2 ",) | 1242 | 42 | foo | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042 + (1248,48,foo,,,,"ft2 ",) | 1248 | 48 | foo | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048 + (1254,54,foo,,,,"ft2 ",) | 1254 | 54 | foo | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054 + (1260,60,foo,,,,"ft2 ",) | 1260 | 60 | foo | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060 + (1266,66,foo,,,,"ft2 ",) | 1266 | 66 | foo | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066 + (1272,72,foo,,,,"ft2 ",) | 1272 | 72 | foo | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072 + (1278,78,foo,,,,"ft2 ",) | 1278 | 78 | foo | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078 + (1284,84,foo,,,,"ft2 ",) | 1284 | 84 | foo | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084 + (1290,90,foo,,,,"ft2 ",) | 1290 | 90 | foo | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090 + (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096 +(16 rows) + +--Testcase 310: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 + USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; -- can be pushed down + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Delete on public.ft2 + -> Foreign Scan + Output: ft2.c1, ft4.*, ft5.* + SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END FROM ((main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)) AND (((r1.`C 1` % 10) = 0)))) LEFT JOIN main."T 4" r3 ON (((r2.`c1` = r3.`c1`)))) + -> Hash Left Join + Output: ft2.c1, ft4.*, ft5.* + Hash Cond: (ft4.c1 = ft5.c1) + -> Hash Join + Output: ft2.c1, ft4.*, ft4.c1 + Hash Cond: (ft2.c2 = ft4.c1) + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 1200)) AND (((`C 1` % 10) = 0)) + -> Hash + Output: ft4.*, ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.*, ft4.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" + -> Hash + Output: ft5.*, ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.*, ft5.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" +(23 rows) + +--Testcase 311: +SELECT 100 FROM ft2, ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; + ?column? +---------- + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 +(10 rows) + +--Testcase 570: +DELETE FROM ft2 + USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; +--Testcase 312: +DELETE FROM ft2 WHERE ft2.c1 > 1200; +-- Test UPDATE with a MULTIEXPR sub-select +-- (maybe someday this'll be remotely executable, but not today) +--Testcase 571: +EXPLAIN (verbose, costs off) +UPDATE ft2 AS target SET (c2, c7) = ( + SELECT c2 * 10, c7 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 target + -> Foreign Scan on public.ft2 target + Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), target.c1, target.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1100)) + SubPlan 1 + -> Foreign Scan on public.ft2 src + Output: (src.c2 * 10), src.c7 + SQLite query: SELECT `c2`, `c7` FROM main."T 1" WHERE ((? = `C 1`)) +(8 rows) + +--Testcase 572: +UPDATE ft2 AS target SET (c2, c7) = ( + SELECT c2 * 10, c7 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; +--Testcase 573: +UPDATE ft2 AS target SET (c2) = ( + SELECT c2 / 10 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; +-- Test UPDATE involving a join that can be pushed down, +-- but a SET clause that can't be +--Testcase 812: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END + FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 d + -> Foreign Scan + Output: CASE WHEN (random() >= '0'::double precision) THEN d.c2 ELSE 0 END, d.c1, d.*, t.* + SQLite query: SELECT r1.`c2`, r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`C 1` > 1000)))) + -> Hash Join + Output: d.c2, d.c1, d.*, t.* + Hash Cond: (d.c1 = t.c1) + -> Foreign Scan on public.ft2 d + Output: d.c2, d.c1, d.* + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1000)) + -> Hash + Output: t.*, t.c1 + -> Foreign Scan on public.ft2 t + Output: t.*, t.c1 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(15 rows) + +--Testcase 813: +UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END + FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; +-- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing +-- user-defined operators/functions +--ALTER SERVER loopback OPTIONS (DROP extensions); +--Testcase 574: +INSERT INTO ft2 (c1,c2,c3) + SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id; +--Testcase 575: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Foreign Scan on public.ft2 + Output: 'bar'::text, c1, ft2.* + Filter: (sqlite_fdw_abs(ft2.c1) > 2000) + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" +(5 rows) + +--Testcase 576: +UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; +--Testcase 577: +SELECT * FROM ft2 WHERE sqlite_fdw_abs(c1) > 2000; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+----+-----+----+----+----+------------+---- + 2001 | 1 | bar | | | | ft2 | + 2002 | 2 | bar | | | | ft2 | + 2003 | 3 | bar | | | | ft2 | + 2004 | 4 | bar | | | | ft2 | + 2005 | 5 | bar | | | | ft2 | + 2006 | 6 | bar | | | | ft2 | + 2007 | 7 | bar | | | | ft2 | + 2008 | 8 | bar | | | | ft2 | + 2009 | 9 | bar | | | | ft2 | + 2010 | 0 | bar | | | | ft2 | +(10 rows) + +--Testcase 578: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'baz' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; -- can't be pushed down + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + -> Nested Loop + Output: 'baz'::text, ft2.c1, ft2.*, ft4.*, ft5.* + Join Filter: (ft2.c2 === ft4.c1) + -> Hash Join + Output: ft4.*, ft4.c1, ft5.* + Hash Cond: (ft4.c1 = ft5.c1) + -> Foreign Scan on public.ft4 + Output: ft4.*, ft4.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" + -> Hash + Output: ft5.*, ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.*, ft5.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" + -> Materialize + Output: ft2.c1, ft2.*, ft2.c2 + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.*, ft2.c2 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 2000)) +(20 rows) + +--Testcase 579: +UPDATE ft2 SET c3 = 'baz' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; +--Testcase 580: +SELECT ft2.*, ft4.*, ft5.* + FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 +------+----+-----+----+----+----+------------+----+----+----+--------+----+----+-------- + 2006 | 6 | baz | | | | ft2 | | 6 | 7 | AAA006 | 6 | 7 | AAA006 +(1 row) + +--Testcase 581: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 + USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Delete on public.ft2 + -> Nested Loop + Output: ft2.c1, ft4.*, ft5.* + Join Filter: (ft4.c1 === ft5.c1) + -> Hash Join + Output: ft2.c1, ft4.*, ft4.c1 + Hash Cond: (ft4.c1 = ft2.c2) + -> Foreign Scan on public.ft4 + Output: ft4.*, ft4.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" + -> Hash + Output: ft2.c1, ft2.c2 + -> Foreign Scan on public.ft2 + Output: ft2.c1, ft2.c2 + SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 2000)) + -> Materialize + Output: ft5.*, ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.*, ft5.c1 + SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" +(20 rows) + +--Testcase 582: +SELECT ft2.c1, ft2.c2, ft2.c3 FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down + c1 | c2 | c3 +------+----+----- + 2006 | 6 | baz +(1 row) + +--Testcase 583: +DELETE FROM ft2 + USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; +--Testcase 584: +DELETE FROM ft2 WHERE ft2.c1 > 2000; +--ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +-- Test that trigger on remote table works as expected +--Testcase 585: +CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$ +BEGIN + NEW.c3 = NEW.c3 || '_trig_update'; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +--Testcase 586: +CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE + ON ft2 FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG(); +--Testcase 313: +INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff'); +--Testcase 314: +SELECT * FROM ft2 WHERE c1 = 1208; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+-----------------+----+----+----+------------+---- + 1208 | 818 | fff_trig_update | | | | ft2 | +(1 row) + +--Testcase 315: +INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;'); +--Testcase 316: +SELECT * FROM ft2 WHERE c1 = 1218; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+-----------------+----+----+------+------------+---- + 1218 | 818 | ggg_trig_update | | | (--; | ft2 | +(1 row) + +--Testcase 317: +UPDATE ft2 SET c2 = c2 + 600, c3 = c3 WHERE c1 % 10 = 8 AND c1 < 1200; +--Testcase 318: +SELECT * FROM ft2 WHERE c1 % 10 = 8 AND c1 < 1200; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+------------------------+------------------------------+--------------------------+----+------------+----- + 8 | 608 | 00008_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 18 | 608 | 00018_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 28 | 608 | 00028_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 38 | 608 | 00038_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 48 | 608 | 00048_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 58 | 608 | 00058_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 68 | 608 | 00068_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 78 | 608 | 00078_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 88 | 608 | 00088_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 98 | 608 | 00098_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 108 | 608 | 00108_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 118 | 608 | 00118_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 128 | 608 | 00128_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 138 | 608 | 00138_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 148 | 608 | 00148_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 158 | 608 | 00158_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 168 | 608 | 00168_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 178 | 608 | 00178_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 188 | 608 | 00188_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 198 | 608 | 00198_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 208 | 608 | 00208_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 218 | 608 | 00218_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 228 | 608 | 00228_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 238 | 608 | 00238_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 248 | 608 | 00248_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 258 | 608 | 00258_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 268 | 608 | 00268_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 278 | 608 | 00278_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 288 | 608 | 00288_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 298 | 608 | 00298_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 308 | 608 | 00308_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 318 | 608 | 00318_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 328 | 608 | 00328_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 338 | 608 | 00338_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 348 | 608 | 00348_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 358 | 608 | 00358_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 368 | 608 | 00368_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 378 | 608 | 00378_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 388 | 608 | 00388_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 398 | 608 | 00398_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 408 | 608 | 00408_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 418 | 608 | 00418_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 428 | 608 | 00428_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 438 | 608 | 00438_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 448 | 608 | 00448_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 458 | 608 | 00458_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 468 | 608 | 00468_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 478 | 608 | 00478_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 488 | 608 | 00488_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 498 | 608 | 00498_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 508 | 608 | 00508_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 518 | 608 | 00518_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 528 | 608 | 00528_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 538 | 608 | 00538_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 548 | 608 | 00548_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 558 | 608 | 00558_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 568 | 608 | 00568_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 578 | 608 | 00578_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 588 | 608 | 00588_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 598 | 608 | 00598_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 608 | 608 | 00608_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 618 | 608 | 00618_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 628 | 608 | 00628_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 638 | 608 | 00638_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 648 | 608 | 00648_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 658 | 608 | 00658_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 668 | 608 | 00668_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 678 | 608 | 00678_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 688 | 608 | 00688_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 698 | 608 | 00698_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 708 | 608 | 00708_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 718 | 608 | 00718_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 728 | 608 | 00728_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 738 | 608 | 00738_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 748 | 608 | 00748_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 758 | 608 | 00758_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 768 | 608 | 00768_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 778 | 608 | 00778_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 788 | 608 | 00788_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 798 | 608 | 00798_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 808 | 608 | 00808_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 818 | 608 | 00818_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 828 | 608 | 00828_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 838 | 608 | 00838_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 848 | 608 | 00848_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 858 | 608 | 00858_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 868 | 608 | 00868_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 878 | 608 | 00878_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 888 | 608 | 00888_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 898 | 608 | 00898_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 908 | 608 | 00908_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo + 918 | 608 | 00918_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo + 928 | 608 | 00928_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo + 938 | 608 | 00938_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo + 948 | 608 | 00948_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo + 958 | 608 | 00958_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo + 968 | 608 | 00968_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo + 978 | 608 | 00978_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo + 988 | 608 | 00988_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo + 998 | 608 | 00998_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo + 1008 | 708 | 0000800008_trig_update | | | | ft2 | + 1018 | 708 | 0001800018_trig_update | | | | ft2 | +(102 rows) + +-- Test errors thrown on remote side during update +-- create table in the remote server with check contraint +--Testcase 738: +CREATE FOREIGN TABLE ft1_constraint ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_svr OPTIONS (table 't1_constraint'); +--Testcase 747: +INSERT INTO ft1_constraint SELECT * FROM ft1 ON CONFLICT DO NOTHING; +-- c2 must be greater than or equal to 0, so this case is ignored. +--Testcase 754: +INSERT INTO ft1_constraint(c1, c2) VALUES (2222, -2) ON CONFLICT DO NOTHING; -- ignore, do nothing +--Testcase 755: +SELECT c1, c2 FROM ft1_constraint WHERE c1 = 2222 or c2 = -2; -- empty result + c1 | c2 +----+---- +(0 rows) + +--Testcase 748: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; +--Testcase 749: +ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; +--Testcase 319: +INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: t1_constraint.c1', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) +--Testcase 320: +INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +--Testcase 321: +INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +--Testcase 743: +INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive +ERROR: Failed to execute remote SQL +HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) +--Testcase 744: +UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive +ERROR: Failed to execute remote SQL +HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 +CONTEXT: SQL query: UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) +--Testcase 750: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_constraint; +--Testcase 751: +ALTER FOREIGN TABLE ft1_org RENAME TO ft1; +-- Test savepoint/rollback behavior +--Testcase 322: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 0 | 100 + 1 | 100 + 4 | 100 + 6 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +--Testcase 323: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 0 | 100 + 1 | 100 + 4 | 100 + 6 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +begin; +--Testcase 324: +update ft2 set c2 = 42 where c2 = 0; +--Testcase 325: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 4 | 100 + 6 | 100 + 42 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +savepoint s1; +--Testcase 326: +update ft2 set c2 = 44 where c2 = 4; +--Testcase 327: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +release savepoint s1; +--Testcase 328: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +savepoint s2; +--Testcase 329: +update ft2 set c2 = 46 where c2 = 6; +--Testcase 330: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 42 | 100 + 44 | 100 + 46 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +rollback to savepoint s2; +--Testcase 331: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +release savepoint s2; +--Testcase 332: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +savepoint s3; +--Testcase 333: +--skip, does not support CHECK +--update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side +rollback to savepoint s3; +--Testcase 334: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +release savepoint s3; +--Testcase 335: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +-- none of the above is committed yet remotely +--Testcase 336: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +commit; +--Testcase 337: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +--Testcase 338: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; + c2 | count +-----+------- + 1 | 100 + 6 | 100 + 42 | 100 + 44 | 100 + 100 | 2 + 101 | 2 + 104 | 2 + 106 | 2 + 201 | 1 + 204 | 1 + 303 | 100 + 403 | 2 + 407 | 100 +(13 rows) + +--VACUUM ANALYZE "S 1"."T 1"; +-- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs +-- FIRST behavior here. +-- ORDER BY DESC NULLS LAST options +--Testcase 339: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 795 +(3 rows) + +--Testcase 340: +SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+--------------------+------------------------------+--------------------------+------+------------+----- + 960 | 42 | 00960_trig_update | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0 | 0 | foo + 970 | 42 | 00970_trig_update | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0 | 0 | foo + 980 | 42 | 00980_trig_update | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0 | 0 | foo + 990 | 42 | 00990_trig_update | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0 | 0 | foo + 1000 | 42 | 01000_trig_update | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo + 1218 | 818 | ggg_trig_update | | | (--; | ft2 | + 1001 | 101 | 0000100001 | | | | ft2 | + 1003 | 403 | 0000300003_update3 | | | | ft2 | + 1004 | 104 | 0000400004 | | | | ft2 | + 1006 | 106 | 0000600006 | | | | ft2 | +(10 rows) + +-- ORDER BY DESC NULLS FIRST options +--Testcase 341: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 +(3 rows) + +--Testcase 342: +SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+-----------------+------------------------------+--------------------------+----+------------+----- + 1020 | 100 | 0002000020 | | | | ft2 | + 1101 | 201 | aaa | | | | ft2 | + 1103 | 503 | ccc_update3 | | | | ft2 | + 1104 | 204 | ddd | | | | ft2 | + 1208 | 818 | fff_trig_update | | | | ft2 | + 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | ft2 | foo + 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | ft2 | foo + 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9 | ft2 | foo + 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9 | ft2 | foo + 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9 | ft2 | foo +(10 rows) + +-- ORDER BY ASC NULLS FIRST options +--Testcase 343: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, c2, c3, c4, c5, c6, c7, c8 + SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` ASC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 +(3 rows) + +--Testcase 344: +SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +------+-----+-------------------+------------------------------+--------------------------+------+------------+----- + 1020 | 100 | 0002000020 | | | | ft2 | + 1101 | 201 | aaa | | | | ft2 | + 1103 | 503 | ccc_update3 | | | | ft2 | + 1104 | 204 | ddd | | | | ft2 | + 1208 | 818 | fff_trig_update | | | | ft2 | + 1218 | 818 | ggg_trig_update | | | (--; | ft2 | + 10 | 42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo + 20 | 42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0 | 0 | foo + 30 | 42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0 | 0 | foo + 40 | 42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0 | 0 | foo +(10 rows) + +-- Test ReScan code path that recreates the cursor even when no parameters +-- change (bug #17889) +--Testcase 1032: +CREATE FOREIGN TABLE loct1_rescan (c1 int OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'loct1_rescan'); +--Testcase 1033: +CREATE FOREIGN TABLE loct2_rescan (c1 int OPTIONS (key 'true'), c2 text) SERVER sqlite_svr OPTIONS (table 'loct2_rescan'); +--Testcase 1034: +INSERT INTO loct1_rescan VALUES (1001); +--Testcase 1035: +INSERT INTO loct1_rescan VALUES (1002); +--Testcase 1036: +INSERT INTO loct2_rescan SELECT id, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; +--Testcase 1037: +INSERT INTO loct2_rescan VALUES (1001, 'foo'); +--Testcase 1038: +INSERT INTO loct2_rescan VALUES (1002, 'bar'); +--Testcase 1039: +CREATE FOREIGN TABLE remt2_rescan (c1 int OPTIONS (key 'true'), c2 text) SERVER sqlite_svr OPTIONS (table 'loct2_rescan'); +-- ANALYZE loct1_rescan; +-- ANALYZE remt2_rescan; +SET enable_mergejoin TO false; +SET enable_hashjoin TO false; +SET enable_material TO false; +--Testcase 1040: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE remt2_rescan SET c2 = remt2_rescan.c2 || remt2_rescan.c2 FROM loct1_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.remt2_rescan + -> Foreign Scan + Output: (remt2_rescan.c2 || remt2_rescan.c2), remt2_rescan.c1, remt2_rescan.*, loct1_rescan.* + SQLite query: SELECT r1.`c2`, r1.`c1`, CASE WHEN ( r1.`c1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) THEN ("(" || COALESCE(r1.`c1`, '') || "," || COALESCE(r1.`c2`, '')|| ")") END, CASE WHEN ( r2.`c1` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '')|| ")") END FROM (main."loct2_rescan" r1 INNER JOIN main."loct1_rescan" r2 ON (((r1.`c1` = r2.`c1`)))) + -> Nested Loop + Output: remt2_rescan.c2, remt2_rescan.c1, remt2_rescan.*, loct1_rescan.* + Join Filter: (remt2_rescan.c1 = loct1_rescan.c1) + -> Foreign Scan on public.remt2_rescan + Output: remt2_rescan.c2, remt2_rescan.c1, remt2_rescan.* + SQLite query: SELECT `c1`, `c2` FROM main."loct2_rescan" + -> Foreign Scan on public.loct1_rescan + Output: loct1_rescan.*, loct1_rescan.c1 + SQLite query: SELECT `c1` FROM main."loct1_rescan" +(13 rows) + +--Testcase 1041: +UPDATE remt2_rescan SET c2 = remt2_rescan.c2 || remt2_rescan.c2 FROM loct1_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; +--Testcase 1042: +SELECT remt2_rescan.* FROM loct1_rescan, remt2_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; + c1 | c2 +------+-------- + 1001 | foofoo + 1002 | barbar +(2 rows) + +RESET enable_mergejoin; +RESET enable_hashjoin; +RESET enable_material; +--Testcase 1043: +DROP FOREIGN TABLE loct1_rescan; +--Testcase 1044: +DROP FOREIGN TABLE loct2_rescan; +--Testcase 1045: +DROP FOREIGN TABLE remt2_rescan; +-- =================================================================== +-- test check constraints +-- =================================================================== +--Testcase 752: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; +--Testcase 753: +ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; +-- Consistent check constraints provide consistent results +--Testcase 814: +ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0); +--Testcase 587: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; + QUERY PLAN +------------------------------------------------------------------------------ + Foreign Scan + Output: (count(*)) + SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` < 0)) +(3 rows) + +--Testcase 588: +SELECT count(*) FROM ft1 WHERE c2 < 0; + count +------- + 0 +(1 row) + +--Testcase 815: +SET constraint_exclusion = 'on'; +--Testcase 589: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; + QUERY PLAN +-------------------------------- + Aggregate + Output: count(*) + -> Result + One-Time Filter: false +(4 rows) + +--Testcase 590: +SELECT count(*) FROM ft1 WHERE c2 < 0; + count +------- + 0 +(1 row) + +--Testcase 816: +RESET constraint_exclusion; +-- check constraint is enforced on the remote side, not locally +--Testcase 745: +INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive +ERROR: Failed to execute remote SQL +HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) +--Testcase 746: +UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive +ERROR: Failed to execute remote SQL +HINT: SQLite error 'CHECK constraint failed: c2 >= 0', SQLite result code 19 +CONTEXT: SQL query: UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) +--Testcase 817: +ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive; +-- But inconsistent check constraints provide inconsistent results +--Testcase 818: +ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0); +--Testcase 591: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; + QUERY PLAN +------------------------------------------------------------------------------- + Foreign Scan + Output: (count(*)) + SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` >= 0)) +(3 rows) + +--Testcase 592: +SELECT count(*) FROM ft1 WHERE c2 >= 0; + count +------- + 821 +(1 row) + +--Testcase 819: +SET constraint_exclusion = 'on'; +--Testcase 593: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; + QUERY PLAN +-------------------------------- + Aggregate + Output: count(*) + -> Result + One-Time Filter: false +(4 rows) + +--Testcase 594: +SELECT count(*) FROM ft1 WHERE c2 >= 0; + count +------- + 0 +(1 row) + +--Testcase 820: +RESET constraint_exclusion; +-- local check constraint is not actually enforced +--Testcase 595: +INSERT INTO ft1(c1, c2) VALUES(1111, 2); +--Testcase 596: +UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1; +--Testcase 821: +ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative; +-- =================================================================== +-- test WITH CHECK OPTION constraints +-- =================================================================== +--Testcase 597: +CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql; +--Testcase 598: +CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) + SERVER sqlite_svr; +--Testcase 599: +CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); +--Testcase 600: +CREATE VIEW rw_view AS SELECT * FROM foreign_tbl + WHERE a < b WITH CHECK OPTION; +--Testcase 601: +\d+ rw_view + View "public.rw_view" + Column | Type | Collation | Nullable | Default | Storage | Description +--------+---------+-----------+----------+---------+---------+------------- + a | integer | | | | plain | + b | integer | | | | plain | +View definition: + SELECT a, + b + FROM foreign_tbl + WHERE a < b; +Options: check_option=cascaded + +--Testcase 345: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 5); + QUERY PLAN +------------------------------ + Insert on public.foreign_tbl + Batch Size: 1 + -> Result + Output: 0, 5 +(4 rows) + +--Testcase 602: +INSERT INTO rw_view VALUES (0, 5); -- should fail +ERROR: new row violates check option for view "rw_view" +DETAIL: Failing row contains (10, 5). +--Testcase 603: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15); + QUERY PLAN +------------------------------ + Insert on public.foreign_tbl + Batch Size: 1 + -> Result + Output: 0, 15 +(4 rows) + +--Testcase 604: +INSERT INTO rw_view VALUES (0, 15); -- error +--Testcase 605: +SELECT * FROM foreign_tbl; + a | b +----+---- + 10 | 15 +(1 row) + +--Testcase 606: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 5; + QUERY PLAN +----------------------------------------------------------------------------------- + Update on public.foreign_tbl + -> Foreign Scan on public.foreign_tbl + Output: (foreign_tbl.b + 5), foreign_tbl.a, foreign_tbl.* + SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) +(4 rows) + +--Testcase 607: +UPDATE rw_view SET b = b + 5; -- should fail +ERROR: new row violates check option for view "rw_view" +DETAIL: Failing row contains (20, 20). +--Testcase 608: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 15; + QUERY PLAN +----------------------------------------------------------------------------------- + Update on public.foreign_tbl + -> Foreign Scan on public.foreign_tbl + Output: (foreign_tbl.b + 15), foreign_tbl.a, foreign_tbl.* + SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) +(4 rows) + +--Testcase 609: +UPDATE rw_view SET b = b + 15; -- ok +--Testcase 610: +SELECT * FROM foreign_tbl; + a | b +----+---- + 20 | 30 +(1 row) + +-- We don't allow batch insert when there are any WCO constraints +ALTER SERVER sqlite_svr OPTIONS (ADD batch_size '10'); +--Testcase 989: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15), (1, 5); + QUERY PLAN +-------------------------------------------------------- + Insert on public.foreign_tbl + Batch Size: 1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2 +(4 rows) + +--Testcase 990: +INSERT INTO rw_view VALUES (0, 15), (1, 5); -- should fail +ERROR: new row violates check option for view "rw_view" +DETAIL: Failing row contains (11, 5). +--Testcase 991: +SELECT * FROM foreign_tbl; + a | b +----+---- + 20 | 30 +(1 row) + +ALTER SERVER sqlite_svr OPTIONS (DROP batch_size); +--Testcase 611: +DROP FOREIGN TABLE foreign_tbl CASCADE; +NOTICE: drop cascades to view rw_view +--Testcase 612: +DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; +ERROR: relation "foreign_tbl" does not exist +-- test WCO for partitions +--Testcase 613: +CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) + SERVER sqlite_svr; +--Testcase 614: +CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); +--Testcase 615: +CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a); +--Testcase 822: +ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); +-- Detach and re-attach once, to stress the concurrent detach case. +--Testcase 975: +ALTER TABLE parent_tbl DETACH PARTITION foreign_tbl CONCURRENTLY; +--Testcase 976: +ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); +--Testcase 616: +CREATE VIEW rw_view AS SELECT * FROM parent_tbl + WHERE a < b WITH CHECK OPTION; +--Testcase 617: +\d+ rw_view + View "public.rw_view" + Column | Type | Collation | Nullable | Default | Storage | Description +--------+---------+-----------+----------+---------+---------+------------- + a | integer | | | | plain | + b | integer | | | | plain | +View definition: + SELECT a, + b + FROM parent_tbl + WHERE a < b; +Options: check_option=cascaded + +--Testcase 618: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 5); + QUERY PLAN +----------------------------- + Insert on public.parent_tbl + -> Result + Output: 0, 5 +(3 rows) + +--Testcase 619: +INSERT INTO rw_view VALUES (0, 5); -- should fail +ERROR: Not support partition insert +--Testcase 620: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15); + QUERY PLAN +----------------------------- + Insert on public.parent_tbl + -> Result + Output: 0, 15 +(3 rows) + +--Testcase 621: +INSERT INTO rw_view VALUES (0, 15); -- ok +ERROR: Not support partition insert +--Testcase 622: +SELECT * FROM foreign_tbl; + a | b +----+---- + 20 | 30 +(1 row) + +--Testcase 623: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 5; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Update on public.parent_tbl + Foreign Update on public.foreign_tbl parent_tbl_1 + -> Foreign Scan on public.foreign_tbl parent_tbl_1 + Output: (parent_tbl_1.b + 5), parent_tbl_1.tableoid, parent_tbl_1.a, parent_tbl_1.* + SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) +(5 rows) + +--Testcase 624: +UPDATE rw_view SET b = b + 5; -- should fail +--Testcase 625: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 15; + QUERY PLAN +---------------------------------------------------------------------------------------------- + Update on public.parent_tbl + Foreign Update on public.foreign_tbl parent_tbl_1 + -> Foreign Scan on public.foreign_tbl parent_tbl_1 + Output: (parent_tbl_1.b + 15), parent_tbl_1.tableoid, parent_tbl_1.a, parent_tbl_1.* + SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) +(5 rows) + +--Testcase 626: +UPDATE rw_view SET b = b + 15; -- ok +--Testcase 627: +SELECT * FROM foreign_tbl; + a | b +----+---- + 40 | 50 +(1 row) + +-- We don't allow batch insert when there are any WCO constraints +ALTER SERVER sqlite_svr OPTIONS (ADD batch_size '10'); +--Testcase 992: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15), (1, 5); + QUERY PLAN +-------------------------------------------------------- + Insert on public.parent_tbl + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2 +(3 rows) + +--Testcase 993: +INSERT INTO rw_view VALUES (0, 15), (1, 5); -- should fail +ERROR: Not support partition insert +--Testcase 994: +SELECT * FROM foreign_tbl; + a | b +----+---- + 40 | 50 +(1 row) + +ALTER SERVER sqlite_svr OPTIONS (DROP batch_size); +--Testcase 628: +DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; +--Testcase 629: +DROP FOREIGN TABLE foreign_tbl CASCADE; +--Testcase 630: +DROP TABLE parent_tbl CASCADE; +NOTICE: drop cascades to view rw_view +--Testcase 631: +DROP FUNCTION row_before_insupd_trigfunc; +-- -- Try a more complex permutation of WCO where there are multiple levels of +-- -- partitioned tables with columns not all in the same order +-- CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a); +-- CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a); +-- ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10); +-- CREATE TABLE child_local (b text, c numeric, a int); +-- CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int) +-- SERVER loopback OPTIONS (table_name 'child_local'); +-- ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10); +-- CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION; +-- INSERT INTO parent_tbl (a) VALUES(1),(5); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- UPDATE rw_view SET b = 'text', c = 123.456; +-- UPDATE rw_view SET b = 'text', c = 123.456; +-- SELECT * FROM parent_tbl ORDER BY a; +-- DROP VIEW rw_view; +-- DROP TABLE child_local; +-- DROP FOREIGN TABLE child_foreign; +-- DROP TABLE sub_parent; +-- DROP TABLE parent_tbl; +-- =================================================================== +-- test serial columns (ie, sequence-based defaults) +-- =================================================================== +--Testcase 632: +create foreign table loc1 (f1 serial, f2 text, id integer options (key 'true')) + server sqlite_svr; +--Testcase 633: +create foreign table rem1 (f1 serial, f2 text, id integer options (key 'true')) + server sqlite_svr options(table 'loc1'); +--Testcase 352: +select pg_catalog.setval('rem1_f1_seq', 10, false); + setval +-------- + 10 +(1 row) + +--Testcase 353: +insert into loc1(f2) values('hi'); +--Testcase 634: +insert into rem1(f2) values('hi remote'); +--Testcase 354: +insert into loc1(f2) values('bye'); +--Testcase 635: +insert into rem1(f2) values('bye remote'); +--Testcase 355: +select f1, f2 from loc1; + f1 | f2 +----+------------ + 1 | hi + 10 | hi remote + 2 | bye + 11 | bye remote +(4 rows) + +--Testcase 636: +select f1, f2 from rem1; + f1 | f2 +----+------------ + 1 | hi + 10 | hi remote + 2 | bye + 11 | bye remote +(4 rows) + +-- =================================================================== +-- test generated columns +-- =================================================================== +--Testcase 637: +create foreign table grem1 ( + a int options (key 'true'), + b int generated always as (a * 2) stored) + server sqlite_svr options(table 'grem1_post14'); +--Testcase 638: +explain (verbose, costs off) +insert into grem1 (a) values (1), (2); + QUERY PLAN +--------------------------------------------------- + Insert on public.grem1 + Batch Size: 1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, NULL::integer +(4 rows) + +--Testcase 823: +insert into grem1 (a) values (1), (2); +--Testcase 639: +explain (verbose, costs off) +update grem1 set a = 22 where a = 2; + QUERY PLAN +---------------------------------------------------------------------------------- + Update on public.grem1 + -> Foreign Scan on public.grem1 + Output: 22, a, grem1.* + SQLite query: SELECT `a`, `b` FROM main."grem1_post14" WHERE ((`a` = 2)) +(4 rows) + +--Testcase 824: +update grem1 set a = 22 where a = 2; +--Testcase 640: +select * from grem1; + a | b +----+---- + 1 | 2 + 22 | 44 +(2 rows) + +--Testcase 825: +delete from grem1; +-- -- test copy from +-- copy grem1 from stdin; +-- 1 +-- 2 +-- \. +-- select * from grem1; +-- delete from grem1; +-- test batch insert +--Testcase 826: +alter server sqlite_svr options (add batch_size '10'); +--Testcase 827: +explain (verbose, costs off) +insert into grem1 (a) values (1), (2); + QUERY PLAN +--------------------------------------------------- + Insert on public.grem1 + Batch Size: 10 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, NULL::integer +(4 rows) + +--Testcase 828: +insert into grem1 (a) values (1), (2); +--Testcase 829: +select * from grem1; + a | b +---+--- + 1 | 2 + 2 | 4 +(2 rows) + +--Testcase 830: +delete from grem1; +-- -- batch insert with foreign partitions. +-- -- This schema uses two partitions, one local and one remote with a modulo +-- -- to loop across all of them in batches. +-- create table tab_batch_local (id int, data text); +-- insert into tab_batch_local select i, 'test'|| i from generate_series(1, 45) i; +-- create table tab_batch_sharded (id int, data text) partition by hash(id); +-- create table tab_batch_sharded_p0 partition of tab_batch_sharded +-- for values with (modulus 2, remainder 0); +-- create table tab_batch_sharded_p1_remote (id int, data text); +-- create foreign table tab_batch_sharded_p1 partition of tab_batch_sharded +-- for values with (modulus 2, remainder 1) +-- server loopback options (table_name 'tab_batch_sharded_p1_remote'); +-- insert into tab_batch_sharded select * from tab_batch_local; +-- select count(*) from tab_batch_sharded; +-- drop table tab_batch_local; +-- drop table tab_batch_sharded; +-- drop table tab_batch_sharded_p1_remote; +--Testcase 831: +alter server sqlite_svr options (drop batch_size); +-- =================================================================== +-- test local triggers +-- =================================================================== +-- Trigger functions "borrowed" from triggers regress test. +--Testcase 641: +CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$ +BEGIN + RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %', + TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; + RETURN NULL; +END;$$; +--Testcase 642: +CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 1005: +CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 644: +CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger +LANGUAGE plpgsql AS $$ + +declare + oldnew text[]; + relid text; + argstr text; +begin + + relid := TG_relid::regclass; + argstr := ''; + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + + RAISE NOTICE '%(%) % % % ON %', + tg_name, argstr, TG_when, TG_level, TG_OP, relid; + oldnew := '{}'::text[]; + if TG_OP != 'INSERT' then + oldnew := array_append(oldnew, format('OLD: %s', OLD)); + end if; + + if TG_OP != 'DELETE' then + oldnew := array_append(oldnew, format('NEW: %s', NEW)); + end if; + + RAISE NOTICE '%', array_to_string(oldnew, ','); + + if TG_OP = 'DELETE' then + return OLD; + else + return NEW; + end if; +end; +$$; +-- Test basic functionality +--Testcase 645: +CREATE TRIGGER trig_row_before +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 646: +CREATE TRIGGER trig_row_after +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 356: +delete from rem1; +NOTICE: trigger_func() called: action = DELETE, when = BEFORE, level = STATEMENT +NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 +NOTICE: OLD: (1,hi,1) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 +NOTICE: OLD: (10,"hi remote",2) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 +NOTICE: OLD: (2,bye,3) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 +NOTICE: OLD: (11,"bye remote",4) +NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (1,hi,1) +NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (10,"hi remote",2) +NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (2,bye,3) +NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (11,"bye remote",4) +NOTICE: trigger_func() called: action = DELETE, when = AFTER, level = STATEMENT +--Testcase 357: +insert into rem1 values(1,'insert'); +NOTICE: trigger_func() called: action = INSERT, when = BEFORE, level = STATEMENT +NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 +NOTICE: NEW: (1,insert,) +NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (1,insert,) +NOTICE: trigger_func() called: action = INSERT, when = AFTER, level = STATEMENT +--Testcase 358: +update rem1 set f2 = 'update' where f1 = 1; +NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 +NOTICE: OLD: (1,insert,5),NEW: (1,update,5) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,insert,5),NEW: (1,update,5) +NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT +--Testcase 359: +update rem1 set f2 = f2 || f2; +NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 +NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) +NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT +truncate rem1; +NOTICE: trigger_func() called: action = TRUNCATE, when = BEFORE, level = STATEMENT +NOTICE: trigger_func() called: action = TRUNCATE, when = AFTER, level = STATEMENT +-- cleanup +--Testcase 647: +DROP TRIGGER trig_row_before ON rem1; +--Testcase 648: +DROP TRIGGER trig_row_after ON rem1; +--Testcase 649: +DROP TRIGGER trig_stmt_before ON rem1; +--Testcase 650: +DROP TRIGGER trig_stmt_after ON rem1; +--Testcase 360: +DELETE from rem1; +-- Test multiple AFTER ROW triggers on a foreign table +--Testcase 651: +CREATE TRIGGER trig_row_after1 +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 652: +CREATE TRIGGER trig_row_after2 +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 653: +insert into rem1 values(1,'insert'); +NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (1,insert,) +NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (1,insert,) +--Testcase 654: +update rem1 set f2 = 'update' where f1 = 1; +NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,insert,6),NEW: (1,update,6) +NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,insert,6),NEW: (1,update,6) +--Testcase 655: +update rem1 set f2 = f2 || f2; +NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) +NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) +--Testcase 656: +delete from rem1; +NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (1,updateupdate,6) +NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (1,updateupdate,6) +-- cleanup +--Testcase 657: +DROP TRIGGER trig_row_after1 ON rem1; +--Testcase 658: +DROP TRIGGER trig_row_after2 ON rem1; +-- Test WHEN conditions +--Testcase 659: +CREATE TRIGGER trig_row_before_insupd +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW +WHEN (NEW.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 660: +CREATE TRIGGER trig_row_after_insupd +AFTER INSERT OR UPDATE ON rem1 +FOR EACH ROW +WHEN (NEW.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); +-- Insert or update not matching: nothing happens +--Testcase 363: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 364: +UPDATE rem1 set f2 = 'test'; +-- Insert or update matching: triggers are fired +--Testcase 365: +INSERT INTO rem1 values(2, 'update'); +NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1 +NOTICE: NEW: (2,update,) +NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (2,update,) +--Testcase 366: +UPDATE rem1 set f2 = 'update update' where f1 = '2'; +NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1 +NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) +NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) +--Testcase 661: +CREATE TRIGGER trig_row_before_delete +BEFORE DELETE ON rem1 +FOR EACH ROW +WHEN (OLD.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 662: +CREATE TRIGGER trig_row_after_delete +AFTER DELETE ON rem1 +FOR EACH ROW +WHEN (OLD.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); +-- Trigger is fired for f1=2, not for f1=1 +--Testcase 369: +DELETE FROM rem1; +NOTICE: trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1 +NOTICE: OLD: (2,"update update",8) +NOTICE: trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1 +NOTICE: OLD: (2,"update update",8) +-- cleanup +--Testcase 663: +DROP TRIGGER trig_row_before_insupd ON rem1; +--Testcase 664: +DROP TRIGGER trig_row_after_insupd ON rem1; +--Testcase 665: +DROP TRIGGER trig_row_before_delete ON rem1; +--Testcase 666: +DROP TRIGGER trig_row_after_delete ON rem1; +-- Test various RETURN statements in BEFORE triggers. +--Testcase 667: +CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ + BEGIN + NEW.f2 := NEW.f2 || ' triggered !'; + RETURN NEW; + END +$$ language plpgsql; +--Testcase 668: +CREATE TRIGGER trig_row_before_insupd +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); +-- The new values should have 'triggered' appended +--Testcase 370: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 371: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------- + 1 | insert triggered ! +(1 row) + +--Testcase 372: +INSERT INTO rem1 values(2, 'insert'); +--Testcase 373: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------- + 1 | insert triggered ! + 2 | insert triggered ! +(2 rows) + +--Testcase 374: +UPDATE rem1 set f2 = ''; +--Testcase 375: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------- + 1 | triggered ! + 2 | triggered ! +(2 rows) + +--Testcase 376: +UPDATE rem1 set f2 = 'skidoo'; +--Testcase 377: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------- + 1 | skidoo triggered ! + 2 | skidoo triggered ! +(2 rows) + +--Testcase 669: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f1 = 10; -- all columns should be transmitted + QUERY PLAN +---------------------------------------------------------------- + Update on public.rem1 + -> Foreign Scan on public.rem1 + Output: 10, id, rem1.* + SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" +(4 rows) + +--Testcase 670: +UPDATE rem1 set f1 = 10; +--Testcase 671: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------------------- + 10 | skidoo triggered ! triggered ! + 10 | skidoo triggered ! triggered ! +(2 rows) + +--Testcase 378: +DELETE FROM rem1; +-- Add a second trigger, to check that the changes are propagated correctly +-- from trigger to trigger +--Testcase 672: +CREATE TRIGGER trig_row_before_insupd2 +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); +--Testcase 379: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 380: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------------------- + 1 | insert triggered ! triggered ! +(1 row) + +--Testcase 381: +INSERT INTO rem1 values(2, 'insert'); +--Testcase 382: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------------------- + 1 | insert triggered ! triggered ! + 2 | insert triggered ! triggered ! +(2 rows) + +--Testcase 383: +UPDATE rem1 set f2 = ''; +--Testcase 384: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------------- + 1 | triggered ! triggered ! + 2 | triggered ! triggered ! +(2 rows) + +--Testcase 385: +UPDATE rem1 set f2 = 'skidoo'; +--Testcase 386: +SELECT f1, f2 from rem1; + f1 | f2 +----+-------------------------------- + 1 | skidoo triggered ! triggered ! + 2 | skidoo triggered ! triggered ! +(2 rows) + +--Testcase 673: +DROP TRIGGER trig_row_before_insupd ON rem1; +--Testcase 674: +DROP TRIGGER trig_row_before_insupd2 ON rem1; +--Testcase 387: +DELETE from rem1; +--Testcase 388: +INSERT INTO rem1 VALUES (1, 'test'); +-- Test with a trigger returning NULL +--Testcase 675: +CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +--Testcase 676: +CREATE TRIGGER trig_null +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_null(); +-- Nothing should have changed. +--Testcase 389: +INSERT INTO rem1 VALUES (2, 'test2'); +--Testcase 390: +SELECT f1, f2 from rem1; + f1 | f2 +----+------ + 1 | test +(1 row) + +--Testcase 391: +UPDATE rem1 SET f2 = 'test2'; +--Testcase 392: +SELECT f1, f2 from rem1; + f1 | f2 +----+------ + 1 | test +(1 row) + +--Testcase 393: +DELETE from rem1; +--Testcase 394: +SELECT f1, f2 from rem1; + f1 | f2 +----+------ + 1 | test +(1 row) + +--Testcase 677: +DROP TRIGGER trig_null ON rem1; +--Testcase 395: +DELETE from rem1; +-- Test a combination of local and remote triggers +--Testcase 678: +CREATE TRIGGER trig_row_before +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 679: +CREATE TRIGGER trig_row_after +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 680: +CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); +--Testcase 681: +INSERT INTO rem1(f2) VALUES ('test'); +NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 +NOTICE: NEW: (12,"test triggered !",) +NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (12,"test triggered !",) +--Testcase 682: +UPDATE rem1 SET f2 = 'testo'; +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 +NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 +NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) +-- Test returning a system attribute +--Testcase 683: +INSERT INTO rem1(f2) VALUES ('test'); +NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 +NOTICE: NEW: (13,"test triggered !",) +NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 +NOTICE: NEW: (13,"test triggered !",) +-- cleanup +--Testcase 684: +DROP TRIGGER trig_row_before ON rem1; +--Testcase 685: +DROP TRIGGER trig_row_after ON rem1; +--Testcase 686: +DROP TRIGGER trig_local_before ON rem1; +-- Test direct foreign table modification functionality +--Testcase 832: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 833: +EXPLAIN (verbose, costs off) +DELETE FROM rem1 WHERE false; -- currently can't be pushed down + QUERY PLAN +-------------------------------- + Delete on public.rem1 + -> Result + Output: id + One-Time Filter: false +(4 rows) + +-- Test with statement-level triggers +--Testcase 687: +CREATE TRIGGER trig_stmt_before + BEFORE DELETE OR INSERT OR UPDATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 396: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 397: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 688: +DROP TRIGGER trig_stmt_before ON rem1; +--Testcase 689: +CREATE TRIGGER trig_stmt_after + AFTER DELETE OR INSERT OR UPDATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 398: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 399: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 690: +DROP TRIGGER trig_stmt_after ON rem1; +-- Test with row-level ON INSERT triggers +--Testcase 691: +CREATE TRIGGER trig_row_before_insert +BEFORE INSERT ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 400: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 401: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 692: +DROP TRIGGER trig_row_before_insert ON rem1; +--Testcase 693: +CREATE TRIGGER trig_row_after_insert +AFTER INSERT ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 402: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 403: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 694: +DROP TRIGGER trig_row_after_insert ON rem1; +-- Test with row-level ON UPDATE triggers +--Testcase 695: +CREATE TRIGGER trig_row_before_update +BEFORE UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 404: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------- + Update on public.rem1 + -> Foreign Scan on public.rem1 + Output: ''::text, id, rem1.* + SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" +(4 rows) + +--Testcase 405: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 696: +DROP TRIGGER trig_row_before_update ON rem1; +--Testcase 697: +CREATE TRIGGER trig_row_after_update +AFTER UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 406: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------- + Update on public.rem1 + -> Foreign Scan on public.rem1 + Output: ''::text, id, rem1.* + SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" +(4 rows) + +--Testcase 407: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down + QUERY PLAN +----------------------------------------------- + Delete on public.rem1 + -> Foreign Delete on public.rem1 + SQLite query: DELETE FROM main."loc1" +(3 rows) + +--Testcase 698: +DROP TRIGGER trig_row_after_update ON rem1; +-- Test with row-level ON DELETE triggers +--Testcase 699: +CREATE TRIGGER trig_row_before_delete +BEFORE DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 408: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 409: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------- + Delete on public.rem1 + -> Foreign Scan on public.rem1 + Output: id, rem1.* + SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" +(4 rows) + +--Testcase 700: +DROP TRIGGER trig_row_before_delete ON rem1; +--Testcase 701: +CREATE TRIGGER trig_row_after_delete +AFTER DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 410: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down + QUERY PLAN +-------------------------------------------------------- + Update on public.rem1 + -> Foreign Update on public.rem1 + SQLite query: UPDATE main."loc1" SET `f2` = '' +(3 rows) + +--Testcase 411: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------- + Delete on public.rem1 + -> Foreign Scan on public.rem1 + Output: id, rem1.* + SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" +(4 rows) + +--Testcase 702: +DROP TRIGGER trig_row_after_delete ON rem1; +-- =================================================================== +-- test inheritance features +-- =================================================================== +--Testcase 703: +CREATE TABLE a (aa TEXT); +--Testcase 834: +ALTER TABLE a SET (autovacuum_enabled = 'false'); +--Testcase 704: +CREATE FOREIGN TABLE b (aa TEXT OPTIONS (key 'true'), bb TEXT) INHERITS (a) + SERVER sqlite_svr OPTIONS (table 'loct'); +NOTICE: merging column "aa" with inherited definition +--Testcase 412: +INSERT INTO a(aa) VALUES('aaa'); +--Testcase 413: +INSERT INTO a(aa) VALUES('aaaa'); +--Testcase 414: +INSERT INTO a(aa) VALUES('aaaaa'); +--Testcase 415: +INSERT INTO b(aa) VALUES('bbb'); +--Testcase 416: +INSERT INTO b(aa) VALUES('bbbb'); +--Testcase 417: +INSERT INTO b(aa) VALUES('bbbbb'); +--Testcase 418: +SELECT tableoid::regclass, * FROM a; + tableoid | aa +----------+------- + a | aaa + a | aaaa + a | aaaaa + b | bbb + b | bbbb + b | bbbbb +(6 rows) + +--Testcase 419: +SELECT tableoid::regclass, * FROM b; + tableoid | aa | bb +----------+-------+---- + b | bbb | + b | bbbb | + b | bbbbb | +(3 rows) + +--Testcase 420: +SELECT tableoid::regclass, * FROM ONLY a; + tableoid | aa +----------+------- + a | aaa + a | aaaa + a | aaaaa +(3 rows) + +--Testcase 421: +UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%'; +--Testcase 422: +SELECT tableoid::regclass, * FROM a; + tableoid | aa +----------+-------- + a | aaa + a | zzzzzz + a | zzzzzz + b | bbb + b | bbbb + b | bbbbb +(6 rows) + +--Testcase 423: +SELECT tableoid::regclass, * FROM b; + tableoid | aa | bb +----------+-------+---- + b | bbb | + b | bbbb | + b | bbbbb | +(3 rows) + +--Testcase 424: +SELECT tableoid::regclass, * FROM ONLY a; + tableoid | aa +----------+-------- + a | aaa + a | zzzzzz + a | zzzzzz +(3 rows) + +--Testcase 425: +UPDATE b SET aa = 'new'; +--Testcase 426: +SELECT tableoid::regclass, * FROM a; + tableoid | aa +----------+-------- + a | aaa + a | zzzzzz + a | zzzzzz + b | new + b | new + b | new +(6 rows) + +--Testcase 427: +SELECT tableoid::regclass, * FROM b; + tableoid | aa | bb +----------+-----+---- + b | new | + b | new | + b | new | +(3 rows) + +--Testcase 428: +SELECT tableoid::regclass, * FROM ONLY a; + tableoid | aa +----------+-------- + a | aaa + a | zzzzzz + a | zzzzzz +(3 rows) + +--Testcase 429: +UPDATE a SET aa = 'newtoo'; +--Testcase 430: +SELECT tableoid::regclass, * FROM a; + tableoid | aa +----------+-------- + a | newtoo + a | newtoo + a | newtoo + b | newtoo + b | newtoo + b | newtoo +(6 rows) + +--Testcase 431: +SELECT tableoid::regclass, * FROM b; + tableoid | aa | bb +----------+--------+---- + b | newtoo | + b | newtoo | + b | newtoo | +(3 rows) + +--Testcase 432: +SELECT tableoid::regclass, * FROM ONLY a; + tableoid | aa +----------+-------- + a | newtoo + a | newtoo + a | newtoo +(3 rows) + +--Testcase 433: +DELETE FROM a; +--Testcase 434: +SELECT tableoid::regclass, * FROM a; + tableoid | aa +----------+---- +(0 rows) + +--Testcase 435: +SELECT tableoid::regclass, * FROM b; + tableoid | aa | bb +----------+----+---- +(0 rows) + +--Testcase 436: +SELECT tableoid::regclass, * FROM ONLY a; + tableoid | aa +----------+---- +(0 rows) + +--Testcase 705: +DROP TABLE a CASCADE; +NOTICE: drop cascades to foreign table b +-- Check SELECT FOR UPDATE/SHARE with an inherited source table +--Testcase 706: +create table foo (f1 int, f2 int); +--Testcase 707: +create foreign table foo2 (f3 int OPTIONS (key 'true')) inherits (foo) + server sqlite_svr options (table 'loct1'); +--Testcase 708: +create table bar (f1 int, f2 int); +--Testcase 709: +create foreign table bar2 (f3 int OPTIONS (key 'true')) inherits (bar) + server sqlite_svr options (table 'loct2'); +--Testcase 835: +alter table foo set (autovacuum_enabled = 'false'); +--Testcase 836: +alter table bar set (autovacuum_enabled = 'false'); +--Testcase 437: +insert into foo values(1,1); +--Testcase 438: +insert into foo values(3,3); +--Testcase 439: +insert into foo2 values(2,2,2); +--Testcase 440: +insert into foo2 values(4,4,4); +--Testcase 441: +insert into bar values(1,11); +--Testcase 442: +insert into bar values(2,22); +--Testcase 443: +insert into bar values(6,66); +--Testcase 444: +insert into bar2 values(3,33,33); +--Testcase 445: +insert into bar2 values(4,44,44); +--Testcase 446: +insert into bar2 values(7,77,77); +--Testcase 447: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo) for update; + QUERY PLAN +---------------------------------------------------------------------------------------------- + LockRows + Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid + -> Hash Join + Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid + Inner Unique: true + Hash Cond: (bar.f1 = foo.f1) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Hash + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + -> HashAggregate + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + Group Key: foo.f1 + -> Append + -> Seq Scan on public.foo foo_1 + Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid + -> Foreign Scan on public.foo2 foo_2 + Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" +(23 rows) + +--Testcase 448: +select * from bar where f1 in (select f1 from foo) for update; + f1 | f2 +----+---- + 1 | 11 + 2 | 22 + 3 | 33 + 4 | 44 +(4 rows) + +--Testcase 449: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo) for share; + QUERY PLAN +---------------------------------------------------------------------------------------------- + LockRows + Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid + -> Hash Join + Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid + Inner Unique: true + Hash Cond: (bar.f1 = foo.f1) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Hash + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + -> HashAggregate + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + Group Key: foo.f1 + -> Append + -> Seq Scan on public.foo foo_1 + Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid + -> Foreign Scan on public.foo2 foo_2 + Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" +(23 rows) + +--Testcase 450: +select * from bar where f1 in (select f1 from foo) for share; + f1 | f2 +----+---- + 1 | 11 + 2 | 22 + 3 | 33 + 4 | 44 +(4 rows) + +-- Now check SELECT FOR UPDATE/SHARE with an inherited source table, +-- where the parent is itself a foreign table +--Testcase 837: +create foreign table foo2child (f3 int) inherits (foo2) + server sqlite_svr options (table 'loct4_2'); +NOTICE: moving and merging column "f3" with inherited definition +DETAIL: User-specified column moved to the position of the inherited column. +--Testcase 838: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo2) for share; + QUERY PLAN +------------------------------------------------------------------------------------------- + LockRows + Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid + -> Hash Join + Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid + Inner Unique: true + Hash Cond: (bar.f1 = foo2.f1) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Hash + Output: foo2.*, foo2.f1, foo2.tableoid + -> HashAggregate + Output: foo2.*, foo2.f1, foo2.tableoid + Group Key: foo2.f1 + -> Append + -> Foreign Scan on public.foo2 foo2_1 + Output: foo2_1.*, foo2_1.f1, foo2_1.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" + -> Foreign Scan on public.foo2child foo2_2 + Output: foo2_2.*, foo2_2.f1, foo2_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct4_2" +(24 rows) + +--Testcase 839: +select * from bar where f1 in (select f1 from foo2) for share; + f1 | f2 +----+---- + 2 | 22 + 4 | 44 +(2 rows) + +--Testcase 840: +drop foreign table foo2child; +-- And with a local child relation of the foreign table parent +--Testcase 841: +create table foo2child (f3 int) inherits (foo2); +NOTICE: moving and merging column "f3" with inherited definition +DETAIL: User-specified column moved to the position of the inherited column. +--Testcase 842: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo2) for share; + QUERY PLAN +------------------------------------------------------------------------------------------------- + LockRows + Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid + -> Hash Join + Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid + Inner Unique: true + Hash Cond: (bar.f1 = foo2.f1) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Hash + Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid + -> HashAggregate + Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid + Group Key: foo2.f1 + -> Append + -> Foreign Scan on public.foo2 foo2_1 + Output: foo2_1.*, foo2_1.f1, foo2_1.ctid, foo2_1.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" + -> Seq Scan on public.foo2child foo2_2 + Output: foo2_2.*, foo2_2.f1, foo2_2.ctid, foo2_2.tableoid +(23 rows) + +--Testcase 843: +select * from bar where f1 in (select f1 from foo2) for share; + f1 | f2 +----+---- + 2 | 22 + 4 | 44 +(2 rows) + +--Testcase 844: +drop table foo2child; +-- Check UPDATE with inherited target and an inherited source table +--Testcase 451: +explain (verbose, costs off) +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Update on public.bar + Update on public.bar bar_1 + Foreign Update on public.bar2 bar_2 + -> Hash Join + Output: (bar.f2 + 100), foo.ctid, bar.tableoid, bar.ctid, (NULL::integer), (NULL::record), foo.*, foo.tableoid + Inner Unique: true + Hash Cond: (bar.f1 = foo.f1) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f2, bar_2.f1, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Hash + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + -> HashAggregate + Output: foo.ctid, foo.f1, foo.*, foo.tableoid + Group Key: foo.f1 + -> Append + -> Seq Scan on public.foo foo_1 + Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid + -> Foreign Scan on public.foo2 foo_2 + Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" +(24 rows) + +--Testcase 452: +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); +--Testcase 453: +select tableoid::regclass, * from bar order by 1,2; + tableoid | f1 | f2 +----------+----+----- + bar | 1 | 111 + bar | 2 | 122 + bar | 6 | 66 + bar2 | 3 | 133 + bar2 | 4 | 144 + bar2 | 7 | 77 +(6 rows) + +-- Check UPDATE with inherited target and an appendrel subquery +--Testcase 454: +explain (verbose, costs off) +update bar set f2 = f2 + 100 +from + ( select f1 from foo union all select f1+3 from foo ) ss +where bar.f1 = ss.f1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Update on public.bar + Update on public.bar bar_1 + Foreign Update on public.bar2 bar_2 + -> Merge Join + Output: (bar.f2 + 100), (ROW(foo.f1)), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) + Merge Cond: (bar.f1 = foo.f1) + -> Sort + Output: bar.f2, bar.f1, bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) + Sort Key: bar.f1 + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f2, bar_2.f1, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" + -> Sort + Output: (ROW(foo.f1)), foo.f1 + Sort Key: foo.f1 + -> Append + -> Seq Scan on public.foo + Output: ROW(foo.f1), foo.f1 + -> Foreign Scan on public.foo2 foo_1 + Output: ROW(foo_1.f1), foo_1.f1 + SQLite query: SELECT `f1` FROM main."loct1" + -> Seq Scan on public.foo foo_2 + Output: ROW((foo_2.f1 + 3)), (foo_2.f1 + 3) + -> Foreign Scan on public.foo2 foo_3 + Output: ROW((foo_3.f1 + 3)), (foo_3.f1 + 3) + SQLite query: SELECT `f1` FROM main."loct1" +(29 rows) + +--Testcase 455: +update bar set f2 = f2 + 100 +from + ( select f1 from foo union all select f1+3 from foo ) ss +where bar.f1 = ss.f1; +--Testcase 456: +select tableoid::regclass, * from bar order by 1,2; + tableoid | f1 | f2 +----------+----+----- + bar | 1 | 211 + bar | 2 | 222 + bar | 6 | 166 + bar2 | 3 | 233 + bar2 | 4 | 244 + bar2 | 7 | 177 +(6 rows) + +-- Test forcing the remote server to produce sorted data for a merge join, +-- but the foreign table is an inheritance child. +--truncate table loct1; +--Testcase 710: +delete from foo2; +truncate table only foo; +\set num_rows_foo 2000 +--Testcase 711: +insert into foo2 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2); +--Testcase 712: +insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2); +--Testcase 845: +SET enable_hashjoin to false; +--Testcase 846: +SET enable_nestloop to false; +--alter foreign table foo2 options (use_remote_estimate 'true'); +--create index i_loct1_f1 on loct1(f1); +--Testcase 713: +create index i_foo_f1 on foo(f1); +analyze foo; +--analyze loct1; +-- inner join; expressions in the clauses appear in the equivalence class list +--Testcase 714: +explain (verbose, costs off) + select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + Limit + Output: foo.f1, foo2.f1, foo.f2 + -> Sort + Output: foo.f1, foo2.f1, foo.f2 + Sort Key: foo.f2 + -> Merge Join + Output: foo.f1, foo2.f1, foo.f2 + Merge Cond: (foo.f1 = foo2.f1) + -> Merge Append + Sort Key: foo.f1 + -> Index Scan using i_foo_f1 on public.foo foo_1 + Output: foo_1.f1, foo_1.f2 + -> Sort + Output: foo_2.f1, foo_2.f2 + Sort Key: foo_2.f1 + -> Foreign Scan on public.foo2 foo_2 + Output: foo_2.f1, foo_2.f2 + SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST + -> Sort + Output: foo2.f1 + Sort Key: foo2.f1 + -> Foreign Scan on public.foo2 + Output: foo2.f1 + SQLite query: SELECT `f1` FROM main."loct1" +(24 rows) + +--Testcase 715: +select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; + f1 | f1 +----+---- + 20 | 20 + 22 | 22 + 24 | 24 + 26 | 26 + 28 | 28 + 30 | 30 + 32 | 32 + 34 | 34 + 36 | 36 + 38 | 38 +(10 rows) + +-- outer join; expressions in the clauses do not appear in equivalence class +-- list but no output change as compared to the previous query +--Testcase 716: +explain (verbose, costs off) + select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + Limit + Output: foo.f1, foo2.f1, foo.f2 + -> Sort + Output: foo.f1, foo2.f1, foo.f2 + Sort Key: foo.f2 + -> Merge Left Join + Output: foo.f1, foo2.f1, foo.f2 + Merge Cond: (foo.f1 = foo2.f1) + -> Merge Append + Sort Key: foo.f1 + -> Index Scan using i_foo_f1 on public.foo foo_1 + Output: foo_1.f1, foo_1.f2 + -> Sort + Output: foo_2.f1, foo_2.f2 + Sort Key: foo_2.f1 + -> Foreign Scan on public.foo2 foo_2 + Output: foo_2.f1, foo_2.f2 + SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST + -> Sort + Output: foo2.f1 + Sort Key: foo2.f1 + -> Foreign Scan on public.foo2 + Output: foo2.f1 + SQLite query: SELECT `f1` FROM main."loct1" +(24 rows) + +--Testcase 717: +select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; + f1 | f1 +----+---- + 10 | 10 + 11 | + 12 | 12 + 13 | + 14 | 14 + 15 | + 16 | 16 + 17 | + 18 | 18 + 19 | +(10 rows) + +--Testcase 847: +RESET enable_hashjoin; +--Testcase 848: +RESET enable_nestloop; +-- Test that WHERE CURRENT OF is not supported +begin; +declare c cursor for select * from bar where f1 = 7; +--Testcase 457: +fetch from c; + f1 | f2 +----+----- + 7 | 177 +(1 row) + +--Testcase 458: +update bar set f2 = null where current of c; +ERROR: WHERE CURRENT OF is not supported for this table type +rollback; +--Testcase 459: +explain (verbose, costs off) +delete from foo where f1 < 5; + QUERY PLAN +------------------------------------------------------------------------- + Delete on public.foo + Delete on public.foo foo_1 + Foreign Delete on public.foo2 foo_2 + -> Append + -> Index Scan using i_foo_f1 on public.foo foo_1 + Output: foo_1.tableoid, foo_1.ctid, NULL::integer + Index Cond: (foo_1.f1 < 5) + -> Foreign Delete on public.foo2 foo_2 + SQLite query: DELETE FROM main."loct1" WHERE ((`f1` < 5)) +(9 rows) + +--Testcase 460: +delete from foo where f1 < 5; +--Testcase 461: +explain (verbose, costs off) +update bar set f2 = f2 + 100; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Update on public.bar + Update on public.bar bar_1 + Foreign Update on public.bar2 bar_2 + -> Result + Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record + -> Foreign Update on public.bar2 bar_2 + SQLite query: UPDATE main."loct2" SET `f2` = (`f2` + 100) +(10 rows) + +--Testcase 462: +update bar set f2 = f2 + 100; +--Testcase 463: +select * from bar; + f1 | f2 +----+----- + 1 | 311 + 2 | 322 + 6 | 266 + 3 | 333 + 4 | 344 + 7 | 277 +(6 rows) + +-- Test that UPDATE/DELETE with inherited target works with row-level triggers +--Testcase 718: +CREATE TRIGGER trig_row_before +BEFORE UPDATE OR DELETE ON bar2 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 719: +CREATE TRIGGER trig_row_after +AFTER UPDATE OR DELETE ON bar2 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 464: +explain (verbose, costs off) +update bar set f2 = f2 + 100; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Update on public.bar + Update on public.bar bar_1 + Foreign Update on public.bar2 bar_2 + -> Result + Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.f2, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" +(11 rows) + +--Testcase 465: +update bar set f2 = f2 + 100; +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 +NOTICE: OLD: (3,333,33),NEW: (3,433,33) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 +NOTICE: OLD: (4,344,44),NEW: (4,444,44) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 +NOTICE: OLD: (7,277,77),NEW: (7,377,77) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 +NOTICE: OLD: (3,333,33),NEW: (3,433,33) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 +NOTICE: OLD: (4,344,44),NEW: (4,444,44) +NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 +NOTICE: OLD: (7,277,77),NEW: (7,377,77) +--Testcase 466: +explain (verbose, costs off) +delete from bar where f2 < 400; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Delete on public.bar + Delete on public.bar bar_1 + Foreign Delete on public.bar2 bar_2 + -> Append + -> Seq Scan on public.bar bar_1 + Output: bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record + Filter: (bar_1.f2 < 400) + -> Foreign Scan on public.bar2 bar_2 + Output: bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* + SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" WHERE ((`f2` < 400)) +(10 rows) + +--Testcase 467: +delete from bar where f2 < 400; +NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2 +NOTICE: OLD: (7,377,77) +NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2 +NOTICE: OLD: (7,377,77) +-- cleanup +--Testcase 720: +drop table foo cascade; +NOTICE: drop cascades to foreign table foo2 +--Testcase 721: +drop table bar cascade; +NOTICE: drop cascades to foreign table bar2 +-- Test pushing down UPDATE/DELETE joins to the remote server +--Testcase 722: +create table parent (a int, b text); +--Testcase 723: +create foreign table remt1 (a int OPTIONS (key 'true'), b text) + server sqlite_svr options (table 'loct3'); +--Testcase 724: +create foreign table remt2 (a int OPTIONS (key 'true'), b text) + server sqlite_svr options (table 'loct4'); +--Testcase 849: +alter foreign table remt1 inherit parent; +--Testcase 468: +insert into remt1 values (1, 'foo'); +--Testcase 469: +insert into remt1 values (2, 'bar'); +--Testcase 470: +insert into remt2 values (1, 'foo'); +--Testcase 471: +insert into remt2 values (2, 'bar'); +--Testcase 472: +explain (verbose, costs off) +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Update on public.parent + Update on public.parent parent_1 + Foreign Update on public.remt1 parent_2 + -> Hash Join + Output: (parent.b || remt2.b), remt2.*, parent.tableoid, parent.ctid, (NULL::integer), (NULL::record) + Hash Cond: (remt2.a = parent.a) + -> Foreign Scan on public.remt2 + Output: remt2.b, remt2.*, remt2.a + SQLite query: SELECT `a`, `b` FROM main."loct4" + -> Hash + Output: parent.b, parent.a, parent.tableoid, parent.ctid, (NULL::integer), (NULL::record) + -> Append + -> Seq Scan on public.parent parent_1 + Output: parent_1.b, parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::integer, NULL::record + -> Foreign Scan on public.remt1 parent_2 + Output: parent_2.b, parent_2.a, parent_2.tableoid, NULL::tid, parent_2.a, parent_2.* + SQLite query: SELECT `a`, `b` FROM main."loct3" +(17 rows) + +--Testcase 473: +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; +--Testcase 474: +select * from parent inner join remt2 on (parent.a = remt2.a); + a | b | a | b +---+--------+---+----- + 1 | foofoo | 1 | foo + 2 | barbar | 2 | bar +(2 rows) + +--Testcase 475: +explain (verbose, costs off) +delete from parent using remt2 where parent.a = remt2.a; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Delete on public.parent + Delete on public.parent parent_1 + Foreign Delete on public.remt1 parent_2 + -> Merge Join + Output: remt2.*, parent.tableoid, parent.ctid, (NULL::integer) + Merge Cond: (remt2.a = parent.a) + -> Sort + Output: remt2.*, remt2.a + Sort Key: remt2.a + -> Foreign Scan on public.remt2 + Output: remt2.*, remt2.a + SQLite query: SELECT `a`, `b` FROM main."loct4" + -> Sort + Output: parent.a, parent.tableoid, parent.ctid, (NULL::integer) + Sort Key: parent.a + -> Append + -> Seq Scan on public.parent parent_1 + Output: parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::integer + -> Foreign Scan on public.remt1 parent_2 + Output: parent_2.a, parent_2.tableoid, NULL::tid, parent_2.a + SQLite query: SELECT `a` FROM main."loct3" +(21 rows) + +--Testcase 476: +delete from parent using remt2 where parent.a = remt2.a; +-- cleanup +--Testcase 725: +drop foreign table remt1; +--Testcase 726: +drop foreign table remt2; +--Testcase 727: +drop table parent; +/* +-- Skip these tests, sqlite fdw does not support partition table, check constraint, copy from +-- =================================================================== +-- test tuple routing for foreign-table partitions +-- =================================================================== + +-- Test insert tuple routing +create table itrtest (a int, b text) partition by list (a); +create table loct1 (a int check (a in (1)), b text); +create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); +create table loct2 (a int check (a in (2)), b text); +create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); +alter table itrtest attach partition remp1 for values in (1); +alter table itrtest attach partition remp2 for values in (2); + +insert into itrtest values (1, 'foo'); +insert into itrtest values (1, 'bar') returning *; +insert into itrtest values (2, 'baz'); +insert into itrtest values (2, 'qux') returning *; +insert into itrtest values (1, 'test1'), (2, 'test2') returning *; + +select tableoid::regclass, * FROM itrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +delete from itrtest; + +-- MERGE ought to fail cleanly +merge into itrtest using (select 1, 'foo') as source on (true) + when matched then do nothing; + +create unique index loct1_idx on loct1 (a); + +-- DO NOTHING without an inference specification is supported +insert into itrtest values (1, 'foo') on conflict do nothing returning *; +insert into itrtest values (1, 'foo') on conflict do nothing returning *; + +-- But other cases are not supported +insert into itrtest values (1, 'bar') on conflict (a) do nothing; +insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b; + +select tableoid::regclass, * FROM itrtest; + +delete from itrtest; + +drop index loct1_idx; + +-- Test that remote triggers work with insert tuple routing +create function br_insert_trigfunc() returns trigger as $$ +begin + new.b := new.b || ' triggered !'; + return new; +end +$$ language plpgsql; +create trigger loct1_br_insert_trigger before insert on loct1 + for each row execute procedure br_insert_trigfunc(); +create trigger loct2_br_insert_trigger before insert on loct2 + for each row execute procedure br_insert_trigfunc(); + +-- The new values are concatenated with ' triggered !' +insert into itrtest values (1, 'foo') returning *; +insert into itrtest values (2, 'qux') returning *; +insert into itrtest values (1, 'test1'), (2, 'test2') returning *; +with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result; + +drop trigger loct1_br_insert_trigger on loct1; +drop trigger loct2_br_insert_trigger on loct2; + +drop table itrtest; +drop table loct1; +drop table loct2; + +-- Test update tuple routing +create table utrtest (a int, b text) partition by list (a); +create table loct (a int check (a in (1)), b text); +create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct'); +create table locp (a int check (a in (2)), b text); +alter table utrtest attach partition remp for values in (1); +alter table utrtest attach partition locp for values in (2); + +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +select tableoid::regclass, * FROM utrtest; +select tableoid::regclass, * FROM remp; +select tableoid::regclass, * FROM locp; + +-- It's not allowed to move a row from a partition that is foreign to another +update utrtest set a = 2 where b = 'foo' returning *; + +-- But the reverse is allowed +update utrtest set a = 1 where b = 'qux' returning *; + +select tableoid::regclass, * FROM utrtest; +select tableoid::regclass, * FROM remp; +select tableoid::regclass, * FROM locp; + +-- The executor should not let unexercised FDWs shut down +update utrtest set a = 1 where b = 'foo'; + +-- Test that remote triggers work with update tuple routing +create trigger loct_br_insert_trigger before insert on loct + for each row execute procedure br_insert_trigfunc(); + +delete from utrtest; +insert into utrtest values (2, 'qux'); + +-- Check case where the foreign partition is a subplan target rel +explain (verbose, costs off) +update utrtest set a = 1 where a = 1 or a = 2 returning *; +-- The new values are concatenated with ' triggered !' +update utrtest set a = 1 where a = 1 or a = 2 returning *; + +delete from utrtest; +insert into utrtest values (2, 'qux'); + +-- Check case where the foreign partition isn't a subplan target rel +explain (verbose, costs off) +update utrtest set a = 1 where a = 2 returning *; +-- The new values are concatenated with ' triggered !' +update utrtest set a = 1 where a = 2 returning *; + +drop trigger loct_br_insert_trigger on loct; + +-- We can move rows to a foreign partition that has been updated already, +-- but can't move rows to a foreign partition that hasn't been updated yet + +delete from utrtest; +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +-- Test the former case: +-- with a direct modification plan +explain (verbose, costs off) +update utrtest set a = 1 returning *; +update utrtest set a = 1 returning *; + +delete from utrtest; +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +-- with a non-direct modification plan +explain (verbose, costs off) +update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; +update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; + +-- Change the definition of utrtest so that the foreign partition get updated +-- after the local partition +delete from utrtest; +alter table utrtest detach partition remp; +drop foreign table remp; +alter table loct drop constraint loct_a_check; +alter table loct add check (a in (3)); +create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct'); +alter table utrtest attach partition remp for values in (3); +insert into utrtest values (2, 'qux'); +insert into utrtest values (3, 'xyzzy'); + +-- Test the latter case: +-- with a direct modification plan +explain (verbose, costs off) +update utrtest set a = 3 returning *; +update utrtest set a = 3 returning *; -- ERROR + +-- with a non-direct modification plan +explain (verbose, costs off) +update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; +update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR + +drop table utrtest; +drop table loct; + +-- Test copy tuple routing +create table ctrtest (a int, b text) partition by list (a); +create table loct1 (a int check (a in (1)), b text); +create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); +create table loct2 (a int check (a in (2)), b text); +create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); +alter table ctrtest attach partition remp1 for values in (1); +alter table ctrtest attach partition remp2 for values in (2); + +copy ctrtest from stdin; +1 foo +2 qux +\. + +select tableoid::regclass, * FROM ctrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +-- Copying into foreign partitions directly should work as well +copy remp1 from stdin; +1 bar +\. + +select tableoid::regclass, * FROM remp1; + +delete from ctrtest; + +-- Test copy tuple routing with the batch_size option enabled +alter server loopback options (add batch_size '2'); + +copy ctrtest from stdin; +1 foo +1 bar +2 baz +2 qux +1 test1 +2 test2 +\. + +select tableoid::regclass, * FROM ctrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +delete from ctrtest; + +alter server loopback options (drop batch_size); + + +drop table ctrtest; +drop table loct1; +drop table loct2; + +-- =================================================================== +-- test COPY FROM +-- =================================================================== + +create table loc2 (f1 int, f2 text); +alter table loc2 set (autovacuum_enabled = 'false'); +create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2'); + +-- Test basic functionality +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +delete from rem2; + +-- Test check constraints +alter table loc2 add constraint loc2_f1positive check (f1 >= 0); +alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); + +-- check constraint is enforced on the remote side, not locally +copy rem2 from stdin; +1 foo +2 bar +\. +copy rem2 from stdin; -- ERROR +-1 xyzzy +\. +select * from rem2; + +alter foreign table rem2 drop constraint rem2_f1positive; +alter table loc2 drop constraint loc2_f1positive; + +delete from rem2; + +-- Test local triggers +create trigger trig_stmt_before before insert on rem2 + for each statement execute procedure trigger_func(); +create trigger trig_stmt_after after insert on rem2 + for each statement execute procedure trigger_func(); +create trigger trig_row_before before insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger trig_row_after after insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); + +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before on rem2; +drop trigger trig_row_after on rem2; +drop trigger trig_stmt_before on rem2; +drop trigger trig_stmt_after on rem2; + +delete from rem2; + +create trigger trig_row_before_insert before insert on rem2 + for each row execute procedure trig_row_before_insupdate(); + +-- The new values are concatenated with ' triggered !' +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before_insert on rem2; + +delete from rem2; + +create trigger trig_null before insert on rem2 + for each row execute procedure trig_null(); + +-- Nothing happens +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_null on rem2; + +delete from rem2; + +-- Test remote triggers +create trigger trig_row_before_insert before insert on loc2 + for each row execute procedure trig_row_before_insupdate(); + +-- The new values are concatenated with ' triggered !' +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before_insert on loc2; + +delete from rem2; + +create trigger trig_null before insert on loc2 + for each row execute procedure trig_null(); + +-- Nothing happens +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_null on loc2; + +delete from rem2; + +-- Test a combination of local and remote triggers +create trigger rem2_trig_row_before before insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger rem2_trig_row_after after insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger loc2_trig_row_before_insert before insert on loc2 + for each row execute procedure trig_row_before_insupdate(); + +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger rem2_trig_row_before on rem2; +drop trigger rem2_trig_row_after on rem2; +drop trigger loc2_trig_row_before_insert on loc2; + +delete from rem2; + +-- test COPY FROM with foreign table created in the same transaction +create table loc3 (f1 int, f2 text); +begin; +create foreign table rem3 (f1 int, f2 text) + server loopback options(table_name 'loc3'); +copy rem3 from stdin; +1 foo +2 bar +\. +commit; +select * from rem3; +drop foreign table rem3; +drop table loc3; +*/ +-- Test COPY FROM with the batch_size option enabled +-- alter server loopback options (add batch_size '2'); +-- -- Test basic functionality +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; +-- delete from rem2; +-- -- Test check constraints +-- alter table loc2 add constraint loc2_f1positive check (f1 >= 0); +-- alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); +-- -- check constraint is enforced on the remote side, not locally +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- copy rem2 from stdin; -- ERROR +-- -1 xyzzy +-- \. +-- select * from rem2; +-- alter foreign table rem2 drop constraint rem2_f1positive; +-- alter table loc2 drop constraint loc2_f1positive; +-- delete from rem2; +-- -- Test remote triggers +-- create trigger trig_row_before_insert before insert on loc2 +-- for each row execute procedure trig_row_before_insupdate(); +-- -- The new values are concatenated with ' triggered !' +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; +-- drop trigger trig_row_before_insert on loc2; +-- delete from rem2; +-- create trigger trig_null before insert on loc2 +-- for each row execute procedure trig_null(); +-- -- Nothing happens +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; +-- drop trigger trig_null on loc2; +-- delete from rem2; +-- -- Check with zero-column foreign table; batch insert will be disabled +-- alter table loc2 drop column f1; +-- alter table loc2 drop column f2; +-- alter table rem2 drop column f1; +-- alter table rem2 drop column f2; +-- copy rem2 from stdin; +-- select * from rem2; +-- delete from rem2; +-- alter server loopback options (drop batch_size); +-- =================================================================== +-- test for TRUNCATE +-- =================================================================== +--Testcase 850: +CREATE FOREIGN TABLE tru_ftable (id int) + SERVER sqlite_svr OPTIONS (table 'tru_rtable0'); +--Testcase 851: +INSERT INTO "S 1".tru_rtable0 (SELECT x FROM generate_series(1,10) x); +-- CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id); +-- CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable +-- FOR VALUES WITH (MODULUS 2, REMAINDER 0); +-- CREATE TABLE tru_rtable1 (id int primary key); +-- CREATE FOREIGN TABLE tru_ftable__p1 (id int) +-- SERVER sqlite_svr OPTIONS (table 'tru_ptable'); +-- INSERT INTO tru_ptable (SELECT x FROM generate_series(11,20) x); +--Testcase 852: +INSERT INTO "S 1".tru_pk_table (SELECT x FROM generate_series(1,10) x); +--Testcase 853: +INSERT INTO "S 1".tru_fk_table(fkey) (SELECT x % 10 + 1 FROM generate_series(5,25) x); +--Testcase 854: +CREATE FOREIGN TABLE tru_pk_ftable (id int) + SERVER sqlite_svr OPTIONS (table 'tru_pk_table'); +--Testcase 855: +CREATE FOREIGN TABLE tru_ftable_parent (id int) + SERVER sqlite_svr OPTIONS (table 'tru_rtable_parent'); +--Testcase 856: +CREATE FOREIGN TABLE tru_ftable_child () INHERITS (tru_ftable_parent) + SERVER sqlite_svr OPTIONS (table 'tru_rtable_child'); +--Testcase 857: +INSERT INTO "S 1".tru_rtable_parent (SELECT x FROM generate_series(1,8) x); +--Testcase 858: +INSERT INTO "S 1".tru_rtable_child (SELECT x FROM generate_series(10, 18) x); +-- normal truncate +--Testcase 859: +SELECT sum(id) FROM tru_ftable; -- 55 + sum +----- + 55 +(1 row) + +TRUNCATE tru_ftable; +--Testcase 860: +SELECT count(*) FROM "S 1".tru_rtable0; -- 0 + count +------- + 0 +(1 row) + +--Testcase 861: +SELECT count(*) FROM tru_ftable; -- 0 + count +------- + 0 +(1 row) + +-- 'truncatable' option +--Testcase 862: +ALTER SERVER sqlite_svr OPTIONS (ADD truncatable 'false'); +TRUNCATE tru_ftable; -- error +ERROR: foreign table "tru_ftable" does not allow truncates +--Testcase 863: +ALTER FOREIGN TABLE tru_ftable OPTIONS (ADD truncatable 'true'); +TRUNCATE tru_ftable; -- accepted +--Testcase 864: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); +TRUNCATE tru_ftable; -- error +ERROR: foreign table "tru_ftable" does not allow truncates +--Testcase 865: +ALTER SERVER sqlite_svr OPTIONS (DROP truncatable); +--Testcase 866: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); +TRUNCATE tru_ftable; -- error +ERROR: foreign table "tru_ftable" does not allow truncates +--Testcase 867: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'true'); +TRUNCATE tru_ftable; -- accepted +-- -- partitioned table with both local and foreign tables as partitions +-- SELECT sum(id) FROM tru_ptable; -- 155 +-- TRUNCATE tru_ptable; +-- SELECT count(*) FROM tru_ptable; -- 0 +-- SELECT count(*) FROM tru_ptable__p0; -- 0 +-- SELECT count(*) FROM tru_ftable__p1; -- 0 +-- SELECT count(*) FROM tru_rtable1; -- 0 +-- 'CASCADE' option +--Testcase 868: +SELECT sum(id) FROM tru_pk_ftable; -- 55 + sum +----- + 55 +(1 row) + +-- SQLite FDW support TRUNCATE command by executing DELETE statement without WHERE clause. +-- In order to delete records in parent and child table subsequently, +-- SQLite FDW executes "PRAGMA foreign_keys = ON" before executing DELETE statement. +TRUNCATE tru_pk_ftable; -- success +TRUNCATE tru_pk_ftable CASCADE; -- success +--Testcase 869: +SELECT count(*) FROM tru_pk_ftable; -- 0 + count +------- + 0 +(1 row) + +--Testcase 870: +SELECT count(*) FROM "S 1".tru_fk_table; -- also truncated,0 + count +------- + 0 +(1 row) + +-- truncate two tables at a command +--Testcase 871: +INSERT INTO tru_ftable (SELECT x FROM generate_series(1,8) x); +--Testcase 872: +INSERT INTO tru_pk_ftable (SELECT x FROM generate_series(3,10) x); +--Testcase 873: +SELECT count(*) from tru_ftable; -- 8 + count +------- + 8 +(1 row) + +--Testcase 874: +SELECT count(*) from tru_pk_ftable; -- 8 + count +------- + 8 +(1 row) + +TRUNCATE tru_ftable, tru_pk_ftable; +--Testcase 875: +SELECT count(*) from tru_ftable; -- 0 + count +------- + 0 +(1 row) + +--Testcase 876: +SELECT count(*) from tru_pk_ftable; -- 0 + count +------- + 0 +(1 row) + +-- truncate with ONLY clause +-- Since ONLY is specified, the table tru_ftable_child that inherits +-- tru_ftable_parent locally is not truncated. +TRUNCATE ONLY tru_ftable_parent; +--Testcase 877: +SELECT sum(id) FROM tru_ftable_parent; -- 126 + sum +----- + 126 +(1 row) + +TRUNCATE tru_ftable_parent; +--Testcase 878: +SELECT count(*) FROM tru_ftable_parent; -- 0 + count +------- + 0 +(1 row) + +-- -- in case when remote table has inherited children +-- CREATE TABLE tru_rtable0_child () INHERITS (tru_rtable0); +-- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x); +-- INSERT INTO "S 1".tru_rtable0_child (SELECT x FROM generate_series(10,14) x); +-- SELECT sum(id) FROM tru_ftable; -- 95 +-- -- Both parent and child tables in the foreign server are truncated +-- -- even though ONLY is specified because ONLY has no effect +-- -- when truncating a foreign table. +-- TRUNCATE ONLY tru_ftable; +-- SELECT count(*) FROM tru_ftable; -- 0 +-- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x); +-- INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x); +-- SELECT sum(id) FROM tru_ftable; -- 255 +-- TRUNCATE tru_ftable; -- truncate both of parent and child +-- SELECT count(*) FROM tru_ftable; -- 0 +-- cleanup +--Testcase 879: +DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable; +-- DROP TABLE tru_rtable0, tru_rtable1, tru_ptable, tru_ptable__p0, tru_pk_table, tru_fk_table, +-- tru_rtable_parent,tru_rtable_child, tru_rtable0_child; +-- =================================================================== +-- test IMPORT FOREIGN SCHEMA +-- =================================================================== +--Testcase 728: +CREATE SCHEMA import_dest1; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; +--Testcase 477: +\det+ import_dest1.* + List of foreign tables + Schema | Table | Server | FDW options | Description +--------------+-------------------+------------+-------------------------------+------------- + import_dest1 | T 0 | sqlite_svr | ("table" 'T 0') | + import_dest1 | T 1 | sqlite_svr | ("table" 'T 1') | + import_dest1 | T 2 | sqlite_svr | ("table" 'T 2') | + import_dest1 | T 3 | sqlite_svr | ("table" 'T 3') | + import_dest1 | T 4 | sqlite_svr | ("table" 'T 4') | + import_dest1 | base_tbl | sqlite_svr | ("table" 'base_tbl') | + import_dest1 | batch_table | sqlite_svr | ("table" 'batch_table') | + import_dest1 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | + import_dest1 | ft3 | sqlite_svr | ("table" 'ft3') | + import_dest1 | grem1 | sqlite_svr | ("table" 'grem1') | + import_dest1 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | + import_dest1 | loc1 | sqlite_svr | ("table" 'loc1') | + import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | + import_dest1 | loct | sqlite_svr | ("table" 'loct') | + import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest1 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | + import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest1 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | + import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | + import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | + import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | + import_dest1 | loct5 | sqlite_svr | ("table" 'loct5') | + import_dest1 | loct6 | sqlite_svr | ("table" 'loct6') | + import_dest1 | loct7 | sqlite_svr | ("table" 'loct7') | + import_dest1 | loct_empty | sqlite_svr | ("table" 'loct_empty') | + import_dest1 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | + import_dest1 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | + import_dest1 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | + import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | + import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | + import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | +(31 rows) + +--Testcase 478: +\d import_dest1.* + Foreign table "import_dest1.T 0" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + C 1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 0') + + Foreign table "import_dest1.T 1" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + C 1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 1') + + Foreign table "import_dest1.T 2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 2') + + Foreign table "import_dest1.T 3" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 3') + + Foreign table "import_dest1.T 4" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 4') + + Foreign table "import_dest1.base_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'base_tbl') + + Foreign table "import_dest1.batch_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + x | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'batch_table') + + Foreign table "import_dest1.foreign_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'foreign_tbl') + + Foreign table "import_dest1.ft3" + Column | Type | Collation | Nullable | Default | FDW options +--------+------+-----------+----------+---------+-------------- + f1 | text | | | | (key 'true') + f2 | text | | | | (key 'true') + f3 | text | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'ft3') + + Foreign table "import_dest1.grem1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'grem1') + + Foreign table "import_dest1.grem1_post14" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'grem1_post14') + + Foreign table "import_dest1.loc1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + f1 | bigint | | | | + f2 | text | | | | + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'loc1') + + Foreign table "import_dest1.local_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'local_tbl') + + Foreign table "import_dest1.loct" + Column | Type | Collation | Nullable | Default | FDW options +--------+------+-----------+----------+---------+------------- + aa | text | | | | + bb | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct') + + Foreign table "import_dest1.loct1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1') + + Foreign table "import_dest1.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + + Foreign table "import_dest1.loct2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2') + + Foreign table "import_dest1.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + + Foreign table "import_dest1.loct3" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct3') + + Foreign table "import_dest1.loct4" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct4') + + Foreign table "import_dest1.loct4_2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct4_2') + + Foreign table "import_dest1.loct5" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct5') + + Foreign table "import_dest1.loct6" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct6') + + Foreign table "import_dest1.loct7" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct7') + + Foreign table "import_dest1.loct_empty" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | not null | | (key 'true') + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct_empty') + + Foreign table "import_dest1.t1_constraint" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 't1_constraint') + + Foreign table "import_dest1.tru_fk_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + fkey | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_fk_table') + + Foreign table "import_dest1.tru_pk_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'tru_pk_table') + + Foreign table "import_dest1.tru_rtable0" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'tru_rtable0') + + Foreign table "import_dest1.tru_rtable_child" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + id | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_rtable_child') + + Foreign table "import_dest1.tru_rtable_parent" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + id | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_rtable_parent') + +-- Options +--Testcase 729: +CREATE SCHEMA import_dest2; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 + OPTIONS (import_default 'true'); +--Testcase 479: +\det+ import_dest2.* + List of foreign tables + Schema | Table | Server | FDW options | Description +--------------+-------------------+------------+-------------------------------+------------- + import_dest2 | T 0 | sqlite_svr | ("table" 'T 0') | + import_dest2 | T 1 | sqlite_svr | ("table" 'T 1') | + import_dest2 | T 2 | sqlite_svr | ("table" 'T 2') | + import_dest2 | T 3 | sqlite_svr | ("table" 'T 3') | + import_dest2 | T 4 | sqlite_svr | ("table" 'T 4') | + import_dest2 | base_tbl | sqlite_svr | ("table" 'base_tbl') | + import_dest2 | batch_table | sqlite_svr | ("table" 'batch_table') | + import_dest2 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | + import_dest2 | ft3 | sqlite_svr | ("table" 'ft3') | + import_dest2 | grem1 | sqlite_svr | ("table" 'grem1') | + import_dest2 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | + import_dest2 | loc1 | sqlite_svr | ("table" 'loc1') | + import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | + import_dest2 | loct | sqlite_svr | ("table" 'loct') | + import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest2 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | + import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest2 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | + import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | + import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | + import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | + import_dest2 | loct5 | sqlite_svr | ("table" 'loct5') | + import_dest2 | loct6 | sqlite_svr | ("table" 'loct6') | + import_dest2 | loct7 | sqlite_svr | ("table" 'loct7') | + import_dest2 | loct_empty | sqlite_svr | ("table" 'loct_empty') | + import_dest2 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | + import_dest2 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | + import_dest2 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | + import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | + import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | + import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | +(31 rows) + +--Testcase 480: +\d import_dest2.* + Foreign table "import_dest2.T 0" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + C 1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 0') + + Foreign table "import_dest2.T 1" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + C 1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 1') + + Foreign table "import_dest2.T 2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 2') + + Foreign table "import_dest2.T 3" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 3') + + Foreign table "import_dest2.T 4" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'T 4') + + Foreign table "import_dest2.base_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'base_tbl') + + Foreign table "import_dest2.batch_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + x | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'batch_table') + + Foreign table "import_dest2.foreign_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'foreign_tbl') + + Foreign table "import_dest2.ft3" + Column | Type | Collation | Nullable | Default | FDW options +--------+------+-----------+----------+---------+-------------- + f1 | text | | | | (key 'true') + f2 | text | | | | (key 'true') + f3 | text | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'ft3') + + Foreign table "import_dest2.grem1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') + b | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'grem1') + + Foreign table "import_dest2.grem1_post14" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + a | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'grem1_post14') + + Foreign table "import_dest2.loc1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + f1 | bigint | | | | + f2 | text | | | | + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'loc1') + + Foreign table "import_dest2.local_tbl" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | | | + c3 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'local_tbl') + + Foreign table "import_dest2.loct" + Column | Type | Collation | Nullable | Default | FDW options +--------+------+-----------+----------+---------+------------- + aa | text | | | | + bb | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct') + + Foreign table "import_dest2.loct1" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1') + + Foreign table "import_dest2.loct1_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct1_rescan') + + Foreign table "import_dest2.loct2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2') + + Foreign table "import_dest2.loct2_rescan" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + c1 | bigint | | | | + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct2_rescan') + + Foreign table "import_dest2.loct3" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct3') + + Foreign table "import_dest2.loct4" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct4') + + Foreign table "import_dest2.loct4_2" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + f1 | bigint | | | | + f2 | bigint | | | | + f3 | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'loct4_2') + + Foreign table "import_dest2.loct5" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct5') + + Foreign table "import_dest2.loct6" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct6') + + Foreign table "import_dest2.loct7" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + a | bigint | | | | + b | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct7') + + Foreign table "import_dest2.loct_empty" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + c1 | bigint | | not null | | (key 'true') + c2 | text | | | | +Server: sqlite_svr +FDW options: ("table" 'loct_empty') + + Foreign table "import_dest2.t1_constraint" + Column | Type | Collation | Nullable | Default | FDW options +--------+-----------------------------+-----------+----------+---------+-------------- + c1 | bigint | | | | (key 'true') + c2 | bigint | | not null | | + c3 | text | | | | + c4 | timestamp with time zone | | | | + c5 | timestamp without time zone | | | | + c6 | character varying(10) | | | | + c7 | character(10) | | | | + c8 | text | | | | +Server: sqlite_svr +FDW options: ("table" 't1_constraint') + + Foreign table "import_dest2.tru_fk_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + fkey | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_fk_table') + + Foreign table "import_dest2.tru_pk_table" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'tru_pk_table') + + Foreign table "import_dest2.tru_rtable0" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+-------------- + id | bigint | | | | (key 'true') +Server: sqlite_svr +FDW options: ("table" 'tru_rtable0') + + Foreign table "import_dest2.tru_rtable_child" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + id | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_rtable_child') + + Foreign table "import_dest2.tru_rtable_parent" + Column | Type | Collation | Nullable | Default | FDW options +--------+--------+-----------+----------+---------+------------- + id | bigint | | | | +Server: sqlite_svr +FDW options: ("table" 'tru_rtable_parent') + +-- Check LIMIT TO and EXCEPT +--Testcase 730: +CREATE SCHEMA import_dest3; +IMPORT FOREIGN SCHEMA public LIMIT TO ("T 1", loct6, nonesuch) + FROM SERVER sqlite_svr INTO import_dest3; +--Testcase 481: +\det+ import_dest3.* + List of foreign tables + Schema | Table | Server | FDW options | Description +--------------+-------+------------+-------------------+------------- + import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | + import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | +(2 rows) + +IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) + FROM SERVER sqlite_svr INTO import_dest3; +--Testcase 482: +\det+ import_dest3.* + List of foreign tables + Schema | Table | Server | FDW options | Description +--------------+-------------------+------------+-------------------------------+------------- + import_dest3 | T 0 | sqlite_svr | ("table" 'T 0') | + import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | + import_dest3 | T 2 | sqlite_svr | ("table" 'T 2') | + import_dest3 | T 3 | sqlite_svr | ("table" 'T 3') | + import_dest3 | T 4 | sqlite_svr | ("table" 'T 4') | + import_dest3 | base_tbl | sqlite_svr | ("table" 'base_tbl') | + import_dest3 | batch_table | sqlite_svr | ("table" 'batch_table') | + import_dest3 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | + import_dest3 | ft3 | sqlite_svr | ("table" 'ft3') | + import_dest3 | grem1 | sqlite_svr | ("table" 'grem1') | + import_dest3 | grem1_post14 | sqlite_svr | ("table" 'grem1_post14') | + import_dest3 | loc1 | sqlite_svr | ("table" 'loc1') | + import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | + import_dest3 | loct | sqlite_svr | ("table" 'loct') | + import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | + import_dest3 | loct1_rescan | sqlite_svr | ("table" 'loct1_rescan') | + import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | + import_dest3 | loct2_rescan | sqlite_svr | ("table" 'loct2_rescan') | + import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | + import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | + import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | + import_dest3 | loct5 | sqlite_svr | ("table" 'loct5') | + import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | + import_dest3 | loct7 | sqlite_svr | ("table" 'loct7') | + import_dest3 | loct_empty | sqlite_svr | ("table" 'loct_empty') | + import_dest3 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | + import_dest3 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | + import_dest3 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | + import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | + import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | + import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | +(31 rows) + +-- Assorted error cases +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; +ERROR: relation "T 0" already exists +CONTEXT: importing foreign table "T 0" +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO notthere; +ERROR: schema "notthere" does not exist +IMPORT FOREIGN SCHEMA public FROM SERVER nowhere INTO notthere; +ERROR: server "nowhere" does not exist +/* +-- Skip these test, sqlite fdw does not support fetch_size option, partition table +-- Check case of a type present only on the remote server. +-- We can fake this by dropping the type locally in our transaction. +CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue'); +CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors"); + +CREATE SCHEMA import_dest5; +BEGIN; +DROP TYPE "Colors" CASCADE; +IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5) + FROM SERVER loopback INTO import_dest5; -- ERROR + +ROLLBACK; + +BEGIN; + + +CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' ); + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=101']; + +ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' ); + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=101']; + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=202']; + +CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' ); + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=30000']; + +ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000'); + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=30000']; + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=60000']; + +ROLLBACK; + +-- =================================================================== +-- test partitionwise joins +-- =================================================================== +SET enable_partitionwise_join=on; + +CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a); +CREATE TABLE fprt1_p1 (LIKE fprt1); +CREATE TABLE fprt1_p2 (LIKE fprt1); +ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false'); +ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false'); +INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i; +INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i; +CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250) + SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true'); +CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500) + SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2'); +ANALYZE fprt1; +ANALYZE fprt1_p1; +ANALYZE fprt1_p2; + +CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b); +CREATE TABLE fprt2_p1 (LIKE fprt2); +CREATE TABLE fprt2_p2 (LIKE fprt2); +ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false'); +ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false'); +INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i; +INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i; +CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int) + SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true'); +ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250); +CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500) + SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true'); +ANALYZE fprt2; +ANALYZE fprt2_p1; +ANALYZE fprt2_p2; + +-- inner join three tables +EXPLAIN (COSTS OFF) +SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; +SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; + +-- left outer join + nullable clause +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; +SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; + +-- with whole-row reference; partitionwise join does not apply +EXPLAIN (COSTS OFF) +SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; +SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; + +-- join with lateral reference +EXPLAIN (COSTS OFF) +SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; +SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; + +-- with PHVs, partitionwise join selected but no join pushdown +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + +-- test FOR UPDATE; partitionwise join does not apply +EXPLAIN (COSTS OFF) +SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; +SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; + +RESET enable_partitionwise_join; + + +-- =================================================================== +-- test partitionwise aggregates +-- =================================================================== + +CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); + +CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); + +INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; +INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; +INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; + +-- Create foreign partitions +CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); +CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2'); +CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3'); + +ANALYZE pagg_tab; +ANALYZE fpagg_tab_p1; +ANALYZE fpagg_tab_p2; +ANALYZE fpagg_tab_p3; + +-- When GROUP BY clause matches with PARTITION KEY. +-- Plan with partitionwise aggregates is disabled +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Plan with partitionwise aggregates is enabled +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Check with whole-row reference +-- Should have all the columns in the target list for the given relation +EXPLAIN (VERBOSE, COSTS OFF) +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- When GROUP BY clause does not match with PARTITION KEY. +EXPLAIN (COSTS OFF) +SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; +*/ +/* +-- Skip these tests, sqlite fdw does not support nosuper user. +-- =================================================================== +-- access rights and superuser +-- =================================================================== + +-- Non-superuser cannot create a FDW without a password in the connstr +CREATE ROLE regress_nosuper NOSUPERUSER; + +GRANT USAGE ON FOREIGN DATA WRAPPER sqlite_fdw TO regress_nosuper; + +SET ROLE regress_nosuper; + +SHOW is_superuser; + +-- This will be OK, we can create the FDW +DO $d$ + BEGIN + EXECUTE $$CREATE SERVER sqlite_nopw FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; + +-- But creation of user mappings for non-superusers should fail +CREATE USER MAPPING FOR public SERVER sqlite_nopw; +CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; + +CREATE FOREIGN TABLE ft1_nopw ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_nopw; + +ALTER FOREIGN TABLE ft1_nopw OPTIONS (table 'T 1'); +ALTER FOREIGN TABLE ft1_nopw ALTER COLUMN c1 OPTIONS (column_name 'C 1'); + +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- If we add a password to the connstr it'll fail, because we don't allow passwords +-- in connstrs only in user mappings. + +ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw'); + + +-- If we add a password for our user mapping instead, we should get a different +-- error because the password wasn't actually *used* when we run with trust auth. +-- +-- This won't work with installcheck, but neither will most of the FDW checks. + +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw'); + +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- Unpriv user cannot make the mapping passwordless +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); + + +SELECT 1 FROM ft1_nopw LIMIT 1; + +RESET ROLE; + +-- But the superuser can +ALTER USER MAPPING FOR regress_nosuper SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); + +SET ROLE regress_nosuper; + +-- Should finally work now +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- unpriv user also cannot set sslcert / sslkey on the user mapping +-- first set password_required so we see the right error messages +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (SET password_required 'true'); +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslcert 'foo.crt'); +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslkey 'foo.key'); + +-- We're done with the role named after a specific user and need to check the +-- changes to the public mapping. +DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; + +-- This will fail again as it'll resolve the user mapping for public, which +-- lacks password_required=false +SELECT 1 FROM ft1_nopw LIMIT 1; + +RESET ROLE; + +-- The user mapping for public is passwordless and lacks the password_required=false +-- mapping option, but will work because the current user is a superuser. +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- cleanup +DROP USER MAPPING FOR public SERVER sqlite_nopw; +DROP OWNED BY regress_nosuper; +DROP ROLE regress_nosuper; + +-- Clean-up +RESET enable_partitionwise_aggregate; +*/ +-- Two-phase transactions are not supported. +BEGIN; +--Testcase 731: +SELECT count(*) FROM ft1; + count +------- + 822 +(1 row) + +-- error here +--Testcase 732: +PREPARE TRANSACTION 'fdw_tpc'; +ERROR: cannot prepare a transaction that modified remote tables +ROLLBACK; +WARNING: there is no transaction in progress +-- =================================================================== +-- reestablish new connection +-- =================================================================== +-- -- Test case relative with option application_name is not suitable for SQLite FDW. +-- -- Because this option is in libpq of postgres. +-- -- Change application_name of remote connection to special one +-- -- so that we can easily terminate the connection later. +-- ALTER SERVER sqlite_svr OPTIONS (application_name 'fdw_retry_check'); +-- -- Make sure we have a remote connection. +-- SELECT 1 FROM ft1 LIMIT 1; +-- -- Terminate the remote connection and wait for the termination to complete. +-- (If a cache flush happens, the remote connection might have already been +-- dropped; so code this step in a way that doesn't fail if no connection.) +-- DO $$ BEGIN +-- PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity +-- WHERE application_name = 'fdw_retry_check'; +-- END $$; +-- -- This query should detect the broken connection when starting new remote +-- -- transaction, reestablish new connection, and then succeed. +-- BEGIN; +-- SELECT 1 FROM ft1 LIMIT 1; +-- -- If we detect the broken connection when starting a new remote +-- -- subtransaction, we should fail instead of establishing a new connection. +-- -- Terminate the remote connection and wait for the termination to complete. +-- DO $$ BEGIN +-- PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity +-- WHERE application_name = 'fdw_retry_check'; +-- END $$; +-- SAVEPOINT s; +-- -- The text of the error might vary across platforms, so only show SQLSTATE. +-- \set VERBOSITY sqlstate +-- SELECT 1 FROM ft1 LIMIT 1; -- should fail +-- \set VERBOSITY default +-- COMMIT; +-- ============================================================================= +-- test connection invalidation cases and sqlite_fdw_get_connections function +-- ============================================================================= +-- Let's ensure to close all the existing cached connections. +--Testcase 880: +SELECT 1 FROM sqlite_fdw_disconnect_all(); + ?column? +---------- + 1 +(1 row) + +-- No cached connections, so no records should be output. +--Testcase 881: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- +(0 rows) + +-- This test case is for closing the connection in sqlitefdw_xact_callback +BEGIN; +-- Connection xact depth becomes 1 i.e. the connection is in midst of the xact. +--Testcase 882: +SELECT 1 FROM ft1 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +--Testcase 883: +SELECT 1 FROM ft7 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +-- List all the existing cached connections. sqlite_svr and sqlite_svr3 should be +-- output. +--Testcase 884: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- + sqlite_svr + sqlite_svr3 +(2 rows) + +-- Connections are not closed at the end of the alter and drop statements. +-- That's because the connections are in midst of this xact, +-- they are just marked as invalid in sqlitefdw_inval_callback. +--Testcase 885: +ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); +--Testcase 886: +DROP SERVER sqlite_svr3 CASCADE; +NOTICE: drop cascades to foreign table ft7 +-- List all the existing cached connections. sqlite_svr and sqlite_svr3 +-- should be output as invalid connections. Also the server name for +-- sqlite_svr3 should be NULL because the server was dropped. +--Testcase 887: +SELECT * FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name | valid +-------------+------- + sqlite_svr | f + | f +(2 rows) + +-- The invalid connections get closed in sqlitefdw_xact_callback during commit. +COMMIT; +--Testcase 888: +ALTER SERVER sqlite_svr OPTIONS (DROP keep_connections); +-- All cached connections were closed while committing above xact, so no +-- records should be output. +--Testcase 889: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- +(0 rows) + +-- ======================================================================= +-- test sqlite_fdw_disconnect and sqlite_fdw_disconnect_all functions +-- ======================================================================= +BEGIN; +-- Ensure to cache loopback connection. +--Testcase 890: +SELECT 1 FROM ft1 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +-- Ensure to cache loopback2 connection. +--Testcase 891: +SELECT 1 FROM ft6 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +-- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be +-- output. +--Testcase 892: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- + sqlite_svr + sqlite_svr2 +(2 rows) + +-- Issue a warning and return false as sqlite_svr connection is still in use and +-- can not be closed. +--Testcase 893: +SELECT sqlite_fdw_disconnect('sqlite_svr'); +WARNING: cannot close connection for server "sqlite_svr" because it is still in use + sqlite_fdw_disconnect +----------------------- + f +(1 row) + +-- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be +-- output. +--Testcase 894: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- + sqlite_svr + sqlite_svr2 +(2 rows) + +-- Return false as connections are still in use, warnings are issued. +-- But disable warnings temporarily because the order of them is not stable. +--Testcase 895: +SET client_min_messages = 'ERROR'; +--Testcase 896: +SELECT sqlite_fdw_disconnect_all(); + sqlite_fdw_disconnect_all +--------------------------- + f +(1 row) + +--Testcase 897: +RESET client_min_messages; +COMMIT; +-- Ensure that sqlite_svr2 connection is closed. +--Testcase 898: +SELECT 1 FROM sqlite_fdw_disconnect('sqlite_svr2'); + ?column? +---------- + 1 +(1 row) + +--Testcase 899: +SELECT server_name FROM sqlite_fdw_get_connections() WHERE server_name = 'sqlite_svr2'; + server_name +------------- +(0 rows) + +-- Return false as sqlite_svr2 connection is closed already. +--Testcase 900: +SELECT sqlite_fdw_disconnect('sqlite_svr2'); + sqlite_fdw_disconnect +----------------------- + f +(1 row) + +-- Return an error as there is no foreign server with given name. +--Testcase 901: +SELECT sqlite_fdw_disconnect('unknownserver'); +ERROR: server "unknownserver" does not exist +-- Let's ensure to close all the existing cached connections. +--Testcase 902: +SELECT 1 FROM sqlite_fdw_disconnect_all(); + ?column? +---------- + 1 +(1 row) + +-- No cached connections, so no records should be output. +--Testcase 903: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- +(0 rows) + +-- ============================================================================= +-- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. +-- ============================================================================= +--Testcase 904: +CREATE ROLE regress_multi_conn_user1 SUPERUSER; +--Testcase 905: +CREATE ROLE regress_multi_conn_user2 SUPERUSER; +--Testcase 906: +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +--Testcase 907: +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +BEGIN; +-- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 +--Testcase 908: +SET ROLE regress_multi_conn_user1; +--Testcase 909: +SELECT 1 FROM ft1 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +--Testcase 910: +RESET ROLE; +-- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user2 +--Testcase 911: +SET ROLE regress_multi_conn_user2; +--Testcase 912: +SELECT 1 FROM ft1 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +--Testcase 913: +RESET ROLE; +-- Should output one cached connection for sqlite_svr server +--Testcase 914: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- + sqlite_svr +(1 row) + +COMMIT; +-- Let's ensure to close all the existing cached connections. +--Testcase 915: +SELECT 1 FROM sqlite_fdw_disconnect_all(); + ?column? +---------- + 1 +(1 row) + +-- No cached connections, so no records should be output. +--Testcase 916: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- +(0 rows) + +-- Clean up +--Testcase 917: +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +--Testcase 918: +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +--Testcase 919: +DROP ROLE regress_multi_conn_user1; +--Testcase 920: +DROP ROLE regress_multi_conn_user2; +-- =================================================================== +-- Test foreign server level option keep_connections +-- =================================================================== +-- By default, the connections associated with foreign server are cached i.e. +-- keep_connections option is on. Set it to off. +--Testcase 921: +ALTER SERVER sqlite_svr OPTIONS (keep_connections 'off'); +-- connection to sqlite_svr server is closed at the end of xact +-- as keep_connections was set to off. +--Testcase 922: +SELECT 1 FROM ft1 LIMIT 1; + ?column? +---------- + 1 +(1 row) + +-- No cached connections, so no records should be output. +--Testcase 923: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + server_name +------------- +(0 rows) + +--Testcase 924: +ALTER SERVER sqlite_svr OPTIONS (SET keep_connections 'on'); +-- =================================================================== +-- batch insert +-- =================================================================== +BEGIN; +--Testcase 925: +CREATE SERVER batch10 FOREIGN DATA WRAPPER sqlite_fdw OPTIONS( batch_size '10' ); +--Testcase 926: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=10']; + count +------- + 1 +(1 row) + +--Testcase 927: +ALTER SERVER batch10 OPTIONS( SET batch_size '20' ); +--Testcase 928: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=10']; + count +------- + 0 +(1 row) + +--Testcase 929: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=20']; + count +------- + 1 +(1 row) + +--Testcase 930: +CREATE FOREIGN TABLE table30 ( x int ) SERVER batch10 OPTIONS ( batch_size '30' ); +--Testcase 931: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=30']; + count +------- + 1 +(1 row) + +--Testcase 932: +ALTER FOREIGN TABLE table30 OPTIONS ( SET batch_size '40'); +--Testcase 933: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=30']; + count +------- + 0 +(1 row) + +--Testcase 934: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=40']; + count +------- + 1 +(1 row) + +ROLLBACK; +--Testcase 935: +CREATE FOREIGN TABLE ftable ( x int OPTIONS (key 'true') ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '10' ); +--Testcase 936: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; + QUERY PLAN +----------------------------------------------------- + Insert on public.ftable + Batch Size: 10 + -> Function Scan on pg_catalog.generate_series i + Output: i.i + Function Call: generate_series(1, 10) +(5 rows) + +--Testcase 937: +INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; +--Testcase 938: +INSERT INTO ftable SELECT * FROM generate_series(11, 31) i; +--Testcase 939: +INSERT INTO ftable VALUES (32); +--Testcase 940: +INSERT INTO ftable VALUES (33), (34); +--Testcase 946: +SELECT COUNT(*) FROM ftable; + count +------- + 34 +(1 row) + +--Testcase 947: +DELETE FROM ftable; +--Testcase 948: +DROP FOREIGN TABLE ftable; +-- Disable batch insert +--Testcase 949: +CREATE FOREIGN TABLE ftable ( x int ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '1' ); +--Testcase 950: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (1), (2); + QUERY PLAN +------------------------------------ + Insert on public.ftable + Batch Size: 1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1 +(4 rows) + +--Testcase 951: +INSERT INTO ftable VALUES (1), (2); +--Testcase 952: +SELECT COUNT(*) FROM ftable; + count +------- + 2 +(1 row) + +-- Disable batch inserting into foreign tables with BEFORE ROW INSERT triggers +-- even if the batch_size option is enabled. +--Testcase 977: +ALTER FOREIGN TABLE ftable OPTIONS ( SET batch_size '10' ); +--Testcase 978: +CREATE TRIGGER trig_row_before BEFORE INSERT ON ftable +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 980: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (3), (4); + QUERY PLAN +------------------------------------ + Insert on public.ftable + Batch Size: 1 + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1 +(4 rows) + +--Testcase 981: +INSERT INTO ftable VALUES (3), (4); +NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable +NOTICE: NEW: (3) +NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable +NOTICE: NEW: (4) +--Testcase 982: +SELECT COUNT(*) FROM ftable; + count +------- + 4 +(1 row) + +-- Clean up +--Testcase 983: +DROP TRIGGER trig_row_before ON ftable; +--Testcase 953: +DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; +-- -- Use partitioning +-- CREATE TABLE batch_table ( x int ) PARTITION BY HASH (x); +-- CREATE TABLE batch_table_p0 (LIKE batch_table); +-- CREATE FOREIGN TABLE batch_table_p0f + -- PARTITION OF batch_table + -- FOR VALUES WITH (MODULUS 3, REMAINDER 0) + -- SERVER sqlite_svr + -- OPTIONS (table 'batch_table_p0', batch_size '10'); +-- CREATE TABLE batch_table_p1 (LIKE batch_table); +-- CREATE FOREIGN TABLE batch_table_p1f + -- PARTITION OF batch_table + -- FOR VALUES WITH (MODULUS 3, REMAINDER 1) +-- SERVER sqlite_svr +-- OPTIONS (table 'batch_table_p1', batch_size '1'); +-- CREATE TABLE batch_table_p2 +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 3, REMAINDER 2); +-- INSERT INTO "S 1".batch_table SELECT * FROM generate_series(1, 66) i; +-- SELECT COUNT(*) FROM "S 1".batch_table; +-- -- Clean up +-- DROP TABLE batch_table; +-- DROP TABLE batch_table_p0; +-- DROP TABLE batch_table_p1; +-- Check that batched mode also works for some inserts made during +-- cross-partition updates +-- CREATE TABLE batch_cp_upd_test (a int) PARTITION BY LIST (a); +-- CREATE TABLE batch_cp_upd_test1 (LIKE batch_cp_upd_test); +-- CREATE FOREIGN TABLE batch_cp_upd_test1_f +-- PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (1) +-- SERVER sqlite_svr +-- OPTIONS (table_name 'batch_cp_upd_test1', batch_size '10'); +-- CREATE TABLE batch_cp_upd_test2 PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (2); +-- CREATE TABLE batch_cp_upd_test3 (LIKE batch_cp_upd_test); +-- CREATE FOREIGN TABLE batch_cp_upd_test3_f +-- PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (3) +-- SERVER loopback +-- OPTIONS (table_name 'batch_cp_upd_test3', batch_size '1'); +-- -- Create statement triggers on remote tables that "log" any INSERTs +-- -- performed on them. +-- CREATE TABLE cmdlog (cmd text); +-- CREATE FUNCTION log_stmt() RETURNS TRIGGER LANGUAGE plpgsql AS $$ +-- BEGIN INSERT INTO public.cmdlog VALUES (TG_OP || ' on ' || TG_RELNAME); RETURN NULL; END; +-- $$; +-- CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test1 +-- FOR EACH STATEMENT EXECUTE FUNCTION log_stmt(); +-- CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test3 +-- FOR EACH STATEMENT EXECUTE FUNCTION log_stmt(); +-- -- This update moves rows from the local partition 'batch_cp_upd_test2' to the +-- -- foreign partition 'batch_cp_upd_test1', one that has insert batching +-- -- enabled, so a single INSERT for both rows. +-- INSERT INTO batch_cp_upd_test VALUES (2), (2); +-- UPDATE batch_cp_upd_test t SET a = 1 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2; +-- -- This one moves rows from the local partition 'batch_cp_upd_test2' to the +-- -- foreign partition 'batch_cp_upd_test2', one that has insert batching +-- -- disabled, so separate INSERTs for the two rows. +-- INSERT INTO batch_cp_upd_test VALUES (2), (2); +-- UPDATE batch_cp_upd_test t SET a = 3 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2; +-- SELECT tableoid::regclass, * FROM batch_cp_upd_test ORDER BY 1; +-- -- Should see 1 INSERT on batch_cp_upd_test1 and 2 on batch_cp_upd_test3 as +-- -- described above. +-- SELECT * FROM cmdlog ORDER BY 1; +-- -- Clean up +-- DROP TABLE batch_cp_upd_test; +-- DROP TABLE batch_cp_upd_test1; +-- DROP TABLE batch_cp_upd_test3; +-- DROP TABLE cmdlog; +-- DROP FUNCTION log_stmt(); +-- -- Use partitioning +-- ALTER SERVER loopback OPTIONS (ADD batch_size '10'); +-- CREATE TABLE batch_table ( x int, field1 text, field2 text) PARTITION BY HASH (x); +-- CREATE TABLE batch_table_p0 (LIKE batch_table); +-- ALTER TABLE batch_table_p0 ADD CONSTRAINT p0_pkey PRIMARY KEY (x); +-- CREATE FOREIGN TABLE batch_table_p0f +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 2, REMAINDER 0) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table_p0'); +-- CREATE TABLE batch_table_p1 (LIKE batch_table); +-- ALTER TABLE batch_table_p1 ADD CONSTRAINT p1_pkey PRIMARY KEY (x); +-- CREATE FOREIGN TABLE batch_table_p1f +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 2, REMAINDER 1) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table_p1'); +-- INSERT INTO batch_table SELECT i, 'test'||i, 'test'|| i FROM generate_series(1, 50) i; +-- SELECT COUNT(*) FROM batch_table; +-- SELECT * FROM batch_table ORDER BY x; +-- -- Clean up +-- DROP TABLE batch_table; +-- DROP TABLE batch_table_p0; +-- DROP TABLE batch_table_p1; +-- ALTER SERVER loopback OPTIONS (DROP batch_size); +-- Test that pending inserts are handled properly when needed +-- CREATE TABLE batch_table (a text, b int); +-- CREATE FOREIGN TABLE ftable (a text, b int) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table', batch_size '2'); +-- CREATE TABLE ltable (a text, b int); +-- CREATE FUNCTION ftable_rowcount_trigf() RETURNS trigger LANGUAGE plpgsql AS +-- $$ +-- begin +-- raise notice '%: there are % rows in ftable', +-- TG_NAME, (SELECT count(*) FROM ftable); +-- if TG_OP = 'DELETE' then +-- return OLD; +-- else +-- return NEW; +-- end if; +-- end; +-- $$; +-- CREATE TRIGGER ftable_rowcount_trigger +-- BEFORE INSERT OR UPDATE OR DELETE ON ltable +-- FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf(); +-- WITH t AS ( +-- INSERT INTO ltable VALUES ('AAA', 42), ('BBB', 42) RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; +-- WITH t AS ( +-- UPDATE ltable SET b = b + 100 RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; +-- WITH t AS ( +-- DELETE FROM ltable RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; +-- -- Clean up +-- DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; +-- DROP TRIGGER ftable_rowcount_trigger ON ltable; +-- DROP TABLE ltable; +-- CREATE TABLE parent (a text, b int) PARTITION BY LIST (a); +-- CREATE TABLE batch_table (a text, b int); +-- CREATE FOREIGN TABLE ftable +-- PARTITION OF parent +-- FOR VALUES IN ('AAA') +-- SERVER loopback +-- OPTIONS (table_name 'batch_table', batch_size '2'); +-- CREATE TABLE ltable +-- PARTITION OF parent +-- FOR VALUES IN ('BBB'); +-- CREATE TRIGGER ftable_rowcount_trigger +-- BEFORE INSERT ON ltable +-- FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf(); +-- INSERT INTO parent VALUES ('AAA', 42), ('BBB', 42), ('AAA', 42), ('BBB', 42); +-- SELECT tableoid::regclass, * FROM parent; +-- -- Clean up +-- DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; +-- DROP TRIGGER ftable_rowcount_trigger ON ltable; +-- DROP TABLE ltable; +-- DROP TABLE parent; +-- DROP FUNCTION ftable_rowcount_trigf; +-- =================================================================== +-- test asynchronous execution +-- =================================================================== +-- ALTER SERVER loopback OPTIONS (DROP extensions); +-- ALTER SERVER loopback OPTIONS (ADD async_capable 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD async_capable 'true'); +-- CREATE TABLE async_pt (a int, b int, c text) PARTITION BY RANGE (a); +-- CREATE TABLE base_tbl1 (a int, b int, c text); +-- CREATE TABLE base_tbl2 (a int, b int, c text); +-- CREATE FOREIGN TABLE async_p1 PARTITION OF async_pt FOR VALUES FROM (1000) TO (2000) +-- SERVER loopback OPTIONS (table_name 'base_tbl1'); +-- CREATE FOREIGN TABLE async_p2 PARTITION OF async_pt FOR VALUES FROM (2000) TO (3000) +-- SERVER loopback2 OPTIONS (table_name 'base_tbl2'); +-- INSERT INTO async_p1 SELECT 1000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- INSERT INTO async_p2 SELECT 2000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; +-- -- simple queries +-- CREATE TABLE result_tbl (a int, b int, c text); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- -- Test error handling, if accessing one of the foreign partitions errors out +-- CREATE FOREIGN TABLE async_p_broken PARTITION OF async_pt FOR VALUES FROM (10000) TO (10001) +-- SERVER loopback OPTIONS (table_name 'non_existent_table'); +-- SELECT * FROM async_pt; +-- DROP FOREIGN TABLE async_p_broken; +-- -- Check case where multiple partitions use the same connection +-- CREATE TABLE base_tbl3 (a int, b int, c text); +-- CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000) +-- SERVER loopback2 OPTIONS (table_name 'base_tbl3'); +-- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- DROP FOREIGN TABLE async_p3; +-- DROP TABLE base_tbl3; +-- -- Check case where the partitioned table has local/remote partitions +-- CREATE TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000); +-- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- -- partitionwise joins +-- SET enable_partitionwise_join TO true; +-- CREATE TABLE join_tbl (a1 int, b1 int, c1 text, a2 int, b2 int, c2 text); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; +-- RESET enable_partitionwise_join; +-- -- Test rescan of an async Append node with do_exec_prune=false +-- SET enable_hashjoin TO false; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; +-- RESET enable_hashjoin; +-- -- Test interaction of async execution with plan-time partition pruning +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE a < 3000; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE a < 2000; +-- -- Test interaction of async execution with run-time partition pruning +-- SET plan_cache_mode TO force_generic_plan; +-- PREPARE async_pt_query (int, int) AS +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE a < $1 AND b === $2; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- EXECUTE async_pt_query (3000, 505); +-- EXECUTE async_pt_query (3000, 505); +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- EXECUTE async_pt_query (2000, 505); +-- EXECUTE async_pt_query (2000, 505); +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- RESET plan_cache_mode; +-- CREATE TABLE local_tbl(a int, b int, c text); +-- INSERT INTO local_tbl VALUES (1505, 505, 'foo'), (2505, 505, 'bar'); +-- ANALYZE local_tbl; +-- CREATE INDEX base_tbl1_idx ON base_tbl1 (a); +-- CREATE INDEX base_tbl2_idx ON base_tbl2 (a); +-- CREATE INDEX async_p3_idx ON async_p3 (a); +-- ANALYZE base_tbl1; +-- ANALYZE base_tbl2; +-- ANALYZE async_p3; +-- ALTER FOREIGN TABLE async_p1 OPTIONS (use_remote_estimate 'true'); +-- ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true'); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; +-- ALTER FOREIGN TABLE async_p1 OPTIONS (DROP use_remote_estimate); +-- ALTER FOREIGN TABLE async_p2 OPTIONS (DROP use_remote_estimate); +-- DROP TABLE local_tbl; +-- DROP INDEX base_tbl1_idx; +-- DROP INDEX base_tbl2_idx; +-- DROP INDEX async_p3_idx; +-- -- UNION queries +-- SET enable_sort TO off; +-- SET enable_incremental_sort TO off; +-- -- Adjust fdw_startup_cost so that we get an unordered path in the Append. +-- ALTER SERVER loopback2 OPTIONS (ADD fdw_startup_cost '0.00'); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION ALL +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION ALL +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; +-- RESET enable_incremental_sort; +-- RESET enable_sort; +-- ALTER SERVER loopback2 OPTIONS (DROP fdw_startup_cost); +-- -- Disable async execution if we use gating Result nodes for pseudoconstant +-- -- quals +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- (SELECT * FROM async_p1 WHERE CURRENT_USER = SESSION_USER) +-- UNION ALL +-- (SELECT * FROM async_p2 WHERE CURRENT_USER = SESSION_USER); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM ((SELECT * FROM async_p1 WHERE b < 10) UNION ALL (SELECT * FROM async_p2 WHERE b < 10)) s WHERE CURRENT_USER = SESSION_USER; +-- -- Test that pending requests are processed properly +-- SET enable_mergejoin TO false; +-- SET enable_hashjoin TO false; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; +-- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; +-- CREATE TABLE local_tbl (a int, b int, c text); +-- INSERT INTO local_tbl VALUES (1505, 505, 'foo'); +-- ANALYZE local_tbl; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; +-- -- Check with foreign modify +-- CREATE TABLE base_tbl3 (a int, b int, c text); +-- CREATE FOREIGN TABLE remote_tbl (a int, b int, c text) +-- SERVER loopback OPTIONS (table_name 'base_tbl3'); +-- INSERT INTO remote_tbl VALUES (2505, 505, 'bar'); +-- CREATE TABLE base_tbl4 (a int, b int, c text); +-- CREATE FOREIGN TABLE insert_tbl (a int, b int, c text) +-- SERVER loopback OPTIONS (table_name 'base_tbl4'); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); +-- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); +-- SELECT * FROM insert_tbl ORDER BY a; +-- -- Check with direct modify +-- EXPLAIN (VERBOSE, COSTS OFF) +-- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) +-- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; +-- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) +-- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; +-- DROP TABLE local_tbl; +-- DROP FOREIGN TABLE remote_tbl; +-- DROP FOREIGN TABLE insert_tbl; +-- DROP TABLE base_tbl3; +-- DROP TABLE base_tbl4; +-- RESET enable_mergejoin; +-- RESET enable_hashjoin; +-- -- Test that UPDATE/DELETE with inherited target works with async_capable enabled +-- EXPLAIN (VERBOSE, COSTS OFF) +-- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; +-- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- DELETE FROM async_pt WHERE b = 0 RETURNING *; +-- DELETE FROM async_pt WHERE b = 0 RETURNING *; +-- -- Check EXPLAIN ANALYZE for a query that scans empty partitions asynchronously +-- DELETE FROM async_p1; +-- DELETE FROM async_p2; +-- DELETE FROM async_p3; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM async_pt; +-- -- Clean up +-- DROP TABLE async_pt; +-- DROP TABLE base_tbl1; +-- DROP TABLE base_tbl2; +-- DROP TABLE result_tbl; +-- DROP TABLE join_tbl; +-- -- Test that an asynchronous fetch is processed before restarting the scan in +-- -- ReScanForeignScan +-- CREATE TABLE base_tbl (a int, b int); +-- INSERT INTO base_tbl VALUES (1, 11), (2, 22), (3, 33); +-- CREATE FOREIGN TABLE foreign_tbl (b int) +-- SERVER loopback OPTIONS (table_name 'base_tbl'); +-- CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl) +-- SERVER loopback OPTIONS (table_name 'base_tbl'); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl); +-- SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl); +-- -- Clean up +-- DROP FOREIGN TABLE foreign_tbl CASCADE; +-- DROP TABLE base_tbl; +-- ALTER SERVER loopback OPTIONS (DROP async_capable); +-- ALTER SERVER loopback2 OPTIONS (DROP async_capable); +-- =================================================================== +-- test invalid server and foreign table options +-- =================================================================== +-- -- Invalid fdw_startup_cost option +-- CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw +-- OPTIONS(fdw_startup_cost '100$%$#$#'); +-- -- Invalid fdw_tuple_cost option +-- CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw +-- OPTIONS(fdw_tuple_cost '100$%$#$#'); +-- -- Invalid fetch_size option +-- CREATE FOREIGN TABLE inv_fsz (c1 int ) +-- SERVER loopback OPTIONS (fetch_size '100$%$#$#'); +-- Invalid batch_size option +--Testcase 954: +CREATE FOREIGN TABLE inv_bsz (c1 int ) + SERVER sqlite_svr OPTIONS (batch_size '100$%$#$#'); +ERROR: invalid value for integer option "batch_size": 100$%$#$# +-- -- No option is allowed to be specified at foreign data wrapper level +-- ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw'); +-- -- =================================================================== +-- -- test postgres_fdw.application_name GUC +-- -- =================================================================== +-- To avoid race conditions in checking the remote session's application_name, +-- use this view to make the remote session itself read its application_name. +-- CREATE VIEW my_application_name AS +-- SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid(); +-- CREATE FOREIGN TABLE remote_application_name (application_name text) +-- SERVER loopback2 +-- OPTIONS (schema_name 'public', table_name 'my_application_name'); +-- SELECT count(*) FROM remote_application_name; +-- Specify escape sequences in application_name option of a server +-- object so as to test that they are replaced with status information +-- expectedly. Note that we are also relying on ALTER SERVER to force +-- the remote session to be restarted with its new application name. +-- -- Since pg_stat_activity.application_name may be truncated to less than +-- -- NAMEDATALEN characters, note that substring() needs to be used +-- -- at the condition of test query to make sure that the string consisting +-- -- of database name and process ID is also less than that. +-- ALTER SERVER loopback2 OPTIONS (application_name 'fdw_%d%p'); +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_database() || pg_backend_pid() for +-- current_setting('max_identifier_length')::int); +-- -- postgres_fdw.application_name overrides application_name option +-- -- of a server object if both settings are present. +-- ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_wrong'); +-- SET postgres_fdw.application_name TO 'fdw_%a%u%%'; +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_setting('application_name') || +-- CURRENT_USER || '%' for current_setting('max_identifier_length')::int); +-- RESET postgres_fdw.application_name; +-- -- Test %c (session ID) and %C (cluster name) escape sequences. +-- ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_%C%c'); +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_setting('cluster_name') || +-- to_hex(trunc(EXTRACT(EPOCH FROM (SELECT backend_start FROM +-- pg_stat_get_activity(pg_backend_pid()))))::integer) || '.' || +-- to_hex(pg_backend_pid()) +-- for current_setting('max_identifier_length')::int); +-- -- Clean up. +-- DROP FOREIGN TABLE remote_application_name; +-- DROP VIEW my_application_name; +-- -- =================================================================== +-- -- test parallel commit and parallel abort +-- -- =================================================================== +-- ALTER SERVER loopback OPTIONS (ADD parallel_commit 'true'); +-- ALTER SERVER loopback OPTIONS (ADD parallel_abort 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD parallel_commit 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD parallel_abort 'true'); +-- CREATE TABLE ploc1 (f1 int, f2 text); +-- CREATE FOREIGN TABLE prem1 (f1 int, f2 text) +-- SERVER loopback OPTIONS (table_name 'ploc1'); +-- CREATE TABLE ploc2 (f1 int, f2 text); +-- CREATE FOREIGN TABLE prem2 (f1 int, f2 text) +-- SERVER loopback2 OPTIONS (table_name 'ploc2'); +-- BEGIN; +-- INSERT INTO prem1 VALUES (101, 'foo'); +-- INSERT INTO prem2 VALUES (201, 'bar'); +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (102, 'foofoo'); +-- INSERT INTO prem2 VALUES (202, 'barbar'); +-- RELEASE SAVEPOINT s; +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; +-- -- This tests executing DEALLOCATE ALL against foreign servers in parallel +-- -- during pre-commit +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (103, 'baz'); +-- INSERT INTO prem2 VALUES (203, 'qux'); +-- ROLLBACK TO SAVEPOINT s; +-- RELEASE SAVEPOINT s; +-- INSERT INTO prem1 VALUES (104, 'bazbaz'); +-- INSERT INTO prem2 VALUES (204, 'quxqux'); +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; +-- BEGIN; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ABORT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; +-- -- This tests executing DEALLOCATE ALL against foreign servers in parallel +-- -- during post-abort +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ROLLBACK TO SAVEPOINT s; +-- RELEASE SAVEPOINT s; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ABORT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; +-- ALTER SERVER loopback OPTIONS (DROP parallel_commit); +-- ALTER SERVER loopback OPTIONS (DROP parallel_abort); +-- ALTER SERVER loopback2 OPTIONS (DROP parallel_commit); +-- ALTER SERVER loopback2 OPTIONS (DROP parallel_abort); +-- -- =================================================================== +-- -- test for ANALYZE sampling +-- -- =================================================================== +-- CREATE TABLE analyze_table (id int, a text, b bigint); +-- CREATE FOREIGN TABLE analyze_ftable (id int, a text, b bigint) +-- SERVER loopback OPTIONS (table_name 'analyze_rtable1'); +-- INSERT INTO analyze_table (SELECT x FROM generate_series(1,1000) x); +-- ANALYZE analyze_table; +-- SET default_statistics_target = 10; +-- ANALYZE analyze_table; +-- ALTER SERVER loopback OPTIONS (analyze_sampling 'invalid'); +-- ALTER SERVER loopback OPTIONS (analyze_sampling 'auto'); +-- ANALYZE analyze_table; +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'system'); +-- ANALYZE analyze_table; +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'bernoulli'); +-- ANALYZE analyze_table; +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'random'); +-- ANALYZE analyze_table; +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'off'); +-- ANALYZE analyze_table; +-- cleanup +-- DROP FOREIGN TABLE analyze_ftable; +-- DROP TABLE analyze_table; +-- SQLite FDW does not support query cancel feature +-- SELECT version() ~ 'cygwin' AS skip_test \gset +-- \if :skip_test +-- \quit +-- \endif +-- -- Let's test canceling a remote query. Use a table that does not have +-- -- remote_estimate enabled, else there will be multiple queries to the +-- -- remote and we might unluckily send the cancel in between two of them. +-- -- First let's confirm that the query is actually pushed down. +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; +-- BEGIN; +-- -- Make sure that connection is open and set up. +-- SELECT count(*) FROM ft1 a; +-- -- Timeout needs to be long enough to be sure that we've sent the slow query. +-- SET LOCAL statement_timeout = '100ms'; +-- -- This would take very long if not canceled: +-- SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; +-- COMMIT; +-- Clean-up +--Testcase 733: +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +--Testcase 734: +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +--Testcase 735: +DROP SERVER sqlite_svr CASCADE; +NOTICE: drop cascades to 134 other objects +DETAIL: drop cascades to foreign table "S 1"."T 0" +drop cascades to foreign table "S 1"."T 1" +drop cascades to foreign table "S 1"."T 2" +drop cascades to foreign table "S 1"."T 3" +drop cascades to foreign table "S 1"."T 4" +drop cascades to foreign table "S 1".base_tbl +drop cascades to foreign table "S 1".loc1 +drop cascades to foreign table "S 1".loct +drop cascades to foreign table "S 1".loct1 +drop cascades to foreign table "S 1".loct2 +drop cascades to foreign table "S 1".loct3 +drop cascades to foreign table "S 1".loct4 +drop cascades to foreign table "S 1".loct4_2 +drop cascades to foreign table "S 1".loct5 +drop cascades to foreign table "S 1".loct6 +drop cascades to foreign table "S 1".loct7 +drop cascades to foreign table "S 1".local_tbl +drop cascades to foreign table "S 1".ft3 +drop cascades to foreign table "S 1".foreign_tbl +drop cascades to foreign table "S 1".grem1 +drop cascades to foreign table "S 1".grem1_post14 +drop cascades to foreign table "S 1".loct1_rescan +drop cascades to foreign table "S 1".loct2_rescan +drop cascades to foreign table "S 1".t1_constraint +drop cascades to foreign table "S 1".tru_rtable0 +drop cascades to foreign table "S 1".tru_pk_table +drop cascades to foreign table "S 1".tru_fk_table +drop cascades to foreign table "S 1".tru_rtable_parent +drop cascades to foreign table "S 1".tru_rtable_child +drop cascades to foreign table "S 1".loct_empty +drop cascades to foreign table "S 1".batch_table +drop cascades to foreign table ft1_org +drop cascades to foreign table ft2 +drop cascades to foreign table ft4 +drop cascades to foreign table ft5 +drop cascades to foreign table ft_empty +drop cascades to foreign table ft3 +drop cascades to foreign table ft1 +drop cascades to foreign table loc1 +drop cascades to foreign table rem1 +drop cascades to foreign table grem1 +drop cascades to foreign table import_dest1."T 0" +drop cascades to foreign table import_dest1."T 1" +drop cascades to foreign table import_dest1."T 2" +drop cascades to foreign table import_dest1."T 3" +drop cascades to foreign table import_dest1."T 4" +drop cascades to foreign table import_dest1.base_tbl +drop cascades to foreign table import_dest1.loc1 +drop cascades to foreign table import_dest1.loct +drop cascades to foreign table import_dest1.loct1 +drop cascades to foreign table import_dest1.loct2 +drop cascades to foreign table import_dest1.loct3 +drop cascades to foreign table import_dest1.loct4 +drop cascades to foreign table import_dest1.loct4_2 +drop cascades to foreign table import_dest1.loct5 +drop cascades to foreign table import_dest1.loct6 +drop cascades to foreign table import_dest1.loct7 +drop cascades to foreign table import_dest1.local_tbl +drop cascades to foreign table import_dest1.ft3 +drop cascades to foreign table import_dest1.foreign_tbl +drop cascades to foreign table import_dest1.grem1 +drop cascades to foreign table import_dest1.grem1_post14 +drop cascades to foreign table import_dest1.loct1_rescan +drop cascades to foreign table import_dest1.loct2_rescan +drop cascades to foreign table import_dest1.t1_constraint +drop cascades to foreign table import_dest1.tru_rtable0 +drop cascades to foreign table import_dest1.tru_pk_table +drop cascades to foreign table import_dest1.tru_fk_table +drop cascades to foreign table import_dest1.tru_rtable_parent +drop cascades to foreign table import_dest1.tru_rtable_child +drop cascades to foreign table import_dest1.loct_empty +drop cascades to foreign table import_dest1.batch_table +drop cascades to foreign table import_dest2."T 0" +drop cascades to foreign table import_dest2."T 1" +drop cascades to foreign table import_dest2."T 2" +drop cascades to foreign table import_dest2."T 3" +drop cascades to foreign table import_dest2."T 4" +drop cascades to foreign table import_dest2.base_tbl +drop cascades to foreign table import_dest2.loc1 +drop cascades to foreign table import_dest2.loct +drop cascades to foreign table import_dest2.loct1 +drop cascades to foreign table import_dest2.loct2 +drop cascades to foreign table import_dest2.loct3 +drop cascades to foreign table import_dest2.loct4 +drop cascades to foreign table import_dest2.loct4_2 +drop cascades to foreign table import_dest2.loct5 +drop cascades to foreign table import_dest2.loct6 +drop cascades to foreign table import_dest2.loct7 +drop cascades to foreign table import_dest2.local_tbl +drop cascades to foreign table import_dest2.ft3 +drop cascades to foreign table import_dest2.foreign_tbl +drop cascades to foreign table import_dest2.grem1 +drop cascades to foreign table import_dest2.grem1_post14 +drop cascades to foreign table import_dest2.loct1_rescan +drop cascades to foreign table import_dest2.loct2_rescan +drop cascades to foreign table import_dest2.t1_constraint +drop cascades to foreign table import_dest2.tru_rtable0 +drop cascades to foreign table import_dest2.tru_pk_table +drop cascades to foreign table import_dest2.tru_fk_table +drop cascades to foreign table import_dest2.tru_rtable_parent +and 34 other objects (see server log for list) +--Testcase 736: +DROP SERVER sqlite_svr2 CASCADE; +NOTICE: drop cascades to foreign table ft6 +--Testcase 737: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/16.0/extra/timestamp.out b/expected/17.0/extra/timestamp.out similarity index 83% rename from expected/16.0/extra/timestamp.out rename to expected/17.0/extra/timestamp.out index 802a83f5..072185d1 100644 --- a/expected/16.0/extra/timestamp.out +++ b/expected/17.0/extra/timestamp.out @@ -318,10 +318,134 @@ WHERE date_as_number > (('2020-05-10 10:45:29')::timestamp); SQLite query: SELECT `name`, `date_as_text`, `date_as_number` FROM main."dates" WHERE ((`date_as_number` > strftime('%s', '2020-05-10 10:45:29'))) (3 rows) +-- test arithmetic with infinite timestamps +--Testcase 39: +CREATE FOREIGN TABLE inf_timestamp ( + t1 TIMESTAMP , + t2 TIMESTAMP, + id int OPTIONS (key 'true')) +SERVER sqlite_svr OPTIONS (table 'infinite_timestamp');; +--Testcase 40: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, 'infinity'::timestamp); +--Testcase 41: +SELECT t1 - t2 FROM inf_timestamp; +ERROR: interval out of range +--Testcase 42: +DELETE FROM inf_timestamp; +--Testcase 43: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '-infinity'::timestamp); +--Testcase 44: +SELECT t1 - t2 FROM inf_timestamp; + ?column? +---------- + infinity +(1 row) + +--Testcase 45: +DELETE FROM inf_timestamp; +--Testcase 46: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, 'infinity'::timestamp); +--Testcase 47: +SELECT t1 - t2 FROM inf_timestamp; + ?column? +----------- + -infinity +(1 row) + +--Testcase 48: +DELETE FROM inf_timestamp; +--Testcase 49: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '-infinity'::timestamp); +--Testcase 50: +SELECT t1 - t2 FROM inf_timestamp; +ERROR: interval out of range +--Testcase 51: +DELETE FROM inf_timestamp; +--Testcase 52: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '1995-08-06 12:12:12'::timestamp); +--Testcase 53: +SELECT t1 - t2 FROM inf_timestamp; + ?column? +---------- + infinity +(1 row) + +--Testcase 54: +DELETE FROM inf_timestamp; +--Testcase 55: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '1995-08-06 12:12:12'::timestamp); +--Testcase 56: +SELECT t1 - t2 FROM inf_timestamp; + ?column? +----------- + -infinity +(1 row) + +-- test age() with infinite timestamps +--Testcase 58: +DELETE FROM inf_timestamp; +--Testcase 59: +INSERT INTO inf_timestamp(t1) VALUES ('infinity'::timestamp); +--Testcase 60: +SELECT age(t1) FROM inf_timestamp; + age +----------- + -infinity +(1 row) + +--Testcase 61: +DELETE FROM inf_timestamp; +--Testcase 62: +INSERT INTO inf_timestamp(t1) VALUES ('-infinity'::timestamp); +--Testcase 63: +SELECT age(t1) FROM inf_timestamp; + age +---------- + infinity +(1 row) + +--Testcase 64: +DELETE FROM inf_timestamp; +--Testcase 65: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, 'infinity':: timestamp); +--Testcase 66: +SELECT age(t1, t2) FROM inf_timestamp; +ERROR: interval out of range +--Testcase 67: +DELETE FROM inf_timestamp; +--Testcase 68: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '-infinity':: timestamp); +--Testcase 69: +SELECT age(t1, t2) FROM inf_timestamp; + age +---------- + infinity +(1 row) + +--Testcase 70: +DELETE FROM inf_timestamp; +--Testcase 71: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, 'infinity':: timestamp); +--Testcase 72: +SELECT age(t1, t2) FROM inf_timestamp; + age +----------- + -infinity +(1 row) + +--Testcase 73: +DELETE FROM inf_timestamp; +--Testcase 74: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '-infinity':: timestamp); +--Testcase 75: +SELECT age(t1, t2) FROM inf_timestamp; +ERROR: interval out of range --Testcase 35: DROP FOREIGN TABLE dates1; --Testcase 36: DROP FOREIGN TABLE dates2; +--Testcase 57: +DROP FOREIGN TABLE inf_timestamp; --Testcase 37: DROP SERVER sqlite_svr; --Testcase 38: diff --git a/expected/13.12/extra/update.out b/expected/17.0/extra/update.out similarity index 90% rename from expected/13.12/extra/update.out rename to expected/17.0/extra/update.out index a0c29c4b..f89629ca 100644 --- a/expected/13.12/extra/update.out +++ b/expected/17.0/extra/update.out @@ -61,6 +61,13 @@ SELECT * FROM update_test; 2 | 10 | 20 | (2 rows) +-- error, you're not supposed to qualify the target column +--Testcase 41: +UPDATE update_test t SET t.b = t.b + 10 WHERE t.a = 10; +ERROR: column "t" of relation "update_test" does not exist +LINE 1: UPDATE update_test t SET t.b = t.b + 10 WHERE t.a = 10; + ^ +HINT: SET target columns cannot be qualified with the relation name. -- -- Test VALUES in FROM -- @@ -216,12 +223,12 @@ UPDATE update_test t ----------------------------------------------------------------------------------------- Update on public.update_test t -> Result - Output: t.i, $1, $2, t.c, (SubPlan 1 (returns $1,$2)), t.i + Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), t.i, t.* One-Time Filter: (CURRENT_USER = SESSION_USER) -> Foreign Scan on public.update_test t - Output: t.i, t.a, t.b, t.c - SQLite query: SELECT `i`, `a`, `c` FROM main."update_test" - SubPlan 1 (returns $1,$2) + Output: t.a, t.i, t.* + SQLite query: SELECT `i`, `a`, `b`, `c` FROM main."update_test" + SubPlan 1 -> Foreign Scan on public.update_test s Output: s.b, s.a SQLite query: SELECT `a`, `b` FROM main."update_test" WHERE ((`a` = ?)) @@ -243,17 +250,17 @@ SELECT a, b, char_length(c) FROM update_test; /* Skip, sqlite fdw does not support ON CONFLICT DO UPDATE -- Test ON CONFLICT DO UPDATE -INSERT INTO upsert_test VALUES(1, 'Boo'); +INSERT INTO upsert_test VALUES(1, 'Boo'), (3, 'Zoo'); -- uncorrelated sub-select: WITH aaa AS (SELECT 1 AS a, 'Foo' AS b) INSERT INTO upsert_test VALUES (1, 'Bar') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b, a FROM aaa) RETURNING *; -- correlated sub-select: -INSERT INTO upsert_test VALUES (1, 'Baz') ON CONFLICT(a) +INSERT INTO upsert_test VALUES (1, 'Baz'), (3, 'Zaz') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b || ', Correlated', a from upsert_test i WHERE i.a = upsert_test.a) RETURNING *; -- correlated sub-select (EXCLUDED.* alias): -INSERT INTO upsert_test VALUES (1, 'Bat') ON CONFLICT(a) +INSERT INTO upsert_test VALUES (1, 'Bat'), (3, 'Zot') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) RETURNING *; @@ -274,6 +281,29 @@ DROP FOREIGN TABLE update_test; DROP FOREIGN TABLE upsert_test; */ /*Skip, sqlite fdw does not support create partition table +-- Test ON CONFLICT DO UPDATE with partitioned table and non-identical children + +CREATE TABLE upsert_test ( + a INT PRIMARY KEY, + b TEXT +) PARTITION BY LIST (a); + +CREATE TABLE upsert_test_1 PARTITION OF upsert_test FOR VALUES IN (1); +CREATE TABLE upsert_test_2 (b TEXT, a INT PRIMARY KEY); +ALTER TABLE upsert_test ATTACH PARTITION upsert_test_2 FOR VALUES IN (2); + +INSERT INTO upsert_test VALUES(1, 'Boo'), (2, 'Zoo'); +-- uncorrelated sub-select: +WITH aaa AS (SELECT 1 AS a, 'Foo' AS b) INSERT INTO upsert_test + VALUES (1, 'Bar') ON CONFLICT(a) + DO UPDATE SET (b, a) = (SELECT b, a FROM aaa) RETURNING *; +-- correlated sub-select: +WITH aaa AS (SELECT 1 AS ctea, ' Foo' AS cteb) INSERT INTO upsert_test + VALUES (1, 'Bar'), (2, 'Baz') ON CONFLICT(a) + DO UPDATE SET (b, a) = (SELECT upsert_test.b||cteb, upsert_test.a FROM aaa) RETURNING *; + +DROP TABLE upsert_test; + --------------------------- -- UPDATE with row movement --------------------------- @@ -645,6 +675,37 @@ UPDATE list_default set a = 'x' WHERE a = 'd'; DROP TABLE list_parted; +-- Test retrieval of system columns with non-consistent partition row types. +-- This is only partially supported, as seen in the results. + +create table utrtest (a int, b text) partition by list (a); +create table utr1 (a int check (a in (1)), q text, b text); +create table utr2 (a int check (a in (2)), b text); +alter table utr1 drop column q; +alter table utrtest attach partition utr1 for values in (1); +alter table utrtest attach partition utr2 for values in (2); + +insert into utrtest values (1, 'foo') + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; +insert into utrtest values (2, 'bar') + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; -- fails +insert into utrtest values (2, 'bar') + returning *, tableoid::regclass; + +update utrtest set b = b || b from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; + +update utrtest set a = 3 - a from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; -- fails + +update utrtest set a = 3 - a from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass; + +delete from utrtest + returning *, tableoid::regclass, xmax = pg_current_xact_id()::xid as xmax_ok; + +drop table utrtest; + -------------- -- Some more update-partition-key test scenarios below. This time use list -- partitions. diff --git a/expected/13.12/extra/uuid.out b/expected/17.0/extra/uuid.out similarity index 99% rename from expected/13.12/extra/uuid.out rename to expected/17.0/extra/uuid.out index 2f16427a..35bf1e87 100644 --- a/expected/13.12/extra/uuid.out +++ b/expected/17.0/extra/uuid.out @@ -77,9 +77,10 @@ INSERT INTO "type_UUID" ("i", "u") VALUES (28, '{b0eebc99-9c0b4ef8-bb6d6bb9-bd38 QUERY PLAN ------------------------------------------------------------------ Insert on public."type_UUID" + Batch Size: 1 -> Result Output: 28, 'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'::uuid -(3 rows) +(4 rows) --Testcase 042: ALTER FOREIGN TABLE "type_UUID" ALTER COLUMN "u" OPTIONS (ADD column_type 'BLOB'); @@ -113,9 +114,10 @@ INSERT INTO "type_UUID" ("i", "u") VALUES (39, 'b0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd QUERY PLAN ------------------------------------------------------------------ Insert on public."type_UUID" + Batch Size: 1 -> Result Output: 39, 'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'::uuid -(3 rows) +(4 rows) --Testcase 056: CREATE FOREIGN TABLE "type_UUID+"( "i" int OPTIONS (key 'true'), "u" uuid, "t" text, "l" smallint) SERVER sqlite_svr OPTIONS (table 'type_UUID+'); diff --git a/expected/16.0/selectfunc.out b/expected/17.0/selectfunc.out similarity index 100% rename from expected/16.0/selectfunc.out rename to expected/17.0/selectfunc.out diff --git a/expected/17.0/sqlite_fdw.out b/expected/17.0/sqlite_fdw.out new file mode 100644 index 00000000..a57333b5 --- /dev/null +++ b/expected/17.0/sqlite_fdw.out @@ -0,0 +1,2117 @@ +--SET log_min_messages TO DEBUG1; +--SET client_min_messages TO DEBUG1; +--Testcase 129: +CREATE EXTENSION sqlite_fdw; +--Testcase 130: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); +--Testcase 131: +CREATE FOREIGN TABLE department(department_id int OPTIONS (key 'true'), department_name text) SERVER sqlite_svr; +--Testcase 132: +CREATE FOREIGN TABLE employee(emp_id int OPTIONS (key 'true'), emp_name text, emp_dept_id int) SERVER sqlite_svr; +--Testcase 133: +CREATE FOREIGN TABLE empdata(emp_id int OPTIONS (key 'true'), emp_dat bytea) SERVER sqlite_svr; +--Testcase 134: +CREATE FOREIGN TABLE numbers(a int OPTIONS (key 'true'), b varchar(255)) SERVER sqlite_svr; +--Testcase 135: +CREATE FOREIGN TABLE multiprimary(a int, b int OPTIONS (key 'true'), c int OPTIONS(key 'true')) SERVER sqlite_svr; +--Testcase 136: +CREATE FOREIGN TABLE noprimary(a int, b text) SERVER sqlite_svr; +--Testcase 137: +CREATE FOREIGN TABLE RO_RW_test(i int OPTIONS (key 'true'), a text, b float, c int) SERVER sqlite_svr; +--Testcase 1: +SELECT * FROM department LIMIT 10; + department_id | department_name +---------------+----------------- +(0 rows) + +--Testcase 2: +SELECT * FROM employee LIMIT 10; + emp_id | emp_name | emp_dept_id +--------+----------+------------- +(0 rows) + +--Testcase 3: +SELECT * FROM empdata LIMIT 10; + emp_id | emp_dat +--------+--------- +(0 rows) + +--Testcase 4: +INSERT INTO department VALUES(generate_series(1,100), 'dept - ' || generate_series(1,100)); +--Testcase 5: +INSERT INTO employee VALUES(generate_series(1,100), 'emp - ' || generate_series(1,100), generate_series(1,100)); +--Testcase 6: +INSERT INTO empdata VALUES(1, decode ('01234567', 'hex')); +--Testcase 7: +INSERT INTO numbers VALUES(1, 'One'); +--Testcase 8: +INSERT INTO numbers VALUES(2, 'Two'); +--Testcase 9: +INSERT INTO numbers VALUES(3, 'Three'); +--Testcase 10: +INSERT INTO numbers VALUES(4, 'Four'); +--Testcase 11: +INSERT INTO numbers VALUES(5, 'Five'); +--Testcase 12: +INSERT INTO numbers VALUES(6, 'Six'); +--Testcase 13: +INSERT INTO numbers VALUES(7, 'Seven'); +--Testcase 14: +INSERT INTO numbers VALUES(8, 'Eight'); +--Testcase 15: +INSERT INTO numbers VALUES(9, 'Nine'); +--Testcase 16: +SELECT count(*) FROM department; + count +------- + 100 +(1 row) + +--Testcase 17: +SELECT count(*) FROM employee; + count +------- + 100 +(1 row) + +--Testcase 18: +SELECT count(*) FROM empdata; + count +------- + 1 +(1 row) + +--Testcase 19: +EXPLAIN (COSTS FALSE) SELECT * FROM department d, employee e WHERE d.department_id = e.emp_dept_id LIMIT 10; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 20: +EXPLAIN (COSTS FALSE) SELECT * FROM department d, employee e WHERE d.department_id IN (SELECT department_id FROM department) LIMIT 10; + QUERY PLAN +-------------- + Foreign Scan +(1 row) + +--Testcase 21: +SELECT * FROM department d, employee e WHERE d.department_id = e.emp_dept_id LIMIT 10; + department_id | department_name | emp_id | emp_name | emp_dept_id +---------------+-----------------+--------+----------+------------- + 1 | dept - 1 | 1 | emp - 1 | 1 + 2 | dept - 2 | 2 | emp - 2 | 2 + 3 | dept - 3 | 3 | emp - 3 | 3 + 4 | dept - 4 | 4 | emp - 4 | 4 + 5 | dept - 5 | 5 | emp - 5 | 5 + 6 | dept - 6 | 6 | emp - 6 | 6 + 7 | dept - 7 | 7 | emp - 7 | 7 + 8 | dept - 8 | 8 | emp - 8 | 8 + 9 | dept - 9 | 9 | emp - 9 | 9 + 10 | dept - 10 | 10 | emp - 10 | 10 +(10 rows) + +--Testcase 22: +SELECT * FROM department d, employee e WHERE d.department_id IN (SELECT department_id FROM department) ORDER BY d.department_id LIMIT 10; + department_id | department_name | emp_id | emp_name | emp_dept_id +---------------+-----------------+--------+----------+------------- + 1 | dept - 1 | 1 | emp - 1 | 1 + 1 | dept - 1 | 2 | emp - 2 | 2 + 1 | dept - 1 | 3 | emp - 3 | 3 + 1 | dept - 1 | 4 | emp - 4 | 4 + 1 | dept - 1 | 5 | emp - 5 | 5 + 1 | dept - 1 | 6 | emp - 6 | 6 + 1 | dept - 1 | 7 | emp - 7 | 7 + 1 | dept - 1 | 8 | emp - 8 | 8 + 1 | dept - 1 | 9 | emp - 9 | 9 + 1 | dept - 1 | 10 | emp - 10 | 10 +(10 rows) + +--Testcase 23: +SELECT * FROM empdata; + emp_id | emp_dat +--------+------------ + 1 | \x01234567 +(1 row) + +--Testcase 24: +DELETE FROM employee WHERE emp_id = 10; +--Testcase 25: +SELECT COUNT(*) FROM department LIMIT 10; + count +------- + 100 +(1 row) + +--Testcase 26: +SELECT COUNT(*) FROM employee WHERE emp_id = 10; + count +------- + 0 +(1 row) + +--Testcase 27: +UPDATE employee SET emp_name = 'UPDATEd emp' WHERE emp_id = 20; +--Testcase 28: +SELECT emp_id, emp_name FROM employee WHERE emp_name like 'UPDATEd emp'; + emp_id | emp_name +--------+------------- + 20 | UPDATEd emp +(1 row) + +--Testcase 29: +UPDATE empdata SET emp_dat = decode ('0123', 'hex'); +--Testcase 30: +SELECT * FROM empdata; + emp_id | emp_dat +--------+--------- + 1 | \x0123 +(1 row) + +--Testcase 31: +SELECT * FROM employee LIMIT 10; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 1 | emp - 1 | 1 + 2 | emp - 2 | 2 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 + 6 | emp - 6 | 6 + 7 | emp - 7 | 7 + 8 | emp - 8 | 8 + 9 | emp - 9 | 9 + 11 | emp - 11 | 11 +(10 rows) + +--Testcase 32: +SELECT * FROM employee WHERE emp_id IN (1); + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 1 | emp - 1 | 1 +(1 row) + +--Testcase 33: +SELECT * FROM employee WHERE emp_id IN (1,3,4,5); + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 1 | emp - 1 | 1 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 +(4 rows) + +--Testcase 34: +SELECT * FROM employee WHERE emp_id IN (10000,1000); + emp_id | emp_name | emp_dept_id +--------+----------+------------- +(0 rows) + +--Testcase 35: +SELECT * FROM employee WHERE emp_id NOT IN (1) LIMIT 5; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 2 | emp - 2 | 2 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 + 6 | emp - 6 | 6 +(5 rows) + +--Testcase 36: +SELECT * FROM employee WHERE emp_id NOT IN (1,3,4,5) LIMIT 5; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 2 | emp - 2 | 2 + 6 | emp - 6 | 6 + 7 | emp - 7 | 7 + 8 | emp - 8 | 8 + 9 | emp - 9 | 9 +(5 rows) + +--Testcase 37: +SELECT * FROM employee WHERE emp_id NOT IN (10000,1000) LIMIT 5; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 1 | emp - 1 | 1 + 2 | emp - 2 | 2 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 +(5 rows) + +--Testcase 38: +SELECT * FROM employee WHERE emp_id NOT IN (SELECT emp_id FROM employee WHERE emp_id IN (1,10)); + emp_id | emp_name | emp_dept_id +--------+-------------+------------- + 2 | emp - 2 | 2 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 + 6 | emp - 6 | 6 + 7 | emp - 7 | 7 + 8 | emp - 8 | 8 + 9 | emp - 9 | 9 + 11 | emp - 11 | 11 + 12 | emp - 12 | 12 + 13 | emp - 13 | 13 + 14 | emp - 14 | 14 + 15 | emp - 15 | 15 + 16 | emp - 16 | 16 + 17 | emp - 17 | 17 + 18 | emp - 18 | 18 + 19 | emp - 19 | 19 + 20 | UPDATEd emp | 20 + 21 | emp - 21 | 21 + 22 | emp - 22 | 22 + 23 | emp - 23 | 23 + 24 | emp - 24 | 24 + 25 | emp - 25 | 25 + 26 | emp - 26 | 26 + 27 | emp - 27 | 27 + 28 | emp - 28 | 28 + 29 | emp - 29 | 29 + 30 | emp - 30 | 30 + 31 | emp - 31 | 31 + 32 | emp - 32 | 32 + 33 | emp - 33 | 33 + 34 | emp - 34 | 34 + 35 | emp - 35 | 35 + 36 | emp - 36 | 36 + 37 | emp - 37 | 37 + 38 | emp - 38 | 38 + 39 | emp - 39 | 39 + 40 | emp - 40 | 40 + 41 | emp - 41 | 41 + 42 | emp - 42 | 42 + 43 | emp - 43 | 43 + 44 | emp - 44 | 44 + 45 | emp - 45 | 45 + 46 | emp - 46 | 46 + 47 | emp - 47 | 47 + 48 | emp - 48 | 48 + 49 | emp - 49 | 49 + 50 | emp - 50 | 50 + 51 | emp - 51 | 51 + 52 | emp - 52 | 52 + 53 | emp - 53 | 53 + 54 | emp - 54 | 54 + 55 | emp - 55 | 55 + 56 | emp - 56 | 56 + 57 | emp - 57 | 57 + 58 | emp - 58 | 58 + 59 | emp - 59 | 59 + 60 | emp - 60 | 60 + 61 | emp - 61 | 61 + 62 | emp - 62 | 62 + 63 | emp - 63 | 63 + 64 | emp - 64 | 64 + 65 | emp - 65 | 65 + 66 | emp - 66 | 66 + 67 | emp - 67 | 67 + 68 | emp - 68 | 68 + 69 | emp - 69 | 69 + 70 | emp - 70 | 70 + 71 | emp - 71 | 71 + 72 | emp - 72 | 72 + 73 | emp - 73 | 73 + 74 | emp - 74 | 74 + 75 | emp - 75 | 75 + 76 | emp - 76 | 76 + 77 | emp - 77 | 77 + 78 | emp - 78 | 78 + 79 | emp - 79 | 79 + 80 | emp - 80 | 80 + 81 | emp - 81 | 81 + 82 | emp - 82 | 82 + 83 | emp - 83 | 83 + 84 | emp - 84 | 84 + 85 | emp - 85 | 85 + 86 | emp - 86 | 86 + 87 | emp - 87 | 87 + 88 | emp - 88 | 88 + 89 | emp - 89 | 89 + 90 | emp - 90 | 90 + 91 | emp - 91 | 91 + 92 | emp - 92 | 92 + 93 | emp - 93 | 93 + 94 | emp - 94 | 94 + 95 | emp - 95 | 95 + 96 | emp - 96 | 96 + 97 | emp - 97 | 97 + 98 | emp - 98 | 98 + 99 | emp - 99 | 99 + 100 | emp - 100 | 100 +(98 rows) + +--Testcase 39: +SELECT * FROM employee WHERE emp_name NOT IN ('emp - 1', 'emp - 2') LIMIT 5; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 + 6 | emp - 6 | 6 + 7 | emp - 7 | 7 +(5 rows) + +--Testcase 40: +SELECT * FROM employee WHERE emp_name NOT IN ('emp - 10') LIMIT 5; + emp_id | emp_name | emp_dept_id +--------+----------+------------- + 1 | emp - 1 | 1 + 2 | emp - 2 | 2 + 3 | emp - 3 | 3 + 4 | emp - 4 | 4 + 5 | emp - 5 | 5 +(5 rows) + +--Testcase 41: +SELECT * FROM numbers WHERE (CASE WHEN a % 2 = 0 THEN 1 WHEN a % 5 = 0 THEN 1 ELSE 0 END) = 1; + a | b +---+------- + 2 | Two + 4 | Four + 5 | Five + 6 | Six + 8 | Eight +(5 rows) + +--Testcase 42: +SELECT * FROM numbers WHERE (CASE b WHEN 'Two' THEN 1 WHEN 'Six' THEN 1 ELSE 0 END) = 1; + a | b +---+----- + 2 | Two + 6 | Six +(2 rows) + +--Testcase 152: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE (round(abs(a)) = 1); + QUERY PLAN +----------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((round(abs(`a`)) = 1)) +(3 rows) + +--Testcase 153: +SELECT * FROM numbers WHERE (round(abs(a)) = 1); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 137: +create or replace function test_param_WHERE() returns void as $$ +DECLARE + n varchar; +BEGIN + FOR x IN 1..9 LOOP +--Testcase 138: + SELECT b INTO n from numbers WHERE a=x; + raise notice 'Found number %', n; + end loop; + return; +END +$$ LANGUAGE plpgsql; +--Testcase 43: +SELECT test_param_WHERE(); +NOTICE: Found number One +NOTICE: Found number Two +NOTICE: Found number Three +NOTICE: Found number Four +NOTICE: Found number Five +NOTICE: Found number Six +NOTICE: Found number Seven +NOTICE: Found number Eight +NOTICE: Found number Nine + test_param_where +------------------ + +(1 row) + +--Testcase 44: +SELECT b from numbers WHERE a=1; + b +----- + One +(1 row) + +--Testcase 45: +EXPLAIN(COSTS OFF) SELECT b from numbers WHERE a=1; + QUERY PLAN +------------------------- + Foreign Scan on numbers +(1 row) + +--Testcase 46: +SELECT a FROM numbers WHERE b = (SELECT NULL::text); + a +--- +(0 rows) + +--Testcase 47: +PREPARE stmt1 (int, int) AS + SELECT * FROM numbers WHERE a=$1 or a=$2; +--Testcase 48: +EXECUTE stmt1(1,2); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 49: +EXECUTE stmt1(2,2); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 50: +EXECUTE stmt1(3,2); + a | b +---+------- + 2 | Two + 3 | Three +(2 rows) + +--Testcase 51: +EXECUTE stmt1(4,2); + a | b +---+------ + 2 | Two + 4 | Four +(2 rows) + +-- generic plan +--Testcase 52: +EXECUTE stmt1(5,2); + a | b +---+------ + 2 | Two + 5 | Five +(2 rows) + +--Testcase 53: +EXECUTE stmt1(6,2); + a | b +---+----- + 2 | Two + 6 | Six +(2 rows) + +--Testcase 54: +EXECUTE stmt1(7,2); + a | b +---+------- + 2 | Two + 7 | Seven +(2 rows) + +--Testcase 55: +DELETE FROM employee; +--Testcase 56: +DELETE FROM department; +--Testcase 57: +DELETE FROM empdata; +--Testcase 58: +DELETE FROM numbers; +BEGIN; +--Testcase 59: +INSERT INTO numbers VALUES(1, 'One'); +--Testcase 60: +INSERT INTO numbers VALUES(2, 'Two'); +COMMIT; +--Testcase 61: +SELECT * from numbers; + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +BEGIN; +--Testcase 62: +INSERT INTO numbers VALUES(3, 'Three'); +ROLLBACK; +--Testcase 63: +SELECT * from numbers; + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +BEGIN; +--Testcase 64: +INSERT INTO numbers VALUES(4, 'Four'); +SAVEPOINT my_savepoint; +--Testcase 65: +INSERT INTO numbers VALUES(5, 'Five'); +ROLLBACK TO SAVEPOINT my_savepoint; +--Testcase 66: +INSERT INTO numbers VALUES(6, 'Six'); +COMMIT; +--Testcase 67: +SELECT * from numbers; + a | b +---+------ + 1 | One + 2 | Two + 4 | Four + 6 | Six +(4 rows) + +-- duplicate key +--Testcase 68: +INSERT INTO numbers VALUES(1, 'One'); +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: numbers.b', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."numbers"(`a`, `b`) VALUES (?, ?) +--Testcase 69: +DELETE from numbers; +BEGIN; +--Testcase 70: +INSERT INTO numbers VALUES(1, 'One'); +--Testcase 71: +INSERT INTO numbers VALUES(2, 'Two'); +COMMIT; +-- violate unique constraint +--Testcase 72: +UPDATE numbers SET b='Two' WHERE a = 1; +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: numbers.b', SQLite result code 19 +CONTEXT: SQL query: UPDATE main."numbers" SET `b` = 'Two' WHERE ((`a` = 1)) +--Testcase 73: +SELECT * from numbers; + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +-- push down +--Testcase 74: +explain (verbose, costs off) SELECT * from numbers WHERE a = any(ARRAY[2,3,4,5]::int[]); + QUERY PLAN +--------------------------------------------------------------------------------- + Foreign Scan on public.numbers + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (2, 3, 4, 5)) +(3 rows) + +-- (1,2,3) is pushed down +--Testcase 75: +explain (verbose, costs off) SELECT * from numbers WHERE a in (1,2,3) AND (1,2) < (a,5); + QUERY PLAN +------------------------------------------------------------------------------ + Foreign Scan on public.numbers + Output: a, b + Filter: (ROW(1, 2) < ROW(numbers.a, 5)) + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, 3)) +(4 rows) + +--Testcase 76: +explain (verbose, costs off) SELECT * from numbers WHERE a in (a+2*a,5); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Foreign Scan on public.numbers + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (((`a` = (`a` + (2 * `a`))) OR (`a` = 5))) +(3 rows) + +--Testcase 77: +explain (verbose, costs off) SELECT * from numbers WHERE a = any(ARRAY[1,2,a]::int[]); + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.numbers + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, `a`)) +(3 rows) + +--Testcase 78: +SELECT * from numbers WHERE a = any(ARRAY[2,3,4,5]::int[]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 79: +SELECT * from numbers WHERE a = any(ARRAY[1,2,a]::int[]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +-- ANY with ARRAY expression +--Testcase 154: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY(ARRAY[1, a + 1]); + QUERY PLAN +----------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, (`a` + 1))) +(3 rows) + +--Testcase 155: +SELECT * FROM numbers WHERE a = ANY(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 156: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, a + 1]); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <> 1) OR (`a` <> (`a` + 1))) +(3 rows) + +--Testcase 157: +SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 158: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, a + 1]); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` >= 1) OR (`a` >= (`a` + 1))) +(3 rows) + +--Testcase 159: +SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 160: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, a + 1]); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <= 1) OR (`a` <= (`a` + 1))) +(3 rows) + +--Testcase 161: +SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 162: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ANY(ARRAY[1, a + 1]); + QUERY PLAN +-------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` > 1) OR (`a` > (`a` + 1))) +(3 rows) + +--Testcase 163: +SELECT * FROM numbers WHERE a > ANY(ARRAY[1, a + 1]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 164: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ANY(ARRAY[1, a + 1]); + QUERY PLAN +-------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` < 1) OR (`a` < (`a` + 1))) +(3 rows) + +--Testcase 165: +SELECT * FROM numbers WHERE a < ANY(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +-- ANY with ARRAY const +--Testcase 166: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY(ARRAY[1, 2]); + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2)) +(3 rows) + +--Testcase 167: +SELECT * FROM numbers WHERE a = ANY(ARRAY[1, 2]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 168: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, 2]); + QUERY PLAN +---------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <> 1 OR `a` <> 2) +(3 rows) + +--Testcase 169: +SELECT * FROM numbers WHERE a <> ANY(ARRAY[1, 2]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 170: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, 2]); + QUERY PLAN +---------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` >= 1 OR `a` >= 2) +(3 rows) + +--Testcase 171: +SELECT * FROM numbers WHERE a >= ANY(ARRAY[1, 2]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 172: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, 2]); + QUERY PLAN +---------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <= 1 OR `a` <= 2) +(3 rows) + +--Testcase 173: +SELECT * FROM numbers WHERE a <= ANY(ARRAY[1, 2]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 174: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ANY(ARRAY[1, 2]); + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` > 1 OR `a` > 2) +(3 rows) + +--Testcase 175: +SELECT * FROM numbers WHERE a > ANY(ARRAY[1, 2]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 176: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ANY(ARRAY[1, 2]); + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` < 1 OR `a` < 2) +(3 rows) + +--Testcase 177: +SELECT * FROM numbers WHERE a < ANY(ARRAY[1, 2]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 210: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ANY('{1, 2, 3}'); + QUERY PLAN +------------------------------------------------------------------------------ + Foreign Scan on public.numbers (cost=10.00..3.00 rows=3 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` IN (1, 2, 3)) +(3 rows) + +--Testcase 211: +SELECT * FROM numbers WHERE a = ANY('{1, 2, 3}'); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 212: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ANY('{1, 2, 3}'); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..150.00 rows=150 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <> 1 OR `a` <> 2 OR `a` <> 3) +(3 rows) + +--Testcase 213: +SELECT * FROM numbers WHERE a <> ANY('{1, 2, 3}'); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +-- ALL with ARRAY expression +--Testcase 178: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ALL(ARRAY[1, a * 1]); + QUERY PLAN +--------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` = 1) AND (`a` = (`a` * 1))) +(3 rows) + +--Testcase 179: +SELECT * FROM numbers WHERE a = ALL(ARRAY[1, a * 1]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 180: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, a + 1]); + QUERY PLAN +--------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` NOT IN (1, (`a` + 1))) +(3 rows) + +--Testcase 181: +SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, a + 1]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 182: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, a / 1]); + QUERY PLAN +----------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` >= 1) AND (`a` >= (`a` / 1))) +(3 rows) + +--Testcase 183: +SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, a / 1]); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 184: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, a + 1]); + QUERY PLAN +----------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` <= 1) AND (`a` <= (`a` + 1))) +(3 rows) + +--Testcase 185: +SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, a + 1]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 186: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ALL(ARRAY[1, a - 1]); + QUERY PLAN +--------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` > 1) AND (`a` > (`a` - 1))) +(3 rows) + +--Testcase 187: +SELECT * FROM numbers WHERE a > ALL(ARRAY[1, a - 1]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 188: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ALL(ARRAY[2, a + 1]); + QUERY PLAN +--------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((`a` < 2) AND (`a` < (`a` + 1))) +(3 rows) + +--Testcase 189: +SELECT * FROM numbers WHERE a < ALL(ARRAY[2, a + 1]); + a | b +---+----- + 1 | One +(1 row) + +-- ALL with ARRAY const +--Testcase 190: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a = ALL(ARRAY[1, 1]); + QUERY PLAN +--------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..1.00 rows=1 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` = 1 AND `a` = 1) +(3 rows) + +--Testcase 191: +SELECT * FROM numbers WHERE a = ALL(ARRAY[1, 1]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 192: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, 3]); + QUERY PLAN +------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` NOT IN (1, 3)) +(3 rows) + +--Testcase 193: +SELECT * FROM numbers WHERE a <> ALL(ARRAY[1, 3]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 194: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, 2]); + QUERY PLAN +----------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` >= 1 AND `a` >= 2) +(3 rows) + +--Testcase 195: +SELECT * FROM numbers WHERE a >= ALL(ARRAY[1, 2]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 196: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, 2]); + QUERY PLAN +----------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` <= 1 AND `a` <= 2) +(3 rows) + +--Testcase 197: +SELECT * FROM numbers WHERE a <= ALL(ARRAY[1, 2]); + a | b +---+----- + 1 | One +(1 row) + +--Testcase 198: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a > ALL(ARRAY[0, 1]); + QUERY PLAN +--------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` > 0 AND `a` > 1) +(3 rows) + +--Testcase 199: +SELECT * FROM numbers WHERE a > ALL(ARRAY[0, 1]); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 200: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE a < ALL(ARRAY[2, 3]); + QUERY PLAN +--------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`a` < 2 AND `a` < 3) +(3 rows) + +--Testcase 201: +SELECT * FROM numbers WHERE a < ALL(ARRAY[2, 3]); + a | b +---+----- + 1 | One +(1 row) + +-- ANY/ALL with TEXT ARRAY const +--Testcase 202: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE b = ANY(ARRAY['One', 'Two']); + QUERY PLAN +----------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..2.00 rows=2 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` IN ('One', 'Two')) +(3 rows) + +--Testcase 203: +SELECT * FROM numbers WHERE b = ANY(ARRAY['One', 'Two']); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 204: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE b <> ALL(ARRAY['One', 'Four']); + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..148.00 rows=148 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` NOT IN ('One', 'Four')) +(3 rows) + +--Testcase 205: +SELECT * FROM numbers WHERE b <> ALL(ARRAY['One', 'Four']); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 206: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE b > ANY(ARRAY['One', 'Two']); + QUERY PLAN +---------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..83.00 rows=83 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` > 'One' OR `b` > 'Two') +(3 rows) + +--Testcase 207: +SELECT * FROM numbers WHERE b > ANY(ARRAY['One', 'Two']); + a | b +---+----- + 2 | Two +(1 row) + +--Testcase 208: +EXPLAIN VERBOSE SELECT * FROM numbers WHERE b > ALL(ARRAY['Four', 'Five']); + QUERY PLAN +------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers (cost=10.00..17.00 rows=17 width=520) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE (`b` > 'Four' AND `b` > 'Five') +(3 rows) + +--Testcase 209: +SELECT * FROM numbers WHERE b > ALL(ARRAY['Four', 'Five']); + a | b +---+----- + 1 | One + 2 | Two +(2 rows) + +--Testcase 80: +INSERT INTO multiprimary VALUES(1,2,3); +--Testcase 81: +INSERT INTO multiprimary VALUES(1,2,4); +--Testcase 82: +UPDATE multiprimary SET b = 10 WHERE c = 3; +--Testcase 83: +SELECT * from multiprimary; + a | b | c +---+----+--- + 1 | 10 | 3 + 1 | 2 | 4 +(2 rows) + +--Testcase 84: +UPDATE multiprimary SET a = 10 WHERE a = 1; +--Testcase 85: +SELECT * from multiprimary; + a | b | c +----+----+--- + 10 | 10 | 3 + 10 | 2 | 4 +(2 rows) + +--Testcase 86: +UPDATE multiprimary SET a = 100, b=200, c=300 WHERE a=10 AND b=10; +--Testcase 87: +SELECT * from multiprimary; + a | b | c +-----+-----+----- + 100 | 200 | 300 + 10 | 2 | 4 +(2 rows) + +--Testcase 88: +UPDATE multiprimary SET a = 1234; +--Testcase 89: +SELECT * from multiprimary; + a | b | c +------+-----+----- + 1234 | 200 | 300 + 1234 | 2 | 4 +(2 rows) + +--Testcase 90: +UPDATE multiprimary SET a = a+1, b=b+1 WHERE b=200 AND c=300; +--Testcase 91: +SELECT * from multiprimary; + a | b | c +------+-----+----- + 1235 | 201 | 300 + 1234 | 2 | 4 +(2 rows) + +--Testcase 92: +DELETE from multiprimary WHERE a = 1235; +--Testcase 93: +SELECT * from multiprimary; + a | b | c +------+---+--- + 1234 | 2 | 4 +(1 row) + +--Testcase 94: +DELETE from multiprimary WHERE b = 2; +--Testcase 95: +SELECT * from multiprimary; + a | b | c +---+---+--- +(0 rows) + +--Testcase 96: +INSERT INTO multiprimary VALUES(1,2,3); +--Testcase 97: +INSERT INTO multiprimary VALUES(1,2,4); +--Testcase 98: +INSERT INTO multiprimary VALUES(1,10,20); +--Testcase 99: +INSERT INTO multiprimary VALUES(2,20,40); +--Testcase 100: +SELECT count(distinct a) from multiprimary; + count +------- + 2 +(1 row) + +--Testcase 101: +SELECT sum(b),max(b), min(b) from multiprimary; + sum | max | min +-----+-----+----- + 34 | 20 | 2 +(1 row) + +--Testcase 102: +SELECT sum(b+5)+2 from multiprimary group by b/2 order by b/2; + ?column? +---------- + 16 + 17 + 27 +(3 rows) + +--Testcase 103: +SELECT sum(a) from multiprimary group by b having sum(a) > 0 order by sum(a); + sum +----- + 1 + 2 + 2 +(3 rows) + +--Testcase 104: +SELECT sum(a) A from multiprimary group by b having avg(abs(a)) > 0 AND sum(a) > 0 order by A; + a +--- + 1 + 2 + 2 +(3 rows) + +--Testcase 105: +SELECT count(nullif(a, 1)) FROM multiprimary; + count +------- + 1 +(1 row) + +--Testcase 106: +SELECT a,a FROM multiprimary group by 1,2; + a | a +---+--- + 1 | 1 + 2 | 2 +(2 rows) + +--Testcase 107: +SELECT * from multiprimary, numbers WHERE multiprimary.a=numbers.a; + a | b | c | a | b +---+----+----+---+----- + 1 | 2 | 3 | 1 | One + 1 | 2 | 4 | 1 | One + 1 | 10 | 20 | 1 | One + 2 | 20 | 40 | 2 | Two +(4 rows) + +--Testcase 108: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(a) FROM multiprimary HAVING sum(a) > 0; + QUERY PLAN +----------------------------------------------------------- + Aggregate + Output: sum(a) + Filter: (sum(multiprimary.a) > 0) + -> Foreign Scan on public.multiprimary + Output: a, b, c + SQLite query: SELECT `a` FROM main."multiprimary" +(6 rows) + +--Testcase 109: +SELECT sum(a) FROM multiprimary HAVING sum(a) > 0; + sum +----- + 5 +(1 row) + +--Testcase 110: +INSERT INTO numbers VALUES(4, 'Four'); +-- All where clauses are pushed down +--Testcase 111: +SELECT * FROM numbers WHERE abs(a) = 4 AND upper(b) = 'FOUR' AND lower(b) = 'four'; + a | b +---+------ + 4 | Four +(1 row) + +--Testcase 112: +EXPLAIN (verbose, costs off) SELECT b, length(b) FROM numbers WHERE abs(a) = 4 AND upper(b) = 'FOUR' AND lower(b) = 'four'; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers + Output: b, length((b)::text) + Filter: ((upper((numbers.b)::text) = 'FOUR'::text) AND (lower((numbers.b)::text) = 'four'::text)) + SQLite query: SELECT `b` FROM main."numbers" WHERE ((abs(`a`) = 4)) +(4 rows) + +-- Only "length(b) = 4" are pushed down +--Testcase 113: +SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND length(reverse(b)) = 4; + b | length +------+-------- + Four | 4 +(1 row) + +--Testcase 114: +EXPLAIN (verbose, costs off) SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND length(reverse(b)) = 4; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.numbers + Output: b, length((b)::text) + Filter: ((power('1'::double precision, (numbers.a)::double precision) <> '0'::double precision) AND (length(reverse((numbers.b)::text)) = 4)) + SQLite query: SELECT `a`, `b` FROM main."numbers" WHERE ((length(`b`) = 4)) +(4 rows) + +--Testcase 115: +INSERT INTO multiprimary (b,c) VALUES (99, 100); +--Testcase 116: +SELECT c FROM multiprimary WHERE COALESCE(a,b,c) = 99; + c +----- + 100 +(1 row) + +--Testcase 139: +CREATE FOREIGN TABLE multiprimary2(a int, b int, c int OPTIONS(column_name 'b')) SERVER sqlite_svr OPTIONS (table 'multiprimary'); +--Testcase 117: +SELECT * FROM multiprimary2; + a | b | c +---+----+---- + 1 | 2 | 2 + 1 | 2 | 2 + 1 | 10 | 10 + 2 | 20 | 20 + | 99 | 99 +(5 rows) + +--Testcase 214: +ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN a OPTIONS(ADD column_name 'b'); +--Testcase 118: +SELECT * FROM multiprimary2; + a | b | c +----+----+---- + 2 | 2 | 2 + 2 | 2 | 2 + 10 | 10 | 10 + 20 | 20 | 20 + 99 | 99 | 99 +(5 rows) + +--Testcase 215: +ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN b OPTIONS (column_name 'nosuch column'); +--Testcase 119: +SELECT * FROM multiprimary2; +ERROR: SQL error during prepare: no such column: nosuch column SELECT `b`, `nosuch column`, `b` FROM main."multiprimary" +--Testcase 140: +EXPLAIN (VERBOSE) SELECT * FROM multiprimary2; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public.multiprimary2 (cost=10.00..2275.00 rows=2275 width=12) + Output: a, b, c + SQLite query: SELECT `b`, `nosuch column`, `b` FROM main."multiprimary" +(3 rows) + +--Testcase 120: +SELECT a FROM multiprimary2 WHERE b = 1; +ERROR: SQL error during prepare: no such column: nosuch column SELECT `b` FROM main."multiprimary" WHERE ((`nosuch column` = 1)) +--Testcase 141: +CREATE FOREIGN TABLE columntest(a int OPTIONS(column_name 'a a', key 'true'), "b b" int OPTIONS(key 'true'), c int OPTIONS(column_name 'c c')) SERVER sqlite_svr; +--Testcase 121: +INSERT INTO columntest VALUES(1,2,3); +--Testcase 122: +UPDATE columntest SET c=10 WHERE a = 1; +--Testcase 123: +SELECT * FROM columntest; + a | b b | c +---+-----+---- + 1 | 2 | 10 +(1 row) + +--Testcase 124: +UPDATE columntest SET a=100 WHERE c = 10; +--Testcase 125: +SELECT * FROM columntest; + a | b b | c +-----+-----+---- + 100 | 2 | 10 +(1 row) + +--Testcase 126: +INSERT INTO noprimary VALUES(1,'2'); +--Testcase 127: +INSERT INTO noprimary SELECT * FROM noprimary; +--Testcase 128: +SELECT * FROM noprimary; + a | b +---+--- + 1 | 2 + 1 | 2 +(2 rows) + +--get version +--Testcase 153: +\df sqlite* + List of functions + Schema | Name | Result data type | Argument data types | Type +--------+----------------------------+------------------+-----------------------------------------+------ + public | sqlite_fdw_disconnect | boolean | text | func + public | sqlite_fdw_disconnect_all | boolean | | func + public | sqlite_fdw_get_connections | SETOF record | OUT server_name text, OUT valid boolean | func + public | sqlite_fdw_handler | fdw_handler | | func + public | sqlite_fdw_validator | void | text[], oid | func + public | sqlite_fdw_version | integer | | func +(6 rows) + +--Testcase 154: +SELECT * FROM public.sqlite_fdw_version(); + sqlite_fdw_version +-------------------- + 20500 +(1 row) + +--Testcase 155: +SELECT sqlite_fdw_version(); + sqlite_fdw_version +-------------------- + 20500 +(1 row) + +-- issue #44 github +--Testcase 156: +CREATE FOREIGN TABLE fts_table (name text, description text) SERVER sqlite_svr; +--Testcase 157: +INSERT INTO fts_table VALUES ('this is name', 'this is description'); +--Testcase 158: +SELECT * FROM fts_table; -- should work + name | description +--------------+--------------------- + this is name | this is description +(1 row) + +--Testcase 159: +ALTER TABLE fts_table ALTER COLUMN name TYPE int; +--Testcase 160: +SELECT * FROM fts_table; -- should fail +ERROR: SQLite value is not compatible with PostgreSQL column data type +HINT: SQLite value with "text" affinity (12 bytes) : 'this is name' +CONTEXT: foreign table "fts_table" foreign column "name" have data type "integer" (usual affinity "integer"), in query there is whole-row reference to foreign table +-- issue #62 github +--Testcase 236: +INSERT INTO noprimary VALUES (4, 'Test''s'); +--Testcase 237: +INSERT INTO noprimary VALUES (5, 'Test'); +--Testcase 238: +SELECT * FROM noprimary; + a | b +---+-------- + 1 | 2 + 1 | 2 + 4 | Test's + 5 | Test +(4 rows) + +--Testcase 239: +EXPLAIN VERBOSE +SELECT * FROM noprimary where b = 'Test''s'; + QUERY PLAN +--------------------------------------------------------------------------------- + Foreign Scan on public.noprimary (cost=10.00..7.00 rows=7 width=36) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."noprimary" WHERE ((`b` = 'Test''s')) +(3 rows) + +--Testcase 240: +SELECT * FROM noprimary where b = 'Test''s'; + a | b +---+-------- + 4 | Test's +(1 row) + +--Testcase 241: +EXPLAIN VERBOSE +SELECT * FROM noprimary where b in ('Test''s', 'Test'); + QUERY PLAN +------------------------------------------------------------------------------------------ + Foreign Scan on public.noprimary (cost=10.00..14.00 rows=14 width=36) + Output: a, b + SQLite query: SELECT `a`, `b` FROM main."noprimary" WHERE (`b` IN ('Test''s', 'Test')) +(3 rows) + +--Testcase 242: +SELECT * FROM noprimary where b in ('Test''s', 'Test'); + a | b +---+-------- + 4 | Test's + 5 | Test +(2 rows) + +-- INSERT/UPDATE whole row with generated column +--Testcase 216: +CREATE FOREIGN TABLE grem1_1 ( + a int generated always as (0) stored) + SERVER sqlite_svr OPTIONS(table 'grem1_1'); +--Testcase 217: +INSERT INTO grem1_1 DEFAULT VALUES; +--Testcase 218: +SELECT * FROM grem1_1; + a +--- + +(1 row) + +--Testcase 219: +CREATE FOREIGN TABLE grem1_2 ( + a int generated always as (0) stored, + b int generated always as (1) stored, + c int generated always as (2) stored, + d int generated always as (3) stored) + SERVER sqlite_svr OPTIONS(table 'grem1_2'); +--Testcase 220: +INSERT INTO grem1_2 DEFAULT VALUES; +--Testcase 221: +SELECT * FROM grem1_2; + a | b | c | d +---+---+---+--- + | | | +(1 row) + +-- Executable test case for pushdown CASE expressions (results) +--Testcase 224: +CREATE FOREIGN TABLE case_exp(c1 int OPTIONS (key 'true'), c3 text, c6 varchar(10)) SERVER sqlite_svr; +--Testcase 225: +INSERT INTO case_exp + SELECT id, + to_char(id, 'FM00000'), + id % 10 + FROM generate_series(1, 10) id; +--Testcase 226: +SELECT * FROM case_exp; + c1 | c3 | c6 +----+-------+---- + 1 | 00001 | 1 + 2 | 00002 | 2 + 3 | 00003 | 3 + 4 | 00004 | 4 + 5 | 00005 | 5 + 6 | 00006 | 6 + 7 | 00007 | 7 + 8 | 00008 | 8 + 9 | 00009 | 9 + 10 | 00010 | 0 +(10 rows) + +-- CASE arg WHEN +--Testcase 227: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM case_exp WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.case_exp + Output: c1, c3, c6 + SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE ((`c1` > CASE mod(`c1`, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)) +(3 rows) + +--Testcase 228: +SELECT * FROM case_exp WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + c1 | c3 | c6 +----+-------+---- + 4 | 00004 | 4 + 8 | 00008 | 8 +(2 rows) + +-- these are shippable +--Testcase 229: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM case_exp WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.case_exp + Output: c1, c3, c6 + SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE (CASE `c6` WHEN 'foo' THEN 1 ELSE (`c3` < 'bar') END) +(3 rows) + +--Testcase 230: +SELECT * FROM case_exp WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; + c1 | c3 | c6 +----+-------+---- + 1 | 00001 | 1 + 2 | 00002 | 2 + 3 | 00003 | 3 + 4 | 00004 | 4 + 5 | 00005 | 5 + 6 | 00006 | 6 + 7 | 00007 | 7 + 8 | 00008 | 8 + 9 | 00009 | 9 + 10 | 00010 | 0 +(10 rows) + +--Testcase 231: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM case_exp WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Foreign Scan on public.case_exp + Output: c1, c3, c6 + SQLite query: SELECT `c1`, `c3`, `c6` FROM main."case_exp" WHERE (CASE `c3` WHEN `c6` THEN 1 ELSE (`c3` < 'bar') END) +(3 rows) + +--Testcase 232: +SELECT * FROM case_exp WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; + c1 | c3 | c6 +----+-------+---- + 1 | 00001 | 1 + 2 | 00002 | 2 + 3 | 00003 | 3 + 4 | 00004 | 4 + 5 | 00005 | 5 + 6 | 00006 | 6 + 7 | 00007 | 7 + 8 | 00008 | 8 + 9 | 00009 | 9 + 10 | 00010 | 0 +(10 rows) + +-- but this is not because of collation +--Testcase 233: +SELECT * FROM case_exp WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END; + c1 | c3 | c6 +----+-------+---- + 1 | 00001 | 1 + 2 | 00002 | 2 + 3 | 00003 | 3 + 4 | 00004 | 4 + 5 | 00005 | 5 + 6 | 00006 | 6 + 7 | 00007 | 7 + 8 | 00008 | 8 + 9 | 00009 | 9 + 10 | 00010 | 0 +(10 rows) + +--Testcase 234: +DELETE FROM case_exp; +-- readonly/readwrite tests +-- Full combinations +-- force_RO default SERVER default TABLE default +-- force_RO default SERVER true TABLE default +-- force_RO default SERVER false TABLE default +-- force_RO default SERVER default TABLE true +-- force_RO default SERVER default TABLE false +-- force_RO default SERVER true TABLE true +-- force_RO default SERVER false TABLE true +-- force_RO default SERVER false TABLE false +-- force_RO default SERVER true TABLE false +-- force_RO false SERVER default TABLE default +-- force_RO false SERVER true TABLE default +-- force_RO false SERVER false TABLE default +-- force_RO false SERVER default TABLE true +-- force_RO false SERVER default TABLE false +-- force_RO false SERVER true TABLE true +-- force_RO false SERVER false TABLE true +-- force_RO false SERVER false TABLE false +-- force_RO false SERVER true TABLE false +-- force_RO true SERVER default TABLE default +-- force_RO true SERVER true TABLE default +-- force_RO true SERVER false TABLE default +-- force_RO true SERVER default TABLE true +-- force_RO true SERVER default TABLE false +-- force_RO true SERVER true TABLE true +-- force_RO true SERVER false TABLE true +-- force_RO true SERVER false TABLE false +-- force_RO true SERVER true TABLE false +-- force_RO default SERVER default TABLE default +--Testcase 235: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- OK +--Testcase 236: +UPDATE RO_RW_test SET a='C' WHERE i=2; -- OK +--Testcase 237: +DELETE FROM RO_RW_test WHERE i=2; -- OK +-- force_RO default SERVER true TABLE default +--Testcase 238: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); +--Testcase 239: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- OK +--Testcase 240: +UPDATE RO_RW_test SET a='E' WHERE i=3; -- OK +--Testcase 241: +DELETE FROM RO_RW_test WHERE i=3; -- OK +--Testcase 242: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- OK +-- force_RO default SERVER false TABLE default +--Testcase 243: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 244: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 245: +UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 246: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO default SERVER default TABLE true +--Testcase 247: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 248: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); +--Testcase 249: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- OK +--Testcase 250: +UPDATE RO_RW_test SET a='J' WHERE i=6; -- OK +--Testcase 251: +DELETE FROM RO_RW_test WHERE i=6; -- OK +-- force_RO default SERVER default TABLE false +--Testcase 252: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 253: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 254: +UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 255: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO default SERVER true TABLE true +--Testcase 256: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); +--Testcase 257: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); +--Testcase 258: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- OK +--Testcase 258: +UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK +--Testcase 260: +DELETE FROM RO_RW_test WHERE i=8; -- OK +--Testcase 261: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- OK +-- force_RO default SERVER false TABLE true +--Testcase 262: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 263: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- OK +--Testcase 264: +UPDATE RO_RW_test SET a='Q' WHERE i=9; -- OK +--Testcase 265: +DELETE FROM RO_RW_test WHERE i=9; -- OK +-- force_RO default SERVER false TABLE false +--Testcase 266: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 267: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 268: +UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 269: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO default SERVER true TABLE false +--Testcase 270: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); +--Testcase 271: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 272: +UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 273: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +--Testcase 274: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 275: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); +--Testcase 276: +SELECT * FROM RO_RW_test ORDER BY i; + i | a | b | c +----+---+-------+--- + 1 | A | 1.001 | 0 + 4 | F | 0.005 | 5 + 10 | P | 4.15 | 1 +(3 rows) + +--Bind error message test for some unsupported data type +--Testcase 277: +ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE tsquery; +--Testcase 278: +INSERT INTO numbers VALUES(8,'fat & (rat | cat)'); +ERROR: cannot convert constant value to Sqlite value +HINT: Constant value data type: "tsquery" in column "b" +--Testcase 279: +ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE varchar(255); +--Testcase 277: +DELETE FROM RO_RW_test; +--Testcase 278: +ALTER SERVER sqlite_svr OPTIONS (ADD force_readonly 'false'); +-- force_RO false SERVER default TABLE default +--Testcase 279: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- OK +--Testcase 280: +UPDATE RO_RW_test SET a='C' WHERE i=2; -- OK +--Testcase 281: +DELETE FROM RO_RW_test WHERE i=2; -- OK +-- force_RO false SERVER true TABLE default +--Testcase 282: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); +--Testcase 283: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- OK +--Testcase 284: +UPDATE RO_RW_test SET a='E' WHERE i=3; -- OK +--Testcase 285: +DELETE FROM RO_RW_test WHERE i=3; -- OK +--Testcase 286: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- OK +-- force_RO false SERVER false TABLE default +--Testcase 287: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 288: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 289: +UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 290: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO false SERVER default TABLE true +--Testcase 291: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 292: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); +--Testcase 293: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- OK +--Testcase 294: +UPDATE RO_RW_test SET a='J' WHERE i=6; -- OK +--Testcase 295: +DELETE FROM RO_RW_test WHERE i=6; -- OK +-- force_RO false SERVER default TABLE false +--Testcase 296: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 297: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 298: +UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 299: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO false SERVER true TABLE true +--Testcase 300: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); +--Testcase 301: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); +--Testcase 302: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- OK +--Testcase 303: +UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK +--Testcase 304: +DELETE FROM RO_RW_test WHERE i=8; -- OK +--Testcase 305: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- OK +-- force_RO false SERVER false TABLE true +--Testcase 306: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 307: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- OK +--Testcase 308: +UPDATE RO_RW_test SET a='Q' WHERE i=9; -- OK +--Testcase 309: +DELETE FROM RO_RW_test WHERE i=9; -- OK +-- force_RO false SERVER false TABLE false +--Testcase 310: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 311: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 312: +UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 313: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO false SERVER true TABLE false +--Testcase 314: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); +--Testcase 315: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 316: +UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 317: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +--Testcase 318: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 319: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); +--Testcase 320: +SELECT * FROM RO_RW_test ORDER BY i; + i | a | b | c +----+---+-------+--- + 4 | F | 0.005 | 5 + 10 | P | 4.15 | 1 +(2 rows) + +--Testcase 321: +DELETE FROM RO_RW_test; +--Testcase 322: +ALTER SERVER sqlite_svr OPTIONS (SET force_readonly 'true'); +-- force_RO true SERVER default TABLE default +--Testcase 323: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (2, 'B', 3.01, 1); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 324: +UPDATE RO_RW_test SET a='C' WHERE i=2; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 325: +DELETE FROM RO_RW_test WHERE i=2; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER true TABLE default +--Testcase 326: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); +--Testcase 327: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (3, 'D', 5.02, 8); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 328: +UPDATE RO_RW_test SET a='E' WHERE i=3; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 329: +DELETE FROM RO_RW_test WHERE i=3; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +--Testcase 330: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (4, 'F', 0.005, 5); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +-- force_RO true SERVER false TABLE default +--Testcase 331: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 332: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (5, 'H', 0.03, 7); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 333: +UPDATE RO_RW_test SET a='E' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 334: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER default TABLE true +--Testcase 335: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 336: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (ADD updatable 'true'); +--Testcase 337: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (6, 'I', 1.403, 2); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 338: +UPDATE RO_RW_test SET a='J' WHERE i=6; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 339: +DELETE FROM RO_RW_test WHERE i=6; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER default TABLE false +--Testcase 340: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 341: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (7, 'K', 2.01, 4); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 342: +UPDATE RO_RW_test SET a='L' WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 343: +DELETE FROM RO_RW_test WHERE i=4; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER true TABLE true +--Testcase 344: +ALTER SERVER sqlite_svr OPTIONS (ADD updatable 'true'); -- ERR +--Testcase 345: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'true'); -- ERR +--Testcase 346: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (8, 'M', 5.02, 8); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 347: +UPDATE RO_RW_test SET a='N' WHERE i=8; -- OK +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 348: +DELETE FROM RO_RW_test WHERE i=8; -- OK +ERROR: foreign table "ro_rw_test" does not allow deletes +--Testcase 349: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (9, 'O', 3.21, 9); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +-- force_RO true SERVER false TABLE true +--Testcase 350: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'false'); +--Testcase 351: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (10, 'P', 4.15, 1); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 352: +UPDATE RO_RW_test SET a='Q' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 353: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER false TABLE false +--Testcase 354: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (SET updatable 'false'); +--Testcase 355: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (11, 'Q', 2.27, 5); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 356: +UPDATE RO_RW_test SET a='S' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 357: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +-- force_RO true SERVER true TABLE false +--Testcase 358: +ALTER SERVER sqlite_svr OPTIONS (SET updatable 'true'); +--Testcase 359: +INSERT INTO RO_RW_test (i, a, b, c) VALUES (12, 'R', 6.18, 11); -- ERR +ERROR: foreign table "ro_rw_test" does not allow inserts +--Testcase 360: +UPDATE RO_RW_test SET a='T' WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow updates +--Testcase 361: +DELETE FROM RO_RW_test WHERE i=9; -- ERR +ERROR: foreign table "ro_rw_test" does not allow deletes +--Testcase 362: +ALTER SERVER sqlite_svr OPTIONS (DROP updatable); +--Testcase 363: +ALTER FOREIGN TABLE RO_RW_test OPTIONS (DROP updatable); +--Testcase 364: +ALTER SERVER sqlite_svr OPTIONS (DROP force_readonly); +--Testcase 365: +SELECT * FROM RO_RW_test ORDER BY i; + i | a | b | c +---+---+---+--- +(0 rows) + +--Testcase 366: +DROP FOREIGN TABLE RO_RW_test; +-- End of RO/RW test +--Bind error message test for some unsupported data type +--Testcase 366: +ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE tsquery; +--Testcase 367: +INSERT INTO numbers VALUES(8,'fat & (rat | cat)'); +ERROR: cannot convert constant value to Sqlite value +HINT: Constant value data type: "tsquery" in column "b" +--Testcase 368: +ALTER FOREIGN TABLE numbers ALTER COLUMN b TYPE varchar(255); +--Testcase 142: +DROP FUNCTION test_param_WHERE(); +--Testcase 143: +DROP FOREIGN TABLE numbers; +--Testcase 144: +DROP FOREIGN TABLE department; +--Testcase 145: +DROP FOREIGN TABLE employee; +--Testcase 146: +DROP FOREIGN TABLE empdata; +--Testcase 147: +DROP FOREIGN TABLE multiprimary; +--Testcase 148: +DROP FOREIGN TABLE multiprimary2; +--Testcase 149: +DROP FOREIGN TABLE columntest; +--Testcase 150: +DROP FOREIGN TABLE noprimary; +--Testcase 161: +DROP FOREIGN TABLE fts_table; +--Testcase 222: +DROP FOREIGN TABLE grem1_1; +--Testcase 223: +DROP FOREIGN TABLE grem1_2; +--Testcase 235: +DROP FOREIGN TABLE case_exp; +--Testcase 151: +DROP SERVER sqlite_svr; +--Testcase 152: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/expected/17.0/type.out b/expected/17.0/type.out new file mode 100644 index 00000000..deedc213 --- /dev/null +++ b/expected/17.0/type.out @@ -0,0 +1,630 @@ +--SET log_min_messages TO DEBUG1; +--SET client_min_messages TO DEBUG1; +--Testcase 44: +CREATE EXTENSION sqlite_fdw; +--Testcase 45: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); +--Testcase 46: +CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO public; +--Testcase 1: +INSERT INTO "type_STRING"(col) VALUES ('string'); +--Testcase 4: +INSERT INTO "type_BYTE"(col) VALUES ('c'); +--Testcase 5: +INSERT INTO "type_SINT"(col) VALUES (32767); +--Testcase 6: +INSERT INTO "type_SINT"(col) VALUES (-32768); +--Testcase 7: +INSERT INTO "type_BINT"(col) VALUES (9223372036854775807); +--Testcase 8: +INSERT INTO "type_BINT"(col) VALUES (-9223372036854775808); +--Testcase 9: +INSERT INTO "type_INTEGER"(col) VALUES (9223372036854775807); +--Testcase 10: +INSERT INTO "type_FLOAT"(col) VALUES (3.1415); +--Testcase 11: +INSERT INTO "type_DOUBLE"(col) VALUES (3.14159265); +--Testcase 12: +INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 12:34:56.789', '2017.11.06'); +--Testcase 13: +INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 1:3:0', '2017.11.07'); +--Testcase 14: +INSERT INTO "type_BLOB"(col) VALUES (bytea('\xDEADBEEF')); +--Testcase 15: +INSERT INTO typetest VALUES(1,'a', 'b', 'c','2017.11.06 12:34:56.789', '2017.11.06 12:34:56.789' ) ; +--Testcase 16: +SELECT * FROM "type_STRING"; + col +-------- + string +(1 row) + +--Testcase 18: +SELECT * FROM "type_BYTE"; + col +----- + c +(1 row) + +--Testcase 19: +SELECT * FROM "type_SINT"; + col +-------- + 32767 + -32768 +(2 rows) + +--Testcase 20: +SELECT * FROM "type_BINT"; + col +---------------------- + 9223372036854775807 + -9223372036854775808 +(2 rows) + +--Testcase 21: +SELECT * FROM "type_INTEGER"; + col +--------------------- + 9223372036854775807 +(1 row) + +--Testcase 22: +SELECT * FROM "type_FLOAT"; + col +-------- + 3.1415 +(1 row) + +--Testcase 23: +SELECT * FROM "type_DOUBLE"; + col +------------ + 3.14159265 +(1 row) + +set datestyle=ISO; +--Testcase 24: +SELECT * FROM "type_TIMESTAMP"; + col | b +-------------------------+--------------------- + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 + 2017-11-06 01:03:00 | 2017-11-07 00:00:00 +(2 rows) + +--Testcase 25: +SELECT * FROM "type_BLOB"; + col +------------ + \xdeadbeef +(1 row) + +--Testcase 26: +SELECT * FROM typetest; + i | v | c | t | d | ti +---+---+------------+---+-------------------------+------------------------- + 1 | a | b | c | 2017-11-06 12:34:56.789 | 2017-11-06 12:34:56.789 +(1 row) + +--Testcase 27: +insert into "type_STRING" values('TYPE'); +--Testcase 28: +insert into "type_STRING" values('type'); +-- not pushdown +--Testcase 29: +SELECT *FROM "type_STRING" WHERE col like 'TYP%'; + col +------ + TYPE +(1 row) + +--Testcase 30: +EXPLAIN SELECT *FROM "type_STRING" WHERE col like 'TYP%'; + QUERY PLAN +------------------------------------------------------------------- + Foreign Scan on "type_STRING" (cost=10.00..7.00 rows=7 width=32) +(1 row) + +-- pushdown +--Testcase 31: +SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; + col +------ + TYPE + type +(2 rows) + +--Testcase 32: +EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; + QUERY PLAN +--------------------------------------------------------------------- + Foreign Scan on "type_STRING" (cost=10.00..58.00 rows=58 width=32) + Filter: (col ~~* 'typ%'::text) +(2 rows) + +--Testcase 33: +SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; + col +------ + TYPE +(1 row) + +--Testcase 34: +EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; + QUERY PLAN +------------------------------------------------------------------- + Foreign Scan on "type_STRING" (cost=10.00..1.00 rows=1 width=32) + Filter: (col ~~* 'typ%'::text) +(2 rows) + +--Testcase 35: +SELECT * FROM "type_TIMESTAMP"; + col | b +-------------------------+--------------------- + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 + 2017-11-06 01:03:00 | 2017-11-07 00:00:00 +(2 rows) + +--Testcase 36: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Foreign Scan on public."type_TIMESTAMP" + Output: col, b + SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" WHERE ((`col` > '2017-11-06')) +(3 rows) + +--Testcase 37: +SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; + col | b +-------------------------+--------------------- + 2017-11-06 01:03:00 | 2017-11-07 00:00:00 + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 +(2 rows) + +--Testcase 38: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; + QUERY PLAN +----------------------------------------------------------------------- + Foreign Scan on public."type_TIMESTAMP" + Output: col, b + Filter: (("type_TIMESTAMP".col)::text > ('2017-11-06'::date)::text) + SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" +(4 rows) + +--Testcase 39: +SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; + col | b +-------------------------+--------------------- + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 + 2017-11-06 01:03:00 | 2017-11-07 00:00:00 +(2 rows) + +--Testcase 40: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; + QUERY PLAN +-------------------------------------------------------------------------------- + Foreign Scan on public."type_TIMESTAMP" + Output: col, b + Filter: ("type_TIMESTAMP".col > ("type_TIMESTAMP".b - '@ 1 hour'::interval)) + SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" +(4 rows) + +--Testcase 41: +SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; + col | b +-------------------------+--------------------- + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 +(1 row) + +--Testcase 42: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b; + QUERY PLAN +------------------------------------------------------------------------------------ + Foreign Scan on public."type_TIMESTAMP" + Output: col, b + SQLite query: SELECT `col`, `b` FROM main."type_TIMESTAMP" WHERE ((`col` > `b`)) +(3 rows) + +--Testcase 43: +SELECT * FROM "type_TIMESTAMP" WHERE col > b; + col | b +-------------------------+--------------------- + 2017-11-06 12:34:56.789 | 2017-11-06 00:00:00 +(1 row) + +--Testcase 48: +INSERT INTO "type_DATE"(col) VALUES ('2021.02.23'); +--Testcase 49: +INSERT INTO "type_DATE"(col) VALUES ('2021/03/08'); +--Testcase 50: +INSERT INTO "type_DATE"(col) VALUES ('9999-12-30'); +--Testcase 58: +SELECT * FROM "type_DATE"; + col +------------ + 2021-02-23 + 2021-03-08 + 9999-12-30 +(3 rows) + +--Testcase 51: +INSERT INTO "type_TIME"(col) VALUES ('01:23:45'); +--Testcase 52: +INSERT INTO "type_TIME"(col) VALUES ('01:23:45.6789'); +--Testcase 59: +SELECT * FROM "type_TIME"; + col +--------------- + 01:23:45 + 01:23:45.6789 +(2 rows) + +--Testcase 60: +EXPLAIN VERBOSE +SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Foreign Scan on public.alltypetest (cost=10.00..57.00 rows=57 width=1400) + Output: c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 + SQLite query: SELECT `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`, `c9`, `c10`, `c11`, `c12`, `c13`, `c14`, `c15`, sqlite_fdw_float(`c17`), sqlite_fdw_float(`c18`), sqlite_fdw_float(`c19`), sqlite_fdw_float(`c21`), sqlite_fdw_float(`c22`), `c23`, `c24` FROM main."alltypetest" +(3 rows) + +--Testcase 61: +SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | c17 | c18 | c19 | c2 | c21 | c22 | c23 | c24 +--------+-----+-------+--------+---------------+--------------+---------------+------------+----------------------+------------------------+---------------------+------------------+-------------------------------------------+-----------------------------+--------------------------+---------+--------------+-------------+-----+------+-------------+------------+--------------------- + 583647 | 127 | 12767 | 388607 | 2036854775807 | 573709551615 | 2036854775807 | abcdefghij | abcdefghijjhgfjfuafh | Côte dIvoire Fijifoxju | Hôm nay tôi rất vui | I am happy today | 今日はとても幸せです 今日はとても幸せです | The quick brown fox jumps o | ABCDEFGHIJKLMNOPQRSTUVWX | 3.4e+18 | 1.79769e+108 | 1.79769e+88 | 127 | 1234 | 99999.99999 | 9999-12-31 | 9999-12-31 23:59:59 +(1 row) + +--Testcase 53: +CREATE FOREIGN TABLE type_JSON(col JSON OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'type_TEXT'); +--Testcase 54: +INSERT INTO type_JSON(col) VALUES ('[1, 2, "foo", null]'); +--Testcase 55: +INSERT INTO type_JSON(col) VALUES ('{"bar": "baz", "balance": 7.77, "active": false}'::json); +--Testcase 56 +SELECT * FROM type_JSON; + col +-------------------------------------------------- + [1, 2, "foo", null] + {"bar": "baz", "balance": 7.77, "active": false} +(2 rows) + +--Testcase 57 +DELETE FROM type_JSON; +--Testcase 62: +DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; +--Testcase 63: +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); +--Testcase 64: +ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; +--Testcase 65: +SELECT * FROM "type_BOOLEAN"; -- OK + b +--- + t + f + t + f + t + f + t + t + t + f + f + f + f + f + t + t + t + t + t + t + f + f + f + t + +(25 rows) + +-- define INTEGER as TEXT column +--Testcase 67: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE text; +--Testcase 68: +SELECT * FROM "type_INTEGER"; -- OK + col +--------------------- + 9223372036854775807 +(1 row) + +-- define INTEGER as bpchar +--Testcase 69: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE char(30); +--Testcase 70: +SELECT * FROM "type_INTEGER"; -- OK + col +-------------------------------- + 9223372036854775807 +(1 row) + +-- define INTEGER as varchar +--Testcase 71: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE varchar(30); +--Testcase 72: +SELECT * FROM "type_INTEGER"; -- OK + col +--------------------- + 9223372036854775807 +(1 row) + +-- define INTEGER as name +--Testcase 73: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE name; +--Testcase 74: +SELECT * FROM "type_INTEGER"; -- OK + col +--------------------- + 9223372036854775807 +(1 row) + +-- define INTEGER as json +--Testcase 75: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE json; +--Testcase 76: +SELECT * FROM "type_INTEGER"; -- OK + col +--------------------- + 9223372036854775807 +(1 row) + +-- define INTEGER as time +--Testcase 77: +DELETE FROM "type_INTEGER"; +--Testcase 78: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; +--Testcase 79: +INSERT INTO "type_INTEGER" VALUES (120506); +--Testcase 80: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE time; +--Testcase 81: +SELECT * FROM "type_INTEGER"; -- OK + col +---------- + 12:05:06 +(1 row) + +-- define INTEGER as date +--Testcase 82: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE date; +--Testcase 83: +SELECT * FROM "type_INTEGER"; -- OK + col +------------ + 2012-05-06 +(1 row) + +--Testcase 84: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; +--Testcase 85: +INSERT INTO "type_DOUBLE" VALUES (1.3e-5); +--Testcase 86: +SELECT * FROM "type_DOUBLE"; + col +------------ + 3.14159265 + 1.3e-05 +(2 rows) + +-- define DOUBLE as TEXT column +--Testcase 87: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE text; +--Testcase 88: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------ + 3.14159265 + 1.3e-05 +(2 rows) + +-- define DOUBLE as bpchar +--Testcase 89: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE char(30); +--Testcase 90: +SELECT * FROM "type_DOUBLE"; -- OK + col +-------------------------------- + 3.14159265 + 1.3e-05 +(2 rows) + +-- define DOUBLE as varchar +--Testcase 91: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE varchar(30); +--Testcase 92: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------ + 3.14159265 + 1.3e-05 +(2 rows) + +-- define DOUBLE as name +--Testcase 93: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE name; +--Testcase 94: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------ + 3.14159265 + 1.3e-05 +(2 rows) + +-- define DOUBLE as json +--Testcase 95: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE json; +--Testcase 96: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------ + 3.14159265 + 1.3e-05 +(2 rows) + +--Testcase 97: +DELETE FROM "type_DOUBLE"; +--Testcase 98: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; +--Testcase 99: +INSERT INTO "type_DOUBLE" VALUES (120506.12); +-- define DOUBLE as time +--Testcase 100: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE time; +--Testcase 101: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------- + 12:05:06.12 +(1 row) + +--Testcase 102: +DELETE FROM "type_DOUBLE"; +--Testcase 103: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; +--Testcase 104: +INSERT INTO "type_DOUBLE" VALUES (1999.012); +-- define DOUBLE as date +--Testcase 105: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE date; +--Testcase 106: +SELECT * FROM "type_DOUBLE"; -- OK + col +------------ + 1999-01-12 +(1 row) + +--Testcase 107: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; +--Testcase 108: +INSERT INTO "type_DOUBLE" VALUES (PI()); +--Testcase 109: ERR primary key +INSERT INTO "type_DOUBLE" VALUES (PI()); +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) +--Testcase 110: +INSERT INTO "type_DOUBLE" VALUES ('Infinity'); +--Testcase 111: +INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); +--Testcase 113: +SELECT * FROM "type_DOUBLE"; -- OK, +- Inf + col +------------------- + 1999.012 + 3.141592653589793 + Infinity + -Infinity +(4 rows) + +--Testcase 114: ERR primary key +INSERT INTO "type_DOUBLE" VALUES ('Infinity'); +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) +--Testcase 115: ERR primary key +INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); +ERROR: Failed to execute remote SQL +HINT: SQLite error 'UNIQUE constraint failed: type_DOUBLE.col', SQLite result code 19 +CONTEXT: SQL query: INSERT INTO main."type_DOUBLE"(`col`) VALUES (?) +--Testcase 116: +SELECT * FROM "type_DOUBLE"; -- OK, +- Inf + col +------------------- + 1999.012 + 3.141592653589793 + Infinity + -Infinity +(4 rows) + +--Testcase 47: +DROP EXTENSION sqlite_fdw CASCADE; +NOTICE: drop cascades to 48 other objects +DETAIL: drop cascades to server sqlite_svr +drop cascades to foreign table department +drop cascades to foreign table employee +drop cascades to foreign table empdata +drop cascades to foreign table numbers +drop cascades to foreign table t +drop cascades to foreign table multiprimary +drop cascades to foreign table columntest +drop cascades to foreign table noprimary +drop cascades to foreign table limittest +drop cascades to foreign table grem1_1 +drop cascades to foreign table grem1_2 +drop cascades to foreign table case_exp +drop cascades to foreign table "type_STRING" +drop cascades to foreign table "type_BOOLEANpk" +drop cascades to foreign table "type_BYTE" +drop cascades to foreign table "type_SINT" +drop cascades to foreign table "type_BINT" +drop cascades to foreign table "type_INTEGER" +drop cascades to foreign table "type_FLOAT" +drop cascades to foreign table "type_DOUBLE" +drop cascades to foreign table "type_TIMESTAMP" +drop cascades to foreign table "type_BLOB" +drop cascades to foreign table "type_DATE" +drop cascades to foreign table "type_TIME" +drop cascades to foreign table "type_BIT" +drop cascades to foreign table "type_VARBIT" +drop cascades to foreign table "type_UUIDpk" +drop cascades to foreign table "type_UUID" +drop cascades to foreign table "BitT" +drop cascades to foreign table notype +drop cascades to foreign table typetest +drop cascades to foreign table "type_TEXT" +drop cascades to foreign table alltypetest +drop cascades to foreign table shorty +drop cascades to foreign table "A a" +drop cascades to foreign table fts_table +drop cascades to foreign table fts_table_data +drop cascades to foreign table fts_table_idx +drop cascades to foreign table fts_table_content +drop cascades to foreign table fts_table_docsize +drop cascades to foreign table fts_table_config +drop cascades to foreign table "RO_RW_test" +drop cascades to foreign table "Unicode data" +drop cascades to foreign table "type_BOOLEAN_oper" +drop cascades to foreign table type_json +drop cascades to foreign table "type_BOOLEAN" +drop cascades to server sqlite2 diff --git a/option.c b/option.c index 2672ec15..c0b6b5d1 100644 --- a/option.c +++ b/option.c @@ -69,7 +69,7 @@ bool /* * Validate the generic options given to a FOREIGN DATA WRAPPER, SERVER, - * USER MAPPING or FOREIGN TABLE that uses file_fdw. + * or FOREIGN TABLE that supported by sqlite_fdw. * * Raise an ERROR if the option or its value is considered invalid. */ @@ -229,8 +229,6 @@ sqlite_get_options(Oid foreignoid) options = list_concat(options, f_table->options); options = list_concat(options, f_server->options); - opt->use_remote_estimate = false; - /* Loop through the options, and get the server/port */ foreach(lc, options) { diff --git a/sql/13.12/extra/int4.sql b/sql/13.12/extra/int4.sql deleted file mode 100644 index 574b9137..00000000 --- a/sql/13.12/extra/int4.sql +++ /dev/null @@ -1,387 +0,0 @@ --- --- INT4 Based on PostgreSQL tests, please don't add additional tests here, use other test files --- ---Testcase 61: -CREATE EXTENSION sqlite_fdw; ---Testcase 62: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 63: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 64: -CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; - ---Testcase 1: -INSERT INTO INT4_TBL(f1) VALUES (' 0 '); - ---Testcase 2: -INSERT INTO INT4_TBL(f1) VALUES ('123456 '); - ---Testcase 3: -INSERT INTO INT4_TBL(f1) VALUES (' -123456'); - ---Testcase 4: -INSERT INTO INT4_TBL(f1) VALUES ('34.5'); - --- largest and smallest values ---Testcase 5: -INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); - ---Testcase 6: -INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); - --- bad input values -- should give errors ---Testcase 7: -INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); ---Testcase 8: -INSERT INTO INT4_TBL(f1) VALUES ('asdf'); ---Testcase 9: -INSERT INTO INT4_TBL(f1) VALUES (' '); ---Testcase 10: -INSERT INTO INT4_TBL(f1) VALUES (' asdf '); ---Testcase 11: -INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); ---Testcase 12: -INSERT INTO INT4_TBL(f1) VALUES ('123 5'); ---Testcase 13: -INSERT INTO INT4_TBL(f1) VALUES (''); - - ---Testcase 14: -SELECT '' AS five, * FROM INT4_TBL; - ---Testcase 15: -SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int2 '0'; - ---Testcase 16: -SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int4 '0'; - ---Testcase 17: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int2 '0'; - ---Testcase 18: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int4 '0'; - ---Testcase 19: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int2 '0'; - ---Testcase 20: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int4 '0'; - ---Testcase 21: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int2 '0'; - ---Testcase 22: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int4 '0'; - ---Testcase 23: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int2 '0'; - ---Testcase 24: -SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int4 '0'; - ---Testcase 25: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int2 '0'; - ---Testcase 26: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int4 '0'; - --- positive odds ---Testcase 27: -SELECT '' AS one, i.* FROM INT4_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; - --- any evens ---Testcase 28: -SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; - ---Testcase 29: -SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i; - ---Testcase 30: -SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i -WHERE abs(f1) < 1073741824; - ---Testcase 31: -SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i; - ---Testcase 32: -SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i -WHERE abs(f1) < 1073741824; - ---Testcase 33: -SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i; - ---Testcase 34: -SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i -WHERE f1 < 2147483646; - ---Testcase 35: -SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i; - ---Testcase 36: -SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i -WHERE f1 < 2147483646; - ---Testcase 37: -SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i; - ---Testcase 38: -SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i -WHERE f1 > -2147483647; - ---Testcase 39: -SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i; - ---Testcase 40: -SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i -WHERE f1 > -2147483647; - ---Testcase 41: -SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i; - ---Testcase 42: -SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i; - --- --- more complex expressions --- - --- variations on unary minus parsing - ---Testcase 65: -DELETE FROM INT4_TMP; ---Testcase 66: -INSERT INTO INT4_TMP VALUES (-2, 3); ---Testcase 67: -SELECT f1 + f2 as one FROM INT4_TMP; - ---Testcase 68: -DELETE FROM INT4_TMP; ---Testcase 69: -INSERT INTO INT4_TMP VALUES (4, 2); ---Testcase 70: -SELECT f1 - f2 as two FROM INT4_TMP; - ---Testcase 46: -DELETE FROM INT4_TMP; ---Testcase 71: -INSERT INTO INT4_TMP VALUES (2, 1); ---Testcase 72: -SELECT f1- -f2 as three FROM INT4_TMP; - ---Testcase 47: -DELETE FROM INT4_TMP; ---Testcase 73: -INSERT INTO INT4_TMP VALUES (2, 2); ---Testcase 74: -SELECT f1 - -f2 as four FROM INT4_TMP; - ---Testcase 75: -DELETE FROM INT4_TMP; ---Testcase 76: -INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int2, '16'::int2 / '4'::int2); ---Testcase 77: -SELECT f1 = f2 AS true FROM INT4_TMP; - ---Testcase 78: -DELETE FROM INT4_TMP; ---Testcase 79: -INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int4, '16'::int2 / '4'::int4); ---Testcase 80: -SELECT f1 = f2 AS true FROM INT4_TMP; - ---Testcase 81: -DELETE FROM INT4_TMP; ---Testcase 82: -INSERT INTO INT4_TMP VALUES ('2'::int4 * '2'::int2, '16'::int4 / '4'::int2); ---Testcase 83: -SELECT f1 = f2 AS true FROM INT4_TMP; - ---Testcase 84: -DELETE FROM INT4_TMP; ---Testcase 85: -INSERT INTO INT4_TMP VALUES ('1000'::int4, '999'::int4); ---Testcase 86: -SELECT f1 < f2 AS false FROM INT4_TMP; - ---Testcase 48: -DELETE FROM INT4_TMP; ---Testcase 87: -INSERT INTO INT4_TMP VALUES (4!); ---Testcase 88: -SELECT f1 as twenty_four FROM INT4_TMP; - ---Testcase 49: -DELETE FROM INT4_TMP; ---Testcase 89: -INSERT INTO INT4_TMP VALUES (!!3); ---Testcase 90: -SELECT f1 as six FROM INT4_TMP; - ---Testcase 50: -DELETE FROM INT4_TMP; ---Testcase 91: -INSERT INTO INT4_TMP VALUES (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1); ---Testcase 92: -SELECT f1 as ten FROM INT4_TMP; - ---Testcase 51: -DELETE FROM INT4_TMP; ---Testcase 93: -INSERT INTO INT4_TMP VALUES (2 , 2); ---Testcase 94: -SELECT f1 + f1/f2 as three FROM INT4_TMP; - ---Testcase 52: -DELETE FROM INT4_TMP; ---Testcase 95: -INSERT INTO INT4_TMP VALUES (2 , 2); ---Testcase 96: -SELECT (f1 + f2)/f2 as two FROM INT4_TMP; - --- corner case ---Testcase 54: -DELETE FROM INT4_TMP; ---Testcase 97: -INSERT INTO INT4_TMP VALUES (-1); ---Testcase 98: -SELECT (f1<<31)::text FROM INT4_TMP; - ---Testcase 56: -DELETE FROM INT4_TMP; ---Testcase 99: -INSERT INTO INT4_TMP VALUES (-1); ---Testcase 100: -SELECT ((f1<<31)+1)::text FROM INT4_TMP; - --- check sane handling of INT_MIN overflow cases ---Testcase 58: -DELETE FROM INT4_TMP; ---Testcase 101: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int4); ---Testcase 102: -SELECT f1 * f2 FROM INT4_TMP; ---Testcase 103: -SELECT f1 / f2 FROM INT4_TMP; ---Testcase 104: -SELECT f1 % f2 FROM INT4_TMP; - ---Testcase 60: -DELETE FROM INT4_TMP; ---Testcase 105: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int2); ---Testcase 106: -SELECT f1 * f2 FROM INT4_TMP; ---Testcase 107: -SELECT f1 / f2 FROM INT4_TMP; ---Testcase 108: -SELECT f1 % f2 FROM INT4_TMP; - --- check rounding when casting from float ---Testcase 109: -CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 110: -DELETE FROM FLOAT8_TMP; ---Testcase 111: -INSERT INTO FLOAT8_TMP VALUES - (-2.5::float8), - (-1.5::float8), - (-0.5::float8), - (0.0::float8), - (0.5::float8), - (1.5::float8), - (2.5::float8); - ---Testcase 112: -SELECT f1 as x, f1::int4 as int4_value FROM FLOAT8_TMP; - --- check rounding when casting from numeric ---Testcase 113: -CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 114: -DELETE FROM NUMERIC_TMP; ---Testcase 115: -INSERT INTO NUMERIC_TMP VALUES - (-2.5::numeric), - (-1.5::numeric), - (-0.5::numeric), - (0.0::numeric), - (0.5::numeric), - (1.5::numeric), - (2.5::numeric); ---Testcase 116: -SELECT f1 as x, f1::int4 as int4_value FROM NUMERIC_TMP; - --- test gcd() ---Testcase 117: -DELETE FROM INT4_TMP; ---Testcase 118: -INSERT INTO INT4_TMP VALUES - (0::int4, 0::int4), - (0::int4, 6410818::int4), - (61866666::int4, 6410818::int4), - (-61866666::int4, 6410818::int4), - ((-2147483648)::int4, 1::int4), - ((-2147483648)::int4, 2147483647::int4), - ((-2147483648)::int4, 1073741824::int4); ---Testcase 119: -SELECT f1, f2, gcd(f1, f2), gcd(f1, -f2), gcd(f2, f1), gcd(-f2, f1) FROM INT4_TMP; - ---Testcase 120: -DELETE FROM INT4_TMP; ---Testcase 121: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 0::int4); ---Testcase 122: -SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow - ---Testcase 123: -DELETE FROM INT4_TMP; ---Testcase 124: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-2147483648)::int4); ---Testcase 125: -SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow - --- test lcm() ---Testcase 126: -DELETE FROM INT4_TMP; ---Testcase 127: -INSERT INTO INT4_TMP VALUES - (0::int4, 0::int4), - (0::int4, 42::int4), - (42::int4, 42::int4), - (330::int4, 462::int4), - (-330::int4, 462::int4), - ((-2147483648)::int4, 0::int4); ---Testcase 128: -SELECT f1, f2, lcm(f1, f2), lcm(f1, -f2), lcm(f2, f1), lcm(-f2, f1) FROM INT4_TMP; - ---Testcase 129: -DELETE FROM INT4_TMP; ---Testcase 130: -INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 1::int4); ---Testcase 131: -SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow - ---Testcase 132: -DELETE FROM INT4_TMP; ---Testcase 133: -INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); ---Testcase 134: -SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow - --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; - ---Testcase 135: -DROP SERVER sqlite_svr; ---Testcase 136: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/13.12/extra/int8.sql b/sql/13.12/extra/int8.sql deleted file mode 100644 index 7d4ba4ba..00000000 --- a/sql/13.12/extra/int8.sql +++ /dev/null @@ -1,633 +0,0 @@ --- --- INT8 --- Test int8 64-bit integers. --- ---Testcase 140: -CREATE EXTENSION sqlite_fdw; ---Testcase 141: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 142: -CREATE FOREIGN TABLE INT8_TBL( - q1 int8 OPTIONS (key 'true'), - q2 int8 OPTIONS (key 'true') -) SERVER sqlite_svr; ---Testcase 143: -CREATE FOREIGN TABLE INT8_TMP( - q1 int8, - q2 int8, - q3 int4, - q4 int2, - q5 text, - id int options (key 'true') -) SERVER sqlite_svr; - ---Testcase 1: -INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); ---Testcase 2: -INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); ---Testcase 3: -INSERT INTO INT8_TBL VALUES('4567890123456789','123'); ---Testcase 4: -INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); ---Testcase 5: -INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); - --- bad inputs ---Testcase 6: -INSERT INTO INT8_TBL(q1) VALUES (' '); ---Testcase 7: -INSERT INTO INT8_TBL(q1) VALUES ('xxx'); ---Testcase 8: -INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); ---Testcase 9: -INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); ---Testcase 10: -INSERT INTO INT8_TBL(q1) VALUES ('- 123'); ---Testcase 11: -INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); ---Testcase 12: -INSERT INTO INT8_TBL(q1) VALUES (''); - ---Testcase 13: -SELECT * FROM INT8_TBL; - --- int8/int8 cmp ---Testcase 14: -SELECT * FROM INT8_TBL WHERE q2 = 4567890123456789; ---Testcase 15: -SELECT * FROM INT8_TBL WHERE q2 <> 4567890123456789; ---Testcase 16: -SELECT * FROM INT8_TBL WHERE q2 < 4567890123456789; ---Testcase 17: -SELECT * FROM INT8_TBL WHERE q2 > 4567890123456789; ---Testcase 18: -SELECT * FROM INT8_TBL WHERE q2 <= 4567890123456789; ---Testcase 19: -SELECT * FROM INT8_TBL WHERE q2 >= 4567890123456789; - --- int8/int4 cmp ---Testcase 20: -SELECT * FROM INT8_TBL WHERE q2 = 456; ---Testcase 21: -SELECT * FROM INT8_TBL WHERE q2 <> 456; ---Testcase 22: -SELECT * FROM INT8_TBL WHERE q2 < 456; ---Testcase 23: -SELECT * FROM INT8_TBL WHERE q2 > 456; ---Testcase 24: -SELECT * FROM INT8_TBL WHERE q2 <= 456; ---Testcase 25: -SELECT * FROM INT8_TBL WHERE q2 >= 456; - --- int4/int8 cmp ---Testcase 26: -SELECT * FROM INT8_TBL WHERE 123 = q1; ---Testcase 27: -SELECT * FROM INT8_TBL WHERE 123 <> q1; ---Testcase 28: -SELECT * FROM INT8_TBL WHERE 123 < q1; ---Testcase 29: -SELECT * FROM INT8_TBL WHERE 123 > q1; ---Testcase 30: -SELECT * FROM INT8_TBL WHERE 123 <= q1; ---Testcase 31: -SELECT * FROM INT8_TBL WHERE 123 >= q1; - --- int8/int2 cmp ---Testcase 32: -SELECT * FROM INT8_TBL WHERE q2 = '456'::int2; ---Testcase 33: -SELECT * FROM INT8_TBL WHERE q2 <> '456'::int2; ---Testcase 34: -SELECT * FROM INT8_TBL WHERE q2 < '456'::int2; ---Testcase 35: -SELECT * FROM INT8_TBL WHERE q2 > '456'::int2; ---Testcase 36: -SELECT * FROM INT8_TBL WHERE q2 <= '456'::int2; ---Testcase 37: -SELECT * FROM INT8_TBL WHERE q2 >= '456'::int2; - --- int2/int8 cmp ---Testcase 38: -SELECT * FROM INT8_TBL WHERE '123'::int2 = q1; ---Testcase 39: -SELECT * FROM INT8_TBL WHERE '123'::int2 <> q1; ---Testcase 40: -SELECT * FROM INT8_TBL WHERE '123'::int2 < q1; ---Testcase 41: -SELECT * FROM INT8_TBL WHERE '123'::int2 > q1; ---Testcase 42: -SELECT * FROM INT8_TBL WHERE '123'::int2 <= q1; ---Testcase 43: -SELECT * FROM INT8_TBL WHERE '123'::int2 >= q1; - - ---Testcase 44: -SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL; - ---Testcase 45: -SELECT '' AS five, q1, q2, q1 + q2 AS plus FROM INT8_TBL; ---Testcase 46: -SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL; ---Testcase 47: -SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL; ---Testcase 48: -SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL - WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); ---Testcase 49: -SELECT '' AS five, q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL; - ---Testcase 50: -SELECT '' AS five, q1, float8(q1) FROM INT8_TBL; ---Testcase 51: -SELECT '' AS five, q2, float8(q2) FROM INT8_TBL; - ---Testcase 52: -SELECT 37 + q1 AS plus4 FROM INT8_TBL; ---Testcase 53: -SELECT 37 - q1 AS minus4 FROM INT8_TBL; ---Testcase 54: -SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL; ---Testcase 55: -SELECT '' AS five, q1 * 2 AS "twice int4" FROM INT8_TBL; - --- int8 op int4 ---Testcase 56: -SELECT q1 + 42::int4 AS "8plus4", q1 - 42::int4 AS "8minus4", q1 * 42::int4 AS "8mul4", q1 / 42::int4 AS "8div4" FROM INT8_TBL; --- int4 op int8 ---Testcase 57: -SELECT 246::int4 + q1 AS "4plus8", 246::int4 - q1 AS "4minus8", 246::int4 * q1 AS "4mul8", 246::int4 / q1 AS "4div8" FROM INT8_TBL; - --- int8 op int2 ---Testcase 58: -SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "8mul2", q1 / 42::int2 AS "8div2" FROM INT8_TBL; --- int2 op int8 ---Testcase 59: -SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL; - ---Testcase 60: -SELECT q2, abs(q2) FROM INT8_TBL; ---Testcase 61: -SELECT min(q1), min(q2) FROM INT8_TBL; ---Testcase 62: -SELECT max(q1), max(q2) FROM INT8_TBL; - - --- TO_CHAR() --- ---Testcase 63: -SELECT '' AS to_char_1, to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999') - FROM INT8_TBL; - ---Testcase 64: -SELECT '' AS to_char_2, to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999') - FROM INT8_TBL; - ---Testcase 65: -SELECT '' AS to_char_3, to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR') - FROM INT8_TBL; - ---Testcase 66: -SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999') - FROM INT8_TBL; - ---Testcase 67: -SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL; ---Testcase 68: -SELECT '' AS to_char_6, to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; ---Testcase 69: -SELECT '' AS to_char_7, to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL; ---Testcase 70: -SELECT '' AS to_char_8, to_char(q2, 'SG9999999999999999th') FROM INT8_TBL; ---Testcase 71: -SELECT '' AS to_char_9, to_char(q2, '0999999999999999') FROM INT8_TBL; ---Testcase 72: -SELECT '' AS to_char_10, to_char(q2, 'S0999999999999999') FROM INT8_TBL; ---Testcase 73: -SELECT '' AS to_char_11, to_char(q2, 'FM0999999999999999') FROM INT8_TBL; ---Testcase 74: -SELECT '' AS to_char_12, to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL; ---Testcase 75: -SELECT '' AS to_char_13, to_char(q2, 'L9999999999999999.000') FROM INT8_TBL; ---Testcase 76: -SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL; ---Testcase 77: -SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL; ---Testcase 78: -SELECT '' AS to_char_16, to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; ---Testcase 79: -SELECT '' AS to_char_17, to_char(q2, '999999SG9999999999') FROM INT8_TBL; - --- check min/max values and overflow behavior ---Testcase 80: -DELETE FROM INT8_TMP; ---Testcase 144: -INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); ---Testcase 145: -SELECT q1 FROM INT8_TMP; - ---Testcase 81: -DELETE FROM INT8_TMP; ---Testcase 146: -INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); ---Testcase 147: -SELECT q1 FROM INT8_TMP; - ---Testcase 82: -DELETE FROM INT8_TMP; ---Testcase 148: -INSERT INTO INT8_TMP VALUES ('9223372036854775807'::int8); ---Testcase 149: -SELECT q1 FROM INT8_TMP; - ---Testcase 83: -DELETE FROM INT8_TMP; ---Testcase 150: -INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); ---Testcase 151: -SELECT q1 FROM INT8_TMP; - ---Testcase 84: -DELETE FROM INT8_TMP; ---Testcase 152: -INSERT INTO INT8_TMP VALUES (-('-9223372036854775807'::int8)); ---Testcase 153: -SELECT q1 FROM INT8_TMP; - ---Testcase 86: -DELETE FROM INT8_TMP; ---Testcase 154: -INSERT INTO INT8_TMP VALUES (-('-9223372036854775808'::int8)); ---Testcase 155: -SELECT q1 FROM INT8_TMP; - ---Testcase 87: -DELETE FROM INT8_TMP; ---Testcase 156: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 157: -SELECT q1 + q2 FROM INT8_TMP; ---Testcase 88: -DELETE FROM INT8_TMP; ---Testcase 158: -INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '-9223372036854775800'::int8); ---Testcase 159: -SELECT q1 + q2 FROM INT8_TMP; - ---Testcase 89: -DELETE FROM INT8_TMP; ---Testcase 160: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '-9223372036854775800'::int8); ---Testcase 161: -SELECT q1-q2 FROM INT8_TMP; ---Testcase 90: -DELETE FROM INT8_TMP; ---Testcase 162: -INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 163: -SELECT q1 - q2 FROM INT8_TMP; - ---Testcase 91: -DELETE FROM INT8_TMP; ---Testcase 164: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); ---Testcase 165: -SELECT q1 * q2 FROM INT8_TMP; - ---Testcase 92: -DELETE FROM INT8_TMP; ---Testcase 166: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); ---Testcase 167: -SELECT q1 / q2 FROM INT8_TMP; - ---Testcase 93: -DELETE FROM INT8_TMP; ---Testcase 168: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); ---Testcase 169: -SELECT q1 % q2 FROM INT8_TMP; - ---Testcase 94: -DELETE FROM INT8_TMP; ---Testcase 170: -INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); ---Testcase 171: -SELECT abs(q1) FROM INT8_TMP; - ---Testcase 95: -DELETE FROM INT8_TMP; ---Testcase 172: -INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); ---Testcase 173: -SELECT q1 + q3 FROM INT8_TMP; ---Testcase 96: -DELETE FROM INT8_TMP; ---Testcase 174: -INSERT INTO INT8_TMP(q1, q3) VALUES ('-9223372036854775800'::int8 , '100'::int4); ---Testcase 175: -SELECT q1 - q3 FROM INT8_TMP; ---Testcase 97: -DELETE FROM INT8_TMP; ---Testcase 176: -INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); ---Testcase 177: -SELECT q1 * q3 FROM INT8_TMP; - ---Testcase 98: -DELETE FROM INT8_TMP; ---Testcase 178: -INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); ---Testcase 179: -SELECT q3 + q1 FROM INT8_TMP; ---Testcase 99: -DELETE FROM INT8_TMP; ---Testcase 180: -INSERT INTO INT8_TMP(q3, q1) VALUES ('-100'::int4 , '9223372036854775800'::int8); ---Testcase 181: -SELECT q3 - q1 FROM INT8_TMP; ---Testcase 100: -DELETE FROM INT8_TMP; ---Testcase 182: -INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); ---Testcase 183: -SELECT q3 * q1 FROM INT8_TMP; - ---Testcase 101: -DELETE FROM INT8_TMP; ---Testcase 184: -INSERT INTO INT8_TMP(q1, q4) VALUES ('9223372036854775800'::int8 , '100'::int2); ---Testcase 185: -SELECT q1 + q4 FROM INT8_TMP; ---Testcase 102: -DELETE FROM INT8_TMP; ---Testcase 186: -INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775800'::int8 , '100'::int2); ---Testcase 187: -SELECT q1 - q4 FROM INT8_TMP; ---Testcase 103: -DELETE FROM INT8_TMP; ---Testcase 188: -INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '100'::int2); ---Testcase 189: -SELECT q1 * q4 FROM INT8_TMP; ---Testcase 104: -DELETE FROM INT8_TMP; ---Testcase 190: -INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775808'::int8 , '0'::int2); ---Testcase 191: -SELECT q1 / q4 FROM INT8_TMP; - ---Testcase 105: -DELETE FROM INT8_TMP; ---Testcase 192: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); ---Testcase 193: -SELECT q4 + q1 FROM INT8_TMP; ---Testcase 106: -DELETE FROM INT8_TMP; ---Testcase 194: -INSERT INTO INT8_TMP(q4, q1) VALUES ('-100'::int2 , '9223372036854775800'::int8); ---Testcase 195: -SELECT q4 - q1 FROM INT8_TMP; ---Testcase 107: -DELETE FROM INT8_TMP; ---Testcase 196: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); ---Testcase 197: -SELECT q4 * q1 FROM INT8_TMP; ---Testcase 108: -DELETE FROM INT8_TMP; ---Testcase 198: -INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '0'::int8); ---Testcase 199: -SELECT q4 / q1 FROM INT8_TMP; - ---Testcase 110: -SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 = 456; ---Testcase 111: -SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 <> 456; - ---Testcase 112: -SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 = 456; ---Testcase 113: -SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 <> 456; - ---Testcase 200: -DELETE FROM INT8_TMP; ---Testcase 201: -INSERT INTO INT8_TMP(q5) VALUES ('42'), ('-37'); ---Testcase 202: -SELECT CAST(q5::int2 as int8) FROM INT8_TMP; - ---Testcase 114: -SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL; - ---Testcase 203: -DELETE FROM INT8_TMP; ---Testcase 204: -INSERT INTO INT8_TMP(q5) VALUES ('36854775807.0'); ---Testcase 205: -SELECT CAST(q5::float4 AS int8) FROM INT8_TMP; - ---Testcase 206: -DELETE FROM INT8_TMP; ---Testcase 207: -INSERT INTO INT8_TMP(q5) VALUES ('922337203685477580700.0'); ---Testcase 208: -SELECT CAST(q5::float8 AS int8) FROM INT8_TMP; - ---Testcase 115: -SELECT CAST(q1 AS oid) FROM INT8_TBL; ---Testcase 209: -SELECT oid::int8 FROM pg_class WHERE relname = 'pg_class'; - --- bit operations - ---Testcase 116: -SELECT q1, q2, q1 & q2 AS "and", q1 | q2 AS "or", q1 # q2 AS "xor", ~q1 AS "not" FROM INT8_TBL; ---Testcase 117: -SELECT q1, q1 << 2 AS "shl", q1 >> 3 AS "shr" FROM INT8_TBL; - - --- generate_series - ---Testcase 118: -DELETE FROM INT8_TMP; ---Testcase 210: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8) q1; ---Testcase 211: -SELECT q1 FROM INT8_TMP; - ---Testcase 120: -DELETE FROM INT8_TMP; ---Testcase 212: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 0) q1; -- should error ---Testcase 213: -SELECT q1 FROM INT8_TMP; - ---Testcase 122: -DELETE FROM INT8_TMP; ---Testcase 214: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 2) q1; ---Testcase 215: -SELECT q1 FROM INT8_TMP; - --- corner case ---Testcase 216: -DELETE FROM INT8_TMP; ---Testcase 217: -INSERT INTO INT8_TMP VALUES (-1::int8<<63); ---Testcase 218: -SELECT q1::text FROM INT8_TMP; - ---Testcase 219: -DELETE FROM INT8_TMP; ---Testcase 220: -INSERT INTO INT8_TMP VALUES ((-1::int8<<63)+1); ---Testcase 221: -SELECT q1::text FROM INT8_TMP; - --- check sane handling of INT64_MIN overflow cases ---Testcase 125: -DELETE FROM INT8_TMP; ---Testcase 222: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int8, 888); ---Testcase 126: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int8, 888); ---Testcase 127: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int8, 888); ---Testcase 128: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; ---Testcase 129: -DELETE FROM INT8_TMP WHERE q2 = 888; ---Testcase 130: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int4, 888); ---Testcase 131: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int4, 888); ---Testcase 132: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int4, 888); ---Testcase 133: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; ---Testcase 134: -DELETE FROM INT8_TMP WHERE q2 = 888; ---Testcase 135: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int2, 888); ---Testcase 136: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int2, 888); ---Testcase 137: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int2, 888); ---Testcase 138: -SELECT q1 FROM INT8_TMP WHERE q2 = 888; ---Testcase 139: -DELETE FROM INT8_TMP WHERE q2 = 888; - --- check rounding when casting from float ---Testcase 223: -CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 224: -DELETE FROM FLOAT8_TMP; ---Testcase 225: -INSERT INTO FLOAT8_TMP VALUES - (-2.5::float8), - (-1.5::float8), - (-0.5::float8), - (0.0::float8), - (0.5::float8), - (1.5::float8), - (2.5::float8); - ---Testcase 226: -SELECT f1 as x, f1::int8 as int8_value FROM FLOAT8_TMP; - --- check rounding when casting from numeric ---Testcase 227: -CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 228: -DELETE FROM NUMERIC_TMP; ---Testcase 229: -INSERT INTO NUMERIC_TMP VALUES - (-2.5::numeric), - (-1.5::numeric), - (-0.5::numeric), - (0.0::numeric), - (0.5::numeric), - (1.5::numeric), - (2.5::numeric); ---Testcase 230: -SELECT f1 as x, f1::int8 as int8_value FROM NUMERIC_TMP; - --- test gcd() ---Testcase 231: -DELETE FROM INT8_TMP; ---Testcase 232: -INSERT INTO INT8_TMP VALUES - (0::int8, 0::int8), - (0::int8, 29893644334::int8), - (288484263558::int8, 29893644334::int8), - (-288484263558::int8, 29893644334::int8), - ((-9223372036854775808)::int8, 1::int8), - ((-9223372036854775808)::int8, 9223372036854775807::int8), - ((-9223372036854775808)::int8, 4611686018427387904::int8); ---Testcase 233: -SELECT q1, q2, gcd(q1, q2), gcd(q1, -q2), gcd(q2, q1), gcd(-q2, q1) FROM INT8_TMP; - ---Testcase 234: -DELETE FROM INT8_TMP; ---Testcase 235: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 0::int8); ---Testcase 236: -SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow - ---Testcase 237: -DELETE FROM INT8_TMP; ---Testcase 238: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, (-9223372036854775808)::int8); ---Testcase 239: -SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow - --- test lcm() ---Testcase 240: -DELETE FROM INT8_TMP; ---Testcase 241: -INSERT INTO INT8_TMP VALUES - (0::int8, 0::int8), - (0::int8, 29893644334::int8), - (29893644334::int8, 29893644334::int8), - (288484263558::int8, 29893644334::int8), - (-288484263558::int8, 29893644334::int8), - ((-9223372036854775808)::int8, 0::int8); ---Testcase 242: -SELECT q1, q2, lcm(q1, q2), lcm(q1, -q2), lcm(q2, q1), lcm(-q2, q1) FROM INT8_TMP; - ---Testcase 243: -DELETE FROM INT8_TMP; ---Testcase 244: -INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 1::int8); ---Testcase 245: -SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow - ---Testcase 246: -DELETE FROM INT8_TMP; ---Testcase 247: -INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806)::int8); ---Testcase 248: -SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow - --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; - ---Testcase 249: -DROP SERVER sqlite_svr; ---Testcase 250: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/13.12/extra/limit.sql b/sql/13.12/extra/limit.sql deleted file mode 100644 index fad57bf9..00000000 --- a/sql/13.12/extra/limit.sql +++ /dev/null @@ -1,438 +0,0 @@ --- --- LIMIT --- Check the LIMIT/OFFSET feature of SELECT --- ---Testcase 27: -CREATE EXTENSION sqlite_fdw; ---Testcase 28: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); ---Testcase 29: -CREATE FOREIGN TABLE onek( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; - ---Testcase 30: -CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; ---Testcase 31: -CREATE FOREIGN TABLE INT8_TMP( - q1 int8, - q2 int8, - q3 int4, - q4 int2, - q5 text, - id int options (key 'true') -) SERVER sqlite_svr; - ---Testcase 32: -CREATE FOREIGN TABLE tenk1 ( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; - ---Testcase 88: -CREATE TABLE parent_table ( - unique1 int4 PRIMARY KEY, - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -); - ---Testcase 89: -CREATE FOREIGN table inherited_table () -INHERITS (parent_table) -SERVER sqlite_svr options (table 'tenk1'); - ---Testcase 1: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 50 - ORDER BY unique1 LIMIT 2; ---Testcase 2: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 60 - ORDER BY unique1 LIMIT 5; ---Testcase 3: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 60 AND unique1 < 63 - ORDER BY unique1 LIMIT 5; ---Testcase 4: -SELECT ''::text AS three, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 100 - ORDER BY unique1 LIMIT 3 OFFSET 20; ---Testcase 5: -SELECT ''::text AS zero, unique1, unique2, stringu1 - FROM onek WHERE unique1 < 50 - ORDER BY unique1 DESC LIMIT 8 OFFSET 99; ---Testcase 6: -SELECT ''::text AS eleven, unique1, unique2, stringu1 - FROM onek WHERE unique1 < 50 - ORDER BY unique1 DESC LIMIT 20 OFFSET 39; ---Testcase 7: -SELECT ''::text AS ten, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 OFFSET 990; ---Testcase 8: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 OFFSET 990 LIMIT 5; ---Testcase 9: -SELECT ''::text AS five, unique1, unique2, stringu1 - FROM onek - ORDER BY unique1 LIMIT 5 OFFSET 900; - --- Test null limit and offset. The planner would discard a simple null --- constant, so to ensure executor is exercised, do this: ---Testcase 10: -select * from int8_tbl limit (case when random() < 0.5 then null::bigint end); ---Testcase 11: -select * from int8_tbl offset (case when random() < 0.5 then null::bigint end); - --- Test assorted cases involving backwards fetch from a LIMIT plan node -begin; - -declare c1 scroll cursor for select * from int8_tbl order by q1 limit 10; ---Testcase 12: -fetch all in c1; ---Testcase 13: -fetch 1 in c1; ---Testcase 14: -fetch backward 1 in c1; ---Testcase 33: -fetch backward all in c1; ---Testcase 34: -fetch backward 1 in c1; ---Testcase 35: -fetch all in c1; - -declare c2 scroll cursor for select * from int8_tbl limit 3; ---Testcase 36: -fetch all in c2; ---Testcase 37: -fetch 1 in c2; ---Testcase 38: -fetch backward 1 in c2; ---Testcase 39: -fetch backward all in c2; ---Testcase 40: -fetch backward 1 in c2; ---Testcase 41: -fetch all in c2; - -declare c3 scroll cursor for select * from int8_tbl offset 3; ---Testcase 42: -fetch all in c3; ---Testcase 43: -fetch 1 in c3; ---Testcase 44: -fetch backward 1 in c3; ---Testcase 45: -fetch backward all in c3; ---Testcase 46: -fetch backward 1 in c3; ---Testcase 47: -fetch all in c3; - -declare c4 scroll cursor for select * from int8_tbl offset 10; ---Testcase 48: -fetch all in c4; ---Testcase 49: -fetch 1 in c4; ---Testcase 50: -fetch backward 1 in c4; ---Testcase 51: -fetch backward all in c4; ---Testcase 52: -fetch backward 1 in c4; ---Testcase 53: -fetch all in c4; - -declare c5 scroll cursor for select * from int8_tbl order by q1 fetch first 2 rows with ties; ---Testcase 54: -fetch all in c5; ---Testcase 55: -fetch 1 in c5; ---Testcase 56: -fetch backward 1 in c5; ---Testcase 57: -fetch backward 1 in c5; ---Testcase 58: -fetch all in c5; ---Testcase 59: -fetch backward all in c5; ---Testcase 60: -fetch all in c5; ---Testcase 61: -fetch backward all in c5; - -rollback; - --- Stress test for variable LIMIT in conjunction with bounded-heap sorting ---Testcase 62: -DELETE FROM INT8_TMP; ---Testcase 63: -INSERT INTO INT8_TMP SELECT q1 FROM generate_series(1,10) q1; - ---Testcase 64: -SELECT - (SELECT s.q1 - FROM (VALUES (1)) AS x, - (SELECT q1 FROM INT8_TMP as n - ORDER BY q1 LIMIT 1 OFFSET s.q1-1) AS y) AS z - FROM INT8_TMP AS s; - --- --- Test behavior of volatile and set-returning functions in conjunction --- with ORDER BY and LIMIT. --- - ---Testcase 65: -create temp sequence testseq; - ---Testcase 15: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10; - ---Testcase 16: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10; - ---Testcase 90: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10 offset 5; - ---Testcase 91: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 limit 10 offset 5; - ---Testcase 17: -select currval('testseq'); - ---Testcase 92: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10; - ---Testcase 93: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10; - - ---Testcase 94: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10 offset 5; - ---Testcase 95: -select unique1, unique2, nextval('testseq') - from tenk1 order by unique2 desc limit 10 offset 5; - ---Testcase 96: -select currval('testseq'); - ---Testcase 18: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10; - ---Testcase 19: -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10; - ---Testcase 97: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10 offset 5; - ---Testcase 98: -select unique1, unique2, nextval('testseq') - from tenk1 order by tenthous limit 10 offset 5; - ---Testcase 20: -select currval('testseq'); - --- test for limit and offset when querying table and foreign table inherited ---Testcase 99: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10; - ---Testcase 100: -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10; - --- when querying regular tables with inherited tables, only limit is pushed-down when no offset is specified ---Testcase 101: -explain (verbose, costs off) -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10 offset 5; - ---Testcase 102: -select unique1, unique2, nextval('testseq') - from parent_table order by tenthous limit 10 offset 5; - ---Testcase 103: -select currval('testseq'); - ---Testcase 21: -explain (verbose, costs off) -select unique1, unique2, generate_series(1,10) - from tenk1 order by unique2 limit 7; - ---Testcase 22: -select unique1, unique2, generate_series(1,10) - from tenk1 order by unique2 limit 7; - ---Testcase 23: -explain (verbose, costs off) -select unique1, unique2, generate_series(1,10) - from tenk1 order by tenthous limit 7; - ---Testcase 24: -select unique1, unique2, generate_series(1,10) - from tenk1 order by tenthous limit 7; - --- use of random() is to keep planner from folding the expressions together ---Testcase 66: -DELETE FROM INT8_TMP; ---Testcase 67: -INSERT INTO INT8_TMP VALUES (generate_series(0,2), generate_series((random()*.1)::int,2)); ---Testcase 68: -explain (verbose, costs off) -select q1, q2 from int8_tmp; - ---Testcase 69: -select q1, q2 from int8_tmp; - ---Testcase 70: -explain (verbose, costs off) -select q1, q2 from int8_tmp order by q2 desc; - ---Testcase 71: -select q1, q2 from int8_tmp order by q2 desc; - --- test for failure to set all aggregates' aggtranstype ---Testcase 25: -explain (verbose, costs off) -select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 - from tenk1 group by thousand order by thousand limit 3; - ---Testcase 26: -select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 - from tenk1 group by thousand order by thousand limit 3; - --- --- FETCH FIRST --- Check the WITH TIES clause --- - ---Testcase 72: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 2 ROW WITH TIES; - ---Testcase 73: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST ROWS WITH TIES; - ---Testcase 74: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES; - ---Testcase 75: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 2 ROW ONLY; - --- should fail ---Testcase 76: -SELECT ''::text AS two, unique1, unique2, stringu1 - FROM onek WHERE unique1 > 50 - FETCH FIRST 2 ROW WITH TIES; - --- test ruleutils ---Testcase 77: -CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; ---Testcase 78: -\d+ limit_thousand_v_1 ---Testcase 79: -CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY; ---Testcase 80: -\d+ limit_thousand_v_2 ---Testcase 81: -CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS WITH TIES; -- fails ---Testcase 82: -CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; ---Testcase 83: -\d+ limit_thousand_v_3 ---Testcase 84: -CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS ONLY; ---Testcase 85: -\d+ limit_thousand_v_4 --- leave these views - --- Clean up -DO $d$ -declare - l_rec record; -begin - for l_rec in (select foreign_table_schema, foreign_table_name - from information_schema.foreign_tables) loop - execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); - end loop; -end; -$d$; - ---Testcase 86: -DROP SERVER sqlite_svr; ---Testcase 87: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/13.12/extra/sqlite_fdw_post.sql b/sql/13.12/extra/sqlite_fdw_post.sql deleted file mode 100644 index 62073513..00000000 --- a/sql/13.12/extra/sqlite_fdw_post.sql +++ /dev/null @@ -1,3268 +0,0 @@ --- =================================================================== --- create FDW objects --- =================================================================== - ---Testcase 483: -CREATE EXTENSION sqlite_fdw; - -DO $d$ - BEGIN - EXECUTE $$CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - EXECUTE $$CREATE SERVER sqlite_svr2 FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; - ---Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; ---Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; - --- =================================================================== --- create objects used through FDW sqlite server --- =================================================================== ---Testcase 486: -CREATE SCHEMA "S 1"; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO "S 1"; - ---Testcase 1: -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10, - 'foo' - FROM generate_series(1, 1000) id; ---Testcase 2: -INSERT INTO "S 1"."T 2" - SELECT id, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 3: -INSERT INTO "S 1"."T 3" - SELECT id, - id + 1, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 487: -DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests ---Testcase 4: -INSERT INTO "S 1"."T 4" - SELECT id, - id + 1, - 'AAA' || to_char(id, 'FM000') - FROM generate_series(1, 100) id; ---Testcase 488: -DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests - -/*ANALYZE "S 1"."T 1"; -ANALYZE "S 1"."T 2"; -ANALYZE "S 1"."T 3"; -ANALYZE "S 1"."T 4";*/ - --- =================================================================== --- create foreign tables --- =================================================================== ---Testcase 489: -CREATE FOREIGN TABLE ft1 ( - c0 int, - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_svr; -ALTER FOREIGN TABLE ft1 DROP COLUMN c0; - ---Testcase 490: -CREATE FOREIGN TABLE ft2 ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - cx int, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft2', - c8 text -) SERVER sqlite_svr; -ALTER FOREIGN TABLE ft2 DROP COLUMN cx; - ---Testcase 491: -CREATE FOREIGN TABLE ft4 ( - c1 int NOT NULL, - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr OPTIONS (table 'T 3'); - ---Testcase 492: -CREATE FOREIGN TABLE ft5 ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr OPTIONS (table 'T 4'); - ---Testcase 493: -CREATE FOREIGN TABLE ft6 ( - c1 int NOT NULL, - c2 int NOT NULL, - c3 text -) SERVER sqlite_svr2 OPTIONS (table 'T 4'); - -ALTER FOREIGN TABLE ft1 OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft2 OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); -ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); ---Testcase 5: -\det+ - --- Test that alteration of server options causes reconnection --- Remote's errors might be non-English, so hide them to ensure stable results -\set VERBOSITY terse ---Testcase 6: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work -ALTER SERVER sqlite_svr OPTIONS (SET database 'no such database'); ---Testcase 7: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail -DO $d$ - BEGIN - EXECUTE $$ALTER SERVER sqlite_svr - OPTIONS (SET database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; ---Testcase 8: -SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again -\set VERBOSITY default - --- Now we should be able to run ANALYZE. --- To exercise multiple code paths, we use local stats on ft1 --- and remote-estimate mode on ft2. ---ANALYZE ft1; ---ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true'); - --- =================================================================== --- simple queries --- =================================================================== --- single table without alias ---Testcase 9: -EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; ---Testcase 10: -SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; --- single table with alias - also test that tableoid sort is not pushed to remote side ---Testcase 11: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; ---Testcase 12: -SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; --- whole-row reference ---Testcase 13: -EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; ---Testcase 14: -SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; --- empty result ---Testcase 15: -SELECT * FROM ft1 WHERE false; --- with WHERE clause ---Testcase 16: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; ---Testcase 17: -SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; --- with FOR UPDATE/SHARE ---Testcase 18: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; ---Testcase 19: -SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; ---Testcase 20: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; ---Testcase 21: -SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; --- aggregate ---Testcase 22: -SELECT COUNT(*) FROM ft1 t1; --- subquery ---Testcase 23: -SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1; --- subquery+MAX ---Testcase 24: -SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1; --- used in CTE ---Testcase 25: -WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1; --- fixed values ---Testcase 26: -SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1; --- Test forcing the remote server to produce sorted data for a merge join. -SET enable_hashjoin TO false; -SET enable_nestloop TO false; --- inner join; expressions in the clauses appear in the equivalence class list ---Testcase 27: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; ---Testcase 28: -SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; --- outer join; expressions in the clauses do not appear in equivalence class --- list but no output change as compared to the previous query ---Testcase 29: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; ---Testcase 30: -SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; --- A join between local table and foreign join. ORDER BY clause is added to the --- foreign join so that the local table can be joined using merge join strategy. ---Testcase 31: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; ---Testcase 32: -SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; --- Test similar to above, except that the full join prevents any equivalence --- classes from being merged. This produces single relation equivalence classes --- included in join restrictions. ---Testcase 33: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; ---Testcase 34: -SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; --- Test similar to above with all full outer joins ---Testcase 35: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; ---Testcase 36: -SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; -RESET enable_hashjoin; -RESET enable_nestloop; - --- =================================================================== --- WHERE with remotely-executable conditions --- =================================================================== ---Testcase 37: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const ---Testcase 38: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr ---Testcase 39: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL; -- NullTest ---Testcase 40: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; -- NullTest ---Testcase 41: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr ---Testcase 42: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) ---Testcase 43: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r) ---Testcase 44: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr ---Testcase 45: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr ---Testcase 46: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef ---Testcase 47: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars ---Testcase 48: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote --- parameterized remote path for foreign table ---Testcase 49: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; ---Testcase 50: -SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2; - --- check both safe and unsafe join conditions ---Testcase 51: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 a, ft2 b - WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); ---Testcase 52: -SELECT * FROM ft2 a, ft2 b -WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); --- bug before 9.3.5 due to sloppy handling of remote-estimate parameters ---Testcase 53: -SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5)); ---Testcase 54: -SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5)); --- we should not push order by clause with volatile expressions or unsafe --- collations ---Testcase 55: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 ORDER BY ft2.c1, random(); ---Testcase 56: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C"; - --- user-defined operator/function ---Testcase 494: -CREATE FUNCTION sqlite_fdw_abs(int) RETURNS int AS $$ -BEGIN -RETURN abs($1); -END -$$ LANGUAGE plpgsql IMMUTABLE; ---Testcase 495: -CREATE OPERATOR === ( - LEFTARG = int, - RIGHTARG = int, - PROCEDURE = int4eq, - COMMUTATOR = === -); - --- built-in operators and functions can be shipped for remote execution ---Testcase 57: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); ---Testcase 58: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); ---Testcase 59: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; ---Testcase 60: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; - --- by default, user-defined ones cannot ---Testcase 61: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); ---Testcase 62: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); ---Testcase 63: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; ---Testcase 64: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - --- ORDER BY can be shipped, though ---Testcase 496: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; ---Testcase 497: -SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - --- but let's put them in an extension ... -ALTER EXTENSION sqlite_fdw ADD FUNCTION sqlite_fdw_abs(int); -ALTER EXTENSION sqlite_fdw ADD OPERATOR === (int, int); ---ALTER SERVER sqlite_svr2 OPTIONS (ADD extensions 'sqlite_fdw'); - --- ... now they can be shipped ---Testcase 498: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); ---Testcase 499: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); ---Testcase 500: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; ---Testcase 501: -SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; - --- and both ORDER BY and LIMIT can be shipped ---Testcase 502: -EXPLAIN (VERBOSE, COSTS OFF) - SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; ---Testcase 503: -SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; - --- =================================================================== --- JOIN queries --- =================================================================== --- Analyze ft4 and ft5 so that we have better statistics. These tables do not --- have use_remote_estimate set. ---ANALYZE ft4; ---ANALYZE ft5; - --- join two tables ---Testcase 65: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; ---Testcase 66: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; --- join three tables ---Testcase 67: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; ---Testcase 68: -SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; --- left outer join ---Testcase 69: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; ---Testcase 70: -SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; --- left outer join three tables ---Testcase 71: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 72: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; --- left outer join + placement of clauses. --- clauses within the nullable side are not pulled up, but top level clause on --- non-nullable side is pushed into non-nullable side ---Testcase 73: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; ---Testcase 74: -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; --- clauses within the nullable side are not pulled up, but the top level clause --- on nullable side is not pushed down into nullable side ---Testcase 75: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) - WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; ---Testcase 76: -SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) - WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; --- right outer join ---Testcase 77: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; ---Testcase 78: -SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; --- right outer join three tables ---Testcase 79: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 80: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; --- full outer join ---Testcase 81: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; ---Testcase 82: -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; --- full outer join with restrictions on the joining relations --- a. the joining relations are both base relations ---Testcase 83: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; ---Testcase 84: -SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; ---Testcase 85: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; ---Testcase 86: -SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; --- b. one of the joining relations is a base relation and the other is a join --- relation ---Testcase 87: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; ---Testcase 88: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; --- c. test deparsing the remote query as nested subqueries ---Testcase 89: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; ---Testcase 90: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; --- d. test deparsing rowmarked relations as subqueries ---Testcase 91: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; ---Testcase 92: -SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; --- full outer join + inner join ---Testcase 93: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; ---Testcase 94: -SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; --- full outer join three tables ---Testcase 95: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 96: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; --- full outer join + right outer join ---Testcase 97: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 98: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; --- right outer join + full outer join ---Testcase 99: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 100: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; --- full outer join + left outer join ---Testcase 101: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 102: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; --- left outer join + full outer join ---Testcase 103: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 104: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; --- right outer join + left outer join ---Testcase 105: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 106: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; --- left outer join + right outer join ---Testcase 107: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; ---Testcase 108: -SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; --- full outer join + WHERE clause, only matched rows ---Testcase 109: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; ---Testcase 110: -SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; --- full outer join + WHERE clause with shippable extensions set ---Testcase 504: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; ---ALTER SERVER sqlite_svr2 OPTIONS (DROP extensions); --- full outer join + WHERE clause with shippable extensions not set ---Testcase 505: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; -ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --- join two tables with FOR UPDATE clause --- tests whole-row reference for row marks ---Testcase 111: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; ---Testcase 112: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; ---Testcase 113: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; ---Testcase 114: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; --- join two tables with FOR SHARE clause ---Testcase 115: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; ---Testcase 116: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; ---Testcase 117: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; ---Testcase 118: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; --- join in CTE ---Testcase 119: -EXPLAIN (VERBOSE, COSTS OFF) -WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; ---Testcase 120: -WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; --- ctid with whole-row reference ---Testcase 121: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; --- SEMI JOIN, not pushed down ---Testcase 122: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; ---Testcase 123: -SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; --- ANTI JOIN, not pushed down ---Testcase 124: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; ---Testcase 125: -SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; --- CROSS JOIN can be pushed down ---Testcase 126: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; ---Testcase 127: -SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; --- different server, not pushed down. No result expected. ---Testcase 128: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; ---Testcase 129: -SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; --- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS --- JOIN since c8 in both tables has same value. ---Testcase 130: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; ---Testcase 131: -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; --- unsafe conditions on one side (c8 has a UDT), not pushed down. ---Testcase 132: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; ---Testcase 133: -SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; --- join where unsafe to pushdown condition in WHERE clause has a column not --- in the SELECT clause. In this test unsafe clause needs to have column --- references from both joining sides so that the clause is not pushed down --- into one of the joining sides. ---Testcase 134: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; ---Testcase 135: -SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; --- Aggregate after UNION, for testing setrefs ---Testcase 136: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; ---Testcase 137: -SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; --- join with lateral reference ---Testcase 138: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; ---Testcase 139: -SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; - --- non-Var items in targetlist of the nullable rel of a join preventing --- push-down in some cases --- unable to push {ft1, ft2} ---Testcase 140: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; ---Testcase 141: -SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; - --- ok to push {ft1, ft2} but not {ft1, ft2, ft4} ---Testcase 142: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; ---Testcase 143: -SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; - --- join with nullable side with some columns with null values ---Testcase 144: -UPDATE ft5 SET c3 = null where c1 % 9 = 0; ---Testcase 145: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; ---Testcase 146: -SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; - --- multi-way join involving multiple merge joins --- (this case used to have EPQ-related planning problems) ---Testcase 506: -CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1)); ---Testcase 507: -INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; -ANALYZE local_tbl; -SET enable_nestloop TO false; -SET enable_hashjoin TO false; ---Testcase 147: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 - AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; ---Testcase 148: -SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 - AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 ORDER BY ft1.c1 FOR UPDATE; -RESET enable_nestloop; -RESET enable_hashjoin; ---DROP TABLE local_tbl; - --- check join pushdown in situations where multiple userids are involved ---Testcase 508: -CREATE ROLE regress_view_owner SUPERUSER; ---Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; -GRANT SELECT ON ft4 TO regress_view_owner; -GRANT SELECT ON ft5 TO regress_view_owner; - ---Testcase 510: -CREATE VIEW v4 AS SELECT * FROM ft4; ---Testcase 511: -CREATE VIEW v5 AS SELECT * FROM ft5; -ALTER VIEW v5 OWNER TO regress_view_owner; ---Testcase 149: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, different view owners ---Testcase 150: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -ALTER VIEW v4 OWNER TO regress_view_owner; ---Testcase 151: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down ---Testcase 152: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; - ---Testcase 153: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, view owner not current user ---Testcase 154: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -ALTER VIEW v4 OWNER TO CURRENT_USER; ---Testcase 155: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down ---Testcase 156: -SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -ALTER VIEW v4 OWNER TO regress_view_owner; - --- cleanup ---Testcase 512: -DROP OWNED BY regress_view_owner; ---Testcase 513: -DROP ROLE regress_view_owner; - - --- =================================================================== --- Aggregate and grouping queries --- =================================================================== - --- Simple aggregates ---Testcase 157: -explain (verbose, costs off) -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; ---Testcase 158: -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; - ---Testcase 514: -explain (verbose, costs off) -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; ---Testcase 515: -select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; - --- Aggregate is not pushed down as aggregation contains random() ---Testcase 159: -explain (verbose, costs off) -select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1; - --- Aggregate over join query ---Testcase 160: -explain (verbose, costs off) -select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; ---Testcase 161: -select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; - --- Not pushed down due to local conditions present in underneath input rel ---Testcase 162: -explain (verbose, costs off) -select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1; - --- GROUP BY clause having expressions ---Testcase 163: -explain (verbose, costs off) -select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; ---Testcase 164: -select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; - --- Aggregates in subquery are pushed down. ---Testcase 165: -explain (verbose, costs off) -select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; ---Testcase 166: -select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; - --- Aggregate is still pushed down by taking unshippable expression out ---Testcase 167: -explain (verbose, costs off) -select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; ---Testcase 168: -select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; - --- Aggregate with unshippable GROUP BY clause are not pushed ---Testcase 169: -explain (verbose, costs off) -select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1; - --- GROUP BY clause in various forms, cardinal, alias and constant expression ---Testcase 516: -explain (verbose, costs off) -select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; ---Testcase 517: -select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; - --- GROUP BY clause referring to same column multiple times --- Also, ORDER BY contains an aggregate function ---Testcase 170: -explain (verbose, costs off) -select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); ---Testcase 171: -select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); - --- Testing HAVING clause shippability ---Testcase 172: -explain (verbose, costs off) -select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; ---Testcase 173: -select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; - --- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down ---Testcase 174: -explain (verbose, costs off) -select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; ---Testcase 175: -select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; - --- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down ---Testcase 176: -explain (verbose, costs off) -select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1; - --- Remote aggregate in combination with a local Param (for the output --- of an initplan) can be trouble, per bug #15781 ---Testcase 518: -explain (verbose, costs off) -select exists(select 1 from pg_enum), sum(c1) from ft1; ---Testcase 519: -select exists(select 1 from pg_enum), sum(c1) from ft1; - ---Testcase 520: -explain (verbose, costs off) -select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; ---Testcase 521: -select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; - - --- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates - --- ORDER BY within aggregate, same column used to order ---Testcase 177: -explain (verbose, costs off) -select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; ---Testcase 178: -select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; - --- ORDER BY within aggregate, different column used to order also using DESC ---Testcase 179: -explain (verbose, costs off) -select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; ---Testcase 180: -select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; - --- DISTINCT within aggregate ---Testcase 181: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; ---Testcase 182: -select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - --- DISTINCT combined with ORDER BY within aggregate ---Testcase 183: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; ---Testcase 184: -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - ---Testcase 185: -explain (verbose, costs off) -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; ---Testcase 186: -select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; - --- FILTER within aggregate ---Testcase 187: -explain (verbose, costs off) -select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; ---Testcase 188: -select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; - --- DISTINCT, ORDER BY and FILTER within aggregate ---Testcase 189: -explain (verbose, costs off) -select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; ---Testcase 190: -select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; - --- Outer query is aggregation query ---Testcase 191: -explain (verbose, costs off) -select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; ---Testcase 192: -select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; --- Inner query is aggregation query ---Testcase 193: -explain (verbose, costs off) -select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; ---Testcase 194: -select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; - --- Aggregate not pushed down as FILTER condition is not pushable ---Testcase 195: -explain (verbose, costs off) -select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1; ---Testcase 196: -explain (verbose, costs off) -select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; - --- Ordered-sets within aggregate ---Testcase 197: -explain (verbose, costs off) -select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; ---Testcase 198: -select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; - --- Using multiple arguments within aggregates ---Testcase 199: -explain (verbose, costs off) -select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; ---Testcase 200: -select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; - --- User defined function for user defined aggregate, VARIADIC ---Testcase 522: -create function least_accum(anyelement, variadic anyarray) -returns anyelement language sql as - 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; ---Testcase 523: -create aggregate least_agg(variadic items anyarray) ( - stype = anyelement, sfunc = least_accum -); - --- Disable hash aggregation for plan stability. -set enable_hashagg to false; - --- Not pushed down due to user defined aggregate ---Testcase 524: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 group by c2 order by c2; - --- Add function and aggregate into extension ---alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray); ---alter extension postgres_fdw add aggregate least_agg(variadic items anyarray); ---alter server loopback options (set extensions 'postgres_fdw'); - --- Now aggregate will be pushed. Aggregate will display VARIADIC argument. ---Testcase 525: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; ---Testcase 526: -select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; - --- Remove function and aggregate from extension ---alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray); ---alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray); ---alter server loopback options (set extensions 'postgres_fdw'); - --- Not pushed down as we have dropped objects from extension. ---Testcase 527: -explain (verbose, costs off) -select c2, least_agg(c1) from ft1 group by c2 order by c2; - --- Cleanup -reset enable_hashagg; ---Testcase 528: -drop aggregate least_agg(variadic items anyarray); ---Testcase 529: -drop function least_accum(anyelement, variadic anyarray); - - --- Testing USING OPERATOR() in ORDER BY within aggregate. --- For this, we need user defined operators along with operator family and --- operator class. Create those and then add them in extension. Note that --- user defined objects are considered unshippable unless they are part of --- the extension. ---Testcase 530: -create operator public.<^ ( - leftarg = int4, - rightarg = int4, - procedure = int4eq -); - ---Testcase 531: -create operator public.=^ ( - leftarg = int4, - rightarg = int4, - procedure = int4lt -); - ---Testcase 532: -create operator public.>^ ( - leftarg = int4, - rightarg = int4, - procedure = int4gt -); - ---Testcase 533: -create operator family my_op_family using btree; - ---Testcase 534: -create function my_op_cmp(a int, b int) returns int as - $$begin return btint4cmp(a, b); end $$ language plpgsql; - ---Testcase 535: -create operator class my_op_class for type int using btree family my_op_family as - operator 1 public.<^, - operator 3 public.=^, - operator 5 public.>^, - function 1 my_op_cmp(int, int); - --- This will not be pushed as user defined sort operator is not part of the --- extension yet. ---Testcase 536: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - --- Update local stats on ft2 ---ANALYZE ft2; - --- Add into extension -alter extension sqlite_fdw add operator class my_op_class using btree; -alter extension sqlite_fdw add function my_op_cmp(a int, b int); -alter extension sqlite_fdw add operator family my_op_family using btree; -alter extension sqlite_fdw add operator public.<^(int, int); -alter extension sqlite_fdw add operator public.=^(int, int); -alter extension sqlite_fdw add operator public.>^(int, int); ---alter server loopback options (set extensions 'postgres_fdw'); - --- Now this will be pushed as sort operator is part of the extension. ---Testcase 537: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; ---Testcase 538: -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - --- Remove from extension -alter extension sqlite_fdw drop operator class my_op_class using btree; -alter extension sqlite_fdw drop function my_op_cmp(a int, b int); -alter extension sqlite_fdw drop operator family my_op_family using btree; -alter extension sqlite_fdw drop operator public.<^(int, int); -alter extension sqlite_fdw drop operator public.=^(int, int); -alter extension sqlite_fdw drop operator public.>^(int, int); ---alter server loopback options (set extensions 'postgres_fdw'); - --- This will not be pushed as sort operator is now removed from the extension. ---Testcase 539: -explain (verbose, costs off) -select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; - --- Cleanup ---Testcase 540: -drop operator class my_op_class using btree; ---Testcase 541: -drop function my_op_cmp(a int, b int); ---Testcase 542: -drop operator family my_op_family using btree; ---Testcase 543: -drop operator public.>^(int, int); ---Testcase 544: -drop operator public.=^(int, int); ---Testcase 545: -drop operator public.<^(int, int); - --- Input relation to aggregate push down hook is not safe to pushdown and thus --- the aggregate cannot be pushed down to foreign server. ---Testcase 201: -explain (verbose, costs off) -select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2); - --- Subquery in FROM clause having aggregate ---Testcase 202: -explain (verbose, costs off) -select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; ---Testcase 203: -select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; - --- FULL join with IS NULL check in HAVING ---Testcase 204: -explain (verbose, costs off) -select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; ---Testcase 205: -select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; - --- Aggregate over FULL join needing to deparse the joining relations as --- subqueries. ---Testcase 206: -explain (verbose, costs off) -select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); ---Testcase 207: -select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); - --- ORDER BY expression is part of the target list but not pushed down to --- foreign server. ---Testcase 208: -explain (verbose, costs off) -select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; ---Testcase 209: -select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; - --- LATERAL join, with parameterization -set enable_hashagg to false; ---Testcase 210: -explain (verbose, costs off) -select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; ---Testcase 211: -select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; -reset enable_hashagg; - --- bug #15613: bad plan for foreign table scan with lateral reference ---Testcase 546: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ref_0.c2, subq_1.* -FROM - "S 1"."T 1" AS ref_0, - LATERAL ( - SELECT ref_0."C 1" c1, subq_0.* - FROM (SELECT ref_0.c2, ref_1.c3 - FROM ft1 AS ref_1) AS subq_0 - RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) - ) AS subq_1 -WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' -ORDER BY ref_0."C 1"; - ---Testcase 547: -SELECT ref_0.c2, subq_1.* -FROM - "S 1"."T 1" AS ref_0, - LATERAL ( - SELECT ref_0."C 1" c1, subq_0.* - FROM (SELECT ref_0.c2, ref_1.c3 - FROM ft1 AS ref_1) AS subq_0 - RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) - ) AS subq_1 -WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' -ORDER BY ref_0."C 1"; - --- Check with placeHolderVars ---Testcase 212: -explain (verbose, costs off) -select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); ---Testcase 213: -select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); - - --- Not supported cases --- Grouping sets ---Testcase 214: -explain (verbose, costs off) -select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; ---Testcase 215: -select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; ---Testcase 216: -explain (verbose, costs off) -select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; ---Testcase 217: -select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; ---Testcase 218: -explain (verbose, costs off) -select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; ---Testcase 219: -select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; ---Testcase 220: -explain (verbose, costs off) -select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; ---Testcase 221: -select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; - --- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed ---Testcase 222: -explain (verbose, costs off) -select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; ---Testcase 223: -select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; - --- WindowAgg ---Testcase 224: -explain (verbose, costs off) -select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; ---Testcase 225: -select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; ---Testcase 226: -explain (verbose, costs off) -select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; ---Testcase 227: -select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; ---Testcase 228: -explain (verbose, costs off) -select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; ---Testcase 229: -select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; - - --- =================================================================== --- parameterized queries --- =================================================================== --- simple join ---Testcase 230: -PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2; ---Testcase 231: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2); ---Testcase 232: -EXECUTE st1(1, 1); ---Testcase 233: -EXECUTE st1(101, 101); --- subquery using stable function (can't be sent to remote) ---Testcase 234: -PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1; ---Testcase 235: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20); ---Testcase 236: -EXECUTE st2(10, 20); ---Testcase 237: -EXECUTE st2(101, 121); --- subquery using immutable function (can be sent to remote) ---Testcase 238: -PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1; ---Testcase 239: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20); ---Testcase 240: -EXECUTE st3(10, 20); ---Testcase 241: -EXECUTE st3(20, 30); --- custom plan should be chosen initially ---Testcase 242: -PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1; ---Testcase 243: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); ---Testcase 244: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); ---Testcase 245: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); ---Testcase 246: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); ---Testcase 247: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); --- once we try it enough times, should switch to generic plan ---Testcase 248: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); --- value of $1 should not be sent to remote ---Testcase 249: -PREPARE st5(text,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2; ---Testcase 250: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 251: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 252: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 253: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 254: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 255: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); ---Testcase 256: -EXECUTE st5('foo', 1); - --- altering FDW options requires replanning ---Testcase 257: -PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2; ---Testcase 258: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; ---Testcase 259: -PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); ---Testcase 260: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; ---Testcase 548: -INSERT INTO "S 1"."T 0" SELECT * FROM "S 1"."T 1"; -ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 0'); ---Testcase 261: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; ---Testcase 262: -EXECUTE st6; ---Testcase 263: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; -ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 1'); - ---Testcase 549: -PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; ---Testcase 550: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; ---ALTER SERVER loopback OPTIONS (DROP extensions); ---Testcase 551: -EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; ---Testcase 552: -EXECUTE st8; ---ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); --- cleanup -DEALLOCATE st1; -DEALLOCATE st2; -DEALLOCATE st3; -DEALLOCATE st4; -DEALLOCATE st5; -DEALLOCATE st6; -DEALLOCATE st7; -DEALLOCATE st8; - --- System columns, except ctid and oid, should not be sent to remote ---Testcase 264: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1; ---Testcase 265: -SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1; ---Testcase 266: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; ---Testcase 267: -SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; ---Testcase 268: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; ---Testcase 553: -SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; ---Testcase 554: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT ctid, * FROM ft1 t1 LIMIT 1; ---Testcase 271: -SELECT ctid, * FROM ft1 t1 LIMIT 1; - --- =================================================================== --- used in PL/pgSQL function --- =================================================================== ---Testcase 555: -CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$ -DECLARE - v_c1 int; -BEGIN ---Testcase 556: - SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1; - PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1; - RETURN v_c1; -END; -$$ LANGUAGE plpgsql; ---Testcase 272: -SELECT f_test(100); ---Testcase 557: -DROP FUNCTION f_test(int); - --- =================================================================== --- conversion error --- =================================================================== -ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int; ---Testcase 273: -SELECT * FROM ft1 WHERE c1 = 1; ---Testcase 274: -SELECT ft1.c1, ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; ---Testcase 275: -SELECT ft1.c1, ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; ---Testcase 276: -SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text; - --- =================================================================== --- subtransaction --- + local/remote error doesn't break cursor --- =================================================================== -BEGIN; -DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1; ---Testcase 277: -FETCH c; -SAVEPOINT s; -ERROR OUT; -- ERROR -ROLLBACK TO s; ---Testcase 278: -FETCH c; -SAVEPOINT s; ---Testcase 279: -SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR -ROLLBACK TO s; ---Testcase 280: -FETCH c; ---Testcase 281: -SELECT * FROM ft1 ORDER BY c1 LIMIT 1; -COMMIT; - --- =================================================================== --- test handling of collations --- =================================================================== ---Testcase 558: -create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10)) server sqlite_svr; - --- can be sent to remote ---Testcase 559: -explain (verbose, costs off) select * from ft3 where f1 = 'foo'; ---Testcase 560: -explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo'; ---Testcase 561: -explain (verbose, costs off) select * from ft3 where f2 = 'foo'; ---Testcase 562: -explain (verbose, costs off) select * from ft3 where f3 = 'foo'; ---Testcase 563: -explain (verbose, costs off) select * from ft3 f, loct3 l - where f.f3 = l.f3 and l.f1 = 'foo'; --- can't be sent to remote ---Testcase 564: -explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo'; ---Testcase 565: -explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C"; ---Testcase 566: -explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo'; ---Testcase 567: -explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C"; ---Testcase 568: -explain (verbose, costs off) select * from ft3 f, loct3 l - where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo'; - --- =================================================================== --- test writable foreign table stuff --- =================================================================== ---Testcase 282: -EXPLAIN (verbose, costs off) -INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; ---Testcase 283: -INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; ---Testcase 284: -INSERT INTO ft2 (c1,c2,c3) VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc'); ---Testcase 285: -SELECT * FROM ft2 WHERE c1 >= 1101; ---Testcase 286: -INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); ---Testcase 287: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down ---Testcase 288: -UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; ---Testcase 289: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; -- can be pushed down ---Testcase 290: -UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; ---Testcase 291: -SELECT * FROM ft2 WHERE c1 % 10 = 7; ---Testcase 292: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT - FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down ---Testcase 293: -UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT - FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; ---Testcase 294: -EXPLAIN (verbose, costs off) - DELETE FROM ft2 WHERE c1 % 10 = 5; -- can be pushed down ---Testcase 295: -SELECT c1, c4 FROM ft2 WHERE c1 % 10 = 5; ---Testcase 569: -DELETE FROM ft2 WHERE c1 % 10 = 5; ---Testcase 297: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down ---Testcase 298: -DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; ---Testcase 299: -SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; ---Testcase 300: -EXPLAIN (verbose, costs off) -INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); ---Testcase 301: -INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); ---Testcase 302: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; -- can be pushed down ---Testcase 303: -UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; ---Testcase 304: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 WHERE c1 = 1200; -- can be pushed down ---Testcase 305: -DELETE FROM ft2 WHERE c1 = 1200; - --- Test UPDATE/DELETE on a three-table join ---Testcase 306: -INSERT INTO ft2 (c1,c2,c3) - SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id; ---Testcase 307: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'foo' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; -- can be pushed down ---Testcase 308: -UPDATE ft2 SET c3 = 'foo' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; ---Testcase 309: -SELECT ft2, ft2.*, ft4, ft4.* - FROM ft2 INNER JOIN ft4 ON (ft2.c1 > 1200 AND ft2.c2 = ft4.c1) - INNER JOIN ft5 ON (ft4.c1 = ft5.c1); ---Testcase 310: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 - USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; -- can be pushed down ---Testcase 311: -SELECT 100 FROM ft2, ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; - ---Testcase 570: -DELETE FROM ft2 - USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; ---Testcase 312: -DELETE FROM ft2 WHERE ft2.c1 > 1200; - --- Test UPDATE with a MULTIEXPR sub-select --- (maybe someday this'll be remotely executable, but not today) ---Testcase 571: -EXPLAIN (verbose, costs off) -UPDATE ft2 AS target SET (c2, c7) = ( - SELECT c2 * 10, c7 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; ---Testcase 572: -UPDATE ft2 AS target SET (c2, c7) = ( - SELECT c2 * 10, c7 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; - ---Testcase 573: -UPDATE ft2 AS target SET (c2) = ( - SELECT c2 / 10 - FROM ft2 AS src - WHERE target.c1 = src.c1 -) WHERE c1 > 1100; - --- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing --- user-defined operators/functions ---ALTER SERVER loopback OPTIONS (DROP extensions); ---Testcase 574: -INSERT INTO ft2 (c1,c2,c3) - SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id; ---Testcase 575: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; -- can't be pushed down ---Testcase 576: -UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; ---Testcase 577: -SELECT * FROM ft2 WHERE sqlite_fdw_abs(c1) > 2000; ---Testcase 578: -EXPLAIN (verbose, costs off) -UPDATE ft2 SET c3 = 'baz' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; -- can't be pushed down ---Testcase 579: -UPDATE ft2 SET c3 = 'baz' - FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; ---Testcase 580: -SELECT ft2.*, ft4.*, ft5.* - FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; - ---Testcase 581: -EXPLAIN (verbose, costs off) -DELETE FROM ft2 - USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down - ---Testcase 582: -SELECT ft2.c1, ft2.c2, ft2.c3 FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down - ---Testcase 583: -DELETE FROM ft2 - USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) - WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; - ---Testcase 584: -DELETE FROM ft2 WHERE ft2.c1 > 2000; ---ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); - --- Test that trigger on remote table works as expected ---Testcase 585: -CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$ -BEGIN - NEW.c3 = NEW.c3 || '_trig_update'; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; ---Testcase 586: -CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE - ON ft2 FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG(); - ---Testcase 313: -INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff'); ---Testcase 314: -SELECT * FROM ft2 WHERE c1 = 1208; ---Testcase 315: -INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;'); ---Testcase 316: -SELECT * FROM ft2 WHERE c1 = 1218; ---Testcase 317: -UPDATE ft2 SET c2 = c2 + 600, c3 = c3 WHERE c1 % 10 = 8 AND c1 < 1200; ---Testcase 318: -SELECT * FROM ft2 WHERE c1 % 10 = 8 AND c1 < 1200; - --- Test errors thrown on remote side during update --- create table in the remote server with check contraint ---Testcase 738: -CREATE FOREIGN TABLE ft1_constraint ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_svr OPTIONS (table 't1_constraint'); ---Testcase 747: -INSERT INTO ft1_constraint SELECT * FROM ft1 ON CONFLICT DO NOTHING; --- c2 must be greater than or equal to 0, so this case is ignored. ---Testcase 754: -INSERT INTO ft1_constraint(c1, c2) VALUES (2222, -2) ON CONFLICT DO NOTHING; -- ignore, do nothing ---Testcase 755: -SELECT c1, c2 FROM ft1_constraint WHERE c1 = 2222 or c2 = -2; -- empty result ---Testcase 748: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; ---Testcase 749: -ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; ---Testcase 319: -INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key ---Testcase 320: -INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported ---Testcase 321: -INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported ---Testcase 743: -INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive ---Testcase 744: -UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive ---Testcase 750: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_constraint; ---Testcase 751: -ALTER FOREIGN TABLE ft1_org RENAME TO ft1; - --- Test savepoint/rollback behavior ---Testcase 322: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; ---Testcase 323: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; -begin; ---Testcase 324: -update ft2 set c2 = 42 where c2 = 0; ---Testcase 325: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -savepoint s1; ---Testcase 326: -update ft2 set c2 = 44 where c2 = 4; ---Testcase 327: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -release savepoint s1; ---Testcase 328: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -savepoint s2; ---Testcase 329: -update ft2 set c2 = 46 where c2 = 6; ---Testcase 330: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -rollback to savepoint s2; ---Testcase 331: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -release savepoint s2; ---Testcase 332: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -savepoint s3; ---Testcase 333: ---skip, does not support CHECK ---update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side -rollback to savepoint s3; ---Testcase 334: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; -release savepoint s3; ---Testcase 335: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; --- none of the above is committed yet remotely ---Testcase 336: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; -commit; ---Testcase 337: -select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; ---Testcase 338: -select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; - ---VACUUM ANALYZE "S 1"."T 1"; - --- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs --- FIRST behavior here. --- ORDER BY DESC NULLS LAST options ---Testcase 339: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; ---Testcase 340: -SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; --- ORDER BY DESC NULLS FIRST options ---Testcase 341: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; ---Testcase 342: -SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; --- ORDER BY ASC NULLS FIRST options ---Testcase 343: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; ---Testcase 344: -SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; - --- =================================================================== --- test check constraints --- =================================================================== ---Testcase 752: -ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; ---Testcase 753: -ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; --- Consistent check constraints provide consistent results -ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0); ---Testcase 587: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; ---Testcase 588: -SELECT count(*) FROM ft1 WHERE c2 < 0; -SET constraint_exclusion = 'on'; ---Testcase 589: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; ---Testcase 590: -SELECT count(*) FROM ft1 WHERE c2 < 0; -RESET constraint_exclusion; --- check constraint is enforced on the remote side, not locally ---Testcase 745: -INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive ---Testcase 746: -UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive -ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive; - --- But inconsistent check constraints provide inconsistent results -ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0); ---Testcase 591: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; ---Testcase 592: -SELECT count(*) FROM ft1 WHERE c2 >= 0; -SET constraint_exclusion = 'on'; ---Testcase 593: -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; ---Testcase 594: -SELECT count(*) FROM ft1 WHERE c2 >= 0; -RESET constraint_exclusion; --- local check constraint is not actually enforced ---Testcase 595: -INSERT INTO ft1(c1, c2) VALUES(1111, 2); ---Testcase 596: -UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1; -ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative; - --- =================================================================== --- test WITH CHECK OPTION constraints --- =================================================================== ---Testcase 597: -CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql; - ---Testcase 598: -CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) - SERVER sqlite_svr; ---Testcase 599: -CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); ---Testcase 600: -CREATE VIEW rw_view AS SELECT * FROM foreign_tbl - WHERE a < b WITH CHECK OPTION; ---Testcase 601: -\d+ rw_view - ---Testcase 345: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 5); ---Testcase 602: -INSERT INTO rw_view VALUES (0, 5); -- should fail ---Testcase 603: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 15); ---Testcase 604: -INSERT INTO rw_view VALUES (0, 15); -- error ---Testcase 605: -SELECT * FROM foreign_tbl; - ---Testcase 606: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 5; ---Testcase 607: -UPDATE rw_view SET b = b + 5; -- should fail ---Testcase 608: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 15; ---Testcase 609: -UPDATE rw_view SET b = b + 15; -- ok ---Testcase 610: -SELECT * FROM foreign_tbl; - ---Testcase 611: -DROP FOREIGN TABLE foreign_tbl CASCADE; ---Testcase 612: -DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; - --- test WCO for partitions - ---Testcase 613: -CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) - SERVER sqlite_svr; ---Testcase 614: -CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); - ---Testcase 615: -CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a); -ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); - ---Testcase 616: -CREATE VIEW rw_view AS SELECT * FROM parent_tbl - WHERE a < b WITH CHECK OPTION; ---Testcase 617: -\d+ rw_view - ---Testcase 618: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 5); ---Testcase 619: -INSERT INTO rw_view VALUES (0, 5); -- should fail ---Testcase 620: -EXPLAIN (VERBOSE, COSTS OFF) -INSERT INTO rw_view VALUES (0, 15); ---Testcase 621: -INSERT INTO rw_view VALUES (0, 15); -- ok ---Testcase 622: -SELECT * FROM foreign_tbl; - ---Testcase 623: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 5; ---Testcase 624: -UPDATE rw_view SET b = b + 5; -- should fail ---Testcase 625: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE rw_view SET b = b + 15; ---Testcase 626: -UPDATE rw_view SET b = b + 15; -- ok ---Testcase 627: -SELECT * FROM foreign_tbl; - ---Testcase 628: -DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; ---Testcase 629: -DROP FOREIGN TABLE foreign_tbl CASCADE; ---Testcase 630: -DROP TABLE parent_tbl CASCADE; - ---Testcase 631: -DROP FUNCTION row_before_insupd_trigfunc; - --- =================================================================== --- test serial columns (ie, sequence-based defaults) --- =================================================================== ---Testcase 632: -create foreign table loc1 (f1 serial, f2 text, id integer options (key 'true')) - server sqlite_svr; ---Testcase 633: -create foreign table rem1 (f1 serial, f2 text, id integer options (key 'true')) - server sqlite_svr options(table 'loc1'); ---Testcase 352: -select pg_catalog.setval('rem1_f1_seq', 10, false); ---Testcase 353: -insert into loc1(f2) values('hi'); ---Testcase 634: -insert into rem1(f2) values('hi remote'); ---Testcase 354: -insert into loc1(f2) values('bye'); ---Testcase 635: -insert into rem1(f2) values('bye remote'); ---Testcase 355: -select f1, f2 from loc1; ---Testcase 636: -select f1, f2 from rem1; - --- =================================================================== --- test generated columns --- =================================================================== ---Testcase 637: -create foreign table grem1 ( - a int options (key 'true'), - b int generated always as (a * 2) stored) - server sqlite_svr; ---Testcase 638: -insert into grem1 (a) values (1), (2); ---Testcase 639: -update grem1 set a = 22 where a = 2; ---Testcase 640: -select * from grem1; - --- =================================================================== --- test local triggers --- =================================================================== - --- Trigger functions "borrowed" from triggers regress test. ---Testcase 641: -CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$ -BEGIN - RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %', - TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END;$$; - ---Testcase 642: -CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 643: -CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); - ---Testcase 644: -CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger -LANGUAGE plpgsql AS $$ - -declare - oldnew text[]; - relid text; - argstr text; -begin - - relid := TG_relid::regclass; - argstr := ''; - for i in 0 .. TG_nargs - 1 loop - if i > 0 then - argstr := argstr || ', '; - end if; - argstr := argstr || TG_argv[i]; - end loop; - - RAISE NOTICE '%(%) % % % ON %', - tg_name, argstr, TG_when, TG_level, TG_OP, relid; - oldnew := '{}'::text[]; - if TG_OP != 'INSERT' then - oldnew := array_append(oldnew, format('OLD: %s', OLD)); - end if; - - if TG_OP != 'DELETE' then - oldnew := array_append(oldnew, format('NEW: %s', NEW)); - end if; - - RAISE NOTICE '%', array_to_string(oldnew, ','); - - if TG_OP = 'DELETE' then - return OLD; - else - return NEW; - end if; -end; -$$; - --- Test basic functionality ---Testcase 645: -CREATE TRIGGER trig_row_before -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 646: -CREATE TRIGGER trig_row_after -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 356: -delete from rem1; ---Testcase 357: -insert into rem1 values(1,'insert'); ---Testcase 358: -update rem1 set f2 = 'update' where f1 = 1; ---Testcase 359: -update rem1 set f2 = f2 || f2; - - --- cleanup ---Testcase 647: -DROP TRIGGER trig_row_before ON rem1; ---Testcase 648: -DROP TRIGGER trig_row_after ON rem1; ---Testcase 649: -DROP TRIGGER trig_stmt_before ON rem1; ---Testcase 650: -DROP TRIGGER trig_stmt_after ON rem1; - ---Testcase 360: -DELETE from rem1; - --- Test multiple AFTER ROW triggers on a foreign table ---Testcase 651: -CREATE TRIGGER trig_row_after1 -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 652: -CREATE TRIGGER trig_row_after2 -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 653: -insert into rem1 values(1,'insert'); ---Testcase 654: -update rem1 set f2 = 'update' where f1 = 1; ---Testcase 655: -update rem1 set f2 = f2 || f2; ---Testcase 656: -delete from rem1; - --- cleanup ---Testcase 657: -DROP TRIGGER trig_row_after1 ON rem1; ---Testcase 658: -DROP TRIGGER trig_row_after2 ON rem1; - --- Test WHEN conditions - ---Testcase 659: -CREATE TRIGGER trig_row_before_insupd -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW -WHEN (NEW.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 660: -CREATE TRIGGER trig_row_after_insupd -AFTER INSERT OR UPDATE ON rem1 -FOR EACH ROW -WHEN (NEW.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); - --- Insert or update not matching: nothing happens ---Testcase 363: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 364: -UPDATE rem1 set f2 = 'test'; - --- Insert or update matching: triggers are fired ---Testcase 365: -INSERT INTO rem1 values(2, 'update'); ---Testcase 366: -UPDATE rem1 set f2 = 'update update' where f1 = '2'; - ---Testcase 661: -CREATE TRIGGER trig_row_before_delete -BEFORE DELETE ON rem1 -FOR EACH ROW -WHEN (OLD.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 662: -CREATE TRIGGER trig_row_after_delete -AFTER DELETE ON rem1 -FOR EACH ROW -WHEN (OLD.f2 like '%update%') -EXECUTE PROCEDURE trigger_data(23,'skidoo'); - --- Trigger is fired for f1=2, not for f1=1 ---Testcase 369: -DELETE FROM rem1; - --- cleanup ---Testcase 663: -DROP TRIGGER trig_row_before_insupd ON rem1; ---Testcase 664: -DROP TRIGGER trig_row_after_insupd ON rem1; ---Testcase 665: -DROP TRIGGER trig_row_before_delete ON rem1; ---Testcase 666: -DROP TRIGGER trig_row_after_delete ON rem1; - - --- Test various RETURN statements in BEFORE triggers. - ---Testcase 667: -CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ - BEGIN - NEW.f2 := NEW.f2 || ' triggered !'; - RETURN NEW; - END -$$ language plpgsql; - ---Testcase 668: -CREATE TRIGGER trig_row_before_insupd -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); - --- The new values should have 'triggered' appended ---Testcase 370: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 371: -SELECT f1, f2 from rem1; ---Testcase 372: -INSERT INTO rem1 values(2, 'insert'); ---Testcase 373: -SELECT f1, f2 from rem1; ---Testcase 374: -UPDATE rem1 set f2 = ''; ---Testcase 375: -SELECT f1, f2 from rem1; ---Testcase 376: -UPDATE rem1 set f2 = 'skidoo'; ---Testcase 377: -SELECT f1, f2 from rem1; - ---Testcase 669: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f1 = 10; -- all columns should be transmitted ---Testcase 670: -UPDATE rem1 set f1 = 10; ---Testcase 671: -SELECT f1, f2 from rem1; - ---Testcase 378: -DELETE FROM rem1; - --- Add a second trigger, to check that the changes are propagated correctly --- from trigger to trigger ---Testcase 672: -CREATE TRIGGER trig_row_before_insupd2 -BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); - ---Testcase 379: -INSERT INTO rem1 values(1, 'insert'); ---Testcase 380: -SELECT f1, f2 from rem1; ---Testcase 381: -INSERT INTO rem1 values(2, 'insert'); ---Testcase 382: -SELECT f1, f2 from rem1; ---Testcase 383: -UPDATE rem1 set f2 = ''; ---Testcase 384: -SELECT f1, f2 from rem1; ---Testcase 385: -UPDATE rem1 set f2 = 'skidoo'; ---Testcase 386: -SELECT f1, f2 from rem1; - ---Testcase 673: -DROP TRIGGER trig_row_before_insupd ON rem1; ---Testcase 674: -DROP TRIGGER trig_row_before_insupd2 ON rem1; - ---Testcase 387: -DELETE from rem1; - ---Testcase 388: -INSERT INTO rem1 VALUES (1, 'test'); - --- Test with a trigger returning NULL ---Testcase 675: -CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$ - BEGIN - RETURN NULL; - END -$$ language plpgsql; - ---Testcase 676: -CREATE TRIGGER trig_null -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_null(); - --- Nothing should have changed. ---Testcase 389: -INSERT INTO rem1 VALUES (2, 'test2'); - ---Testcase 390: -SELECT f1, f2 from rem1; - ---Testcase 391: -UPDATE rem1 SET f2 = 'test2'; - ---Testcase 392: -SELECT f1, f2 from rem1; - ---Testcase 393: -DELETE from rem1; - ---Testcase 394: -SELECT f1, f2 from rem1; - ---Testcase 677: -DROP TRIGGER trig_null ON rem1; ---Testcase 395: -DELETE from rem1; - --- Test a combination of local and remote triggers ---Testcase 678: -CREATE TRIGGER trig_row_before -BEFORE INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 679: -CREATE TRIGGER trig_row_after -AFTER INSERT OR UPDATE OR DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 680: -CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); - ---Testcase 681: -INSERT INTO rem1(f2) VALUES ('test'); ---Testcase 682: -UPDATE rem1 SET f2 = 'testo'; - --- Test returning a system attribute ---Testcase 683: -INSERT INTO rem1(f2) VALUES ('test'); - --- cleanup ---Testcase 684: -DROP TRIGGER trig_row_before ON rem1; ---Testcase 685: -DROP TRIGGER trig_row_after ON rem1; ---Testcase 686: -DROP TRIGGER trig_local_before ON rem1; - - --- Test direct foreign table modification functionality - --- Test with statement-level triggers ---Testcase 687: -CREATE TRIGGER trig_stmt_before - BEFORE DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 396: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 397: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 688: -DROP TRIGGER trig_stmt_before ON rem1; - ---Testcase 689: -CREATE TRIGGER trig_stmt_after - AFTER DELETE OR INSERT OR UPDATE ON rem1 - FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); ---Testcase 398: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 399: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 690: -DROP TRIGGER trig_stmt_after ON rem1; - --- Test with row-level ON INSERT triggers ---Testcase 691: -CREATE TRIGGER trig_row_before_insert -BEFORE INSERT ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 400: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 401: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 692: -DROP TRIGGER trig_row_before_insert ON rem1; - ---Testcase 693: -CREATE TRIGGER trig_row_after_insert -AFTER INSERT ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 402: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 403: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 694: -DROP TRIGGER trig_row_after_insert ON rem1; - --- Test with row-level ON UPDATE triggers ---Testcase 695: -CREATE TRIGGER trig_row_before_update -BEFORE UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 404: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can't be pushed down ---Testcase 405: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 696: -DROP TRIGGER trig_row_before_update ON rem1; - ---Testcase 697: -CREATE TRIGGER trig_row_after_update -AFTER UPDATE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 406: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can't be pushed down ---Testcase 407: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can be pushed down ---Testcase 698: -DROP TRIGGER trig_row_after_update ON rem1; - --- Test with row-level ON DELETE triggers ---Testcase 699: -CREATE TRIGGER trig_row_before_delete -BEFORE DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 408: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 409: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can't be pushed down ---Testcase 700: -DROP TRIGGER trig_row_before_delete ON rem1; - ---Testcase 701: -CREATE TRIGGER trig_row_after_delete -AFTER DELETE ON rem1 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); ---Testcase 410: -EXPLAIN (verbose, costs off) -UPDATE rem1 set f2 = ''; -- can be pushed down ---Testcase 411: -EXPLAIN (verbose, costs off) -DELETE FROM rem1; -- can't be pushed down ---Testcase 702: -DROP TRIGGER trig_row_after_delete ON rem1; - --- =================================================================== --- test inheritance features --- =================================================================== - ---Testcase 703: -CREATE TABLE a (aa TEXT); -ALTER TABLE a SET (autovacuum_enabled = 'false'); ---Testcase 704: -CREATE FOREIGN TABLE b (aa TEXT OPTIONS (key 'true'), bb TEXT) INHERITS (a) - SERVER sqlite_svr OPTIONS (table 'loct'); - ---Testcase 412: -INSERT INTO a(aa) VALUES('aaa'); ---Testcase 413: -INSERT INTO a(aa) VALUES('aaaa'); ---Testcase 414: -INSERT INTO a(aa) VALUES('aaaaa'); - ---Testcase 415: -INSERT INTO b(aa) VALUES('bbb'); ---Testcase 416: -INSERT INTO b(aa) VALUES('bbbb'); ---Testcase 417: -INSERT INTO b(aa) VALUES('bbbbb'); - ---Testcase 418: -SELECT tableoid::regclass, * FROM a; ---Testcase 419: -SELECT tableoid::regclass, * FROM b; ---Testcase 420: -SELECT tableoid::regclass, * FROM ONLY a; - ---Testcase 421: -UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%'; - ---Testcase 422: -SELECT tableoid::regclass, * FROM a; ---Testcase 423: -SELECT tableoid::regclass, * FROM b; ---Testcase 424: -SELECT tableoid::regclass, * FROM ONLY a; - ---Testcase 425: -UPDATE b SET aa = 'new'; - ---Testcase 426: -SELECT tableoid::regclass, * FROM a; ---Testcase 427: -SELECT tableoid::regclass, * FROM b; ---Testcase 428: -SELECT tableoid::regclass, * FROM ONLY a; - ---Testcase 429: -UPDATE a SET aa = 'newtoo'; - ---Testcase 430: -SELECT tableoid::regclass, * FROM a; ---Testcase 431: -SELECT tableoid::regclass, * FROM b; ---Testcase 432: -SELECT tableoid::regclass, * FROM ONLY a; - ---Testcase 433: -DELETE FROM a; - ---Testcase 434: -SELECT tableoid::regclass, * FROM a; ---Testcase 435: -SELECT tableoid::regclass, * FROM b; ---Testcase 436: -SELECT tableoid::regclass, * FROM ONLY a; - ---Testcase 705: -DROP TABLE a CASCADE; - --- Check SELECT FOR UPDATE/SHARE with an inherited source table - ---Testcase 706: -create table foo (f1 int, f2 int); ---Testcase 707: -create foreign table foo2 (f3 int OPTIONS (key 'true')) inherits (foo) - server sqlite_svr options (table 'loct1'); ---Testcase 708: -create table bar (f1 int, f2 int); ---Testcase 709: -create foreign table bar2 (f3 int OPTIONS (key 'true')) inherits (bar) - server sqlite_svr options (table 'loct2'); - -alter table foo set (autovacuum_enabled = 'false'); -alter table bar set (autovacuum_enabled = 'false'); - ---Testcase 437: -insert into foo values(1,1); ---Testcase 438: -insert into foo values(3,3); ---Testcase 439: -insert into foo2 values(2,2,2); ---Testcase 440: -insert into foo2 values(4,4,4); ---Testcase 441: -insert into bar values(1,11); ---Testcase 442: -insert into bar values(2,22); ---Testcase 443: -insert into bar values(6,66); ---Testcase 444: -insert into bar2 values(3,33,33); ---Testcase 445: -insert into bar2 values(4,44,44); ---Testcase 446: -insert into bar2 values(7,77,77); - ---Testcase 447: -explain (verbose, costs off) -select * from bar where f1 in (select f1 from foo) for update; ---Testcase 448: -select * from bar where f1 in (select f1 from foo) for update; - ---Testcase 449: -explain (verbose, costs off) -select * from bar where f1 in (select f1 from foo) for share; ---Testcase 450: -select * from bar where f1 in (select f1 from foo) for share; - --- Check UPDATE with inherited target and an inherited source table ---Testcase 451: -explain (verbose, costs off) -update bar set f2 = f2 + 100 where f1 in (select f1 from foo); ---Testcase 452: -update bar set f2 = f2 + 100 where f1 in (select f1 from foo); - ---Testcase 453: -select tableoid::regclass, * from bar order by 1,2; - --- Check UPDATE with inherited target and an appendrel subquery ---Testcase 454: -explain (verbose, costs off) -update bar set f2 = f2 + 100 -from - ( select f1 from foo union all select f1+3 from foo ) ss -where bar.f1 = ss.f1; ---Testcase 455: -update bar set f2 = f2 + 100 -from - ( select f1 from foo union all select f1+3 from foo ) ss -where bar.f1 = ss.f1; - ---Testcase 456: -select tableoid::regclass, * from bar order by 1,2; - --- Test forcing the remote server to produce sorted data for a merge join, --- but the foreign table is an inheritance child. ---truncate table loct1; ---Testcase 710: -delete from foo2; -truncate table only foo; -\set num_rows_foo 2000 ---Testcase 711: -insert into foo2 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2); ---Testcase 712: -insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2); -SET enable_hashjoin to false; -SET enable_nestloop to false; ---alter foreign table foo2 options (use_remote_estimate 'true'); ---create index i_loct1_f1 on loct1(f1); ---Testcase 713: -create index i_foo_f1 on foo(f1); -analyze foo; ---analyze loct1; --- inner join; expressions in the clauses appear in the equivalence class list ---Testcase 714: -explain (verbose, costs off) - select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; ---Testcase 715: -select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; --- outer join; expressions in the clauses do not appear in equivalence class --- list but no output change as compared to the previous query ---Testcase 716: -explain (verbose, costs off) - select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; ---Testcase 717: -select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; -RESET enable_hashjoin; -RESET enable_nestloop; - --- Test that WHERE CURRENT OF is not supported -begin; -declare c cursor for select * from bar where f1 = 7; ---Testcase 457: -fetch from c; ---Testcase 458: -update bar set f2 = null where current of c; -rollback; - ---Testcase 459: -explain (verbose, costs off) -delete from foo where f1 < 5; ---Testcase 460: -delete from foo where f1 < 5; ---Testcase 461: -explain (verbose, costs off) -update bar set f2 = f2 + 100; ---Testcase 462: -update bar set f2 = f2 + 100; ---Testcase 463: -select * from bar; - --- Test that UPDATE/DELETE with inherited target works with row-level triggers ---Testcase 718: -CREATE TRIGGER trig_row_before -BEFORE UPDATE OR DELETE ON bar2 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 719: -CREATE TRIGGER trig_row_after -AFTER UPDATE OR DELETE ON bar2 -FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); - ---Testcase 464: -explain (verbose, costs off) -update bar set f2 = f2 + 100; ---Testcase 465: -update bar set f2 = f2 + 100; - ---Testcase 466: -explain (verbose, costs off) -delete from bar where f2 < 400; ---Testcase 467: -delete from bar where f2 < 400; - --- cleanup ---Testcase 720: -drop table foo cascade; ---Testcase 721: -drop table bar cascade; - --- Test pushing down UPDATE/DELETE joins to the remote server ---Testcase 722: -create table parent (a int, b text); ---Testcase 723: -create foreign table remt1 (a int OPTIONS (key 'true'), b text) - server sqlite_svr options (table 'loct3'); ---Testcase 724: -create foreign table remt2 (a int OPTIONS (key 'true'), b text) - server sqlite_svr options (table 'loct4'); -alter foreign table remt1 inherit parent; - ---Testcase 468: -insert into remt1 values (1, 'foo'); ---Testcase 469: -insert into remt1 values (2, 'bar'); ---Testcase 470: -insert into remt2 values (1, 'foo'); ---Testcase 471: -insert into remt2 values (2, 'bar'); - ---Testcase 472: -explain (verbose, costs off) -update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; ---Testcase 473: -update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; ---Testcase 474: -select * from parent inner join remt2 on (parent.a = remt2.a); ---Testcase 475: -explain (verbose, costs off) -delete from parent using remt2 where parent.a = remt2.a; ---Testcase 476: -delete from parent using remt2 where parent.a = remt2.a; - --- cleanup ---Testcase 725: -drop foreign table remt1; ---Testcase 726: -drop foreign table remt2; ---Testcase 727: -drop table parent; - -/* --- Skip these tests, sqlite fdw does not support partition table, check constraint, copy from --- =================================================================== --- test tuple routing for foreign-table partitions --- =================================================================== - --- Test insert tuple routing -create table itrtest (a int, b text) partition by list (a); -create table loct1 (a int check (a in (1)), b text); -create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); -create table loct2 (a int check (a in (2)), b text); -create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); -alter table itrtest attach partition remp1 for values in (1); -alter table itrtest attach partition remp2 for values in (2); - -insert into itrtest values (1, 'foo'); -insert into itrtest values (1, 'bar') returning *; -insert into itrtest values (2, 'baz'); -insert into itrtest values (2, 'qux') returning *; -insert into itrtest values (1, 'test1'), (2, 'test2') returning *; - -select tableoid::regclass, * FROM itrtest; -select tableoid::regclass, * FROM remp1; -select tableoid::regclass, * FROM remp2; - -delete from itrtest; - -create unique index loct1_idx on loct1 (a); - --- DO NOTHING without an inference specification is supported -insert into itrtest values (1, 'foo') on conflict do nothing returning *; -insert into itrtest values (1, 'foo') on conflict do nothing returning *; - --- But other cases are not supported -insert into itrtest values (1, 'bar') on conflict (a) do nothing; -insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b; - -select tableoid::regclass, * FROM itrtest; - -delete from itrtest; - -drop index loct1_idx; - --- Test that remote triggers work with insert tuple routing -create function br_insert_trigfunc() returns trigger as $$ -begin - new.b := new.b || ' triggered !'; - return new; -end -$$ language plpgsql; -create trigger loct1_br_insert_trigger before insert on loct1 - for each row execute procedure br_insert_trigfunc(); -create trigger loct2_br_insert_trigger before insert on loct2 - for each row execute procedure br_insert_trigfunc(); - --- The new values are concatenated with ' triggered !' -insert into itrtest values (1, 'foo') returning *; -insert into itrtest values (2, 'qux') returning *; -insert into itrtest values (1, 'test1'), (2, 'test2') returning *; -with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result; - -drop trigger loct1_br_insert_trigger on loct1; -drop trigger loct2_br_insert_trigger on loct2; - -drop table itrtest; -drop table loct1; -drop table loct2; - --- Test update tuple routing -create table utrtest (a int, b text) partition by list (a); -create table loct (a int check (a in (1)), b text); -create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct'); -create table locp (a int check (a in (2)), b text); -alter table utrtest attach partition remp for values in (1); -alter table utrtest attach partition locp for values in (2); - -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - -select tableoid::regclass, * FROM utrtest; -select tableoid::regclass, * FROM remp; -select tableoid::regclass, * FROM locp; - --- It's not allowed to move a row from a partition that is foreign to another -update utrtest set a = 2 where b = 'foo' returning *; - --- But the reverse is allowed -update utrtest set a = 1 where b = 'qux' returning *; - -select tableoid::regclass, * FROM utrtest; -select tableoid::regclass, * FROM remp; -select tableoid::regclass, * FROM locp; - --- The executor should not let unexercised FDWs shut down -update utrtest set a = 1 where b = 'foo'; - --- Test that remote triggers work with update tuple routing -create trigger loct_br_insert_trigger before insert on loct - for each row execute procedure br_insert_trigfunc(); - -delete from utrtest; -insert into utrtest values (2, 'qux'); - --- Check case where the foreign partition is a subplan target rel -explain (verbose, costs off) -update utrtest set a = 1 where a = 1 or a = 2 returning *; --- The new values are concatenated with ' triggered !' -update utrtest set a = 1 where a = 1 or a = 2 returning *; - -delete from utrtest; -insert into utrtest values (2, 'qux'); - --- Check case where the foreign partition isn't a subplan target rel -explain (verbose, costs off) -update utrtest set a = 1 where a = 2 returning *; --- The new values are concatenated with ' triggered !' -update utrtest set a = 1 where a = 2 returning *; - -drop trigger loct_br_insert_trigger on loct; - --- We can move rows to a foreign partition that has been updated already, --- but can't move rows to a foreign partition that hasn't been updated yet - -delete from utrtest; -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - --- Test the former case: --- with a direct modification plan -explain (verbose, costs off) -update utrtest set a = 1 returning *; -update utrtest set a = 1 returning *; - -delete from utrtest; -insert into utrtest values (1, 'foo'); -insert into utrtest values (2, 'qux'); - --- with a non-direct modification plan -explain (verbose, costs off) -update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; -update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; - --- Change the definition of utrtest so that the foreign partition get updated --- after the local partition -delete from utrtest; -alter table utrtest detach partition remp; -drop foreign table remp; -alter table loct drop constraint loct_a_check; -alter table loct add check (a in (3)); -create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct'); -alter table utrtest attach partition remp for values in (3); -insert into utrtest values (2, 'qux'); -insert into utrtest values (3, 'xyzzy'); - --- Test the latter case: --- with a direct modification plan -explain (verbose, costs off) -update utrtest set a = 3 returning *; -update utrtest set a = 3 returning *; -- ERROR - --- with a non-direct modification plan -explain (verbose, costs off) -update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR - -drop table utrtest; -drop table loct; - --- Test copy tuple routing -create table ctrtest (a int, b text) partition by list (a); -create table loct1 (a int check (a in (1)), b text); -create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); -create table loct2 (a int check (a in (2)), b text); -create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); -alter table ctrtest attach partition remp1 for values in (1); -alter table ctrtest attach partition remp2 for values in (2); - -copy ctrtest from stdin; -1 foo -2 qux -\. - -select tableoid::regclass, * FROM ctrtest; -select tableoid::regclass, * FROM remp1; -select tableoid::regclass, * FROM remp2; - --- Copying into foreign partitions directly should work as well -copy remp1 from stdin; -1 bar -\. - -select tableoid::regclass, * FROM remp1; - -drop table ctrtest; -drop table loct1; -drop table loct2; - --- =================================================================== --- test COPY FROM --- =================================================================== - -create table loc2 (f1 int, f2 text); -alter table loc2 set (autovacuum_enabled = 'false'); -create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2'); - --- Test basic functionality -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -delete from rem2; - --- Test check constraints -alter table loc2 add constraint loc2_f1positive check (f1 >= 0); -alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); - --- check constraint is enforced on the remote side, not locally -copy rem2 from stdin; -1 foo -2 bar -\. -copy rem2 from stdin; -- ERROR --1 xyzzy -\. -select * from rem2; - -alter foreign table rem2 drop constraint rem2_f1positive; -alter table loc2 drop constraint loc2_f1positive; - -delete from rem2; - --- Test local triggers -create trigger trig_stmt_before before insert on rem2 - for each statement execute procedure trigger_func(); -create trigger trig_stmt_after after insert on rem2 - for each statement execute procedure trigger_func(); -create trigger trig_row_before before insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger trig_row_after after insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); - -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before on rem2; -drop trigger trig_row_after on rem2; -drop trigger trig_stmt_before on rem2; -drop trigger trig_stmt_after on rem2; - -delete from rem2; - -create trigger trig_row_before_insert before insert on rem2 - for each row execute procedure trig_row_before_insupdate(); - --- The new values are concatenated with ' triggered !' -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before_insert on rem2; - -delete from rem2; - -create trigger trig_null before insert on rem2 - for each row execute procedure trig_null(); - --- Nothing happens -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_null on rem2; - -delete from rem2; - --- Test remote triggers -create trigger trig_row_before_insert before insert on loc2 - for each row execute procedure trig_row_before_insupdate(); - --- The new values are concatenated with ' triggered !' -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_row_before_insert on loc2; - -delete from rem2; - -create trigger trig_null before insert on loc2 - for each row execute procedure trig_null(); - --- Nothing happens -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger trig_null on loc2; - -delete from rem2; - --- Test a combination of local and remote triggers -create trigger rem2_trig_row_before before insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger rem2_trig_row_after after insert on rem2 - for each row execute procedure trigger_data(23,'skidoo'); -create trigger loc2_trig_row_before_insert before insert on loc2 - for each row execute procedure trig_row_before_insupdate(); - -copy rem2 from stdin; -1 foo -2 bar -\. -select * from rem2; - -drop trigger rem2_trig_row_before on rem2; -drop trigger rem2_trig_row_after on rem2; -drop trigger loc2_trig_row_before_insert on loc2; - -delete from rem2; - --- test COPY FROM with foreign table created in the same transaction -create table loc3 (f1 int, f2 text); -begin; -create foreign table rem3 (f1 int, f2 text) - server loopback options(table_name 'loc3'); -copy rem3 from stdin; -1 foo -2 bar -\. -commit; -select * from rem3; -drop foreign table rem3; -drop table loc3; -*/ --- =================================================================== --- test IMPORT FOREIGN SCHEMA --- =================================================================== - ---Testcase 728: -CREATE SCHEMA import_dest1; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; ---Testcase 477: -\det+ import_dest1.* ---Testcase 478: -\d import_dest1.* - --- Options ---Testcase 729: -CREATE SCHEMA import_dest2; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 - OPTIONS (import_default 'true'); ---Testcase 479: -\det+ import_dest2.* ---Testcase 480: -\d import_dest2.* - --- Check LIMIT TO and EXCEPT ---Testcase 730: -CREATE SCHEMA import_dest3; -IMPORT FOREIGN SCHEMA public LIMIT TO ("T 1", loct6, nonesuch) - FROM SERVER sqlite_svr INTO import_dest3; ---Testcase 481: -\det+ import_dest3.* -IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) - FROM SERVER sqlite_svr INTO import_dest3; ---Testcase 482: -\det+ import_dest3.* - --- Assorted error cases -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO notthere; -IMPORT FOREIGN SCHEMA public FROM SERVER nowhere INTO notthere; - -/* --- Skip these test, sqlite fdw does not support fetch_size option, partition table --- Check case of a type present only on the remote server. --- We can fake this by dropping the type locally in our transaction. -CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue'); -CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors"); - -CREATE SCHEMA import_dest5; -BEGIN; -DROP TYPE "Colors" CASCADE; -IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5) - FROM SERVER loopback INTO import_dest5; -- ERROR - -ROLLBACK; - -BEGIN; - - -CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' ); - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=101']; - -ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' ); - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=101']; - -SELECT count(*) -FROM pg_foreign_server -WHERE srvname = 'fetch101' -AND srvoptions @> array['fetch_size=202']; - -CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' ); - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=30000']; - -ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000'); - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=30000']; - -SELECT COUNT(*) -FROM pg_foreign_table -WHERE ftrelid = 'table30000'::regclass -AND ftoptions @> array['fetch_size=60000']; - -ROLLBACK; - --- =================================================================== --- test partitionwise joins --- =================================================================== -SET enable_partitionwise_join=on; - -CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a); -CREATE TABLE fprt1_p1 (LIKE fprt1); -CREATE TABLE fprt1_p2 (LIKE fprt1); -ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false'); -ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false'); -INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i; -INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i; -CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250) - SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true'); -CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500) - SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2'); -ANALYZE fprt1; -ANALYZE fprt1_p1; -ANALYZE fprt1_p2; - -CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b); -CREATE TABLE fprt2_p1 (LIKE fprt2); -CREATE TABLE fprt2_p2 (LIKE fprt2); -ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false'); -ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false'); -INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i; -INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i; -CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int) - SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true'); -ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250); -CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500) - SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true'); -ANALYZE fprt2; -ANALYZE fprt2_p1; -ANALYZE fprt2_p2; - --- inner join three tables -EXPLAIN (COSTS OFF) -SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; -SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; - --- left outer join + nullable clause -EXPLAIN (VERBOSE, COSTS OFF) -SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; -SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; - --- with whole-row reference; partitionwise join does not apply -EXPLAIN (COSTS OFF) -SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; -SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; - --- join with lateral reference -EXPLAIN (COSTS OFF) -SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; -SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; - --- with PHVs, partitionwise join selected but no join pushdown -EXPLAIN (COSTS OFF) -SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; -SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; - --- test FOR UPDATE; partitionwise join does not apply -EXPLAIN (COSTS OFF) -SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; -SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; - -RESET enable_partitionwise_join; - - --- =================================================================== --- test partitionwise aggregates --- =================================================================== - -CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); - -CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); -CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); -CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); - -INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; -INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; -INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; - --- Create foreign partitions -CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); -CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');; -CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');; - -ANALYZE pagg_tab; -ANALYZE fpagg_tab_p1; -ANALYZE fpagg_tab_p2; -ANALYZE fpagg_tab_p3; - --- When GROUP BY clause matches with PARTITION KEY. --- Plan with partitionwise aggregates is disabled -SET enable_partitionwise_aggregate TO false; -EXPLAIN (COSTS OFF) -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- Plan with partitionwise aggregates is enabled -SET enable_partitionwise_aggregate TO true; -EXPLAIN (COSTS OFF) -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- Check with whole-row reference --- Should have all the columns in the target list for the given relation -EXPLAIN (VERBOSE, COSTS OFF) -SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; - --- When GROUP BY clause does not match with PARTITION KEY. -EXPLAIN (COSTS OFF) -SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; -*/ - -/* --- Skip these tests, sqlite fdw does not support nosuper user. --- =================================================================== --- access rights and superuser --- =================================================================== - --- Non-superuser cannot create a FDW without a password in the connstr -CREATE ROLE regress_nosuper NOSUPERUSER; - -GRANT USAGE ON FOREIGN DATA WRAPPER sqlite_fdw TO regress_nosuper; - -SET ROLE regress_nosuper; - -SHOW is_superuser; - --- This will be OK, we can create the FDW -DO $d$ - BEGIN - EXECUTE $$CREATE SERVER sqlite_nopw FOREIGN DATA WRAPPER sqlite_fdw - OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; - END; -$d$; - --- But creation of user mappings for non-superusers should fail -CREATE USER MAPPING FOR public SERVER sqlite_nopw; -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; - -CREATE FOREIGN TABLE ft1_nopw ( - c1 int OPTIONS (key 'true'), - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10) default 'ft1', - c8 text -) SERVER sqlite_nopw; - -ALTER FOREIGN TABLE ft1_nopw OPTIONS (table 'T 1'); -ALTER FOREIGN TABLE ft1_nopw ALTER COLUMN c1 OPTIONS (column_name 'C 1'); - -SELECT * FROM ft1_nopw LIMIT 1; - --- If we add a password to the connstr it'll fail, because we don't allow passwords --- in connstrs only in user mappings. - -DO $d$ - BEGIN - EXECUTE $$ALTER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw')$$; - END; -$d$; - --- If we add a password for our user mapping instead, we should get a different --- error because the password wasn't actually *used* when we run with trust auth. --- --- This won't work with installcheck, but neither will most of the FDW checks. - -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw'); - -SELECT * FROM ft1_nopw LIMIT 1; - --- Unpriv user cannot make the mapping passwordless -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); - - -SELECT * FROM ft1_nopw LIMIT 1; - -RESET ROLE; - --- But the superuser can -ALTER USER MAPPING FOR regress_nosuper SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); - -SET ROLE regress_nosuper; - --- Should finally work now -SELECT * FROM ft1_nopw LIMIT 1; - --- unpriv user also cannot set sslcert / sslkey on the user mapping --- first set password_required so we see the right error messages -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (SET password_required 'true'); -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslcert 'foo.crt'); -ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslkey 'foo.key'); - --- We're done with the role named after a specific user and need to check the --- changes to the public mapping. -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; - --- This will fail again as it'll resolve the user mapping for public, which --- lacks password_required=false -SELECT * FROM ft1_nopw LIMIT 1; - -RESET ROLE; - --- The user mapping for public is passwordless and lacks the password_required=false --- mapping option, but will work because the current user is a superuser. -SELECT * FROM ft1_nopw LIMIT 1; - --- cleanup -DROP USER MAPPING FOR public SERVER sqlite_nopw; -DROP OWNED BY regress_nosuper; -DROP ROLE regress_nosuper; - --- Clean-up -RESET enable_partitionwise_aggregate; -*/ --- Two-phase transactions are not supported. -BEGIN; ---Testcase 731: -SELECT count(*) FROM ft1; --- error here ---Testcase 732: -PREPARE TRANSACTION 'fdw_tpc'; -ROLLBACK; - - --- Clean-up ---Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; ---Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; ---Testcase 735: -DROP SERVER sqlite_svr CASCADE; ---Testcase 736: -DROP SERVER sqlite_svr2 CASCADE; ---Testcase 737: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/12.16/aggregate.sql b/sql/13.15/aggregate.sql similarity index 100% rename from sql/12.16/aggregate.sql rename to sql/13.15/aggregate.sql diff --git a/sql/13.12/extra/aggregates.sql b/sql/13.15/extra/aggregates.sql similarity index 97% rename from sql/13.12/extra/aggregates.sql rename to sql/13.15/extra/aggregates.sql index dc9bdcd2..a1884907 100644 --- a/sql/13.12/extra/aggregates.sql +++ b/sql/13.15/extra/aggregates.sql @@ -65,9 +65,29 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 588: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 589: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 590: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 591: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 592: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 593: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 594: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 595: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 596: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 597: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; @@ -77,7 +97,16 @@ CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqli --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; - +--Testcase 598: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 599: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 600: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 601: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 602: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: @@ -119,12 +148,12 @@ SELECT any_value(v) FROM agg_tb2; -- In 7.1, avg(float4) is computed using float8 arithmetic. --Testcase 3: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 678: +--Testcase 603: SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; --Testcase 4: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 679: +--Testcase 604: SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; @@ -134,11 +163,11 @@ SELECT sum(four) AS sum_1500 FROM onek; SELECT sum(a) AS sum_198 FROM aggtest; --Testcase 7: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 680: +--Testcase 605: SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; --Testcase 8: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 681: +--Testcase 606: SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; --Testcase 9: @@ -152,19 +181,19 @@ SELECT max(student.gpa) AS max_3_7 FROM student; --Testcase 13: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 682: +--Testcase 607: SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; --Testcase 14: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 683: +--Testcase 608: SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; --Testcase 15: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 684: +--Testcase 609: SELECT var_pop(b)::numeric(20,10) FROM aggtest; --Testcase 16: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 685: +--Testcase 610: SELECT var_samp(b)::numeric(20,10) FROM aggtest; --Testcase 17: @@ -319,21 +348,21 @@ DELETE FROM agg_t3; --Testcase 332: INSERT INTO agg_t3 VALUES ('1'::float8), ('infinity'::float8); --Testcase 333: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; +SELECT avg(a), var_pop(a) FROM agg_t3; --Testcase 334: DELETE FROM agg_t3; --Testcase 335: INSERT INTO agg_t3 VALUES ('infinity'::float8), ('1'::float8); --Testcase 336: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; +SELECT avg(a), var_pop(a) FROM agg_t3; --Testcase 337: DELETE FROM agg_t3; --Testcase 338: INSERT INTO agg_t3 VALUES ('infinity'::float8), ('infinity'::float8); --Testcase 339: -SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; +SELECT avg(a), var_pop(a) FROM agg_t3; --Testcase 340: DELETE FROM agg_t3; @@ -408,31 +437,31 @@ SELECT regr_count(b, a) FROM aggtest; SELECT regr_sxx(b, a) FROM aggtest; --Testcase 23: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 686: +--Testcase 611: SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; --Testcase 24: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 687: +--Testcase 612: SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; --Testcase 25: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 688: +--Testcase 613: SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; --Testcase 26: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 689: +--Testcase 614: SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; --Testcase 27: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 690: +--Testcase 615: SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; --Testcase 28: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 691: +--Testcase 616: SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; --Testcase 29: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 692: +--Testcase 617: SELECT corr(b, a)::numeric(20,10) FROM aggtest; -- check single-tuple behavior @@ -1574,15 +1603,15 @@ rollback; --Testcase 179: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 693: +--Testcase 618: select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; --Testcase 180: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 694: +--Testcase 619: select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; --Testcase 181: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 695: +--Testcase 620: select percentile_cont(0.5) within group (order by thousand) from tenk1; --Testcase 182: select percentile_disc(0.5) within group (order by thousand) from tenk1; @@ -1600,7 +1629,7 @@ select cume_dist(3) within group (order by f1) from INT4_TBL; insert into INT4_TBL values (5); --Testcase 458: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 696: +--Testcase 621: select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; --Testcase 459: delete from INT4_TBL where f1 = 5; @@ -2447,6 +2476,13 @@ set work_mem to default; union all (select * from agg_group_4 except select * from agg_hash_4); +--Testcase 622: +DELETE FROM INT4_TBL; +--Testcase 623: +DELETE FROM INT8_TBL; +--Testcase 624: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/12.16/extra/bitstring.sql b/sql/13.15/extra/bitstring.sql similarity index 100% rename from sql/12.16/extra/bitstring.sql rename to sql/13.15/extra/bitstring.sql diff --git a/sql/12.16/extra/bool.sql b/sql/13.15/extra/bool.sql similarity index 99% rename from sql/12.16/extra/bool.sql rename to sql/13.15/extra/bool.sql index c1c58db1..f464c35d 100644 --- a/sql/12.16/extra/bool.sql +++ b/sql/13.15/extra/bool.sql @@ -186,5 +186,8 @@ DELETE FROM "type_BOOLEAN_oper" WHERE b2; --Testcase 78: SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 79: +DELETE FROM "type_BOOLEAN"; + --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/12.16/extra/encodings.sql b/sql/13.15/extra/encodings.sql similarity index 100% rename from sql/12.16/extra/encodings.sql rename to sql/13.15/extra/encodings.sql diff --git a/sql/12.16/extra/float4.sql b/sql/13.15/extra/float4.sql similarity index 100% rename from sql/12.16/extra/float4.sql rename to sql/13.15/extra/float4.sql diff --git a/sql/13.12/extra/float8.sql b/sql/13.15/extra/float8.sql similarity index 99% rename from sql/13.12/extra/float8.sql rename to sql/13.15/extra/float8.sql index 1a944995..92330e74 100644 --- a/sql/13.12/extra/float8.sql +++ b/sql/13.15/extra/float8.sql @@ -892,6 +892,9 @@ rollback; --Testcase 269: drop type xfloat8 cascade; +--Testcase 272: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/12.16/extra/insert.sql b/sql/13.15/extra/insert.sql similarity index 100% rename from sql/12.16/extra/insert.sql rename to sql/13.15/extra/insert.sql diff --git a/sql/12.16/extra/int4.sql b/sql/13.15/extra/int4.sql similarity index 99% rename from sql/12.16/extra/int4.sql rename to sql/13.15/extra/int4.sql index 574b9137..2225f2ef 100644 --- a/sql/12.16/extra/int4.sql +++ b/sql/13.15/extra/int4.sql @@ -369,6 +369,9 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow +--Testcase 137: +DELETE FROM INT4_TBL; + -- Clean up DO $d$ declare diff --git a/sql/12.16/extra/int8.sql b/sql/13.15/extra/int8.sql similarity index 99% rename from sql/12.16/extra/int8.sql rename to sql/13.15/extra/int8.sql index 7d4ba4ba..f822e676 100644 --- a/sql/12.16/extra/int8.sql +++ b/sql/13.15/extra/int8.sql @@ -615,6 +615,9 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow +--Testcase 251: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/13.12/extra/join.sql b/sql/13.15/extra/join.sql similarity index 98% rename from sql/13.12/extra/join.sql rename to sql/13.15/extra/join.sql index 85eabb84..7a41b9e1 100644 --- a/sql/13.12/extra/join.sql +++ b/sql/13.15/extra/join.sql @@ -63,13 +63,46 @@ CREATE FOREIGN TABLE tenk2 ( --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 489: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 490: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 491: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 492: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 493: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 494: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 495: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 496: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 497: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 498: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); + --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 499: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 500: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 501: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 502: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 503: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; @@ -708,6 +741,7 @@ select * from t12 left join t22 on (t12.a = t22.a); --Testcase 120: select t12.x from t12 join t32 on (t12.a = t32.x); +--Testcase 504: drop table t2a; -- @@ -889,6 +923,7 @@ select * from left join zv1 on (f3 = f1) where f2 = 53; +--Testcase 505: drop view zv1; -- @@ -2724,6 +2759,13 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 506: +DELETE FROM INT4_TBL; +--Testcase 507: +DELETE FROM INT8_TBL; +--Testcase 508: +DELETE FROM FLOAT8_TBL; + DO $d$ declare l_rec record; diff --git a/sql/16.0/extra/limit.sql b/sql/13.15/extra/limit.sql similarity index 96% rename from sql/16.0/extra/limit.sql rename to sql/13.15/extra/limit.sql index abdc06e9..47737211 100644 --- a/sql/16.0/extra/limit.sql +++ b/sql/13.15/extra/limit.sql @@ -29,6 +29,17 @@ CREATE FOREIGN TABLE onek( --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 104: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 105: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 107: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 108: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); + --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -388,12 +399,6 @@ SELECT thousand FROM onek WHERE thousand < 5 ORDER BY thousand FETCH FIRST 2 ROW ONLY; --- SKIP LOCKED and WITH TIES are incompatible ---Testcase 104: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; - -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -426,6 +431,9 @@ CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 \d+ limit_thousand_v_4 -- leave these views +--Testcase 109: +DELETE FROM int8_tbl; + -- Clean up DO $d$ declare diff --git a/sql/12.16/extra/numeric.sql b/sql/13.15/extra/numeric.sql similarity index 100% rename from sql/12.16/extra/numeric.sql rename to sql/13.15/extra/numeric.sql diff --git a/sql/12.16/extra/out_of_range.sql b/sql/13.15/extra/out_of_range.sql similarity index 100% rename from sql/12.16/extra/out_of_range.sql rename to sql/13.15/extra/out_of_range.sql diff --git a/sql/12.16/extra/prepare.sql b/sql/13.15/extra/prepare.sql similarity index 100% rename from sql/12.16/extra/prepare.sql rename to sql/13.15/extra/prepare.sql diff --git a/sql/12.16/extra/select.sql b/sql/13.15/extra/select.sql similarity index 96% rename from sql/12.16/extra/select.sql rename to sql/13.15/extra/select.sql index 12ee7b82..0755d502 100644 --- a/sql/12.16/extra/select.sql +++ b/sql/13.15/extra/select.sql @@ -52,6 +52,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( @@ -380,6 +390,9 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; + --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/sql/12.16/extra/select_having.sql b/sql/13.15/extra/select_having.sql similarity index 100% rename from sql/12.16/extra/select_having.sql rename to sql/13.15/extra/select_having.sql diff --git a/sql/12.16/extra/sqlite_fdw_post.sql b/sql/13.15/extra/sqlite_fdw_post.sql similarity index 99% rename from sql/12.16/extra/sqlite_fdw_post.sql rename to sql/13.15/extra/sqlite_fdw_post.sql index 62073513..0d5483a9 100644 --- a/sql/12.16/extra/sqlite_fdw_post.sql +++ b/sql/13.15/extra/sqlite_fdw_post.sql @@ -14,10 +14,11 @@ DO $d$ END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; -- =================================================================== -- create objects used through FDW sqlite server @@ -663,10 +664,19 @@ RESET enable_hashjoin; --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; @@ -3257,9 +3267,9 @@ ROLLBACK; -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; --Testcase 736: diff --git a/sql/12.16/extra/timestamp.sql b/sql/13.15/extra/timestamp.sql similarity index 100% rename from sql/12.16/extra/timestamp.sql rename to sql/13.15/extra/timestamp.sql diff --git a/sql/12.16/extra/update.sql b/sql/13.15/extra/update.sql similarity index 100% rename from sql/12.16/extra/update.sql rename to sql/13.15/extra/update.sql diff --git a/sql/12.16/extra/uuid.sql b/sql/13.15/extra/uuid.sql similarity index 100% rename from sql/12.16/extra/uuid.sql rename to sql/13.15/extra/uuid.sql diff --git a/sql/12.16/selectfunc.sql b/sql/13.15/selectfunc.sql similarity index 100% rename from sql/12.16/selectfunc.sql rename to sql/13.15/selectfunc.sql diff --git a/sql/13.12/sqlite_fdw.sql b/sql/13.15/sqlite_fdw.sql similarity index 100% rename from sql/13.12/sqlite_fdw.sql rename to sql/13.15/sqlite_fdw.sql diff --git a/sql/14.9/type.sql b/sql/13.15/type.sql similarity index 94% rename from sql/14.9/type.sql rename to sql/13.15/type.sql index a438b6c4..2d2dfa1b 100644 --- a/sql/14.9/type.sql +++ b/sql/13.15/type.sql @@ -141,7 +141,35 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); + --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/sql/13.12/aggregate.sql b/sql/14.12/aggregate.sql similarity index 100% rename from sql/13.12/aggregate.sql rename to sql/14.12/aggregate.sql diff --git a/sql/15.4/extra/aggregates.sql b/sql/14.12/extra/aggregates.sql similarity index 98% rename from sql/15.4/extra/aggregates.sql rename to sql/14.12/extra/aggregates.sql index 790e2936..6489baaa 100644 --- a/sql/15.4/extra/aggregates.sql +++ b/sql/14.12/extra/aggregates.sql @@ -65,9 +65,29 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 678: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 679: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 680: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 681: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 682: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 683: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 684: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 685: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 686: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 687: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; @@ -77,7 +97,16 @@ CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqli --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; - +--Testcase 688: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 689: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 690: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 691: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 692: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: @@ -119,12 +148,12 @@ SELECT any_value(v) FROM agg_tb2; -- In 7.1, avg(float4) is computed using float8 arithmetic. --Testcase 3: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 678: +--Testcase 693: SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; --Testcase 4: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 679: +--Testcase 694: SELECT avg(gpa)::numeric(10,3) AS avg_3_4 FROM ONLY student; @@ -134,11 +163,11 @@ SELECT sum(four) AS sum_1500 FROM onek; SELECT sum(a) AS sum_198 FROM aggtest; --Testcase 7: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 680: +--Testcase 695: SELECT sum(b)::numeric(10,3) AS avg_431_773 FROM aggtest; --Testcase 8: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 681: +--Testcase 696: SELECT sum(gpa)::numeric(10,3) AS avg_6_8 FROM ONLY student; --Testcase 9: @@ -152,19 +181,19 @@ SELECT max(student.gpa) AS max_3_7 FROM student; --Testcase 13: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 682: +--Testcase 697: SELECT stddev_pop(b)::numeric(20,10) FROM aggtest; --Testcase 14: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 683: +--Testcase 698: SELECT stddev_samp(b)::numeric(20,10) FROM aggtest; --Testcase 15: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 684: +--Testcase 699: SELECT var_pop(b)::numeric(20,10) FROM aggtest; --Testcase 16: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 685: +--Testcase 700: SELECT var_samp(b)::numeric(20,10) FROM aggtest; --Testcase 17: @@ -408,31 +437,31 @@ SELECT regr_count(b, a) FROM aggtest; SELECT regr_sxx(b, a) FROM aggtest; --Testcase 23: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 686: +--Testcase 701: SELECT regr_syy(b, a)::numeric(20,10) FROM aggtest; --Testcase 24: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 687: +--Testcase 702: SELECT regr_sxy(b, a)::numeric(20,10) FROM aggtest; --Testcase 25: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 688: +--Testcase 703: SELECT regr_avgx(b, a), regr_avgy(b, a)::numeric(20,10) FROM aggtest; --Testcase 26: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 689: +--Testcase 704: SELECT regr_r2(b, a)::numeric(20,10) FROM aggtest; --Testcase 27: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 690: +--Testcase 705: SELECT regr_slope(b, a)::numeric(20,10), regr_intercept(b, a)::numeric(20,10) FROM aggtest; --Testcase 28: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 691: +--Testcase 706: SELECT covar_pop(b, a)::numeric(20,10), covar_samp(b, a)::numeric(20,10) FROM aggtest; --Testcase 29: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 692: +--Testcase 707: SELECT corr(b, a)::numeric(20,10) FROM aggtest; -- check single-tuple behavior @@ -1574,15 +1603,15 @@ rollback; --Testcase 179: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 693: +--Testcase 708: select (percentile_cont(0.5) within group (order by b))::numeric(20,10) from aggtest; --Testcase 180: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 694: +--Testcase 709: select (percentile_cont(0.5) within group (order by b))::numeric(20,10), sum(b)::numeric(10,3) from aggtest; --Testcase 181: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 695: +--Testcase 710: select percentile_cont(0.5) within group (order by thousand) from tenk1; --Testcase 182: select percentile_disc(0.5) within group (order by thousand) from tenk1; @@ -1600,7 +1629,7 @@ select cume_dist(3) within group (order by f1) from INT4_TBL; insert into INT4_TBL values (5); --Testcase 458: -- Round the result to limited digits to avoid platform-specific results. ---Testcase 696: +--Testcase 711: select (percent_rank(3) within group (order by f1))::numeric(20,10) from INT4_TBL; --Testcase 459: delete from INT4_TBL where f1 = 5; @@ -2447,6 +2476,13 @@ set work_mem to default; union all (select * from agg_group_4 except select * from agg_hash_4); +--Testcase 712: +DELETE FROM INT4_TBL; +--Testcase 713: +DELETE FROM INT8_TBL; +--Testcase 714: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/13.12/extra/bitstring.sql b/sql/14.12/extra/bitstring.sql similarity index 100% rename from sql/13.12/extra/bitstring.sql rename to sql/14.12/extra/bitstring.sql diff --git a/sql/14.9/extra/bool.sql b/sql/14.12/extra/bool.sql similarity index 99% rename from sql/14.9/extra/bool.sql rename to sql/14.12/extra/bool.sql index c1c58db1..f464c35d 100644 --- a/sql/14.9/extra/bool.sql +++ b/sql/14.12/extra/bool.sql @@ -186,5 +186,8 @@ DELETE FROM "type_BOOLEAN_oper" WHERE b2; --Testcase 78: SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 79: +DELETE FROM "type_BOOLEAN"; + --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/13.12/extra/encodings.sql b/sql/14.12/extra/encodings.sql similarity index 100% rename from sql/13.12/extra/encodings.sql rename to sql/14.12/extra/encodings.sql diff --git a/sql/14.9/extra/float4.sql b/sql/14.12/extra/float4.sql similarity index 100% rename from sql/14.9/extra/float4.sql rename to sql/14.12/extra/float4.sql diff --git a/sql/14.9/extra/float8.sql b/sql/14.12/extra/float8.sql similarity index 99% rename from sql/14.9/extra/float8.sql rename to sql/14.12/extra/float8.sql index 0074fe52..18f74da7 100644 --- a/sql/14.9/extra/float8.sql +++ b/sql/14.12/extra/float8.sql @@ -1079,6 +1079,9 @@ rollback; --Testcase 269: drop type xfloat8 cascade; +--Testcase 363: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/14.9/extra/insert.sql b/sql/14.12/extra/insert.sql similarity index 100% rename from sql/14.9/extra/insert.sql rename to sql/14.12/extra/insert.sql diff --git a/sql/14.9/extra/int4.sql b/sql/14.12/extra/int4.sql similarity index 99% rename from sql/14.9/extra/int4.sql rename to sql/14.12/extra/int4.sql index 4a3788cf..49d22bfe 100644 --- a/sql/14.9/extra/int4.sql +++ b/sql/14.12/extra/int4.sql @@ -355,6 +355,9 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow +--Testcase 137: +DELETE FROM INT4_TBL; + -- Clean up DO $d$ declare diff --git a/sql/14.9/extra/int8.sql b/sql/14.12/extra/int8.sql similarity index 99% rename from sql/14.9/extra/int8.sql rename to sql/14.12/extra/int8.sql index f931d7cb..bd28b520 100644 --- a/sql/14.9/extra/int8.sql +++ b/sql/14.12/extra/int8.sql @@ -615,6 +615,9 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow +--Testcase 251: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/15.4/extra/join.sql b/sql/14.12/extra/join.sql similarity index 98% rename from sql/15.4/extra/join.sql rename to sql/14.12/extra/join.sql index c9cd483f..73d11385 100644 --- a/sql/15.4/extra/join.sql +++ b/sql/14.12/extra/join.sql @@ -63,13 +63,46 @@ CREATE FOREIGN TABLE tenk2 ( --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 539: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 540: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 541: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 542: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 543: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 544: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 545: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 546: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 547: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 548: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); + --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 549: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 550: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 551: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 552: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 553: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; @@ -741,33 +774,6 @@ select * from t12 left join t22 on (t12.a = t22.a); --Testcase 120: select t12.x from t12 join t32 on (t12.a = t32.x); --- Test matching of locking clause with wrong alias - ---Testcase 540: -select t12.*, t22.*, unnamed_join.* from - t12 join t22 on (t12.a = t22.a), t32 as unnamed_join - for update of unnamed_join; - ---Testcase 541: -select foo.*, unnamed_join.* from - t12 join t22 using (a) as foo, t32 as unnamed_join - for update of unnamed_join; - ---Testcase 542: -select foo.*, unnamed_join.* from - t12 join t22 using (a) as foo, t32 as unnamed_join - for update of foo; - ---Testcase 543: -select bar.*, unnamed_join.* from - (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join - for update of foo; - ---Testcase 544: -select bar.*, unnamed_join.* from - (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join - for update of bar; - --Testcase 536: drop table t2a; @@ -2531,10 +2537,6 @@ select * from (select q1.v) ) as q2; --- check the number of columns specified ---Testcase 539: -SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d); - -- check we don't try to do a unique-ified semijoin with LATERAL --Testcase 314: explain (verbose, costs off) @@ -2939,6 +2941,13 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 554: +DELETE FROM INT4_TBL; +--Testcase 555: +DELETE FROM INT8_TBL; +--Testcase 556: +DELETE FROM FLOAT8_TBL; + DO $d$ declare l_rec record; diff --git a/sql/15.4/extra/limit.sql b/sql/14.12/extra/limit.sql similarity index 96% rename from sql/15.4/extra/limit.sql rename to sql/14.12/extra/limit.sql index abdc06e9..47737211 100644 --- a/sql/15.4/extra/limit.sql +++ b/sql/14.12/extra/limit.sql @@ -29,6 +29,17 @@ CREATE FOREIGN TABLE onek( --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 104: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 105: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 107: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 108: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); + --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -388,12 +399,6 @@ SELECT thousand FROM onek WHERE thousand < 5 ORDER BY thousand FETCH FIRST 2 ROW ONLY; --- SKIP LOCKED and WITH TIES are incompatible ---Testcase 104: -SELECT thousand - FROM onek WHERE thousand < 5 - ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; - -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -426,6 +431,9 @@ CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 \d+ limit_thousand_v_4 -- leave these views +--Testcase 109: +DELETE FROM int8_tbl; + -- Clean up DO $d$ declare diff --git a/sql/14.9/extra/numeric.sql b/sql/14.12/extra/numeric.sql similarity index 100% rename from sql/14.9/extra/numeric.sql rename to sql/14.12/extra/numeric.sql diff --git a/sql/13.12/extra/out_of_range.sql b/sql/14.12/extra/out_of_range.sql similarity index 100% rename from sql/13.12/extra/out_of_range.sql rename to sql/14.12/extra/out_of_range.sql diff --git a/sql/13.12/extra/prepare.sql b/sql/14.12/extra/prepare.sql similarity index 100% rename from sql/13.12/extra/prepare.sql rename to sql/14.12/extra/prepare.sql diff --git a/sql/14.9/extra/select.sql b/sql/14.12/extra/select.sql similarity index 96% rename from sql/14.9/extra/select.sql rename to sql/14.12/extra/select.sql index 12ee7b82..fe56af40 100644 --- a/sql/14.9/extra/select.sql +++ b/sql/14.12/extra/select.sql @@ -53,6 +53,17 @@ CREATE FOREIGN TABLE INT8_TBL( q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -380,6 +391,9 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; + --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/sql/13.12/extra/select_having.sql b/sql/14.12/extra/select_having.sql similarity index 100% rename from sql/13.12/extra/select_having.sql rename to sql/14.12/extra/select_having.sql diff --git a/sql/14.9/extra/sqlite_fdw_post.sql b/sql/14.12/extra/sqlite_fdw_post.sql similarity index 98% rename from sql/14.9/extra/sqlite_fdw_post.sql rename to sql/14.12/extra/sqlite_fdw_post.sql index 937e2318..4e29e96a 100644 --- a/sql/14.9/extra/sqlite_fdw_post.sql +++ b/sql/14.12/extra/sqlite_fdw_post.sql @@ -16,12 +16,13 @@ DO $d$ END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -709,10 +710,19 @@ RESET enable_hashjoin; --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; @@ -3705,15 +3715,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 @@ -3732,7 +3747,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; COMMIT; @@ -3745,9 +3760,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -4193,9 +4208,9 @@ CREATE FOREIGN TABLE inv_bsz (c1 int ) -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; --Testcase 736: diff --git a/sql/13.12/extra/timestamp.sql b/sql/14.12/extra/timestamp.sql similarity index 100% rename from sql/13.12/extra/timestamp.sql rename to sql/14.12/extra/timestamp.sql diff --git a/sql/14.9/extra/update.sql b/sql/14.12/extra/update.sql similarity index 100% rename from sql/14.9/extra/update.sql rename to sql/14.12/extra/update.sql diff --git a/sql/13.12/extra/uuid.sql b/sql/14.12/extra/uuid.sql similarity index 100% rename from sql/13.12/extra/uuid.sql rename to sql/14.12/extra/uuid.sql diff --git a/sql/13.12/selectfunc.sql b/sql/14.12/selectfunc.sql similarity index 100% rename from sql/13.12/selectfunc.sql rename to sql/14.12/selectfunc.sql diff --git a/sql/14.9/sqlite_fdw.sql b/sql/14.12/sqlite_fdw.sql similarity index 100% rename from sql/14.9/sqlite_fdw.sql rename to sql/14.12/sqlite_fdw.sql diff --git a/sql/14.12/type.sql b/sql/14.12/type.sql new file mode 100644 index 00000000..2d2dfa1b --- /dev/null +++ b/sql/14.12/type.sql @@ -0,0 +1,308 @@ +--SET log_min_messages TO DEBUG1; +--SET client_min_messages TO DEBUG1; +--Testcase 44: +CREATE EXTENSION sqlite_fdw; +--Testcase 45: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); + +--Testcase 46: +CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; + +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO public; + +--Testcase 1: +INSERT INTO "type_STRING"(col) VALUES ('string'); +--Testcase 4: +INSERT INTO "type_BYTE"(col) VALUES ('c'); +--Testcase 5: +INSERT INTO "type_SINT"(col) VALUES (32767); +--Testcase 6: +INSERT INTO "type_SINT"(col) VALUES (-32768); +--Testcase 7: +INSERT INTO "type_BINT"(col) VALUES (9223372036854775807); +--Testcase 8: +INSERT INTO "type_BINT"(col) VALUES (-9223372036854775808); +--Testcase 9: +INSERT INTO "type_INTEGER"(col) VALUES (9223372036854775807); + +--Testcase 10: +INSERT INTO "type_FLOAT"(col) VALUES (3.1415); +--Testcase 11: +INSERT INTO "type_DOUBLE"(col) VALUES (3.14159265); +--Testcase 12: +INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 12:34:56.789', '2017.11.06'); +--Testcase 13: +INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 1:3:0', '2017.11.07'); +--Testcase 14: +INSERT INTO "type_BLOB"(col) VALUES (bytea('\xDEADBEEF')); +--Testcase 15: +INSERT INTO typetest VALUES(1,'a', 'b', 'c','2017.11.06 12:34:56.789', '2017.11.06 12:34:56.789' ) ; + +--Testcase 16: +SELECT * FROM "type_STRING"; +--Testcase 18: +SELECT * FROM "type_BYTE"; +--Testcase 19: +SELECT * FROM "type_SINT"; +--Testcase 20: +SELECT * FROM "type_BINT"; +--Testcase 21: +SELECT * FROM "type_INTEGER"; +--Testcase 22: +SELECT * FROM "type_FLOAT"; +--Testcase 23: +SELECT * FROM "type_DOUBLE"; +set datestyle=ISO; +--Testcase 24: +SELECT * FROM "type_TIMESTAMP"; +--Testcase 25: +SELECT * FROM "type_BLOB"; +--Testcase 26: +SELECT * FROM typetest; + +--Testcase 27: +insert into "type_STRING" values('TYPE'); +--Testcase 28: +insert into "type_STRING" values('type'); + +-- not pushdown +--Testcase 29: +SELECT *FROM "type_STRING" WHERE col like 'TYP%'; +--Testcase 30: +EXPLAIN SELECT *FROM "type_STRING" WHERE col like 'TYP%'; +-- pushdown +--Testcase 31: +SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; +--Testcase 32: +EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; + +--Testcase 33: +SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; +--Testcase 34: +EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; + +--Testcase 35: +SELECT * FROM "type_TIMESTAMP"; + +--Testcase 36: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; +--Testcase 37: +SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; + +--Testcase 38: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; +--Testcase 39: +SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; + +--Testcase 40: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; +--Testcase 41: +SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; + +--Testcase 42: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b; +--Testcase 43: +SELECT * FROM "type_TIMESTAMP" WHERE col > b; + +--Testcase 48: +INSERT INTO "type_DATE"(col) VALUES ('2021.02.23'); +--Testcase 49: +INSERT INTO "type_DATE"(col) VALUES ('2021/03/08'); +--Testcase 50: +INSERT INTO "type_DATE"(col) VALUES ('9999-12-30'); +--Testcase 58: +SELECT * FROM "type_DATE"; + +--Testcase 51: +INSERT INTO "type_TIME"(col) VALUES ('01:23:45'); +--Testcase 52: +INSERT INTO "type_TIME"(col) VALUES ('01:23:45.6789'); +--Testcase 59: +SELECT * FROM "type_TIME"; + +--Testcase 60: +EXPLAIN VERBOSE +SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; +--Testcase 61: +SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; + +--Testcase 53: +CREATE FOREIGN TABLE type_JSON(col JSON OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'type_TEXT'); +--Testcase 54: +INSERT INTO type_JSON(col) VALUES ('[1, 2, "foo", null]'); +--Testcase 55: +INSERT INTO type_JSON(col) VALUES ('{"bar": "baz", "balance": 7.77, "active": false}'::json); +--Testcase 56 +SELECT * FROM type_JSON; +--Testcase 57 +DELETE FROM type_JSON; + +--Testcase 62: +DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; +--Testcase 63: +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); + +--Testcase 64: +ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; +--Testcase 65: +SELECT * FROM "type_BOOLEAN"; -- OK + +-- define INTEGER as TEXT column +--Testcase 67: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE text; +--Testcase 68: +SELECT * FROM "type_INTEGER"; -- OK + +-- define INTEGER as bpchar +--Testcase 69: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE char(30); +--Testcase 70: +SELECT * FROM "type_INTEGER"; -- OK +-- define INTEGER as varchar +--Testcase 71: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE varchar(30); +--Testcase 72: +SELECT * FROM "type_INTEGER"; -- OK + +-- define INTEGER as name +--Testcase 73: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE name; +--Testcase 74: +SELECT * FROM "type_INTEGER"; -- OK + +-- define INTEGER as json +--Testcase 75: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE json; +--Testcase 76: +SELECT * FROM "type_INTEGER"; -- OK + +-- define INTEGER as time +--Testcase 77: +DELETE FROM "type_INTEGER"; +--Testcase 78: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; +--Testcase 79: +INSERT INTO "type_INTEGER" VALUES (120506); +--Testcase 80: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE time; +--Testcase 81: +SELECT * FROM "type_INTEGER"; -- OK + +-- define INTEGER as date +--Testcase 82: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE date; +--Testcase 83: +SELECT * FROM "type_INTEGER"; -- OK + +--Testcase 84: +ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; + +--Testcase 85: +INSERT INTO "type_DOUBLE" VALUES (1.3e-5); +--Testcase 86: +SELECT * FROM "type_DOUBLE"; + +-- define DOUBLE as TEXT column +--Testcase 87: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE text; +--Testcase 88: +SELECT * FROM "type_DOUBLE"; -- OK + +-- define DOUBLE as bpchar +--Testcase 89: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE char(30); +--Testcase 90: +SELECT * FROM "type_DOUBLE"; -- OK +-- define DOUBLE as varchar +--Testcase 91: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE varchar(30); +--Testcase 92: +SELECT * FROM "type_DOUBLE"; -- OK + +-- define DOUBLE as name +--Testcase 93: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE name; +--Testcase 94: +SELECT * FROM "type_DOUBLE"; -- OK + +-- define DOUBLE as json +--Testcase 95: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE json; +--Testcase 96: +SELECT * FROM "type_DOUBLE"; -- OK + +--Testcase 97: +DELETE FROM "type_DOUBLE"; +--Testcase 98: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; +--Testcase 99: +INSERT INTO "type_DOUBLE" VALUES (120506.12); + +-- define DOUBLE as time +--Testcase 100: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE time; +--Testcase 101: +SELECT * FROM "type_DOUBLE"; -- OK + +--Testcase 102: +DELETE FROM "type_DOUBLE"; +--Testcase 103: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; +--Testcase 104: +INSERT INTO "type_DOUBLE" VALUES (1999.012); +-- define DOUBLE as date +--Testcase 105: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE date; +--Testcase 106: +SELECT * FROM "type_DOUBLE"; -- OK + +--Testcase 107: +ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; + +--Testcase 108: +INSERT INTO "type_DOUBLE" VALUES (PI()); +--Testcase 109: ERR primary key +INSERT INTO "type_DOUBLE" VALUES (PI()); +--Testcase 110: +INSERT INTO "type_DOUBLE" VALUES ('Infinity'); +--Testcase 111: +INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); +--Testcase 113: +SELECT * FROM "type_DOUBLE"; -- OK, +- Inf +--Testcase 114: ERR primary key +INSERT INTO "type_DOUBLE" VALUES ('Infinity'); +--Testcase 115: ERR primary key +INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); +--Testcase 116: +SELECT * FROM "type_DOUBLE"; -- OK, +- Inf + +--Testcase 47: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/14.9/aggregate.sql b/sql/15.7/aggregate.sql similarity index 100% rename from sql/14.9/aggregate.sql rename to sql/15.7/aggregate.sql diff --git a/sql/16.0/extra/aggregates.sql b/sql/15.7/extra/aggregates.sql similarity index 98% rename from sql/16.0/extra/aggregates.sql rename to sql/15.7/extra/aggregates.sql index 790e2936..51fe22ff 100644 --- a/sql/16.0/extra/aggregates.sql +++ b/sql/15.7/extra/aggregates.sql @@ -65,9 +65,29 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 697: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 698: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 699: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 700: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 701: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 702: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 703: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 704: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 705: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 706: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; @@ -77,7 +97,16 @@ CREATE FOREIGN TABLE VARCHAR_TBL(f1 varchar(4) OPTIONS (key 'true')) SERVER sqli --Testcase 276: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; - +--Testcase 707: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 708: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 709: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 710: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 711: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- avoid bit-exact output here because operations may not be bit-exact. --Testcase 588: @@ -2447,6 +2476,13 @@ set work_mem to default; union all (select * from agg_group_4 except select * from agg_hash_4); +--Testcase 712: +DELETE FROM INT4_TBL; +--Testcase 713: +DELETE FROM INT8_TBL; +--Testcase 714: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/14.9/extra/bitstring.sql b/sql/15.7/extra/bitstring.sql similarity index 100% rename from sql/14.9/extra/bitstring.sql rename to sql/15.7/extra/bitstring.sql diff --git a/sql/13.12/extra/bool.sql b/sql/15.7/extra/bool.sql similarity index 99% rename from sql/13.12/extra/bool.sql rename to sql/15.7/extra/bool.sql index c1c58db1..f464c35d 100644 --- a/sql/13.12/extra/bool.sql +++ b/sql/15.7/extra/bool.sql @@ -186,5 +186,8 @@ DELETE FROM "type_BOOLEAN_oper" WHERE b2; --Testcase 78: SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 79: +DELETE FROM "type_BOOLEAN"; + --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/14.9/extra/encodings.sql b/sql/15.7/extra/encodings.sql similarity index 100% rename from sql/14.9/extra/encodings.sql rename to sql/15.7/extra/encodings.sql diff --git a/sql/15.4/extra/float4.sql b/sql/15.7/extra/float4.sql similarity index 100% rename from sql/15.4/extra/float4.sql rename to sql/15.7/extra/float4.sql diff --git a/sql/15.4/extra/float8.sql b/sql/15.7/extra/float8.sql similarity index 99% rename from sql/15.4/extra/float8.sql rename to sql/15.7/extra/float8.sql index 0074fe52..18f74da7 100644 --- a/sql/15.4/extra/float8.sql +++ b/sql/15.7/extra/float8.sql @@ -1079,6 +1079,9 @@ rollback; --Testcase 269: drop type xfloat8 cascade; +--Testcase 363: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/15.4/extra/insert.sql b/sql/15.7/extra/insert.sql similarity index 100% rename from sql/15.4/extra/insert.sql rename to sql/15.7/extra/insert.sql diff --git a/sql/15.4/extra/int4.sql b/sql/15.7/extra/int4.sql similarity index 99% rename from sql/15.4/extra/int4.sql rename to sql/15.7/extra/int4.sql index 4a3788cf..49d22bfe 100644 --- a/sql/15.4/extra/int4.sql +++ b/sql/15.7/extra/int4.sql @@ -355,6 +355,9 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); --Testcase 134: SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow +--Testcase 137: +DELETE FROM INT4_TBL; + -- Clean up DO $d$ declare diff --git a/sql/15.4/extra/int8.sql b/sql/15.7/extra/int8.sql similarity index 99% rename from sql/15.4/extra/int8.sql rename to sql/15.7/extra/int8.sql index f931d7cb..bd28b520 100644 --- a/sql/15.4/extra/int8.sql +++ b/sql/15.7/extra/int8.sql @@ -615,6 +615,9 @@ INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806): --Testcase 248: SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow +--Testcase 251: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/14.9/extra/join.sql b/sql/15.7/extra/join.sql similarity index 97% rename from sql/14.9/extra/join.sql rename to sql/15.7/extra/join.sql index feaf8ee7..2fcdbb66 100644 --- a/sql/14.9/extra/join.sql +++ b/sql/15.7/extra/join.sql @@ -63,13 +63,46 @@ CREATE FOREIGN TABLE tenk2 ( --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 545: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 546: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 547: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 548: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 549: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 550: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 551: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 552: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 553: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 554: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); + --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 555: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 556: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 557: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 558: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 559: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; @@ -741,6 +774,33 @@ select * from t12 left join t22 on (t12.a = t22.a); --Testcase 120: select t12.x from t12 join t32 on (t12.a = t32.x); +-- Test matching of locking clause with wrong alias + +--Testcase 540: +select t12.*, t22.*, unnamed_join.* from + t12 join t22 on (t12.a = t22.a), t32 as unnamed_join + for update of unnamed_join; + +--Testcase 541: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of unnamed_join; + +--Testcase 542: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of foo; + +--Testcase 543: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of foo; + +--Testcase 544: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of bar; + --Testcase 536: drop table t2a; @@ -2504,6 +2564,10 @@ select * from (select q1.v) ) as q2; +-- check the number of columns specified +--Testcase 539: +SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d); + -- check we don't try to do a unique-ified semijoin with LATERAL --Testcase 314: explain (verbose, costs off) @@ -2908,6 +2972,13 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 560: +DELETE FROM INT4_TBL; +--Testcase 561: +DELETE FROM INT8_TBL; +--Testcase 562: +DELETE FROM FLOAT8_TBL; + DO $d$ declare l_rec record; diff --git a/sql/12.16/extra/limit.sql b/sql/15.7/extra/limit.sql similarity index 94% rename from sql/12.16/extra/limit.sql rename to sql/15.7/extra/limit.sql index fad57bf9..8a8276a7 100644 --- a/sql/12.16/extra/limit.sql +++ b/sql/15.7/extra/limit.sql @@ -29,6 +29,17 @@ CREATE FOREIGN TABLE onek( --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); + --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -388,6 +399,12 @@ SELECT thousand FROM onek WHERE thousand < 5 ORDER BY thousand FETCH FIRST 2 ROW ONLY; +-- SKIP LOCKED and WITH TIES are incompatible +--Testcase 104: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; + -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -420,6 +437,9 @@ CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 \d+ limit_thousand_v_4 -- leave these views +--Testcase 110: +DELETE FROM int8_tbl; + -- Clean up DO $d$ declare diff --git a/sql/15.4/extra/numeric.sql b/sql/15.7/extra/numeric.sql similarity index 100% rename from sql/15.4/extra/numeric.sql rename to sql/15.7/extra/numeric.sql diff --git a/sql/14.9/extra/out_of_range.sql b/sql/15.7/extra/out_of_range.sql similarity index 100% rename from sql/14.9/extra/out_of_range.sql rename to sql/15.7/extra/out_of_range.sql diff --git a/sql/14.9/extra/prepare.sql b/sql/15.7/extra/prepare.sql similarity index 100% rename from sql/14.9/extra/prepare.sql rename to sql/15.7/extra/prepare.sql diff --git a/sql/15.4/extra/select.sql b/sql/15.7/extra/select.sql similarity index 96% rename from sql/15.4/extra/select.sql rename to sql/15.7/extra/select.sql index ccc055f8..366a4c12 100644 --- a/sql/15.4/extra/select.sql +++ b/sql/15.7/extra/select.sql @@ -53,6 +53,17 @@ CREATE FOREIGN TABLE INT8_TBL( q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -380,6 +391,9 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; + --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/sql/14.9/extra/select_having.sql b/sql/15.7/extra/select_having.sql similarity index 100% rename from sql/14.9/extra/select_having.sql rename to sql/15.7/extra/select_having.sql diff --git a/sql/15.4/extra/sqlite_fdw_post.sql b/sql/15.7/extra/sqlite_fdw_post.sql similarity index 98% rename from sql/15.4/extra/sqlite_fdw_post.sql rename to sql/15.7/extra/sqlite_fdw_post.sql index 77256265..5f2f366f 100644 --- a/sql/15.4/extra/sqlite_fdw_post.sql +++ b/sql/15.7/extra/sqlite_fdw_post.sql @@ -16,12 +16,13 @@ DO $d$ END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -784,10 +785,19 @@ SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1. --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; @@ -3847,15 +3857,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 @@ -3874,7 +3889,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; COMMIT; @@ -3887,9 +3902,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -4512,9 +4527,9 @@ CREATE FOREIGN TABLE inv_bsz (c1 int ) -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; --Testcase 736: diff --git a/sql/14.9/extra/timestamp.sql b/sql/15.7/extra/timestamp.sql similarity index 100% rename from sql/14.9/extra/timestamp.sql rename to sql/15.7/extra/timestamp.sql diff --git a/sql/15.4/extra/update.sql b/sql/15.7/extra/update.sql similarity index 100% rename from sql/15.4/extra/update.sql rename to sql/15.7/extra/update.sql diff --git a/sql/14.9/extra/uuid.sql b/sql/15.7/extra/uuid.sql similarity index 100% rename from sql/14.9/extra/uuid.sql rename to sql/15.7/extra/uuid.sql diff --git a/sql/14.9/selectfunc.sql b/sql/15.7/selectfunc.sql similarity index 100% rename from sql/14.9/selectfunc.sql rename to sql/15.7/selectfunc.sql diff --git a/sql/15.4/sqlite_fdw.sql b/sql/15.7/sqlite_fdw.sql similarity index 100% rename from sql/15.4/sqlite_fdw.sql rename to sql/15.7/sqlite_fdw.sql diff --git a/sql/13.12/type.sql b/sql/15.7/type.sql similarity index 94% rename from sql/13.12/type.sql rename to sql/15.7/type.sql index a438b6c4..e9e2fbe4 100644 --- a/sql/13.12/type.sql +++ b/sql/15.7/type.sql @@ -141,7 +141,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/sql/16.0/extra/bool.sql b/sql/16.0/extra/bool.sql deleted file mode 100644 index c1c58db1..00000000 --- a/sql/16.0/extra/bool.sql +++ /dev/null @@ -1,190 +0,0 @@ ---SET log_min_messages TO DEBUG1; ---SET client_min_messages TO DEBUG1; ---Testcase 000: -CREATE EXTENSION sqlite_fdw; ---Testcase 001: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); ---Testcase 002: -CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; - ---Testcase 01: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int OPTIONS (key 'true'), b bool) SERVER sqlite_svr; ---Testcase 02: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (1, TRUE); ---Testcase 03: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (2, FALSE); ---Testcase 04: -CREATE FOREIGN TABLE "type_BOOLEAN+"( "i" int, "b" bool, "t" text, "l" smallint) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN+'); ---Testcase 05: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE text; ---Testcase 06: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (3, TRUE); ---Testcase 07: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (4, FALSE); ---Testcase 08: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (5, true); ---Testcase 09: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (6, false); ---Testcase 10: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (7, 'Yes'); ---Testcase 11: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (8, 'YeS'); ---Testcase 12: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (9, 'yes'); ---Testcase 13: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (10, 'no'); ---Testcase 14: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (11, 'No'); ---Testcase 15: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (12, 'nO'); ---Testcase 16: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (13, 'off'); ---Testcase 17: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (14, 'oFf'); ---Testcase 18: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (15, 'on'); ---Testcase 19: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (16, 'ON'); ---Testcase 20: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (17, 't'); ---Testcase 21: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (18, 'T'); ---Testcase 22: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (19, 'Y'); ---Testcase 23: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (20, 'y'); ---Testcase 24: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (21, 'F'); ---Testcase 25: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (22, 'f'); ---Testcase 26: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (23, 'x'); ---Testcase 27: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (24, '0'); ---Testcase 28: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (25, '1'); ---Testcase 29: -INSERT INTO "type_BOOLEAN" (i, b) VALUES (26, NULL); ---Testcase 30: -SELECT * FROM "type_BOOLEAN"; ---Testcase 31: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; ---Testcase 32: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM "type_BOOLEAN"; ---Testcase 33: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM "type_BOOLEAN+"; ---Testcase 34: ERR - invalid text affinity because not ISO:SQL text input -SELECT * FROM "type_BOOLEAN+"; ---Testcase 35 -DELETE FROM "type_BOOLEAN" WHERE i = 23; ---Testcase 36: -SELECT * FROM "type_BOOLEAN+"; ---Testcase 37: -SELECT * FROM "type_BOOLEAN+" WHERE b IS NULL; ---Testcase 38: -SELECT * FROM "type_BOOLEAN+" WHERE b IS NOT NULL; ---Testcase 39: -SELECT * FROM "type_BOOLEAN+" WHERE b; ---Testcase 40: -SELECT * FROM "type_BOOLEAN+" WHERE NOT b; - ---Testcase 41: -CREATE FOREIGN TABLE "type_BOOLEANpk" (col bool OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 42: -INSERT INTO "type_BOOLEANpk" VALUES (TRUE); ---Testcase 43: -INSERT INTO "type_BOOLEANpk" VALUES (FALSE); ---Testcase 44: ERR - primary key -INSERT INTO "type_BOOLEANpk" VALUES (TRUE); ---Testcase 45: -DELETE FROM "type_BOOLEANpk"; - ---Testcase 46: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE float8; ---Testcase 47: -INSERT INTO "type_BOOLEAN"(i, b) VALUES (27, 3.14159265358979); ---Testcase 48: -ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; ---Testcase 49: ERR - invalid float for bool column -SELECT * FROM "type_BOOLEAN+"; ---Testcase 50 -DELETE FROM "type_BOOLEAN" WHERE i = 27; ---Testcase 51: -SELECT * FROM "type_BOOLEAN+"; - ---Testcase 52: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN" SET b = NULL WHERE b; ---Testcase 53: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN" SET b = NULL WHERE NOT b; ---Testcase 54: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN" WHERE b; ---Testcase 55: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN" WHERE NOT b; - ---Testcase 56: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT *, NOT b nb FROM "type_BOOLEAN+" b; ---Testcase 57: -SELECT *, NOT b nb FROM "type_BOOLEAN+" b; - ---Testcase 58: -CREATE FOREIGN TABLE "type_BOOLEAN_oper"( "i" int OPTIONS (key 'true'), i1 smallint, b1 boolean, i2 smallint, b2 boolean) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN_oper'); ---Testcase 59: see INIT.SQL with mixed affinity boolean data -SELECT * FROM "type_BOOLEAN_oper"; ---Testcase 60: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; ---Testcase 61: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; - ---Testcase 62: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; ---Testcase 63: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; - ---Testcase 64: -EXPLAIN (VERBOSE, COSTS OFF) -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; ---Testcase 65: -SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; - ---Testcase 66: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; ---Testcase 67: -UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; ---Testcase 68: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; ---Testcase 69: -UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; ---Testcase 70: -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; ---Testcase 71: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; ---Testcase 72: -EXPLAIN (VERBOSE, COSTS OFF) -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; ---Testcase 73: -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; ---Testcase 74: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; ---Testcase 75: -DELETE FROM "type_BOOLEAN_oper" WHERE NOT b2; ---Testcase 76: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; ---Testcase 77: -DELETE FROM "type_BOOLEAN_oper" WHERE b2; ---Testcase 78: -SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; - ---Testcase 003: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/16.0/type.sql b/sql/16.0/type.sql deleted file mode 100644 index a438b6c4..00000000 --- a/sql/16.0/type.sql +++ /dev/null @@ -1,280 +0,0 @@ ---SET log_min_messages TO DEBUG1; ---SET client_min_messages TO DEBUG1; ---Testcase 44: -CREATE EXTENSION sqlite_fdw; ---Testcase 45: -CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw -OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); - ---Testcase 46: -CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; - -IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO public; - ---Testcase 1: -INSERT INTO "type_STRING"(col) VALUES ('string'); ---Testcase 4: -INSERT INTO "type_BYTE"(col) VALUES ('c'); ---Testcase 5: -INSERT INTO "type_SINT"(col) VALUES (32767); ---Testcase 6: -INSERT INTO "type_SINT"(col) VALUES (-32768); ---Testcase 7: -INSERT INTO "type_BINT"(col) VALUES (9223372036854775807); ---Testcase 8: -INSERT INTO "type_BINT"(col) VALUES (-9223372036854775808); ---Testcase 9: -INSERT INTO "type_INTEGER"(col) VALUES (9223372036854775807); - ---Testcase 10: -INSERT INTO "type_FLOAT"(col) VALUES (3.1415); ---Testcase 11: -INSERT INTO "type_DOUBLE"(col) VALUES (3.14159265); ---Testcase 12: -INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 12:34:56.789', '2017.11.06'); ---Testcase 13: -INSERT INTO "type_TIMESTAMP" VALUES ('2017.11.06 1:3:0', '2017.11.07'); ---Testcase 14: -INSERT INTO "type_BLOB"(col) VALUES (bytea('\xDEADBEEF')); ---Testcase 15: -INSERT INTO typetest VALUES(1,'a', 'b', 'c','2017.11.06 12:34:56.789', '2017.11.06 12:34:56.789' ) ; - ---Testcase 16: -SELECT * FROM "type_STRING"; ---Testcase 18: -SELECT * FROM "type_BYTE"; ---Testcase 19: -SELECT * FROM "type_SINT"; ---Testcase 20: -SELECT * FROM "type_BINT"; ---Testcase 21: -SELECT * FROM "type_INTEGER"; ---Testcase 22: -SELECT * FROM "type_FLOAT"; ---Testcase 23: -SELECT * FROM "type_DOUBLE"; -set datestyle=ISO; ---Testcase 24: -SELECT * FROM "type_TIMESTAMP"; ---Testcase 25: -SELECT * FROM "type_BLOB"; ---Testcase 26: -SELECT * FROM typetest; - ---Testcase 27: -insert into "type_STRING" values('TYPE'); ---Testcase 28: -insert into "type_STRING" values('type'); - --- not pushdown ---Testcase 29: -SELECT *FROM "type_STRING" WHERE col like 'TYP%'; ---Testcase 30: -EXPLAIN SELECT *FROM "type_STRING" WHERE col like 'TYP%'; --- pushdown ---Testcase 31: -SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; ---Testcase 32: -EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%'; - ---Testcase 33: -SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; ---Testcase 34: -EXPLAIN SELECT *FROM "type_STRING" WHERE col ilike 'typ%' and col like 'TYPE'; - ---Testcase 35: -SELECT * FROM "type_TIMESTAMP"; - ---Testcase 36: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; ---Testcase 37: -SELECT * FROM "type_TIMESTAMP" WHERE col > date ('2017.11.06 12:34:56.789') ; - ---Testcase 38: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; ---Testcase 39: -SELECT * FROM "type_TIMESTAMP" WHERE col::text > date ('2017.11.06 12:34:56.789')::text ; - ---Testcase 40: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; ---Testcase 41: -SELECT * FROM "type_TIMESTAMP" WHERE col > b - interval '1 hour'; - ---Testcase 42: -EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "type_TIMESTAMP" WHERE col > b; ---Testcase 43: -SELECT * FROM "type_TIMESTAMP" WHERE col > b; - ---Testcase 48: -INSERT INTO "type_DATE"(col) VALUES ('2021.02.23'); ---Testcase 49: -INSERT INTO "type_DATE"(col) VALUES ('2021/03/08'); ---Testcase 50: -INSERT INTO "type_DATE"(col) VALUES ('9999-12-30'); ---Testcase 58: -SELECT * FROM "type_DATE"; - ---Testcase 51: -INSERT INTO "type_TIME"(col) VALUES ('01:23:45'); ---Testcase 52: -INSERT INTO "type_TIME"(col) VALUES ('01:23:45.6789'); ---Testcase 59: -SELECT * FROM "type_TIME"; - ---Testcase 60: -EXPLAIN VERBOSE -SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; ---Testcase 61: -SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c17, c18, c19, c2, c21, c22, c23, c24 FROM alltypetest; - ---Testcase 53: -CREATE FOREIGN TABLE type_JSON(col JSON OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'type_TEXT'); ---Testcase 54: -INSERT INTO type_JSON(col) VALUES ('[1, 2, "foo", null]'); ---Testcase 55: -INSERT INTO type_JSON(col) VALUES ('{"bar": "baz", "balance": 7.77, "active": false}'::json); ---Testcase 56 -SELECT * FROM type_JSON; ---Testcase 57 -DELETE FROM type_JSON; - ---Testcase 62: -DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; ---Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; ---Testcase 64: -ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; ---Testcase 65: -SELECT * FROM "type_BOOLEAN"; -- OK - --- define INTEGER as TEXT column ---Testcase 67: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE text; ---Testcase 68: -SELECT * FROM "type_INTEGER"; -- OK - --- define INTEGER as bpchar ---Testcase 69: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE char(30); ---Testcase 70: -SELECT * FROM "type_INTEGER"; -- OK --- define INTEGER as varchar ---Testcase 71: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE varchar(30); ---Testcase 72: -SELECT * FROM "type_INTEGER"; -- OK - --- define INTEGER as name ---Testcase 73: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE name; ---Testcase 74: -SELECT * FROM "type_INTEGER"; -- OK - --- define INTEGER as json ---Testcase 75: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE json; ---Testcase 76: -SELECT * FROM "type_INTEGER"; -- OK - --- define INTEGER as time ---Testcase 77: -DELETE FROM "type_INTEGER"; ---Testcase 78: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; ---Testcase 79: -INSERT INTO "type_INTEGER" VALUES (120506); ---Testcase 80: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE time; ---Testcase 81: -SELECT * FROM "type_INTEGER"; -- OK - --- define INTEGER as date ---Testcase 82: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE date; ---Testcase 83: -SELECT * FROM "type_INTEGER"; -- OK - ---Testcase 84: -ALTER FOREIGN TABLE "type_INTEGER" ALTER COLUMN col TYPE int; - ---Testcase 85: -INSERT INTO "type_DOUBLE" VALUES (1.3e-5); ---Testcase 86: -SELECT * FROM "type_DOUBLE"; - --- define DOUBLE as TEXT column ---Testcase 87: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE text; ---Testcase 88: -SELECT * FROM "type_DOUBLE"; -- OK - --- define DOUBLE as bpchar ---Testcase 89: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE char(30); ---Testcase 90: -SELECT * FROM "type_DOUBLE"; -- OK --- define DOUBLE as varchar ---Testcase 91: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE varchar(30); ---Testcase 92: -SELECT * FROM "type_DOUBLE"; -- OK - --- define DOUBLE as name ---Testcase 93: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE name; ---Testcase 94: -SELECT * FROM "type_DOUBLE"; -- OK - --- define DOUBLE as json ---Testcase 95: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE json; ---Testcase 96: -SELECT * FROM "type_DOUBLE"; -- OK - ---Testcase 97: -DELETE FROM "type_DOUBLE"; ---Testcase 98: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; ---Testcase 99: -INSERT INTO "type_DOUBLE" VALUES (120506.12); - --- define DOUBLE as time ---Testcase 100: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE time; ---Testcase 101: -SELECT * FROM "type_DOUBLE"; -- OK - ---Testcase 102: -DELETE FROM "type_DOUBLE"; ---Testcase 103: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; ---Testcase 104: -INSERT INTO "type_DOUBLE" VALUES (1999.012); --- define DOUBLE as date ---Testcase 105: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE date; ---Testcase 106: -SELECT * FROM "type_DOUBLE"; -- OK - ---Testcase 107: -ALTER FOREIGN TABLE "type_DOUBLE" ALTER COLUMN col TYPE float8; - ---Testcase 108: -INSERT INTO "type_DOUBLE" VALUES (PI()); ---Testcase 109: ERR primary key -INSERT INTO "type_DOUBLE" VALUES (PI()); ---Testcase 110: -INSERT INTO "type_DOUBLE" VALUES ('Infinity'); ---Testcase 111: -INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); ---Testcase 113: -SELECT * FROM "type_DOUBLE"; -- OK, +- Inf ---Testcase 114: ERR primary key -INSERT INTO "type_DOUBLE" VALUES ('Infinity'); ---Testcase 115: ERR primary key -INSERT INTO "type_DOUBLE" VALUES ('-Infinity'); ---Testcase 116: -SELECT * FROM "type_DOUBLE"; -- OK, +- Inf - ---Testcase 47: -DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/15.4/aggregate.sql b/sql/16.3/aggregate.sql similarity index 100% rename from sql/15.4/aggregate.sql rename to sql/16.3/aggregate.sql diff --git a/sql/14.9/extra/aggregates.sql b/sql/16.3/extra/aggregates.sql similarity index 97% rename from sql/14.9/extra/aggregates.sql rename to sql/16.3/extra/aggregates.sql index 790e2936..edec91bb 100644 --- a/sql/14.9/extra/aggregates.sql +++ b/sql/16.3/extra/aggregates.sql @@ -65,9 +65,29 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 697: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 698: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 699: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 700: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 701: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: -CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 702: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 703: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 704: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 705: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 706: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; @@ -88,32 +108,32 @@ SELECT avg(four) AS avg_1 FROM onek; --Testcase 2: SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100; ---Testcase 697: +--Testcase 707: CREATE FOREIGN TABLE agg_tb(v int, id integer OPTIONS (key 'true')) SERVER sqlite_svr; ---Testcase 698: +--Testcase 708: INSERT INTO agg_tb(v) VALUES(1), (2), (3); ---Testcase 699: -- Pg 16+ +--Testcase 709: -- Pg 16+ SELECT any_value(v) FROM agg_tb; ---Testcase 700: +--Testcase 710: DELETE FROM agg_tb; ---Testcase 701: +--Testcase 711: INSERT INTO agg_tb(v) VALUES (NULL); ---Testcase 702: -- Pg 16+ +--Testcase 712: -- Pg 16+ SELECT any_value(v) FROM agg_tb; ---Testcase 703: +--Testcase 713: DELETE FROM agg_tb; ---Testcase 704: +--Testcase 714: INSERT INTO agg_tb(v) VALUES (NULL), (1), (2); ---Testcase 705: -- Pg 16+ +--Testcase 715: -- Pg 16+ SELECT any_value(v) FROM agg_tb; ---Testcase 706: +--Testcase 716: CREATE FOREIGN TABLE agg_tb2(v text) SERVER sqlite_svr; ---Testcase 707: +--Testcase 717: INSERT INTO agg_tb2(v) VALUES (array['hello', 'world']); ---Testcase 708: -- Pg 16+ +--Testcase 718: -- Pg 16+ SELECT any_value(v) FROM agg_tb2; -- In 7.1, avg(float4) is computed using float8 arithmetic. @@ -966,6 +986,7 @@ select distinct min(f1), max(f1) from minmaxtest; select max(min(unique1)) from tenk1; --Testcase 88: select (select max(min(unique1)) from int8_tbl) from tenk1; +--Testcase 719: select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) from tenk1 a1(col1))) from tenk1 a2(col2); @@ -1053,11 +1074,13 @@ select t1.f1 from t1 left join t2 using (f1) group by t1.f1; select t1.f1 from t1 left join t2 using (f1) group by f1; -- check case where we have to inject nullingrels into coerced join alias +--Testcase 720: select f1, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) group by f1; -- same, for a RelabelType coercion +--Testcase 721: select f2, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) group by f2; @@ -1069,12 +1092,14 @@ drop foreign table t1, t2; -- -- Ensure we order by four. This suits the most aggregate functions. +--Testcase 722: explain (costs off) select sum(two order by two),max(four order by four), min(four order by four) from tenk1; -- Ensure we order by two. It's a tie between ordering by two and four but -- we tiebreak on the aggregate's position. +--Testcase 723: explain (costs off) select sum(two order by two), max(four order by four), @@ -1082,6 +1107,7 @@ select from tenk1; -- Similar to above, but tiebreak on ordering by four +--Testcase 724: explain (costs off) select max(four order by four), sum(two order by two), @@ -1090,6 +1116,7 @@ from tenk1; -- Ensure this one orders by ten since there are 3 aggregates that require ten -- vs two that suit two and four. +--Testcase 725: explain (costs off) select max(four order by four), sum(two order by two), @@ -1100,6 +1127,7 @@ from tenk1; -- Try a case involving a GROUP BY clause where the GROUP BY column is also -- part of an aggregate's ORDER BY clause. We want a sort order that works -- for the GROUP BY along with the first and the last aggregate. +--Testcase 726: explain (costs off) select sum(unique1 order by ten, two), sum(unique1 order by four), @@ -1110,6 +1138,7 @@ group by ten; -- Ensure that we never choose to provide presorted input to an Aggref with -- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure -- these sorts are performed individually rather than at the query level. +--Testcase 727: explain (costs off) select sum(unique1 order by two), sum(unique1 order by four), @@ -1119,11 +1148,13 @@ from tenk1 group by ten; -- Ensure consecutive NULLs are properly treated as distinct from each other +--Testcase 728: select array_agg(distinct val) -from (select null as val from generate_series(1, 2)) g; +from (select null as val from generate_series(1, 2)); -- Ensure no ordering is requested when enable_presorted_aggregate is off set enable_presorted_aggregate to off; +--Testcase 729: explain (costs off) select sum(two order by two) from tenk1; reset enable_presorted_aggregate; @@ -1372,7 +1403,9 @@ select string_agg(v, decode('ee', 'hex')) from bytea_test_table; drop foreign table bytea_test_table; -- Test parallel string_agg and array_agg +--Testcase 730: create foreign table pagg_test (x int, y int) server sqlite_svr; +--Testcase 731: insert into pagg_test select (case x % 4 when 1 then null else x end), x % 10 from generate_series(1,5000) x; @@ -1385,6 +1418,7 @@ set bytea_output = 'escape'; set max_parallel_workers_per_gather = 2; -- create a view as we otherwise have to repeat this query a few times. +--Testcase 732: create view v_pagg_test AS select y, @@ -1413,14 +1447,17 @@ from ( group by y; -- Ensure results are correct. +--Testcase 733: select * from v_pagg_test order by y; -- Ensure parallel aggregation is actually being used. +--Testcase 734: explain (costs off) select * from v_pagg_test order by y; set max_parallel_workers_per_gather = 0; -- Ensure results are the same without parallel aggregation. +--Testcase 735: select * from v_pagg_test order by y; -- Clean up @@ -1431,7 +1468,9 @@ reset parallel_leader_participation; reset parallel_tuple_cost; reset parallel_setup_cost; +--Testcase 736: drop view v_pagg_test; +--Testcase 737: drop foreign table pagg_test; @@ -1461,8 +1500,11 @@ insert into agg_t17 values ('a', 'b'); select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0') from agg_t17; +--Testcase 738: create foreign table agg_t170(v int) server sqlite_svr; +--Testcase 739: insert into agg_t170(v) values (1), (2), (3); +--Testcase 740: select any_value(v) filter (where v > 2) from agg_t170; -- outer reference in FILTER (PostgreSQL extension) @@ -2128,6 +2170,7 @@ ROLLBACK; -- test multiple usage of an aggregate whose finalfn returns a R/W datum BEGIN; +--Testcase 741: CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN @@ -2135,6 +2178,7 @@ BEGIN END; $$; +--Testcase 742: CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray LANGUAGE plpgsql STRICT IMMUTABLE AS $$ DECLARE @@ -2146,12 +2190,14 @@ BEGIN END; $$; +--Testcase 743: CREATE AGGREGATE rwagg(anyarray) ( STYPE = anyarray, SFUNC = rwagg_sfunc, FINALFUNC = rwagg_finalfunc ); +--Testcase 744: CREATE FUNCTION eatarray(x real[]) RETURNS real[] LANGUAGE plpgsql STRICT IMMUTABLE AS $$ BEGIN @@ -2160,8 +2206,11 @@ BEGIN END; $$; +--Testcase 745: CREATE FOREIGN TABLE float_tb(f real) SERVER sqlite_svr; +--Testcase 746: INSERT INTO float_tb(f) VALUES (1.0); +--Testcase 747: SELECT eatarray(rwagg(ARRAY[f::real])), eatarray(rwagg(ARRAY[f::real])) FROM float_tb; ROLLBACK; @@ -2447,6 +2496,11 @@ set work_mem to default; union all (select * from agg_group_4 except select * from agg_hash_4); +--Testcase 748: +DELETE FROM INT4_TBL; +--Testcase 749: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/15.4/extra/bitstring.sql b/sql/16.3/extra/bitstring.sql similarity index 100% rename from sql/15.4/extra/bitstring.sql rename to sql/16.3/extra/bitstring.sql diff --git a/sql/15.4/extra/bool.sql b/sql/16.3/extra/bool.sql similarity index 99% rename from sql/15.4/extra/bool.sql rename to sql/16.3/extra/bool.sql index c1c58db1..f464c35d 100644 --- a/sql/15.4/extra/bool.sql +++ b/sql/16.3/extra/bool.sql @@ -186,5 +186,8 @@ DELETE FROM "type_BOOLEAN_oper" WHERE b2; --Testcase 78: SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 79: +DELETE FROM "type_BOOLEAN"; + --Testcase 003: DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/15.4/extra/encodings.sql b/sql/16.3/extra/encodings.sql similarity index 100% rename from sql/15.4/extra/encodings.sql rename to sql/16.3/extra/encodings.sql diff --git a/sql/16.0/extra/float4.sql b/sql/16.3/extra/float4.sql similarity index 100% rename from sql/16.0/extra/float4.sql rename to sql/16.3/extra/float4.sql diff --git a/sql/16.0/extra/float8.sql b/sql/16.3/extra/float8.sql similarity index 99% rename from sql/16.0/extra/float8.sql rename to sql/16.3/extra/float8.sql index d5014224..ae9d234b 100644 --- a/sql/16.0/extra/float8.sql +++ b/sql/16.3/extra/float8.sql @@ -1104,6 +1104,9 @@ rollback; --Testcase 269: drop type xfloat8 cascade; +--Testcase 363: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/16.0/extra/insert.sql b/sql/16.3/extra/insert.sql similarity index 100% rename from sql/16.0/extra/insert.sql rename to sql/16.3/extra/insert.sql diff --git a/sql/16.3/extra/int4.sql b/sql/16.3/extra/int4.sql new file mode 100644 index 00000000..503bb7a0 --- /dev/null +++ b/sql/16.3/extra/int4.sql @@ -0,0 +1,577 @@ +-- +-- INT4 Based on PostgreSQL tests, please don't add additional tests here, use other test files +-- +--Testcase 61: +CREATE EXTENSION sqlite_fdw; +--Testcase 62: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 63: +CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 64: +CREATE FOREIGN TABLE INT4_TMP(f1 int4, f2 int4, id int OPTIONS (key 'true')) SERVER sqlite_svr; + +--Testcase 1: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); + +--Testcase 2: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); + +--Testcase 3: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); + +--Testcase 4: +INSERT INTO INT4_TBL(f1) VALUES ('34.5'); + +-- largest and smallest values +--Testcase 5: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); + +--Testcase 6: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + +-- bad input values -- should give errors +--Testcase 7: +INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); +--Testcase 8: +INSERT INTO INT4_TBL(f1) VALUES ('asdf'); +--Testcase 9: +INSERT INTO INT4_TBL(f1) VALUES (' '); +--Testcase 10: +INSERT INTO INT4_TBL(f1) VALUES (' asdf '); +--Testcase 11: +INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); +--Testcase 12: +INSERT INTO INT4_TBL(f1) VALUES ('123 5'); +--Testcase 13: +INSERT INTO INT4_TBL(f1) VALUES (''); + + +--Testcase 14: +SELECT * FROM INT4_TBL; + +-- Also try it with non-error-throwing API +--Testcase 137: +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 138: +INSERT INTO NON_ERROR_THROWING_API_INT4 VALUES ('34', 1), ('asdf', 2), ('1000000000000', 3); +--Testcase 139: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 1; +--Testcase 140: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 2; +--Testcase 141: +SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3; +--Testcase 142: +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3), 'int4'); + +--Testcase 15: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <> int2 '0'; + +--Testcase 16: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <> int4 '0'; + +--Testcase 17: +SELECT i.* FROM INT4_TBL i WHERE i.f1 = int2 '0'; + +--Testcase 18: +SELECT i.* FROM INT4_TBL i WHERE i.f1 = int4 '0'; + +--Testcase 19: +SELECT i.* FROM INT4_TBL i WHERE i.f1 < int2 '0'; + +--Testcase 20: +SELECT i.* FROM INT4_TBL i WHERE i.f1 < int4 '0'; + +--Testcase 21: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <= int2 '0'; + +--Testcase 22: +SELECT i.* FROM INT4_TBL i WHERE i.f1 <= int4 '0'; + +--Testcase 23: +SELECT i.* FROM INT4_TBL i WHERE i.f1 > int2 '0'; + +--Testcase 24: +SELECT i.* FROM INT4_TBL i WHERE i.f1 > int4 '0'; + +--Testcase 25: +SELECT i.* FROM INT4_TBL i WHERE i.f1 >= int2 '0'; + +--Testcase 26: +SELECT i.* FROM INT4_TBL i WHERE i.f1 >= int4 '0'; + +-- positive odds +--Testcase 27: +SELECT i.* FROM INT4_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; + +-- any evens +--Testcase 28: +SELECT i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; + +--Testcase 29: +SELECT i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i; + +--Testcase 30: +SELECT i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i +WHERE abs(f1) < 1073741824; + +--Testcase 31: +SELECT i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i; + +--Testcase 32: +SELECT i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i +WHERE abs(f1) < 1073741824; + +--Testcase 33: +SELECT i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i; + +--Testcase 34: +SELECT i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i +WHERE f1 < 2147483646; + +--Testcase 35: +SELECT i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i; + +--Testcase 36: +SELECT i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i +WHERE f1 < 2147483646; + +--Testcase 37: +SELECT i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i; + +--Testcase 38: +SELECT i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i +WHERE f1 > -2147483647; + +--Testcase 39: +SELECT i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i; + +--Testcase 40: +SELECT i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i +WHERE f1 > -2147483647; + +--Testcase 41: +SELECT i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i; + +--Testcase 42: +SELECT i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i; + +-- +-- more complex expressions +-- + +-- variations on unary minus parsing + +--Testcase 65: +DELETE FROM INT4_TMP; +--Testcase 66: +INSERT INTO INT4_TMP VALUES (-2, 3); +--Testcase 67: +SELECT f1 + f2 as one FROM INT4_TMP; + +--Testcase 68: +DELETE FROM INT4_TMP; +--Testcase 69: +INSERT INTO INT4_TMP VALUES (4, 2); +--Testcase 70: +SELECT f1 - f2 as two FROM INT4_TMP; + +--Testcase 46: +DELETE FROM INT4_TMP; +--Testcase 71: +INSERT INTO INT4_TMP VALUES (2, 1); +--Testcase 72: +SELECT f1- -f2 as three FROM INT4_TMP; + +--Testcase 47: +DELETE FROM INT4_TMP; +--Testcase 73: +INSERT INTO INT4_TMP VALUES (2, 2); +--Testcase 74: +SELECT f1 - -f2 as four FROM INT4_TMP; + +--Testcase 75: +DELETE FROM INT4_TMP; +--Testcase 76: +INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int2, '16'::int2 / '4'::int2); +--Testcase 77: +SELECT f1 = f2 AS true FROM INT4_TMP; + +--Testcase 78: +DELETE FROM INT4_TMP; +--Testcase 79: +INSERT INTO INT4_TMP VALUES ('2'::int2 * '2'::int4, '16'::int2 / '4'::int4); +--Testcase 80: +SELECT f1 = f2 AS true FROM INT4_TMP; + +--Testcase 81: +DELETE FROM INT4_TMP; +--Testcase 82: +INSERT INTO INT4_TMP VALUES ('2'::int4 * '2'::int2, '16'::int4 / '4'::int2); +--Testcase 83: +SELECT f1 = f2 AS true FROM INT4_TMP; + +--Testcase 84: +DELETE FROM INT4_TMP; +--Testcase 85: +INSERT INTO INT4_TMP VALUES ('1000'::int4, '999'::int4); +--Testcase 86: +SELECT f1 < f2 AS false FROM INT4_TMP; + +--Testcase 50: +DELETE FROM INT4_TMP; +--Testcase 91: +INSERT INTO INT4_TMP VALUES (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1); +--Testcase 92: +SELECT f1 as ten FROM INT4_TMP; + +--Testcase 51: +DELETE FROM INT4_TMP; +--Testcase 93: +INSERT INTO INT4_TMP VALUES (2 , 2); +--Testcase 94: +SELECT f1 + f1/f2 as three FROM INT4_TMP; + +--Testcase 52: +DELETE FROM INT4_TMP; +--Testcase 95: +INSERT INTO INT4_TMP VALUES (2 , 2); +--Testcase 96: +SELECT (f1 + f2)/f2 as two FROM INT4_TMP; + +-- corner case +--Testcase 54: +DELETE FROM INT4_TMP; +--Testcase 97: +INSERT INTO INT4_TMP VALUES (-1); +--Testcase 98: +SELECT (f1<<31)::text FROM INT4_TMP; + +--Testcase 56: +DELETE FROM INT4_TMP; +--Testcase 99: +INSERT INTO INT4_TMP VALUES (-1); +--Testcase 100: +SELECT ((f1<<31)+1)::text FROM INT4_TMP; + +-- check sane handling of INT_MIN overflow cases +--Testcase 58: +DELETE FROM INT4_TMP; +--Testcase 101: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int4); +--Testcase 102: +SELECT f1 * f2 FROM INT4_TMP; +--Testcase 103: +SELECT f1 / f2 FROM INT4_TMP; +--Testcase 104: +SELECT f1 % f2 FROM INT4_TMP; + +--Testcase 60: +DELETE FROM INT4_TMP; +--Testcase 105: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-1)::int2); +--Testcase 106: +SELECT f1 * f2 FROM INT4_TMP; +--Testcase 107: +SELECT f1 / f2 FROM INT4_TMP; +--Testcase 108: +SELECT f1 % f2 FROM INT4_TMP; + +-- check rounding when casting from float +--Testcase 109: +CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 110: +DELETE FROM FLOAT8_TMP; +--Testcase 111: +INSERT INTO FLOAT8_TMP VALUES + (-2.5::float8), + (-1.5::float8), + (-0.5::float8), + (0.0::float8), + (0.5::float8), + (1.5::float8), + (2.5::float8); + +--Testcase 112: +SELECT f1 as x, f1::int4 as int4_value FROM FLOAT8_TMP; + +-- check rounding when casting from numeric +--Testcase 113: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 114: +DELETE FROM NUMERIC_TMP; +--Testcase 115: +INSERT INTO NUMERIC_TMP VALUES + (-2.5::numeric), + (-1.5::numeric), + (-0.5::numeric), + (0.0::numeric), + (0.5::numeric), + (1.5::numeric), + (2.5::numeric); +--Testcase 116: +SELECT f1 as x, f1::int4 as int4_value FROM NUMERIC_TMP; + +-- test gcd() +--Testcase 117: +DELETE FROM INT4_TMP; +--Testcase 118: +INSERT INTO INT4_TMP VALUES + (0::int4, 0::int4), + (0::int4, 6410818::int4), + (61866666::int4, 6410818::int4), + (-61866666::int4, 6410818::int4), + ((-2147483648)::int4, 1::int4), + ((-2147483648)::int4, 2147483647::int4), + ((-2147483648)::int4, 1073741824::int4); +--Testcase 119: +SELECT f1, f2, gcd(f1, f2), gcd(f1, -f2), gcd(f2, f1), gcd(-f2, f1) FROM INT4_TMP; + +--Testcase 120: +DELETE FROM INT4_TMP; +--Testcase 121: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 0::int4); +--Testcase 122: +SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow + +--Testcase 123: +DELETE FROM INT4_TMP; +--Testcase 124: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, (-2147483648)::int4); +--Testcase 125: +SELECT gcd(f1, f2) FROM INT4_TMP; -- overflow + +-- test lcm() +--Testcase 126: +DELETE FROM INT4_TMP; +--Testcase 127: +INSERT INTO INT4_TMP VALUES + (0::int4, 0::int4), + (0::int4, 42::int4), + (42::int4, 42::int4), + (330::int4, 462::int4), + (-330::int4, 462::int4), + ((-2147483648)::int4, 0::int4); +--Testcase 128: +SELECT f1, f2, lcm(f1, f2), lcm(f1, -f2), lcm(f2, f1), lcm(-f2, f1) FROM INT4_TMP; + +--Testcase 129: +DELETE FROM INT4_TMP; +--Testcase 130: +INSERT INTO INT4_TMP VALUES ((-2147483648)::int4, 1::int4); +--Testcase 131: +SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow + +--Testcase 132: +DELETE FROM INT4_TMP; +--Testcase 133: +INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); +--Testcase 134: +SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow + +-- non-decimal literals +--Testcase 143: +CREATE FOREIGN TABLE special_case_int4 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 144: +INSERT INTO special_case_int4 VALUES ('0b100101'::int4); +--Testcase 145: +SELECT f1 FROM special_case_int4; + +--Testcase 146: +DELETE FROM special_case_int4; +--Testcase 147: +INSERT INTO special_case_int4 VALUES ('0o273'::int4); +--Testcase 148: +SELECT f1 FROM special_case_int4; + +--Testcase 149: +DELETE FROM special_case_int4; +--Testcase 150: +INSERT INTO special_case_int4 VALUES ('0x42F'::int4); +--Testcase 151: +SELECT f1 FROM special_case_int4; + +--Testcase 152: +DELETE FROM special_case_int4; +--Testcase 153: +INSERT INTO special_case_int4 VALUES ('0b'::int4); +--Testcase 154: +SELECT f1 FROM special_case_int4; + +--Testcase 155: +DELETE FROM special_case_int4; +--Testcase 156: +INSERT INTO special_case_int4 VALUES ('0x'::int4); +--Testcase 157: +SELECT f1 FROM special_case_int4; + +--Testcase 158: +DELETE FROM special_case_int4; +--Testcase 159: +INSERT INTO special_case_int4 VALUES ('0x'::int4); +--Testcase 160: +SELECT f1 FROM special_case_int4; + +-- cases near overflow +--Testcase 161: +DELETE FROM special_case_int4; +--Testcase 162: +INSERT INTO special_case_int4 VALUES ('0b1111111111111111111111111111111'::int4); +--Testcase 163: +SELECT f1 FROM special_case_int4; + +--Testcase 164: +DELETE FROM special_case_int4; +--Testcase 165: +INSERT INTO special_case_int4 VALUES ('0b10000000000000000000000000000000'::int4); +--Testcase 166: +SELECT f1 FROM special_case_int4; + +--Testcase 167: +DELETE FROM special_case_int4; +--Testcase 168: +INSERT INTO special_case_int4 VALUES ('0o17777777777'::int4); +--Testcase 169: +SELECT f1 FROM special_case_int4; + +--Testcase 170: +DELETE FROM special_case_int4; +--Testcase 171: +INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4); +--Testcase 172: +SELECT f1 FROM special_case_int4; + +--Testcase 173: +DELETE FROM special_case_int4; +--Testcase 174: +INSERT INTO special_case_int4 VALUES ('0x7FFFFFFF'::int4); +--Testcase 175: +SELECT f1 FROM special_case_int4; + +--Testcase 176: +DELETE FROM special_case_int4; +--Testcase 177: +INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); +--Testcase 178: +SELECT f1 FROM special_case_int4; + +--Testcase 179: +DELETE FROM special_case_int4; +--Testcase 180: +INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000000'::int4); +--Testcase 181: +SELECT f1 FROM special_case_int4; + +--Testcase 182: +DELETE FROM special_case_int4; +--Testcase 183: +INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000001'::int4); +--Testcase 184: +SELECT f1 FROM special_case_int4; + +--Testcase 185: +DELETE FROM special_case_int4; +--Testcase 186: +INSERT INTO special_case_int4 VALUES ('-0o20000000000'::int4); +--Testcase 187: +SELECT f1 FROM special_case_int4; + +--Testcase 188: +DELETE FROM special_case_int4; +--Testcase 189: +INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4); +--Testcase 190: +SELECT f1 FROM special_case_int4; + +--Testcase 191: +DELETE FROM special_case_int4; +--Testcase 192: +INSERT INTO special_case_int4 VALUES ('-0x80000000'::int4); +--Testcase 193: +SELECT f1 FROM special_case_int4; + +--Testcase 194: +DELETE FROM special_case_int4; +--Testcase 195: +INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); +--Testcase 196: +SELECT f1 FROM special_case_int4; + + +-- underscores +--Testcase 197: +DELETE FROM special_case_int4; +--Testcase 198: +INSERT INTO special_case_int4 VALUES ('1_000_000'::int4); +--Testcase 199: +SELECT f1 FROM special_case_int4; + +--Testcase 200: +DELETE FROM special_case_int4; +--Testcase 201: +INSERT INTO special_case_int4 VALUES ('1_2_3'::int4); +--Testcase 202: +SELECT f1 FROM special_case_int4; + +--Testcase 203: +DELETE FROM special_case_int4; +--Testcase 204: +INSERT INTO special_case_int4 VALUES ('0x1EEE_FFFF'::int4); +--Testcase 205: +SELECT f1 FROM special_case_int4; + +--Testcase 206: +DELETE FROM special_case_int4; +--Testcase 207: +INSERT INTO special_case_int4 VALUES ('0o2_73'::int4); +--Testcase 208: +SELECT f1 FROM special_case_int4; + +--Testcase 209: +DELETE FROM special_case_int4; +--Testcase 210: +INSERT INTO special_case_int4 VALUES ('0b_10_0101'::int4); +--Testcase 211: +SELECT f1 FROM special_case_int4; + +-- error cases +--Testcase 212: +DELETE FROM special_case_int4; +--Testcase 213: +INSERT INTO special_case_int4 VALUES ('_100'::int4); +--Testcase 214: +SELECT f1 FROM special_case_int4; + +--Testcase 215: +DELETE FROM special_case_int4; +--Testcase 216: +INSERT INTO special_case_int4 VALUES ('100_'::int4); +--Testcase 217: +SELECT f1 FROM special_case_int4; + +--Testcase 218: +DELETE FROM special_case_int4; +--Testcase 219: +INSERT INTO special_case_int4 VALUES ('100__000'::int4); +--Testcase 220: +SELECT f1 FROM special_case_int4; + +--Testcase 221: +DELETE FROM INT4_TBL; + +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; + +--Testcase 135: +DROP SERVER sqlite_svr; +--Testcase 136: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/16.0/extra/int8.sql b/sql/16.3/extra/int8.sql similarity index 94% rename from sql/16.0/extra/int8.sql rename to sql/16.3/extra/int8.sql index 3989b9e6..7d0a2fe1 100644 --- a/sql/16.0/extra/int8.sql +++ b/sql/16.3/extra/int8.sql @@ -53,11 +53,17 @@ INSERT INTO INT8_TBL(q1) VALUES (''); SELECT * FROM INT8_TBL; -- Also try it with non-error-throwing API +--Testcase 251: CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 252: INSERT INTO NON_ERROR_THROWING_API_INT8 VALUES ('34', 1), ('asdf', 2), ('10000000000000000000', 3); +--Testcase 253: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 1; +--Testcase 254: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 2; +--Testcase 255: SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3; +--Testcase 256: SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3), 'int8'); @@ -625,113 +631,194 @@ SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow -- non-decimal literals +--Testcase 257: CREATE FOREIGN TABLE special_case_int8 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 258: INSERT INTO special_case_int8 VALUES ('0b100101'::int8); +--Testcase 259: SELECT f1 FROM special_case_int8; +--Testcase 260: DELETE FROM special_case_int8; +--Testcase 261: INSERT INTO special_case_int8 VALUES ('0o273'::int8); +--Testcase 262: SELECT f1 FROM special_case_int8; +--Testcase 263: DELETE FROM special_case_int8; +--Testcase 264: INSERT INTO special_case_int8 VALUES ('0x42F'::int8); +--Testcase 265: SELECT f1 FROM special_case_int8; +--Testcase 266: DELETE FROM special_case_int8; +--Testcase 267: INSERT INTO special_case_int8 VALUES ('0b'::int8); +--Testcase 268: SELECT f1 FROM special_case_int8; +--Testcase 269: DELETE FROM special_case_int8; +--Testcase 270: INSERT INTO special_case_int8 VALUES ('0o'::int8); +--Testcase 271: SELECT f1 FROM special_case_int8; +--Testcase 272: DELETE FROM special_case_int8; +--Testcase 273: INSERT INTO special_case_int8 VALUES ('0x'::int8); +--Testcase 274: SELECT f1 FROM special_case_int8; -- cases near overflow +--Testcase 275: DELETE FROM special_case_int8; +--Testcase 276: INSERT INTO special_case_int8 VALUES ('0b111111111111111111111111111111111111111111111111111111111111111'::int8); +--Testcase 277: SELECT f1 FROM special_case_int8; +--Testcase 278: DELETE FROM special_case_int8; +--Testcase 279: INSERT INTO special_case_int8 VALUES ('0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 280: SELECT f1 FROM special_case_int8; +--Testcase 281: DELETE FROM special_case_int8; +--Testcase 282: INSERT INTO special_case_int8 VALUES ('0o777777777777777777777'::int8); +--Testcase 283: SELECT f1 FROM special_case_int8; +--Testcase 284: DELETE FROM special_case_int8; +--Testcase 285: INSERT INTO special_case_int8 VALUES ('0o1000000000000000000000'::int8); +--Testcase 286: SELECT f1 FROM special_case_int8; +--Testcase 287: DELETE FROM special_case_int8; +--Testcase 288: INSERT INTO special_case_int8 VALUES ('0x7FFFFFFFFFFFFFFF'::int8); +--Testcase 289: SELECT f1 FROM special_case_int8; +--Testcase 290: DELETE FROM special_case_int8; +--Testcase 291: INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::int8); +--Testcase 292: SELECT f1 FROM special_case_int8; +--Testcase 293: DELETE FROM special_case_int8; +--Testcase 294: INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 295: SELECT f1 FROM special_case_int8; +--Testcase 296: DELETE FROM special_case_int8; +--Testcase 297: INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000001'::int8); +--Testcase 298: SELECT f1 FROM special_case_int8; +--Testcase 299: DELETE FROM special_case_int8; +--Testcase 300: INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000000'::int8); +--Testcase 301: SELECT f1 FROM special_case_int8; +--Testcase 302: DELETE FROM special_case_int8; +--Testcase 303: INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000001'::int8); +--Testcase 304: SELECT f1 FROM special_case_int8; +--Testcase 305: DELETE FROM special_case_int8; +--Testcase 306: INSERT INTO special_case_int8 VALUES ('-0x8000000000000000'::int8); +--Testcase 307: SELECT f1 FROM special_case_int8; +--Testcase 308: DELETE FROM special_case_int8; +--Testcase 309: INSERT INTO special_case_int8 VALUES ('-0x8000000000000001'::int8); +--Testcase 310: SELECT f1 FROM special_case_int8; -- underscores +--Testcase 311: DELETE FROM special_case_int8; +--Testcase 312: INSERT INTO special_case_int8 VALUES ('1_000_000'::int8); +--Testcase 313: SELECT f1 FROM special_case_int8; +--Testcase 314: DELETE FROM special_case_int8; +--Testcase 315: INSERT INTO special_case_int8 VALUES ('1_2_3'::int8); +--Testcase 316: SELECT f1 FROM special_case_int8; +--Testcase 317: DELETE FROM special_case_int8; +--Testcase 318: INSERT INTO special_case_int8 VALUES ('0x1EEE_FFFF'::int8); +--Testcase 319: SELECT f1 FROM special_case_int8; +--Testcase 320: DELETE FROM special_case_int8; +--Testcase 321: INSERT INTO special_case_int8 VALUES ('0o2_73'::int8); +--Testcase 322: SELECT f1 FROM special_case_int8; +--Testcase 323: DELETE FROM special_case_int8; +--Testcase 324: INSERT INTO special_case_int8 VALUES ('0b_10_0101'::int8); +--Testcase 325: SELECT f1 FROM special_case_int8; -- error cases +--Testcase 326: DELETE FROM special_case_int8; +--Testcase 327: INSERT INTO special_case_int8 VALUES ('_100'::int8); +--Testcase 328: SELECT f1 FROM special_case_int8; +--Testcase 329: DELETE FROM special_case_int8; +--Testcase 330: INSERT INTO special_case_int8 VALUES ('100_'::int8); +--Testcase 331: SELECT f1 FROM special_case_int8; +--Testcase 332: DELETE FROM special_case_int8; +--Testcase 333: INSERT INTO special_case_int8 VALUES ('100__000'::int8); +--Testcase 334: SELECT f1 FROM special_case_int8; +--Testcase 335: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/16.0/extra/join.sql b/sql/16.3/extra/join.sql similarity index 98% rename from sql/16.0/extra/join.sql rename to sql/16.3/extra/join.sql index 77d5bf23..5ee165df 100644 --- a/sql/16.0/extra/join.sql +++ b/sql/16.3/extra/join.sql @@ -63,13 +63,46 @@ CREATE FOREIGN TABLE tenk2 ( --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 632: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 633: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 634: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 635: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 636: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 637: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 638: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 639: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 640: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 641: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); + --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 642: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 643: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 644: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 645: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 646: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; @@ -3600,6 +3633,13 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +--Testcase 647: +DELETE FROM INT4_TBL; +--Testcase 648: +DELETE FROM INT8_TBL; +--Testcase 649: +DELETE FROM FLOAT8_TBL; + DO $d$ declare l_rec record; diff --git a/sql/16.3/extra/limit.sql b/sql/16.3/extra/limit.sql new file mode 100644 index 00000000..8a8276a7 --- /dev/null +++ b/sql/16.3/extra/limit.sql @@ -0,0 +1,458 @@ +-- +-- LIMIT +-- Check the LIMIT/OFFSET feature of SELECT +-- +--Testcase 27: +CREATE EXTENSION sqlite_fdw; +--Testcase 28: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 29: +CREATE FOREIGN TABLE onek( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; + +--Testcase 30: +CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); + +--Testcase 31: +CREATE FOREIGN TABLE INT8_TMP( + q1 int8, + q2 int8, + q3 int4, + q4 int2, + q5 text, + id int options (key 'true') +) SERVER sqlite_svr; + +--Testcase 32: +CREATE FOREIGN TABLE tenk1 ( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; + +--Testcase 88: +CREATE TABLE parent_table ( + unique1 int4 PRIMARY KEY, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +); + +--Testcase 89: +CREATE FOREIGN table inherited_table () +INHERITS (parent_table) +SERVER sqlite_svr options (table 'tenk1'); + +--Testcase 1: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 50 + ORDER BY unique1 LIMIT 2; +--Testcase 2: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 60 + ORDER BY unique1 LIMIT 5; +--Testcase 3: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 60 AND unique1 < 63 + ORDER BY unique1 LIMIT 5; +--Testcase 4: +SELECT ''::text AS three, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 100 + ORDER BY unique1 LIMIT 3 OFFSET 20; +--Testcase 5: +SELECT ''::text AS zero, unique1, unique2, stringu1 + FROM onek WHERE unique1 < 50 + ORDER BY unique1 DESC LIMIT 8 OFFSET 99; +--Testcase 6: +SELECT ''::text AS eleven, unique1, unique2, stringu1 + FROM onek WHERE unique1 < 50 + ORDER BY unique1 DESC LIMIT 20 OFFSET 39; +--Testcase 7: +SELECT ''::text AS ten, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 OFFSET 990; +--Testcase 8: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 OFFSET 990 LIMIT 5; +--Testcase 9: +SELECT ''::text AS five, unique1, unique2, stringu1 + FROM onek + ORDER BY unique1 LIMIT 5 OFFSET 900; + +-- Test null limit and offset. The planner would discard a simple null +-- constant, so to ensure executor is exercised, do this: +--Testcase 10: +select * from int8_tbl limit (case when random() < 0.5 then null::bigint end); +--Testcase 11: +select * from int8_tbl offset (case when random() < 0.5 then null::bigint end); + +-- Test assorted cases involving backwards fetch from a LIMIT plan node +begin; + +declare c1 scroll cursor for select * from int8_tbl order by q1 limit 10; +--Testcase 12: +fetch all in c1; +--Testcase 13: +fetch 1 in c1; +--Testcase 14: +fetch backward 1 in c1; +--Testcase 33: +fetch backward all in c1; +--Testcase 34: +fetch backward 1 in c1; +--Testcase 35: +fetch all in c1; + +declare c2 scroll cursor for select * from int8_tbl limit 3; +--Testcase 36: +fetch all in c2; +--Testcase 37: +fetch 1 in c2; +--Testcase 38: +fetch backward 1 in c2; +--Testcase 39: +fetch backward all in c2; +--Testcase 40: +fetch backward 1 in c2; +--Testcase 41: +fetch all in c2; + +declare c3 scroll cursor for select * from int8_tbl offset 3; +--Testcase 42: +fetch all in c3; +--Testcase 43: +fetch 1 in c3; +--Testcase 44: +fetch backward 1 in c3; +--Testcase 45: +fetch backward all in c3; +--Testcase 46: +fetch backward 1 in c3; +--Testcase 47: +fetch all in c3; + +declare c4 scroll cursor for select * from int8_tbl offset 10; +--Testcase 48: +fetch all in c4; +--Testcase 49: +fetch 1 in c4; +--Testcase 50: +fetch backward 1 in c4; +--Testcase 51: +fetch backward all in c4; +--Testcase 52: +fetch backward 1 in c4; +--Testcase 53: +fetch all in c4; + +declare c5 scroll cursor for select * from int8_tbl order by q1 fetch first 2 rows with ties; +--Testcase 54: +fetch all in c5; +--Testcase 55: +fetch 1 in c5; +--Testcase 56: +fetch backward 1 in c5; +--Testcase 57: +fetch backward 1 in c5; +--Testcase 58: +fetch all in c5; +--Testcase 59: +fetch backward all in c5; +--Testcase 60: +fetch all in c5; +--Testcase 61: +fetch backward all in c5; + +rollback; + +-- Stress test for variable LIMIT in conjunction with bounded-heap sorting +--Testcase 62: +DELETE FROM INT8_TMP; +--Testcase 63: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series(1,10) q1; + +--Testcase 64: +SELECT + (SELECT s.q1 + FROM (VALUES (1)) AS x, + (SELECT q1 FROM INT8_TMP as n + ORDER BY q1 LIMIT 1 OFFSET s.q1-1) AS y) AS z + FROM INT8_TMP AS s; + +-- +-- Test behavior of volatile and set-returning functions in conjunction +-- with ORDER BY and LIMIT. +-- + +--Testcase 65: +create temp sequence testseq; + +--Testcase 15: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10; + +--Testcase 16: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10; + +--Testcase 90: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10 offset 5; + +--Testcase 91: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 limit 10 offset 5; + +--Testcase 17: +select currval('testseq'); + +--Testcase 92: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10; + +--Testcase 93: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10; + + +--Testcase 94: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10 offset 5; + +--Testcase 95: +select unique1, unique2, nextval('testseq') + from tenk1 order by unique2 desc limit 10 offset 5; + +--Testcase 96: +select currval('testseq'); + +--Testcase 18: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10; + +--Testcase 19: +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10; + +--Testcase 97: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10 offset 5; + +--Testcase 98: +select unique1, unique2, nextval('testseq') + from tenk1 order by tenthous limit 10 offset 5; + +--Testcase 20: +select currval('testseq'); + +-- test for limit and offset when querying table and foreign table inherited +--Testcase 99: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10; + +--Testcase 100: +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10; + +-- when querying regular tables with inherited tables, only limit is pushed-down when no offset is specified +--Testcase 101: +explain (verbose, costs off) +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10 offset 5; + +--Testcase 102: +select unique1, unique2, nextval('testseq') + from parent_table order by tenthous limit 10 offset 5; + +--Testcase 103: +select currval('testseq'); + +--Testcase 21: +explain (verbose, costs off) +select unique1, unique2, generate_series(1,10) + from tenk1 order by unique2 limit 7; + +--Testcase 22: +select unique1, unique2, generate_series(1,10) + from tenk1 order by unique2 limit 7; + +--Testcase 23: +explain (verbose, costs off) +select unique1, unique2, generate_series(1,10) + from tenk1 order by tenthous limit 7; + +--Testcase 24: +select unique1, unique2, generate_series(1,10) + from tenk1 order by tenthous limit 7; + +-- use of random() is to keep planner from folding the expressions together +--Testcase 66: +DELETE FROM INT8_TMP; +--Testcase 67: +INSERT INTO INT8_TMP VALUES (generate_series(0,2), generate_series((random()*.1)::int,2)); +--Testcase 68: +explain (verbose, costs off) +select q1, q2 from int8_tmp; + +--Testcase 69: +select q1, q2 from int8_tmp; + +--Testcase 70: +explain (verbose, costs off) +select q1, q2 from int8_tmp order by q2 desc; + +--Testcase 71: +select q1, q2 from int8_tmp order by q2 desc; + +-- test for failure to set all aggregates' aggtranstype +--Testcase 25: +explain (verbose, costs off) +select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 + from tenk1 group by thousand order by thousand limit 3; + +--Testcase 26: +select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2 + from tenk1 group by thousand order by thousand limit 3; + +-- +-- FETCH FIRST +-- Check the WITH TIES clause +-- + +--Testcase 72: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 2 ROW WITH TIES; + +--Testcase 73: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST ROWS WITH TIES; + +--Testcase 74: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES; + +--Testcase 75: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 2 ROW ONLY; + +-- SKIP LOCKED and WITH TIES are incompatible +--Testcase 104: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; + +-- should fail +--Testcase 76: +SELECT ''::text AS two, unique1, unique2, stringu1 + FROM onek WHERE unique1 > 50 + FETCH FIRST 2 ROW WITH TIES; + +-- test ruleutils +--Testcase 77: +CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; +--Testcase 78: +\d+ limit_thousand_v_1 +--Testcase 79: +CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY; +--Testcase 80: +\d+ limit_thousand_v_2 +--Testcase 81: +CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS WITH TIES; -- fails +--Testcase 82: +CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; +--Testcase 83: +\d+ limit_thousand_v_3 +--Testcase 84: +CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS ONLY; +--Testcase 85: +\d+ limit_thousand_v_4 +-- leave these views + +--Testcase 110: +DELETE FROM int8_tbl; + +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; + +--Testcase 86: +DROP SERVER sqlite_svr; +--Testcase 87: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/16.0/extra/numeric.sql b/sql/16.3/extra/numeric.sql similarity index 100% rename from sql/16.0/extra/numeric.sql rename to sql/16.3/extra/numeric.sql diff --git a/sql/15.4/extra/out_of_range.sql b/sql/16.3/extra/out_of_range.sql similarity index 100% rename from sql/15.4/extra/out_of_range.sql rename to sql/16.3/extra/out_of_range.sql diff --git a/sql/16.0/extra/prepare.sql b/sql/16.3/extra/prepare.sql similarity index 100% rename from sql/16.0/extra/prepare.sql rename to sql/16.3/extra/prepare.sql diff --git a/sql/16.0/extra/select.sql b/sql/16.3/extra/select.sql similarity index 96% rename from sql/16.0/extra/select.sql rename to sql/16.3/extra/select.sql index ccc055f8..4bb0375f 100644 --- a/sql/16.0/extra/select.sql +++ b/sql/16.3/extra/select.sql @@ -52,6 +52,16 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 48: CREATE FOREIGN TABLE person ( @@ -380,6 +390,9 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; + --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/sql/15.4/extra/select_having.sql b/sql/16.3/extra/select_having.sql similarity index 100% rename from sql/15.4/extra/select_having.sql rename to sql/16.3/extra/select_having.sql diff --git a/sql/16.0/extra/sqlite_fdw_post.sql b/sql/16.3/extra/sqlite_fdw_post.sql similarity index 99% rename from sql/16.0/extra/sqlite_fdw_post.sql rename to sql/16.3/extra/sqlite_fdw_post.sql index 974a7ab2..a430ea2e 100644 --- a/sql/16.0/extra/sqlite_fdw_post.sql +++ b/sql/16.3/extra/sqlite_fdw_post.sql @@ -16,12 +16,13 @@ DO $d$ END; $d$; +-- SQLite FDW does not need User and User Mapping. --Testcase 484: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: -CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 756: -CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== @@ -800,10 +801,19 @@ SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1. --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: -CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; @@ -4035,15 +4045,20 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- ============================================================================= -- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. -- ============================================================================= --Testcase 904: CREATE ROLE regress_multi_conn_user1 SUPERUSER; --Testcase 905: CREATE ROLE regress_multi_conn_user2 SUPERUSER; --Testcase 906: -CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 907: -CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 @@ -4062,7 +4077,7 @@ SELECT 1 FROM ft1 LIMIT 1; --Testcase 913: RESET ROLE; --- Should output two connections for sqlite_svr server +-- Should output one cached connection for sqlite_svr server --Testcase 914: SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; COMMIT; @@ -4075,9 +4090,9 @@ SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; -- Clean up --Testcase 917: -DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; --Testcase 918: -DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; --Testcase 919: DROP ROLE regress_multi_conn_user1; --Testcase 920: @@ -4875,9 +4890,9 @@ CREATE FOREIGN TABLE inv_bsz (c1 int ) -- Clean-up --Testcase 733: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: -DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; --Testcase 736: diff --git a/sql/15.4/extra/timestamp.sql b/sql/16.3/extra/timestamp.sql similarity index 100% rename from sql/15.4/extra/timestamp.sql rename to sql/16.3/extra/timestamp.sql diff --git a/sql/16.0/extra/update.sql b/sql/16.3/extra/update.sql similarity index 100% rename from sql/16.0/extra/update.sql rename to sql/16.3/extra/update.sql diff --git a/sql/15.4/extra/uuid.sql b/sql/16.3/extra/uuid.sql similarity index 100% rename from sql/15.4/extra/uuid.sql rename to sql/16.3/extra/uuid.sql diff --git a/sql/15.4/selectfunc.sql b/sql/16.3/selectfunc.sql similarity index 100% rename from sql/15.4/selectfunc.sql rename to sql/16.3/selectfunc.sql diff --git a/sql/16.0/sqlite_fdw.sql b/sql/16.3/sqlite_fdw.sql similarity index 100% rename from sql/16.0/sqlite_fdw.sql rename to sql/16.3/sqlite_fdw.sql diff --git a/sql/15.4/type.sql b/sql/16.3/type.sql similarity index 94% rename from sql/15.4/type.sql rename to sql/16.3/type.sql index a438b6c4..e9e2fbe4 100644 --- a/sql/15.4/type.sql +++ b/sql/16.3/type.sql @@ -141,7 +141,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/sql/16.0/aggregate.sql b/sql/17.0/aggregate.sql similarity index 100% rename from sql/16.0/aggregate.sql rename to sql/17.0/aggregate.sql diff --git a/sql/12.16/extra/aggregates.sql b/sql/17.0/extra/aggregates.sql similarity index 91% rename from sql/12.16/extra/aggregates.sql rename to sql/17.0/extra/aggregates.sql index ef01279d..cdcdf685 100644 --- a/sql/12.16/extra/aggregates.sql +++ b/sql/17.0/extra/aggregates.sql @@ -65,9 +65,29 @@ CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 782: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 783: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 784: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 785: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 786: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 273: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 787: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 788: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 789: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 790: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 791: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); --Testcase 274: CREATE FOREIGN TABLE multi_arg_agg (a int OPTIONS (key 'true'), b int, c text) SERVER sqlite_svr; @@ -351,7 +371,7 @@ SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; --Testcase 606: DELETE FROM agg_t3; ---Testcase 607: -- Pg 14+ +--Testcase 607: INSERT INTO agg_t3 VALUES ('1'::numeric), ('infinity'::numeric); --Testcase 608: SELECT sum(a), avg(a), var_pop(a) FROM agg_t3; @@ -665,7 +685,7 @@ CREATE FOREIGN TABLE bitwise_test( ) SERVER sqlite_svr; -- empty case ---Testcase 43: +--Testcase 43: SELECT BIT_AND(i2) AS "?", BIT_OR(i4) AS "?", @@ -678,7 +698,7 @@ INSERT INTO bitwise_test VALUES (3, 3, 3, null, 2), (7, 7, 7, 3, 4); ---Testcase 45: -- bit_xor Pg 14+ +--Testcase 45: SELECT BIT_AND(i2) AS "1", BIT_AND(i4) AS "1", @@ -961,11 +981,24 @@ explain (costs off) --Testcase 86: select distinct min(f1), max(f1) from minmaxtest; +-- DISTINCT can also trigger wrong answers with hash aggregation (bug #18465) +begin; +set local enable_sort = off; +--Testcase 709: +explain (costs off) + select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) + from int4_tbl t0; +--Testcase 710: +select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) +from int4_tbl t0; +rollback; + -- check for correct detection of nested-aggregate errors --Testcase 87: select max(min(unique1)) from tenk1; --Testcase 88: select (select max(min(unique1)) from int8_tbl) from tenk1; +--Testcase 711: select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) from tenk1 a1(col1))) from tenk1 a2(col2); @@ -1053,11 +1086,13 @@ select t1.f1 from t1 left join t2 using (f1) group by t1.f1; select t1.f1 from t1 left join t2 using (f1) group by f1; -- check case where we have to inject nullingrels into coerced join alias +--Testcase 712: select f1, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) group by f1; -- same, for a RelabelType coercion +--Testcase 713: select f2, count(*) from t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) group by f2; @@ -1069,12 +1104,14 @@ drop foreign table t1, t2; -- -- Ensure we order by four. This suits the most aggregate functions. +--Testcase 714: explain (costs off) select sum(two order by two),max(four order by four), min(four order by four) from tenk1; -- Ensure we order by two. It's a tie between ordering by two and four but -- we tiebreak on the aggregate's position. +--Testcase 715: explain (costs off) select sum(two order by two), max(four order by four), @@ -1082,6 +1119,7 @@ select from tenk1; -- Similar to above, but tiebreak on ordering by four +--Testcase 716: explain (costs off) select max(four order by four), sum(two order by two), @@ -1090,6 +1128,7 @@ from tenk1; -- Ensure this one orders by ten since there are 3 aggregates that require ten -- vs two that suit two and four. +--Testcase 717: explain (costs off) select max(four order by four), sum(two order by two), @@ -1100,6 +1139,7 @@ from tenk1; -- Try a case involving a GROUP BY clause where the GROUP BY column is also -- part of an aggregate's ORDER BY clause. We want a sort order that works -- for the GROUP BY along with the first and the last aggregate. +--Testcase 718: explain (costs off) select sum(unique1 order by ten, two), sum(unique1 order by four), @@ -1110,6 +1150,7 @@ group by ten; -- Ensure that we never choose to provide presorted input to an Aggref with -- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure -- these sorts are performed individually rather than at the query level. +--Testcase 719: explain (costs off) select sum(unique1 order by two), sum(unique1 order by four), @@ -1119,11 +1160,13 @@ from tenk1 group by ten; -- Ensure consecutive NULLs are properly treated as distinct from each other +--Testcase 720: select array_agg(distinct val) -from (select null as val from generate_series(1, 2)) g; +from (select null as val from generate_series(1, 2)); -- Ensure no ordering is requested when enable_presorted_aggregate is off set enable_presorted_aggregate to off; +--Testcase 721: explain (costs off) select sum(two order by two) from tenk1; reset enable_presorted_aggregate; @@ -1222,6 +1265,24 @@ select aggfns(distinct a,a,c order by a) from multi_arg_agg, generate_series(1,2 --Testcase 115: select aggfns(distinct a,b,c order by a,c using ~<~,b) from multi_arg_agg, generate_series(1,2) i; +-- test a more complex permutation that has previous caused issues +--Testcase 761: +create foreign table agg_t22 (c1 text, id int) server sqlite_svr; +--Testcase 762: +create foreign table agg_t23 (id int) server sqlite_svr; +--Testcase 763: +insert into agg_t22 values ('a', 1); +--Testcase 764: +insert into agg_t23 values (1); +--Testcase 765: +select + string_agg(distinct c1, ','), + sum(( + select sum(b.id) + from agg_t23 b + where a.id = b.id +)) from agg_t22 a; + -- check node I/O via view creation and usage, also deparsing logic --Testcase 438: @@ -1372,7 +1433,9 @@ select string_agg(v, decode('ee', 'hex')) from bytea_test_table; drop foreign table bytea_test_table; -- Test parallel string_agg and array_agg +--Testcase 723: create foreign table pagg_test (x int, y int) server sqlite_svr; +--Testcase 724: insert into pagg_test select (case x % 4 when 1 then null else x end), x % 10 from generate_series(1,5000) x; @@ -1385,6 +1448,7 @@ set bytea_output = 'escape'; set max_parallel_workers_per_gather = 2; -- create a view as we otherwise have to repeat this query a few times. +--Testcase 725: create view v_pagg_test AS select y, @@ -1413,14 +1477,17 @@ from ( group by y; -- Ensure results are correct. +--Testcase 726: select * from v_pagg_test order by y; -- Ensure parallel aggregation is actually being used. +--Testcase 727: explain (costs off) select * from v_pagg_test order by y; set max_parallel_workers_per_gather = 0; -- Ensure results are the same without parallel aggregation. +--Testcase 728: select * from v_pagg_test order by y; -- Clean up @@ -1431,7 +1498,9 @@ reset parallel_leader_participation; reset parallel_tuple_cost; reset parallel_setup_cost; +--Testcase 729: drop view v_pagg_test; +--Testcase 730: drop foreign table pagg_test; @@ -1461,8 +1530,11 @@ insert into agg_t17 values ('a', 'b'); select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0') from agg_t17; +--Testcase 731: create foreign table agg_t170(v int) server sqlite_svr; +--Testcase 732: insert into agg_t170(v) values (1), (2), (3); +--Testcase 733: select any_value(v) filter (where v > 2) from agg_t170; -- outer reference in FILTER (PostgreSQL extension) @@ -2087,6 +2159,139 @@ SELECT balk(hundred) FROM tenk1; ROLLBACK; +-- GROUP BY optimization by reordering GROUP BY clauses +--Testcase 766: +CREATE FOREIGN TABLE btg_groupby(x int, y int, z text, w int) SERVER sqlite_svr; +--Testcase 767: +INSERT INTO btg_groupby + SELECT + i % 10 AS x, + i % 10 AS y, + 'abc' || i % 10 AS z, + i AS w + FROM generate_series(1, 100) AS i; + +-- CREATE INDEX is not supported for foreign tables. +-- CREATE INDEX btg_x_y_idx ON btg_groupby(x, y); +-- ANALYZE btg_groupby; + +SET enable_hashagg = off; +SET enable_seqscan = off; + +-- Because CREATE INDEX is not supported for foreign tables, +-- we cannot utilize the ordering of index scan to avoid a Sort operation +-- Utilize the ordering of index scan to avoid a Sort operation +--Testcase 768: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY y, x; + +-- Engage incremental sort +--Testcase 769: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY z, y, w, x; + +-- Utilize the ordering of subquery scan to avoid a Sort operation +--Testcase 770: +EXPLAIN (COSTS OFF) SELECT count(*) +FROM (SELECT * FROM btg_groupby ORDER BY x, y, w, z) AS q1 +GROUP BY w, x, z, y; + +-- Utilize the ordering of merge join to avoid a full Sort operation +SET enable_hashjoin = off; +SET enable_nestloop = off; +--Testcase 771: +EXPLAIN (COSTS OFF) +SELECT count(*) + FROM btg_groupby t1 JOIN btg_groupby t2 ON t1.z = t2.z AND t1.w = t2.w AND t1.x = t2.x + GROUP BY t1.x, t1.y, t1.z, t1.w; +RESET enable_nestloop; +RESET enable_hashjoin; + +-- Should work with and without GROUP-BY optimization +--Testcase 772: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY w, x, z, y ORDER BY y, x, z, w; + +-- Utilize incremental sort to make the ORDER BY rule a bit cheaper +--Testcase 773: +EXPLAIN (COSTS OFF) +SELECT count(*) FROM btg_groupby GROUP BY w, x, y, z ORDER BY x*x, z; + +-- Test the case where the number of incoming subtree path keys is more than +-- the number of grouping keys. +-- CREATE INDEX btg_y_x_w_idx ON btg_groupby(y, x, w); +--Testcase 774: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT y, x, array_agg(distinct w) + FROM btg_groupby WHERE y < 0 GROUP BY x, y; + +-- Ensure that we do not select the aggregate pathkeys instead of the grouping +-- pathkeys +--Testcase 775: +CREATE FOREIGN TABLE group_agg_pk(x int, y int, z int, w int, f int) SERVER sqlite_svr; +--Testcase 776: +INSERT INTO group_agg_pk SELECT + i % 10 AS x, + i % 2 AS y, + i % 2 AS z, + 2 AS w, + i % 10 AS f +FROM generate_series(1,100) AS i; +-- ANALYZE group_agg_pk; +SET enable_nestloop = off; +SET enable_hashjoin = off; +--Testcase 777: +EXPLAIN (COSTS OFF) +SELECT avg(c1.f ORDER BY c1.x, c1.y) +FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x +GROUP BY c1.w, c1.z; +--Testcase 778: +SELECT avg(c1.f ORDER BY c1.x, c1.y) +FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x +GROUP BY c1.w, c1.z; + +-- Pathkeys, built in a subtree, can be used to optimize GROUP-BY clause +-- ordering. Also, here we check that it doesn't depend on the initial clause +-- order in the GROUP-BY list. +--Testcase 780: +EXPLAIN (COSTS OFF) +SELECT c1.y,c1.x FROM group_agg_pk c1 + JOIN group_agg_pk c2 + ON c1.x = c2.x +GROUP BY c1.y,c1.x,c2.x; +--Testcase 781: +EXPLAIN (COSTS OFF) +SELECT c1.y,c1.x FROM group_agg_pk c1 + JOIN group_agg_pk c2 + ON c1.x = c2.x +GROUP BY c1.y,c2.x,c1.x; + +RESET enable_nestloop; +RESET enable_hashjoin; + +--Testcase 779: +DROP FOREIGN TABLE group_agg_pk; + +-- -- CREATE UNIQUE INDEX is not supported for foreign table +-- -- Test the case where the ordering of the scan matches the ordering within the +-- -- aggregate but cannot be found in the group-by list +-- CREATE TABLE agg_sort_order (c1 int PRIMARY KEY, c2 int); +-- CREATE UNIQUE INDEX agg_sort_order_c2_idx ON agg_sort_order(c2); +-- INSERT INTO agg_sort_order SELECT i, i FROM generate_series(1,100)i; +-- ANALYZE agg_sort_order; + +-- EXPLAIN (COSTS OFF) +-- SELECT array_agg(c1 ORDER BY c2),c2 +-- FROM agg_sort_order WHERE c2 < 100 GROUP BY c1 ORDER BY 2; + +-- DROP TABLE agg_sort_order CASCADE; + +--Testcase 678: +DROP FOREIGN TABLE btg_groupby; + +RESET enable_hashagg; +RESET enable_seqscan; + -- Secondly test the case of a parallel aggregate combiner function -- returning NULL. For that use normal transition function, but a -- combiner function returning NULL. @@ -2128,6 +2333,7 @@ ROLLBACK; -- test multiple usage of an aggregate whose finalfn returns a R/W datum BEGIN; +--Testcase 754: CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN @@ -2135,6 +2341,7 @@ BEGIN END; $$; +--Testcase 755: CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray LANGUAGE plpgsql STRICT IMMUTABLE AS $$ DECLARE @@ -2146,12 +2353,14 @@ BEGIN END; $$; +--Testcase 756: CREATE AGGREGATE rwagg(anyarray) ( STYPE = anyarray, SFUNC = rwagg_sfunc, FINALFUNC = rwagg_finalfunc ); +--Testcase 757: CREATE FUNCTION eatarray(x real[]) RETURNS real[] LANGUAGE plpgsql STRICT IMMUTABLE AS $$ BEGIN @@ -2160,8 +2369,11 @@ BEGIN END; $$; +--Testcase 758: CREATE FOREIGN TABLE float_tb(f real) SERVER sqlite_svr; +--Testcase 759: INSERT INTO float_tb(f) VALUES (1.0); +--Testcase 760: SELECT eatarray(rwagg(ARRAY[f::real])), eatarray(rwagg(ARRAY[f::real])) FROM float_tb; ROLLBACK; @@ -2447,6 +2659,11 @@ set work_mem to default; union all (select * from agg_group_4 except select * from agg_hash_4); +--Testcase 792: +DELETE FROM INT4_TBL; +--Testcase 793: +DELETE FROM INT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/16.0/extra/bitstring.sql b/sql/17.0/extra/bitstring.sql similarity index 100% rename from sql/16.0/extra/bitstring.sql rename to sql/17.0/extra/bitstring.sql diff --git a/sql/17.0/extra/bool.sql b/sql/17.0/extra/bool.sql new file mode 100644 index 00000000..f464c35d --- /dev/null +++ b/sql/17.0/extra/bool.sql @@ -0,0 +1,193 @@ +--SET log_min_messages TO DEBUG1; +--SET client_min_messages TO DEBUG1; +--Testcase 000: +CREATE EXTENSION sqlite_fdw; +--Testcase 001: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/common.db'); +--Testcase 002: +CREATE SERVER sqlite2 FOREIGN DATA WRAPPER sqlite_fdw; + +--Testcase 01: +CREATE FOREIGN TABLE "type_BOOLEAN" (i int OPTIONS (key 'true'), b bool) SERVER sqlite_svr; +--Testcase 02: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (1, TRUE); +--Testcase 03: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (2, FALSE); +--Testcase 04: +CREATE FOREIGN TABLE "type_BOOLEAN+"( "i" int, "b" bool, "t" text, "l" smallint) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN+'); +--Testcase 05: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE text; +--Testcase 06: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (3, TRUE); +--Testcase 07: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (4, FALSE); +--Testcase 08: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (5, true); +--Testcase 09: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (6, false); +--Testcase 10: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (7, 'Yes'); +--Testcase 11: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (8, 'YeS'); +--Testcase 12: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (9, 'yes'); +--Testcase 13: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (10, 'no'); +--Testcase 14: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (11, 'No'); +--Testcase 15: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (12, 'nO'); +--Testcase 16: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (13, 'off'); +--Testcase 17: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (14, 'oFf'); +--Testcase 18: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (15, 'on'); +--Testcase 19: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (16, 'ON'); +--Testcase 20: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (17, 't'); +--Testcase 21: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (18, 'T'); +--Testcase 22: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (19, 'Y'); +--Testcase 23: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (20, 'y'); +--Testcase 24: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (21, 'F'); +--Testcase 25: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (22, 'f'); +--Testcase 26: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (23, 'x'); +--Testcase 27: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (24, '0'); +--Testcase 28: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (25, '1'); +--Testcase 29: +INSERT INTO "type_BOOLEAN" (i, b) VALUES (26, NULL); +--Testcase 30: +SELECT * FROM "type_BOOLEAN"; +--Testcase 31: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; +--Testcase 32: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM "type_BOOLEAN"; +--Testcase 33: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM "type_BOOLEAN+"; +--Testcase 34: ERR - invalid text affinity because not ISO:SQL text input +SELECT * FROM "type_BOOLEAN+"; +--Testcase 35 +DELETE FROM "type_BOOLEAN" WHERE i = 23; +--Testcase 36: +SELECT * FROM "type_BOOLEAN+"; +--Testcase 37: +SELECT * FROM "type_BOOLEAN+" WHERE b IS NULL; +--Testcase 38: +SELECT * FROM "type_BOOLEAN+" WHERE b IS NOT NULL; +--Testcase 39: +SELECT * FROM "type_BOOLEAN+" WHERE b; +--Testcase 40: +SELECT * FROM "type_BOOLEAN+" WHERE NOT b; + +--Testcase 41: +CREATE FOREIGN TABLE "type_BOOLEANpk" (col bool OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 42: +INSERT INTO "type_BOOLEANpk" VALUES (TRUE); +--Testcase 43: +INSERT INTO "type_BOOLEANpk" VALUES (FALSE); +--Testcase 44: ERR - primary key +INSERT INTO "type_BOOLEANpk" VALUES (TRUE); +--Testcase 45: +DELETE FROM "type_BOOLEANpk"; + +--Testcase 46: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE float8; +--Testcase 47: +INSERT INTO "type_BOOLEAN"(i, b) VALUES (27, 3.14159265358979); +--Testcase 48: +ALTER FOREIGN TABLE "type_BOOLEAN" ALTER COLUMN "b" TYPE bool; +--Testcase 49: ERR - invalid float for bool column +SELECT * FROM "type_BOOLEAN+"; +--Testcase 50 +DELETE FROM "type_BOOLEAN" WHERE i = 27; +--Testcase 51: +SELECT * FROM "type_BOOLEAN+"; + +--Testcase 52: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN" SET b = NULL WHERE b; +--Testcase 53: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN" SET b = NULL WHERE NOT b; +--Testcase 54: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN" WHERE b; +--Testcase 55: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN" WHERE NOT b; + +--Testcase 56: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT *, NOT b nb FROM "type_BOOLEAN+" b; +--Testcase 57: +SELECT *, NOT b nb FROM "type_BOOLEAN+" b; + +--Testcase 58: +CREATE FOREIGN TABLE "type_BOOLEAN_oper"( "i" int OPTIONS (key 'true'), i1 smallint, b1 boolean, i2 smallint, b2 boolean) SERVER sqlite_svr OPTIONS (table 'type_BOOLEAN_oper'); +--Testcase 59: see INIT.SQL with mixed affinity boolean data +SELECT * FROM "type_BOOLEAN_oper"; +--Testcase 60: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; +--Testcase 61: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper"; + +--Testcase 62: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; +--Testcase 63: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 AND b2; + +--Testcase 64: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; +--Testcase 65: +SELECT DISTINCT b1, b2, b1 AND b2 a, b1 OR b2 o FROM "type_BOOLEAN_oper" WHERE b1 OR b2; + +--Testcase 66: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; +--Testcase 67: +UPDATE "type_BOOLEAN_oper" SET b1 = NULL WHERE NOT b1; +--Testcase 68: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 69: +UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; +--Testcase 70: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE "type_BOOLEAN_oper" SET b1 = false WHERE b1 OR b2; +--Testcase 71: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 72: +EXPLAIN (VERBOSE, COSTS OFF) +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; +--Testcase 73: +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b1 AND b2; +--Testcase 74: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 75: +DELETE FROM "type_BOOLEAN_oper" WHERE NOT b2; +--Testcase 76: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; +--Testcase 77: +DELETE FROM "type_BOOLEAN_oper" WHERE b2; +--Testcase 78: +SELECT DISTINCT b1, b2 FROM "type_BOOLEAN_oper"; + +--Testcase 79: +DELETE FROM "type_BOOLEAN"; + +--Testcase 003: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/16.0/extra/encodings.sql b/sql/17.0/extra/encodings.sql similarity index 100% rename from sql/16.0/extra/encodings.sql rename to sql/17.0/extra/encodings.sql diff --git a/sql/13.12/extra/float4.sql b/sql/17.0/extra/float4.sql similarity index 94% rename from sql/13.12/extra/float4.sql rename to sql/17.0/extra/float4.sql index 7532f63b..85a75181 100644 --- a/sql/13.12/extra/float4.sql +++ b/sql/17.0/extra/float4.sql @@ -68,6 +68,15 @@ INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); --Testcase 17: INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_FLOAT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_FLOAT4 VALUES ('34.5', 1), ('xyz', 2), ('1e400', 3); +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 1; +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 2; +SELECT pg_input_is_valid(f1, 'float4') FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 3; +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_FLOAT4 WHERE id = 3), 'float4'); + + -- special inputs --Testcase 18: DELETE FROM FLOAT4_TMP; @@ -132,12 +141,24 @@ DELETE FROM FLOAT4_TMP; INSERT INTO FLOAT4_TMP VALUES ('Infinity'::float4 / 'Infinity'::float4); --Testcase 77: SELECT f1 FROM FLOAT4_TMP; +--Testcase 185: +DELETE FROM FLOAT4_TMP; +--Testcase 186: +INSERT INTO FLOAT4_TMP VALUES ('42'::float4 / 'Infinity'::float4); +--Testcase 187: +SELECT f1 FROM FLOAT4_TMP; --Testcase 31: DELETE FROM FLOAT4_TMP; --Testcase 78: INSERT INTO FLOAT4_TMP VALUES ('nan'::float4 / 'nan'::float4); --Testcase 79: SELECT f1 FROM FLOAT4_TMP; +--Testcase 188: +DELETE FROM FLOAT4_TMP; +--Testcase 189: +INSERT INTO FLOAT4_TMP VALUES ('nan'::float4 / '0'::float4); +--Testcase 190: +SELECT f1 FROM FLOAT4_TMP; --Testcase 32: DELETE FROM FLOAT4_TMP; --Testcase 80: @@ -146,7 +167,7 @@ INSERT INTO FLOAT4_TMP VALUES ('nan'::numeric::float4); SELECT f1 FROM FLOAT4_TMP; --Testcase 34: -SELECT '' AS five, * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL; --SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <> '1004.3'; @@ -157,37 +178,37 @@ SELECT '' AS five, * FROM FLOAT4_TBL; --SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE f.f1 < '1004.3'; --Testcase 35: -SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1; +SELECT f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1; --Testcase 36: -SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <= '1004.3'; +SELECT f.* FROM FLOAT4_TBL f WHERE f.f1 <= '1004.3'; --Testcase 37: -SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; --Testcase 38: -SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; --Testcase 39: -SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; --Testcase 40: -SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f +SELECT f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f WHERE f.f1 > '0.0'; -- test divide by zero --Testcase 41: -SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f; +SELECT f.f1 / '0.0' from FLOAT4_TBL f; --Testcase 42: -SELECT '' AS five, * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL; -- test the unary float4abs operator --Testcase 43: -SELECT '' AS five, f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; +SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; --Testcase 44: UPDATE FLOAT4_TBL @@ -195,7 +216,7 @@ UPDATE FLOAT4_TBL WHERE FLOAT4_TBL.f1 > '0.0'; --Testcase 45: -SELECT '' AS five, * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL; -- test edge-case coercions to integer --Testcase 82: diff --git a/sql/12.16/extra/float8.sql b/sql/17.0/extra/float8.sql similarity index 79% rename from sql/12.16/extra/float8.sql rename to sql/17.0/extra/float8.sql index 1a944995..ae9d234b 100644 --- a/sql/12.16/extra/float8.sql +++ b/sql/17.0/extra/float8.sql @@ -56,6 +56,14 @@ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); --Testcase 17: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_FLOAT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_FLOAT8 VALUES ('34.5', 1), ('xyz', 2), ('1e4000', 3); +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 1; +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 2; +SELECT pg_input_is_valid(f1, 'float8') FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 3; +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_FLOAT8 WHERE id = 3), 'float8'); + -- special inputs --Testcase 19: DELETE FROM FLOAT8_TMP; @@ -120,12 +128,24 @@ DELETE FROM FLOAT8_TMP; INSERT INTO FLOAT8_TMP VALUES ('Infinity'::float8 / 'Infinity'::float8); --Testcase 138: SELECT f1 FROM FLOAT8_TMP; +--Testcase 272: +DELETE FROM FLOAT8_TMP; +--Testcase 273: +INSERT INTO FLOAT8_TMP VALUES ('42'::float8 / 'Infinity'::float8); +--Testcase 274: +SELECT f1 FROM FLOAT8_TMP; --Testcase 31: DELETE FROM FLOAT8_TMP; --Testcase 139: INSERT INTO FLOAT8_TMP VALUES ('nan'::float8 / 'nan'::float8); --Testcase 140: SELECT f1 FROM FLOAT8_TMP; +--Testcase 275: +DELETE FROM FLOAT8_TMP; +--Testcase 276: +INSERT INTO FLOAT8_TMP VALUES ('nan'::float8 / '0'::float8); +--Testcase 277: +SELECT f1 FROM FLOAT8_TMP; --Testcase 32: DELETE FROM FLOAT8_TMP; --Testcase 141: @@ -134,63 +154,63 @@ INSERT INTO FLOAT8_TMP VALUES ('nan'::numeric::float8); SELECT f1 FROM FLOAT8_TMP; --Testcase 34: -SELECT '' AS five, * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL; --Testcase 35: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; --Testcase 36: -SELECT '' AS one, f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; --Testcase 37: -SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; +SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; --Testcase 38: -SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; --Testcase 39: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; +SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; --Testcase 40: -SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; +SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; --Testcase 41: -SELECT '' AS three, f.f1, f.f1 * '-10' AS x +SELECT f.f1, f.f1 * '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; --Testcase 42: -SELECT '' AS three, f.f1, f.f1 + '-10' AS x +SELECT f.f1, f.f1 + '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; --Testcase 43: -SELECT '' AS three, f.f1, f.f1 / '-10' AS x +SELECT f.f1, f.f1 / '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; --Testcase 44: -SELECT '' AS three, f.f1, f.f1 - '-10' AS x +SELECT f.f1, f.f1 - '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; --Testcase 45: -SELECT '' AS one, f.f1 ^ '2.0' AS square_f1 +SELECT f.f1 ^ '2.0' AS square_f1 FROM FLOAT8_TBL f where f.f1 = '1004.3'; -- absolute value --Testcase 46: -SELECT '' AS five, f.f1, @f.f1 AS abs_f1 +SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT8_TBL f; -- truncate --Testcase 47: -SELECT '' AS five, f.f1, trunc(f.f1) AS trunc_f1 +SELECT f.f1, trunc(f.f1) AS trunc_f1 FROM FLOAT8_TBL f; -- round --Testcase 48: -SELECT '' AS five, f.f1, round(f.f1) AS round_f1 +SELECT f.f1, round(f.f1) AS round_f1 FROM FLOAT8_TBL f; -- ceil / ceiling @@ -208,6 +228,7 @@ select floor(f1) as floor_f1 from float8_tbl f; select sign(f1) as sign_f1 from float8_tbl f; -- avoid bit-exact output here because operations may not be bit-exact. +--Testcase 278: SET extra_float_digits = 0; -- square root @@ -223,7 +244,7 @@ SELECT |/f1 as eight FROM FLOAT8_TBL; ROLLBACK; --Testcase 57: -SELECT '' AS three, f.f1, |/f.f1 AS sqrt_f1 +SELECT f.f1, |/f.f1 AS sqrt_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; @@ -270,13 +291,186 @@ DELETE FROM FLOAT8_TMP; INSERT INTO FLOAT8_TMP VALUES ('NaN'::float8 , '0'::float8); --Testcase 156: SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 279: +DELETE FROM FLOAT8_TMP; +--Testcase 280: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '0'::float8); +--Testcase 281: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 282: +DELETE FROM FLOAT8_TMP; +--Testcase 283: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '0'::float8); +--Testcase 284: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 285: +DELETE FROM FLOAT8_TMP; +--Testcase 286: +INSERT INTO FLOAT8_TMP VALUES ('0'::float8, 'infinity'::float8); +--Testcase 287: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 288: +DELETE FROM FLOAT8_TMP; +--Testcase 289: +INSERT INTO FLOAT8_TMP VALUES ('0'::float8, '-infinity'::float8); +--Testcase 290: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 291: +DELETE FROM FLOAT8_TMP; +--Testcase 292: +INSERT INTO FLOAT8_TMP VALUES ('1'::float8, 'infinity'::float8); +--Testcase 293: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 294: +DELETE FROM FLOAT8_TMP; +--Testcase 295: +INSERT INTO FLOAT8_TMP VALUES ('1'::float8, '-infinity'::float8); +--Testcase 296: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 297: +DELETE FROM FLOAT8_TMP; +--Testcase 298: +INSERT INTO FLOAT8_TMP VALUES ('-1'::float8, 'infinity'::float8); +--Testcase 299: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 300: +DELETE FROM FLOAT8_TMP; +--Testcase 301: +INSERT INTO FLOAT8_TMP VALUES ('-1'::float8, '-infinity'::float8); +--Testcase 302: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 303: +DELETE FROM FLOAT8_TMP; +--Testcase 304: +INSERT INTO FLOAT8_TMP VALUES ('0.1'::float8, 'infinity'::float8); +--Testcase 305: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 306: +DELETE FROM FLOAT8_TMP; +--Testcase 307: +INSERT INTO FLOAT8_TMP VALUES ('-0.1'::float8, 'infinity'::float8); +--Testcase 308: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 309: +DELETE FROM FLOAT8_TMP; +--Testcase 310: +INSERT INTO FLOAT8_TMP VALUES ('1.1'::float8, 'infinity'::float8); +--Testcase 311: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 312: +DELETE FROM FLOAT8_TMP; +--Testcase 313: +INSERT INTO FLOAT8_TMP VALUES ('-1.1'::float8, 'infinity'::float8); +--Testcase 314: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 315: +DELETE FROM FLOAT8_TMP; +--Testcase 316: +INSERT INTO FLOAT8_TMP VALUES ('0.1'::float8, '-infinity'::float8); +--Testcase 317: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 318: +DELETE FROM FLOAT8_TMP; +--Testcase 319: +INSERT INTO FLOAT8_TMP VALUES ('-0.1'::float8, '-infinity'::float8); +--Testcase 320: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 321: +DELETE FROM FLOAT8_TMP; +--Testcase 322: +INSERT INTO FLOAT8_TMP VALUES ('1.1'::float8, '-infinity'::float8); +--Testcase 323: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 324: +DELETE FROM FLOAT8_TMP; +--Testcase 325: +INSERT INTO FLOAT8_TMP VALUES ('-1.1'::float8, '-infinity'::float8); +--Testcase 326: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 327: +DELETE FROM FLOAT8_TMP; +--Testcase 328: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '-2'::float8); +--Testcase 329: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 330: +DELETE FROM FLOAT8_TMP; +--Testcase 331: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '2'::float8); +--Testcase 332: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 333: +DELETE FROM FLOAT8_TMP; +--Testcase 334: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, 'infinity'::float8); +--Testcase 335: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 336: +DELETE FROM FLOAT8_TMP; +--Testcase 337: +INSERT INTO FLOAT8_TMP VALUES ('infinity'::float8, '-infinity'::float8); +--Testcase 338: +SELECT power(f1, f2) FROM FLOAT8_TMP; + +-- Intel's icc misoptimizes the code that controls the sign of this result, +-- even with -mp1. Pending a fix for that, only test for "is it zero". +--Testcase 339: +DELETE FROM FLOAT8_TMP; +--Testcase 340: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-2'::float8); +--Testcase 341: +SELECT power(f1, f2) = '0' FROM FLOAT8_TMP; +--Testcase 342: +DELETE FROM FLOAT8_TMP; +--Testcase 343: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-3'::float8); +--Testcase 344: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 345: +DELETE FROM FLOAT8_TMP; +--Testcase 346: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '2'::float8); +--Testcase 347: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 348: +DELETE FROM FLOAT8_TMP; +--Testcase 349: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '3'::float8); +--Testcase 350: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 351: +DELETE FROM FLOAT8_TMP; +--Testcase 352: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-3.5'::float8); +--Testcase 353: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 354: +DELETE FROM FLOAT8_TMP; +--Testcase 355: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, 'infinity'::float8); +--Testcase 356: +SELECT power(f1, f2) FROM FLOAT8_TMP; +--Testcase 357: +DELETE FROM FLOAT8_TMP; +--Testcase 358: +INSERT INTO FLOAT8_TMP VALUES ('-infinity'::float8, '-infinity'::float8); +--Testcase 359: +SELECT power(f1, f2) FROM FLOAT8_TMP; -- take exp of ln(f.f1) --Testcase 67: -SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1 +SELECT f.f1, exp(ln(f.f1)) AS exp_ln_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; +-- check edge cases for exp +--Testcase 360: +DELETE FROM FLOAT8_TMP; +--Testcase 361: +INSERT INTO FLOAT8_TMP VALUES ('inf'::float8), ('-inf'::float8), ('nan'::float8); +--Testcase 362: +SELECT exp(f1) FROM FLOAT8_TMP; + -- cube root BEGIN; --Testcase 68: @@ -288,11 +482,11 @@ SELECT ||/f1 as three FROM FLOAT8_TBL; ROLLBACK; --Testcase 71: -SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; +SELECT f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; --Testcase 72: -SELECT '' AS five, * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL; --Testcase 73: UPDATE FLOAT8_TBL @@ -300,10 +494,10 @@ UPDATE FLOAT8_TBL WHERE FLOAT8_TBL.f1 > '0.0'; --Testcase 74: -SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; +SELECT f.f1 * '1e200' from FLOAT8_TBL f; --Testcase 75: -SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; +SELECT f.f1 ^ '1e200' from FLOAT8_TBL f; BEGIN; --Testcase 76: @@ -315,19 +509,19 @@ SELECT * FROM FLOAT8_TBL; ROLLBACK; --Testcase 79: -SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; +SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; --Testcase 80: -SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; +SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; --Testcase 81: -SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; +SELECT exp(f.f1) from FLOAT8_TBL f; --Testcase 82: -SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; +SELECT f.f1 / '0.0' from FLOAT8_TBL f; --Testcase 83: -SELECT '' AS five, * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL; -- hyperbolic functions -- we run these with extra_float_digits = 0 too, since different platforms @@ -480,6 +674,24 @@ INSERT INTO FLOAT8_TMP VALUES ((float8 'nan')); --Testcase 219: SELECT atanh(f1) FROM FLOAT8_TMP; +-- error functions +-- we run these with extra_float_digits = -1, to get consistently rounded +-- results on all platforms. +SET extra_float_digits = -1; + +DELETE FROM FLOAT8_TBL; +INSERT INTO FLOAT8_TBL(f1) VALUES (float8 '-infinity'), + (-28), (-6), (-3.4), (-2.1), (-1.1), (-0.45), + (-1.2e-9), (-2.3e-13), (-1.2e-17), (0), + (1.2e-17), (2.3e-13), (1.2e-9), + (0.45), (1.1), (2.1), (3.4), (6), (28), + (float8 'infinity'), (float8 'nan'); +SELECT f1, + erf(f1), + erfc(f1) +FROM FLOAT8_TBL; + +--Testcase 369: RESET extra_float_digits; -- test for over- and underflow @@ -517,7 +729,7 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e+200'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200'); --Testcase 94: -SELECT '' AS five, * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL; -- test edge-case coercions to integer --Testcase 220: @@ -892,6 +1104,9 @@ rollback; --Testcase 269: drop type xfloat8 cascade; +--Testcase 363: +DELETE FROM FLOAT8_TBL; + -- Clean up DO $d$ declare diff --git a/sql/13.12/extra/insert.sql b/sql/17.0/extra/insert.sql similarity index 85% rename from sql/13.12/extra/insert.sql rename to sql/17.0/extra/insert.sql index 2a9a1403..2d30b447 100644 --- a/sql/13.12/extra/insert.sql +++ b/sql/17.0/extra/insert.sql @@ -56,6 +56,29 @@ insert into inserttest01 values(30, 50, repeat('x', 10000)); --Testcase 15: select col1, col2, char_length(col3) from inserttest01; +-- +-- tuple larger than fillfactor +-- foreign table does not support fillfactor +-- +-- CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10); +-- ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain; + +-- -- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize) +-- INSERT INTO large_tuple_test (select 1, NULL); + +-- -- should still fit on the page +-- INSERT INTO large_tuple_test (select 2, repeat('a', 1000)); +-- SELECT pg_size_pretty(pg_relation_size('large_tuple_test'::regclass, 'main')); + +-- -- add small record to the second page +-- INSERT INTO large_tuple_test (select 3, NULL); + +-- -- now this tuple won't fit on the second page, but the insert should +-- -- still succeed by extending the relation +-- INSERT INTO large_tuple_test (select 4, repeat('a', 8126)); + +-- DROP TABLE large_tuple_test; + -- skip, sqlite fdw does not support customized type /* -- check indirection (field/array assignment), cf bug #14265 @@ -103,7 +126,83 @@ create rule irule3 as on insert to inserttest2 do also drop table inserttest2; drop table inserttest; -drop type insert_test_type; +-- Make the same tests with domains over the array and composite fields + +create domain insert_pos_ints as int[] check (value[1] > 0); + +create domain insert_test_domain as insert_test_type + check ((value).if2[1] is not null); + +create table inserttesta (f1 int, f2 insert_pos_ints); +create table inserttestb (f3 insert_test_domain, f4 insert_test_domain[]); + +insert into inserttesta (f2[1], f2[2]) values (1,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (5,6); +insert into inserttesta (f2[1], f2[2]) select 7,8; +insert into inserttesta (f2[1], f2[2]) values (1,default); -- not supported +insert into inserttesta (f2[1], f2[2]) values (0,2); +insert into inserttesta (f2[1], f2[2]) values (3,4), (0,6); +insert into inserttesta (f2[1], f2[2]) select 0,8; + +insert into inserttestb (f3.if1, f3.if2) values (1,array['foo']); +insert into inserttestb (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{baz,quux}'; +insert into inserttestb (f3.if1, f3.if2) values (1,default); -- not supported +insert into inserttestb (f3.if1, f3.if2) values (1,array[null]); +insert into inserttestb (f3.if1, f3.if2) values (1,'{null}'), (2,'{bar}'); +insert into inserttestb (f3.if1, f3.if2) select 3, '{null,quux}'; + +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'); +insert into inserttestb (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux'); +insert into inserttestb (f3.if2[1], f3.if2[2]) select 'bear', 'beer'; + +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) values (row(1,'{x}'), 'foo', 'bar'), (row(2,'{y}'), 'baz', 'quux'); +insert into inserttestb (f3, f4[1].if2[1], f4[1].if2[2]) select row(1,'{x}')::insert_test_domain, 'bear', 'beer'; + +select * from inserttesta; +select * from inserttestb; + +-- also check reverse-listing +create table inserttest2 (f1 bigint, f2 text); +create rule irule1 as on insert to inserttest2 do also + insert into inserttestb (f3.if2[1], f3.if2[2]) + values (new.f1,new.f2); +create rule irule2 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + values (1,'fool'),(new.f1,new.f2); +create rule irule3 as on insert to inserttest2 do also + insert into inserttestb (f4[1].if1, f4[1].if2[2]) + select new.f1, new.f2; +\d+ inserttest2 + +drop table inserttest2; +drop table inserttesta; +drop table inserttestb; +drop domain insert_pos_ints; +drop domain insert_test_domain; + +-- Verify that multiple inserts to subfields of a domain-over-container +-- check the domain constraints only on the finished value + +create domain insert_nnarray as int[] + check (value[1] is not null and value[2] is not null); + +create domain insert_test_domain as insert_test_type + check ((value).if1 is not null and (value).if2 is not null); + +create table inserttesta (f1 insert_nnarray); +insert into inserttesta (f1[1]) values (1); -- fail +insert into inserttesta (f1[1], f1[2]) values (1, 2); + +create table inserttestb (f1 insert_test_domain); +insert into inserttestb (f1.if1) values (1); -- fail +insert into inserttestb (f1.if1, f1.if2) values (1, '{foo}'); + +drop table inserttesta; +drop table inserttestb; +drop domain insert_nnarray; +drop type insert_test_type cascade; -- direct partition inserts should check partition bound constraint create table range_parted ( @@ -248,33 +347,6 @@ select tableoid::regclass::text, a, min(b) as min_b, max(b) as max_b from list_p -- direct partition inserts should check hash partition bound constraint --- Use hand-rolled hash functions and operator classes to get predictable --- result on different machines. The hash function for int4 simply returns --- the sum of the values passed to it and the one for text returns the length --- of the non-empty string value passed to it or 0. - -create or replace function part_hashint4_noop(value int4, seed int8) -returns int8 as $$ -select value + seed; -$$ language sql immutable; - -create operator class part_test_int4_ops -for type int4 -using hash as -operator 1 =, -function 2 part_hashint4_noop(int4, int8); - -create or replace function part_hashtext_length(value text, seed int8) -RETURNS int8 AS $$ -select length(coalesce(value, ''))::int8 -$$ language sql immutable; - -create operator class part_test_text_ops -for type text -using hash as -operator 1 =, -function 2 part_hashtext_length(text, int8); - create table hash_parted ( a int ) partition by hash (a part_test_int4_ops); @@ -562,9 +634,7 @@ drop table inserttest3; drop table brtrigpartcon; drop function brtrigpartcon1trigf(); --- check that "do nothing" BR triggers work with tuple-routing (this checks --- that estate->es_result_relation_info is appropriately set/reset for each --- routed tuple) +-- check that "do nothing" BR triggers work with tuple-routing create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test2 (c text, b text, a int); diff --git a/sql/16.0/extra/int4.sql b/sql/17.0/extra/int4.sql similarity index 90% rename from sql/16.0/extra/int4.sql rename to sql/17.0/extra/int4.sql index 763cebea..c55ba7be 100644 --- a/sql/16.0/extra/int4.sql +++ b/sql/17.0/extra/int4.sql @@ -51,11 +51,17 @@ INSERT INTO INT4_TBL(f1) VALUES (''); SELECT * FROM INT4_TBL; -- Also try it with non-error-throwing API +--Testcase 137: CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 138: INSERT INTO NON_ERROR_THROWING_API_INT4 VALUES ('34', 1), ('asdf', 2), ('1000000000000', 3); +--Testcase 139: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 1; +--Testcase 140: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 2; +--Testcase 141: SELECT pg_input_is_valid(f1, 'int4') FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3; +--Testcase 142: SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4 WHERE id = 3), 'int4'); --Testcase 15: @@ -364,114 +370,194 @@ INSERT INTO INT4_TMP VALUES (2147483647::int4, 2147483646::int4); SELECT lcm(f1, f2) FROM INT4_TMP; -- overflow -- non-decimal literals +--Testcase 143: CREATE FOREIGN TABLE special_case_int4 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 144: INSERT INTO special_case_int4 VALUES ('0b100101'::int4); +--Testcase 145: SELECT f1 FROM special_case_int4; +--Testcase 146: DELETE FROM special_case_int4; +--Testcase 147: INSERT INTO special_case_int4 VALUES ('0o273'::int4); +--Testcase 148: SELECT f1 FROM special_case_int4; +--Testcase 149: DELETE FROM special_case_int4; +--Testcase 150: INSERT INTO special_case_int4 VALUES ('0x42F'::int4); +--Testcase 151: SELECT f1 FROM special_case_int4; +--Testcase 152: DELETE FROM special_case_int4; +--Testcase 153: INSERT INTO special_case_int4 VALUES ('0b'::int4); +--Testcase 154: SELECT f1 FROM special_case_int4; +--Testcase 155: DELETE FROM special_case_int4; +--Testcase 156: INSERT INTO special_case_int4 VALUES ('0x'::int4); +--Testcase 157: SELECT f1 FROM special_case_int4; +--Testcase 158: DELETE FROM special_case_int4; +--Testcase 159: INSERT INTO special_case_int4 VALUES ('0x'::int4); +--Testcase 160: SELECT f1 FROM special_case_int4; -- cases near overflow +--Testcase 161: DELETE FROM special_case_int4; +--Testcase 162: INSERT INTO special_case_int4 VALUES ('0b1111111111111111111111111111111'::int4); +--Testcase 163: SELECT f1 FROM special_case_int4; +--Testcase 164: DELETE FROM special_case_int4; +--Testcase 165: INSERT INTO special_case_int4 VALUES ('0b10000000000000000000000000000000'::int4); +--Testcase 166: SELECT f1 FROM special_case_int4; +--Testcase 167: DELETE FROM special_case_int4; +--Testcase 168: INSERT INTO special_case_int4 VALUES ('0o17777777777'::int4); +--Testcase 169: SELECT f1 FROM special_case_int4; +--Testcase 170: DELETE FROM special_case_int4; +--Testcase 171: INSERT INTO special_case_int4 VALUES ('0o20000000000'::int4); +--Testcase 172: SELECT f1 FROM special_case_int4; +--Testcase 173: DELETE FROM special_case_int4; +--Testcase 174: INSERT INTO special_case_int4 VALUES ('0x7FFFFFFF'::int4); +--Testcase 175: SELECT f1 FROM special_case_int4; +--Testcase 176: DELETE FROM special_case_int4; +--Testcase 177: INSERT INTO special_case_int4 VALUES ('0x80000000'::int4); +--Testcase 178: SELECT f1 FROM special_case_int4; +--Testcase 179: DELETE FROM special_case_int4; +--Testcase 180: INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000000'::int4); +--Testcase 181: SELECT f1 FROM special_case_int4; +--Testcase 182: DELETE FROM special_case_int4; +--Testcase 183: INSERT INTO special_case_int4 VALUES ('-0b10000000000000000000000000000001'::int4); +--Testcase 184: SELECT f1 FROM special_case_int4; +--Testcase 185: DELETE FROM special_case_int4; +--Testcase 186: INSERT INTO special_case_int4 VALUES ('-0o20000000000'::int4); +--Testcase 187: SELECT f1 FROM special_case_int4; +--Testcase 188: DELETE FROM special_case_int4; +--Testcase 189: INSERT INTO special_case_int4 VALUES ('-0o20000000001'::int4); +--Testcase 190: SELECT f1 FROM special_case_int4; +--Testcase 191: DELETE FROM special_case_int4; +--Testcase 192: INSERT INTO special_case_int4 VALUES ('-0x80000000'::int4); +--Testcase 193: SELECT f1 FROM special_case_int4; +--Testcase 194: DELETE FROM special_case_int4; +--Testcase 195: INSERT INTO special_case_int4 VALUES ('-0x80000001'::int4); +--Testcase 196: SELECT f1 FROM special_case_int4; -- underscores +--Testcase 197: DELETE FROM special_case_int4; +--Testcase 198: INSERT INTO special_case_int4 VALUES ('1_000_000'::int4); +--Testcase 199: SELECT f1 FROM special_case_int4; +--Testcase 200: DELETE FROM special_case_int4; +--Testcase 201: INSERT INTO special_case_int4 VALUES ('1_2_3'::int4); +--Testcase 202: SELECT f1 FROM special_case_int4; +--Testcase 203: DELETE FROM special_case_int4; +--Testcase 204: INSERT INTO special_case_int4 VALUES ('0x1EEE_FFFF'::int4); +--Testcase 205: SELECT f1 FROM special_case_int4; +--Testcase 206: DELETE FROM special_case_int4; +--Testcase 207: INSERT INTO special_case_int4 VALUES ('0o2_73'::int4); +--Testcase 208: SELECT f1 FROM special_case_int4; +--Testcase 209: DELETE FROM special_case_int4; +--Testcase 210: INSERT INTO special_case_int4 VALUES ('0b_10_0101'::int4); +--Testcase 211: SELECT f1 FROM special_case_int4; -- error cases +--Testcase 212: DELETE FROM special_case_int4; +--Testcase 213: INSERT INTO special_case_int4 VALUES ('_100'::int4); +--Testcase 214: SELECT f1 FROM special_case_int4; +--Testcase 215: DELETE FROM special_case_int4; +--Testcase 216: INSERT INTO special_case_int4 VALUES ('100_'::int4); +--Testcase 217: SELECT f1 FROM special_case_int4; +--Testcase 218: DELETE FROM special_case_int4; +--Testcase 219: INSERT INTO special_case_int4 VALUES ('100__000'::int4); +--Testcase 220: SELECT f1 FROM special_case_int4; +--Testcase 221: +DELETE FROM INT4_TBL; -- Clean up DO $d$ declare diff --git a/sql/17.0/extra/int8.sql b/sql/17.0/extra/int8.sql new file mode 100644 index 00000000..f8e3dee9 --- /dev/null +++ b/sql/17.0/extra/int8.sql @@ -0,0 +1,844 @@ +-- +-- INT8 +-- Test int8 64-bit integers. +-- +--Testcase 140: +CREATE EXTENSION sqlite_fdw; +--Testcase 141: +CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw +OPTIONS (database '/tmp/sqlite_fdw_test/core.db'); +--Testcase 142: +CREATE FOREIGN TABLE INT8_TBL( + q1 int8 OPTIONS (key 'true'), + q2 int8 OPTIONS (key 'true') +) SERVER sqlite_svr; +--Testcase 143: +CREATE FOREIGN TABLE INT8_TMP( + q1 int8, + q2 int8, + q3 int4, + q4 int2, + q5 text, + id int options (key 'true') +) SERVER sqlite_svr; + +--Testcase 1: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 2: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 3: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 4: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 5: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + +-- bad inputs +--Testcase 6: +INSERT INTO INT8_TBL(q1) VALUES (' '); +--Testcase 7: +INSERT INTO INT8_TBL(q1) VALUES ('xxx'); +--Testcase 8: +INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485'); +--Testcase 9: +INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934'); +--Testcase 10: +INSERT INTO INT8_TBL(q1) VALUES ('- 123'); +--Testcase 11: +INSERT INTO INT8_TBL(q1) VALUES (' 345 5'); +--Testcase 12: +INSERT INTO INT8_TBL(q1) VALUES (''); + +--Testcase 13: +SELECT * FROM INT8_TBL; + +-- Also try it with non-error-throwing API +--Testcase 251: +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT8(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 252: +INSERT INTO NON_ERROR_THROWING_API_INT8 VALUES ('34', 1), ('asdf', 2), ('10000000000000000000', 3); +--Testcase 253: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 1; +--Testcase 254: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 2; +--Testcase 255: +SELECT pg_input_is_valid(f1, 'int8') FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3; +--Testcase 256: +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT8 WHERE id = 3), 'int8'); + + +-- int8/int8 cmp +--Testcase 14: +SELECT * FROM INT8_TBL WHERE q2 = 4567890123456789; +--Testcase 15: +SELECT * FROM INT8_TBL WHERE q2 <> 4567890123456789; +--Testcase 16: +SELECT * FROM INT8_TBL WHERE q2 < 4567890123456789; +--Testcase 17: +SELECT * FROM INT8_TBL WHERE q2 > 4567890123456789; +--Testcase 18: +SELECT * FROM INT8_TBL WHERE q2 <= 4567890123456789; +--Testcase 19: +SELECT * FROM INT8_TBL WHERE q2 >= 4567890123456789; + +-- int8/int4 cmp +--Testcase 20: +SELECT * FROM INT8_TBL WHERE q2 = 456; +--Testcase 21: +SELECT * FROM INT8_TBL WHERE q2 <> 456; +--Testcase 22: +SELECT * FROM INT8_TBL WHERE q2 < 456; +--Testcase 23: +SELECT * FROM INT8_TBL WHERE q2 > 456; +--Testcase 24: +SELECT * FROM INT8_TBL WHERE q2 <= 456; +--Testcase 25: +SELECT * FROM INT8_TBL WHERE q2 >= 456; + +-- int4/int8 cmp +--Testcase 26: +SELECT * FROM INT8_TBL WHERE 123 = q1; +--Testcase 27: +SELECT * FROM INT8_TBL WHERE 123 <> q1; +--Testcase 28: +SELECT * FROM INT8_TBL WHERE 123 < q1; +--Testcase 29: +SELECT * FROM INT8_TBL WHERE 123 > q1; +--Testcase 30: +SELECT * FROM INT8_TBL WHERE 123 <= q1; +--Testcase 31: +SELECT * FROM INT8_TBL WHERE 123 >= q1; + +-- int8/int2 cmp +--Testcase 32: +SELECT * FROM INT8_TBL WHERE q2 = '456'::int2; +--Testcase 33: +SELECT * FROM INT8_TBL WHERE q2 <> '456'::int2; +--Testcase 34: +SELECT * FROM INT8_TBL WHERE q2 < '456'::int2; +--Testcase 35: +SELECT * FROM INT8_TBL WHERE q2 > '456'::int2; +--Testcase 36: +SELECT * FROM INT8_TBL WHERE q2 <= '456'::int2; +--Testcase 37: +SELECT * FROM INT8_TBL WHERE q2 >= '456'::int2; + +-- int2/int8 cmp +--Testcase 38: +SELECT * FROM INT8_TBL WHERE '123'::int2 = q1; +--Testcase 39: +SELECT * FROM INT8_TBL WHERE '123'::int2 <> q1; +--Testcase 40: +SELECT * FROM INT8_TBL WHERE '123'::int2 < q1; +--Testcase 41: +SELECT * FROM INT8_TBL WHERE '123'::int2 > q1; +--Testcase 42: +SELECT * FROM INT8_TBL WHERE '123'::int2 <= q1; +--Testcase 43: +SELECT * FROM INT8_TBL WHERE '123'::int2 >= q1; + + +--Testcase 44: +SELECT q1 AS plus, -q1 AS minus FROM INT8_TBL; + +--Testcase 45: +SELECT q1, q2, q1 + q2 AS plus FROM INT8_TBL; +--Testcase 46: +SELECT q1, q2, q1 - q2 AS minus FROM INT8_TBL; +--Testcase 47: +SELECT q1, q2, q1 * q2 AS multiply FROM INT8_TBL; +--Testcase 48: +SELECT q1, q2, q1 * q2 AS multiply FROM INT8_TBL + WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); +--Testcase 49: +SELECT q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL; + +--Testcase 50: +SELECT q1, float8(q1) FROM INT8_TBL; +--Testcase 51: +SELECT q2, float8(q2) FROM INT8_TBL; + +--Testcase 52: +SELECT 37 + q1 AS plus4 FROM INT8_TBL; +--Testcase 53: +SELECT 37 - q1 AS minus4 FROM INT8_TBL; +--Testcase 54: +SELECT 2 * q1 AS "twice int4" FROM INT8_TBL; +--Testcase 55: +SELECT q1 * 2 AS "twice int4" FROM INT8_TBL; + +-- int8 op int4 +--Testcase 56: +SELECT q1 + 42::int4 AS "8plus4", q1 - 42::int4 AS "8minus4", q1 * 42::int4 AS "8mul4", q1 / 42::int4 AS "8div4" FROM INT8_TBL; +-- int4 op int8 +--Testcase 57: +SELECT 246::int4 + q1 AS "4plus8", 246::int4 - q1 AS "4minus8", 246::int4 * q1 AS "4mul8", 246::int4 / q1 AS "4div8" FROM INT8_TBL; + +-- int8 op int2 +--Testcase 58: +SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "8mul2", q1 / 42::int2 AS "8div2" FROM INT8_TBL; +-- int2 op int8 +--Testcase 59: +SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL; + +--Testcase 60: +SELECT q2, abs(q2) FROM INT8_TBL; +--Testcase 61: +SELECT min(q1), min(q2) FROM INT8_TBL; +--Testcase 62: +SELECT max(q1), max(q2) FROM INT8_TBL; + + +-- TO_CHAR() +-- +--Testcase 63: +SELECT to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999') + FROM INT8_TBL; + +--Testcase 64: +SELECT to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999') + FROM INT8_TBL; + +--Testcase 65: +SELECT to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR') + FROM INT8_TBL; + +--Testcase 66: +SELECT to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999') + FROM INT8_TBL; + +--Testcase 67: +SELECT to_char(q2, 'MI9999999999999999') FROM INT8_TBL; +--Testcase 68: +SELECT to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; +--Testcase 69: +SELECT to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL; +--Testcase 70: +SELECT to_char(q2, 'SG9999999999999999th') FROM INT8_TBL; +--Testcase 71: +SELECT to_char(q2, '0999999999999999') FROM INT8_TBL; +--Testcase 72: +SELECT to_char(q2, 'S0999999999999999') FROM INT8_TBL; +--Testcase 73: +SELECT to_char(q2, 'FM0999999999999999') FROM INT8_TBL; +--Testcase 74: +SELECT to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL; +--Testcase 75: +SELECT to_char(q2, 'L9999999999999999.000') FROM INT8_TBL; +--Testcase 76: +SELECT to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL; +--Testcase 77: +SELECT to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL; +--Testcase 78: +SELECT to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; +--Testcase 79: +SELECT to_char(q2, '999999SG9999999999') FROM INT8_TBL; + +-- check min/max values and overflow behavior +--Testcase 80: +DELETE FROM INT8_TMP; +--Testcase 144: +INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); +--Testcase 145: +SELECT q1 FROM INT8_TMP; + +--Testcase 81: +DELETE FROM INT8_TMP; +--Testcase 146: +INSERT INTO INT8_TMP VALUES ('-9223372036854775809'::int8); +--Testcase 147: +SELECT q1 FROM INT8_TMP; + +--Testcase 82: +DELETE FROM INT8_TMP; +--Testcase 148: +INSERT INTO INT8_TMP VALUES ('9223372036854775807'::int8); +--Testcase 149: +SELECT q1 FROM INT8_TMP; + +--Testcase 83: +DELETE FROM INT8_TMP; +--Testcase 150: +INSERT INTO INT8_TMP VALUES ('9223372036854775808'::int8); +--Testcase 151: +SELECT q1 FROM INT8_TMP; + +--Testcase 84: +DELETE FROM INT8_TMP; +--Testcase 152: +INSERT INTO INT8_TMP VALUES (-('-9223372036854775807'::int8)); +--Testcase 153: +SELECT q1 FROM INT8_TMP; + +--Testcase 86: +DELETE FROM INT8_TMP; +--Testcase 154: +INSERT INTO INT8_TMP VALUES (-('-9223372036854775808'::int8)); +--Testcase 155: +SELECT q1 FROM INT8_TMP; + +--Testcase 257: +DELETE FROM INT8_TMP; +--Testcase 258: +INSERT INTO INT8_TMP VALUES (0::int8 , '-9223372036854775808'::int8); +--Testcase 259: +SELECT q1 - q2 FROM INT8_TMP; + +--Testcase 87: +DELETE FROM INT8_TMP; +--Testcase 156: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 157: +SELECT q1 + q2 FROM INT8_TMP; +--Testcase 88: +DELETE FROM INT8_TMP; +--Testcase 158: +INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '-9223372036854775800'::int8); +--Testcase 159: +SELECT q1 + q2 FROM INT8_TMP; + +--Testcase 89: +DELETE FROM INT8_TMP; +--Testcase 160: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '-9223372036854775800'::int8); +--Testcase 161: +SELECT q1-q2 FROM INT8_TMP; +--Testcase 90: +DELETE FROM INT8_TMP; +--Testcase 162: +INSERT INTO INT8_TMP VALUES ('-9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 163: +SELECT q1 - q2 FROM INT8_TMP; + +--Testcase 91: +DELETE FROM INT8_TMP; +--Testcase 164: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '9223372036854775800'::int8); +--Testcase 165: +SELECT q1 * q2 FROM INT8_TMP; + +--Testcase 92: +DELETE FROM INT8_TMP; +--Testcase 166: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); +--Testcase 167: +SELECT q1 / q2 FROM INT8_TMP; + +--Testcase 93: +DELETE FROM INT8_TMP; +--Testcase 168: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '0'::int8); +--Testcase 169: +SELECT q1 % q2 FROM INT8_TMP; + +--Testcase 94: +DELETE FROM INT8_TMP; +--Testcase 170: +INSERT INTO INT8_TMP VALUES ('-9223372036854775808'::int8); +--Testcase 171: +SELECT abs(q1) FROM INT8_TMP; + +--Testcase 95: +DELETE FROM INT8_TMP; +--Testcase 172: +INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); +--Testcase 173: +SELECT q1 + q3 FROM INT8_TMP; +--Testcase 96: +DELETE FROM INT8_TMP; +--Testcase 174: +INSERT INTO INT8_TMP(q1, q3) VALUES ('-9223372036854775800'::int8 , '100'::int4); +--Testcase 175: +SELECT q1 - q3 FROM INT8_TMP; +--Testcase 97: +DELETE FROM INT8_TMP; +--Testcase 176: +INSERT INTO INT8_TMP(q1, q3) VALUES ('9223372036854775800'::int8 , '100'::int4); +--Testcase 177: +SELECT q1 * q3 FROM INT8_TMP; + +--Testcase 98: +DELETE FROM INT8_TMP; +--Testcase 178: +INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); +--Testcase 179: +SELECT q3 + q1 FROM INT8_TMP; +--Testcase 99: +DELETE FROM INT8_TMP; +--Testcase 180: +INSERT INTO INT8_TMP(q3, q1) VALUES ('-100'::int4 , '9223372036854775800'::int8); +--Testcase 181: +SELECT q3 - q1 FROM INT8_TMP; +--Testcase 100: +DELETE FROM INT8_TMP; +--Testcase 182: +INSERT INTO INT8_TMP(q3, q1) VALUES ('100'::int4 , '9223372036854775800'::int8); +--Testcase 183: +SELECT q3 * q1 FROM INT8_TMP; + +--Testcase 101: +DELETE FROM INT8_TMP; +--Testcase 184: +INSERT INTO INT8_TMP(q1, q4) VALUES ('9223372036854775800'::int8 , '100'::int2); +--Testcase 185: +SELECT q1 + q4 FROM INT8_TMP; +--Testcase 102: +DELETE FROM INT8_TMP; +--Testcase 186: +INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775800'::int8 , '100'::int2); +--Testcase 187: +SELECT q1 - q4 FROM INT8_TMP; +--Testcase 103: +DELETE FROM INT8_TMP; +--Testcase 188: +INSERT INTO INT8_TMP VALUES ('9223372036854775800'::int8 , '100'::int2); +--Testcase 189: +SELECT q1 * q4 FROM INT8_TMP; +--Testcase 104: +DELETE FROM INT8_TMP; +--Testcase 190: +INSERT INTO INT8_TMP(q1, q4) VALUES ('-9223372036854775808'::int8 , '0'::int2); +--Testcase 191: +SELECT q1 / q4 FROM INT8_TMP; + +--Testcase 105: +DELETE FROM INT8_TMP; +--Testcase 192: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); +--Testcase 193: +SELECT q4 + q1 FROM INT8_TMP; +--Testcase 106: +DELETE FROM INT8_TMP; +--Testcase 194: +INSERT INTO INT8_TMP(q4, q1) VALUES ('-100'::int2 , '9223372036854775800'::int8); +--Testcase 195: +SELECT q4 - q1 FROM INT8_TMP; +--Testcase 107: +DELETE FROM INT8_TMP; +--Testcase 196: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '9223372036854775800'::int8); +--Testcase 197: +SELECT q4 * q1 FROM INT8_TMP; +--Testcase 108: +DELETE FROM INT8_TMP; +--Testcase 198: +INSERT INTO INT8_TMP(q4, q1) VALUES ('100'::int2 , '0'::int8); +--Testcase 199: +SELECT q4 / q1 FROM INT8_TMP; + +--Testcase 110: +SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 = 456; +--Testcase 111: +SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 <> 456; + +--Testcase 112: +SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 = 456; +--Testcase 113: +SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 <> 456; + +--Testcase 200: +DELETE FROM INT8_TMP; +--Testcase 201: +INSERT INTO INT8_TMP(q5) VALUES ('42'), ('-37'); +--Testcase 202: +SELECT CAST(q5::int2 as int8) FROM INT8_TMP; + +--Testcase 114: +SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL; + +--Testcase 203: +DELETE FROM INT8_TMP; +--Testcase 204: +INSERT INTO INT8_TMP(q5) VALUES ('36854775807.0'); +--Testcase 205: +SELECT CAST(q5::float4 AS int8) FROM INT8_TMP; + +--Testcase 206: +DELETE FROM INT8_TMP; +--Testcase 207: +INSERT INTO INT8_TMP(q5) VALUES ('922337203685477580700.0'); +--Testcase 208: +SELECT CAST(q5::float8 AS int8) FROM INT8_TMP; + +--Testcase 115: +SELECT CAST(q1 AS oid) FROM INT8_TBL; +--Testcase 209: +SELECT oid::int8 FROM pg_class WHERE relname = 'pg_class'; + +-- bit operations + +--Testcase 116: +SELECT q1, q2, q1 & q2 AS "and", q1 | q2 AS "or", q1 # q2 AS "xor", ~q1 AS "not" FROM INT8_TBL; +--Testcase 117: +SELECT q1, q1 << 2 AS "shl", q1 >> 3 AS "shr" FROM INT8_TBL; + +-- generate_series + +--Testcase 118: +DELETE FROM INT8_TMP; +--Testcase 210: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8) q1; +--Testcase 211: +SELECT q1 FROM INT8_TMP; + +--Testcase 120: +DELETE FROM INT8_TMP; +--Testcase 212: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 0) q1; -- should error +--Testcase 213: +SELECT q1 FROM INT8_TMP; + +--Testcase 122: +DELETE FROM INT8_TMP; +--Testcase 214: +INSERT INTO INT8_TMP SELECT q1 FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 2) q1; +--Testcase 215: +SELECT q1 FROM INT8_TMP; + +-- corner case +--Testcase 216: +DELETE FROM INT8_TMP; +--Testcase 217: +INSERT INTO INT8_TMP VALUES (-1::int8<<63); +--Testcase 218: +SELECT q1::text FROM INT8_TMP; + +--Testcase 219: +DELETE FROM INT8_TMP; +--Testcase 220: +INSERT INTO INT8_TMP VALUES ((-1::int8<<63)+1); +--Testcase 221: +SELECT q1::text FROM INT8_TMP; + +-- check sane handling of INT64_MIN overflow cases +--Testcase 125: +DELETE FROM INT8_TMP; +--Testcase 222: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int8, 888); +--Testcase 126: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int8, 888); +--Testcase 127: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int8, 888); +--Testcase 128: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; +--Testcase 129: +DELETE FROM INT8_TMP WHERE q2 = 888; +--Testcase 130: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int4, 888); +--Testcase 131: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int4, 888); +--Testcase 132: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int4, 888); +--Testcase 133: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; +--Testcase 134: +DELETE FROM INT8_TMP WHERE q2 = 888; +--Testcase 135: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 * (-1)::int2, 888); +--Testcase 136: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 / (-1)::int2, 888); +--Testcase 137: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8 % (-1)::int2, 888); +--Testcase 138: +SELECT q1 FROM INT8_TMP WHERE q2 = 888; +--Testcase 139: +DELETE FROM INT8_TMP WHERE q2 = 888; + +-- check rounding when casting from float +--Testcase 223: +CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 224: +DELETE FROM FLOAT8_TMP; +--Testcase 225: +INSERT INTO FLOAT8_TMP VALUES + (-2.5::float8), + (-1.5::float8), + (-0.5::float8), + (0.0::float8), + (0.5::float8), + (1.5::float8), + (2.5::float8); + +--Testcase 226: +SELECT f1 as x, f1::int8 as int8_value FROM FLOAT8_TMP; + +-- check rounding when casting from numeric +--Testcase 227: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 228: +DELETE FROM NUMERIC_TMP; +--Testcase 229: +INSERT INTO NUMERIC_TMP VALUES + (-2.5::numeric), + (-1.5::numeric), + (-0.5::numeric), + (0.0::numeric), + (0.5::numeric), + (1.5::numeric), + (2.5::numeric); +--Testcase 230: +SELECT f1 as x, f1::int8 as int8_value FROM NUMERIC_TMP; + +-- test gcd() +--Testcase 231: +DELETE FROM INT8_TMP; +--Testcase 232: +INSERT INTO INT8_TMP VALUES + (0::int8, 0::int8), + (0::int8, 29893644334::int8), + (288484263558::int8, 29893644334::int8), + (-288484263558::int8, 29893644334::int8), + ((-9223372036854775808)::int8, 1::int8), + ((-9223372036854775808)::int8, 9223372036854775807::int8), + ((-9223372036854775808)::int8, 4611686018427387904::int8); +--Testcase 233: +SELECT q1, q2, gcd(q1, q2), gcd(q1, -q2), gcd(q2, q1), gcd(-q2, q1) FROM INT8_TMP; + +--Testcase 234: +DELETE FROM INT8_TMP; +--Testcase 235: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 0::int8); +--Testcase 236: +SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow + +--Testcase 237: +DELETE FROM INT8_TMP; +--Testcase 238: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, (-9223372036854775808)::int8); +--Testcase 239: +SELECT gcd(q1, q2) FROM INT8_TMP; -- overflow + +-- test lcm() +--Testcase 240: +DELETE FROM INT8_TMP; +--Testcase 241: +INSERT INTO INT8_TMP VALUES + (0::int8, 0::int8), + (0::int8, 29893644334::int8), + (29893644334::int8, 29893644334::int8), + (288484263558::int8, 29893644334::int8), + (-288484263558::int8, 29893644334::int8), + ((-9223372036854775808)::int8, 0::int8); +--Testcase 242: +SELECT q1, q2, lcm(q1, q2), lcm(q1, -q2), lcm(q2, q1), lcm(-q2, q1) FROM INT8_TMP; + +--Testcase 243: +DELETE FROM INT8_TMP; +--Testcase 244: +INSERT INTO INT8_TMP VALUES ((-9223372036854775808)::int8, 1::int8); +--Testcase 245: +SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow + +--Testcase 246: +DELETE FROM INT8_TMP; +--Testcase 247: +INSERT INTO INT8_TMP VALUES ((9223372036854775807)::int8, (9223372036854775806)::int8); +--Testcase 248: +SELECT lcm(q1, q2) FROM INT8_TMP; -- overflow + +-- non-decimal literals + +--Testcase 260: +CREATE FOREIGN TABLE special_case_int8 (f1 text, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 261: +INSERT INTO special_case_int8 VALUES ('0b100101'::int8); +--Testcase 262: +SELECT f1 FROM special_case_int8; + +--Testcase 263: +DELETE FROM special_case_int8; +--Testcase 264: +INSERT INTO special_case_int8 VALUES ('0o273'::int8); +--Testcase 265: +SELECT f1 FROM special_case_int8; + +--Testcase 266: +DELETE FROM special_case_int8; +--Testcase 267: +INSERT INTO special_case_int8 VALUES ('0x42F'::int8); +--Testcase 268: +SELECT f1 FROM special_case_int8; + +--Testcase 269: +DELETE FROM special_case_int8; +--Testcase 270: +INSERT INTO special_case_int8 VALUES ('0b'::int8); +--Testcase 271: +SELECT f1 FROM special_case_int8; + +--Testcase 272: +DELETE FROM special_case_int8; +--Testcase 273: +INSERT INTO special_case_int8 VALUES ('0o'::int8); +--Testcase 274: +SELECT f1 FROM special_case_int8; + +--Testcase 275: +DELETE FROM special_case_int8; +--Testcase 276: +INSERT INTO special_case_int8 VALUES ('0x'::int8); +--Testcase 277: +SELECT f1 FROM special_case_int8; + +-- cases near overflow +--Testcase 278: +DELETE FROM special_case_int8; +--Testcase 279: +INSERT INTO special_case_int8 VALUES ('0b111111111111111111111111111111111111111111111111111111111111111'::int8); +--Testcase 280: +SELECT f1 FROM special_case_int8; + +--Testcase 281: +DELETE FROM special_case_int8; +--Testcase 282: +INSERT INTO special_case_int8 VALUES ('0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 283: +SELECT f1 FROM special_case_int8; + +--Testcase 284: +DELETE FROM special_case_int8; +--Testcase 285: +INSERT INTO special_case_int8 VALUES ('0o777777777777777777777'::int8); +--Testcase 286: +SELECT f1 FROM special_case_int8; + +--Testcase 287: +DELETE FROM special_case_int8; +--Testcase 288: +INSERT INTO special_case_int8 VALUES ('0o1000000000000000000000'::int8); +--Testcase 289: +SELECT f1 FROM special_case_int8; + +--Testcase 290: +DELETE FROM special_case_int8; +--Testcase 291: +INSERT INTO special_case_int8 VALUES ('0x7FFFFFFFFFFFFFFF'::int8); +--Testcase 292: +SELECT f1 FROM special_case_int8; + +--Testcase 293: +DELETE FROM special_case_int8; +--Testcase 294: +INSERT INTO special_case_int8 VALUES ('0x8000000000000000'::int8); +--Testcase 295: +SELECT f1 FROM special_case_int8; + +--Testcase 296: +DELETE FROM special_case_int8; +--Testcase 297: +INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000000'::int8); +--Testcase 298: +SELECT f1 FROM special_case_int8; + +--Testcase 299: +DELETE FROM special_case_int8; +--Testcase 300: +INSERT INTO special_case_int8 VALUES ('-0b1000000000000000000000000000000000000000000000000000000000000001'::int8); +--Testcase 301: +SELECT f1 FROM special_case_int8; + +--Testcase 302: +DELETE FROM special_case_int8; +--Testcase 303: +INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000000'::int8); +--Testcase 304: +SELECT f1 FROM special_case_int8; + +--Testcase 305: +DELETE FROM special_case_int8; +--Testcase 306: +INSERT INTO special_case_int8 VALUES ('-0o1000000000000000000001'::int8); +--Testcase 307: +SELECT f1 FROM special_case_int8; + +--Testcase 308: +DELETE FROM special_case_int8; +--Testcase 309: +INSERT INTO special_case_int8 VALUES ('-0x8000000000000000'::int8); +--Testcase 310: +SELECT f1 FROM special_case_int8; + +--Testcase 311: +DELETE FROM special_case_int8; +--Testcase 312: +INSERT INTO special_case_int8 VALUES ('-0x8000000000000001'::int8); +--Testcase 313: +SELECT f1 FROM special_case_int8; + +-- underscores +--Testcase 314: +DELETE FROM special_case_int8; +--Testcase 315: +INSERT INTO special_case_int8 VALUES ('1_000_000'::int8); +--Testcase 316: +SELECT f1 FROM special_case_int8; + +--Testcase 317: +DELETE FROM special_case_int8; +--Testcase 318: +INSERT INTO special_case_int8 VALUES ('1_2_3'::int8); +--Testcase 319: +SELECT f1 FROM special_case_int8; + +--Testcase 320: +DELETE FROM special_case_int8; +--Testcase 321: +INSERT INTO special_case_int8 VALUES ('0x1EEE_FFFF'::int8); +--Testcase 322: +SELECT f1 FROM special_case_int8; + +--Testcase 323: +DELETE FROM special_case_int8; +--Testcase 324: +INSERT INTO special_case_int8 VALUES ('0o2_73'::int8); +--Testcase 325: +SELECT f1 FROM special_case_int8; + +--Testcase 326: +DELETE FROM special_case_int8; +--Testcase 327: +INSERT INTO special_case_int8 VALUES ('0b_10_0101'::int8); +--Testcase 328: +SELECT f1 FROM special_case_int8; + +-- error cases +--Testcase 329: +DELETE FROM special_case_int8; +--Testcase 330: +INSERT INTO special_case_int8 VALUES ('_100'::int8); +--Testcase 331: +SELECT f1 FROM special_case_int8; + +--Testcase 332: +DELETE FROM special_case_int8; +--Testcase 333: +INSERT INTO special_case_int8 VALUES ('100_'::int8); +--Testcase 334: +SELECT f1 FROM special_case_int8; + +--Testcase 335: +DELETE FROM special_case_int8; +--Testcase 336: +INSERT INTO special_case_int8 VALUES ('100__000'::int8); +--Testcase 337: +SELECT f1 FROM special_case_int8; + +--Testcase 338: +DELETE FROM INT8_TBL; + +-- Clean up +DO $d$ +declare + l_rec record; +begin + for l_rec in (select foreign_table_schema, foreign_table_name + from information_schema.foreign_tables) loop + execute format('drop foreign table %I.%I cascade;', l_rec.foreign_table_schema, l_rec.foreign_table_name); + end loop; +end; +$d$; + +--Testcase 249: +DROP SERVER sqlite_svr; +--Testcase 250: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/12.16/extra/join.sql b/sql/17.0/extra/join.sql similarity index 72% rename from sql/12.16/extra/join.sql rename to sql/17.0/extra/join.sql index 85eabb84..7ba9f36a 100644 --- a/sql/12.16/extra/join.sql +++ b/sql/17.0/extra/join.sql @@ -63,13 +63,47 @@ CREATE FOREIGN TABLE tenk2 ( --Testcase 366: CREATE FOREIGN TABLE INT4_TBL(f1 int4 OPTIONS (key 'true')) SERVER sqlite_svr; + +--Testcase 641: +INSERT INTO INT4_TBL(f1) VALUES (' 0 '); +--Testcase 642: +INSERT INTO INT4_TBL(f1) VALUES ('123456 '); +--Testcase 643: +INSERT INTO INT4_TBL(f1) VALUES (' -123456'); +--Testcase 644: +INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); +--Testcase 645: +INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); + --Testcase 367: CREATE FOREIGN TABLE FLOAT8_TBL(f1 float8 OPTIONS (key 'true')) SERVER sqlite_svr; + +--Testcase 646: +INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); +--Testcase 647: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); +--Testcase 648: +INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); +--Testcase 649: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); +--Testcase 650: +INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); + --Testcase 368: CREATE FOREIGN TABLE INT8_TBL( q1 int8 OPTIONS (key 'true'), q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 651: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 652: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 653: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 654: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 655: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); --Testcase 369: CREATE FOREIGN TABLE INT2_TBL(f1 int2 OPTIONS (key 'true')) SERVER sqlite_svr; @@ -130,27 +164,27 @@ analyze onerow; -- --Testcase 21: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL AS tx; --Testcase 22: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL tx; --Testcase 23: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL AS t1 (a, b, c); --Testcase 24: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c); --Testcase 25: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e); --Testcase 26: -SELECT '' AS "xxx", t1.a, t2.e +SELECT t1.a, t2.e FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e) WHERE t1.a = t2.d; @@ -162,31 +196,31 @@ SELECT '' AS "xxx", t1.a, t2.e -- --Testcase 27: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL CROSS JOIN J2_TBL; -- ambiguous column --Testcase 28: -SELECT '' AS "xxx", i, k, t +SELECT i, k, t FROM J1_TBL CROSS JOIN J2_TBL; -- resolve previous ambiguity by specifying the table name --Testcase 29: -SELECT '' AS "xxx", t1.i, k, t +SELECT t1.i, k, t FROM J1_TBL t1 CROSS JOIN J2_TBL t2; --Testcase 30: -SELECT '' AS "xxx", ii, tt, kk +SELECT ii, tt, kk FROM (J1_TBL CROSS JOIN J2_TBL) AS tx (ii, jj, tt, ii2, kk); --Testcase 31: -SELECT '' AS "xxx", tx.ii, tx.jj, tx.kk +SELECT tx.ii, tx.jj, tx.kk FROM (J1_TBL t1 (a, b, c) CROSS JOIN J2_TBL t2 (d, e)) AS tx (ii, jj, tt, ii2, kk); --Testcase 32: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL CROSS JOIN J2_TBL a CROSS JOIN J2_TBL b; @@ -204,24 +238,55 @@ SELECT '' AS "xxx", * -- Inner equi-join on specified column --Testcase 33: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL INNER JOIN J2_TBL USING (i); -- Same as above, slightly different syntax --Testcase 34: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL JOIN J2_TBL USING (i); --Testcase 35: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a) ORDER BY a, d; --Testcase 36: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, b) USING (b) ORDER BY b, t1.a; +-- test join using aliases +--Testcase 489: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) WHERE J1_TBL.t = 'one'; -- ok +--Testcase 490: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; -- ok +--Testcase 491: +SELECT * + FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t = 'one'; -- error +--Testcase 492: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.i = 1; -- ok +--Testcase 493: +SELECT * + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one'; -- error +--Testcase 494: +SELECT * + FROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1; -- error (XXX could use better hint) +--Testcase 495: +SELECT * + FROM J1_TBL a1 JOIN J2_TBL a2 USING (i) AS a1; -- error +--Testcase 496: +SELECT x.* + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; +--Testcase 497: +SELECT ROW(x.*) + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; +--Testcase 498: +SELECT row_to_json(x.*) + FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one'; -- -- NATURAL JOIN @@ -229,21 +294,21 @@ SELECT '' AS "xxx", * -- --Testcase 37: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL NATURAL JOIN J2_TBL; --Testcase 38: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (a, d); --Testcase 39: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (d, a); -- mismatch number of columns -- currently, Postgres will fill in with underlying names --Testcase 40: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL t1 (a, b) NATURAL JOIN J2_TBL t2 (a); @@ -252,11 +317,11 @@ SELECT '' AS "xxx", * -- --Testcase 41: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i); --Testcase 42: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k); @@ -265,7 +330,7 @@ SELECT '' AS "xxx", * -- --Testcase 43: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k); @@ -275,39 +340,39 @@ SELECT '' AS "xxx", * -- --Testcase 44: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL LEFT OUTER JOIN J2_TBL USING (i) ORDER BY i, k, t; --Testcase 45: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL LEFT JOIN J2_TBL USING (i) ORDER BY i, k, t; --Testcase 46: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL RIGHT OUTER JOIN J2_TBL USING (i); --Testcase 47: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL RIGHT JOIN J2_TBL USING (i); --Testcase 48: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL FULL OUTER JOIN J2_TBL USING (i) ORDER BY i, k, t; --Testcase 49: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL FULL JOIN J2_TBL USING (i) ORDER BY i, k, t; --Testcase 50: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1); --Testcase 51: -SELECT '' AS "xxx", * +SELECT * FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (i = 1); -- @@ -336,6 +401,27 @@ CREATE FOREIGN TABLE t21 (name TEXT, n INTEGER) SERVER sqlite_svr; --Testcase 374: CREATE FOREIGN TABLE t31 (name TEXT, n INTEGER) SERVER sqlite_svr; +--Testcase 483: +CREATE FOREIGN TABLE onek ( + unique1 int4 OPTIONS (key 'true'), + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) SERVER sqlite_svr; + + --Testcase 53: INSERT INTO t11 VALUES ( 'bb', 11 ); --Testcase 54: @@ -524,7 +610,9 @@ select count(*) from tenk1 x where -- try that with GEQO too begin; +--Testcase 499: set geqo = on; +--Testcase 500: set geqo_threshold = 2; --Testcase 93: select count(*) from tenk1 x where @@ -564,8 +652,8 @@ select * from int8_tbl i1 left join (int8_tbl i2 join order by 1, 2; -- --- regression test: check a case where join_clause_is_movable_into() gives --- an imprecise result, causing an assertion failure +-- regression test: check a case where join_clause_is_movable_into() +-- used to give an imprecise result, causing an assertion failure -- --Testcase 96: select count(*) @@ -597,6 +685,131 @@ select a.f1, b.f1, t.thousand, t.tenthous from (select sum(f1) as f1 from int4_tbl i4b) b where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; +-- +-- checks for correct handling of quals in multiway outer joins +-- +--Testcase 545: +explain (costs off) +select t1.f1 +from int4_tbl t1, int4_tbl t2 + left join int4_tbl t3 on t3.f1 > 0 + left join int4_tbl t4 on t3.f1 > 1 +where t4.f1 is null; + +--Testcase 546: +select t1.f1 +from int4_tbl t1, int4_tbl t2 + left join int4_tbl t3 on t3.f1 > 0 + left join int4_tbl t4 on t3.f1 > 1 +where t4.f1 is null; + +--Testcase 547: +explain (costs off) +select * +from int4_tbl t1 left join int4_tbl t2 on true + left join int4_tbl t3 on t2.f1 > 0 + left join int4_tbl t4 on t3.f1 > 0; + +--Testcase 548: +explain (costs off) +select * from onek t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join onek t3 on t2.unique1 != t3.unique1 + left join onek t4 on t3.unique1 = t4.unique1; + +--Testcase 549: +explain (costs off) +select * from int4_tbl t1 + left join (select now() from int4_tbl t2 + left join int4_tbl t3 on t2.f1 = t3.f1 + left join int4_tbl t4 on t3.f1 = t4.f1) s on true + inner join int4_tbl t5 on true; + +--Testcase 550: +explain (costs off) +select * from int4_tbl t1 + left join int4_tbl t2 on true + left join int4_tbl t3 on true + left join int4_tbl t4 on t2.f1 = t3.f1; + +--Testcase 551: +explain (costs off) +select * from int4_tbl t1 + left join int4_tbl t2 on true + left join int4_tbl t3 on t2.f1 = t3.f1 + left join int4_tbl t4 on t3.f1 != t4.f1; + +--Testcase 552: +explain (costs off) +select * from int4_tbl t1 + left join (int4_tbl t2 left join int4_tbl t3 on t2.f1 > 0) on t2.f1 > 1 + left join int4_tbl t4 on t2.f1 > 2 and t3.f1 > 3 +where t1.f1 = coalesce(t2.f1, 1); + +--Testcase 553: +explain (costs off) +select * from int4_tbl t1 + left join ((select t2.f1 from int4_tbl t2 + left join int4_tbl t3 on t2.f1 > 0 + where t3.f1 is null) s + left join tenk1 t4 on s.f1 > 1) + on s.f1 = t1.f1; + +--Testcase 554: +explain (costs off) +select * from int4_tbl t1 + left join ((select t2.f1 from int4_tbl t2 + left join int4_tbl t3 on t2.f1 > 0 + where t2.f1 <> coalesce(t3.f1, -1)) s + left join tenk1 t4 on s.f1 > 1) + on s.f1 = t1.f1; + +--Testcase 555: +explain (costs off) +select * from onek t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join onek t3 on t2.unique1 = t3.unique1 + left join onek t4 on t3.unique1 = t4.unique1 and t2.unique2 = t4.unique2; + +--Testcase 556: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 left join int8_tbl t3 full join int8_tbl t4 on false on false) + left join int8_tbl t5 on t2.q1 = t5.q1 +on t2.q2 = 123; + +--Testcase 557: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select * from int8_tbl t3 where t3.q1 = t2.q1 offset 0) s + on t2.q1 = 1; + +--Testcase 558: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select * from generate_series(t2.q1, 100)) s + on t2.q1 = 1; + +--Testcase 559: +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral + (select t2.q1 from int8_tbl t3) s + on t2.q1 = 1; + +--Testcase 560: +explain (costs off) +select * from onek t1 + left join onek t2 on true + left join lateral + (select * from onek t3 where t3.two = t2.two offset 0) s + on t2.unique1 = 1; + -- -- check a case where we formerly got confused by conflicting sort orders -- in redundant merge join path keys @@ -633,6 +846,25 @@ select count(*) from (select * from tenk1 y order by y.unique2) y on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; +set enable_hashjoin = 0; +set enable_nestloop = 0; +set enable_hashagg = 0; + +-- +-- Check that we use the pathkeys from a prefix of the group by / order by +-- clause for the join pathkeys when that prefix covers all join quals. We +-- expect this to lead to an incremental sort for the group by / order by. +-- +--Testcase 561: +explain (costs off) +select x.thousand, x.twothousand, count(*) +from tenk1 x inner join tenk1 y on x.thousand = y.thousand +group by x.thousand, x.twothousand +order by x.thousand desc, x.twothousand; + +reset enable_hashagg; +reset enable_nestloop; +reset enable_hashjoin; -- -- Clean up @@ -708,6 +940,34 @@ select * from t12 left join t22 on (t12.a = t22.a); --Testcase 120: select t12.x from t12 join t32 on (t12.a = t32.x); +-- Test matching of locking clause with wrong alias + +--Testcase 540: +select t12.*, t22.*, unnamed_join.* from + t12 join t22 on (t12.a = t22.a), t32 as unnamed_join + for update of unnamed_join; + +--Testcase 541: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of unnamed_join; + +--Testcase 542: +select foo.*, unnamed_join.* from + t12 join t22 using (a) as foo, t32 as unnamed_join + for update of foo; + +--Testcase 543: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of foo; + +--Testcase 544: +select bar.*, unnamed_join.* from + (t12 join t22 using (a) as foo) as bar, t32 as unnamed_join + for update of bar; + +--Testcase 536: drop table t2a; -- @@ -728,7 +988,9 @@ INSERT INTO tt2 VALUES (21, 11); --Testcase 124: INSERT INTO tt2 VALUES (22, 11); +--Testcase 501: set enable_hashjoin to off; +--Testcase 502: set enable_nestloop to off; -- these should give the same results @@ -739,6 +1001,39 @@ select tt1.*, tt2.* from tt1 left join tt2 on tt1.joincol = tt2.joincol; --Testcase 126: select tt1.*, tt2.* from tt2 right join tt1 on tt1.joincol = tt2.joincol; +--Testcase 503: +reset enable_hashjoin; +--Testcase 504: +reset enable_nestloop; + +-- +-- regression test for bug #18522 (merge-right-anti-join in inner_unique cases) +-- + +--Testcase 637: +create foreign table tbl_ra(a int options (key 'true'), b int) server sqlite_svr; +--Testcase 638: +insert into tbl_ra select i, i%100 from generate_series(1,1000)i; +-- CREATE INDEX, ANALYZE are not supported for foreign tables. +-- create index on tbl_ra (b); +-- analyze tbl_ra; + +set enable_hashjoin to off; +set enable_nestloop to off; + +-- Because CREATE INDEX is not supported for foreign tables, +-- we cannot use this index to create a merge right anti join plan +-- ensure we get a merge right anti join +--Testcase 639: +explain (costs off) +select * from tbl_ra t1 +where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; + +-- and check we get the expected results +--Testcase 640: +select * from tbl_ra t1 +where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; + reset enable_hashjoin; reset enable_nestloop; @@ -746,8 +1041,12 @@ reset enable_nestloop; -- regression test for bug #13908 (hash join with skew tuples & nbatch increase) -- +--Testcase 505: set work_mem to '64kB'; +--Testcase 506: set enable_mergejoin to off; +--Testcase 507: +set enable_memoize to off; --Testcase 127: explain (costs off) @@ -757,8 +1056,12 @@ select count(*) from tenk1 a, tenk1 b select count(*) from tenk1 a, tenk1 b where a.hundred = b.thousand and (b.fivethous % 10) < 10; +--Testcase 508: reset work_mem; +--Testcase 509: reset enable_mergejoin; +--Testcase 510: +reset enable_memoize; -- -- regression test for 8.2 bug with improper re-ordering of left joins @@ -774,15 +1077,63 @@ create foreign table tt4(f1 int) server sqlite_svr; --Testcase 130: insert into tt4 values (0),(1),(9999); ---Testcase 131: +set enable_nestloop to off; + +--Testcase 562: +EXPLAIN (COSTS OFF) SELECT a.f1 FROM tt4 a LEFT JOIN ( SELECT b.f1 FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) - WHERE c.f1 IS NULL + WHERE COALESCE(c.f1, 0) = 0 ) AS d ON (a.f1 = d.f1) -WHERE d.f1 IS NULL; +WHERE COALESCE(d.f1, 0) = 0 +ORDER BY 1; + +--Testcase 563: +SELECT a.f1 +FROM tt4 a +LEFT JOIN ( + SELECT b.f1 + FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) + WHERE COALESCE(c.f1, 0) = 0 +) AS d ON (a.f1 = d.f1) +WHERE COALESCE(d.f1, 0) = 0 +ORDER BY 1; + +reset enable_nestloop; + +-- +-- basic semijoin and antijoin recognition tests +-- + +--Testcase 564: +explain (costs off) +select a.* from tenk1 a +where unique1 in (select unique2 from tenk1 b); + +-- sadly, this is not an antijoin +--Testcase 565: +explain (costs off) +select a.* from tenk1 a +where unique1 not in (select unique2 from tenk1 b); + +--Testcase 566: +explain (costs off) +select a.* from tenk1 a +where exists (select 1 from tenk1 b where a.unique1 = b.unique2); + +--Testcase 567: +explain (costs off) +select a.* from tenk1 a +where not exists (select 1 from tenk1 b where a.unique1 = b.unique2); + +--Testcase 568: +explain (costs off) +select a.* from tenk1 a left join tenk1 b on a.unique1 = b.unique2 +where b.unique2 is null; + -- -- regression test for proper handling of outer joins within antijoins @@ -889,6 +1240,7 @@ select * from left join zv1 on (f3 = f1) where f2 = 53; +--Testcase 537: drop view zv1; -- @@ -921,8 +1273,11 @@ execute foo(false); begin; +--Testcase 511: set enable_mergejoin = 1; +--Testcase 512: set enable_hashjoin = 0; +--Testcase 513: set enable_nestloop = 0; --Testcase 403: @@ -1188,6 +1543,35 @@ where 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) order by 1,2; +-- +-- variant where a PlaceHolderVar is needed at a join, but not above the join +-- + +--Testcase 514: +explain (costs off) +select * from + int4_tbl as i41, + lateral + (select 1 as x from + (select i41.f1 as lat, + i42.f1 as loc from + int8_tbl as i81, int4_tbl as i42) as ss1 + right join int4_tbl as i43 on (i43.f1 > 1) + where ss1.loc = ss1.lat) as ss2 +where i41.f1 > 0; + +--Testcase 515: +select * from + int4_tbl as i41, + lateral + (select 1 as x from + (select i41.f1 as lat, + i42.f1 as loc from + int8_tbl as i81, int4_tbl as i42) as ss1 + right join int4_tbl as i43 on (i43.f1 > 1) + where ss1.loc = ss1.lat) as ss2 +where i41.f1 > 0; + -- -- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE -- @@ -1326,7 +1710,60 @@ select * from select * from (select key1 as x from sub_tbl as x) ss1 left join (select key6 as y from sub_tbl) ss2 on (true), lateral (select ss2.y as z limit 1) ss3; - + +-- Test proper handling of appendrel PHVs during useless-RTE removal +--Testcase 516: +explain (costs off) +select * from + (select 0 as z) as t1 + left join + (select true as a) as t2 + on true, + lateral (select true as b + union all + select a as b) as t3 +where b; + +--Testcase 517: +select * from + (select 0 as z) as t1 + left join + (select true as a) as t2 + on true, + lateral (select true as b + union all + select a as b) as t3 +where b; + +-- Test PHV in a semijoin qual, which confused useless-RTE removal (bug #17700) +--Testcase 569: +explain (verbose, costs off) +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + +--Testcase 570: +with ctetable as not materialized ( select 1 as f1 ) +select * from ctetable c1 +where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); + +-- Test PHV that winds up in a Result node, despite having nonempty nullingrels +--Testcase 571: +explain (verbose, costs off) +select table_catalog, table_name +from int4_tbl t1 + inner join (int8_tbl t2 + left join information_schema.column_udt_usage on null) + on null; + +-- Test handling of qual pushdown to appendrel members with non-Var outputs +--Testcase 572: +explain (verbose, costs off) +select * from int4_tbl left join ( + select text 'foo' union all select text 'bar' +) ss(x) on true +where ss.x is null; + -- -- test inlining of immutable functions -- @@ -1354,6 +1791,10 @@ select unique1 from tenk1, f_immutable_int4(1) x where x = unique1; explain (costs off) select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1; +--Testcase 538: +explain (costs off) +select unique1 from tenk1, lateral f_immutable_int4(1) x where x in (select 17); + --Testcase 428: explain (costs off) select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x; @@ -1420,6 +1861,21 @@ drop function mki8(bigint, bigint); --Testcase 442: drop function mki4(int); +-- test const-folding of a whole-row Var into a per-field Var +-- (need to inline a function to reach this case, else parser does it) +--Testcase 632: +create function f_field_select(t onek) returns int4 as +$$ select t.unique2; $$ language sql immutable; + +--Testcase 633: +explain (verbose, costs off) +select (t2.*).unique1, f_field_select(t2) from tenk1 t1 + left join onek t2 on t1.unique1 = t2.unique1 + left join int8_tbl t3 on true; + +--Testcase 634: +drop function f_field_select(t onek); + -- -- test extraction of restriction OR clauses from join OR clause -- (we used to only do this for indexable clauses) @@ -1560,6 +2016,17 @@ select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; +-- related case + +--Testcase 573: +explain (costs off) +select * from int8_tbl t1 left join int8_tbl t2 on t1.q2 = t2.q1, + lateral (select * from int8_tbl t3 where t2.q1 = t2.q2) ss; + +--Testcase 574: +select * from int8_tbl t1 left join int8_tbl t2 on t1.q2 = t2.q1, + lateral (select * from int8_tbl t3 where t2.q1 = t2.q2) ss; + -- -- check handling of join aliases when flattening multiple levels of subquery -- @@ -1593,6 +2060,32 @@ left join ) foo3 using (join_key); +-- +-- check handling of a variable-free join alias +-- +--Testcase 575: +explain (verbose, costs off) +select * from +int4_tbl i0 left join +( (select *, 123 as x from int4_tbl i1) ss1 + left join + (select *, q2 as x from int8_tbl i2) ss2 + using (x) +) ss0 +on (i0.f1 = ss0.f1) +order by i0.f1, x; + +--Testcase 576: +select * from +int4_tbl i0 left join +( (select *, 123 as x from int4_tbl i1) ss1 + left join + (select *, q2 as x from int8_tbl i2) ss2 + using (x) +) ss0 +on (i0.f1 = ss0.f1) +order by i0.f1, x; + -- -- test successful handling of nested outer joins with degenerate join quals -- @@ -1697,6 +2190,29 @@ select * from left join int4_tbl i4 on i8.q1 = i4.f1; +-- check handling of a variable-free qual for a non-commutable outer join +--Testcase 577: +explain (costs off) +select nspname +from (select 1 as x) ss1 +left join +( select n.nspname, c.relname + from pg_class c left join pg_namespace n on n.oid = c.relnamespace + where c.relkind = 'r' +) ss2 on false; + +-- check handling of apparently-commutable outer joins with non-commutable +-- joins between them +--Testcase 578: +explain (costs off) +select 1 from + int4_tbl i4 + left join int8_tbl i8 on i4.f1 is not null + left join (select 1 as a) ss1 on null + join int4_tbl i42 on ss1.a is null or i8.q1 <> i8.q2 + right join (select 2 as b) ss2 + on ss2.b < i4.f1; + -- -- test for appropriate join order in the presence of lateral references -- @@ -1756,6 +2272,49 @@ select 1 from lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 where tt1.f1 = ss1.c0; +--Testcase 579: +explain (verbose, costs off) +select 1 from + int4_tbl as i4 + inner join + ((select 42 as n from int4_tbl x1 left join int8_tbl x2 on f1 = q1) as ss1 + right join (select 1 as z) as ss2 on true) + on false, + lateral (select i4.f1, ss1.n from int8_tbl as i8 limit 1) as ss3; + +--Testcase 580: +select 1 from + int4_tbl as i4 + inner join + ((select 42 as n from int4_tbl x1 left join int8_tbl x2 on f1 = q1) as ss1 + right join (select 1 as z) as ss2 on true) + on false, + lateral (select i4.f1, ss1.n from int8_tbl as i8 limit 1) as ss3; + +-- +-- check a case where we formerly generated invalid parameterized paths +-- + +begin; + +--Testcase 630: +CREATE FOREIGN TABLE t (a int options (key 'true')) SERVER sqlite_svr; + +--Testcase 631: +explain (costs off) +select 1 from t t1 + join lateral (select t1.a from (select 1) foo offset 0) as s1 on true + join + (select 1 from t t2 + inner join (t t3 + left join (t t4 left join t t5 on t4.a = 1) + on t3.a = t4.a) + on false + where t3.a = coalesce(t5.a,1)) as s2 + on true; + +rollback; + -- -- check a case in which a PlaceHolderVar forces join order -- @@ -1820,7 +2379,9 @@ explain (costs off) -- we force a mergejoin so that coalesce(b.q1, 1) appears as a join input -- +--Testcase 518: set enable_hashjoin to off; +--Testcase 519: set enable_nestloop to off; --Testcase 231: @@ -1833,9 +2394,82 @@ select a.q2, b.q1 from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) where coalesce(b.q1, 1) > 0; +--Testcase 520: reset enable_hashjoin; +--Testcase 521: reset enable_nestloop; +-- +-- test join strength reduction with a SubPlan providing the proof +-- + +--Testcase 581: +explain (costs off) +select a.unique1, b.unique2 + from onek a left join onek b on a.unique1 = b.unique2 + where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1); + +--Testcase 582: +select a.unique1, b.unique2 + from onek a left join onek b on a.unique1 = b.unique2 + where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1); + +-- +-- test full-join strength reduction +-- + +--Testcase 583: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42; + +--Testcase 584: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42; + +--Testcase 585: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where b.unique2 = 43; + +--Testcase 586: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where b.unique2 = 43; + +--Testcase 587: +explain (costs off) +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42 and b.unique2 = 42; + +--Testcase 588: +select a.unique1, b.unique2 + from onek a full join onek b on a.unique1 = b.unique2 + where a.unique1 = 42 and b.unique2 = 42; + +-- +-- test result-RTE removal underneath a full join +-- + +--Testcase 589: +explain (costs off) +select * from + (select * from int8_tbl i81 join (values(123,2)) v(v1,v2) on q2=v1) ss1 +full join + (select * from (values(456,2)) w(v1,v2) join int8_tbl i82 on q2=v1) ss2 +on true; + +--Testcase 590: +select * from + (select * from int8_tbl i81 join (values(123,2)) v(v1,v2) on q2=v1) ss1 +full join + (select * from (values(456,2)) w(v1,v2) join int8_tbl i82 on q2=v1) ss2 +on true; + -- -- test join removal -- @@ -1876,6 +2510,107 @@ select id from a3 where id in ( select b3.id from b3 left join c3 on b3.id = c3.id ); +-- check optimization with oddly-nested outer joins +--Testcase 591: +explain (costs off) +select a31.id from + (a3 a31 left join a3 a32 on true) + left join + (a3 a33 left join a3 a34 on a33.id = a34.id) + on a32.id = a33.id; + +--Testcase 592: +explain (costs off) +select a31.id from + (a3 a31 left join a3 a32 on a31.id = a32.id) + left join + (a3 a33 left join a3 a34 on a33.id = a34.id) + on a32.id = a33.id; + +--Testcase 593: +explain (costs off) +select 1 from a3 t1 + left join a3 t2 on true + inner join a3 t3 on true + left join a3 t4 on t2.id = t4.id and t2.id = t3.id; + +-- another example (bug #17781) +--Testcase 594: +explain (costs off) +select ss1.f1 +from int4_tbl as t1 + left join (int4_tbl as t2 + right join int4_tbl as t3 on null + left join (int4_tbl as t4 + right join int8_tbl as t5 on null) + on t2.f1 = t4.f1 + left join ((select null as f1 from int4_tbl as t6) as ss1 + inner join int8_tbl as t7 on null) + on t5.q1 = t7.q2) + on false; + +-- variant with Var rather than PHV coming from t6 +--Testcase 595: +explain (costs off) +select ss1.f1 +from int4_tbl as t1 + left join (int4_tbl as t2 + right join int4_tbl as t3 on null + left join (int4_tbl as t4 + right join int8_tbl as t5 on null) + on t2.f1 = t4.f1 + left join ((select f1 from int4_tbl as t6) as ss1 + inner join int8_tbl as t7 on null) + on t5.q1 = t7.q2) + on false; + +-- per further discussion of bug #17781 +--Testcase 596: +explain (costs off) +select ss1.x +from (select f1/2 as x from int4_tbl i4 left join a3 on a3.id = i4.f1) ss1 + right join int8_tbl i8 on true +where current_user is not null; -- this is to add a Result node + +-- and further discussion of bug #17781 +--Testcase 597: +explain (costs off) +select * +from int8_tbl t1 + left join (int8_tbl t2 left join onek t3 on t2.q1 > t3.unique1) + on t1.q2 = t2.q2 + left join onek t4 + on t2.q2 < t3.unique2; + +-- More tests of correct placement of pseudoconstant quals + +-- simple constant-false condition +--Testcase 598: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on false + left join int8_tbl t4 on t2.q2 = t4.q2) +on t1.q1 = t2.q1; + +-- deduce constant-false from an EquivalenceClass +--Testcase 599: +explain (costs off) +select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on (t2.q1-t3.q2) = 0 and (t2.q1-t3.q2) = 1 + left join int8_tbl t4 on t2.q2 = t4.q2) +on t1.q1 = t2.q1; + +-- pseudoconstant based on an outer-level Param +--Testcase 600: +explain (costs off) +select exists( + select * from int8_tbl t1 left join + (int8_tbl t2 inner join int8_tbl t3 on x0.f1 = 1 + left join int8_tbl t4 on t2.q2 = t4.q2) + on t1.q1 = t2.q1 +) from int4_tbl x0; + + -- check that join removal works for a left join when joining a subquery -- that is guaranteed to be unique by its GROUP BY clause --Testcase 241: @@ -1904,6 +2639,12 @@ explain (costs off) select d3.* from d3 left join (select distinct * from b3) s on d3.a = s.id; +-- join removal is not possible here +--Testcase 601: +explain (costs off) +select 1 from a3 t1 + left join (a3 t2 left join a3 t3 on t2.id = 1) on t2.id = 1; + -- check join removal works when uniqueness of the join condition is enforced -- by a UNION --Testcase 245: @@ -1923,6 +2664,23 @@ explain (costs off) select 1 from (select a3.id FROM a3 left join b3 on a3.b_id = b3.id) q, lateral generate_series(1, q.id) gs(i) where q.id = gs.i; +-- check join removal within RHS of an outer join +--Testcase 602: +explain (costs off) +select c3.id, ss.a from c3 + left join (select d3.a from onerow, d3 left join b3 on d3.a = b3.id) ss + on c3.id = ss.a; + +--Testcase 603: +CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); +--Testcase 604: +CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10); + +-- test join removals on a partitioned table +--Testcase 605: +explain (costs off) +select a3.* from a3 left join parted_b pb on a3.b_id = pb.id; + rollback; --Testcase 448: @@ -2008,6 +2766,32 @@ SELECT * FROM FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss2 ON true; +-- join removal bug #17769: can't remove if there's a pushed-down reference +--Testcase 606: +EXPLAIN (COSTS OFF) +SELECT q2 FROM + (SELECT * + FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss + WHERE COALESCE(dat1, 0) = q1; + +-- join removal bug #17773: otherwise-removable PHV appears in a qual condition +--Testcase 607: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT q2 FROM + (SELECT q2, 'constant'::text AS x + FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss + RIGHT JOIN int4_tbl ON NULL + WHERE x >= x; + +-- join removal bug #17786: check that OR conditions are cleaned up +--Testcase 608: +EXPLAIN (COSTS OFF) +SELECT f1, x +FROM int4_tbl + JOIN ((SELECT 42 AS x FROM int8_tbl LEFT JOIN innertab ON q1 = id) AS ss1 + RIGHT JOIN tenk1 ON NULL) + ON tenk1.unique1 = ss1.x OR tenk1.unique2 = ss1.x; + rollback; -- another join removal bug: we must clean up correctly when removing a PHV @@ -2054,6 +2838,105 @@ where ss.stringu2 !~* ss.case1; rollback; +-- another join removal bug: we must clean up EquivalenceClasses too +begin; + +--Testcase 609: +create temp table t (a int unique); +--Testcase 610: +insert into t values (1); + +--Testcase 611: +explain (costs off) +select 1 +from t t1 + left join (select 2 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true +where t1.a = s.c; + +--Testcase 612: +select 1 +from t t1 + left join (select 2 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true +where t1.a = s.c; + +rollback; + +-- test cases where we can remove a join, but not a PHV computed at it +begin; + +--Testcase 613: +create temp table t (a int unique, b int); +--Testcase 614: +insert into t values (1,1), (2,2); + +--Testcase 615: +explain (costs off) +select 1 +from t t1 + left join (select t2.a, 1 as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + +--Testcase 616: +explain (costs off) +select t1.a, s.* +from t t1 + left join lateral (select t2.a, coalesce(t1.a, 1) as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + +--Testcase 617: +select t1.a, s.* +from t t1 + left join lateral (select t2.a, coalesce(t1.a, 1) as c + from t t2 left join t t3 on t2.a = t3.a) s + on true + left join t t4 on true +where s.a < s.c; + +rollback; + +-- test case to expose miscomputation of required relid set for a PHV +--Testcase 522: +explain (verbose, costs off) +select i8.*, ss.v, t.unique2 + from int8_tbl i8 + left join int4_tbl i4 on i4.f1 = 1 + left join lateral (select i4.f1 + 1 as v) as ss on true + left join tenk1 t on t.unique2 = ss.v +where q2 = 456; + +--Testcase 523: +select i8.*, ss.v, t.unique2 + from int8_tbl i8 + left join int4_tbl i4 on i4.f1 = 1 + left join lateral (select i4.f1 + 1 as v) as ss on true + left join tenk1 t on t.unique2 = ss.v +where q2 = 456; + +-- -- and check a related issue where we miscompute required relids for +-- -- a PHV that's been translated to a child rel +-- create temp table parttbl (a integer primary key) partition by range (a); +-- create temp table parttbl1 partition of parttbl for values from (1) to (100); +-- insert into parttbl values (11), (12); +-- explain (costs off) +-- select * from +-- (select *, 12 as phv from parttbl) as ss +-- right join int4_tbl on true +-- where ss.a = ss.phv and f1 = 0; +-- select * from +-- (select *, 12 as phv from parttbl) as ss +-- right join int4_tbl on true +-- where ss.a = ss.phv and f1 = 0; + -- bug #8444: we've historically allowed duplicate aliases within aliased JOINs --Testcase 267: @@ -2079,6 +2962,9 @@ select t2.uunique1 from --Testcase 272: select uunique1 from tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once +--Testcase 618: +select ctid from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, need qualification -- -- Take care to reference the correct RTE @@ -2091,6 +2977,13 @@ select atts.relid::regclass, s.* from pg_stats s join indexrelid from pg_index i) atts on atts.attnum = a.attnum where schemaname != 'pg_catalog'; +-- Test bug in rangetable flattening +--Testcase 619: +explain (verbose, costs off) +select 1 from + (select * from int8_tbl where q1 <> (select 42) offset 0) ss +where false; + -- -- Test LATERAL -- @@ -2312,6 +3205,20 @@ select * from ) on c.q2 = ss2.q1, lateral (select ss2.y offset 0) ss3; +-- another case requiring nested PlaceHolderVars +--Testcase 635: +explain (verbose, costs off) +select * from + (select 0 as val0 FROM int8_tbl LIMIT 1) as ss0 + left join (select 1 as val FROM int8_tbl LIMIT 1) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + +--Testcase 636: +select * from + (select 0 as val0 FROM int8_tbl LIMIT 1) as ss0 + left join (select 1 as val FROM int8_tbl LIMIT 1) as ss1 on true + left join lateral (select ss1.val as val_filtered where false) as ss2 on true; + -- case that breaks the old ph_may_need optimization --Testcase 462: explain (verbose, costs off) @@ -2339,6 +3246,13 @@ select * from select * from (select key5 as z from sub_tbl offset 0) z where z.z = x.x ) zz on zz.z = y.y; +-- a new postponed-quals issue (bug #17768) +--Testcase 620: +explain (costs off) +select * from int4_tbl t1, + lateral (select * from int4_tbl t2 inner join int4_tbl t3 on t1.f1 = 1 + inner join (int4_tbl t4 left join int4_tbl t5 on true) on true) ss; + -- check dummy rels with lateral references (bug #15694) --Testcase 466: explain (verbose, costs off) @@ -2360,6 +3274,10 @@ select * from (select q1.v) ) as q2; +-- check the number of columns specified +--Testcase 539: +SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d); + -- check we don't try to do a unique-ified semijoin with LATERAL --Testcase 314: explain (verbose, costs off) @@ -2383,7 +3301,7 @@ select * from (values (0), (1)) v(id), lateral (select * from int8_tbl t1, lateral (select * from (select * from int8_tbl t2 - where q1 = any (select q2 from int8_tbl t3 + where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3 where q2 = (select greatest(t1.q1,t2.q2)) and (select v.id=0)) offset 0) ss2) ss where t1.q1 = ss.q2) ss0; @@ -2393,7 +3311,7 @@ select * from (values (0), (1)) v(id), lateral (select * from int8_tbl t1, lateral (select * from (select * from int8_tbl t2 - where q1 = any (select q2 from int8_tbl t3 + where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3 where q2 = (select greatest(t1.q1,t2.q2)) and (select v.id=0)) offset 0) ss2) ss where t1.q1 = ss.q2) ss0; @@ -2469,6 +3387,40 @@ delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss; --drop table join_pt1; --drop table join_ut1; +-- +-- test estimation behavior with multi-column foreign key and constant qual +-- + +begin; + +--Testcase 524: +create table fkest (x integer, x10 integer, x10b integer, x100 integer); +--Testcase 525: +insert into fkest select x, x/10, x/10, x/100 from generate_series(1,1000) x; +--Testcase 526: +create unique index on fkest(x, x10, x100); +analyze fkest; + +--Testcase 527: +explain (costs off) +select * from fkest f1 + join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100) + join fkest f3 on f1.x = f3.x + where f1.x100 = 2; + +--Testcase 528: +alter table fkest add constraint fk + foreign key (x, x10b, x100) references fkest (x, x10, x100); + +--Testcase 529: +explain (costs off) +select * from fkest f1 + join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100) + join fkest f3 on f1.x = f3.x + where f1.x100 = 2; + +rollback; + -- -- test that foreign key join estimation performs sanely for outer joins -- @@ -2622,11 +3574,46 @@ explain (verbose, costs off) select * from j12 left join j22 on j12.id1 = j22.id1 where j12.id2 = 1; +-- create unique index command does not work with foreign table +-- Add these normal tables for it. +--Testcase 624: +create table j1 (id1 int, id2 int, primary key(id1,id2)); +--Testcase 625: +create table j2 (id1 int, id2 int, primary key(id1,id2)); + +--Testcase 626: +insert into j1 values(1,1),(1,2); +--Testcase 627: +insert into j2 values(1,1); + +analyze j1; +analyze j2; + +--Testcase 621: +create unique index j1_id2_idx on j1(id2) where id2 is not null; + +-- ensure we don't use a partial unique index as unique proofs +--Testcase 622: +explain (verbose, costs off) +select * from j1 +inner join j2 on j1.id2 = j2.id2; + +--Testcase 623: +drop index j1_id2_idx; + +--Testcase 628: +drop table j1; +--Testcase 629: +drop table j2; + -- validate logic in merge joins which skips mark and restore. -- it should only do this if all quals which were used to detect the unique -- are present as join quals, and not plain quals. +--Testcase 530: set enable_nestloop to 0; +--Testcase 531: set enable_hashjoin to 0; +--Testcase 532: set enable_sort to 0; -- skip, cannot create index on foreign table -- create indexes that will be preferred over the PKs to perform the join @@ -2669,8 +3656,11 @@ select * from j12 inner join j22 on j12.id1 = j22.id1 and j12.id2 = j22.id2 where j12.id1 % 1000 = 1 and j22.id1 % 1000 = 1 and j22.id1 >= any (array[1,5]); +--Testcase 533: reset enable_nestloop; +--Testcase 534: reset enable_hashjoin; +--Testcase 535: reset enable_sort; --drop table j1; @@ -2678,26 +3668,6 @@ reset enable_sort; --drop table j3; -- check that semijoin inner is not seen as unique for a portion of the outerrel ---Testcase 483: -CREATE FOREIGN TABLE onek ( - unique1 int4 OPTIONS (key 'true'), - unique2 int4, - two int4, - four int4, - ten int4, - twenty int4, - hundred int4, - thousand int4, - twothousand int4, - fivethous int4, - tenthous int4, - odd int4, - even int4, - stringu1 name, - stringu2 name, - string4 name -) SERVER sqlite_svr; - --Testcase 358: explain (verbose, costs off) select t1.unique1, t2.hundred @@ -2724,6 +3694,36 @@ where exists (select 1 from j3 --Testcase 486: drop table j3; +-- sqlite_fdw is not supported WITH fillfactor, INDEX, VACUM, ANALYZE with foreign table. +-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate +-- tuples are discarded. This may occur when: +-- 1. A join doesn't require all inner tuples to be scanned for each outer +-- tuple, and +-- 2. The inner side is scanned using a bitmap heap scan, and +-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization. +-- This optimization is usable when no data from the underlying table is +-- needed. Use a temp table so it is only visible to this backend and +-- vacuum may reliably mark all blocks in the table all visible in the +-- visibility map. +-- CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10); +-- INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i; +-- CREATE INDEX ON skip_fetch(a); +-- VACUUM (ANALYZE) skip_fetch; +-- SET enable_indexonlyscan = off; +-- SET enable_seqscan = off; +-- EXPLAIN (COSTS OFF) +-- SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; +-- SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; +-- RESET enable_indexonlyscan; +-- RESET enable_seqscan; + +--Testcase 656: +DELETE FROM INT4_TBL; +--Testcase 657: +DELETE FROM FLOAT8_TBL; +--Testcase 658: +DELETE FROM INT8_TBL; + DO $d$ declare l_rec record; diff --git a/sql/14.9/extra/limit.sql b/sql/17.0/extra/limit.sql similarity index 94% rename from sql/14.9/extra/limit.sql rename to sql/17.0/extra/limit.sql index fad57bf9..86023207 100644 --- a/sql/14.9/extra/limit.sql +++ b/sql/17.0/extra/limit.sql @@ -29,6 +29,17 @@ CREATE FOREIGN TABLE onek( --Testcase 30: CREATE FOREIGN TABLE int8_tbl(q1 int8 OPTIONS (key 'true'), q2 int8) SERVER sqlite_svr; +--Testcase 105: +INSERT INTO int8_tbl VALUES(' 123 ',' 456'); +--Testcase 106: +INSERT INTO int8_tbl VALUES('123 ','4567890123456789'); +--Testcase 107: +INSERT INTO int8_tbl VALUES('4567890123456789','123'); +--Testcase 108: +INSERT INTO int8_tbl VALUES(+4567890123456789,'4567890123456789'); +--Testcase 109: +INSERT INTO int8_tbl VALUES('+4567890123456789','-4567890123456789'); + --Testcase 31: CREATE FOREIGN TABLE INT8_TMP( q1 int8, @@ -388,6 +399,12 @@ SELECT thousand FROM onek WHERE thousand < 5 ORDER BY thousand FETCH FIRST 2 ROW ONLY; +-- SKIP LOCKED and WITH TIES are incompatible +--Testcase 104: +SELECT thousand + FROM onek WHERE thousand < 5 + ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; + -- should fail --Testcase 76: SELECT ''::text AS two, unique1, unique2, stringu1 @@ -420,6 +437,8 @@ CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 \d+ limit_thousand_v_4 -- leave these views +--Testcase 110: +DELETE FROM int8_tbl; -- Clean up DO $d$ declare diff --git a/sql/13.12/extra/numeric.sql b/sql/17.0/extra/numeric.sql similarity index 66% rename from sql/13.12/extra/numeric.sql rename to sql/17.0/extra/numeric.sql index 7fdd6aea..68e99128 100644 --- a/sql/13.12/extra/numeric.sql +++ b/sql/17.0/extra/numeric.sql @@ -26,6 +26,9 @@ CREATE FOREIGN TABLE num_exp_log10 (id int4 OPTIONS (key 'true'), expected numer --Testcase 577: CREATE FOREIGN TABLE num_exp_power_10_ln (id int4 OPTIONS (key 'true'), expected numeric(210,10)) SERVER sqlite_svr; +--Testcase 1556: +CREATE FOREIGN TABLE num_variance (a numeric) SERVER sqlite_svr; + --Testcase 578: CREATE FOREIGN TABLE num_result (id1 int4 OPTIONS (key 'true'), id2 int4 OPTIONS (key 'true'), result numeric(210,10)) SERVER sqlite_svr; @@ -1136,12 +1139,406 @@ SELECT t1.id1, t1.result, t2.expected WHERE t1.id1 = t2.id AND t1.result != t2.expected; +-- ****************************** +-- * Check behavior with Inf and NaN inputs. It's easiest to handle these +-- * separately from the num_data framework used above, because some input +-- * combinations will throw errors. +-- ****************************** +--Testcase 1451: +CREATE FOREIGN TABLE v (id int4 OPTIONS (key 'true'), x numeric, val float8) SERVER sqlite_svr; + +BEGIN; +--Testcase 1452: +DELETE FROM v; +--Testcase 1453: +INSERT INTO v(x) VALUES ('0'::float8),('1'),('-1'),('4.2'),('inf'),('-inf'),('nan'); +--Testcase 1454: +SELECT x1, x2, + x1::numeric + x2::numeric AS sum, + x1::numeric - x2::numeric AS diff, + x1::numeric * x2::numeric AS prod +FROM v AS v1(id, x1), v AS v2(id, x2); + +--Testcase 1455: +SELECT x1, x2, + x1::numeric / x2::numeric AS quot, + x1::numeric % x2::numeric AS mod, + div(x1::numeric, x2::numeric) AS div +FROM v AS v1(id, x1), v AS v2(id, x2) WHERE x2 != 0; +ROLLBACK; + +BEGIN; +--Testcase 1286: +DELETE FROM v; +--Testcase 1287: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1288: +SELECT x::numeric / '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1289: +DELETE FROM v; +--Testcase 1290: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1291: +SELECT x::numeric / '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1292: +DELETE FROM v; +--Testcase 1293: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1294: +SELECT x::numeric / '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1295: +DELETE FROM v; +--Testcase 1296: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1297: +SELECT x::numeric / '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1298: +DELETE FROM v; +--Testcase 1299: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1300: +SELECT x::numeric % '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1301: +DELETE FROM v; +--Testcase 1302: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1303: +SELECT x::numeric % '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1304: +DELETE FROM v; +--Testcase 1305: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1306: +SELECT x::numeric % '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1307: +DELETE FROM v; +--Testcase 1308: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1309: +SELECT x::numeric % '0' FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1310: +DELETE FROM v; +--Testcase 1311: +INSERT INTO v(x) VALUES ('inf':: float8); +--Testcase 1312: +SELECT div(x::numeric, '0') FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1313: +DELETE FROM v; +--Testcase 1314: +INSERT INTO v(x) VALUES ('-inf':: float8); +--Testcase 1315: +SELECT div(x::numeric, '0') FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1316: +DELETE FROM v; +--Testcase 1317: +INSERT INTO v(x) VALUES ('nan':: float8); +--Testcase 1318: +SELECT div(x::numeric, '0') FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1319: +DELETE FROM v; +--Testcase 1320: +INSERT INTO v(x) VALUES ('0':: float8); +--Testcase 1321: +SELECT div(x::numeric, '0') FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1456: +DELETE FROM v; +--Testcase 1457: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('-1'),('4.2'),('-7.777'),('inf'),('-inf'),('nan'); +--Testcase 1458: +SELECT x, -x as minusx, abs(x::numeric), floor(x::numeric), ceil(x::numeric), sign(x::numeric), numeric_inc(x::numeric) as inc +FROM v; +ROLLBACK; + +BEGIN; +--Testcase 1459: +DELETE FROM v; +--Testcase 1460: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('-1'),('4.2'),('-7.777'),('inf'),('-inf'),('nan'); +--Testcase 1461: +SELECT x, round(x::numeric), round(x::numeric,1) as round1, trunc(x::numeric), trunc(x::numeric,1) as trunc1 +FROM v; +ROLLBACK; + +-- the large values fall into the numeric abbreviation code's maximal classes +BEGIN; +--Testcase 1462: +INSERT INTO v(x) VALUES ('0'::numeric),('1'),('-1'),('4.2'),('-7.777'), + ('inf'),('-inf'),('nan'), + ('inf'),('-inf'),('nan'); +--Testcase 1463: +SELECT substring(x::text, 1, 32) FROM v ORDER BY x; +ROLLBACK; + +--Testcase 1464: +DELETE FROM v; +--Testcase 1465: +INSERT INTO v(x) VALUES('0'::numeric),('1'),('4.2'),('inf'),('nan'); +--Testcase 1466: +SELECT x, sqrt(x) FROM v; + +--Testcase 1333: +DELETE FROM v; +--Testcase 1334: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1335: +SELECT sqrt(x::numeric) FROM v; +--Testcase 1336: +DELETE FROM v; +--Testcase 1337: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1338: +SELECT sqrt(x::numeric) FROM v; + +--Testcase 1467: +DELETE FROM v; +--Testcase 1468: +INSERT INTO v(x) VALUES ('1'::numeric),('4.2'),('inf'),('nan'); +--Testcase 1469: +SELECT x, + log(x::numeric), + log10(x::numeric), + ln(x::numeric) +FROM v; + +--Testcase 1342: +DELETE FROM v; +--Testcase 1343: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1344: +SELECT ln(x::numeric) FROM v; +--Testcase 1345: +DELETE FROM v; +--Testcase 1346: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1347: +SELECT ln(x::numeric) FROM v; +--Testcase 1348: +DELETE FROM v; +--Testcase 1349: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1350: +SELECT ln(x::numeric) FROM v; +--Testcase 1470: +DELETE FROM v; +--Testcase 1471: +INSERT INTO v(x) VALUES ('2'::numeric),('4.2'),('inf'),('nan'); +--Testcase 1472: +SELECT x1, x2, + log(x1::numeric, x2::numeric) +FROM v AS v1(id, x1), v AS v2(id, x2); +--Testcase 1354: +DELETE FROM v; +--Testcase 1355: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1356: +SELECT log(x::numeric, '10') FROM v; +--Testcase 1357: +DELETE FROM v; +--Testcase 1358: +INSERT INTO v(x) VALUES ('10'::float8); +--Testcase 1359: +SELECT log(x::numeric, '0') FROM v; +--Testcase 1360: +DELETE FROM v; +--Testcase 1361: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1362: +SELECT log(x::numeric, '10') FROM v; +--Testcase 1363: +DELETE FROM v; +--Testcase 1364: +INSERT INTO v(x) VALUES ('10'::float8); +--Testcase 1365: +SELECT log(x::numeric, '-inf') FROM v; +--Testcase 1366: +DELETE FROM v; +--Testcase 1367: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1368: +SELECT log(x::numeric, '0') FROM v; +--Testcase 1369: +DELETE FROM v; +--Testcase 1370: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1371: +SELECT log(x::numeric, '-inf') FROM v; +--Testcase 1372: +DELETE FROM v; +--Testcase 1373: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1374: +SELECT log(x::numeric, 'inf') FROM v; + +--Testcase 1473: +DELETE FROM v; +--Testcase 1474: +INSERT INTO v(x) VALUES ('0'::numeric),('1'),('2'),('4.2'),('inf'),('nan'); +--Testcase 1475: +SELECT x1, x2, + power(x1::numeric, x2::numeric) +FROM v AS v1(id, x1), v AS v2(id, x2) WHERE x1 != 0 OR x2 >= 0; + +--Testcase 1378: +DELETE FROM v; +--Testcase 1379: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1380: +SELECT power(x::numeric, '-1') FROM v; +--Testcase 1381: +DELETE FROM v; +--Testcase 1382: +INSERT INTO v(x) VALUES ('0'::float8); +--Testcase 1383: +SELECT power(x::numeric, '-inf') FROM v; +--Testcase 1384: +DELETE FROM v; +--Testcase 1385: +INSERT INTO v(x) VALUES ('-1'::float8); +--Testcase 1386: +SELECT power(x::numeric, 'inf') FROM v; +--Testcase 1387: +DELETE FROM v; +--Testcase 1388: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1389: +SELECT power(x::numeric, '3') FROM v; +--Testcase 1390: +DELETE FROM v; +--Testcase 1391: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1392: +SELECT power(x::numeric, '3.3') FROM v; +--Testcase 1393: +DELETE FROM v; +--Testcase 1394: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1395: +SELECT power(x::numeric, '-1') FROM v; +--Testcase 1396: +DELETE FROM v; +--Testcase 1397: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1398: +SELECT power(x::numeric, '-1.5') FROM v; +--Testcase 1399: +DELETE FROM v; +--Testcase 1400: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1401: +SELECT power(x::numeric, 'inf') FROM v; +--Testcase 1402: +DELETE FROM v; +--Testcase 1403: +INSERT INTO v(x) VALUES ('-2'::float8); +--Testcase 1404: +SELECT power(x::numeric, '-inf') FROM v; +--Testcase 1405: +DELETE FROM v; +--Testcase 1406: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1407: +SELECT power(x::numeric, '-2') FROM v; +--Testcase 1408: +DELETE FROM v; +--Testcase 1409: +INSERT INTO v(x) VALUES ('inf'::float8); +--Testcase 1410: +SELECT power(x::numeric, '-inf') FROM v; +--Testcase 1411: +DELETE FROM v; +--Testcase 1412: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1413: +SELECT power(x::numeric, '2') FROM v; +--Testcase 1414: +DELETE FROM v; +--Testcase 1415: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1416: +SELECT power(x::numeric, '3') FROM v; +--Testcase 1417: +DELETE FROM v; +--Testcase 1418: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1419: +SELECT power(x::numeric, '4.5') FROM v; +--Testcase 1420: +DELETE FROM v; +--Testcase 1421: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1422: +SELECT power(x::numeric, '-2') FROM v; +--Testcase 1423: +DELETE FROM v; +--Testcase 1424: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1425: +SELECT power(x::numeric, '-3') FROM v; +--Testcase 1426: +DELETE FROM v; +--Testcase 1427: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1428: +SELECT power(x::numeric, '0') FROM v; +--Testcase 1429: +DELETE FROM v; +--Testcase 1430: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1431: +SELECT power(x::numeric, 'inf') FROM v; +--Testcase 1432: +DELETE FROM v; +--Testcase 1433: +INSERT INTO v(x) VALUES ('-inf'::float8); +--Testcase 1434: +SELECT power(x::numeric, '-inf') FROM v; + -- ****************************** -- * miscellaneous checks for things that have been broken in the past... -- ****************************** -- numeric AVG used to fail on some platforms --Testcase 487: SELECT AVG(val) FROM num_data; +--Testcase 1137: +SELECT MAX(val) FROM num_data; +--Testcase 1138: +SELECT MIN(val) FROM num_data; --Testcase 488: SELECT STDDEV(val) FROM num_data; --Testcase 489: @@ -1166,11 +1563,114 @@ INSERT INTO fract_only VALUES (6, '0.99995'); -- should fail INSERT INTO fract_only VALUES (7, '0.00001'); --Testcase 497: INSERT INTO fract_only VALUES (8, '0.00017'); +--Testcase 1139: +INSERT INTO fract_only VALUES (9, 'NaN'); +--Testcase 1140: +INSERT INTO fract_only VALUES (10, 'Inf'); -- should fail +--Testcase 1141: +INSERT INTO fract_only VALUES (11, '-Inf'); -- should fail --Testcase 498: SELECT * FROM fract_only; --Testcase 580: DROP FOREIGN TABLE fract_only; +-- Check conversion to integers +-- SQLite promises to preserve the first 15 significant decimal digits of the floating point value. +-- However, it makes no guarantees about the accuracy of computations on floating point values, as no such guarantees are possible. +-- A floating-point value as written in an SQL statement may not be the same as the value represented internally. +-- Actual result is different from expected result. +--Testcase 1485: +CREATE FOREIGN TABLE num_tmp (n1 numeric, n2 numeric, id int options (key 'true')) SERVER sqlite_svr; + +--Testcase 1486: +DELETE FROM num_tmp; +--Testcase 1487: +INSERT INTO num_tmp(n1) VALUES (-9223372036854775808.5); +--Testcase 1488: +SELECT n1::int8 FROM num_tmp; -- should fail + +--Testcase 1489: +DELETE FROM num_tmp; +--Testcase 1490: +INSERT INTO num_tmp(n1) VALUES (-9223372036854775808.4); +--Testcase 1491: +SELECT n1::int8 FROM num_tmp; -- should fail + +--Testcase 1492: +DELETE FROM num_tmp; +--Testcase 1493: +INSERT INTO num_tmp(n1) VALUES (9223372036854775807.4); +--Testcase 1494: +SELECT n1::int8 FROM num_tmp; -- should fail + +--Testcase 1495: +DELETE FROM num_tmp; +--Testcase 1496: +INSERT INTO num_tmp(n1) VALUES (9223372036854775807.5); +--Testcase 1497: +SELECT n1::int8 FROM num_tmp; -- should fail + +--Testcase 1498: +DELETE FROM num_tmp; +--Testcase 1499: +INSERT INTO num_tmp(n1) VALUES (-2147483648.5); +--Testcase 1500: +SELECT n1::int4 FROM num_tmp; -- should fail + +--Testcase 1501: +DELETE FROM num_tmp; +--Testcase 1502: +INSERT INTO num_tmp(n1) VALUES (-2147483648.4); +--Testcase 1503: +SELECT n1::int4 FROM num_tmp; -- ok + +--Testcase 1504: +DELETE FROM num_tmp; +--Testcase 1505: +INSERT INTO num_tmp(n1) VALUES (2147483647.4); +--Testcase 1506: +SELECT n1::int4 FROM num_tmp; -- ok + +--Testcase 1507: +DELETE FROM num_tmp; +--Testcase 1508: +INSERT INTO num_tmp(n1) VALUES (2147483647.5); +--Testcase 1509: +SELECT n1::int4 FROM num_tmp; -- should fail + +--Testcase 1510: +DELETE FROM num_tmp; +--Testcase 1511: +INSERT INTO num_tmp(n1) VALUES (-32768.5); +--Testcase 1512: +SELECT n1::int2 FROM num_tmp; -- should fail + +--Testcase 1513: +DELETE FROM num_tmp; +--Testcase 1514: +INSERT INTO num_tmp(n1) VALUES (-32768.4); +--Testcase 1515: +SELECT n1::int2 FROM num_tmp; -- ok + +--Testcase 1516: +DELETE FROM num_tmp; +--Testcase 1517: +INSERT INTO num_tmp(n1) VALUES (32767.4); +--Testcase 1518: +SELECT n1::int2 FROM num_tmp; -- ok + +--Testcase 1519: +DELETE FROM num_tmp; +--Testcase 1520: +INSERT INTO num_tmp(n1) VALUES (32767.5); +--Testcase 1521: +SELECT n1::int2 FROM num_tmp; -- should fail + +--Testcase 1555: +DELETE FROM num_tmp; +--Testcase 1555: +DROP FOREIGN TABLE num_tmp; + -- Check inf/nan conversion behavior --Testcase 581: CREATE FOREIGN TABLE FLOAT8_TMP(f1 float8, f2 float8, id int OPTIONS (key 'true')) SERVER sqlite_svr; @@ -1195,6 +1695,28 @@ INSERT INTO FLOAT8_TMP VALUES ('-Infinity'); --Testcase 590: SELECT f1::numeric FROM FLOAT8_TMP; +--Testcase 1142: +CREATE FOREIGN TABLE NUMERIC_TMP(f1 numeric, f2 numeric, id int OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 1143: +DELETE FROM NUMERIC_TMP; +--Testcase 1144: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1145: +SELECT f1::float8 FROM NUMERIC_TMP; + +--Testcase 1146: +DELETE FROM NUMERIC_TMP; +--Testcase 1147: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1148: +SELECT f1::float8 FROM NUMERIC_TMP; + +--Testcase 1149: +DELETE FROM NUMERIC_TMP; +--Testcase 1150: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1151: +SELECT f1::float8 FROM NUMERIC_TMP; --Testcase 591: CREATE FOREIGN TABLE FLOAT4_TMP(f1 float4, id int OPTIONS (key 'true')) SERVER sqlite_svr; @@ -1219,6 +1741,97 @@ INSERT INTO FLOAT4_TMP VALUES ('-Infinity'); --Testcase 600: SELECT f1::numeric FROM FLOAT4_TMP; +--Testcase 1152: +DELETE FROM NUMERIC_TMP; +--Testcase 1153: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1154: +SELECT f1::float4 FROM NUMERIC_TMP; + +--Testcase 1155: +DELETE FROM NUMERIC_TMP; +--Testcase 1156: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1157: +SELECT f1::float4 FROM NUMERIC_TMP; + +--Testcase 1158: +DELETE FROM NUMERIC_TMP; +--Testcase 1159: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1160: +SELECT f1::float4 FROM NUMERIC_TMP; + +--Testcase 1161: +DELETE FROM NUMERIC_TMP; +--Testcase 1162: +INSERT INTO NUMERIC_TMP VALUES ('42'::int2); +--Testcase 1163: +SELECT f1::numeric FROM NUMERIC_TMP; + +--Testcase 1164: +DELETE FROM NUMERIC_TMP; +--Testcase 1165: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1166: +SELECT f1::int2 FROM NUMERIC_TMP; + +--Testcase 1167: +DELETE FROM NUMERIC_TMP; +--Testcase 1168: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1169: +SELECT f1::int2 FROM NUMERIC_TMP; + +--Testcase 1170: +DELETE FROM NUMERIC_TMP; +--Testcase 1171: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1172: +SELECT f1::int2 FROM NUMERIC_TMP; + +--Testcase 1173: +DELETE FROM NUMERIC_TMP; +--Testcase 1174: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1175: +SELECT f1::int4 FROM NUMERIC_TMP; + +--Testcase 1176: +DELETE FROM NUMERIC_TMP; +--Testcase 1177: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1178: +SELECT f1::int4 FROM NUMERIC_TMP; + +--Testcase 1179: +DELETE FROM NUMERIC_TMP; +--Testcase 1180: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1181: +SELECT f1::int4 FROM NUMERIC_TMP; + +--Testcase 1182: +DELETE FROM NUMERIC_TMP; +--Testcase 1183: +INSERT INTO NUMERIC_TMP VALUES ('NaN'); +--Testcase 1184: +SELECT f1::int8 FROM NUMERIC_TMP; + +--Testcase 1185: +DELETE FROM NUMERIC_TMP; +--Testcase 1186: +INSERT INTO NUMERIC_TMP VALUES ('Infinity'); +--Testcase 1187: +SELECT f1::int8 FROM NUMERIC_TMP; + +--Testcase 1188: +DELETE FROM NUMERIC_TMP; +--Testcase 1189: +INSERT INTO NUMERIC_TMP VALUES ('-Infinity'); +--Testcase 1190: +SELECT f1::int8 FROM NUMERIC_TMP; + -- Simple check that ceil(), floor(), and round() work correctly --Testcase 601: CREATE FOREIGN TABLE ceil_floor_round (a numeric OPTIONS (key 'true')) SERVER sqlite_svr; @@ -1256,6 +1869,32 @@ SELECT f1 as pow, round((2.5 * 10 ^ f1)::numeric, -f1) FROM INT4_TMP; +-- These cases contain out of range value for type double precision, cannot insert into foreign table. +-- -- Check limits of rounding before the decimal point +-- SELECT round(4.4e131071, -131071) = 4e131071; +-- SELECT round(4.5e131071, -131071) = 5e131071; +-- SELECT round(4.5e131071, -131072); -- loses all digits +-- SELECT round(5.5e131071, -131072); -- rounds up and overflows +-- SELECT round(5.5e131071, -131073); -- loses all digits +-- SELECT round(5.5e131071, -1000000); -- loses all digits + +-- -- Check limits of rounding after the decimal point +-- SELECT round(5e-16383, 1000000) = 5e-16383; +-- SELECT round(5e-16383, 16383) = 5e-16383; +-- SELECT round(5e-16383, 16382) = 1e-16382; +-- SELECT round(5e-16383, 16381) = 0; + +-- -- Check limits of trunc() before the decimal point +-- SELECT trunc(9.9e131071, -131071) = 9e131071; +-- SELECT trunc(9.9e131071, -131072); -- loses all digits +-- SELECT trunc(9.9e131071, -131073); -- loses all digits +-- SELECT trunc(9.9e131071, -1000000); -- loses all digits + +-- -- Check limits of trunc() after the decimal point +-- SELECT trunc(5e-16383, 1000000) = 5e-16383; +-- SELECT trunc(5e-16383, 16383) = 5e-16383; +-- SELECT trunc(5e-16383, 16382) = 0; + -- Testing for width_bucket(). For convenience, we test both the -- numeric and float8 versions of the function in this file. -- errors @@ -1324,6 +1963,19 @@ INSERT INTO width_bucket_tbl VALUES (0, 'NaN'::numeric, 4.0, 888); --Testcase 630: SELECT width_bucket(id1::float8, id2, id3::float8, id4) FROM width_bucket_tbl; +--Testcase 1191: +DELETE FROM width_bucket_tbl; +--Testcase 1192: +INSERT INTO width_bucket_tbl VALUES (2.0, 3.0, '-inf'::numeric, 888); +--Testcase 1193: +SELECT width_bucket(id1, id2, id3, id4) FROM width_bucket_tbl; + +--Testcase 1194: +DELETE FROM width_bucket_tbl; +--Testcase 1195: +INSERT INTO width_bucket_tbl VALUES (0, '-inf'::numeric, 4.0 , 888); +--Testcase 1196: +SELECT width_bucket(id1::float8, id2, id3::float8, id4) FROM width_bucket_tbl; -- normal operation --Testcase 631: @@ -1373,8 +2025,26 @@ SELECT width_bucket(operand_f8, -25, 25, 10) AS wb_5f FROM width_bucket_test; --- for float8 only, check positive and negative infinity: we require +-- Check positive and negative infinity: we require -- finite bucket bounds, but allow an infinite operand +--Testcase 1197: +DELETE FROM width_bucket_tbl; +--Testcase 1198: +INSERT INTO width_bucket_tbl VALUES (0.0, 'Infinity'::numeric , 5, 10); +--Testcase 1199: +SELECT width_bucket(id1::numeric, 'Infinity'::numeric, id3, id4) FROM width_bucket_tbl; -- error +--Testcase 1200: +DELETE FROM width_bucket_tbl; +--Testcase 1201: +INSERT INTO width_bucket_tbl VALUES (0.0, 5, '-Infinity'::numeric, 20); +--Testcase 1202: +SELECT width_bucket(id1::numeric, id2, '-Infinity'::numeric, id4) FROM width_bucket_tbl; -- error +--Testcase 1203: +DELETE FROM width_bucket_tbl; +--Testcase 1204: +INSERT INTO width_bucket_tbl VALUES ('Infinity'::numeric, 1, 10, 10), ('-Infinity'::numeric, 1, 10, 10); +--Testcase 1205: +SELECT width_bucket(id1::numeric, id2, id3, id4) FROM width_bucket_tbl; --Testcase 510: DELETE FROM width_bucket_tbl; -- postgres does not support insert 'Infinity' and '-Infinity' as numeric. @@ -1396,257 +2066,363 @@ INSERT INTO width_bucket_tbl VALUES (0.0, 1, 10, 10); --Testcase 637: SELECT width_bucket('Infinity'::float8, id2, id3, id4), width_bucket('-Infinity'::float8, id2, id3, id4) FROM width_bucket_tbl; +-- Simple test for roundoff error when results should be exact +--Testcase 1445: +DELETE FROM width_bucket_tbl; +--Testcase 1446: +INSERT INTO width_bucket_tbl SELECT x, 10, 100, 9 FROM generate_series(0, 110, 10) x; +--Testcase 1447: +SELECT id1, width_bucket(id1::float8, id2, id3, id4) as flt, + width_bucket(id1::numeric, id2, id3, id4) as num FROM width_bucket_tbl; + +--Testcase 1448: +DELETE FROM width_bucket_tbl; +--Testcase 1449: +INSERT INTO width_bucket_tbl SELECT x, 100, 10, 9 FROM generate_series(0, 110, 10) x; +--Testcase 1450: +SELECT id1, width_bucket(id1::float8, 100, 10, 9) as flt, + width_bucket(id1::numeric, id2, id3, id4) as num FROM width_bucket_tbl; + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(0, -1e100::numeric, 1, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(0, -1e100::float8, 1, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(1, 1e100::numeric, 0, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + +DELETE FROM width_bucket_tbl; +INSERT INTO width_bucket_tbl VALUES(1, 1e100::float8, 0, 10); +SELECT width_bucket(id1, id2::numeric, id3, id4) FROM width_bucket_tbl; + +-- Check cases that could trigger overflow or underflow within the calculation +SELECT oper, low, high, cnt, width_bucket(oper, low, high, cnt) +FROM + (SELECT 1.797e+308::float8 AS big, 5e-324::float8 AS tiny) as v, + LATERAL (VALUES + (10.5::float8, -big, big, 1), + (10.5::float8, -big, big, 2), + (10.5::float8, -big, big, 3), + (big / 4, -big / 2, big / 2, 10), + (10.5::float8, big, -big, 1), + (10.5::float8, big, -big, 2), + (10.5::float8, big, -big, 3), + (big / 4, big / 2, -big / 2, 10), + (0, 0, tiny, 4), + (tiny, 0, tiny, 4), + (0, 0, 1, 2147483647), + (1, 1, 0, 2147483647) + ) as sample(oper, low, high, cnt); +-- These fail because the result would be out of int32 range: +-- Do not convert to check right. +SELECT width_bucket(1::float8, 0, 1, 2147483647); +SELECT width_bucket(0::float8, 1, 0, 2147483647); + --Testcase 638: DROP FOREIGN TABLE width_bucket_test; + -- TO_CHAR() -- --Testcase 513: -SELECT '' AS to_char_1, to_char(val, '9G999G999G999G999G999') +SELECT to_char(val, '9G999G999G999G999G999') FROM num_data; --Testcase 514: -SELECT '' AS to_char_2, to_char(val, '9G999G999G999G999G999D999G999G999G999G999') +SELECT to_char(val, '9G999G999G999G999G999D999G999G999G999G999') FROM num_data; --Testcase 515: -SELECT '' AS to_char_3, to_char(val, '9999999999999999.999999999999999PR') +SELECT to_char(val, '9999999999999999.999999999999999PR') FROM num_data; --Testcase 516: -SELECT '' AS to_char_4, to_char(val, '9999999999999999.999999999999999S') +SELECT to_char(val, '9999999999999999.999999999999999S') FROM num_data; --Testcase 517: -SELECT '' AS to_char_5, to_char(val, 'MI9999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, 'MI9999999999999999.999999999999999') FROM num_data; --Testcase 518: -SELECT '' AS to_char_6, to_char(val, 'FMS9999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, 'FMS9999999999999999.999999999999999') FROM num_data; --Testcase 519: -SELECT '' AS to_char_7, to_char(val, 'FM9999999999999999.999999999999999THPR') FROM num_data; +SELECT to_char(val, 'FM9999999999999999.999999999999999THPR') FROM num_data; --Testcase 520: -SELECT '' AS to_char_8, to_char(val, 'SG9999999999999999.999999999999999th') FROM num_data; +SELECT to_char(val, 'SG9999999999999999.999999999999999th') FROM num_data; --Testcase 521: -SELECT '' AS to_char_9, to_char(val, '0999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, '0999999999999999.999999999999999') FROM num_data; --Testcase 522: -SELECT '' AS to_char_10, to_char(val, 'S0999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, 'S0999999999999999.999999999999999') FROM num_data; --Testcase 523: -SELECT '' AS to_char_11, to_char(val, 'FM0999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, 'FM0999999999999999.999999999999999') FROM num_data; --Testcase 524: -SELECT '' AS to_char_12, to_char(val, 'FM9999999999999999.099999999999999') FROM num_data; +SELECT to_char(val, 'FM9999999999999999.099999999999999') FROM num_data; --Testcase 525: -SELECT '' AS to_char_13, to_char(val, 'FM9999999999990999.990999999999999') FROM num_data; +SELECT to_char(val, 'FM9999999999990999.990999999999999') FROM num_data; --Testcase 526: -SELECT '' AS to_char_14, to_char(val, 'FM0999999999999999.999909999999999') FROM num_data; +SELECT to_char(val, 'FM0999999999999999.999909999999999') FROM num_data; --Testcase 527: -SELECT '' AS to_char_15, to_char(val, 'FM9999999990999999.099999999999999') FROM num_data; +SELECT to_char(val, 'FM9999999990999999.099999999999999') FROM num_data; --Testcase 528: -SELECT '' AS to_char_16, to_char(val, 'L9999999999999999.099999999999999') FROM num_data; +SELECT to_char(val, 'L9999999999999999.099999999999999') FROM num_data; --Testcase 529: -SELECT '' AS to_char_17, to_char(val, 'FM9999999999999999.99999999999999') FROM num_data; +SELECT to_char(val, 'FM9999999999999999.99999999999999') FROM num_data; --Testcase 530: -SELECT '' AS to_char_18, to_char(val, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; +SELECT to_char(val, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; --Testcase 531: -SELECT '' AS to_char_19, to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; +SELECT to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data; --Testcase 532: -SELECT '' AS to_char_20, to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data; +SELECT to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data; --Testcase 533: -SELECT '' AS to_char_21, to_char(val, '999999SG9999999999') FROM num_data; +SELECT to_char(val, '999999SG9999999999') FROM num_data; --Testcase 534: -SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM num_data; +SELECT to_char(val, 'FM9999999999999999.999999999999999') FROM num_data; --Testcase 535: -SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data; +SELECT to_char(val, '9.999EEEE') FROM num_data; + +--Testcase 1476: +DELETE FROM v; +--Testcase 1477: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1478: +SELECT x, + to_char(x, '9.999EEEE') as numeric, + to_char(x::float8, '9.999EEEE') as float8, + to_char(x::float4, '9.999EEEE') as float4 +FROM v; + +--Testcase 1522: +DELETE FROM v; +--Testcase 1523: +INSERT INTO v(x) VALUES (-16379),(-16378),(-1234),(-789),(-45),(-5),(-4),(-3),(-2),(-1),(0), + (1),(2),(3),(4),(5),(38),(275),(2345),(45678),(131070),(131071); +--Testcase 1524: +SELECT x, + to_char(('1.2345e'||x)::numeric, '9.999EEEE') as numeric +FROM v; + +--Testcase 1479: +DELETE FROM v; +--Testcase 1480: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1481: +SELECT x, + to_char(x, 'MI9999999999.99') as numeric, + to_char(x::float8, 'MI9999999999.99') as float8, + to_char(x::float4, 'MI9999999999.99') as float4 +FROM v; + +--Testcase 1482: +DELETE FROM v; +--Testcase 1483: +INSERT INTO v(x) VALUES ('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan'); +--Testcase 1484: +SELECT x, + to_char(x, 'MI99.99') as numeric, + to_char(x::float8, 'MI99.99') as float8, + to_char(x::float4, 'MI99.99') as float4 +FROM v; --Testcase 536: DELETE FROM ceil_floor_round; --Testcase 537: INSERT INTO ceil_floor_round VALUES ('100'::numeric); --Testcase 538: -SELECT '' AS to_char_24, to_char(a, 'FM999.9') FROM ceil_floor_round; +SELECT to_char(a, 'FM999.9') FROM ceil_floor_round; --Testcase 539: -SELECT '' AS to_char_25, to_char(a, 'FM999.') FROM ceil_floor_round; +SELECT to_char(a, 'FM999.') FROM ceil_floor_round; --Testcase 540: -SELECT '' AS to_char_26, to_char(a, 'FM999') FROM ceil_floor_round; +SELECT to_char(a, 'FM999') FROM ceil_floor_round; + +CREATE FOREIGN TABLE ceil_round_float8(a float8) SERVER sqlite_svr; +INSERT INTO ceil_round_float8 VALUES ('12345678901'::float8); +SELECT to_char(a, 'FM9999999999D9999900000000000000000') FROM ceil_round_float8; -- Check parsing of literal text in a format string --Testcase 541: -SELECT '' AS to_char_27, to_char(a, 'foo999') FROM ceil_floor_round; +SELECT to_char(a, 'foo999') FROM ceil_floor_round; --Testcase 542: -SELECT '' AS to_char_28, to_char(a, 'f\oo999') FROM ceil_floor_round; +SELECT to_char(a, 'f\oo999') FROM ceil_floor_round; --Testcase 543: -SELECT '' AS to_char_29, to_char(a, 'f\\oo999') FROM ceil_floor_round; +SELECT to_char(a, 'f\\oo999') FROM ceil_floor_round; --Testcase 544: -SELECT '' AS to_char_30, to_char(a, 'f\"oo999') FROM ceil_floor_round; +SELECT to_char(a, 'f\"oo999') FROM ceil_floor_round; --Testcase 545: -SELECT '' AS to_char_31, to_char(a, 'f\\"oo999') FROM ceil_floor_round; +SELECT to_char(a, 'f\\"oo999') FROM ceil_floor_round; --Testcase 546: -SELECT '' AS to_char_32, to_char(a, 'f"ool"999') FROM ceil_floor_round; +SELECT to_char(a, 'f"ool"999') FROM ceil_floor_round; --Testcase 547: -SELECT '' AS to_char_33, to_char(a, 'f"\ool"999') FROM ceil_floor_round; +SELECT to_char(a, 'f"\ool"999') FROM ceil_floor_round; --Testcase 548: -SELECT '' AS to_char_34, to_char(a, 'f"\\ool"999') FROM ceil_floor_round; +SELECT to_char(a, 'f"\\ool"999') FROM ceil_floor_round; --Testcase 549: -SELECT '' AS to_char_35, to_char(a, 'f"ool\"999') FROM ceil_floor_round; +SELECT to_char(a, 'f"ool\"999') FROM ceil_floor_round; --Testcase 550: -SELECT '' AS to_char_36, to_char(a, 'f"ool\\"999') FROM ceil_floor_round; +SELECT to_char(a, 'f"ool\\"999') FROM ceil_floor_round; -- TO_NUMBER() -- --Testcase 639: create foreign table to_number_tbl (a text, id int options (key 'true')) server sqlite_svr; +--Testcase 1211: SET lc_numeric = 'C'; --Testcase 640: DELETE FROM to_number_tbl; --Testcase 641: INSERT INTO to_number_tbl VALUES ('-34,338,492'); --Testcase 642: -SELECT '' AS to_number_1, to_number(a, '99G999G999') FROM to_number_tbl; +SELECT to_number(a, '99G999G999') FROM to_number_tbl; --Testcase 643: DELETE FROM to_number_tbl; --Testcase 644: INSERT INTO to_number_tbl VALUES ('-34,338,492.654,878'); --Testcase 645: -SELECT '' AS to_number_2, to_number(a, '99G999G999D999G999') FROM to_number_tbl; +SELECT to_number(a, '99G999G999D999G999') FROM to_number_tbl; --Testcase 646: DELETE FROM to_number_tbl; --Testcase 647: INSERT INTO to_number_tbl VALUES ('<564646.654564>'); --Testcase 648: -SELECT '' AS to_number_3, to_number(a, '999999.999999PR') FROM to_number_tbl; +SELECT to_number(a, '999999.999999PR') FROM to_number_tbl; --Testcase 649: DELETE FROM to_number_tbl; --Testcase 650: INSERT INTO to_number_tbl VALUES ('0.00001-'); --Testcase 651: -SELECT '' AS to_number_4, to_number(a, '9.999999S') FROM to_number_tbl; +SELECT to_number(a, '9.999999S') FROM to_number_tbl; --Testcase 652: DELETE FROM to_number_tbl; --Testcase 653: INSERT INTO to_number_tbl VALUES ('5.01-'); --Testcase 654: -SELECT '' AS to_number_5, to_number(a, 'FM9.999999S') FROM to_number_tbl; +SELECT to_number(a, 'FM9.999999S') FROM to_number_tbl; --Testcase 655: DELETE FROM to_number_tbl; --Testcase 656: INSERT INTO to_number_tbl VALUES ('5.01-'); --Testcase 657: -SELECT '' AS to_number_5, to_number(a, 'FM9.999999MI') FROM to_number_tbl; +SELECT to_number(a, 'FM9.999999MI') FROM to_number_tbl; --Testcase 658: DELETE FROM to_number_tbl; --Testcase 659: INSERT INTO to_number_tbl VALUES ('5 4 4 4 4 8 . 7 8'); --Testcase 660: -SELECT '' AS to_number_7, to_number(a, '9 9 9 9 9 9 . 9 9') FROM to_number_tbl; +SELECT to_number(a, '9 9 9 9 9 9 . 9 9') FROM to_number_tbl; --Testcase 661: DELETE FROM to_number_tbl; --Testcase 662: INSERT INTO to_number_tbl VALUES ('.01'); --Testcase 663: -SELECT '' AS to_number_8, to_number(a, 'FM9.99') FROM to_number_tbl; +SELECT to_number(a, 'FM9.99') FROM to_number_tbl; --Testcase 664: DELETE FROM to_number_tbl; --Testcase 665: INSERT INTO to_number_tbl VALUES ('.0'); --Testcase 666: -SELECT '' AS to_number_9, to_number(a, '99999999.99999999') FROM to_number_tbl; +SELECT to_number(a, '99999999.99999999') FROM to_number_tbl; --Testcase 667: DELETE FROM to_number_tbl; --Testcase 668: INSERT INTO to_number_tbl VALUES ('0'); --Testcase 669: -SELECT '' AS to_number_10, to_number(a, '99.99') FROM to_number_tbl; +SELECT to_number(a, '99.99') FROM to_number_tbl; --Testcase 670: DELETE FROM to_number_tbl; --Testcase 671: INSERT INTO to_number_tbl VALUES ('.-01'); --Testcase 672: -SELECT '' AS to_number_11, to_number(a, 'S99.99') FROM to_number_tbl; +SELECT to_number(a, 'S99.99') FROM to_number_tbl; --Testcase 673: DELETE FROM to_number_tbl; --Testcase 674: INSERT INTO to_number_tbl VALUES ('.01-'); --Testcase 675: -SELECT '' AS to_number_12, to_number(a, '99.99S') FROM to_number_tbl; +SELECT to_number(a, '99.99S') FROM to_number_tbl; --Testcase 676: DELETE FROM to_number_tbl; --Testcase 677: INSERT INTO to_number_tbl VALUES (' . 0 1-'); --Testcase 678: -SELECT '' AS to_number_13, to_number(a, ' 9 9 . 9 9 S') FROM to_number_tbl; +SELECT to_number(a, ' 9 9 . 9 9 S') FROM to_number_tbl; --Testcase 679: DELETE FROM to_number_tbl; --Testcase 680: INSERT INTO to_number_tbl VALUES ('34,50'); --Testcase 681: -SELECT '' AS to_number_14, to_number(a,'999,99') FROM to_number_tbl; +SELECT to_number(a,'999,99') FROM to_number_tbl; --Testcase 682: DELETE FROM to_number_tbl; --Testcase 683: INSERT INTO to_number_tbl VALUES ('123,000'); --Testcase 684: -SELECT '' AS to_number_15, to_number(a,'999G') FROM to_number_tbl; +SELECT to_number(a,'999G') FROM to_number_tbl; --Testcase 685: DELETE FROM to_number_tbl; --Testcase 686: INSERT INTO to_number_tbl VALUES ('123456'); --Testcase 687: -SELECT '' AS to_number_16, to_number(a,'999G999') FROM to_number_tbl; +SELECT to_number(a,'999G999') FROM to_number_tbl; --Testcase 688: DELETE FROM to_number_tbl; --Testcase 689: INSERT INTO to_number_tbl VALUES ('$1234.56'); --Testcase 690: -SELECT '' AS to_number_17, to_number(a,'L9,999.99') FROM to_number_tbl; +SELECT to_number(a,'L9,999.99') FROM to_number_tbl; --Testcase 691: DELETE FROM to_number_tbl; --Testcase 692: INSERT INTO to_number_tbl VALUES ('$1234.56'); --Testcase 693: -SELECT '' AS to_number_18, to_number(a,'L99,999.99') FROM to_number_tbl; +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; --Testcase 694: DELETE FROM to_number_tbl; --Testcase 695: INSERT INTO to_number_tbl VALUES ('$1,234.56'); --Testcase 696: -SELECT '' AS to_number_19, to_number(a,'L99,999.99') FROM to_number_tbl; +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; --Testcase 697: DELETE FROM to_number_tbl; --Testcase 698: INSERT INTO to_number_tbl VALUES ('1234.56'); --Testcase 699: -SELECT '' AS to_number_20, to_number(a,'L99,999.99') FROM to_number_tbl; +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; --Testcase 700: DELETE FROM to_number_tbl; --Testcase 701: INSERT INTO to_number_tbl VALUES ('1,234.56'); --Testcase 702: -SELECT '' AS to_number_21, to_number(a,'L99,999.99') FROM to_number_tbl; +SELECT to_number(a,'L99,999.99') FROM to_number_tbl; --Testcase 703: DELETE FROM to_number_tbl; --Testcase 704: INSERT INTO to_number_tbl VALUES ('42nd'); --Testcase 705: -SELECT '' AS to_number_22, to_number(a, '99th') FROM to_number_tbl; +SELECT to_number(a, '99th') FROM to_number_tbl; +--Testcase 1212: RESET lc_numeric; -- -- Input syntax @@ -1670,6 +2446,29 @@ INSERT INTO num_input_test(n1) VALUES ('-555.50'); INSERT INTO num_input_test(n1) VALUES ('NaN '); --Testcase 557: INSERT INTO num_input_test(n1) VALUES (' nan'); +--Testcase 1213: +INSERT INTO num_input_test(n1) VALUES (' inf '); +--Testcase 1214: +INSERT INTO num_input_test(n1) VALUES (' +inf '); +--Testcase 1215: +INSERT INTO num_input_test(n1) VALUES (' -inf '); +--Testcase 1216: +INSERT INTO num_input_test(n1) VALUES (' Infinity '); +--Testcase 1217: +INSERT INTO num_input_test(n1) VALUES (' +inFinity '); +--Testcase 1218: +INSERT INTO num_input_test(n1) VALUES (' -INFINITY '); +INSERT INTO num_input_test(n1) VALUES ('12_000_000_000'); +INSERT INTO num_input_test(n1) VALUES ('12_000.123_456'); +INSERT INTO num_input_test(n1) VALUES ('23_000_000_000e-1_0'); +INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e1_0'); +INSERT INTO num_input_test(n1) VALUES ('.000_000_000_123e+1_1'); +INSERT INTO num_input_test(n1) VALUES ('0b10001110111100111100001001010'); +INSERT INTO num_input_test(n1) VALUES (' -0B_1010_1011_0101_0100_1010_1001_1000_1100_1110_1011_0001_1111_0000_1010_1101_0010 '); +INSERT INTO num_input_test(n1) VALUES (' +0o112402761777 '); +INSERT INTO num_input_test(n1) VALUES ('-0O0012_5524_5230_6334_3167_0261'); +INSERT INTO num_input_test(n1) VALUES ('-0x0000000000000000000000000deadbeef'); +INSERT INTO num_input_test(n1) VALUES (' 0X_30b1_F33a_6DF0_bD4E_64DF_9BdA_7D15 '); -- bad inputs --Testcase 558: @@ -1688,10 +2487,96 @@ INSERT INTO num_input_test(n1) VALUES ('5. 0 '); INSERT INTO num_input_test(n1) VALUES (''); --Testcase 565: INSERT INTO num_input_test(n1) VALUES (' N aN '); +INSERT INTO num_input_test(n1) VALUES ('+NaN'); +INSERT INTO num_input_test(n1) VALUES ('-NaN'); +--Testcase 1219: +INSERT INTO num_input_test(n1) VALUES ('+ infinity'); +INSERT INTO num_input_test(n1) VALUES ('_123'); +INSERT INTO num_input_test(n1) VALUES ('123_'); +INSERT INTO num_input_test(n1) VALUES ('12__34'); +INSERT INTO num_input_test(n1) VALUES ('123_.456'); +INSERT INTO num_input_test(n1) VALUES ('123._456'); +INSERT INTO num_input_test(n1) VALUES ('1.2e_34'); +INSERT INTO num_input_test(n1) VALUES ('1.2e34_'); +INSERT INTO num_input_test(n1) VALUES ('1.2e3__4'); +INSERT INTO num_input_test(n1) VALUES ('0b1112'); +INSERT INTO num_input_test(n1) VALUES ('0c1112'); +INSERT INTO num_input_test(n1) VALUES ('0o12345678'); +INSERT INTO num_input_test(n1) VALUES ('0x1eg'); +INSERT INTO num_input_test(n1) VALUES ('0x12.34'); +INSERT INTO num_input_test(n1) VALUES ('0x__1234'); +INSERT INTO num_input_test(n1) VALUES ('0x1234_'); +INSERT INTO num_input_test(n1) VALUES ('0x12__34'); --Testcase 566: SELECT * FROM num_input_test; +-- Also try it with non-error-throwing API +CREATE FOREIGN TABLE NON_ERROR_THROWING_API_INT4_NUMERIC(f1 text, id serial OPTIONS (key 'true')) SERVER sqlite_svr; +INSERT INTO NON_ERROR_THROWING_API_INT4_NUMERIC VALUES ('34.5', 1), ('34xyz', 2), ('1e400000', 3); +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 1; +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 2; +SELECT pg_input_is_valid(f1, 'numeric') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 3; +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 3), 'numeric'); + +INSERT INTO NON_ERROR_THROWING_API_INT4_NUMERIC VALUES ('1234.567', 4), ('0x1234.567', 5); +SELECT pg_input_is_valid(f1, 'numeric(8,4)') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4; +SELECT pg_input_is_valid(f1, 'numeric(7,4)') FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4; +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 4), 'numeric(7,4)'); +SELECT * FROM pg_input_error_info((SELECT f1 FROM NON_ERROR_THROWING_API_INT4_NUMERIC WHERE id = 5), 'numeric'); + +-- +-- Test precision and scale typemods +-- + +--Testcase 1557: +CREATE FOREIGN TABLE num_typemod_test ( + millions numeric(3, -6), + thousands numeric(3, -3), + units numeric(3, 0), + thousandths numeric(3, 3), + millionths numeric(3, 6) +) SERVER sqlite_svr; +--Testcase 1558: +\d num_typemod_test + +-- rounding of valid inputs +--Testcase 1559: +INSERT INTO num_typemod_test VALUES (123456, 123, 0.123, 0.000123, 0.000000123); +--Testcase 1560: +INSERT INTO num_typemod_test VALUES (654321, 654, 0.654, 0.000654, 0.000000654); +--Testcase 1561: +INSERT INTO num_typemod_test VALUES (2345678, 2345, 2.345, 0.002345, 0.000002345); +--Testcase 1562: +INSERT INTO num_typemod_test VALUES (7654321, 7654, 7.654, 0.007654, 0.000007654); +--Testcase 1563: +INSERT INTO num_typemod_test VALUES (12345678, 12345, 12.345, 0.012345, 0.000012345); +--Testcase 1564: +INSERT INTO num_typemod_test VALUES (87654321, 87654, 87.654, 0.087654, 0.000087654); +--Testcase 1565: +INSERT INTO num_typemod_test VALUES (123456789, 123456, 123.456, 0.123456, 0.000123456); +--Testcase 1566: +INSERT INTO num_typemod_test VALUES (987654321, 987654, 987.654, 0.987654, 0.000987654); +--Testcase 1567: +INSERT INTO num_typemod_test VALUES ('NaN', 'NaN', 'NaN', 'NaN', 'NaN'); + +--Testcase 1568: +SELECT scale(millions), * FROM num_typemod_test ORDER BY millions; + +-- invalid inputs +--Testcase 1569: +INSERT INTO num_typemod_test (millions) VALUES ('inf'); +--Testcase 1570: +INSERT INTO num_typemod_test (millions) VALUES (999500000); +--Testcase 1571: +INSERT INTO num_typemod_test (thousands) VALUES (999500); +--Testcase 1572: +INSERT INTO num_typemod_test (units) VALUES (999.5); +--Testcase 1573: +INSERT INTO num_typemod_test (thousandths) VALUES (0.9995); +--Testcase 1574: +INSERT INTO num_typemod_test (millionths) VALUES (0.0009995); + -- -- Test some corner cases for multiplication -- @@ -1723,6 +2608,13 @@ INSERT INTO num_tmp VALUES (4769999999999999999999999999999999999999999999999999 --Testcase 718: SELECT n1 * n2 FROM num_tmp; +--Testcase 1525: +DELETE FROM num_tmp; +--Testcase 1526: +INSERT INTO num_tmp VALUES ((0.1 - 2e-16383), (0.1 - 3e-16383)); +--Testcase 1527: +SELECT trim_scale(n1 * n2) FROM num_tmp; + -- -- Test some corner cases for division -- @@ -1863,34 +2755,55 @@ INSERT INTO num_tmp VALUES (117743296169.0, -1000000000); SELECT n1 ^ n2 as overflows FROM num_tmp; -- cases that used to return inaccurate results - --Testcase 776: DELETE FROM num_tmp; --Testcase 777: -INSERT INTO num_tmp VALUES (3.789, 21); +INSERT INTO num_tmp VALUES (3.789, 21.0000000000000000); --Testcase 778: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; + --Testcase 779: DELETE FROM num_tmp; --Testcase 780: -INSERT INTO num_tmp VALUES (3.789, 35); +INSERT INTO num_tmp VALUES (3.789, 35.0000000000000000); --Testcase 781: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; --Testcase 782: DELETE FROM num_tmp; --Testcase 783: INSERT INTO num_tmp VALUES (1.2, 345); --Testcase 784: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; --Testcase 785: DELETE FROM num_tmp; --Testcase 786: INSERT INTO num_tmp VALUES (0.12, (-20)); --Testcase 787: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1220: +DELETE FROM num_tmp; +--Testcase 1221: +INSERT INTO num_tmp VALUES (1.000000000123, (-2147483648)); +--Testcase 1222: +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1528: +DELETE FROM num_tmp; +--Testcase 1529: +INSERT INTO num_tmp VALUES (0.9999999999, 23300000000000); +--Testcase 1530: +SELECT coalesce(nullif(n1 ^ n2, 0), 0) FROM num_tmp; + +--Testcase 1575: +DELETE FROM num_tmp; +--Testcase 1576: +INSERT INTO num_tmp VALUES ((1 - 1.500012345678e-1000), 1.45e1003); +--Testcase 1577: +SELECT round(((1 - 1.500012345678e-1000) ^ 1.45e1003) * 1e1000) FROM num_tmp; -- cases that used to error out --Testcase 788: @@ -1898,14 +2811,62 @@ DELETE FROM num_tmp; --Testcase 789: INSERT INTO num_tmp VALUES (0.12, (-25)); --Testcase 790: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; --Testcase 791: DELETE FROM num_tmp; --Testcase 792: INSERT INTO num_tmp VALUES (0.5678, (-85)); --Testcase 793: -select n1 ^ n2 FROM num_tmp; +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1531: +DELETE FROM num_tmp; +--Testcase 1532: +INSERT INTO num_tmp VALUES (0.9999999999, 70000000000000); +--Testcase 1533: +SELECT coalesce(nullif(n1 ^ n2, 0), 0) FROM num_tmp; + +-- negative base to integer powers +--Testcase 1534: +DELETE FROM num_tmp; +--Testcase 1535: +INSERT INTO num_tmp VALUES ((-1.0), 2147483646); +--Testcase 1536: +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1537: +DELETE FROM num_tmp; +--Testcase 1538: +INSERT INTO num_tmp VALUES ((-1.0), 2147483647); +--Testcase 1539: +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1540: +DELETE FROM num_tmp; +--Testcase 1541: +INSERT INTO num_tmp VALUES ((-1.0), 2147483648); +--Testcase 1542: +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1543: +DELETE FROM num_tmp; +--Testcase 1544: +INSERT INTO num_tmp VALUES ((-1.0), 1000000000000000); +--Testcase 1545: +SELECT n1 ^ n2 FROM num_tmp; + +--Testcase 1546: +DELETE FROM num_tmp; +--Testcase 1547: +INSERT INTO num_tmp VALUES ((-1.0), 1000000000000001); +--Testcase 1548: +SELECT n1 ^ n2 FROM num_tmp; + +-- integer powers of 10 +DELETE FROM num_tmp; +INSERT INTO num_tmp(n1) SELECT n FROM generate_series(-20,20) n; +SELECT n1, 10.0 ^ n1 as "10^n", (10.0 ^ n1) * (10.0 ^ (-n1)) = 1 as ok FROM num_tmp; -- -- Tests for raising to non-integer powers @@ -2054,6 +3015,41 @@ INSERT INTO num_tmp VALUES (1.0::numeric(71,70)); --Testcase 850: select exp(n1) from num_tmp; +--Testcase 1223: +DELETE FROM num_tmp; +--Testcase 1224: +INSERT INTO num_tmp VALUES ('nan'::numeric); +--Testcase 1225: +select exp(n1) from num_tmp; + +--Testcase 1226: +DELETE FROM num_tmp; +--Testcase 1227: +INSERT INTO num_tmp VALUES ('inf'::numeric); +--Testcase 1228: +select exp(n1) from num_tmp; + +--Testcase 1229: +DELETE FROM num_tmp; +--Testcase 1230: +INSERT INTO num_tmp VALUES ('-inf'::numeric); +--Testcase 1231: +select exp(n1) from num_tmp; + +--Testcase 1549: +DELETE FROM num_tmp; +--Testcase 1550: +INSERT INTO num_tmp VALUES ('-5000'::numeric); +--Testcase 1551: +select coalesce(nullif(exp(n1), 0), 0) from num_tmp; + +--Testcase 1552: +DELETE FROM num_tmp; +--Testcase 1553: +INSERT INTO num_tmp VALUES ('-10000'::numeric); +--Testcase 1554: +select coalesce(nullif(exp(n1), 0), 0) from num_tmp; + -- cases that used to generate inaccurate results --Testcase 851: DELETE FROM num_tmp; @@ -2143,6 +3139,28 @@ DELETE FROM num_tmp; INSERT INTO num_tmp select * from generate_series(0::numeric, 'nan'::numeric, 10::numeric); --Testcase 886: SELECT n2 FROM num_tmp; + +--Testcase 1232: +DELETE FROM num_tmp; +--Testcase 1233: +INSERT INTO num_tmp select * from generate_series('inf'::numeric, 'inf'::numeric, 10::numeric); +--Testcase 1234: +SELECT n2 FROM num_tmp; + +--Testcase 1235: +DELETE FROM num_tmp; +--Testcase 1236: +INSERT INTO num_tmp select * from generate_series(0::numeric, 'inf'::numeric, 10::numeric); +--Testcase 1237: +SELECT n2 FROM num_tmp; + +--Testcase 1238: +DELETE FROM num_tmp; +--Testcase 1239: +INSERT INTO num_tmp select * from generate_series(0::numeric, '42'::numeric, '-inf'::numeric); +--Testcase 1240: +SELECT n2 FROM num_tmp; + -- Checks maximum, output is truncated --Testcase 887: DELETE FROM num_tmp; @@ -2400,6 +3418,13 @@ INSERT INTO num_tmp VALUES (numeric 'NaN'); --Testcase 985: select scale(n1) from num_tmp; +--Testcase 1241: +DELETE FROM num_tmp; +--Testcase 1242: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1243: +select scale(n1) from num_tmp; + --Testcase 986: DELETE FROM num_tmp; --Testcase 987: @@ -2466,6 +3491,13 @@ INSERT INTO num_tmp VALUES (numeric 'NaN'); --Testcase 1012: select min_scale(n1) is NULL from num_tmp; -- should be true +--Testcase 1244: +DELETE FROM num_tmp; +--Testcase 1245: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1246: +select min_scale(n1) is NULL from num_tmp; -- should be true + --Testcase 1013: DELETE FROM num_tmp; --Testcase 1014: @@ -2546,6 +3578,13 @@ INSERT INTO num_tmp VALUES (numeric 'NaN'); --Testcase 1045: select trim_scale(n1) from num_tmp; +--Testcase 1247: +DELETE FROM num_tmp; +--Testcase 1248: +INSERT INTO num_tmp VALUES (numeric 'inf'); +--Testcase 1249: +select trim_scale(n1) from num_tmp; + --Testcase 1046: DELETE FROM num_tmp; --Testcase 1047: @@ -2616,6 +3655,49 @@ SELECT SUM(9999::numeric) FROM num_tmp; --Testcase 1073: SELECT SUM((-9999)::numeric) FROM num_tmp; +-- +-- Tests for VARIANCE() +-- +--Testcase 1578: +INSERT INTO num_variance VALUES (0); +--Testcase 1579: +INSERT INTO num_variance VALUES (3e-500); +--Testcase 1580: +INSERT INTO num_variance VALUES (-3e-500); +--Testcase 1581: +INSERT INTO num_variance VALUES (4e-500 - 1e-16383); +--Testcase 1582: +INSERT INTO num_variance VALUES (-4e-500 + 1e-16383); +-- variance is just under 12.5e-1000 and so should round down to 12e-1000 +--Testcase 1583: +SELECT trim_scale(variance(a) * 1e1000) FROM num_variance; + +-- check that parallel execution produces the same result +BEGIN; +-- ALTER TABLE num_variance SET (parallel_workers = 4); +SET LOCAL parallel_setup_cost = 0; +SET LOCAL max_parallel_workers_per_gather = 4; +--Testcase 1584: +SELECT trim_scale(variance(a) * 1e1000) FROM num_variance; +ROLLBACK; + +-- case where sum of squares would overflow but variance does not +--Testcase 1585: +DELETE FROM num_variance; +--Testcase 1586: +INSERT INTO num_variance SELECT 9e131071 + x FROM generate_series(1, 5) x; +--Testcase 1587: +SELECT variance(a) FROM num_variance; + +-- check that parallel execution produces the same result +BEGIN; +-- ALTER TABLE num_variance SET (parallel_workers = 4); +SET LOCAL parallel_setup_cost = 0; +SET LOCAL max_parallel_workers_per_gather = 4; +--Testcase 1588: +SELECT variance(a) FROM num_variance; +ROLLBACK; + -- -- Tests for GCD() -- @@ -2628,7 +3710,11 @@ INSERT INTO num_tmp VALUES (0::numeric, 46375::numeric), (433125::numeric, 46375::numeric), (43312.5::numeric, 4637.5::numeric), - (4331.250::numeric, 463.75000::numeric); + (4331.250::numeric, 463.75000::numeric), + ('Infinity', '0'), + ('Infinity', '42'), + ('Infinity', 'Infinity'); + --Testcase 1076: SELECT n1 as a, n2 as b, gcd(n1, n2), gcd(n1, -n2), gcd(-n2, n1), gcd(-n2, -n1) FROM num_tmp; -- @@ -2644,7 +3730,10 @@ INSERT INTO num_tmp VALUES (13272::numeric, 13272::numeric), (423282::numeric, 13272::numeric), (42328.2::numeric, 1327.2::numeric), - (4232.820::numeric, 132.72000::numeric); + (4232.820::numeric, 132.72000::numeric), + ('Infinity', '0'), + ('Infinity', '42'), + ('Infinity', 'Infinity'); --Testcase 1079: SELECT n1 as a, n2 as b, lcm(n1, n2), lcm(n1, -n2), lcm(-n2, n1), lcm(-n2, -n1) FROM num_tmp; @@ -2655,6 +3744,88 @@ INSERT INTO num_tmp VALUES (10::numeric, 131068); --Testcase 1082: SELECT lcm(9999 * (n1)^n2 + (n1^n2 - 1), 2) FROM num_tmp; -- overflow +-- +-- Tests for factorial +-- +--Testcase 1250: +DELETE FROM num_tmp; +--Testcase 1251: +INSERT INTO num_tmp VALUES (4); +--Testcase 1252: +SELECT factorial(n1::int4) FROM num_tmp; + +--Testcase 1253: +DELETE FROM num_tmp; +--Testcase 1254: +INSERT INTO num_tmp VALUES (15); +--Testcase 1255: +SELECT factorial(n1::int4) FROM num_tmp; + +--Testcase 1256: +DELETE FROM num_tmp; +--Testcase 1257: +INSERT INTO num_tmp VALUES (100000); +--Testcase 1258: +SELECT factorial(n1::int4) FROM num_tmp; + +--Testcase 1259: +DELETE FROM num_tmp; +--Testcase 1260: +INSERT INTO num_tmp VALUES (0); +--Testcase 1261: +SELECT factorial(n1::int4) FROM num_tmp; + +--Testcase 1262: +DELETE FROM num_tmp; +--Testcase 1263: +INSERT INTO num_tmp VALUES (-4); +--Testcase 1264: +SELECT factorial(n1::int4) FROM num_tmp; + +-- +-- Tests for pg_lsn() +-- +--Testcase 1265: +DELETE FROM num_tmp; +--Testcase 1266: +INSERT INTO num_tmp VALUES (23783416::numeric); +--Testcase 1267: +SELECT pg_lsn(n1) FROM num_tmp; + +--Testcase 1268: +DELETE FROM num_tmp; +--Testcase 1269: +INSERT INTO num_tmp VALUES (0::numeric); +--Testcase 1270: +SELECT pg_lsn(n1) FROM num_tmp; + +--Testcase 1271: +DELETE FROM num_tmp; +--Testcase 1272: +INSERT INTO num_tmp VALUES (18446744073709551615::numeric); +--Testcase 1273: +SELECT pg_lsn(n1) FROM num_tmp; + +--Testcase 1274: +DELETE FROM num_tmp; +--Testcase 1275: +INSERT INTO num_tmp VALUES (-1::numeric); +--Testcase 1276: +SELECT pg_lsn(n1) FROM num_tmp; + +--Testcase 1277: +DELETE FROM num_tmp; +--Testcase 1278: +INSERT INTO num_tmp VALUES (18446744073709551616::numeric); +--Testcase 1279: +SELECT pg_lsn(n1) FROM num_tmp; + +--Testcase 1280: +DELETE FROM num_tmp; +--Testcase 1281: +INSERT INTO num_tmp VALUES ('NaN'::numeric); +--Testcase 1282: +SELECT pg_lsn(n1) FROM num_tmp; DO $d$ declare diff --git a/sql/16.0/extra/out_of_range.sql b/sql/17.0/extra/out_of_range.sql similarity index 100% rename from sql/16.0/extra/out_of_range.sql rename to sql/17.0/extra/out_of_range.sql diff --git a/sql/15.4/extra/prepare.sql b/sql/17.0/extra/prepare.sql similarity index 84% rename from sql/15.4/extra/prepare.sql rename to sql/17.0/extra/prepare.sql index 18acbad7..8dd54a30 100644 --- a/sql/15.4/extra/prepare.sql +++ b/sql/17.0/extra/prepare.sql @@ -39,7 +39,7 @@ create foreign table road_tmp (a int, b int, id int options (key 'true')) server insert into road_tmp values (1, 2); --Testcase 1: -SELECT name, statement, parameter_types FROM pg_prepared_statements; +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; --Testcase 2: PREPARE q1 AS SELECT a FROM road_tmp; @@ -47,7 +47,7 @@ PREPARE q1 AS SELECT a FROM road_tmp; EXECUTE q1; --Testcase 4: -SELECT name, statement, parameter_types FROM pg_prepared_statements; +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; -- should fail --Testcase 5: @@ -63,18 +63,18 @@ EXECUTE q1; --Testcase 8: PREPARE q2 AS SELECT b FROM road_tmp; --Testcase 9: -SELECT name, statement, parameter_types FROM pg_prepared_statements; +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; -- sql92 syntax DEALLOCATE PREPARE q1; --Testcase 10: -SELECT name, statement, parameter_types FROM pg_prepared_statements; +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; DEALLOCATE PREPARE q2; -- the view should return the empty set again --Testcase 11: -SELECT name, statement, parameter_types FROM pg_prepared_statements; +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements; -- parameterized queries --Testcase 12: @@ -133,8 +133,11 @@ PREPARE q6 AS PREPARE q7(unknown) AS SELECT * FROM road WHERE thepath = $1; +-- DML statements +PREPARE q8 AS + UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1; --Testcase 24: -SELECT name, statement, parameter_types FROM pg_prepared_statements +SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements ORDER BY name; -- test DEALLOCATE ALL; diff --git a/sql/13.12/extra/select.sql b/sql/17.0/extra/select.sql similarity index 94% rename from sql/13.12/extra/select.sql rename to sql/17.0/extra/select.sql index 12ee7b82..366a4c12 100644 --- a/sql/13.12/extra/select.sql +++ b/sql/17.0/extra/select.sql @@ -53,6 +53,17 @@ CREATE FOREIGN TABLE INT8_TBL( q2 int8 OPTIONS (key 'true') ) SERVER sqlite_svr; +--Testcase 73: +INSERT INTO INT8_TBL VALUES(' 123 ',' 456'); +--Testcase 74: +INSERT INTO INT8_TBL VALUES('123 ','4567890123456789'); +--Testcase 75: +INSERT INTO INT8_TBL VALUES('4567890123456789','123'); +--Testcase 76: +INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789'); +--Testcase 77: +INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789'); + --Testcase 48: CREATE FOREIGN TABLE person ( name text, @@ -159,11 +170,6 @@ RESET enable_bitmapscan; RESET enable_sort; ---Testcase 11: -SELECT two, stringu1, ten, string4 - INTO TABLE tmp - FROM onek; - -- -- awk '{print $1,$2;}' person.data | -- awk '{if(NF!=2){print $3,$2;}else{print;}}' - emp.data | @@ -227,6 +233,11 @@ SELECT 2+2, 57 UNION ALL TABLE int8_tbl; +-- corner case: VALUES with no columns +-- CREATE TEMP TABLE nocols(); +-- INSERT INTO nocols DEFAULT VALUES; +-- SELECT * FROM nocols n, LATERAL (VALUES(n.*)) v; + -- -- Test ORDER BY options -- @@ -380,6 +391,9 @@ explain (costs off) select * from list_parted_tbl; --Testcase 65: drop table list_parted_tbl; +--Testcase 78: +DELETE FROM INT8_TBL; + --Testcase 66: DROP FOREIGN TABLE onek; --Testcase 67: diff --git a/sql/16.0/extra/select_having.sql b/sql/17.0/extra/select_having.sql similarity index 100% rename from sql/16.0/extra/select_having.sql rename to sql/17.0/extra/select_having.sql diff --git a/sql/17.0/extra/sqlite_fdw_post.sql b/sql/17.0/extra/sqlite_fdw_post.sql new file mode 100644 index 00000000..eb05b080 --- /dev/null +++ b/sql/17.0/extra/sqlite_fdw_post.sql @@ -0,0 +1,5160 @@ +-- =================================================================== +-- create FDW objects +-- =================================================================== + +--Testcase 483: +CREATE EXTENSION sqlite_fdw; + +DO $d$ + BEGIN + EXECUTE $$CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + EXECUTE $$CREATE SERVER sqlite_svr2 FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + EXECUTE $$CREATE SERVER sqlite_svr3 FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; + +-- SQLite FDW does not need User and User Mapping. +--Testcase 484: +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +--Testcase 485: +-- CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +--Testcase 756: +-- CREATE USER MAPPING FOR public SERVER sqlite_svr3; +-- =================================================================== +-- create objects used through FDW sqlite server +-- =================================================================== +--Testcase 486: +CREATE SCHEMA "S 1"; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO "S 1"; + +--Testcase 1: +INSERT INTO "S 1"."T 1" + SELECT id, + id % 10, + to_char(id, 'FM00000'), + '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, + '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, + id % 10, + id % 10, + 'foo' + FROM generate_series(1, 1000) id; +--Testcase 2: +INSERT INTO "S 1"."T 2" + SELECT id, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 3: +INSERT INTO "S 1"."T 3" + SELECT id, + id + 1, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 487: +DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests +--Testcase 4: +INSERT INTO "S 1"."T 4" + SELECT id, + id + 1, + 'AAA' || to_char(id, 'FM000') + FROM generate_series(1, 100) id; +--Testcase 488: +DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests + +/*ANALYZE "S 1"."T 1"; +ANALYZE "S 1"."T 2"; +ANALYZE "S 1"."T 3"; +ANALYZE "S 1"."T 4";*/ + +-- =================================================================== +-- create foreign tables +-- =================================================================== +--Testcase 489: +CREATE FOREIGN TABLE ft1 ( + c0 int, + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_svr; +--Testcase 757: +ALTER FOREIGN TABLE ft1 DROP COLUMN c0; + +--Testcase 490: +CREATE FOREIGN TABLE ft2 ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + cx int, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft2', + c8 text +) SERVER sqlite_svr; +--Testcase 758: +ALTER FOREIGN TABLE ft2 DROP COLUMN cx; + +--Testcase 491: +CREATE FOREIGN TABLE ft4 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr OPTIONS (table 'T 3'); + +--Testcase 492: +CREATE FOREIGN TABLE ft5 ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr OPTIONS (table 'T 4'); + +--Testcase 493: +CREATE FOREIGN TABLE ft6 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr2 OPTIONS (table 'T 4'); + +--Testcase 759: +CREATE FOREIGN TABLE ft7 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 text +) SERVER sqlite_svr3 OPTIONS (table 'T 4'); + +--Testcase 760: +ALTER FOREIGN TABLE ft1 OPTIONS (table 'T 1'); +--Testcase 761: +ALTER FOREIGN TABLE ft2 OPTIONS (table 'T 1'); +--Testcase 762: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); +--Testcase 763: +ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); +--Testcase 5: +\det+ + +-- Test that alteration of server options causes reconnection +-- Remote's errors might be non-English, so hide them to ensure stable results +\set VERBOSITY terse +--Testcase 6: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work + +--Testcase 764: +ALTER SERVER sqlite_svr OPTIONS (SET database 'no such database'); +--Testcase 7: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail +DO $d$ + BEGIN + EXECUTE $$ALTER SERVER sqlite_svr + OPTIONS (SET database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; +--Testcase 8: +SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again +\set VERBOSITY default + +-- Now we should be able to run ANALYZE. +-- To exercise multiple code paths, we use local stats on ft1 +-- and remote-estimate mode on ft2. +--ANALYZE ft1; +--ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true'); + +-- =================================================================== +-- test error case for create publication on foreign table +-- =================================================================== +--Testcase 955: +CREATE PUBLICATION testpub_ftbl FOR TABLE ft1; -- should fail + +-- =================================================================== +-- simple queries +-- =================================================================== +-- single table without alias +--Testcase 9: +EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; +--Testcase 10: +SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; +-- single table with alias - also test that tableoid sort is not pushed to remote side +--Testcase 11: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; +--Testcase 12: +SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; +-- whole-row reference +--Testcase 13: +EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +--Testcase 14: +SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +-- empty result +--Testcase 15: +SELECT * FROM ft1 WHERE false; +-- with WHERE clause +--Testcase 16: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; +--Testcase 17: +SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; +-- with FOR UPDATE/SHARE +--Testcase 18: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; +--Testcase 19: +SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; +--Testcase 20: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; +--Testcase 21: +SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; +-- aggregate +--Testcase 22: +SELECT COUNT(*) FROM ft1 t1; +-- subquery +--Testcase 23: +SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1; +-- subquery+MAX +--Testcase 24: +SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1; +-- used in CTE +--Testcase 25: +WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1; +-- fixed values +--Testcase 26: +SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1; +-- Test forcing the remote server to produce sorted data for a merge join. +--Testcase 765: +SET enable_hashjoin TO false; +--Testcase 766: +SET enable_nestloop TO false; +-- inner join; expressions in the clauses appear in the equivalence class list +--Testcase 27: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; +--Testcase 28: +SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; +-- outer join; expressions in the clauses do not appear in equivalence class +-- list but no output change as compared to the previous query +--Testcase 29: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; +--Testcase 30: +SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; +-- A join between local table and foreign join. ORDER BY clause is added to the +-- foreign join so that the local table can be joined using merge join strategy. +--Testcase 31: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +--Testcase 32: +SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +-- Test similar to above, except that the full join prevents any equivalence +-- classes from being merged. This produces single relation equivalence classes +-- included in join restrictions. +--Testcase 33: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +--Testcase 34: +SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +-- Test similar to above with all full outer joins +--Testcase 35: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +--Testcase 36: +SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; +--Testcase 767: +RESET enable_hashjoin; +--Testcase 768: +RESET enable_nestloop; + +-- Test executing assertion in estimate_path_cost_size() that makes sure that +-- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is +-- a sensible value even when the rel has tuples=0 +-- CREATE TABLE loct_empty (c1 int NOT NULL, c2 text); +--Testcase 769: +CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text) + SERVER sqlite_svr OPTIONS (table 'loct_empty'); +--Testcase 770: +INSERT INTO "S 1".loct_empty + SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; +--Testcase 771: +DELETE FROM "S 1".loct_empty; +-- ANALYZE ft_empty; +--Testcase 772: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1; + +-- test restriction on non-system foreign tables. +SET restrict_nonsystem_relation_kind TO 'foreign-table'; +--Testcase 1029: +SELECT * from ft1 where c1 < 1; -- ERROR +--Testcase 1030: +INSERT INTO ft1 (c1) VALUES (1); -- ERROR +--Testcase 1031: +DELETE FROM ft1 WHERE c1 = 1; -- ERROR +TRUNCATE ft1; -- ERROR +RESET restrict_nonsystem_relation_kind; + +-- =================================================================== +-- WHERE with remotely-executable conditions +-- =================================================================== +--Testcase 37: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const +--Testcase 38: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr +--Testcase 39: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NULL; -- NullTest +--Testcase 40: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NOT NULL; -- NullTest +--Testcase 41: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr +--Testcase 42: + +--Testcase 956: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) +--Testcase 44: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr +--Testcase 45: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr +--Testcase 46: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef +--Testcase 47: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars +--Testcase 48: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote +-- parameterized remote path for foreign table +--Testcase 49: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; +--Testcase 50: +SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; + +-- check both safe and unsafe join conditions +--Testcase 51: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 a, ft2 b + WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); +--Testcase 52: +SELECT * FROM ft2 a, ft2 b +WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); +-- bug before 9.3.5 due to sloppy handling of remote-estimate parameters +--Testcase 53: +SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5)); +--Testcase 54: +SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5)); + +-- user-defined operator/function +--Testcase 494: +CREATE FUNCTION sqlite_fdw_abs(int) RETURNS int AS $$ +BEGIN +RETURN abs($1); +END +$$ LANGUAGE plpgsql IMMUTABLE; +--Testcase 495: +CREATE OPERATOR === ( + LEFTARG = int, + RIGHTARG = int, + PROCEDURE = int4eq, + COMMUTATOR = === +); + +-- built-in operators and functions can be shipped for remote execution +--Testcase 57: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); +--Testcase 58: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); +--Testcase 59: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; +--Testcase 60: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; + +-- by default, user-defined ones cannot +--Testcase 61: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); +--Testcase 62: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); +--Testcase 63: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; +--Testcase 64: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + +-- ORDER BY can be shipped, though +--Testcase 496: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; +--Testcase 497: +SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + +-- but let's put them in an extension ... +--Testcase 773: +ALTER EXTENSION sqlite_fdw ADD FUNCTION sqlite_fdw_abs(int); +--Testcase 774: +ALTER EXTENSION sqlite_fdw ADD OPERATOR === (int, int); +--ALTER SERVER sqlite_svr2 OPTIONS (ADD extensions 'sqlite_fdw'); + +-- ... now they can be shipped +--Testcase 498: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); +--Testcase 499: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); +--Testcase 500: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; +--Testcase 501: +SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; + +-- and both ORDER BY and LIMIT can be shipped +--Testcase 502: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; +--Testcase 503: +SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; + +-- Ensure we don't ship FETCH FIRST .. WITH TIES +--Testcase 1027: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES; +--Testcase 1028: +SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES; + +-- Test CASE pushdown +--Testcase 957: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1; +--Testcase 958: +SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1; + +-- Nested CASE +--Testcase 959: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1; + +--Testcase 960: +SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1; + +-- CASE arg WHEN +--Testcase 961: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + +-- CASE cannot be pushed down because of unshippable arg clause +--Testcase 962: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c1 > (CASE random()::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END); + +-- these are shippable +--Testcase 963: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END; +--Testcase 964: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; + +-- but this is not because of collation +--Testcase 965: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END; + +-- a regconfig constant referring to this text search configuration +-- is initially unshippable--Testcase 984: +CREATE TEXT SEARCH CONFIGURATION public.custom_search + (COPY = pg_catalog.english); +--Testcase 985: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; +--Testcase 986: +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + +-- but if it's in a shippable extension, it can be shipped +ALTER EXTENSION sqlite_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search; +-- however, that doesn't flush the shippability cache, so do a quick reconnect +\c - +--Testcase 995: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; +--Testcase 996: +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + +-- =================================================================== +-- ORDER BY queries +-- =================================================================== +-- we should not push order by clause with volatile expressions or unsafe +-- collations +--Testcase 1006: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 ORDER BY ft2.c1, random(); +--Testcase 1007: +EXPLAIN (VERBOSE, COSTS OFF) + SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C"; + +-- Ensure we don't push ORDER BY expressions which are Consts at the UNION +-- child level to the foreign server. +--Testcase 1008: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ( + SELECT 1 AS type,c1 FROM ft1 + UNION ALL + SELECT 2 AS type,c1 FROM ft2 +) a ORDER BY type,c1; + +--Testcase 1009: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ( + SELECT 1 AS type,c1 FROM ft1 + UNION ALL + SELECT 2 AS type,c1 FROM ft2 +) a ORDER BY type; + +-- =================================================================== +-- JOIN queries +-- =================================================================== +-- Analyze ft4 and ft5 so that we have better statistics. These tables do not +-- have use_remote_estimate set. +--ANALYZE ft4; +--ANALYZE ft5; + +-- join two tables +--Testcase 65: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +--Testcase 66: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +-- join three tables +--Testcase 67: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; +--Testcase 68: +SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; +-- left outer join +--Testcase 69: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +--Testcase 70: +SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +-- left outer join three tables +--Testcase 71: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 72: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +-- left outer join + placement of clauses. +-- clauses within the nullable side are not pulled up, but top level clause on +-- non-nullable side is pushed into non-nullable side +--Testcase 73: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; +--Testcase 74: +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; +-- clauses within the nullable side are not pulled up, but the top level clause +-- on nullable side is not pushed down into nullable side +--Testcase 75: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) + WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; +--Testcase 76: +SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) + WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; +-- right outer join +--Testcase 77: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; +--Testcase 78: +SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; +-- right outer join three tables +--Testcase 79: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 80: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +-- full outer join +--Testcase 81: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; +--Testcase 82: +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; +-- full outer join with restrictions on the joining relations +-- a. the joining relations are both base relations +--Testcase 83: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; +--Testcase 84: +SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; +--Testcase 85: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; +--Testcase 86: +SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; +-- b. one of the joining relations is a base relation and the other is a join +-- relation +--Testcase 87: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; +--Testcase 88: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; +-- c. test deparsing the remote query as nested subqueries +--Testcase 89: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; +--Testcase 90: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; +-- d. test deparsing rowmarked relations as subqueries +--Testcase 91: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; +--Testcase 92: +SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; +-- full outer join + inner join +--Testcase 93: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; +--Testcase 94: +SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; +-- full outer join three tables +--Testcase 95: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 96: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; +-- full outer join + right outer join +--Testcase 97: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 98: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +-- right outer join + full outer join +--Testcase 99: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 100: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; +-- full outer join + left outer join +--Testcase 101: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 102: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; +-- left outer join + full outer join +--Testcase 103: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 104: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; +--Testcase 775: +SET enable_memoize TO off; +-- right outer join + left outer join +--Testcase 105: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 106: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 776: +RESET enable_memoize; +-- left outer join + right outer join +--Testcase 107: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; +--Testcase 108: +SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; +-- full outer join + WHERE clause, only matched rows +--Testcase 109: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +--Testcase 110: +SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +-- full outer join + WHERE clause with shippable extensions set +--Testcase 504: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; +--ALTER SERVER sqlite_svr2 OPTIONS (DROP extensions); +-- full outer join + WHERE clause with shippable extensions not set +--Testcase 505: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; +--Testcase 777: +-- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +-- join two tables with FOR UPDATE clause +-- tests whole-row reference for row marks +--Testcase 111: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; +--Testcase 112: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; +--Testcase 113: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; +--Testcase 114: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; +-- join two tables with FOR SHARE clause +--Testcase 115: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; +--Testcase 116: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; +--Testcase 117: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; +--Testcase 118: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; +-- join in CTE +--Testcase 119: +EXPLAIN (VERBOSE, COSTS OFF) +WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; +--Testcase 120: +WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; +-- ctid with whole-row reference +--Testcase 121: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +-- SEMI JOIN +--Testcase 122: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; +--Testcase 123: +SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; +-- ANTI JOIN, not pushed down +--Testcase 124: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; +--Testcase 125: +SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; +-- CROSS JOIN can be pushed down +--Testcase 126: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +--Testcase 127: +SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +-- different server, not pushed down. No result expected. +--Testcase 128: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +--Testcase 129: +SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +-- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS +-- JOIN since c8 in both tables has same value. +--Testcase 130: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +--Testcase 131: +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; +-- unsafe conditions on one side (c8 has a UDT), not pushed down. +--Testcase 132: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +--Testcase 133: +SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +-- join where unsafe to pushdown condition in WHERE clause has a column not +-- in the SELECT clause. In this test unsafe clause needs to have column +-- references from both joining sides so that the clause is not pushed down +-- into one of the joining sides. +--Testcase 134: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +--Testcase 135: +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; +-- Aggregate after UNION, for testing setrefs +--Testcase 136: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; +--Testcase 137: +SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; +-- join with lateral reference +--Testcase 138: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; +--Testcase 139: +SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; +-- join with pseudoconstant quals +--Testcase 997: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; + +-- non-Var items in targetlist of the nullable rel of a join preventing +-- push-down in some cases +-- unable to push {ft1, ft2} +--Testcase 140: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; +--Testcase 141: +SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; + +-- ok to push {ft1, ft2} but not {ft1, ft2, ft4} +--Testcase 142: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; +--Testcase 143: +SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; + +-- join with nullable side with some columns with null values +--Testcase 144: +UPDATE ft5 SET c3 = null where c1 % 9 = 0; +--Testcase 145: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; +--Testcase 146: +SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; + +-- multi-way join involving multiple merge joins +-- (this case used to have EPQ-related planning problems) +--Testcase 506: +CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1)); +--Testcase 507: +INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; +ANALYZE local_tbl; +--Testcase 778: +SET enable_nestloop TO false; +--Testcase 779: +SET enable_hashjoin TO false; +--Testcase 147: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 + AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; +--Testcase 148: +SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 + AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 ORDER BY ft1.c1 FOR UPDATE; +--Testcase 780: +RESET enable_nestloop; +--Testcase 781: +RESET enable_hashjoin; + +-- test that add_paths_with_pathkeys_for_rel() arranges for the epq_path to +-- return columns needed by the parent ForeignScan node +-- This does not work as SQLite FDW does not support use_remote_estimate +--Testcase 987: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.*, COALESCE(ft1.c3 || ft2.c3, 'foobar') FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100)) ss ON (local_tbl.c1 = ss.c1) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl; + +-- ALTER SERVER loopback OPTIONS (DROP extensions); +-- ALTER SERVER loopback OPTIONS (ADD fdw_startup_cost '10000.0'); + +--Testcase 988: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100 AND (ft1.c1 - sqlite_fdw_abs(ft2.c2)) = 0)) ss ON (local_tbl.c3 = ss.c3) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl; +-- ALTER SERVER loopback OPTIONS (DROP fdw_startup_cost); +-- ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); + +--DROP TABLE local_tbl; +-- check join pushdown in situations where multiple userids are involved +-- Although SQLite FDW does not need User and User mapping to connect to +-- the database file, however, JOIN pushdown is decided by the core code. +-- If outer and inner relation are foreign tables (or joins) belonging to +-- the same server and assigned to the same user, join will be pushed down. +-- Otherwise, join cannot be pushed down. +-- In addition to an exact match of userid, we allow the case where one side +-- has zero userid (implying current user) and the other side has explicit +-- userid that happens to equal the current user; but in that case, pushdown of +-- the join is only valid for the current user. +--Testcase 508: +CREATE ROLE regress_view_owner SUPERUSER; +--Testcase 509: +-- CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; +GRANT SELECT ON ft4 TO regress_view_owner; +GRANT SELECT ON ft5 TO regress_view_owner; + +--Testcase 510: +CREATE VIEW v4 AS SELECT * FROM ft4; +--Testcase 511: +CREATE VIEW v5 AS SELECT * FROM ft5; +--Testcase 782: +ALTER VIEW v5 OWNER TO regress_view_owner; +--Testcase 149: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, different view owners +--Testcase 150: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +--Testcase 783: +ALTER VIEW v4 OWNER TO regress_view_owner; +--Testcase 151: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down + +--Testcase 152: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; + +--Testcase 153: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, view owner not current user +--Testcase 154: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +--Testcase 784: +ALTER VIEW v4 OWNER TO CURRENT_USER; +--Testcase 155: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down +--Testcase 156: +SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; +--Testcase 785: +ALTER VIEW v4 OWNER TO regress_view_owner; + +-- Comment out these test cases. +-- sqlite_fdw does not need to getUserMapping in planning phase, +-- so it is unable to check userid to use when querying the remote table is correctly propagated into foreign rels. +-- -- ==================================================================== +-- -- Check that userid to use when querying the remote table is correctly +-- -- propagated into foreign rels present in subqueries under an UNION ALL +-- -- ==================================================================== +-- CREATE ROLE regress_view_owner_another; +-- ALTER VIEW v4 OWNER TO regress_view_owner_another; +-- GRANT SELECT ON ft4 TO regress_view_owner_another; +-- ALTER FOREIGN TABLE ft4 OPTIONS (ADD use_remote_estimate 'true'); +-- -- The following should query the remote backing table of ft4 as user +-- -- regress_view_owner_another, the view owner, though it fails as expected +-- -- due to the lack of a user mapping for that user. +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4; +-- -- Likewise, but with the query under an UNION ALL +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4); +-- -- Should not get that error once a user mapping is created +-- CREATE USER MAPPING FOR regress_view_owner_another SERVER loopback OPTIONS (password_required 'false'); +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4; +-- EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4); +-- DROP USER MAPPING FOR regress_view_owner_another SERVER loopback; +-- DROP OWNED BY regress_view_owner_another; +-- DROP ROLE regress_view_owner_another; +-- ALTER FOREIGN TABLE ft4 OPTIONS (SET use_remote_estimate 'false'); + +-- cleanup +--Testcase 512: +DROP OWNED BY regress_view_owner; +--Testcase 513: +DROP ROLE regress_view_owner; + +-- =================================================================== +-- Aggregate and grouping queries +-- =================================================================== + +-- Simple aggregates +--Testcase 157: +explain (verbose, costs off) +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; +--Testcase 158: +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; + +--Testcase 514: +explain (verbose, costs off) +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; +--Testcase 515: +select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; + +-- Aggregate is not pushed down as aggregation contains random() +--Testcase 159: +explain (verbose, costs off) +select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1; + +-- Aggregate over join query +--Testcase 160: +explain (verbose, costs off) +select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; +--Testcase 161: +select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; + +-- Not pushed down due to local conditions present in underneath input rel +--Testcase 162: +explain (verbose, costs off) +select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1; + +-- GROUP BY clause having expressions +--Testcase 163: +explain (verbose, costs off) +select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; +--Testcase 164: +select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; + +-- Aggregates in subquery are pushed down. +set enable_incremental_sort = off; +--Testcase 165: +explain (verbose, costs off) +select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; +--Testcase 166: +select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; +reset enable_incremental_sort; + +-- Aggregate is still pushed down by taking unshippable expression out +--Testcase 167: +explain (verbose, costs off) +select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; +--Testcase 168: +select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; + +-- Aggregate with unshippable GROUP BY clause are not pushed +--Testcase 169: +explain (verbose, costs off) +select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1; + +-- GROUP BY clause in various forms, cardinal, alias and constant expression +--Testcase 516: +explain (verbose, costs off) +select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; +--Testcase 517: +select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; + +-- GROUP BY clause referring to same column multiple times +-- Also, ORDER BY contains an aggregate function +--Testcase 170: + +--Testcase 966: +explain (verbose, costs off) +select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); +--Testcase 171: +select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); + +-- Testing HAVING clause shippability +--Testcase 172: +explain (verbose, costs off) +select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; +--Testcase 173: +select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; + +-- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down +--Testcase 174: +explain (verbose, costs off) +select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; +--Testcase 175: +select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; + +-- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down +--Testcase 176: +explain (verbose, costs off) +select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1; + +-- Remote aggregate in combination with a local Param (for the output +-- of an initplan) can be trouble, per bug #15781 +--Testcase 518: +explain (verbose, costs off) +select exists(select 1 from pg_enum), sum(c1) from ft1; +--Testcase 519: +select exists(select 1 from pg_enum), sum(c1) from ft1; + +--Testcase 520: +explain (verbose, costs off) +select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; +--Testcase 521: +select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; + + +-- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates + +-- ORDER BY within aggregate, same column used to order +--Testcase 177: +explain (verbose, costs off) +select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; +--Testcase 178: +select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; + +-- ORDER BY within aggregate, different column used to order also using DESC +--Testcase 179: +explain (verbose, costs off) +select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; +--Testcase 180: +select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; +-- DISTINCT within aggregate +--Testcase 181: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; +--Testcase 182: +select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + +-- DISTINCT combined with ORDER BY within aggregate +--Testcase 183: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; +--Testcase 184: +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + +--Testcase 185: +explain (verbose, costs off) +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; +--Testcase 186: +select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; + +-- FILTER within aggregate +--Testcase 187: +explain (verbose, costs off) +select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; +--Testcase 188: +select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; + +-- DISTINCT, ORDER BY and FILTER within aggregate +--Testcase 189: +explain (verbose, costs off) +select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; +--Testcase 190: +select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; + +-- Outer query is aggregation query +--Testcase 191: +explain (verbose, costs off) +select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; +--Testcase 192: +select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; +-- Inner query is aggregation query +--Testcase 193: +explain (verbose, costs off) +select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; +--Testcase 194: +select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; + +-- Aggregate not pushed down as FILTER condition is not pushable +--Testcase 195: +explain (verbose, costs off) +select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1; +--Testcase 196: +explain (verbose, costs off) +select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; + +-- Ordered-sets within aggregate +--Testcase 197: +explain (verbose, costs off) +select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; +--Testcase 198: +select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; + +-- Using multiple arguments within aggregates +--Testcase 199: +explain (verbose, costs off) +select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; +--Testcase 200: +select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; + +-- User defined function for user defined aggregate, VARIADIC +--Testcase 522: +create function least_accum(anyelement, variadic anyarray) +returns anyelement language sql as + 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; +--Testcase 523: +create aggregate least_agg(variadic items anyarray) ( + stype = anyelement, sfunc = least_accum +); + +-- Disable hash aggregation for plan stability. +--Testcase 786: +set enable_hashagg to false; + +-- Not pushed down due to user defined aggregate +--Testcase 524: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 group by c2 order by c2; + +-- Add function and aggregate into extension +--alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray); +--alter extension postgres_fdw add aggregate least_agg(variadic items anyarray); +--alter server loopback options (set extensions 'postgres_fdw'); + +-- Now aggregate will be pushed. Aggregate will display VARIADIC argument. +--Testcase 525: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; +--Testcase 526: +select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; + +-- Remove function and aggregate from extension +--alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray); +--alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray); +--alter server loopback options (set extensions 'postgres_fdw'); + +-- Not pushed down as we have dropped objects from extension. +--Testcase 527: +explain (verbose, costs off) +select c2, least_agg(c1) from ft1 group by c2 order by c2; + +-- Cleanup +--Testcase 787: +reset enable_hashagg; +--Testcase 528: +drop aggregate least_agg(variadic items anyarray); +--Testcase 529: +drop function least_accum(anyelement, variadic anyarray); + + +-- Testing USING OPERATOR() in ORDER BY within aggregate. +-- For this, we need user defined operators along with operator family and +-- operator class. Create those and then add them in extension. Note that +-- user defined objects are considered unshippable unless they are part of +-- the extension. +--Testcase 530: +create operator public.<^ ( + leftarg = int4, + rightarg = int4, + procedure = int4eq +); + +--Testcase 531: +create operator public.=^ ( + leftarg = int4, + rightarg = int4, + procedure = int4lt +); + +--Testcase 532: +create operator public.>^ ( + leftarg = int4, + rightarg = int4, + procedure = int4gt +); + +--Testcase 533: +create operator family my_op_family using btree; + +--Testcase 534: +create function my_op_cmp(a int, b int) returns int as + $$begin return btint4cmp(a, b); end $$ language plpgsql; + +--Testcase 535: +create operator class my_op_class for type int using btree family my_op_family as + operator 1 public.<^, + operator 3 public.=^, + operator 5 public.>^, + function 1 my_op_cmp(int, int); + +-- This will not be pushed as user defined sort operator is not part of the +-- extension yet. +--Testcase 536: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + +-- This should not be pushed either. +--Testcase 967: +explain (verbose, costs off) +select * from ft2 order by c1 using operator(public.<^); + +-- Update local stats on ft2 +--ANALYZE ft2; + +-- Add into extension +--Testcase 788: +alter extension sqlite_fdw add operator class my_op_class using btree; +--Testcase 789: +alter extension sqlite_fdw add function my_op_cmp(a int, b int); +--Testcase 790: +alter extension sqlite_fdw add operator family my_op_family using btree; +--Testcase 791: +alter extension sqlite_fdw add operator public.<^(int, int); +--Testcase 792: +alter extension sqlite_fdw add operator public.=^(int, int); +--Testcase 793: +alter extension sqlite_fdw add operator public.>^(int, int); +--alter server loopback options (set extensions 'postgres_fdw'); +--alter server loopback options (add fdw_tuple_cost '0.5'); +-- Now this will be pushed as sort operator is part of the extension. +--Testcase 537: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; +--Testcase 538: +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; +--alter server loopback options (drop fdw_tuple_cost); +-- This should be pushed too. +-- Sqlite not support pushdown user defined operators +--Testcase 968: +explain (verbose, costs off) +select * from ft2 order by c1 using operator(public.<^); + +-- Remove from extension +--Testcase 794: +alter extension sqlite_fdw drop operator class my_op_class using btree; +--Testcase 795: +alter extension sqlite_fdw drop function my_op_cmp(a int, b int); +--Testcase 796: +alter extension sqlite_fdw drop operator family my_op_family using btree; +--Testcase 797: +alter extension sqlite_fdw drop operator public.<^(int, int); +--Testcase 798: +alter extension sqlite_fdw drop operator public.=^(int, int); +--Testcase 799: +alter extension sqlite_fdw drop operator public.>^(int, int); +--alter server loopback options (set extensions 'postgres_fdw'); + +-- This will not be pushed as sort operator is now removed from the extension. +--Testcase 539: +explain (verbose, costs off) +select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; + +-- Cleanup +--Testcase 540: +drop operator class my_op_class using btree; +--Testcase 541: +drop function my_op_cmp(a int, b int); +--Testcase 542: +drop operator family my_op_family using btree; +--Testcase 543: +drop operator public.>^(int, int); +--Testcase 544: +drop operator public.=^(int, int); +--Testcase 545: +drop operator public.<^(int, int); + +-- Input relation to aggregate push down hook is not safe to pushdown and thus +-- the aggregate cannot be pushed down to foreign server. +--Testcase 201: +explain (verbose, costs off) +select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2); + +-- Subquery in FROM clause having aggregate +--Testcase 202: +explain (verbose, costs off) +select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; +--Testcase 203: +select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; + +-- FULL join with IS NULL check in HAVING +--Testcase 204: +explain (verbose, costs off) +select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; +--Testcase 205: +select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; + +-- Aggregate over FULL join needing to deparse the joining relations as +-- subqueries. +--Testcase 206: +explain (verbose, costs off) +select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); +--Testcase 207: +select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); + +-- ORDER BY expression is part of the target list but not pushed down to +-- foreign server. +--Testcase 208: +explain (verbose, costs off) +select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; +--Testcase 209: +select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; + +-- LATERAL join, with parameterization +--Testcase 800: +set enable_hashagg to false; +--Testcase 210: +explain (verbose, costs off) +select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; +--Testcase 211: +select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; +--Testcase 801: +reset enable_hashagg; + +-- bug #15613: bad plan for foreign table scan with lateral reference +--Testcase 546: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ref_0.c2, subq_1.* +FROM + "S 1"."T 1" AS ref_0, + LATERAL ( + SELECT ref_0."C 1" c1, subq_0.* + FROM (SELECT ref_0.c2, ref_1.c3 + FROM ft1 AS ref_1) AS subq_0 + RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) + ) AS subq_1 +WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' +ORDER BY ref_0."C 1"; + +--Testcase 547: +SELECT ref_0.c2, subq_1.* +FROM + "S 1"."T 1" AS ref_0, + LATERAL ( + SELECT ref_0."C 1" c1, subq_0.* + FROM (SELECT ref_0.c2, ref_1.c3 + FROM ft1 AS ref_1) AS subq_0 + RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) + ) AS subq_1 +WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' +ORDER BY ref_0."C 1"; + +-- Check with placeHolderVars +--Testcase 212: +explain (verbose, costs off) +select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); +--Testcase 213: +select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); + + +-- Not supported cases +-- Grouping sets +--Testcase 214: +explain (verbose, costs off) +select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; +--Testcase 215: +select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; +--Testcase 216: +explain (verbose, costs off) +select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; +--Testcase 217: +select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; +--Testcase 218: +explain (verbose, costs off) +select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; +--Testcase 219: +select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; +--Testcase 220: +explain (verbose, costs off) +select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; +--Testcase 221: +select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; + +-- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed +--Testcase 222: +explain (verbose, costs off) +select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; +--Testcase 223: +select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; + +-- WindowAgg +--Testcase 224: +explain (verbose, costs off) +select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; +--Testcase 225: +select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; +--Testcase 226: +explain (verbose, costs off) +select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; +--Testcase 227: +select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; +--Testcase 228: +explain (verbose, costs off) +select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; +--Testcase 229: +select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; + + +-- =================================================================== +-- parameterized queries +-- =================================================================== +-- simple join +--Testcase 230: +PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2; +--Testcase 231: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2); +--Testcase 232: +EXECUTE st1(1, 1); +--Testcase 233: +EXECUTE st1(101, 101); +SET enable_hashjoin TO off; +SET enable_sort TO off; +-- subquery using stable function (can't be sent to remote) +--Testcase 234: +PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1; +--Testcase 235: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20); +--Testcase 236: +EXECUTE st2(10, 20); +--Testcase 237: +EXECUTE st2(101, 121); +RESET enable_hashjoin; +RESET enable_sort; +-- subquery using immutable function (can be sent to remote) +--Testcase 238: +PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1; +--Testcase 239: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20); +--Testcase 240: +EXECUTE st3(10, 20); +--Testcase 241: +EXECUTE st3(20, 30); +-- custom plan should be chosen initially +--Testcase 242: +PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1; +--Testcase 243: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +--Testcase 244: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +--Testcase 245: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +--Testcase 246: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +--Testcase 247: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +-- once we try it enough times, should switch to generic plan +--Testcase 248: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); +-- value of $1 should not be sent to remote +--Testcase 249: +PREPARE st5(text,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2; +--Testcase 250: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 251: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 252: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 253: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 254: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 255: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); +--Testcase 256: +EXECUTE st5('foo', 1); + +-- altering FDW options requires replanning +--Testcase 257: +PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2; +--Testcase 258: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; +--Testcase 259: +PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); +--Testcase 260: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; +--Testcase 548: +INSERT INTO "S 1"."T 0" SELECT * FROM "S 1"."T 1"; +--Testcase 802: +ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 0'); +--Testcase 261: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; +--Testcase 262: +EXECUTE st6; +--Testcase 263: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; +--Testcase 803: +ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 1'); + +--Testcase 549: +PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; +--Testcase 550: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; +--ALTER SERVER loopback OPTIONS (DROP extensions); +--Testcase 551: +EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; +--Testcase 552: +EXECUTE st8; +--ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); +-- cleanup +DEALLOCATE st1; +DEALLOCATE st2; +DEALLOCATE st3; +DEALLOCATE st4; +DEALLOCATE st5; +DEALLOCATE st6; +DEALLOCATE st7; +DEALLOCATE st8; + +-- System columns, except ctid and oid, should not be sent to remote +--Testcase 264: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1; +--Testcase 265: +SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1; +--Testcase 266: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; +--Testcase 267: +SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; +--Testcase 268: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; +--Testcase 553: +SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; +--Testcase 554: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT ctid, * FROM ft1 t1 LIMIT 1; +--Testcase 271: +SELECT ctid, * FROM ft1 t1 LIMIT 1; + +-- =================================================================== +-- used in PL/pgSQL function +-- =================================================================== +--Testcase 555: +CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$ +DECLARE + v_c1 int; +BEGIN +--Testcase 556: + SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1; + PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1; + RETURN v_c1; +END; +$$ LANGUAGE plpgsql; +--Testcase 272: +SELECT f_test(100); +--Testcase 557: +DROP FUNCTION f_test(int); + +-- =================================================================== +-- REINDEX +-- =================================================================== +-- remote table is not created here +--Testcase 804: +CREATE FOREIGN TABLE reindex_foreign (c1 int, c2 int) + SERVER sqlite_svr2 OPTIONS (table 'reindex_local'); +REINDEX TABLE reindex_foreign; -- error +REINDEX TABLE CONCURRENTLY reindex_foreign; -- error +--Testcase 805: +DROP FOREIGN TABLE reindex_foreign; +-- partitions and foreign tables +--Testcase 806: +CREATE TABLE reind_fdw_parent (c1 int) PARTITION BY RANGE (c1); +--Testcase 807: +CREATE TABLE reind_fdw_0_10 PARTITION OF reind_fdw_parent + FOR VALUES FROM (0) TO (10); +--Testcase 808: +CREATE FOREIGN TABLE reind_fdw_10_20 PARTITION OF reind_fdw_parent + FOR VALUES FROM (10) TO (20) + SERVER sqlite_svr OPTIONS (table 'reind_local_10_20'); +REINDEX TABLE reind_fdw_parent; -- ok +REINDEX TABLE CONCURRENTLY reind_fdw_parent; -- ok +--Testcase 809: +DROP TABLE reind_fdw_parent; + +-- =================================================================== +-- conversion error +-- =================================================================== +--Testcase 810: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int; +--Testcase 273: +SELECT * FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8) WHERE x1 = 1; +--Testcase 274: +SELECT ftx.x1, ft2.c2, ftx.x8 FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; +--Testcase 275: +SELECT ftx.x1, ft2.c2, ftx FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; +--Testcase 276: +SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; +-- ANALYZE ft1; -- ERROR + +-- =================================================================== +-- local type can be different from remote type in some cases, +-- in particular if similarly-named operators do equivalent things +-- =================================================================== +--Testcase 811: +ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text; +--Testcase 969: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1; +--Testcase 970: +SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1; +--Testcase 971: +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1; +--Testcase 972: +SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1; +-- we declared c8 to be text locally, but it's still the same type on +-- the remote which will balk if we try to do anything incompatible +-- with that remote type +-- Can not create user define type in SqliteDB. +-- Type c8 of foreign table ft1 and remote table T1 are +-- match. These case below not error with sqlite_fdw. +-- with that remote type +--Testcase 973: +SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR +--Testcase 974: +SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down + +-- =================================================================== +-- subtransaction +-- + local/remote error doesn't break cursor +-- =================================================================== +BEGIN; +DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1; +--Testcase 277: +FETCH c; +SAVEPOINT s; +ERROR OUT; -- ERROR +ROLLBACK TO s; +--Testcase 278: +FETCH c; +SAVEPOINT s; +--Testcase 279: +SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR +ROLLBACK TO s; +--Testcase 280: +FETCH c; +--Testcase 281: +SELECT * FROM ft1 ORDER BY c1 LIMIT 1; +COMMIT; + +-- =================================================================== +-- test handling of collations +-- =================================================================== +--Testcase 558: +create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10)) server sqlite_svr; + +-- can be sent to remote +--Testcase 559: +explain (verbose, costs off) select * from ft3 where f1 = 'foo'; +--Testcase 560: +explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo'; +--Testcase 561: +explain (verbose, costs off) select * from ft3 where f2 = 'foo'; +--Testcase 562: +explain (verbose, costs off) select * from ft3 where f3 = 'foo'; +--Testcase 563: +explain (verbose, costs off) select * from ft3 f, loct3 l + where f.f3 = l.f3 and l.f1 = 'foo'; +-- can't be sent to remote +--Testcase 564: +explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo'; +--Testcase 565: +explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C"; +--Testcase 566: +explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo'; +--Testcase 567: +explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C"; +--Testcase 568: +explain (verbose, costs off) select * from ft3 f, loct3 l + where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo'; + +-- =================================================================== +-- test SEMI-JOIN pushdown +-- =================================================================== +--Testcase 1012: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1) + ORDER BY ft2.c1; +--Testcase 1013: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1) + ORDER BY ft2.c1; + +-- The same query, different join order +--Testcase 1014: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1; +--Testcase 1015: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1; + +-- Left join +--Testcase 1016: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; +--Testcase 1017: +SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + +-- Several semi-joins per upper level join +--Testcase 1018: +EXPLAIN (verbose, costs off) +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN (SELECT * FROM ft5 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5 + ON ft2.c2 <= ft5.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; +--Testcase 1019: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE + EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN (SELECT * FROM ft5 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5 + ON ft2.c2 <= ft5.c1 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + +-- Semi-join below Semi-join +--Testcase 1020: +EXPLAIN (verbose, costs off) +SELECT ft2.* FROM ft2 WHERE + c1 = ANY ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2)) + AND ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; +--Testcase 1021: +SELECT ft2.* FROM ft2 WHERE + c1 = ANY ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2)) + AND ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + +-- Upper level relations shouldn't refer EXISTS() subqueries +--Testcase 1022: +EXPLAIN (verbose, costs off) +SELECT * FROM ft2 ftupper WHERE + EXISTS ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 ) + AND ftupper.c1 > 900 + ORDER BY ftupper.c1 LIMIT 10; +--Testcase 1023: +SELECT * FROM ft2 ftupper WHERE + EXISTS ( + SELECT c1 FROM ft2 WHERE + EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 ) + AND ftupper.c1 > 900 + ORDER BY ftupper.c1 LIMIT 10; + +-- EXISTS should be propagated to the highest upper inner join +--Testcase 1024: +EXPLAIN (verbose, costs off) + SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE EXISTS ( + SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN + (SELECT * FROM ft2 WHERE EXISTS ( + SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21 + ON ft2.c2 = ft21.c2 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; +--Testcase 1025: +SELECT ft2.*, ft4.* FROM ft2 INNER JOIN + (SELECT * FROM ft4 WHERE EXISTS ( + SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4 + ON ft2.c2 = ft4.c1 + INNER JOIN + (SELECT * FROM ft2 WHERE EXISTS ( + SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21 + ON ft2.c2 = ft21.c2 + WHERE ft2.c1 > 900 + ORDER BY ft2.c1 LIMIT 10; + +-- Can't push down semi-join with inner rel vars in targetlist +--Testcase 1026: +EXPLAIN (verbose, costs off) +SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE + ft1.c1 IN ( + SELECT ft2.c1 FROM ft2 JOIN ft4 ON ft2.c1 = ft4.c1) + ORDER BY ft1.c1 LIMIT 5; + +-- =================================================================== +-- test writable foreign table stuff +-- =================================================================== +--Testcase 282: +EXPLAIN (verbose, costs off) +INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; +--Testcase 283: +INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; +--Testcase 284: +INSERT INTO ft2 (c1,c2,c3) VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc'); +--Testcase 285: +SELECT * FROM ft2 WHERE c1 >= 1101; +--Testcase 286: +INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); +--Testcase 287: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down +--Testcase 288: +UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; +--Testcase 289: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; -- can be pushed down +--Testcase 290: +UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; +--Testcase 291: +SELECT * FROM ft2 WHERE c1 % 10 = 7; +--Testcase 292: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT + FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down +--Testcase 293: +UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT + FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; +--Testcase 294: +EXPLAIN (verbose, costs off) + DELETE FROM ft2 WHERE c1 % 10 = 5; -- can be pushed down +--Testcase 295: +SELECT c1, c4 FROM ft2 WHERE c1 % 10 = 5; +--Testcase 569: +DELETE FROM ft2 WHERE c1 % 10 = 5; +--Testcase 297: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down +--Testcase 298: +DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; +--Testcase 299: +SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; +--Testcase 300: +EXPLAIN (verbose, costs off) +INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); +--Testcase 301: +INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); +--Testcase 302: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; -- can be pushed down +--Testcase 303: +UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; +--Testcase 304: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 WHERE c1 = 1200; -- can be pushed down +--Testcase 305: +DELETE FROM ft2 WHERE c1 = 1200; + +-- Test UPDATE/DELETE on a three-table join +--Testcase 306: +INSERT INTO ft2 (c1,c2,c3) + SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id; +--Testcase 307: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'foo' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; -- can be pushed down +--Testcase 308: +UPDATE ft2 SET c3 = 'foo' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; +--Testcase 309: +SELECT ft2, ft2.*, ft4, ft4.* + FROM ft2 INNER JOIN ft4 ON (ft2.c1 > 1200 AND ft2.c2 = ft4.c1) + INNER JOIN ft5 ON (ft4.c1 = ft5.c1); +--Testcase 310: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 + USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; -- can be pushed down +--Testcase 311: +SELECT 100 FROM ft2, ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; + +--Testcase 570: +DELETE FROM ft2 + USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; +--Testcase 312: +DELETE FROM ft2 WHERE ft2.c1 > 1200; + +-- Test UPDATE with a MULTIEXPR sub-select +-- (maybe someday this'll be remotely executable, but not today) +--Testcase 571: +EXPLAIN (verbose, costs off) +UPDATE ft2 AS target SET (c2, c7) = ( + SELECT c2 * 10, c7 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; +--Testcase 572: +UPDATE ft2 AS target SET (c2, c7) = ( + SELECT c2 * 10, c7 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; + +--Testcase 573: +UPDATE ft2 AS target SET (c2) = ( + SELECT c2 / 10 + FROM ft2 AS src + WHERE target.c1 = src.c1 +) WHERE c1 > 1100; + +-- Test UPDATE involving a join that can be pushed down, +-- but a SET clause that can't be +--Testcase 812: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END + FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; +--Testcase 813: +UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END + FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; + +-- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing +-- user-defined operators/functions +--ALTER SERVER loopback OPTIONS (DROP extensions); +--Testcase 574: +INSERT INTO ft2 (c1,c2,c3) + SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id; +--Testcase 575: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; -- can't be pushed down +--Testcase 576: +UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; +--Testcase 577: +SELECT * FROM ft2 WHERE sqlite_fdw_abs(c1) > 2000; +--Testcase 578: +EXPLAIN (verbose, costs off) +UPDATE ft2 SET c3 = 'baz' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; -- can't be pushed down +--Testcase 579: +UPDATE ft2 SET c3 = 'baz' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; +--Testcase 580: +SELECT ft2.*, ft4.*, ft5.* + FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; + +--Testcase 581: +EXPLAIN (verbose, costs off) +DELETE FROM ft2 + USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down + +--Testcase 582: +SELECT ft2.c1, ft2.c2, ft2.c3 FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down + +--Testcase 583: +DELETE FROM ft2 + USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) + WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; + +--Testcase 584: +DELETE FROM ft2 WHERE ft2.c1 > 2000; +--ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); + +-- Test that trigger on remote table works as expected +--Testcase 585: +CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$ +BEGIN + NEW.c3 = NEW.c3 || '_trig_update'; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +--Testcase 586: +CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE + ON ft2 FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG(); + +--Testcase 313: +INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff'); +--Testcase 314: +SELECT * FROM ft2 WHERE c1 = 1208; +--Testcase 315: +INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;'); +--Testcase 316: +SELECT * FROM ft2 WHERE c1 = 1218; +--Testcase 317: +UPDATE ft2 SET c2 = c2 + 600, c3 = c3 WHERE c1 % 10 = 8 AND c1 < 1200; +--Testcase 318: +SELECT * FROM ft2 WHERE c1 % 10 = 8 AND c1 < 1200; + +-- Test errors thrown on remote side during update +-- create table in the remote server with check contraint +--Testcase 738: +CREATE FOREIGN TABLE ft1_constraint ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_svr OPTIONS (table 't1_constraint'); +--Testcase 747: +INSERT INTO ft1_constraint SELECT * FROM ft1 ON CONFLICT DO NOTHING; +-- c2 must be greater than or equal to 0, so this case is ignored. +--Testcase 754: +INSERT INTO ft1_constraint(c1, c2) VALUES (2222, -2) ON CONFLICT DO NOTHING; -- ignore, do nothing +--Testcase 755: +SELECT c1, c2 FROM ft1_constraint WHERE c1 = 2222 or c2 = -2; -- empty result +--Testcase 748: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; +--Testcase 749: +ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; +--Testcase 319: +INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key +--Testcase 320: +INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported +--Testcase 321: +INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported +--Testcase 743: +INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive +--Testcase 744: +UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive +--Testcase 750: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_constraint; +--Testcase 751: +ALTER FOREIGN TABLE ft1_org RENAME TO ft1; + +-- Test savepoint/rollback behavior +--Testcase 322: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +--Testcase 323: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; +begin; +--Testcase 324: +update ft2 set c2 = 42 where c2 = 0; +--Testcase 325: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +savepoint s1; +--Testcase 326: +update ft2 set c2 = 44 where c2 = 4; +--Testcase 327: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +release savepoint s1; +--Testcase 328: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +savepoint s2; +--Testcase 329: +update ft2 set c2 = 46 where c2 = 6; +--Testcase 330: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +rollback to savepoint s2; +--Testcase 331: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +release savepoint s2; +--Testcase 332: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +savepoint s3; +--Testcase 333: +--skip, does not support CHECK +--update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side +rollback to savepoint s3; +--Testcase 334: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +release savepoint s3; +--Testcase 335: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +-- none of the above is committed yet remotely +--Testcase 336: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; +commit; +--Testcase 337: +select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; +--Testcase 338: +select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; + +--VACUUM ANALYZE "S 1"."T 1"; + +-- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs +-- FIRST behavior here. +-- ORDER BY DESC NULLS LAST options +--Testcase 339: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; +--Testcase 340: +SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; +-- ORDER BY DESC NULLS FIRST options +--Testcase 341: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; +--Testcase 342: +SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; +-- ORDER BY ASC NULLS FIRST options +--Testcase 343: +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; +--Testcase 344: +SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; + +-- Test ReScan code path that recreates the cursor even when no parameters +-- change (bug #17889) +--Testcase 1032: +CREATE FOREIGN TABLE loct1_rescan (c1 int OPTIONS (key 'true')) SERVER sqlite_svr OPTIONS (table 'loct1_rescan'); +--Testcase 1033: +CREATE FOREIGN TABLE loct2_rescan (c1 int OPTIONS (key 'true'), c2 text) SERVER sqlite_svr OPTIONS (table 'loct2_rescan'); +--Testcase 1034: +INSERT INTO loct1_rescan VALUES (1001); +--Testcase 1035: +INSERT INTO loct1_rescan VALUES (1002); +--Testcase 1036: +INSERT INTO loct2_rescan SELECT id, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; +--Testcase 1037: +INSERT INTO loct2_rescan VALUES (1001, 'foo'); +--Testcase 1038: +INSERT INTO loct2_rescan VALUES (1002, 'bar'); +--Testcase 1039: +CREATE FOREIGN TABLE remt2_rescan (c1 int OPTIONS (key 'true'), c2 text) SERVER sqlite_svr OPTIONS (table 'loct2_rescan'); +-- ANALYZE loct1_rescan; +-- ANALYZE remt2_rescan; +SET enable_mergejoin TO false; +SET enable_hashjoin TO false; +SET enable_material TO false; +--Testcase 1040: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE remt2_rescan SET c2 = remt2_rescan.c2 || remt2_rescan.c2 FROM loct1_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; +--Testcase 1041: +UPDATE remt2_rescan SET c2 = remt2_rescan.c2 || remt2_rescan.c2 FROM loct1_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; +--Testcase 1042: +SELECT remt2_rescan.* FROM loct1_rescan, remt2_rescan WHERE loct1_rescan.c1 = remt2_rescan.c1; +RESET enable_mergejoin; +RESET enable_hashjoin; +RESET enable_material; +--Testcase 1043: +DROP FOREIGN TABLE loct1_rescan; +--Testcase 1044: +DROP FOREIGN TABLE loct2_rescan; +--Testcase 1045: +DROP FOREIGN TABLE remt2_rescan; + +-- =================================================================== +-- test check constraints +-- =================================================================== +--Testcase 752: +ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; +--Testcase 753: +ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; +-- Consistent check constraints provide consistent results +--Testcase 814: +ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0); +--Testcase 587: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; +--Testcase 588: +SELECT count(*) FROM ft1 WHERE c2 < 0; +--Testcase 815: +SET constraint_exclusion = 'on'; +--Testcase 589: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; +--Testcase 590: +SELECT count(*) FROM ft1 WHERE c2 < 0; +--Testcase 816: +RESET constraint_exclusion; +-- check constraint is enforced on the remote side, not locally +--Testcase 745: +INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive +--Testcase 746: +UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive +--Testcase 817: +ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive; + +-- But inconsistent check constraints provide inconsistent results +--Testcase 818: +ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0); +--Testcase 591: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; +--Testcase 592: +SELECT count(*) FROM ft1 WHERE c2 >= 0; +--Testcase 819: +SET constraint_exclusion = 'on'; +--Testcase 593: +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; +--Testcase 594: +SELECT count(*) FROM ft1 WHERE c2 >= 0; +--Testcase 820: +RESET constraint_exclusion; +-- local check constraint is not actually enforced +--Testcase 595: +INSERT INTO ft1(c1, c2) VALUES(1111, 2); +--Testcase 596: +UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1; +--Testcase 821: +ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative; + +-- =================================================================== +-- test WITH CHECK OPTION constraints +-- =================================================================== +--Testcase 597: +CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql; + +--Testcase 598: +CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) + SERVER sqlite_svr; +--Testcase 599: +CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); +--Testcase 600: +CREATE VIEW rw_view AS SELECT * FROM foreign_tbl + WHERE a < b WITH CHECK OPTION; +--Testcase 601: +\d+ rw_view + +--Testcase 345: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 5); +--Testcase 602: +INSERT INTO rw_view VALUES (0, 5); -- should fail +--Testcase 603: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15); +--Testcase 604: +INSERT INTO rw_view VALUES (0, 15); -- error +--Testcase 605: +SELECT * FROM foreign_tbl; + +--Testcase 606: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 5; +--Testcase 607: +UPDATE rw_view SET b = b + 5; -- should fail +--Testcase 608: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 15; +--Testcase 609: +UPDATE rw_view SET b = b + 15; -- ok +--Testcase 610: +SELECT * FROM foreign_tbl; + +-- We don't allow batch insert when there are any WCO constraints +ALTER SERVER sqlite_svr OPTIONS (ADD batch_size '10'); +--Testcase 989: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15), (1, 5); +--Testcase 990: +INSERT INTO rw_view VALUES (0, 15), (1, 5); -- should fail +--Testcase 991: +SELECT * FROM foreign_tbl; +ALTER SERVER sqlite_svr OPTIONS (DROP batch_size); + +--Testcase 611: +DROP FOREIGN TABLE foreign_tbl CASCADE; +--Testcase 612: +DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; + +-- test WCO for partitions + +--Testcase 613: +CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) + SERVER sqlite_svr; +--Testcase 614: +CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); + +--Testcase 615: +CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a); +--Testcase 822: +ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); +-- Detach and re-attach once, to stress the concurrent detach case. +--Testcase 975: +ALTER TABLE parent_tbl DETACH PARTITION foreign_tbl CONCURRENTLY; +--Testcase 976: +ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); + +--Testcase 616: +CREATE VIEW rw_view AS SELECT * FROM parent_tbl + WHERE a < b WITH CHECK OPTION; +--Testcase 617: +\d+ rw_view + +--Testcase 618: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 5); +--Testcase 619: +INSERT INTO rw_view VALUES (0, 5); -- should fail +--Testcase 620: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15); +--Testcase 621: +INSERT INTO rw_view VALUES (0, 15); -- ok +--Testcase 622: +SELECT * FROM foreign_tbl; + +--Testcase 623: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 5; +--Testcase 624: +UPDATE rw_view SET b = b + 5; -- should fail +--Testcase 625: +EXPLAIN (VERBOSE, COSTS OFF) +UPDATE rw_view SET b = b + 15; +--Testcase 626: +UPDATE rw_view SET b = b + 15; -- ok +--Testcase 627: +SELECT * FROM foreign_tbl; + +-- We don't allow batch insert when there are any WCO constraints +ALTER SERVER sqlite_svr OPTIONS (ADD batch_size '10'); +--Testcase 992: +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rw_view VALUES (0, 15), (1, 5); +--Testcase 993: +INSERT INTO rw_view VALUES (0, 15), (1, 5); -- should fail +--Testcase 994: +SELECT * FROM foreign_tbl; +ALTER SERVER sqlite_svr OPTIONS (DROP batch_size); + +--Testcase 628: +DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; +--Testcase 629: +DROP FOREIGN TABLE foreign_tbl CASCADE; +--Testcase 630: +DROP TABLE parent_tbl CASCADE; + +--Testcase 631: +DROP FUNCTION row_before_insupd_trigfunc; + +-- -- Try a more complex permutation of WCO where there are multiple levels of +-- -- partitioned tables with columns not all in the same order +-- CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a); +-- CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a); +-- ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10); +-- CREATE TABLE child_local (b text, c numeric, a int); +-- CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int) +-- SERVER loopback OPTIONS (table_name 'child_local'); +-- ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10); +-- CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION; + +-- INSERT INTO parent_tbl (a) VALUES(1),(5); +-- EXPLAIN (VERBOSE, COSTS OFF) +-- UPDATE rw_view SET b = 'text', c = 123.456; +-- UPDATE rw_view SET b = 'text', c = 123.456; +-- SELECT * FROM parent_tbl ORDER BY a; + +-- DROP VIEW rw_view; +-- DROP TABLE child_local; +-- DROP FOREIGN TABLE child_foreign; +-- DROP TABLE sub_parent; +-- DROP TABLE parent_tbl; + + +-- =================================================================== +-- test serial columns (ie, sequence-based defaults) +-- =================================================================== +--Testcase 632: +create foreign table loc1 (f1 serial, f2 text, id integer options (key 'true')) + server sqlite_svr; +--Testcase 633: +create foreign table rem1 (f1 serial, f2 text, id integer options (key 'true')) + server sqlite_svr options(table 'loc1'); +--Testcase 352: +select pg_catalog.setval('rem1_f1_seq', 10, false); +--Testcase 353: +insert into loc1(f2) values('hi'); +--Testcase 634: +insert into rem1(f2) values('hi remote'); +--Testcase 354: +insert into loc1(f2) values('bye'); +--Testcase 635: +insert into rem1(f2) values('bye remote'); +--Testcase 355: +select f1, f2 from loc1; +--Testcase 636: +select f1, f2 from rem1; + +-- =================================================================== +-- test generated columns +-- =================================================================== +--Testcase 637: +create foreign table grem1 ( + a int options (key 'true'), + b int generated always as (a * 2) stored) + server sqlite_svr options(table 'grem1_post14'); +--Testcase 638: +explain (verbose, costs off) +insert into grem1 (a) values (1), (2); +--Testcase 823: +insert into grem1 (a) values (1), (2); +--Testcase 639: +explain (verbose, costs off) +update grem1 set a = 22 where a = 2; +--Testcase 824: +update grem1 set a = 22 where a = 2; +--Testcase 640: +select * from grem1; +--Testcase 825: +delete from grem1; + +-- -- test copy from +-- copy grem1 from stdin; +-- 1 +-- 2 +-- \. +-- select * from grem1; +-- delete from grem1; + +-- test batch insert +--Testcase 826: +alter server sqlite_svr options (add batch_size '10'); +--Testcase 827: +explain (verbose, costs off) +insert into grem1 (a) values (1), (2); +--Testcase 828: +insert into grem1 (a) values (1), (2); +--Testcase 829: +select * from grem1; +--Testcase 830: +delete from grem1; + +-- -- batch insert with foreign partitions. +-- -- This schema uses two partitions, one local and one remote with a modulo +-- -- to loop across all of them in batches. +-- create table tab_batch_local (id int, data text); +-- insert into tab_batch_local select i, 'test'|| i from generate_series(1, 45) i; +-- create table tab_batch_sharded (id int, data text) partition by hash(id); +-- create table tab_batch_sharded_p0 partition of tab_batch_sharded +-- for values with (modulus 2, remainder 0); +-- create table tab_batch_sharded_p1_remote (id int, data text); +-- create foreign table tab_batch_sharded_p1 partition of tab_batch_sharded +-- for values with (modulus 2, remainder 1) +-- server loopback options (table_name 'tab_batch_sharded_p1_remote'); +-- insert into tab_batch_sharded select * from tab_batch_local; +-- select count(*) from tab_batch_sharded; +-- drop table tab_batch_local; +-- drop table tab_batch_sharded; +-- drop table tab_batch_sharded_p1_remote; + +--Testcase 831: +alter server sqlite_svr options (drop batch_size); + +-- =================================================================== +-- test local triggers +-- =================================================================== + +-- Trigger functions "borrowed" from triggers regress test. +--Testcase 641: +CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$ +BEGIN + RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %', + TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; + RETURN NULL; +END;$$; + +--Testcase 642: +CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 1005: +CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); + +--Testcase 644: +CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger +LANGUAGE plpgsql AS $$ + +declare + oldnew text[]; + relid text; + argstr text; +begin + + relid := TG_relid::regclass; + argstr := ''; + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + + RAISE NOTICE '%(%) % % % ON %', + tg_name, argstr, TG_when, TG_level, TG_OP, relid; + oldnew := '{}'::text[]; + if TG_OP != 'INSERT' then + oldnew := array_append(oldnew, format('OLD: %s', OLD)); + end if; + + if TG_OP != 'DELETE' then + oldnew := array_append(oldnew, format('NEW: %s', NEW)); + end if; + + RAISE NOTICE '%', array_to_string(oldnew, ','); + + if TG_OP = 'DELETE' then + return OLD; + else + return NEW; + end if; +end; +$$; + +-- Test basic functionality +--Testcase 645: +CREATE TRIGGER trig_row_before +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 646: +CREATE TRIGGER trig_row_after +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 356: +delete from rem1; +--Testcase 357: +insert into rem1 values(1,'insert'); +--Testcase 358: +update rem1 set f2 = 'update' where f1 = 1; +--Testcase 359: +update rem1 set f2 = f2 || f2; +truncate rem1; + + +-- cleanup +--Testcase 647: +DROP TRIGGER trig_row_before ON rem1; +--Testcase 648: +DROP TRIGGER trig_row_after ON rem1; +--Testcase 649: +DROP TRIGGER trig_stmt_before ON rem1; +--Testcase 650: +DROP TRIGGER trig_stmt_after ON rem1; + +--Testcase 360: +DELETE from rem1; + +-- Test multiple AFTER ROW triggers on a foreign table +--Testcase 651: +CREATE TRIGGER trig_row_after1 +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 652: +CREATE TRIGGER trig_row_after2 +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 653: +insert into rem1 values(1,'insert'); +--Testcase 654: +update rem1 set f2 = 'update' where f1 = 1; +--Testcase 655: +update rem1 set f2 = f2 || f2; +--Testcase 656: +delete from rem1; + +-- cleanup +--Testcase 657: +DROP TRIGGER trig_row_after1 ON rem1; +--Testcase 658: +DROP TRIGGER trig_row_after2 ON rem1; + +-- Test WHEN conditions + +--Testcase 659: +CREATE TRIGGER trig_row_before_insupd +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW +WHEN (NEW.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 660: +CREATE TRIGGER trig_row_after_insupd +AFTER INSERT OR UPDATE ON rem1 +FOR EACH ROW +WHEN (NEW.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +-- Insert or update not matching: nothing happens +--Testcase 363: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 364: +UPDATE rem1 set f2 = 'test'; + +-- Insert or update matching: triggers are fired +--Testcase 365: +INSERT INTO rem1 values(2, 'update'); +--Testcase 366: +UPDATE rem1 set f2 = 'update update' where f1 = '2'; + +--Testcase 661: +CREATE TRIGGER trig_row_before_delete +BEFORE DELETE ON rem1 +FOR EACH ROW +WHEN (OLD.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 662: +CREATE TRIGGER trig_row_after_delete +AFTER DELETE ON rem1 +FOR EACH ROW +WHEN (OLD.f2 like '%update%') +EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +-- Trigger is fired for f1=2, not for f1=1 +--Testcase 369: +DELETE FROM rem1; + +-- cleanup +--Testcase 663: +DROP TRIGGER trig_row_before_insupd ON rem1; +--Testcase 664: +DROP TRIGGER trig_row_after_insupd ON rem1; +--Testcase 665: +DROP TRIGGER trig_row_before_delete ON rem1; +--Testcase 666: +DROP TRIGGER trig_row_after_delete ON rem1; + + +-- Test various RETURN statements in BEFORE triggers. + +--Testcase 667: +CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ + BEGIN + NEW.f2 := NEW.f2 || ' triggered !'; + RETURN NEW; + END +$$ language plpgsql; + +--Testcase 668: +CREATE TRIGGER trig_row_before_insupd +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); + +-- The new values should have 'triggered' appended +--Testcase 370: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 371: +SELECT f1, f2 from rem1; +--Testcase 372: +INSERT INTO rem1 values(2, 'insert'); +--Testcase 373: +SELECT f1, f2 from rem1; +--Testcase 374: +UPDATE rem1 set f2 = ''; +--Testcase 375: +SELECT f1, f2 from rem1; +--Testcase 376: +UPDATE rem1 set f2 = 'skidoo'; +--Testcase 377: +SELECT f1, f2 from rem1; + +--Testcase 669: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f1 = 10; -- all columns should be transmitted +--Testcase 670: +UPDATE rem1 set f1 = 10; +--Testcase 671: +SELECT f1, f2 from rem1; + +--Testcase 378: +DELETE FROM rem1; + +-- Add a second trigger, to check that the changes are propagated correctly +-- from trigger to trigger +--Testcase 672: +CREATE TRIGGER trig_row_before_insupd2 +BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); + +--Testcase 379: +INSERT INTO rem1 values(1, 'insert'); +--Testcase 380: +SELECT f1, f2 from rem1; +--Testcase 381: +INSERT INTO rem1 values(2, 'insert'); +--Testcase 382: +SELECT f1, f2 from rem1; +--Testcase 383: +UPDATE rem1 set f2 = ''; +--Testcase 384: +SELECT f1, f2 from rem1; +--Testcase 385: +UPDATE rem1 set f2 = 'skidoo'; +--Testcase 386: +SELECT f1, f2 from rem1; + +--Testcase 673: +DROP TRIGGER trig_row_before_insupd ON rem1; +--Testcase 674: +DROP TRIGGER trig_row_before_insupd2 ON rem1; + +--Testcase 387: +DELETE from rem1; + +--Testcase 388: +INSERT INTO rem1 VALUES (1, 'test'); + +-- Test with a trigger returning NULL +--Testcase 675: +CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +--Testcase 676: +CREATE TRIGGER trig_null +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_null(); + +-- Nothing should have changed. +--Testcase 389: +INSERT INTO rem1 VALUES (2, 'test2'); + +--Testcase 390: +SELECT f1, f2 from rem1; + +--Testcase 391: +UPDATE rem1 SET f2 = 'test2'; + +--Testcase 392: +SELECT f1, f2 from rem1; + +--Testcase 393: +DELETE from rem1; + +--Testcase 394: +SELECT f1, f2 from rem1; + +--Testcase 677: +DROP TRIGGER trig_null ON rem1; +--Testcase 395: +DELETE from rem1; + +-- Test a combination of local and remote triggers +--Testcase 678: +CREATE TRIGGER trig_row_before +BEFORE INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 679: +CREATE TRIGGER trig_row_after +AFTER INSERT OR UPDATE OR DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 680: +CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); + +--Testcase 681: +INSERT INTO rem1(f2) VALUES ('test'); +--Testcase 682: +UPDATE rem1 SET f2 = 'testo'; + +-- Test returning a system attribute +--Testcase 683: +INSERT INTO rem1(f2) VALUES ('test'); + +-- cleanup +--Testcase 684: +DROP TRIGGER trig_row_before ON rem1; +--Testcase 685: +DROP TRIGGER trig_row_after ON rem1; +--Testcase 686: +DROP TRIGGER trig_local_before ON rem1; + + +-- Test direct foreign table modification functionality +--Testcase 832: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 833: +EXPLAIN (verbose, costs off) +DELETE FROM rem1 WHERE false; -- currently can't be pushed down + +-- Test with statement-level triggers +--Testcase 687: +CREATE TRIGGER trig_stmt_before + BEFORE DELETE OR INSERT OR UPDATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 396: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 397: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 688: +DROP TRIGGER trig_stmt_before ON rem1; + +--Testcase 689: +CREATE TRIGGER trig_stmt_after + AFTER DELETE OR INSERT OR UPDATE ON rem1 + FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); +--Testcase 398: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 399: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 690: +DROP TRIGGER trig_stmt_after ON rem1; + +-- Test with row-level ON INSERT triggers +--Testcase 691: +CREATE TRIGGER trig_row_before_insert +BEFORE INSERT ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 400: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 401: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 692: +DROP TRIGGER trig_row_before_insert ON rem1; + +--Testcase 693: +CREATE TRIGGER trig_row_after_insert +AFTER INSERT ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 402: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 403: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 694: +DROP TRIGGER trig_row_after_insert ON rem1; + +-- Test with row-level ON UPDATE triggers +--Testcase 695: +CREATE TRIGGER trig_row_before_update +BEFORE UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 404: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can't be pushed down +--Testcase 405: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 696: +DROP TRIGGER trig_row_before_update ON rem1; + +--Testcase 697: +CREATE TRIGGER trig_row_after_update +AFTER UPDATE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 406: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can't be pushed down +--Testcase 407: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can be pushed down +--Testcase 698: +DROP TRIGGER trig_row_after_update ON rem1; + +-- Test with row-level ON DELETE triggers +--Testcase 699: +CREATE TRIGGER trig_row_before_delete +BEFORE DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 408: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 409: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can't be pushed down +--Testcase 700: +DROP TRIGGER trig_row_before_delete ON rem1; + +--Testcase 701: +CREATE TRIGGER trig_row_after_delete +AFTER DELETE ON rem1 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 410: +EXPLAIN (verbose, costs off) +UPDATE rem1 set f2 = ''; -- can be pushed down +--Testcase 411: +EXPLAIN (verbose, costs off) +DELETE FROM rem1; -- can't be pushed down +--Testcase 702: +DROP TRIGGER trig_row_after_delete ON rem1; + +-- =================================================================== +-- test inheritance features +-- =================================================================== + +--Testcase 703: +CREATE TABLE a (aa TEXT); +--Testcase 834: +ALTER TABLE a SET (autovacuum_enabled = 'false'); +--Testcase 704: +CREATE FOREIGN TABLE b (aa TEXT OPTIONS (key 'true'), bb TEXT) INHERITS (a) + SERVER sqlite_svr OPTIONS (table 'loct'); + +--Testcase 412: +INSERT INTO a(aa) VALUES('aaa'); +--Testcase 413: +INSERT INTO a(aa) VALUES('aaaa'); +--Testcase 414: +INSERT INTO a(aa) VALUES('aaaaa'); + +--Testcase 415: +INSERT INTO b(aa) VALUES('bbb'); +--Testcase 416: +INSERT INTO b(aa) VALUES('bbbb'); +--Testcase 417: +INSERT INTO b(aa) VALUES('bbbbb'); + +--Testcase 418: +SELECT tableoid::regclass, * FROM a; +--Testcase 419: +SELECT tableoid::regclass, * FROM b; +--Testcase 420: +SELECT tableoid::regclass, * FROM ONLY a; + +--Testcase 421: +UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%'; + +--Testcase 422: +SELECT tableoid::regclass, * FROM a; +--Testcase 423: +SELECT tableoid::regclass, * FROM b; +--Testcase 424: +SELECT tableoid::regclass, * FROM ONLY a; + +--Testcase 425: +UPDATE b SET aa = 'new'; + +--Testcase 426: +SELECT tableoid::regclass, * FROM a; +--Testcase 427: +SELECT tableoid::regclass, * FROM b; +--Testcase 428: +SELECT tableoid::regclass, * FROM ONLY a; + +--Testcase 429: +UPDATE a SET aa = 'newtoo'; + +--Testcase 430: +SELECT tableoid::regclass, * FROM a; +--Testcase 431: +SELECT tableoid::regclass, * FROM b; +--Testcase 432: +SELECT tableoid::regclass, * FROM ONLY a; + +--Testcase 433: +DELETE FROM a; + +--Testcase 434: +SELECT tableoid::regclass, * FROM a; +--Testcase 435: +SELECT tableoid::regclass, * FROM b; +--Testcase 436: +SELECT tableoid::regclass, * FROM ONLY a; + +--Testcase 705: +DROP TABLE a CASCADE; + +-- Check SELECT FOR UPDATE/SHARE with an inherited source table + +--Testcase 706: +create table foo (f1 int, f2 int); +--Testcase 707: +create foreign table foo2 (f3 int OPTIONS (key 'true')) inherits (foo) + server sqlite_svr options (table 'loct1'); +--Testcase 708: +create table bar (f1 int, f2 int); +--Testcase 709: +create foreign table bar2 (f3 int OPTIONS (key 'true')) inherits (bar) + server sqlite_svr options (table 'loct2'); + +--Testcase 835: +alter table foo set (autovacuum_enabled = 'false'); +--Testcase 836: +alter table bar set (autovacuum_enabled = 'false'); + +--Testcase 437: +insert into foo values(1,1); +--Testcase 438: +insert into foo values(3,3); +--Testcase 439: +insert into foo2 values(2,2,2); +--Testcase 440: +insert into foo2 values(4,4,4); +--Testcase 441: +insert into bar values(1,11); +--Testcase 442: +insert into bar values(2,22); +--Testcase 443: +insert into bar values(6,66); +--Testcase 444: +insert into bar2 values(3,33,33); +--Testcase 445: +insert into bar2 values(4,44,44); +--Testcase 446: +insert into bar2 values(7,77,77); + +--Testcase 447: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo) for update; +--Testcase 448: +select * from bar where f1 in (select f1 from foo) for update; + +--Testcase 449: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo) for share; +--Testcase 450: +select * from bar where f1 in (select f1 from foo) for share; + +-- Now check SELECT FOR UPDATE/SHARE with an inherited source table, +-- where the parent is itself a foreign table +--Testcase 837: +create foreign table foo2child (f3 int) inherits (foo2) + server sqlite_svr options (table 'loct4_2'); + +--Testcase 838: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo2) for share; +--Testcase 839: +select * from bar where f1 in (select f1 from foo2) for share; + +--Testcase 840: +drop foreign table foo2child; + +-- And with a local child relation of the foreign table parent +--Testcase 841: +create table foo2child (f3 int) inherits (foo2); + +--Testcase 842: +explain (verbose, costs off) +select * from bar where f1 in (select f1 from foo2) for share; +--Testcase 843: +select * from bar where f1 in (select f1 from foo2) for share; + +--Testcase 844: +drop table foo2child; + +-- Check UPDATE with inherited target and an inherited source table +--Testcase 451: +explain (verbose, costs off) +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); +--Testcase 452: +update bar set f2 = f2 + 100 where f1 in (select f1 from foo); + +--Testcase 453: +select tableoid::regclass, * from bar order by 1,2; + +-- Check UPDATE with inherited target and an appendrel subquery +--Testcase 454: +explain (verbose, costs off) +update bar set f2 = f2 + 100 +from + ( select f1 from foo union all select f1+3 from foo ) ss +where bar.f1 = ss.f1; +--Testcase 455: +update bar set f2 = f2 + 100 +from + ( select f1 from foo union all select f1+3 from foo ) ss +where bar.f1 = ss.f1; + +--Testcase 456: +select tableoid::regclass, * from bar order by 1,2; + +-- Test forcing the remote server to produce sorted data for a merge join, +-- but the foreign table is an inheritance child. +--truncate table loct1; +--Testcase 710: +delete from foo2; +truncate table only foo; +\set num_rows_foo 2000 +--Testcase 711: +insert into foo2 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2); +--Testcase 712: +insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2); +--Testcase 845: +SET enable_hashjoin to false; +--Testcase 846: +SET enable_nestloop to false; +--alter foreign table foo2 options (use_remote_estimate 'true'); +--create index i_loct1_f1 on loct1(f1); +--Testcase 713: +create index i_foo_f1 on foo(f1); +analyze foo; +--analyze loct1; +-- inner join; expressions in the clauses appear in the equivalence class list +--Testcase 714: +explain (verbose, costs off) + select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; +--Testcase 715: +select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; +-- outer join; expressions in the clauses do not appear in equivalence class +-- list but no output change as compared to the previous query +--Testcase 716: +explain (verbose, costs off) + select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; +--Testcase 717: +select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; +--Testcase 847: +RESET enable_hashjoin; +--Testcase 848: +RESET enable_nestloop; + +-- Test that WHERE CURRENT OF is not supported +begin; +declare c cursor for select * from bar where f1 = 7; +--Testcase 457: +fetch from c; +--Testcase 458: +update bar set f2 = null where current of c; +rollback; + +--Testcase 459: +explain (verbose, costs off) +delete from foo where f1 < 5; +--Testcase 460: +delete from foo where f1 < 5; +--Testcase 461: +explain (verbose, costs off) +update bar set f2 = f2 + 100; +--Testcase 462: +update bar set f2 = f2 + 100; +--Testcase 463: +select * from bar; + +-- Test that UPDATE/DELETE with inherited target works with row-level triggers +--Testcase 718: +CREATE TRIGGER trig_row_before +BEFORE UPDATE OR DELETE ON bar2 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 719: +CREATE TRIGGER trig_row_after +AFTER UPDATE OR DELETE ON bar2 +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +--Testcase 464: +explain (verbose, costs off) +update bar set f2 = f2 + 100; +--Testcase 465: +update bar set f2 = f2 + 100; + +--Testcase 466: +explain (verbose, costs off) +delete from bar where f2 < 400; +--Testcase 467: +delete from bar where f2 < 400; + +-- cleanup +--Testcase 720: +drop table foo cascade; +--Testcase 721: +drop table bar cascade; + +-- Test pushing down UPDATE/DELETE joins to the remote server +--Testcase 722: +create table parent (a int, b text); +--Testcase 723: +create foreign table remt1 (a int OPTIONS (key 'true'), b text) + server sqlite_svr options (table 'loct3'); +--Testcase 724: +create foreign table remt2 (a int OPTIONS (key 'true'), b text) + server sqlite_svr options (table 'loct4'); +--Testcase 849: +alter foreign table remt1 inherit parent; + +--Testcase 468: +insert into remt1 values (1, 'foo'); +--Testcase 469: +insert into remt1 values (2, 'bar'); +--Testcase 470: +insert into remt2 values (1, 'foo'); +--Testcase 471: +insert into remt2 values (2, 'bar'); + +--Testcase 472: +explain (verbose, costs off) +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; +--Testcase 473: +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; +--Testcase 474: +select * from parent inner join remt2 on (parent.a = remt2.a); +--Testcase 475: +explain (verbose, costs off) +delete from parent using remt2 where parent.a = remt2.a; +--Testcase 476: +delete from parent using remt2 where parent.a = remt2.a; + +-- cleanup +--Testcase 725: +drop foreign table remt1; +--Testcase 726: +drop foreign table remt2; +--Testcase 727: +drop table parent; + +/* +-- Skip these tests, sqlite fdw does not support partition table, check constraint, copy from +-- =================================================================== +-- test tuple routing for foreign-table partitions +-- =================================================================== + +-- Test insert tuple routing +create table itrtest (a int, b text) partition by list (a); +create table loct1 (a int check (a in (1)), b text); +create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); +create table loct2 (a int check (a in (2)), b text); +create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); +alter table itrtest attach partition remp1 for values in (1); +alter table itrtest attach partition remp2 for values in (2); + +insert into itrtest values (1, 'foo'); +insert into itrtest values (1, 'bar') returning *; +insert into itrtest values (2, 'baz'); +insert into itrtest values (2, 'qux') returning *; +insert into itrtest values (1, 'test1'), (2, 'test2') returning *; + +select tableoid::regclass, * FROM itrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +delete from itrtest; + +-- MERGE ought to fail cleanly +merge into itrtest using (select 1, 'foo') as source on (true) + when matched then do nothing; + +create unique index loct1_idx on loct1 (a); + +-- DO NOTHING without an inference specification is supported +insert into itrtest values (1, 'foo') on conflict do nothing returning *; +insert into itrtest values (1, 'foo') on conflict do nothing returning *; + +-- But other cases are not supported +insert into itrtest values (1, 'bar') on conflict (a) do nothing; +insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b; + +select tableoid::regclass, * FROM itrtest; + +delete from itrtest; + +drop index loct1_idx; + +-- Test that remote triggers work with insert tuple routing +create function br_insert_trigfunc() returns trigger as $$ +begin + new.b := new.b || ' triggered !'; + return new; +end +$$ language plpgsql; +create trigger loct1_br_insert_trigger before insert on loct1 + for each row execute procedure br_insert_trigfunc(); +create trigger loct2_br_insert_trigger before insert on loct2 + for each row execute procedure br_insert_trigfunc(); + +-- The new values are concatenated with ' triggered !' +insert into itrtest values (1, 'foo') returning *; +insert into itrtest values (2, 'qux') returning *; +insert into itrtest values (1, 'test1'), (2, 'test2') returning *; +with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result; + +drop trigger loct1_br_insert_trigger on loct1; +drop trigger loct2_br_insert_trigger on loct2; + +drop table itrtest; +drop table loct1; +drop table loct2; + +-- Test update tuple routing +create table utrtest (a int, b text) partition by list (a); +create table loct (a int check (a in (1)), b text); +create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct'); +create table locp (a int check (a in (2)), b text); +alter table utrtest attach partition remp for values in (1); +alter table utrtest attach partition locp for values in (2); + +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +select tableoid::regclass, * FROM utrtest; +select tableoid::regclass, * FROM remp; +select tableoid::regclass, * FROM locp; + +-- It's not allowed to move a row from a partition that is foreign to another +update utrtest set a = 2 where b = 'foo' returning *; + +-- But the reverse is allowed +update utrtest set a = 1 where b = 'qux' returning *; + +select tableoid::regclass, * FROM utrtest; +select tableoid::regclass, * FROM remp; +select tableoid::regclass, * FROM locp; + +-- The executor should not let unexercised FDWs shut down +update utrtest set a = 1 where b = 'foo'; + +-- Test that remote triggers work with update tuple routing +create trigger loct_br_insert_trigger before insert on loct + for each row execute procedure br_insert_trigfunc(); + +delete from utrtest; +insert into utrtest values (2, 'qux'); + +-- Check case where the foreign partition is a subplan target rel +explain (verbose, costs off) +update utrtest set a = 1 where a = 1 or a = 2 returning *; +-- The new values are concatenated with ' triggered !' +update utrtest set a = 1 where a = 1 or a = 2 returning *; + +delete from utrtest; +insert into utrtest values (2, 'qux'); + +-- Check case where the foreign partition isn't a subplan target rel +explain (verbose, costs off) +update utrtest set a = 1 where a = 2 returning *; +-- The new values are concatenated with ' triggered !' +update utrtest set a = 1 where a = 2 returning *; + +drop trigger loct_br_insert_trigger on loct; + +-- We can move rows to a foreign partition that has been updated already, +-- but can't move rows to a foreign partition that hasn't been updated yet + +delete from utrtest; +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +-- Test the former case: +-- with a direct modification plan +explain (verbose, costs off) +update utrtest set a = 1 returning *; +update utrtest set a = 1 returning *; + +delete from utrtest; +insert into utrtest values (1, 'foo'); +insert into utrtest values (2, 'qux'); + +-- with a non-direct modification plan +explain (verbose, costs off) +update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; +update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; + +-- Change the definition of utrtest so that the foreign partition get updated +-- after the local partition +delete from utrtest; +alter table utrtest detach partition remp; +drop foreign table remp; +alter table loct drop constraint loct_a_check; +alter table loct add check (a in (3)); +create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct'); +alter table utrtest attach partition remp for values in (3); +insert into utrtest values (2, 'qux'); +insert into utrtest values (3, 'xyzzy'); + +-- Test the latter case: +-- with a direct modification plan +explain (verbose, costs off) +update utrtest set a = 3 returning *; +update utrtest set a = 3 returning *; -- ERROR + +-- with a non-direct modification plan +explain (verbose, costs off) +update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; +update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR + +drop table utrtest; +drop table loct; + +-- Test copy tuple routing +create table ctrtest (a int, b text) partition by list (a); +create table loct1 (a int check (a in (1)), b text); +create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); +create table loct2 (a int check (a in (2)), b text); +create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); +alter table ctrtest attach partition remp1 for values in (1); +alter table ctrtest attach partition remp2 for values in (2); + +copy ctrtest from stdin; +1 foo +2 qux +\. + +select tableoid::regclass, * FROM ctrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +-- Copying into foreign partitions directly should work as well +copy remp1 from stdin; +1 bar +\. + +select tableoid::regclass, * FROM remp1; + +delete from ctrtest; + +-- Test copy tuple routing with the batch_size option enabled +alter server loopback options (add batch_size '2'); + +copy ctrtest from stdin; +1 foo +1 bar +2 baz +2 qux +1 test1 +2 test2 +\. + +select tableoid::regclass, * FROM ctrtest; +select tableoid::regclass, * FROM remp1; +select tableoid::regclass, * FROM remp2; + +delete from ctrtest; + +alter server loopback options (drop batch_size); + + +drop table ctrtest; +drop table loct1; +drop table loct2; + +-- =================================================================== +-- test COPY FROM +-- =================================================================== + +create table loc2 (f1 int, f2 text); +alter table loc2 set (autovacuum_enabled = 'false'); +create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2'); + +-- Test basic functionality +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +delete from rem2; + +-- Test check constraints +alter table loc2 add constraint loc2_f1positive check (f1 >= 0); +alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); + +-- check constraint is enforced on the remote side, not locally +copy rem2 from stdin; +1 foo +2 bar +\. +copy rem2 from stdin; -- ERROR +-1 xyzzy +\. +select * from rem2; + +alter foreign table rem2 drop constraint rem2_f1positive; +alter table loc2 drop constraint loc2_f1positive; + +delete from rem2; + +-- Test local triggers +create trigger trig_stmt_before before insert on rem2 + for each statement execute procedure trigger_func(); +create trigger trig_stmt_after after insert on rem2 + for each statement execute procedure trigger_func(); +create trigger trig_row_before before insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger trig_row_after after insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); + +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before on rem2; +drop trigger trig_row_after on rem2; +drop trigger trig_stmt_before on rem2; +drop trigger trig_stmt_after on rem2; + +delete from rem2; + +create trigger trig_row_before_insert before insert on rem2 + for each row execute procedure trig_row_before_insupdate(); + +-- The new values are concatenated with ' triggered !' +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before_insert on rem2; + +delete from rem2; + +create trigger trig_null before insert on rem2 + for each row execute procedure trig_null(); + +-- Nothing happens +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_null on rem2; + +delete from rem2; + +-- Test remote triggers +create trigger trig_row_before_insert before insert on loc2 + for each row execute procedure trig_row_before_insupdate(); + +-- The new values are concatenated with ' triggered !' +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_row_before_insert on loc2; + +delete from rem2; + +create trigger trig_null before insert on loc2 + for each row execute procedure trig_null(); + +-- Nothing happens +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger trig_null on loc2; + +delete from rem2; + +-- Test a combination of local and remote triggers +create trigger rem2_trig_row_before before insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger rem2_trig_row_after after insert on rem2 + for each row execute procedure trigger_data(23,'skidoo'); +create trigger loc2_trig_row_before_insert before insert on loc2 + for each row execute procedure trig_row_before_insupdate(); + +copy rem2 from stdin; +1 foo +2 bar +\. +select * from rem2; + +drop trigger rem2_trig_row_before on rem2; +drop trigger rem2_trig_row_after on rem2; +drop trigger loc2_trig_row_before_insert on loc2; + +delete from rem2; + +-- test COPY FROM with foreign table created in the same transaction +create table loc3 (f1 int, f2 text); +begin; +create foreign table rem3 (f1 int, f2 text) + server loopback options(table_name 'loc3'); +copy rem3 from stdin; +1 foo +2 bar +\. +commit; +select * from rem3; +drop foreign table rem3; +drop table loc3; +*/ +-- Test COPY FROM with the batch_size option enabled +-- alter server loopback options (add batch_size '2'); + +-- -- Test basic functionality +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; + +-- delete from rem2; + +-- -- Test check constraints +-- alter table loc2 add constraint loc2_f1positive check (f1 >= 0); +-- alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); + +-- -- check constraint is enforced on the remote side, not locally +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- copy rem2 from stdin; -- ERROR +-- -1 xyzzy +-- \. +-- select * from rem2; + +-- alter foreign table rem2 drop constraint rem2_f1positive; +-- alter table loc2 drop constraint loc2_f1positive; + +-- delete from rem2; + +-- -- Test remote triggers +-- create trigger trig_row_before_insert before insert on loc2 +-- for each row execute procedure trig_row_before_insupdate(); + +-- -- The new values are concatenated with ' triggered !' +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; + +-- drop trigger trig_row_before_insert on loc2; + +-- delete from rem2; + +-- create trigger trig_null before insert on loc2 +-- for each row execute procedure trig_null(); + +-- -- Nothing happens +-- copy rem2 from stdin; +-- 1 foo +-- 2 bar +-- 3 baz +-- \. +-- select * from rem2; + +-- drop trigger trig_null on loc2; + +-- delete from rem2; + +-- -- Check with zero-column foreign table; batch insert will be disabled +-- alter table loc2 drop column f1; +-- alter table loc2 drop column f2; +-- alter table rem2 drop column f1; +-- alter table rem2 drop column f2; +-- copy rem2 from stdin; + + +-- select * from rem2; + +-- delete from rem2; + +-- alter server loopback options (drop batch_size); + +-- =================================================================== +-- test for TRUNCATE +-- =================================================================== +--Testcase 850: +CREATE FOREIGN TABLE tru_ftable (id int) + SERVER sqlite_svr OPTIONS (table 'tru_rtable0'); +--Testcase 851: +INSERT INTO "S 1".tru_rtable0 (SELECT x FROM generate_series(1,10) x); + +-- CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id); +-- CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable +-- FOR VALUES WITH (MODULUS 2, REMAINDER 0); +-- CREATE TABLE tru_rtable1 (id int primary key); +-- CREATE FOREIGN TABLE tru_ftable__p1 (id int) +-- SERVER sqlite_svr OPTIONS (table 'tru_ptable'); +-- INSERT INTO tru_ptable (SELECT x FROM generate_series(11,20) x); + +--Testcase 852: +INSERT INTO "S 1".tru_pk_table (SELECT x FROM generate_series(1,10) x); +--Testcase 853: +INSERT INTO "S 1".tru_fk_table(fkey) (SELECT x % 10 + 1 FROM generate_series(5,25) x); +--Testcase 854: +CREATE FOREIGN TABLE tru_pk_ftable (id int) + SERVER sqlite_svr OPTIONS (table 'tru_pk_table'); + +--Testcase 855: +CREATE FOREIGN TABLE tru_ftable_parent (id int) + SERVER sqlite_svr OPTIONS (table 'tru_rtable_parent'); +--Testcase 856: +CREATE FOREIGN TABLE tru_ftable_child () INHERITS (tru_ftable_parent) + SERVER sqlite_svr OPTIONS (table 'tru_rtable_child'); +--Testcase 857: +INSERT INTO "S 1".tru_rtable_parent (SELECT x FROM generate_series(1,8) x); +--Testcase 858: +INSERT INTO "S 1".tru_rtable_child (SELECT x FROM generate_series(10, 18) x); + +-- normal truncate +--Testcase 859: +SELECT sum(id) FROM tru_ftable; -- 55 +TRUNCATE tru_ftable; +--Testcase 860: +SELECT count(*) FROM "S 1".tru_rtable0; -- 0 +--Testcase 861: +SELECT count(*) FROM tru_ftable; -- 0 + +-- 'truncatable' option +--Testcase 862: +ALTER SERVER sqlite_svr OPTIONS (ADD truncatable 'false'); +TRUNCATE tru_ftable; -- error +--Testcase 863: +ALTER FOREIGN TABLE tru_ftable OPTIONS (ADD truncatable 'true'); +TRUNCATE tru_ftable; -- accepted +--Testcase 864: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); +TRUNCATE tru_ftable; -- error +--Testcase 865: +ALTER SERVER sqlite_svr OPTIONS (DROP truncatable); +--Testcase 866: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); +TRUNCATE tru_ftable; -- error +--Testcase 867: +ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'true'); +TRUNCATE tru_ftable; -- accepted + +-- -- partitioned table with both local and foreign tables as partitions +-- SELECT sum(id) FROM tru_ptable; -- 155 +-- TRUNCATE tru_ptable; +-- SELECT count(*) FROM tru_ptable; -- 0 +-- SELECT count(*) FROM tru_ptable__p0; -- 0 +-- SELECT count(*) FROM tru_ftable__p1; -- 0 +-- SELECT count(*) FROM tru_rtable1; -- 0 + +-- 'CASCADE' option +--Testcase 868: +SELECT sum(id) FROM tru_pk_ftable; -- 55 +-- SQLite FDW support TRUNCATE command by executing DELETE statement without WHERE clause. +-- In order to delete records in parent and child table subsequently, +-- SQLite FDW executes "PRAGMA foreign_keys = ON" before executing DELETE statement. +TRUNCATE tru_pk_ftable; -- success +TRUNCATE tru_pk_ftable CASCADE; -- success +--Testcase 869: +SELECT count(*) FROM tru_pk_ftable; -- 0 +--Testcase 870: +SELECT count(*) FROM "S 1".tru_fk_table; -- also truncated,0 + +-- truncate two tables at a command +--Testcase 871: +INSERT INTO tru_ftable (SELECT x FROM generate_series(1,8) x); +--Testcase 872: +INSERT INTO tru_pk_ftable (SELECT x FROM generate_series(3,10) x); +--Testcase 873: +SELECT count(*) from tru_ftable; -- 8 +--Testcase 874: +SELECT count(*) from tru_pk_ftable; -- 8 +TRUNCATE tru_ftable, tru_pk_ftable; +--Testcase 875: +SELECT count(*) from tru_ftable; -- 0 +--Testcase 876: +SELECT count(*) from tru_pk_ftable; -- 0 + +-- truncate with ONLY clause +-- Since ONLY is specified, the table tru_ftable_child that inherits +-- tru_ftable_parent locally is not truncated. +TRUNCATE ONLY tru_ftable_parent; +--Testcase 877: +SELECT sum(id) FROM tru_ftable_parent; -- 126 +TRUNCATE tru_ftable_parent; +--Testcase 878: +SELECT count(*) FROM tru_ftable_parent; -- 0 + +-- -- in case when remote table has inherited children +-- CREATE TABLE tru_rtable0_child () INHERITS (tru_rtable0); +-- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x); +-- INSERT INTO "S 1".tru_rtable0_child (SELECT x FROM generate_series(10,14) x); +-- SELECT sum(id) FROM tru_ftable; -- 95 + +-- -- Both parent and child tables in the foreign server are truncated +-- -- even though ONLY is specified because ONLY has no effect +-- -- when truncating a foreign table. +-- TRUNCATE ONLY tru_ftable; +-- SELECT count(*) FROM tru_ftable; -- 0 + +-- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x); +-- INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x); +-- SELECT sum(id) FROM tru_ftable; -- 255 +-- TRUNCATE tru_ftable; -- truncate both of parent and child +-- SELECT count(*) FROM tru_ftable; -- 0 + +-- cleanup +--Testcase 879: +DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable; +-- DROP TABLE tru_rtable0, tru_rtable1, tru_ptable, tru_ptable__p0, tru_pk_table, tru_fk_table, +-- tru_rtable_parent,tru_rtable_child, tru_rtable0_child; + +-- =================================================================== +-- test IMPORT FOREIGN SCHEMA +-- =================================================================== + +--Testcase 728: +CREATE SCHEMA import_dest1; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; +--Testcase 477: +\det+ import_dest1.* +--Testcase 478: +\d import_dest1.* + +-- Options +--Testcase 729: +CREATE SCHEMA import_dest2; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 + OPTIONS (import_default 'true'); +--Testcase 479: +\det+ import_dest2.* +--Testcase 480: +\d import_dest2.* + +-- Check LIMIT TO and EXCEPT +--Testcase 730: +CREATE SCHEMA import_dest3; +IMPORT FOREIGN SCHEMA public LIMIT TO ("T 1", loct6, nonesuch) + FROM SERVER sqlite_svr INTO import_dest3; +--Testcase 481: +\det+ import_dest3.* +IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) + FROM SERVER sqlite_svr INTO import_dest3; +--Testcase 482: +\det+ import_dest3.* + +-- Assorted error cases +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; +IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO notthere; +IMPORT FOREIGN SCHEMA public FROM SERVER nowhere INTO notthere; + +/* +-- Skip these test, sqlite fdw does not support fetch_size option, partition table +-- Check case of a type present only on the remote server. +-- We can fake this by dropping the type locally in our transaction. +CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue'); +CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors"); + +CREATE SCHEMA import_dest5; +BEGIN; +DROP TYPE "Colors" CASCADE; +IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5) + FROM SERVER loopback INTO import_dest5; -- ERROR + +ROLLBACK; + +BEGIN; + + +CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' ); + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=101']; + +ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' ); + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=101']; + +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'fetch101' +AND srvoptions @> array['fetch_size=202']; + +CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' ); + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=30000']; + +ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000'); + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=30000']; + +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30000'::regclass +AND ftoptions @> array['fetch_size=60000']; + +ROLLBACK; + +-- =================================================================== +-- test partitionwise joins +-- =================================================================== +SET enable_partitionwise_join=on; + +CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a); +CREATE TABLE fprt1_p1 (LIKE fprt1); +CREATE TABLE fprt1_p2 (LIKE fprt1); +ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false'); +ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false'); +INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i; +INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i; +CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250) + SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true'); +CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500) + SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2'); +ANALYZE fprt1; +ANALYZE fprt1_p1; +ANALYZE fprt1_p2; + +CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b); +CREATE TABLE fprt2_p1 (LIKE fprt2); +CREATE TABLE fprt2_p2 (LIKE fprt2); +ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false'); +ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false'); +INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i; +INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i; +CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int) + SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true'); +ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250); +CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500) + SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true'); +ANALYZE fprt2; +ANALYZE fprt2_p1; +ANALYZE fprt2_p2; + +-- inner join three tables +EXPLAIN (COSTS OFF) +SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; +SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; + +-- left outer join + nullable clause +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; +SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; + +-- with whole-row reference; partitionwise join does not apply +EXPLAIN (COSTS OFF) +SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; +SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; + +-- join with lateral reference +EXPLAIN (COSTS OFF) +SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; +SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; + +-- with PHVs, partitionwise join selected but no join pushdown +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; +SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; + +-- test FOR UPDATE; partitionwise join does not apply +EXPLAIN (COSTS OFF) +SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; +SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; + +RESET enable_partitionwise_join; + + +-- =================================================================== +-- test partitionwise aggregates +-- =================================================================== + +CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); + +CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); + +INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; +INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; +INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; + +-- Create foreign partitions +CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); +CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2'); +CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3'); + +ANALYZE pagg_tab; +ANALYZE fpagg_tab_p1; +ANALYZE fpagg_tab_p2; +ANALYZE fpagg_tab_p3; + +-- When GROUP BY clause matches with PARTITION KEY. +-- Plan with partitionwise aggregates is disabled +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Plan with partitionwise aggregates is enabled +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Check with whole-row reference +-- Should have all the columns in the target list for the given relation +EXPLAIN (VERBOSE, COSTS OFF) +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- When GROUP BY clause does not match with PARTITION KEY. +EXPLAIN (COSTS OFF) +SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; +*/ + +/* +-- Skip these tests, sqlite fdw does not support nosuper user. +-- =================================================================== +-- access rights and superuser +-- =================================================================== + +-- Non-superuser cannot create a FDW without a password in the connstr +CREATE ROLE regress_nosuper NOSUPERUSER; + +GRANT USAGE ON FOREIGN DATA WRAPPER sqlite_fdw TO regress_nosuper; + +SET ROLE regress_nosuper; + +SHOW is_superuser; + +-- This will be OK, we can create the FDW +DO $d$ + BEGIN + EXECUTE $$CREATE SERVER sqlite_nopw FOREIGN DATA WRAPPER sqlite_fdw + OPTIONS (database '/tmp/sqlite_fdw_test/post.db')$$; + END; +$d$; + +-- But creation of user mappings for non-superusers should fail +CREATE USER MAPPING FOR public SERVER sqlite_nopw; +CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; + +CREATE FOREIGN TABLE ft1_nopw ( + c1 int OPTIONS (key 'true'), + c2 int NOT NULL, + c3 text, + c4 timestamptz, + c5 timestamp, + c6 varchar(10), + c7 char(10) default 'ft1', + c8 text +) SERVER sqlite_nopw; + +ALTER FOREIGN TABLE ft1_nopw OPTIONS (table 'T 1'); +ALTER FOREIGN TABLE ft1_nopw ALTER COLUMN c1 OPTIONS (column_name 'C 1'); + +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- If we add a password to the connstr it'll fail, because we don't allow passwords +-- in connstrs only in user mappings. + +ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw'); + + +-- If we add a password for our user mapping instead, we should get a different +-- error because the password wasn't actually *used* when we run with trust auth. +-- +-- This won't work with installcheck, but neither will most of the FDW checks. + +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw'); + +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- Unpriv user cannot make the mapping passwordless +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); + + +SELECT 1 FROM ft1_nopw LIMIT 1; + +RESET ROLE; + +-- But the superuser can +ALTER USER MAPPING FOR regress_nosuper SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); + +SET ROLE regress_nosuper; + +-- Should finally work now +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- unpriv user also cannot set sslcert / sslkey on the user mapping +-- first set password_required so we see the right error messages +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (SET password_required 'true'); +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslcert 'foo.crt'); +ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslkey 'foo.key'); + +-- We're done with the role named after a specific user and need to check the +-- changes to the public mapping. +DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; + +-- This will fail again as it'll resolve the user mapping for public, which +-- lacks password_required=false +SELECT 1 FROM ft1_nopw LIMIT 1; + +RESET ROLE; + +-- The user mapping for public is passwordless and lacks the password_required=false +-- mapping option, but will work because the current user is a superuser. +SELECT 1 FROM ft1_nopw LIMIT 1; + +-- cleanup +DROP USER MAPPING FOR public SERVER sqlite_nopw; +DROP OWNED BY regress_nosuper; +DROP ROLE regress_nosuper; + +-- Clean-up +RESET enable_partitionwise_aggregate; +*/ +-- Two-phase transactions are not supported. +BEGIN; +--Testcase 731: +SELECT count(*) FROM ft1; +-- error here +--Testcase 732: +PREPARE TRANSACTION 'fdw_tpc'; +ROLLBACK; + +-- =================================================================== +-- reestablish new connection +-- =================================================================== +-- -- Test case relative with option application_name is not suitable for SQLite FDW. +-- -- Because this option is in libpq of postgres. +-- -- Change application_name of remote connection to special one +-- -- so that we can easily terminate the connection later. +-- ALTER SERVER sqlite_svr OPTIONS (application_name 'fdw_retry_check'); +-- -- Make sure we have a remote connection. +-- SELECT 1 FROM ft1 LIMIT 1; +-- -- Terminate the remote connection and wait for the termination to complete. +-- (If a cache flush happens, the remote connection might have already been +-- dropped; so code this step in a way that doesn't fail if no connection.) +-- DO $$ BEGIN +-- PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity +-- WHERE application_name = 'fdw_retry_check'; +-- END $$; +-- -- This query should detect the broken connection when starting new remote +-- -- transaction, reestablish new connection, and then succeed. +-- BEGIN; +-- SELECT 1 FROM ft1 LIMIT 1; +-- -- If we detect the broken connection when starting a new remote +-- -- subtransaction, we should fail instead of establishing a new connection. +-- -- Terminate the remote connection and wait for the termination to complete. +-- DO $$ BEGIN +-- PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity +-- WHERE application_name = 'fdw_retry_check'; +-- END $$; +-- SAVEPOINT s; +-- -- The text of the error might vary across platforms, so only show SQLSTATE. +-- \set VERBOSITY sqlstate +-- SELECT 1 FROM ft1 LIMIT 1; -- should fail +-- \set VERBOSITY default +-- COMMIT; + +-- ============================================================================= +-- test connection invalidation cases and sqlite_fdw_get_connections function +-- ============================================================================= +-- Let's ensure to close all the existing cached connections. +--Testcase 880: +SELECT 1 FROM sqlite_fdw_disconnect_all(); +-- No cached connections, so no records should be output. +--Testcase 881: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +-- This test case is for closing the connection in sqlitefdw_xact_callback +BEGIN; +-- Connection xact depth becomes 1 i.e. the connection is in midst of the xact. +--Testcase 882: +SELECT 1 FROM ft1 LIMIT 1; +--Testcase 883: +SELECT 1 FROM ft7 LIMIT 1; +-- List all the existing cached connections. sqlite_svr and sqlite_svr3 should be +-- output. +--Testcase 884: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +-- Connections are not closed at the end of the alter and drop statements. +-- That's because the connections are in midst of this xact, +-- they are just marked as invalid in sqlitefdw_inval_callback. +--Testcase 885: +ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); +--Testcase 886: +DROP SERVER sqlite_svr3 CASCADE; +-- List all the existing cached connections. sqlite_svr and sqlite_svr3 +-- should be output as invalid connections. Also the server name for +-- sqlite_svr3 should be NULL because the server was dropped. +--Testcase 887: +SELECT * FROM sqlite_fdw_get_connections() ORDER BY 1; +-- The invalid connections get closed in sqlitefdw_xact_callback during commit. +COMMIT; +--Testcase 888: +ALTER SERVER sqlite_svr OPTIONS (DROP keep_connections); +-- All cached connections were closed while committing above xact, so no +-- records should be output. +--Testcase 889: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + +-- ======================================================================= +-- test sqlite_fdw_disconnect and sqlite_fdw_disconnect_all functions +-- ======================================================================= +BEGIN; +-- Ensure to cache loopback connection. +--Testcase 890: +SELECT 1 FROM ft1 LIMIT 1; +-- Ensure to cache loopback2 connection. +--Testcase 891: +SELECT 1 FROM ft6 LIMIT 1; +-- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be +-- output. +--Testcase 892: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +-- Issue a warning and return false as sqlite_svr connection is still in use and +-- can not be closed. +--Testcase 893: +SELECT sqlite_fdw_disconnect('sqlite_svr'); +-- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be +-- output. +--Testcase 894: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +-- Return false as connections are still in use, warnings are issued. +-- But disable warnings temporarily because the order of them is not stable. +--Testcase 895: +SET client_min_messages = 'ERROR'; +--Testcase 896: +SELECT sqlite_fdw_disconnect_all(); +--Testcase 897: +RESET client_min_messages; +COMMIT; +-- Ensure that sqlite_svr2 connection is closed. +--Testcase 898: +SELECT 1 FROM sqlite_fdw_disconnect('sqlite_svr2'); +--Testcase 899: +SELECT server_name FROM sqlite_fdw_get_connections() WHERE server_name = 'sqlite_svr2'; +-- Return false as sqlite_svr2 connection is closed already. +--Testcase 900: +SELECT sqlite_fdw_disconnect('sqlite_svr2'); +-- Return an error as there is no foreign server with given name. +--Testcase 901: +SELECT sqlite_fdw_disconnect('unknownserver'); +-- Let's ensure to close all the existing cached connections. +--Testcase 902: +SELECT 1 FROM sqlite_fdw_disconnect_all(); +-- No cached connections, so no records should be output. +--Testcase 903: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + +-- ============================================================================= +-- test case for having multiple cached connections for a foreign server +-- SQLite FDW does not support User Mapping, so cached connection is identified +-- by only serverid (not like other FDWs use key including serverid and userid), +-- and there is only one server for all users, so there is only one cached connection. +-- In case of using key including serverid and userid, if many users are used, +-- there will be many cached connections. +-- ============================================================================= +--Testcase 904: +CREATE ROLE regress_multi_conn_user1 SUPERUSER; +--Testcase 905: +CREATE ROLE regress_multi_conn_user2 SUPERUSER; +--Testcase 906: +-- CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +--Testcase 907: +-- CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; + +BEGIN; +-- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 +--Testcase 908: +SET ROLE regress_multi_conn_user1; +--Testcase 909: +SELECT 1 FROM ft1 LIMIT 1; +--Testcase 910: +RESET ROLE; + +-- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user2 +--Testcase 911: +SET ROLE regress_multi_conn_user2; +--Testcase 912: +SELECT 1 FROM ft1 LIMIT 1; +--Testcase 913: +RESET ROLE; + +-- Should output one cached connection for sqlite_svr server +--Testcase 914: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +COMMIT; +-- Let's ensure to close all the existing cached connections. +--Testcase 915: +SELECT 1 FROM sqlite_fdw_disconnect_all(); +-- No cached connections, so no records should be output. +--Testcase 916: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; + +-- Clean up +--Testcase 917: +-- DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; +--Testcase 918: +-- DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; +--Testcase 919: +DROP ROLE regress_multi_conn_user1; +--Testcase 920: +DROP ROLE regress_multi_conn_user2; + +-- =================================================================== +-- Test foreign server level option keep_connections +-- =================================================================== +-- By default, the connections associated with foreign server are cached i.e. +-- keep_connections option is on. Set it to off. +--Testcase 921: +ALTER SERVER sqlite_svr OPTIONS (keep_connections 'off'); +-- connection to sqlite_svr server is closed at the end of xact +-- as keep_connections was set to off. +--Testcase 922: +SELECT 1 FROM ft1 LIMIT 1; +-- No cached connections, so no records should be output. +--Testcase 923: +SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; +--Testcase 924: +ALTER SERVER sqlite_svr OPTIONS (SET keep_connections 'on'); + +-- =================================================================== +-- batch insert +-- =================================================================== + +BEGIN; + +--Testcase 925: +CREATE SERVER batch10 FOREIGN DATA WRAPPER sqlite_fdw OPTIONS( batch_size '10' ); + +--Testcase 926: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=10']; + +--Testcase 927: +ALTER SERVER batch10 OPTIONS( SET batch_size '20' ); + +--Testcase 928: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=10']; + +--Testcase 929: +SELECT count(*) +FROM pg_foreign_server +WHERE srvname = 'batch10' +AND srvoptions @> array['batch_size=20']; + +--Testcase 930: +CREATE FOREIGN TABLE table30 ( x int ) SERVER batch10 OPTIONS ( batch_size '30' ); + +--Testcase 931: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=30']; + +--Testcase 932: +ALTER FOREIGN TABLE table30 OPTIONS ( SET batch_size '40'); + +--Testcase 933: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=30']; + +--Testcase 934: +SELECT COUNT(*) +FROM pg_foreign_table +WHERE ftrelid = 'table30'::regclass +AND ftoptions @> array['batch_size=40']; + +ROLLBACK; + +--Testcase 935: +CREATE FOREIGN TABLE ftable ( x int OPTIONS (key 'true') ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '10' ); +--Testcase 936: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; +--Testcase 937: +INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; +--Testcase 938: +INSERT INTO ftable SELECT * FROM generate_series(11, 31) i; +--Testcase 939: +INSERT INTO ftable VALUES (32); +--Testcase 940: +INSERT INTO ftable VALUES (33), (34); +--Testcase 946: +SELECT COUNT(*) FROM ftable; +--Testcase 947: +DELETE FROM ftable; +--Testcase 948: +DROP FOREIGN TABLE ftable; + +-- Disable batch insert +--Testcase 949: +CREATE FOREIGN TABLE ftable ( x int ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '1' ); +--Testcase 950: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (1), (2); +--Testcase 951: +INSERT INTO ftable VALUES (1), (2); +--Testcase 952: +SELECT COUNT(*) FROM ftable; + +-- Disable batch inserting into foreign tables with BEFORE ROW INSERT triggers +-- even if the batch_size option is enabled. +--Testcase 977: +ALTER FOREIGN TABLE ftable OPTIONS ( SET batch_size '10' ); +--Testcase 978: +CREATE TRIGGER trig_row_before BEFORE INSERT ON ftable +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +--Testcase 980: +EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (3), (4); +--Testcase 981: +INSERT INTO ftable VALUES (3), (4); +--Testcase 982: +SELECT COUNT(*) FROM ftable; + +-- Clean up +--Testcase 983: +DROP TRIGGER trig_row_before ON ftable; +--Testcase 953: +DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; + +-- -- Use partitioning +-- CREATE TABLE batch_table ( x int ) PARTITION BY HASH (x); + +-- CREATE TABLE batch_table_p0 (LIKE batch_table); +-- CREATE FOREIGN TABLE batch_table_p0f + -- PARTITION OF batch_table + -- FOR VALUES WITH (MODULUS 3, REMAINDER 0) + -- SERVER sqlite_svr + -- OPTIONS (table 'batch_table_p0', batch_size '10'); + +-- CREATE TABLE batch_table_p1 (LIKE batch_table); +-- CREATE FOREIGN TABLE batch_table_p1f + -- PARTITION OF batch_table + -- FOR VALUES WITH (MODULUS 3, REMAINDER 1) +-- SERVER sqlite_svr +-- OPTIONS (table 'batch_table_p1', batch_size '1'); + +-- CREATE TABLE batch_table_p2 +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 3, REMAINDER 2); + +-- INSERT INTO "S 1".batch_table SELECT * FROM generate_series(1, 66) i; +-- SELECT COUNT(*) FROM "S 1".batch_table; + +-- -- Clean up +-- DROP TABLE batch_table; +-- DROP TABLE batch_table_p0; +-- DROP TABLE batch_table_p1; + +-- Check that batched mode also works for some inserts made during +-- cross-partition updates +-- CREATE TABLE batch_cp_upd_test (a int) PARTITION BY LIST (a); +-- CREATE TABLE batch_cp_upd_test1 (LIKE batch_cp_upd_test); +-- CREATE FOREIGN TABLE batch_cp_upd_test1_f +-- PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (1) +-- SERVER sqlite_svr +-- OPTIONS (table_name 'batch_cp_upd_test1', batch_size '10'); +-- CREATE TABLE batch_cp_upd_test2 PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (2); +-- CREATE TABLE batch_cp_upd_test3 (LIKE batch_cp_upd_test); +-- CREATE FOREIGN TABLE batch_cp_upd_test3_f +-- PARTITION OF batch_cp_upd_test +-- FOR VALUES IN (3) +-- SERVER loopback +-- OPTIONS (table_name 'batch_cp_upd_test3', batch_size '1'); +-- -- Create statement triggers on remote tables that "log" any INSERTs +-- -- performed on them. +-- CREATE TABLE cmdlog (cmd text); +-- CREATE FUNCTION log_stmt() RETURNS TRIGGER LANGUAGE plpgsql AS $$ +-- BEGIN INSERT INTO public.cmdlog VALUES (TG_OP || ' on ' || TG_RELNAME); RETURN NULL; END; +-- $$; +-- CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test1 +-- FOR EACH STATEMENT EXECUTE FUNCTION log_stmt(); +-- CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test3 +-- FOR EACH STATEMENT EXECUTE FUNCTION log_stmt(); +-- -- This update moves rows from the local partition 'batch_cp_upd_test2' to the +-- -- foreign partition 'batch_cp_upd_test1', one that has insert batching +-- -- enabled, so a single INSERT for both rows. +-- INSERT INTO batch_cp_upd_test VALUES (2), (2); +-- UPDATE batch_cp_upd_test t SET a = 1 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2; +-- -- This one moves rows from the local partition 'batch_cp_upd_test2' to the +-- -- foreign partition 'batch_cp_upd_test2', one that has insert batching +-- -- disabled, so separate INSERTs for the two rows. +-- INSERT INTO batch_cp_upd_test VALUES (2), (2); +-- UPDATE batch_cp_upd_test t SET a = 3 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2; +-- SELECT tableoid::regclass, * FROM batch_cp_upd_test ORDER BY 1; +-- -- Should see 1 INSERT on batch_cp_upd_test1 and 2 on batch_cp_upd_test3 as +-- -- described above. +-- SELECT * FROM cmdlog ORDER BY 1; + +-- -- Clean up +-- DROP TABLE batch_cp_upd_test; +-- DROP TABLE batch_cp_upd_test1; +-- DROP TABLE batch_cp_upd_test3; +-- DROP TABLE cmdlog; +-- DROP FUNCTION log_stmt(); + +-- -- Use partitioning +-- ALTER SERVER loopback OPTIONS (ADD batch_size '10'); + +-- CREATE TABLE batch_table ( x int, field1 text, field2 text) PARTITION BY HASH (x); + +-- CREATE TABLE batch_table_p0 (LIKE batch_table); +-- ALTER TABLE batch_table_p0 ADD CONSTRAINT p0_pkey PRIMARY KEY (x); +-- CREATE FOREIGN TABLE batch_table_p0f +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 2, REMAINDER 0) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table_p0'); + +-- CREATE TABLE batch_table_p1 (LIKE batch_table); +-- ALTER TABLE batch_table_p1 ADD CONSTRAINT p1_pkey PRIMARY KEY (x); +-- CREATE FOREIGN TABLE batch_table_p1f +-- PARTITION OF batch_table +-- FOR VALUES WITH (MODULUS 2, REMAINDER 1) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table_p1'); + +-- INSERT INTO batch_table SELECT i, 'test'||i, 'test'|| i FROM generate_series(1, 50) i; +-- SELECT COUNT(*) FROM batch_table; +-- SELECT * FROM batch_table ORDER BY x; + +-- -- Clean up +-- DROP TABLE batch_table; +-- DROP TABLE batch_table_p0; +-- DROP TABLE batch_table_p1; + +-- ALTER SERVER loopback OPTIONS (DROP batch_size); + +-- Test that pending inserts are handled properly when needed +-- CREATE TABLE batch_table (a text, b int); +-- CREATE FOREIGN TABLE ftable (a text, b int) +-- SERVER loopback +-- OPTIONS (table_name 'batch_table', batch_size '2'); +-- CREATE TABLE ltable (a text, b int); +-- CREATE FUNCTION ftable_rowcount_trigf() RETURNS trigger LANGUAGE plpgsql AS +-- $$ +-- begin +-- raise notice '%: there are % rows in ftable', +-- TG_NAME, (SELECT count(*) FROM ftable); +-- if TG_OP = 'DELETE' then +-- return OLD; +-- else +-- return NEW; +-- end if; +-- end; +-- $$; +-- CREATE TRIGGER ftable_rowcount_trigger +-- BEFORE INSERT OR UPDATE OR DELETE ON ltable +-- FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf(); + +-- WITH t AS ( +-- INSERT INTO ltable VALUES ('AAA', 42), ('BBB', 42) RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; + +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; + +-- WITH t AS ( +-- UPDATE ltable SET b = b + 100 RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; + +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; + +-- WITH t AS ( +-- DELETE FROM ltable RETURNING * +-- ) +-- INSERT INTO ftable SELECT * FROM t; + +-- SELECT * FROM ltable; +-- SELECT * FROM ftable; +-- DELETE FROM ftable; + +-- -- Clean up +-- DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; +-- DROP TRIGGER ftable_rowcount_trigger ON ltable; +-- DROP TABLE ltable; + +-- CREATE TABLE parent (a text, b int) PARTITION BY LIST (a); +-- CREATE TABLE batch_table (a text, b int); +-- CREATE FOREIGN TABLE ftable +-- PARTITION OF parent +-- FOR VALUES IN ('AAA') +-- SERVER loopback +-- OPTIONS (table_name 'batch_table', batch_size '2'); +-- CREATE TABLE ltable +-- PARTITION OF parent +-- FOR VALUES IN ('BBB'); +-- CREATE TRIGGER ftable_rowcount_trigger +-- BEFORE INSERT ON ltable +-- FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf(); + +-- INSERT INTO parent VALUES ('AAA', 42), ('BBB', 42), ('AAA', 42), ('BBB', 42); + +-- SELECT tableoid::regclass, * FROM parent; + +-- -- Clean up +-- DROP FOREIGN TABLE ftable; +-- DROP TABLE batch_table; +-- DROP TRIGGER ftable_rowcount_trigger ON ltable; +-- DROP TABLE ltable; +-- DROP TABLE parent; +-- DROP FUNCTION ftable_rowcount_trigf; + + +-- =================================================================== +-- test asynchronous execution +-- =================================================================== + +-- ALTER SERVER loopback OPTIONS (DROP extensions); +-- ALTER SERVER loopback OPTIONS (ADD async_capable 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD async_capable 'true'); + +-- CREATE TABLE async_pt (a int, b int, c text) PARTITION BY RANGE (a); +-- CREATE TABLE base_tbl1 (a int, b int, c text); +-- CREATE TABLE base_tbl2 (a int, b int, c text); +-- CREATE FOREIGN TABLE async_p1 PARTITION OF async_pt FOR VALUES FROM (1000) TO (2000) +-- SERVER loopback OPTIONS (table_name 'base_tbl1'); +-- CREATE FOREIGN TABLE async_p2 PARTITION OF async_pt FOR VALUES FROM (2000) TO (3000) +-- SERVER loopback2 OPTIONS (table_name 'base_tbl2'); +-- INSERT INTO async_p1 SELECT 1000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- INSERT INTO async_p2 SELECT 2000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; + +-- -- simple queries +-- CREATE TABLE result_tbl (a int, b int, c text); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- -- Test error handling, if accessing one of the foreign partitions errors out +-- CREATE FOREIGN TABLE async_p_broken PARTITION OF async_pt FOR VALUES FROM (10000) TO (10001) +-- SERVER loopback OPTIONS (table_name 'non_existent_table'); +-- SELECT * FROM async_pt; +-- DROP FOREIGN TABLE async_p_broken; + +-- -- Check case where multiple partitions use the same connection +-- CREATE TABLE base_tbl3 (a int, b int, c text); +-- CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000) +-- SERVER loopback2 OPTIONS (table_name 'base_tbl3'); +-- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- DROP FOREIGN TABLE async_p3; +-- DROP TABLE base_tbl3; + +-- -- Check case where the partitioned table has local/remote partitions +-- CREATE TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000); +-- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; +-- ANALYZE async_pt; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- -- partitionwise joins +-- SET enable_partitionwise_join TO true; + +-- CREATE TABLE join_tbl (a1 int, b1 int, c1 text, a2 int, b2 int, c2 text); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; + +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; + +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; + +-- RESET enable_partitionwise_join; + +-- -- Test rescan of an async Append node with do_exec_prune=false +-- SET enable_hashjoin TO false; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; +-- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; + +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; + +-- RESET enable_hashjoin; + +-- -- Test interaction of async execution with plan-time partition pruning +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE a < 3000; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE a < 2000; + +-- -- Test interaction of async execution with run-time partition pruning +-- SET plan_cache_mode TO force_generic_plan; + +-- PREPARE async_pt_query (int, int) AS +-- INSERT INTO result_tbl SELECT * FROM async_pt WHERE a < $1 AND b === $2; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- EXECUTE async_pt_query (3000, 505); +-- EXECUTE async_pt_query (3000, 505); + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- EXECUTE async_pt_query (2000, 505); +-- EXECUTE async_pt_query (2000, 505); + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- RESET plan_cache_mode; + +-- CREATE TABLE local_tbl(a int, b int, c text); +-- INSERT INTO local_tbl VALUES (1505, 505, 'foo'), (2505, 505, 'bar'); +-- ANALYZE local_tbl; + +-- CREATE INDEX base_tbl1_idx ON base_tbl1 (a); +-- CREATE INDEX base_tbl2_idx ON base_tbl2 (a); +-- CREATE INDEX async_p3_idx ON async_p3 (a); +-- ANALYZE base_tbl1; +-- ANALYZE base_tbl2; +-- ANALYZE async_p3; + +-- ALTER FOREIGN TABLE async_p1 OPTIONS (use_remote_estimate 'true'); +-- ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true'); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; +-- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; + +-- ALTER FOREIGN TABLE async_p1 OPTIONS (DROP use_remote_estimate); +-- ALTER FOREIGN TABLE async_p2 OPTIONS (DROP use_remote_estimate); + +-- DROP TABLE local_tbl; +-- DROP INDEX base_tbl1_idx; +-- DROP INDEX base_tbl2_idx; +-- DROP INDEX async_p3_idx; + +-- -- UNION queries +-- SET enable_sort TO off; +-- SET enable_incremental_sort TO off; +-- -- Adjust fdw_startup_cost so that we get an unordered path in the Append. +-- ALTER SERVER loopback2 OPTIONS (ADD fdw_startup_cost '0.00'); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION ALL +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); +-- INSERT INTO result_tbl +-- (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10) +-- UNION ALL +-- (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10); + +-- SELECT * FROM result_tbl ORDER BY a; +-- DELETE FROM result_tbl; + +-- RESET enable_incremental_sort; +-- RESET enable_sort; +-- ALTER SERVER loopback2 OPTIONS (DROP fdw_startup_cost); + +-- -- Disable async execution if we use gating Result nodes for pseudoconstant +-- -- quals +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- (SELECT * FROM async_p1 WHERE CURRENT_USER = SESSION_USER) +-- UNION ALL +-- (SELECT * FROM async_p2 WHERE CURRENT_USER = SESSION_USER); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM ((SELECT * FROM async_p1 WHERE b < 10) UNION ALL (SELECT * FROM async_p2 WHERE b < 10)) s WHERE CURRENT_USER = SESSION_USER; + +-- -- Test that pending requests are processed properly +-- SET enable_mergejoin TO false; +-- SET enable_hashjoin TO false; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; +-- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; + +-- CREATE TABLE local_tbl (a int, b int, c text); +-- INSERT INTO local_tbl VALUES (1505, 505, 'foo'); +-- ANALYZE local_tbl; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; +-- SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; +-- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; + +-- -- Check with foreign modify +-- CREATE TABLE base_tbl3 (a int, b int, c text); +-- CREATE FOREIGN TABLE remote_tbl (a int, b int, c text) +-- SERVER loopback OPTIONS (table_name 'base_tbl3'); +-- INSERT INTO remote_tbl VALUES (2505, 505, 'bar'); + +-- CREATE TABLE base_tbl4 (a int, b int, c text); +-- CREATE FOREIGN TABLE insert_tbl (a int, b int, c text) +-- SERVER loopback OPTIONS (table_name 'base_tbl4'); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); +-- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); + +-- SELECT * FROM insert_tbl ORDER BY a; + +-- -- Check with direct modify +-- EXPLAIN (VERBOSE, COSTS OFF) +-- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) +-- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; +-- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) +-- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; + +-- SELECT * FROM join_tbl ORDER BY a1; +-- DELETE FROM join_tbl; + +-- DROP TABLE local_tbl; +-- DROP FOREIGN TABLE remote_tbl; +-- DROP FOREIGN TABLE insert_tbl; +-- DROP TABLE base_tbl3; +-- DROP TABLE base_tbl4; + +-- RESET enable_mergejoin; +-- RESET enable_hashjoin; + +-- -- Test that UPDATE/DELETE with inherited target works with async_capable enabled +-- EXPLAIN (VERBOSE, COSTS OFF) +-- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; +-- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; +-- EXPLAIN (VERBOSE, COSTS OFF) +-- DELETE FROM async_pt WHERE b = 0 RETURNING *; +-- DELETE FROM async_pt WHERE b = 0 RETURNING *; + +-- -- Check EXPLAIN ANALYZE for a query that scans empty partitions asynchronously +-- DELETE FROM async_p1; +-- DELETE FROM async_p2; +-- DELETE FROM async_p3; + +-- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +-- SELECT * FROM async_pt; + +-- -- Clean up +-- DROP TABLE async_pt; +-- DROP TABLE base_tbl1; +-- DROP TABLE base_tbl2; +-- DROP TABLE result_tbl; +-- DROP TABLE join_tbl; + +-- -- Test that an asynchronous fetch is processed before restarting the scan in +-- -- ReScanForeignScan +-- CREATE TABLE base_tbl (a int, b int); +-- INSERT INTO base_tbl VALUES (1, 11), (2, 22), (3, 33); +-- CREATE FOREIGN TABLE foreign_tbl (b int) +-- SERVER loopback OPTIONS (table_name 'base_tbl'); +-- CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl) +-- SERVER loopback OPTIONS (table_name 'base_tbl'); + +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl); +-- SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl); + +-- -- Clean up +-- DROP FOREIGN TABLE foreign_tbl CASCADE; +-- DROP TABLE base_tbl; + +-- ALTER SERVER loopback OPTIONS (DROP async_capable); +-- ALTER SERVER loopback2 OPTIONS (DROP async_capable); + +-- =================================================================== +-- test invalid server and foreign table options +-- =================================================================== +-- -- Invalid fdw_startup_cost option +-- CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw +-- OPTIONS(fdw_startup_cost '100$%$#$#'); +-- -- Invalid fdw_tuple_cost option +-- CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw +-- OPTIONS(fdw_tuple_cost '100$%$#$#'); +-- -- Invalid fetch_size option +-- CREATE FOREIGN TABLE inv_fsz (c1 int ) +-- SERVER loopback OPTIONS (fetch_size '100$%$#$#'); +-- Invalid batch_size option +--Testcase 954: +CREATE FOREIGN TABLE inv_bsz (c1 int ) + SERVER sqlite_svr OPTIONS (batch_size '100$%$#$#'); + +-- -- No option is allowed to be specified at foreign data wrapper level +-- ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw'); + +-- -- =================================================================== +-- -- test postgres_fdw.application_name GUC +-- -- =================================================================== +-- To avoid race conditions in checking the remote session's application_name, +-- use this view to make the remote session itself read its application_name. +-- CREATE VIEW my_application_name AS +-- SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid(); + +-- CREATE FOREIGN TABLE remote_application_name (application_name text) +-- SERVER loopback2 +-- OPTIONS (schema_name 'public', table_name 'my_application_name'); + +-- SELECT count(*) FROM remote_application_name; + +-- Specify escape sequences in application_name option of a server +-- object so as to test that they are replaced with status information +-- expectedly. Note that we are also relying on ALTER SERVER to force +-- the remote session to be restarted with its new application name. +-- -- Since pg_stat_activity.application_name may be truncated to less than +-- -- NAMEDATALEN characters, note that substring() needs to be used +-- -- at the condition of test query to make sure that the string consisting +-- -- of database name and process ID is also less than that. +-- ALTER SERVER loopback2 OPTIONS (application_name 'fdw_%d%p'); +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_database() || pg_backend_pid() for +-- current_setting('max_identifier_length')::int); + +-- -- postgres_fdw.application_name overrides application_name option +-- -- of a server object if both settings are present. +-- ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_wrong'); +-- SET postgres_fdw.application_name TO 'fdw_%a%u%%'; +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_setting('application_name') || +-- CURRENT_USER || '%' for current_setting('max_identifier_length')::int); +-- RESET postgres_fdw.application_name; + +-- -- Test %c (session ID) and %C (cluster name) escape sequences. +-- ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_%C%c'); +-- SELECT count(*) FROM remote_application_name +-- WHERE application_name = +-- substring('fdw_' || current_setting('cluster_name') || +-- to_hex(trunc(EXTRACT(EPOCH FROM (SELECT backend_start FROM +-- pg_stat_get_activity(pg_backend_pid()))))::integer) || '.' || +-- to_hex(pg_backend_pid()) +-- for current_setting('max_identifier_length')::int); + +-- -- Clean up. +-- DROP FOREIGN TABLE remote_application_name; +-- DROP VIEW my_application_name; + +-- -- =================================================================== +-- -- test parallel commit and parallel abort +-- -- =================================================================== +-- ALTER SERVER loopback OPTIONS (ADD parallel_commit 'true'); +-- ALTER SERVER loopback OPTIONS (ADD parallel_abort 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD parallel_commit 'true'); +-- ALTER SERVER loopback2 OPTIONS (ADD parallel_abort 'true'); + +-- CREATE TABLE ploc1 (f1 int, f2 text); +-- CREATE FOREIGN TABLE prem1 (f1 int, f2 text) +-- SERVER loopback OPTIONS (table_name 'ploc1'); +-- CREATE TABLE ploc2 (f1 int, f2 text); +-- CREATE FOREIGN TABLE prem2 (f1 int, f2 text) +-- SERVER loopback2 OPTIONS (table_name 'ploc2'); + +-- BEGIN; +-- INSERT INTO prem1 VALUES (101, 'foo'); +-- INSERT INTO prem2 VALUES (201, 'bar'); +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; + +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (102, 'foofoo'); +-- INSERT INTO prem2 VALUES (202, 'barbar'); +-- RELEASE SAVEPOINT s; +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; + +-- -- This tests executing DEALLOCATE ALL against foreign servers in parallel +-- -- during pre-commit +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (103, 'baz'); +-- INSERT INTO prem2 VALUES (203, 'qux'); +-- ROLLBACK TO SAVEPOINT s; +-- RELEASE SAVEPOINT s; +-- INSERT INTO prem1 VALUES (104, 'bazbaz'); +-- INSERT INTO prem2 VALUES (204, 'quxqux'); +-- COMMIT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; + +-- BEGIN; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ABORT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; + +-- -- This tests executing DEALLOCATE ALL against foreign servers in parallel +-- -- during post-abort +-- BEGIN; +-- SAVEPOINT s; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ROLLBACK TO SAVEPOINT s; +-- RELEASE SAVEPOINT s; +-- INSERT INTO prem1 VALUES (105, 'test1'); +-- INSERT INTO prem2 VALUES (205, 'test2'); +-- ABORT; +-- SELECT * FROM prem1; +-- SELECT * FROM prem2; + +-- ALTER SERVER loopback OPTIONS (DROP parallel_commit); +-- ALTER SERVER loopback OPTIONS (DROP parallel_abort); +-- ALTER SERVER loopback2 OPTIONS (DROP parallel_commit); +-- ALTER SERVER loopback2 OPTIONS (DROP parallel_abort); + +-- -- =================================================================== +-- -- test for ANALYZE sampling +-- -- =================================================================== + +-- CREATE TABLE analyze_table (id int, a text, b bigint); + +-- CREATE FOREIGN TABLE analyze_ftable (id int, a text, b bigint) +-- SERVER loopback OPTIONS (table_name 'analyze_rtable1'); + +-- INSERT INTO analyze_table (SELECT x FROM generate_series(1,1000) x); +-- ANALYZE analyze_table; + +-- SET default_statistics_target = 10; +-- ANALYZE analyze_table; + +-- ALTER SERVER loopback OPTIONS (analyze_sampling 'invalid'); + +-- ALTER SERVER loopback OPTIONS (analyze_sampling 'auto'); +-- ANALYZE analyze_table; + +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'system'); +-- ANALYZE analyze_table; + +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'bernoulli'); +-- ANALYZE analyze_table; + +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'random'); +-- ANALYZE analyze_table; + +-- ALTER SERVER loopback OPTIONS (SET analyze_sampling 'off'); +-- ANALYZE analyze_table; +-- cleanup +-- DROP FOREIGN TABLE analyze_ftable; +-- DROP TABLE analyze_table; + +-- SQLite FDW does not support query cancel feature +-- SELECT version() ~ 'cygwin' AS skip_test \gset +-- \if :skip_test +-- \quit +-- \endif + +-- -- Let's test canceling a remote query. Use a table that does not have +-- -- remote_estimate enabled, else there will be multiple queries to the +-- -- remote and we might unluckily send the cancel in between two of them. +-- -- First let's confirm that the query is actually pushed down. +-- EXPLAIN (VERBOSE, COSTS OFF) +-- SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; + +-- BEGIN; +-- -- Make sure that connection is open and set up. +-- SELECT count(*) FROM ft1 a; +-- -- Timeout needs to be long enough to be sure that we've sent the slow query. +-- SET LOCAL statement_timeout = '100ms'; +-- -- This would take very long if not canceled: +-- SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; +-- COMMIT; + +-- Clean-up +--Testcase 733: +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; +--Testcase 734: +-- DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; +--Testcase 735: +DROP SERVER sqlite_svr CASCADE; +--Testcase 736: +DROP SERVER sqlite_svr2 CASCADE; +--Testcase 737: +DROP EXTENSION sqlite_fdw CASCADE; diff --git a/sql/16.0/extra/timestamp.sql b/sql/17.0/extra/timestamp.sql similarity index 65% rename from sql/16.0/extra/timestamp.sql rename to sql/17.0/extra/timestamp.sql index 4e7bba12..d8bd778e 100644 --- a/sql/16.0/extra/timestamp.sql +++ b/sql/17.0/extra/timestamp.sql @@ -161,10 +161,104 @@ explain (verbose, costs off) SELECT * FROM dates1 WHERE date_as_number > (('2020-05-10 10:45:29')::timestamp); +-- test arithmetic with infinite timestamps +--Testcase 39: +CREATE FOREIGN TABLE inf_timestamp ( + t1 TIMESTAMP , + t2 TIMESTAMP, + id int OPTIONS (key 'true')) +SERVER sqlite_svr OPTIONS (table 'infinite_timestamp');; + +--Testcase 40: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, 'infinity'::timestamp); +--Testcase 41: +SELECT t1 - t2 FROM inf_timestamp; + +--Testcase 42: +DELETE FROM inf_timestamp; +--Testcase 43: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '-infinity'::timestamp); +--Testcase 44: +SELECT t1 - t2 FROM inf_timestamp; + +--Testcase 45: +DELETE FROM inf_timestamp; +--Testcase 46: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, 'infinity'::timestamp); +--Testcase 47: +SELECT t1 - t2 FROM inf_timestamp; + +--Testcase 48: +DELETE FROM inf_timestamp; +--Testcase 49: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '-infinity'::timestamp); +--Testcase 50: +SELECT t1 - t2 FROM inf_timestamp; + +--Testcase 51: +DELETE FROM inf_timestamp; +--Testcase 52: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '1995-08-06 12:12:12'::timestamp); +--Testcase 53: +SELECT t1 - t2 FROM inf_timestamp; + +--Testcase 54: +DELETE FROM inf_timestamp; +--Testcase 55: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '1995-08-06 12:12:12'::timestamp); +--Testcase 56: +SELECT t1 - t2 FROM inf_timestamp; + +-- test age() with infinite timestamps +--Testcase 58: +DELETE FROM inf_timestamp; +--Testcase 59: +INSERT INTO inf_timestamp(t1) VALUES ('infinity'::timestamp); +--Testcase 60: +SELECT age(t1) FROM inf_timestamp; + +--Testcase 61: +DELETE FROM inf_timestamp; +--Testcase 62: +INSERT INTO inf_timestamp(t1) VALUES ('-infinity'::timestamp); +--Testcase 63: +SELECT age(t1) FROM inf_timestamp; + +--Testcase 64: +DELETE FROM inf_timestamp; +--Testcase 65: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, 'infinity':: timestamp); +--Testcase 66: +SELECT age(t1, t2) FROM inf_timestamp; + +--Testcase 67: +DELETE FROM inf_timestamp; +--Testcase 68: +INSERT INTO inf_timestamp VALUES ('infinity'::timestamp, '-infinity':: timestamp); +--Testcase 69: +SELECT age(t1, t2) FROM inf_timestamp; + +--Testcase 70: +DELETE FROM inf_timestamp; +--Testcase 71: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, 'infinity':: timestamp); +--Testcase 72: +SELECT age(t1, t2) FROM inf_timestamp; + +--Testcase 73: +DELETE FROM inf_timestamp; +--Testcase 74: +INSERT INTO inf_timestamp VALUES ('-infinity'::timestamp, '-infinity':: timestamp); +--Testcase 75: +SELECT age(t1, t2) FROM inf_timestamp; + --Testcase 35: DROP FOREIGN TABLE dates1; --Testcase 36: DROP FOREIGN TABLE dates2; + +--Testcase 57: +DROP FOREIGN TABLE inf_timestamp; --Testcase 37: DROP SERVER sqlite_svr; --Testcase 38: diff --git a/sql/13.12/extra/update.sql b/sql/17.0/extra/update.sql similarity index 91% rename from sql/13.12/extra/update.sql rename to sql/17.0/extra/update.sql index 26fa665a..e44de435 100644 --- a/sql/13.12/extra/update.sql +++ b/sql/17.0/extra/update.sql @@ -49,6 +49,10 @@ UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10; --Testcase 9: SELECT * FROM update_test; +-- error, you're not supposed to qualify the target column +--Testcase 41: +UPDATE update_test t SET t.b = t.b + 10 WHERE t.a = 10; + -- -- Test VALUES in FROM -- @@ -144,17 +148,17 @@ SELECT a, b, char_length(c) FROM update_test; /* Skip, sqlite fdw does not support ON CONFLICT DO UPDATE -- Test ON CONFLICT DO UPDATE -INSERT INTO upsert_test VALUES(1, 'Boo'); +INSERT INTO upsert_test VALUES(1, 'Boo'), (3, 'Zoo'); -- uncorrelated sub-select: WITH aaa AS (SELECT 1 AS a, 'Foo' AS b) INSERT INTO upsert_test VALUES (1, 'Bar') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b, a FROM aaa) RETURNING *; -- correlated sub-select: -INSERT INTO upsert_test VALUES (1, 'Baz') ON CONFLICT(a) +INSERT INTO upsert_test VALUES (1, 'Baz'), (3, 'Zaz') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b || ', Correlated', a from upsert_test i WHERE i.a = upsert_test.a) RETURNING *; -- correlated sub-select (EXCLUDED.* alias): -INSERT INTO upsert_test VALUES (1, 'Bat') ON CONFLICT(a) +INSERT INTO upsert_test VALUES (1, 'Bat'), (3, 'Zot') ON CONFLICT(a) DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) RETURNING *; @@ -176,6 +180,29 @@ DROP FOREIGN TABLE upsert_test; */ /*Skip, sqlite fdw does not support create partition table +-- Test ON CONFLICT DO UPDATE with partitioned table and non-identical children + +CREATE TABLE upsert_test ( + a INT PRIMARY KEY, + b TEXT +) PARTITION BY LIST (a); + +CREATE TABLE upsert_test_1 PARTITION OF upsert_test FOR VALUES IN (1); +CREATE TABLE upsert_test_2 (b TEXT, a INT PRIMARY KEY); +ALTER TABLE upsert_test ATTACH PARTITION upsert_test_2 FOR VALUES IN (2); + +INSERT INTO upsert_test VALUES(1, 'Boo'), (2, 'Zoo'); +-- uncorrelated sub-select: +WITH aaa AS (SELECT 1 AS a, 'Foo' AS b) INSERT INTO upsert_test + VALUES (1, 'Bar') ON CONFLICT(a) + DO UPDATE SET (b, a) = (SELECT b, a FROM aaa) RETURNING *; +-- correlated sub-select: +WITH aaa AS (SELECT 1 AS ctea, ' Foo' AS cteb) INSERT INTO upsert_test + VALUES (1, 'Bar'), (2, 'Baz') ON CONFLICT(a) + DO UPDATE SET (b, a) = (SELECT upsert_test.b||cteb, upsert_test.a FROM aaa) RETURNING *; + +DROP TABLE upsert_test; + --------------------------- -- UPDATE with row movement --------------------------- @@ -547,6 +574,37 @@ UPDATE list_default set a = 'x' WHERE a = 'd'; DROP TABLE list_parted; +-- Test retrieval of system columns with non-consistent partition row types. +-- This is only partially supported, as seen in the results. + +create table utrtest (a int, b text) partition by list (a); +create table utr1 (a int check (a in (1)), q text, b text); +create table utr2 (a int check (a in (2)), b text); +alter table utr1 drop column q; +alter table utrtest attach partition utr1 for values in (1); +alter table utrtest attach partition utr2 for values in (2); + +insert into utrtest values (1, 'foo') + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; +insert into utrtest values (2, 'bar') + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; -- fails +insert into utrtest values (2, 'bar') + returning *, tableoid::regclass; + +update utrtest set b = b || b from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; + +update utrtest set a = 3 - a from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass, xmin = pg_current_xact_id()::xid as xmin_ok; -- fails + +update utrtest set a = 3 - a from (values (1), (2)) s(x) where a = s.x + returning *, tableoid::regclass; + +delete from utrtest + returning *, tableoid::regclass, xmax = pg_current_xact_id()::xid as xmax_ok; + +drop table utrtest; + -------------- -- Some more update-partition-key test scenarios below. This time use list -- partitions. diff --git a/sql/16.0/extra/uuid.sql b/sql/17.0/extra/uuid.sql similarity index 100% rename from sql/16.0/extra/uuid.sql rename to sql/17.0/extra/uuid.sql diff --git a/sql/16.0/selectfunc.sql b/sql/17.0/selectfunc.sql similarity index 100% rename from sql/16.0/selectfunc.sql rename to sql/17.0/selectfunc.sql diff --git a/sql/12.16/sqlite_fdw.sql b/sql/17.0/sqlite_fdw.sql similarity index 97% rename from sql/12.16/sqlite_fdw.sql rename to sql/17.0/sqlite_fdw.sql index 3158a65e..546df95a 100644 --- a/sql/12.16/sqlite_fdw.sql +++ b/sql/17.0/sqlite_fdw.sql @@ -17,8 +17,7 @@ CREATE FOREIGN TABLE numbers(a int OPTIONS (key 'true'), b varchar(255)) SERVER CREATE FOREIGN TABLE multiprimary(a int, b int OPTIONS (key 'true'), c int OPTIONS(key 'true')) SERVER sqlite_svr; --Testcase 136: CREATE FOREIGN TABLE noprimary(a int, b text) SERVER sqlite_svr; - --- updatable option test (github pull 59) +--Testcase 137: CREATE FOREIGN TABLE RO_RW_test(i int OPTIONS (key 'true'), a text, b float, c int) SERVER sqlite_svr; --Testcase 1: @@ -483,13 +482,6 @@ SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND le --Testcase 114: EXPLAIN (verbose, costs off) SELECT b, length(b) FROM numbers WHERE length(b) = 4 AND power(1, a) != 0 AND length(reverse(b)) = 4; --- Aggregates in subquery are pushed down. ---Testcase 214: -explain (verbose, costs off) -select count(x.a), sum(x.a) from (select a a, sum(a) b from numbers group by a, abs(a) order by 1, 2) x; ---Testcase 215: -select count(x.a), sum(x.a) from (select a a, sum(a) b from numbers group by a, abs(a) order by 1, 2) x; - --Testcase 115: INSERT INTO multiprimary (b,c) VALUES (99, 100); --Testcase 116: @@ -499,9 +491,11 @@ SELECT c FROM multiprimary WHERE COALESCE(a,b,c) = 99; CREATE FOREIGN TABLE multiprimary2(a int, b int, c int OPTIONS(column_name 'b')) SERVER sqlite_svr OPTIONS (table 'multiprimary'); --Testcase 117: SELECT * FROM multiprimary2; +--Testcase 214: ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN a OPTIONS(ADD column_name 'b'); --Testcase 118: SELECT * FROM multiprimary2; +--Testcase 215: ALTER FOREIGN TABLE multiprimary2 ALTER COLUMN b OPTIONS (column_name 'nosuch column'); --Testcase 119: SELECT * FROM multiprimary2; @@ -574,6 +568,29 @@ SELECT * FROM noprimary where b in ('Test''s', 'Test'); --Testcase 242: SELECT * FROM noprimary where b in ('Test''s', 'Test'); +-- INSERT/UPDATE whole row with generated column +--Testcase 216: +CREATE FOREIGN TABLE grem1_1 ( + a int generated always as (0) stored) + SERVER sqlite_svr OPTIONS(table 'grem1_1'); + +--Testcase 217: +INSERT INTO grem1_1 DEFAULT VALUES; +--Testcase 218: +SELECT * FROM grem1_1; + +--Testcase 219: +CREATE FOREIGN TABLE grem1_2 ( + a int generated always as (0) stored, + b int generated always as (1) stored, + c int generated always as (2) stored, + d int generated always as (3) stored) + SERVER sqlite_svr OPTIONS(table 'grem1_2'); +--Testcase 220: +INSERT INTO grem1_2 DEFAULT VALUES; +--Testcase 221: +SELECT * FROM grem1_2; + -- Executable test case for pushdown CASE expressions (results) --Testcase 224: CREATE FOREIGN TABLE case_exp(c1 int OPTIONS (key 'true'), c3 text, c6 varchar(10)) SERVER sqlite_svr; @@ -1007,6 +1024,10 @@ DROP FOREIGN TABLE columntest; DROP FOREIGN TABLE noprimary; --Testcase 161: DROP FOREIGN TABLE fts_table; +--Testcase 222: +DROP FOREIGN TABLE grem1_1; +--Testcase 223: +DROP FOREIGN TABLE grem1_2; --Testcase 235: DROP FOREIGN TABLE case_exp; diff --git a/sql/12.16/type.sql b/sql/17.0/type.sql similarity index 94% rename from sql/12.16/type.sql rename to sql/17.0/type.sql index a438b6c4..e9e2fbe4 100644 --- a/sql/12.16/type.sql +++ b/sql/17.0/type.sql @@ -141,7 +141,34 @@ DELETE FROM type_JSON; --Testcase 62: DROP FOREIGN TABLE IF EXISTS "type_BOOLEAN"; --Testcase 63: -CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean) SERVER sqlite_svr; +CREATE FOREIGN TABLE "type_BOOLEAN" (i int, b boolean OPTIONS (key 'true')) SERVER sqlite_svr; +--Testcase 108: +INSERT INTO "type_BOOLEAN"(i, b) VALUES + (1, TRUE), + (2, FALSE), + (3, TRUE), + (4, FALSE), + (5, true), + (6, false), + (7, 'Yes'), + (8, 'YeS'), + (9, 'yes'), + (10, 'no'), + (11, 'No'), + (12, 'nO'), + (13, 'off'), + (14, 'oFf'), + (15, 'on'), + (16, 'ON'), + (17, 't'), + (18, 'T'), + (19, 'Y'), + (20, 'y'), + (21, 'F'), + (22, 'f'), + (24, '0'), + (25, '1'), + (26, NULL); --Testcase 64: ALTER FOREIGN TABLE "type_BOOLEAN" DROP COLUMN i; --Testcase 65: diff --git a/sql/init_data/init.sql b/sql/init_data/init.sql index 2498862a..c1c93a80 100644 --- a/sql/init_data/init.sql +++ b/sql/init_data/init.sql @@ -60,7 +60,7 @@ CREATE TABLE "A a" (col int primary key); -- test for issue #44 github CREATE VIRTUAL TABLE fts_table USING fts5(name, description, tokenize = porter); --- github.com/pull/59 +-- updatable option test (github pull 59) CREATE TABLE RO_RW_test ( i int primary key not null, a text, diff --git a/sql/init_data/init_core.sql b/sql/init_data/init_core.sql index ca5e8f14..99760ce1 100644 --- a/sql/init_data/init_core.sql +++ b/sql/init_data/init_core.sql @@ -15,6 +15,8 @@ DROP TABLE IF EXISTS test_having; DROP TABLE IF EXISTS onek; DROP TABLE IF EXISTS tenk1; DROP TABLE IF EXISTS btg; +DROP TABLE IF EXISTS btg_groupby; +DROP TABLE IF EXISTS group_agg_pk; DROP TABLE IF EXISTS num_typemod_test; DROP TABLE IF EXISTS t; DROP TABLE IF EXISTS RO_RW_test; @@ -164,6 +166,8 @@ CREATE TABLE dates ( ); CREATE TABLE btg(id int primary key, p int, v text, c float, d float, e int); +CREATE TABLE btg_groupby(x int, y int, z text, w int); +CREATE TABLE group_agg_pk (x int, y int, z int, w int, f int); .separator "\t" .import /tmp/sqlite_fdw_test/onek.data onek @@ -228,6 +232,8 @@ create table agg_t18 (inner_c int); create table agg_t19 (outer_c int); create table agg_t20 (x text); create table agg_t21 (x int); +create table agg_t22 (c1 text, id int); +create table agg_t23 (id int); CREATE TABLE float_tb(f real); -- multi-arg aggs @@ -431,9 +437,18 @@ CREATE TABLE update_test ( ); create table upsert_test (a int primary key, b text); + create table t (a int unique); +create table tbl_ra(a int unique, b int); CREATE TABLE "type_FLOAT_INF" (i int primary key, f float); CREATE VIEW "type_FLOAT_INF+" AS SELECT *, typeof("f") t, length("f") l FROM "type_FLOAT_INF"; -- In PostgreSQL some of this valus causes error but is infinity representation in SQLite INSERT INTO "type_FLOAT_INF" VALUES (1, -1e999),(2, 1e999),(3, -9e999),(4, 9e999),(5,-1e308),(6, 0),(7, 1e308); + +-- FOR timestamp.sql +CREATE TABLE infinite_timestamp ( + t1 TIMESTAMP, + t2 TIMESTAMP, + id integer primary key autoincrement +); diff --git a/sql/init_data/init_post.sql b/sql/init_data/init_post.sql index 8825ca7c..0bb1f32f 100644 --- a/sql/init_data/init_post.sql +++ b/sql/init_data/init_post.sql @@ -27,6 +27,8 @@ DROP TABLE IF EXISTS tru_rtable_parent; DROP TABLE IF EXISTS tru_rtable_child; DROP TABLE IF EXISTS loct_empty; DROP TABLE IF EXISTS batch_table; +DROP TABLE IF EXISTS loct1_rescan; +DROP TABLE IF EXISTS loct2_rescan; CREATE TABLE "T 0" ( "C 1" int, @@ -86,6 +88,9 @@ create table foreign_tbl (a int primary key, b int); create table grem1 (a int primary key, b int); create table grem1_post14 (a int primary key, b int generated always as (a * 2) stored); +create table loct1_rescan (c1 int); +create table loct2_rescan (c1 int, c2 text); + CREATE TABLE t1_constraint ( c1 int primary key, c2 int NOT NULL check (c2 >= 0), diff --git a/sqlite_fdw.c b/sqlite_fdw.c index 1a3fc760..8f8ee101 100644 --- a/sqlite_fdw.c +++ b/sqlite_fdw.c @@ -74,7 +74,11 @@ PG_MODULE_MAGIC; #define DEFAULT_FDW_STARTUP_COST 100.0 /* Default CPU cost to process 1 row (above and beyond cpu_tuple_cost). */ -#define DEFAULT_FDW_TUPLE_COST 0.01 +#if PG_VERSION_NUM >= 170000 +#define DEFAULT_FDW_TUPLE_COST 0.2 +#else +#define DEFAULT_FDW_TUPLE_COST 0.01 +#endif /* If no remote estimates, assume a sort costs 20% extra */ #define DEFAULT_FDW_SORT_MULTIPLIER 1.2 @@ -91,7 +95,7 @@ enum FdwPathPrivateIndex /* has-final-sort flag (as an integer Value node) */ FdwPathPrivateHasFinalSort, /* has-limit flag (as an integer Value node) */ - FdwPathPrivateHasLimit + FdwPathPrivateHasLimit, }; /* @@ -118,7 +122,7 @@ enum FdwScanPrivateIndex * String describing join i.e. names of relations being joined and types * of join, added when the scan is join */ - FdwScanPrivateRelations + FdwScanPrivateRelations, }; /* @@ -138,7 +142,7 @@ enum FdwModifyPrivateIndex /* Integer list of target attribute numbers for INSERT/UPDATE */ FdwModifyPrivateTargetAttnums, /* Length till the end of VALUES clause (as an Integer node) */ - FdwModifyPrivateLen + FdwModifyPrivateLen, }; /* @@ -159,7 +163,7 @@ enum FdwDirectModifyPrivateIndex /* Integer list of attribute numbers retrieved by RETURNING */ FdwDirectModifyPrivateRetrievedAttrs, /* set-processed flag (as a Boolean node) */ - FdwDirectModifyPrivateSetProcessed + FdwDirectModifyPrivateSetProcessed, }; extern PGDLLEXPORT Datum sqlite_fdw_handler(PG_FUNCTION_ARGS); @@ -351,13 +355,6 @@ static void sqlite_add_foreign_final_paths(PlannerInfo *root, ,FinalPathExtraData *extra #endif ); - -static void sqlite_get_remote_estimate(const char *sql, - sqlite3 * conn, - double *rows, - int *width, - Cost *startup_cost, - Cost *total_cost); static void sqlite_estimate_path_cost_size(PlannerInfo *root, RelOptInfo *foreignrel, List *param_join_conds, @@ -368,6 +365,12 @@ static void sqlite_estimate_path_cost_size(PlannerInfo *root, static bool sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinPathExtraData *extra); +#if PG_VERSION_NUM >= 170000 +static bool sqlite_semijoin_target_ok(PlannerInfo *root, + RelOptInfo *joinrel, + RelOptInfo *outerrel, + RelOptInfo *innerrel); +#endif static void sqlite_adjust_foreign_grouping_path_cost(PlannerInfo *root, List *pathkeys, double retrieved_rows, @@ -375,12 +378,14 @@ static void sqlite_adjust_foreign_grouping_path_cost(PlannerInfo *root, double limit_tuples, Cost *p_startup_cost, Cost *p_run_cost); -static bool sqlite_ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel, - EquivalenceClass *ec, EquivalenceMember *em, - void *arg); static bool sqlite_all_baserels_are_foreign(PlannerInfo *root); -static void sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List *fdw_private, Path *epq_path); +static void sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List *fdw_private, + Path *epq_path +#if PG_VERSION_NUM >= 170000 + , List *restrictlist +#endif +); static List *sqlite_get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel); #if PG_VERSION_NUM >= 140000 @@ -392,13 +397,6 @@ const char* sqlite_datatype(int t); static const char *azType[] = { "?", "integer", "real", "text", "blob", "null" }; -/* Callback argument for sqlite_ec_member_matches_foreign */ -typedef struct -{ - Expr *current; /* current expr, or NULL if not yet found */ - List *already_used; /* expressions already dealt with */ -} ec_member_foreign_arg; - /* * Identify the attribute where data conversion fails. */ @@ -529,9 +527,6 @@ sqliteGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntable { SqliteFdwRelationInfo *fpinfo; ListCell *lc; -#if PG_VERSION_NUM < 160000 - RangeTblEntry *rte = planner_rt_fetch(baserel->relid, root); -#endif elog(DEBUG1, "sqlite_fdw : %s", __func__); @@ -545,33 +540,11 @@ sqliteGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntable fpinfo->server = GetForeignServer(fpinfo->table->serverid); /* - * Extract user-settable option values. Note that per-table setting of - * use_remote_estimate overrides per-server setting. + * Extract user-settable option values. */ - fpinfo->use_remote_estimate = false; fpinfo->fdw_startup_cost = DEFAULT_FDW_STARTUP_COST; fpinfo->fdw_tuple_cost = DEFAULT_FDW_TUPLE_COST; - /* - * If the table or the server is configured to use remote estimates, - * identify which user to do remote access as during planning. - * This should match what ExecCheckPermissions() does (ExecCheckRTEPerms() for older version). - * If we fail due to lack of permissions, the query would have failed at runtime anyway. - */ - if (fpinfo->use_remote_estimate) - { -#if (PG_VERSION_NUM < 160000) - Oid userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); -#else - Oid userid; - userid = OidIsValid(baserel->userid) ? baserel->userid : GetUserId(); -#endif - - fpinfo->user = GetUserMapping(userid, fpinfo->server->serverid); - } - else - fpinfo->user = NULL; - /* * Identify which baserestrictinfo clauses can be sent to the remote * server and which can't. @@ -621,60 +594,36 @@ sqliteGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntable fpinfo->rel_total_cost = -1; /* - * If the table or the server is configured to use remote estimates, - * connect to the foreign server and execute EXPLAIN to estimate the - * number of rows selected by the restriction clauses, as well as the - * average row width. Otherwise, estimate using whatever statistics we - * have locally, in a way similar to ordinary tables. + * If the foreign table has never been ANALYZEd, it will have relpages + * and reltuples equal to zero, which most likely has nothing to do + * with reality. We can't do a whole lot about that if we're not + * allowed to consult the remote server, but we can use a hack similar + * to plancat.c's treatment of empty relations: use a minimum size + * estimate of 10 pages, and divide by the column-datatype-based width + * estimate to get the corresponding number of tuples. */ - if (fpinfo->use_remote_estimate) - { - /* - * Get cost/size estimates with help of remote server. Save the - * values in fpinfo so we don't need to do it again to generate the - * basic foreign path. - */ - sqlite_estimate_path_cost_size(root, baserel, NIL, NIL, NULL, - &fpinfo->rows, &fpinfo->width, - &fpinfo->startup_cost, &fpinfo->total_cost); - /* Report estimated baserel size to planner. */ - baserel->rows = fpinfo->rows; - baserel->reltarget->width = fpinfo->width; - } - else - { - /* - * If the foreign table has never been ANALYZEd, it will have relpages - * and reltuples equal to zero, which most likely has nothing to do - * with reality. We can't do a whole lot about that if we're not - * allowed to consult the remote server, but we can use a hack similar - * to plancat.c's treatment of empty relations: use a minimum size - * estimate of 10 pages, and divide by the column-datatype-based width - * estimate to get the corresponding number of tuples. - */ #if (PG_VERSION_NUM >= 140000) - if (baserel->tuples < 0) + if (baserel->tuples < 0) #else - if (baserel->pages == 0 && baserel->tuples == 0) + if (baserel->pages == 0 && baserel->tuples == 0) #endif - { - baserel->pages = 10; - baserel->tuples = - (10 * BLCKSZ) / (baserel->reltarget->width + - MAXALIGN(SizeofHeapTupleHeader)); - } + { + baserel->pages = 10; + baserel->tuples = + (10 * BLCKSZ) / (baserel->reltarget->width + + MAXALIGN(SizeofHeapTupleHeader)); + } - /* - * Estimate baserel size as best we can with local statistics. - */ - set_baserel_size_estimates(root, baserel); + /* + * Estimate baserel size as best we can with local statistics. + */ + set_baserel_size_estimates(root, baserel); - /* Fill in basically-bogus cost estimates for use later. */ - sqlite_estimate_path_cost_size(root, baserel, NIL, NIL, NULL, - &fpinfo->rows, &fpinfo->width, - &fpinfo->startup_cost, &fpinfo->total_cost); - } + /* Fill in basically-bogus cost estimates for use later. */ + sqlite_estimate_path_cost_size(root, baserel, NIL, NIL, NULL, + &fpinfo->rows, &fpinfo->width, + &fpinfo->startup_cost, &fpinfo->total_cost); /* * Set the name of relation in fpinfo, while we are constructing it here. @@ -688,6 +637,9 @@ sqliteGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntable fpinfo->make_outerrel_subquery = false; fpinfo->make_innerrel_subquery = false; fpinfo->lower_subquery_rels = NULL; +#if PG_VERSION_NUM >= 170000 + fpinfo->hidden_subquery_rels = NULL; +#endif /* Set the relation index. */ fpinfo->relation_index = baserel->relid; } @@ -745,7 +697,12 @@ sqlite_get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel) } static void -sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List *fdw_private, Path *epq_path) +sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List *fdw_private, + Path *epq_path +#if PG_VERSION_NUM >= 170000 + , List *restrictlist +#endif +) { List *useful_pathkeys_list = NIL; /* List of all pathkeys */ ListCell *lc; @@ -845,6 +802,10 @@ sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List NULL, /* no outer rel either */ #endif sorted_epq_path, +#if PG_VERSION_NUM >= 170000 + NIL, /* no fdw_restrictinfo + * list */ +#endif fdw_private)); else add_path(rel, (Path *) @@ -864,6 +825,9 @@ sqlite_add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, List NULL, /* no outer rel either */ #endif sorted_epq_path, +#if PG_VERSION_NUM >= 170000 + restrictlist, +#endif fdw_private)); } } @@ -915,10 +879,6 @@ sqlite_all_baserels_are_foreign(PlannerInfo *root) static void sqliteGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) { - SqliteFdwRelationInfo *fpinfo = (SqliteFdwRelationInfo *) baserel->fdw_private; - ForeignPath *path; - List *ppi_list; - ListCell *lc; Cost startup_cost = 10; Cost total_cost = baserel->rows + startup_cost; List *fdw_private = NIL; @@ -958,192 +918,18 @@ sqliteGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid #else NULL, /* no outer rel either */ #endif - NULL, /* no extra plan */ + NULL, /* no extra plan */ +#if PG_VERSION_NUM >= 170000 + NIL, /* no fdw_restrictinfo list */ +#endif fdw_private)); /* Add paths with pathkeys */ - sqlite_add_paths_with_pathkeys_for_rel(root, baserel, fdw_private, NULL); - - /* - * If we're not using remote estimates, stop here. We have no way to - * estimate whether any join clauses would be worth sending across, so - * don't bother building parameterized paths. - */ - if (!fpinfo->use_remote_estimate) - return; - - /* - * Thumb through all join clauses for the rel to identify which outer - * relations could supply one or more safe-to-send-to-remote join clauses. - * We'll build a parameterized path for each such outer relation. - * - * It's convenient to manage this by representing each candidate outer - * relation by the ParamPathInfo node for it. We can then use the - * ppi_clauses list in the ParamPathInfo node directly as a list of the - * interesting join clauses for that rel. This takes care of the - * possibility that there are multiple safe join clauses for such a rel, - * and also ensures that we account for unsafe join clauses that we'll - * still have to enforce locally (since the parameterized-path machinery - * insists that we handle all movable clauses). - */ - ppi_list = NIL; - foreach(lc, baserel->joininfo) - { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); - Relids required_outer; - ParamPathInfo *param_info; - - /* Check if clause can be moved to this rel */ - if (!join_clause_is_movable_to(rinfo, baserel)) - continue; - - /* See if it is safe to send to remote */ - if (!sqlite_is_foreign_expr(root, baserel, rinfo->clause)) - continue; - - /* Calculate required outer rels for the resulting path */ - required_outer = bms_union(rinfo->clause_relids, - baserel->lateral_relids); - - /* - * We do not want the foreign rel itself listed in required_outer - */ - required_outer = bms_del_member(required_outer, baserel->relid); - - /* - * required_outer probably can't be empty here, but if it were, we - * couldn't make a parameterized path. - */ - if (bms_is_empty(required_outer)) - continue; - - /* Get the ParamPathInfo */ - param_info = get_baserel_parampathinfo(root, baserel, - required_outer); - Assert(param_info != NULL); - - /* - * Add it to list unless we already have it. Testing pointer equality - * is OK since get_baserel_parampathinfo won't make duplicates. - */ - ppi_list = list_append_unique_ptr(ppi_list, param_info); - } - - /* - * The above scan examined only "generic" join clauses, not those that - * were absorbed into EquivalenceClauses. See if we can make anything out - * of EquivalenceClauses. - */ - if (baserel->has_eclass_joins) - { - /* - * We repeatedly scan the eclass list looking for column references - * (or expressions) belonging to the foreign rel. Each time we find - * one, we generate a list of equivalence joinclauses for it, and then - * see if any are safe to send to the remote. Repeat till there are - * no more candidate EC members. - */ - ec_member_foreign_arg arg; - - arg.already_used = NIL; - for (;;) - { - List *clauses; - - /* - * Make clauses, skipping any that join to lateral_referencers - */ - arg.current = NULL; - clauses = generate_implied_equalities_for_column(root, - baserel, - sqlite_ec_member_matches_foreign, - (void *) &arg, - baserel->lateral_referencers); - - /* - * Done if there are no more expressions in the foreign rel - */ - if (arg.current == NULL) - { - Assert(clauses == NIL); - break; - } - - /* Scan the extracted join clauses */ - foreach(lc, clauses) - { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); - Relids required_outer; - ParamPathInfo *param_info; - - /* Check if clause can be moved to this rel */ - if (!join_clause_is_movable_to(rinfo, baserel)) - continue; - - /* See if it is safe to send to remote */ - if (!sqlite_is_foreign_expr(root, baserel, rinfo->clause)) - continue; - - /* - * Calculate required outer rels for the resulting path - */ - required_outer = bms_union(rinfo->clause_relids, - baserel->lateral_relids); - required_outer = bms_del_member(required_outer, baserel->relid); - if (bms_is_empty(required_outer)) - continue; - - /* Get the ParamPathInfo */ - param_info = get_baserel_parampathinfo(root, baserel, - required_outer); - Assert(param_info != NULL); - - /* Add it to list unless we already have it */ - ppi_list = list_append_unique_ptr(ppi_list, param_info); - } - - /* - * Try again, now ignoring the expression we found this time - */ - arg.already_used = lappend(arg.already_used, arg.current); - } - } - - /* - * Now build a path for each useful outer relation. - */ - foreach(lc, ppi_list) - { - ParamPathInfo *param_info = (ParamPathInfo *) lfirst(lc); - double rows; - int width; - Cost param_startup_cost; - Cost param_total_cost; - - /* Get a cost estimate from the remote */ - sqlite_estimate_path_cost_size(root, baserel, - param_info->ppi_clauses, NIL, NULL, - &rows, &width, - ¶m_startup_cost, ¶m_total_cost); - - /* - * ppi_rows currently won't get looked at by anything, but still we - * may as well ensure that it matches our idea of the rowcount. - */ - param_info->ppi_rows = rows; - - /* Make the path */ - path = create_foreignscan_path(root, baserel, - NULL, /* default pathtarget */ - rows, - param_startup_cost, - param_total_cost, - NIL, /* no pathkeys */ - param_info->ppi_req_outer, - NULL, - NIL); /* no fdw_private list */ - add_path(baserel, (Path *) path); - } + sqlite_add_paths_with_pathkeys_for_rel(root, baserel, fdw_private, NULL +#if PG_VERSION_NUM >= 170000 + , NIL +#endif + ); } /* @@ -1490,13 +1276,7 @@ sqliteBeginForeignScan(ForeignScanState *node, int eflags) node->fdw_state = (void *) festate; festate->rowidx = 0; - /* - * Identify which user to do the remote access as. This should match what - * ExecCheckRTEPerms() does (ExecCheckRTEPerms() for older version). - * From PostgreSQL 16, in case of a join or aggregate, use the - * lowest-numbered member RTE as a representative; we would get the same - * result from any. - */ + /* Get info about foreign table. */ if (fsplan->scan.scanrelid > 0) rtindex = fsplan->scan.scanrelid; else @@ -1515,7 +1295,6 @@ sqliteBeginForeignScan(ForeignScanState *node, int eflags) } rte = exec_rt_fetch(rtindex, estate); - /* Get info about foreign table. */ festate->rel = node->ss.ss_currentRelation; festate->table = GetForeignTable(rte->relid); festate->server = GetForeignServer(festate->table->serverid); @@ -2613,17 +2392,13 @@ sqliteBeginDirectModify(ForeignScanState *node, int eflags) dmstate = (SqliteFdwDirectModifyState *) palloc0(sizeof(SqliteFdwDirectModifyState)); node->fdw_state = (void *) dmstate; - /* - * Identify which user to do the remote access as. This should match what - * ExecCheckRTEPerms() does. - */ + /* Get info about foreign table. */ #if (PG_VERSION_NUM >= 140000) rtindex = node->resultRelInfo->ri_RangeTableIndex; #else rtindex = estate->es_result_relation_info->ri_RangeTableIndex; #endif - /* Get info about foreign table. */ #if PG_VERSION_NUM >= 160000 rtindex = node->resultRelInfo->ri_RangeTableIndex; #endif @@ -3235,21 +3010,46 @@ sqliteImportForeignSchema(ImportForeignSchemaStmt *stmt, return commands; } +#if PG_VERSION_NUM >= 170000 /* - * Estimate costs of executing a SQL statement remotely. The given "sql" must - * be an EXPLAIN command. + * Check if reltarget is safe enough to push down semi-join. Reltarget is not + * safe, if it contains references to inner rel relids, which do not belong to + * outer rel. */ -static void -sqlite_get_remote_estimate(const char *sql, sqlite3 * conn, - double *rows, int *width, - Cost *startup_cost, Cost *total_cost) +static bool +sqlite_semijoin_target_ok(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel) { - /* - * Disable this funtionality because Sqlite FDW does not use estimate from - * remote for planning - */ - elog(ERROR, "Not supported to estimate from remote for planning"); + List *vars; + ListCell *lc; + bool ok = true; + + Assert(joinrel->reltarget); + + vars = pull_var_clause((Node *)joinrel->reltarget->exprs, PVC_INCLUDE_PLACEHOLDERS); + + foreach (lc, vars) + { + Var *var = (Var *)lfirst(lc); + + if (!IsA(var, Var)) + continue; + + if (bms_is_member(var->varno, innerrel->relids) && + !bms_is_member(var->varno, outerrel->relids)) + { + /* + * The planner can create semi-join, which refers to inner rel + * vars in its target list. However, we deparse semi-join as an + * exists() subquery, so can't handle references to inner rel in + * the target list. + */ + ok = false; + break; + } + } + return ok; } +#endif /* * Assess whether the join between inner and outer relations can be pushed @@ -3267,6 +3067,23 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype ListCell *lc; List *joinclauses; +#if PG_VERSION_NUM >= 170000 + /* + * We support pushing down INNER, LEFT and SEMI joins. + * Constructing queries representing ANTI joins is hard, hence not + * considered right now. + */ + + if (jointype != JOIN_INNER && jointype != JOIN_LEFT && + jointype != JOIN_SEMI) + return false; + + /* + * We can't push down semi-join if its reltarget is not safe + */ + if ((jointype == JOIN_SEMI) && !sqlite_semijoin_target_ok(root, joinrel, outerrel, innerrel)) + return false; +#else /* * We support pushing down INNER and LEFT joins. Constructing queries * representing SEMI and ANTI joins is hard, hence not considered right @@ -3274,6 +3091,7 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype */ if (jointype != JOIN_INNER && jointype != JOIN_LEFT) return false; +#endif /* * If either of the joining relations is marked as unsafe to pushdown, the @@ -3389,7 +3207,10 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype Assert(bms_is_subset(fpinfo_i->lower_subquery_rels, innerrel->relids)); fpinfo->lower_subquery_rels = bms_union(fpinfo_o->lower_subquery_rels, fpinfo_i->lower_subquery_rels); - +#if PG_VERSION_NUM >= 170000 + fpinfo->hidden_subquery_rels = bms_union(fpinfo_o->hidden_subquery_rels, + fpinfo_i->hidden_subquery_rels); +#endif /* * Pull the other remote conditions from the joining relations into join * clauses or other remote clauses (remote_conds) of this relation @@ -3402,6 +3223,12 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype * the joinclauses, since they need to be evaluated while constructing the * join. * + * For SEMI-JOIN clauses from inner relation can not be added to + * remote_conds, but should be treated as join clauses (as they are + * deparsed to EXISTS subquery, where inner relation can be referred). A + * list of relation ids, which can't be referred to from higher levels, is + * preserved as a hidden_subquery_rels list. + * * For a FULL OUTER JOIN, the other clauses from either relation can not * be added to the joinclauses or remote_conds, since each relation acts * as an outer relation for the other. @@ -3424,6 +3251,17 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype fpinfo->remote_conds = list_concat(fpinfo->remote_conds, fpinfo_o->remote_conds); break; +#if PG_VERSION_NUM >= 170000 + case JOIN_SEMI: + fpinfo->joinclauses = list_concat(fpinfo->joinclauses, + fpinfo_i->remote_conds); + fpinfo->joinclauses = list_concat(fpinfo->joinclauses, + fpinfo->remote_conds); + fpinfo->remote_conds = list_copy(fpinfo_o->remote_conds); + fpinfo->hidden_subquery_rels = bms_union(fpinfo->hidden_subquery_rels, + innerrel->relids); + break; +#endif default: /* Should not happen, we have just checked this above */ @@ -3441,21 +3279,29 @@ sqlite_foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype fpinfo->joinclauses = fpinfo->remote_conds; fpinfo->remote_conds = NIL; } +#if PG_VERSION_NUM >= 170000 + else if (jointype == JOIN_LEFT || jointype == JOIN_RIGHT || jointype == JOIN_FULL) + { + /* + * Conditions, generated from semi-joins, should be evaluated before + * LEFT/RIGHT/FULL join. + */ + if (!bms_is_empty(fpinfo_o->hidden_subquery_rels)) + { + fpinfo->make_outerrel_subquery = true; + fpinfo->lower_subquery_rels = bms_add_members(fpinfo->lower_subquery_rels, outerrel->relids); + } + if (!bms_is_empty(fpinfo_i->hidden_subquery_rels)) + { + fpinfo->make_innerrel_subquery = true; + fpinfo->lower_subquery_rels = bms_add_members(fpinfo->lower_subquery_rels, innerrel->relids); + } + } +#endif /* Mark that this join can be pushed down safely */ fpinfo->pushdown_safe = true; - /* Get user mapping */ - if (fpinfo->use_remote_estimate) - { - if (fpinfo_o->use_remote_estimate) - fpinfo->user = fpinfo_o->user; - else - fpinfo->user = fpinfo_i->user; - } - else - fpinfo->user = NULL; - /* * Set # of retrieved rows and cached relation costs to some negative * value, so that we can detect when they are set to some sensible values, @@ -3548,37 +3394,6 @@ sqlite_adjust_foreign_grouping_path_cost(PlannerInfo *root, } } -/* - * Detect whether we want to process an EquivalenceClass member. - * - * This is a callback for use by generate_implied_equalities_for_column. - */ -static bool -sqlite_ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel, - EquivalenceClass *ec, EquivalenceMember *em, - void *arg) -{ - ec_member_foreign_arg *state = (ec_member_foreign_arg *) arg; - Expr *expr = em->em_expr; - - /* - * If we've identified what we're processing in the current scan, we only - * want to match that expression. - */ - if (state->current != NULL) - return equal(expr, state->current); - - /* - * Otherwise, ignore anything we've already processed. - */ - if (list_member(state->already_used, expr)) - return false; - - /* This is the new target to process. */ - state->current = expr; - return true; -} - /* * sqliteGetForeignJoinPaths Add possible ForeignPath to joinrel, if * join is safe to push down. @@ -3679,11 +3494,10 @@ sqliteGetForeignJoinPaths(PlannerInfo *root, * If we are going to estimate costs locally, estimate the join clause * selectivity here while we have special join info. */ - if (!fpinfo->use_remote_estimate) - fpinfo->joinclause_sel = clauselist_selectivity(root, fpinfo->joinclauses, - 0, fpinfo->jointype, - extra->sjinfo); - + fpinfo->joinclause_sel = clauselist_selectivity(root, fpinfo->joinclauses, + 0, fpinfo->jointype, + extra->sjinfo); + /* Estimate costs for bare join relation */ sqlite_estimate_path_cost_size(root, joinrel, NIL, NIL, NULL, &rows, &width, &startup_cost, &total_cost); @@ -3712,15 +3526,20 @@ sqliteGetForeignJoinPaths(PlannerInfo *root, NIL, /* no pathkeys */ joinrel->lateral_relids, epq_path, - NIL); /* no fdw_private */ +#if PG_VERSION_NUM >= 170000 + extra->restrictlist, +#endif + NIL); /* no fdw_private */ /* Add generated path into joinrel by add_path(). */ add_path(joinrel, (Path *) joinpath); /* Consider pathkeys for the join relation */ - sqlite_add_paths_with_pathkeys_for_rel(root, joinrel, NULL, epq_path); - - /* XXX Consider parameterized paths for the join relation */ + sqlite_add_paths_with_pathkeys_for_rel(root, joinrel, NULL, epq_path +#if PG_VERSION_NUM >= 170000 + , extra->restrictlist +#endif + ); } static void @@ -3742,24 +3561,11 @@ sqlite_merge_fdw_options(SqliteFdwRelationInfo * fpinfo, */ fpinfo->fdw_startup_cost = fpinfo_o->fdw_startup_cost; fpinfo->fdw_tuple_cost = fpinfo_o->fdw_tuple_cost; - fpinfo->shippable_extensions = fpinfo_o->shippable_extensions; - fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate; fpinfo->fetch_size = fpinfo_o->fetch_size; /* Merge the table level options from either side of the join. */ if (fpinfo_i) { - /* - * We'll prefer to use remote estimates for this join if any table - * from either side of the join is using remote estimates. This is - * most likely going to be preferred since they're already willing to - * pay the price of a round trip to get the remote EXPLAIN. In any - * case it's not entirely clear how we might otherwise handle this - * best. - */ - fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate || - fpinfo_i->use_remote_estimate; - /* * Set fetch size to maximum of the joining sides, since we are * expecting the rows returned by the join to be proportional to the @@ -3994,14 +3800,6 @@ sqlite_foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel) /* Safe to pushdown */ fpinfo->pushdown_safe = true; - /* - * If user is willing to estimate cost for a scan using EXPLAIN, he - * intends to estimate scans on that relation more accurately. Then, it - * makes sense to estimate the cost of the grouping on that relation more - * accurately using EXPLAIN. - */ - fpinfo->use_remote_estimate = ofpinfo->use_remote_estimate; - /* Copy startup and tuple cost as is from underneath input rel's fpinfo */ fpinfo->fdw_startup_cost = ofpinfo->fdw_startup_cost; fpinfo->fdw_tuple_cost = ofpinfo->fdw_tuple_cost; @@ -4127,14 +3925,12 @@ sqlite_add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, fpinfo->outerrel = input_rel; /* - * Copy foreign table, foreign server, user mapping, shippable extensions + * Copy foreign table, foreign server * etc. details from the input relation's fpinfo. */ fpinfo->table = ifpinfo->table; fpinfo->server = ifpinfo->server; - fpinfo->shippable_extensions = ifpinfo->shippable_extensions; - /* Assess if it is safe to push down aggregation and grouping. */ if (!sqlite_foreign_grouping_ok(root, grouped_rel)) return; @@ -4148,7 +3944,7 @@ sqlite_add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, fpinfo->total_cost = total_cost; /* Create and add foreign path to the grouping relation. */ -#if (PG_VERSION_NUM >= 120000) +#if PG_VERSION_NUM >= 120000 grouppath = create_foreign_upper_path(root, grouped_rel, grouped_rel->reltarget, @@ -4157,6 +3953,9 @@ sqlite_add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, total_cost, NIL, /* no pathkeys */ NULL, +#if PG_VERSION_NUM >= 170000 + NIL, /* no fdw_restrictinfo list */ +#endif NIL); /* no fdw_private */ #else grouppath = create_foreignscan_path(root, @@ -4218,15 +4017,12 @@ sqlite_add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, fpinfo->outerrel = input_rel; /* - * Copy foreign table, foreign server, user mapping, FDW options etc. + * Copy foreign table, foreign server, FDW options etc. * details from the input relation's fpinfo. */ fpinfo->table = ifpinfo->table; fpinfo->server = ifpinfo->server; - fpinfo->shippable_extensions = ifpinfo->shippable_extensions; - - /* * If the input_rel is a base or join relation, we would already have * considered pushing down the final sort to the remote server when @@ -4314,7 +4110,10 @@ sqlite_add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, startup_cost, total_cost, root->sort_pathkeys, - NULL, /* no extra plan */ + NULL, /* no extra plan */ +#if PG_VERSION_NUM >= 170000 + NIL, /* no fdw_restrictinfo list */ +#endif fdw_private); #else @@ -4411,14 +4210,12 @@ sqlite_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, fpinfo->outerrel = input_rel; /* - * Copy foreign table, foreign server, user mapping, FDW options etc. + * Copy foreign table, foreign server, FDW options etc. * details from the input relation's fpinfo. */ fpinfo->table = ifpinfo->table; fpinfo->server = ifpinfo->server; - fpinfo->shippable_extensions = ifpinfo->shippable_extensions; - #if (PG_VERSION_NUM >= 120000) Assert(extra->limit_needed); #else @@ -4466,9 +4263,14 @@ sqlite_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, return; #if PG_VERSION_NUM >= 130000 - /* Don't pushdown FETCH ... WITH TIES option */ - if (parse->limitCount - && parse->limitOption == LIMIT_OPTION_WITH_TIES) + /* + * If the query has FETCH FIRST .. WITH TIES, 1) it must have ORDER BY as + * well, which is used to determine which additional rows tie for the last + * place in the result set, and 2) ORDER BY must already have been + * determined to be safe to push down before we get here. Since sqlite_fdw + * does not support FETCH FIRST ... WITH TIES, disable pushing this option. + */ + if (parse->limitOption == LIMIT_OPTION_WITH_TIES) return; #endif @@ -4518,7 +4320,10 @@ sqlite_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, startup_cost, total_cost, pathkeys, - NULL, /* no extra plan */ + NULL, /* no extra plan */ +#if PG_VERSION_NUM >= 170000 + NIL, /* no fdw_restrictinfo list */ +#endif fdw_private); #else final_path = create_foreignscan_path(root, @@ -4564,477 +4369,373 @@ sqlite_estimate_path_cost_size(PlannerInfo *root, int width; Cost startup_cost; Cost total_cost; + Cost run_cost = 0; /* Make sure the core code has set up the relation's reltarget */ Assert(foreignrel->reltarget); /* - * If the table or the server is configured to use remote estimates, - * connect to the foreign server and execute EXPLAIN to estimate the - * number of rows selected by the restriction+join clauses. Otherwise, - * estimate rows using whatever statistics we have locally, in a way - * similar to ordinary tables. + * We don't support join conditions in this mode (hence, no + * parameterized paths can be made). + */ + Assert(param_join_conds == NIL); + + /* + * We will come here again and again with different set of pathkeys or + * additional post-scan/join-processing steps that caller wants to + * cost. We don't need to calculate the cost/size estimates for the + * underlying scan, join, or grouping each time. Instead, use those + * estimates if we have cached them already. */ - if (fpinfo->use_remote_estimate) + if (fpinfo->rel_startup_cost >= 0 && fpinfo->rel_total_cost >= 0) { - List *remote_param_join_conds; - List *local_param_join_conds; - StringInfoData sql; - sqlite3 *conn; - Selectivity local_sel; - QualCost local_cost; - List *fdw_scan_tlist = NIL; - List *remote_conds; + Assert(fpinfo->retrieved_rows >= 1); - /* Required only to be passed to deparseSelectStmtForRel */ - List *retrieved_attrs; + rows = fpinfo->rows; + retrieved_rows = fpinfo->retrieved_rows; + width = fpinfo->width; + startup_cost = fpinfo->rel_startup_cost; + run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost; /* - * param_join_conds might contain both clauses that are safe to send - * across, and clauses that aren't. + * If we estimate the costs of a foreign scan or a foreign join + * with additional post-scan/join-processing steps, the scan or + * join costs obtained from the cache wouldn't yet contain the + * eval costs for the final scan/join target, which would've been + * updated by apply_scanjoin_target_to_paths(); add the eval costs + * now. */ - sqlite_classify_conditions(root, foreignrel, param_join_conds, - &remote_param_join_conds, &local_param_join_conds); + if (fpextra && !IS_UPPER_REL(foreignrel)) + { + /* Shouldn't get here unless we have LIMIT */ + Assert(fpextra->has_limit); + Assert(foreignrel->reloptkind == RELOPT_BASEREL || + foreignrel->reloptkind == RELOPT_JOINREL); + startup_cost += foreignrel->reltarget->cost.startup; + run_cost += foreignrel->reltarget->cost.per_tuple * rows; + } + } + else if (IS_JOIN_REL(foreignrel)) + { + SqliteFdwRelationInfo *fpinfo_i; + SqliteFdwRelationInfo *fpinfo_o; + QualCost join_cost; + QualCost remote_conds_cost; + double nrows; + + /* Use rows/width estimates made by the core code. */ + rows = foreignrel->rows; + width = foreignrel->reltarget->width; + + /* For join we expect inner and outer relations set */ + Assert(fpinfo->innerrel && fpinfo->outerrel); + + fpinfo_i = (SqliteFdwRelationInfo *)fpinfo->innerrel->fdw_private; + fpinfo_o = (SqliteFdwRelationInfo *)fpinfo->outerrel->fdw_private; + + /* Estimate of number of rows in cross product */ + nrows = fpinfo_i->rows * fpinfo_o->rows; /* - * Build the list of columns to be fetched from the foreign server. + * Back into an estimate of the number of retrieved rows. Just in + * case this is nuts, clamp to at most nrows. */ - if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel)) - fdw_scan_tlist = sqlite_build_tlist_to_deparse(foreignrel); - else - fdw_scan_tlist = NIL; + retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel); + retrieved_rows = Min(retrieved_rows, nrows); /* - * The complete list of remote conditions includes everything from - * baserestrictinfo plus any extra join_conds relevant to this - * particular path. + * The cost of foreign join is estimated as cost of generating + * rows for the joining relations + cost for applying quals on the + * rows. */ - remote_conds = list_concat(list_copy(remote_param_join_conds), - fpinfo->remote_conds); /* - * Construct EXPLAIN query including the desired SELECT, FROM, and - * WHERE clauses. Params and other-relation Vars are replaced by dummy - * values, so don't request params_list. + * Calculate the cost of clauses pushed down to the foreign server */ - initStringInfo(&sql); - appendStringInfoString(&sql, "EXPLAIN "); - sqlite_deparse_select_stmt_for_rel(&sql, root, foreignrel, fdw_scan_tlist, - remote_conds, pathkeys, - fpextra ? fpextra->has_final_sort : false, - fpextra ? fpextra->has_limit : false, - false, &retrieved_attrs, NULL); - - /* Get the remote estimate */ - conn = sqlite_get_connection(fpinfo->server, false); - - sqlite_get_remote_estimate(sql.data, conn, &rows, &width, - &startup_cost, &total_cost); - - retrieved_rows = rows; - - /* Factor in the selectivity of the locally-checked quals */ - local_sel = clauselist_selectivity(root, - local_param_join_conds, - foreignrel->relid, - JOIN_INNER, - NULL); - local_sel *= fpinfo->local_conds_sel; - - rows = clamp_row_est(rows * local_sel); + cost_qual_eval(&remote_conds_cost, fpinfo->remote_conds, root); + /* Calculate the cost of applying join clauses */ + cost_qual_eval(&join_cost, fpinfo->joinclauses, root); - /* Add in the eval cost of the locally-checked quals */ + /* + * Startup cost includes startup cost of joining relations and the + * startup cost for join and other clauses. We do not include the + * startup cost specific to join strategy (e.g. setting up hash + * tables) since we do not know what strategy the foreign server + * is going to use. + */ + startup_cost = fpinfo_i->rel_startup_cost + fpinfo_o->rel_startup_cost; + startup_cost += join_cost.startup; + startup_cost += remote_conds_cost.startup; startup_cost += fpinfo->local_conds_cost.startup; - total_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; - cost_qual_eval(&local_cost, local_param_join_conds, root); - startup_cost += local_cost.startup; - total_cost += local_cost.per_tuple * retrieved_rows; /* - * Add in tlist eval cost for each output row. In case of an - * aggregate, some of the tlist expressions such as grouping - * expressions will be evaluated remotely, so adjust the costs. + * Run time cost includes: + * + * 1. Run time cost (total_cost - startup_cost) of relations being + * joined + * + * 2. Run time cost of applying join clauses on the cross product + * of the joining relations. + * + * 3. Run time cost of applying pushed down other clauses on the + * result of join + * + * 4. Run time cost of applying nonpushable other clauses locally + * on the result fetched from the foreign server. */ + run_cost = fpinfo_i->rel_total_cost - fpinfo_i->rel_startup_cost; + run_cost += fpinfo_o->rel_total_cost - fpinfo_o->rel_startup_cost; + run_cost += nrows * join_cost.per_tuple; + nrows = clamp_row_est(nrows * fpinfo->joinclause_sel); + run_cost += nrows * remote_conds_cost.per_tuple; + run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; + + /* Add in tlist eval cost for each output row */ startup_cost += foreignrel->reltarget->cost.startup; - total_cost += foreignrel->reltarget->cost.startup; - total_cost += foreignrel->reltarget->cost.per_tuple * rows; - if (IS_UPPER_REL(foreignrel)) - { - QualCost tlist_cost; - - cost_qual_eval(&tlist_cost, fdw_scan_tlist, root); - startup_cost -= tlist_cost.startup; - total_cost -= tlist_cost.startup; - total_cost -= tlist_cost.per_tuple * rows; - } + run_cost += foreignrel->reltarget->cost.per_tuple * rows; } - else + else if (IS_UPPER_REL(foreignrel)) { - Cost run_cost = 0; + RelOptInfo *outerrel = fpinfo->outerrel; + SqliteFdwRelationInfo *ofpinfo; + AggClauseCosts aggcosts; + double input_rows; + int numGroupCols; + double numGroups = 1; /* - * We don't support join conditions in this mode (hence, no - * parameterized paths can be made). + * The upper relation should have its outer relation set */ - Assert(param_join_conds == NIL); + Assert(outerrel); /* - * We will come here again and again with different set of pathkeys or - * additional post-scan/join-processing steps that caller wants to - * cost. We don't need to calculate the cost/size estimates for the - * underlying scan, join, or grouping each time. Instead, use those - * estimates if we have cached them already. + * and that outer relation should have its reltarget set */ - if (fpinfo->rel_startup_cost >= 0 && fpinfo->rel_total_cost >= 0) - { - Assert(fpinfo->retrieved_rows >= 1); + Assert(outerrel->reltarget); - rows = fpinfo->rows; - retrieved_rows = fpinfo->retrieved_rows; - width = fpinfo->width; - startup_cost = fpinfo->rel_startup_cost; - run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost; - - /* - * If we estimate the costs of a foreign scan or a foreign join - * with additional post-scan/join-processing steps, the scan or - * join costs obtained from the cache wouldn't yet contain the - * eval costs for the final scan/join target, which would've been - * updated by apply_scanjoin_target_to_paths(); add the eval costs - * now. - */ - if (fpextra && !IS_UPPER_REL(foreignrel)) - { - /* Shouldn't get here unless we have LIMIT */ - Assert(fpextra->has_limit); - Assert(foreignrel->reloptkind == RELOPT_BASEREL || - foreignrel->reloptkind == RELOPT_JOINREL); - startup_cost += foreignrel->reltarget->cost.startup; - run_cost += foreignrel->reltarget->cost.per_tuple * rows; - } - } - else if (IS_JOIN_REL(foreignrel)) - { - SqliteFdwRelationInfo *fpinfo_i; - SqliteFdwRelationInfo *fpinfo_o; - QualCost join_cost; - QualCost remote_conds_cost; - double nrows; - - /* Use rows/width estimates made by the core code. */ - rows = foreignrel->rows; - width = foreignrel->reltarget->width; - - /* For join we expect inner and outer relations set */ - Assert(fpinfo->innerrel && fpinfo->outerrel); - - fpinfo_i = (SqliteFdwRelationInfo *) fpinfo->innerrel->fdw_private; - fpinfo_o = (SqliteFdwRelationInfo *) fpinfo->outerrel->fdw_private; - - /* Estimate of number of rows in cross product */ - nrows = fpinfo_i->rows * fpinfo_o->rows; - - /* - * Back into an estimate of the number of retrieved rows. Just in - * case this is nuts, clamp to at most nrows. - */ - retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel); - retrieved_rows = Min(retrieved_rows, nrows); - - /* - * The cost of foreign join is estimated as cost of generating - * rows for the joining relations + cost for applying quals on the - * rows. - */ - - /* - * Calculate the cost of clauses pushed down to the foreign server - */ - cost_qual_eval(&remote_conds_cost, fpinfo->remote_conds, root); - /* Calculate the cost of applying join clauses */ - cost_qual_eval(&join_cost, fpinfo->joinclauses, root); + /* + * This cost model is mixture of costing done for sorted and + * hashed aggregates in cost_agg(). We are not sure which + * strategy will be considered at remote side, thus for + * simplicity, we put all startup related costs in startup_cost + * and all finalization and run cost are added in total_cost. + */ - /* - * Startup cost includes startup cost of joining relations and the - * startup cost for join and other clauses. We do not include the - * startup cost specific to join strategy (e.g. setting up hash - * tables) since we do not know what strategy the foreign server - * is going to use. - */ - startup_cost = fpinfo_i->rel_startup_cost + fpinfo_o->rel_startup_cost; - startup_cost += join_cost.startup; - startup_cost += remote_conds_cost.startup; - startup_cost += fpinfo->local_conds_cost.startup; + ofpinfo = (SqliteFdwRelationInfo *)outerrel->fdw_private; - /* - * Run time cost includes: - * - * 1. Run time cost (total_cost - startup_cost) of relations being - * joined - * - * 2. Run time cost of applying join clauses on the cross product - * of the joining relations. - * - * 3. Run time cost of applying pushed down other clauses on the - * result of join - * - * 4. Run time cost of applying nonpushable other clauses locally - * on the result fetched from the foreign server. - */ - run_cost = fpinfo_i->rel_total_cost - fpinfo_i->rel_startup_cost; - run_cost += fpinfo_o->rel_total_cost - fpinfo_o->rel_startup_cost; - run_cost += nrows * join_cost.per_tuple; - nrows = clamp_row_est(nrows * fpinfo->joinclause_sel); - run_cost += nrows * remote_conds_cost.per_tuple; - run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; + /* Get rows from input rel */ + input_rows = ofpinfo->rows; - /* Add in tlist eval cost for each output row */ - startup_cost += foreignrel->reltarget->cost.startup; - run_cost += foreignrel->reltarget->cost.per_tuple * rows; - } - else if (IS_UPPER_REL(foreignrel)) + /* + * Collect statistics about aggregates for estimating costs. + */ + MemSet(&aggcosts, 0, sizeof(AggClauseCosts)); + if (root->parse->hasAggs) { - RelOptInfo *outerrel = fpinfo->outerrel; - SqliteFdwRelationInfo *ofpinfo; - AggClauseCosts aggcosts; - double input_rows; - int numGroupCols; - double numGroups = 1; - - /* - * The upper relation should have its outer relation set - */ - Assert(outerrel); - - /* - * and that outer relation should have its reltarget set - */ - Assert(outerrel->reltarget); - - /* - * This cost model is mixture of costing done for sorted and - * hashed aggregates in cost_agg(). We are not sure which - * strategy will be considered at remote side, thus for - * simplicity, we put all startup related costs in startup_cost - * and all finalization and run cost are added in total_cost. - */ - - ofpinfo = (SqliteFdwRelationInfo *) outerrel->fdw_private; - - /* Get rows from input rel */ - input_rows = ofpinfo->rows; - - /* - * Collect statistics about aggregates for estimating costs. - */ - MemSet(&aggcosts, 0, sizeof(AggClauseCosts)); - if (root->parse->hasAggs) - { #if PG_VERSION_NUM >= 140000 - get_agg_clause_costs(root, AGGSPLIT_SIMPLE, &aggcosts); + get_agg_clause_costs(root, AGGSPLIT_SIMPLE, &aggcosts); #else - get_agg_clause_costs(root, (Node *) fpinfo->grouped_tlist, - AGGSPLIT_SIMPLE, &aggcosts); - - /* - * The cost of aggregates in the HAVING qual will be the same - * for each child as it is for the parent, so there's no need - * to use a translated version of havingQual. - */ - get_agg_clause_costs(root, (Node *) root->parse->havingQual, - AGGSPLIT_SIMPLE, &aggcosts); -#endif - } + get_agg_clause_costs(root, (Node *)fpinfo->grouped_tlist, + AGGSPLIT_SIMPLE, &aggcosts); /* - * Get number of grouping columns and possible number of groups + * The cost of aggregates in the HAVING qual will be the same + * for each child as it is for the parent, so there's no need + * to use a translated version of havingQual. */ + get_agg_clause_costs(root, (Node *)root->parse->havingQual, + AGGSPLIT_SIMPLE, &aggcosts); +#endif + } + + /* + * Get number of grouping columns and possible number of groups + */ #if PG_VERSION_NUM >= 160000 - numGroupCols = list_length(root->processed_groupClause); - numGroups = estimate_num_groups(root, - get_sortgrouplist_exprs(root->processed_groupClause, - fpinfo->grouped_tlist), + numGroupCols = list_length(root->processed_groupClause); + numGroups = estimate_num_groups(root, + get_sortgrouplist_exprs(root->processed_groupClause, + fpinfo->grouped_tlist), #else - numGroupCols = list_length(root->parse->groupClause); - numGroups = estimate_num_groups(root, - get_sortgrouplist_exprs(root->parse->groupClause, - fpinfo->grouped_tlist), + numGroupCols = list_length(root->parse->groupClause); + numGroups = estimate_num_groups(root, + get_sortgrouplist_exprs(root->parse->groupClause, + fpinfo->grouped_tlist), #endif - input_rows, NULL + input_rows, NULL #if PG_VERSION_NUM >= 140000 - ,NULL + , NULL #endif - ); + ); - /* - * Get the retrieved_rows and rows estimates. If there are HAVING - * quals, account for their selectivity. - */ + /* + * Get the retrieved_rows and rows estimates. If there are HAVING + * quals, account for their selectivity. + */ #if PG_VERSION_NUM >= 160000 - if (root->hasHavingQual) + if (root->hasHavingQual) #else - if (root->parse->havingQual) + if (root->parse->havingQual) #endif - { - /* - * Factor in the selectivity of the remotely-checked quals - */ - retrieved_rows = - clamp_row_est(numGroups * - clauselist_selectivity(root, - fpinfo->remote_conds, - 0, - JOIN_INNER, - NULL)); + { + /* + * Factor in the selectivity of the remotely-checked quals + */ + retrieved_rows = + clamp_row_est(numGroups * + clauselist_selectivity(root, + fpinfo->remote_conds, + 0, + JOIN_INNER, + NULL)); - /* - * Factor in the selectivity of the locally-checked quals - */ - rows = clamp_row_est(retrieved_rows * fpinfo->local_conds_sel); - } - else - { - rows = retrieved_rows = numGroups; - } + /* + * Factor in the selectivity of the locally-checked quals + */ + rows = clamp_row_est(retrieved_rows * fpinfo->local_conds_sel); + } + else + { + rows = retrieved_rows = numGroups; + } - /* Use width estimate made by the core code. */ - width = foreignrel->reltarget->width; + /* Use width estimate made by the core code. */ + width = foreignrel->reltarget->width; - /*----- - * Startup cost includes: - * 1. Startup cost for underneath input relation, adjusted for - * tlist replacement by apply_scanjoin_target_to_paths() - * 2. Cost of performing aggregation, per cost_agg() - *----- - */ - startup_cost = ofpinfo->rel_startup_cost; - startup_cost += outerrel->reltarget->cost.startup; - startup_cost += aggcosts.transCost.startup; - startup_cost += aggcosts.transCost.per_tuple * input_rows; + /*----- + * Startup cost includes: + * 1. Startup cost for underneath input relation, adjusted for + * tlist replacement by apply_scanjoin_target_to_paths() + * 2. Cost of performing aggregation, per cost_agg() + *----- + */ + startup_cost = ofpinfo->rel_startup_cost; + startup_cost += outerrel->reltarget->cost.startup; + startup_cost += aggcosts.transCost.startup; + startup_cost += aggcosts.transCost.per_tuple * input_rows; #if PG_VERSION_NUM >= 120000 - startup_cost += aggcosts.finalCost.startup; + startup_cost += aggcosts.finalCost.startup; #else - startup_cost += aggcosts.finalCost; + startup_cost += aggcosts.finalCost; #endif - startup_cost += (cpu_operator_cost * numGroupCols) * input_rows; - - /*----- - * Run time cost includes: - * 1. Run time cost of underneath input relation, adjusted for - * tlist replacement by apply_scanjoin_target_to_paths() - * 2. Run time cost of performing aggregation, per cost_agg() - *----- - */ - run_cost = ofpinfo->rel_total_cost - ofpinfo->rel_startup_cost; - run_cost += outerrel->reltarget->cost.per_tuple * input_rows; + startup_cost += (cpu_operator_cost * numGroupCols) * input_rows; + + /*----- + * Run time cost includes: + * 1. Run time cost of underneath input relation, adjusted for + * tlist replacement by apply_scanjoin_target_to_paths() + * 2. Run time cost of performing aggregation, per cost_agg() + *----- + */ + run_cost = ofpinfo->rel_total_cost - ofpinfo->rel_startup_cost; + run_cost += outerrel->reltarget->cost.per_tuple * input_rows; #if PG_VERSION_NUM >= 120000 - run_cost += aggcosts.finalCost.per_tuple * numGroups; + run_cost += aggcosts.finalCost.per_tuple * numGroups; #else - run_cost += aggcosts.finalCost * numGroups; + run_cost += aggcosts.finalCost * numGroups; #endif - run_cost += cpu_tuple_cost * numGroups; + run_cost += cpu_tuple_cost * numGroups; - /* Account for the eval cost of HAVING quals, if any */ + /* Account for the eval cost of HAVING quals, if any */ #if PG_VERSION_NUM >= 160000 - if (root->hasHavingQual) + if (root->hasHavingQual) #else - if (root->parse->havingQual) + if (root->parse->havingQual) #endif - { - QualCost remote_cost; - - /* - * Add in the eval cost of the remotely-checked quals - */ - cost_qual_eval(&remote_cost, fpinfo->remote_conds, root); - startup_cost += remote_cost.startup; - run_cost += remote_cost.per_tuple * numGroups; - - /* - * Add in the eval cost of the locally-checked quals - */ - startup_cost += fpinfo->local_conds_cost.startup; - run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; - } - - /* Add in tlist eval cost for each output row */ - startup_cost += foreignrel->reltarget->cost.startup; - run_cost += foreignrel->reltarget->cost.per_tuple * rows; - } - else { - Cost cpu_per_tuple; + QualCost remote_cost; /* - * Use rows/width estimates made by set_baserel_size_estimates. + * Add in the eval cost of the remotely-checked quals */ - rows = foreignrel->rows; - width = foreignrel->reltarget->width; + cost_qual_eval(&remote_cost, fpinfo->remote_conds, root); + startup_cost += remote_cost.startup; + run_cost += remote_cost.per_tuple * numGroups; /* - * Back into an estimate of the number of retrieved rows. Just in - * case this is nuts, clamp to at most foreignrel->tuples. + * Add in the eval cost of the locally-checked quals */ - retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel); - retrieved_rows = Min(retrieved_rows, foreignrel->tuples); + startup_cost += fpinfo->local_conds_cost.startup; + run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; + } - /* - * Cost as though this were a seqscan, which is pessimistic. We - * effectively imagine the local_conds are being evaluated - * remotely, too. - */ - startup_cost = 0; - run_cost = 0; - run_cost += seq_page_cost * foreignrel->pages; + /* Add in tlist eval cost for each output row */ + startup_cost += foreignrel->reltarget->cost.startup; + run_cost += foreignrel->reltarget->cost.per_tuple * rows; + } + else + { + Cost cpu_per_tuple; - startup_cost += foreignrel->baserestrictcost.startup; - cpu_per_tuple = cpu_tuple_cost + foreignrel->baserestrictcost.per_tuple; - run_cost += cpu_per_tuple * foreignrel->tuples; + /* + * Use rows/width estimates made by set_baserel_size_estimates. + */ + rows = foreignrel->rows; + width = foreignrel->reltarget->width; - /* Add in tlist eval cost for each output row */ - startup_cost += foreignrel->reltarget->cost.startup; - run_cost += foreignrel->reltarget->cost.per_tuple * rows; - } + /* + * Back into an estimate of the number of retrieved rows. Just in + * case this is nuts, clamp to at most foreignrel->tuples. + */ + retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel); + retrieved_rows = Min(retrieved_rows, foreignrel->tuples); /* - * Without remote estimates, we have no real way to estimate the cost - * of generating sorted output. It could be free if the query plan - * the remote side would have chosen generates properly-sorted output - * anyway, but in most cases it will cost something. Estimate a value - * high enough that we won't pick the sorted path when the ordering - * isn't locally useful, but low enough that we'll err on the side of - * pushing down the ORDER BY clause when it's useful to do so. + * Cost as though this were a seqscan, which is pessimistic. We + * effectively imagine the local_conds are being evaluated + * remotely, too. */ - if (pathkeys != NIL) + startup_cost = 0; + run_cost = 0; + run_cost += seq_page_cost * foreignrel->pages; + + startup_cost += foreignrel->baserestrictcost.startup; + cpu_per_tuple = cpu_tuple_cost + foreignrel->baserestrictcost.per_tuple; + run_cost += cpu_per_tuple * foreignrel->tuples; + + /* Add in tlist eval cost for each output row */ + startup_cost += foreignrel->reltarget->cost.startup; + run_cost += foreignrel->reltarget->cost.per_tuple * rows; + } + + /* + * Without remote estimates, we have no real way to estimate the cost + * of generating sorted output. It could be free if the query plan + * the remote side would have chosen generates properly-sorted output + * anyway, but in most cases it will cost something. Estimate a value + * high enough that we won't pick the sorted path when the ordering + * isn't locally useful, but low enough that we'll err on the side of + * pushing down the ORDER BY clause when it's useful to do so. + */ + if (pathkeys != NIL) + { + if (IS_UPPER_REL(foreignrel)) { - if (IS_UPPER_REL(foreignrel)) - { - Assert(foreignrel->reloptkind == RELOPT_UPPER_REL && - fpinfo->stage == UPPERREL_GROUP_AGG); - sqlite_adjust_foreign_grouping_path_cost(root, pathkeys, - retrieved_rows, width, - fpextra->limit_tuples, - &startup_cost, &run_cost); - } - else - { - startup_cost *= DEFAULT_FDW_SORT_MULTIPLIER; - run_cost *= DEFAULT_FDW_SORT_MULTIPLIER; - } + Assert(foreignrel->reloptkind == RELOPT_UPPER_REL && + fpinfo->stage == UPPERREL_GROUP_AGG); + sqlite_adjust_foreign_grouping_path_cost(root, pathkeys, + retrieved_rows, width, + fpextra->limit_tuples, + &startup_cost, &run_cost); } + else + { + startup_cost *= DEFAULT_FDW_SORT_MULTIPLIER; + run_cost *= DEFAULT_FDW_SORT_MULTIPLIER; + } + } - total_cost = startup_cost + run_cost; + total_cost = startup_cost + run_cost; #if PG_VERSION_NUM >= 120000 - /* Adjust the cost estimates if we have LIMIT */ - if (fpextra && fpextra->has_limit) - { - adjust_limit_rows_costs(&rows, &startup_cost, &total_cost, - fpextra->offset_est, fpextra->count_est); - retrieved_rows = rows; - } -#endif + /* Adjust the cost estimates if we have LIMIT */ + if (fpextra && fpextra->has_limit) + { + adjust_limit_rows_costs(&rows, &startup_cost, &total_cost, + fpextra->offset_est, fpextra->count_est); + retrieved_rows = rows; } +#endif /* * If this includes the final sort step, the given target, which will be @@ -5097,8 +4798,7 @@ sqlite_estimate_path_cost_size(PlannerInfo *root, * the remote restriction to ensure we'll prefer it if LIMIT is a useful * one. */ - if (!fpinfo->use_remote_estimate && - fpextra && fpextra->has_limit && + if (fpextra && fpextra->has_limit && fpextra->limit_tuples > 0 && fpextra->limit_tuples < fpinfo->rows) { @@ -5530,6 +5230,9 @@ EquivalenceMember * sqlite_find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel) { ListCell *lc; +#if PG_VERSION_NUM >= 170000 + SqliteFdwRelationInfo *fpinfo = (SqliteFdwRelationInfo *) rel->fdw_private; +#endif foreach(lc, ec->ec_members) { @@ -5541,6 +5244,9 @@ sqlite_find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel) */ if (bms_is_subset(em->em_relids, rel->relids) && !bms_is_empty(em->em_relids) && +#if PG_VERSION_NUM >= 170000 + bms_is_empty(bms_intersect(em->em_relids, fpinfo->hidden_subquery_rels)) && +#endif sqlite_is_foreign_expr(root, rel, em->em_expr)) return em; } diff --git a/sqlite_fdw.h b/sqlite_fdw.h index 826844c0..a4089c39 100644 --- a/sqlite_fdw.h +++ b/sqlite_fdw.h @@ -52,7 +52,7 @@ #endif /* Code version is updated at new release. */ -#define CODE_VERSION 20400 +#define CODE_VERSION 20500 #if (PG_VERSION_NUM < 100000) /* @@ -107,7 +107,6 @@ typedef struct sqlite_opt * connecting to the SQLite server. */ unsigned long max_blob_size; /* Max blob size to read without * truncation */ - bool use_remote_estimate; /* use remote estimate for rows */ } sqlite_opt; /* Struct for extra information passed to sqlite_estimate_path_cost_size() */ @@ -200,10 +199,8 @@ typedef struct SqliteFdwRelationInfo Cost rel_total_cost; /* Options extracted from catalogs. */ - bool use_remote_estimate; Cost fdw_startup_cost; Cost fdw_tuple_cost; - List *shippable_extensions; /* OIDs of whitelisted extensions */ /* Bitmap of attr numbers we need to fetch from the remote server. */ Bitmapset *attrs_used; @@ -230,7 +227,6 @@ typedef struct SqliteFdwRelationInfo /* Cached catalog information. */ ForeignTable *table; ForeignServer *server; - UserMapping *user; /* only set in use_remote_estimate mode */ int fetch_size; /* fetch size for this remote table */ @@ -251,6 +247,12 @@ typedef struct SqliteFdwRelationInfo * subquery? */ Relids lower_subquery_rels; /* all relids appearing in lower * subqueries */ +#if (PG_VERSION_NUM >= 170000) + Relids hidden_subquery_rels; /* relids, which can't be referred to + * from upper relations, used + * internally for equivalence member + * search */ +#endif /* * Index of the relation. It is used to create an alias to a subquery @@ -356,8 +358,6 @@ extern void sqlite_deparse_direct_delete_sql(StringInfo buf, PlannerInfo *root, List *remote_conds, List **params_list, List **retrieved_attrs); -extern void sqlite_append_where_clause(StringInfo buf, PlannerInfo *root, RelOptInfo *baserel, List *exprs, - bool is_first, List **params); extern void sqlite_deparse_analyze(StringInfo buf, char *dbname, char *relname); extern void sqlite_deparse_string_literal(StringInfo buf, const char *val); extern List *sqlite_build_tlist_to_deparse(RelOptInfo *foreignrel);