From a172312064c91ca49bd9a5bbb7fc7dd6924dcd1d Mon Sep 17 00:00:00 2001 From: Marina Polyakova Date: Sun, 31 Dec 2017 08:44:08 +0300 Subject: [PATCH v6] Precalculate stable and immutable functions Now in Postgresql only immutable functions are precalculated; stable functions are calculated for every row so in fact they don't differ from volatile functions. In this patch the function / operator / another expression is precalculated (= calculated once for all output rows, but as many times as the expression is mentioned in the query) if: 1) it doesn't return a set, 2) it's not volatile itself, 3) its arguments are also constants or precalculated expressions. Costs are changed to reflect the changed behaviour. Tests, small notes in the documentation and support for the prepared statements are included. --- doc/src/sgml/ref/create_function.sgml | 9 + doc/src/sgml/xfunc.sgml | 6 +- src/backend/commands/createas.c | 3 +- src/backend/commands/explain.c | 3 +- src/backend/commands/foreigncmds.c | 1 + src/backend/commands/portalcmds.c | 2 +- src/backend/commands/prepare.c | 7 +- src/backend/commands/schemacmds.c | 1 + src/backend/commands/trigger.c | 1 + src/backend/executor/execExpr.c | 39 +- src/backend/executor/execExprInterp.c | 52 + src/backend/executor/execParallel.c | 1 + src/backend/executor/functions.c | 2 + src/backend/executor/spi.c | 9 +- src/backend/nodes/copyfuncs.c | 17 + src/backend/nodes/equalfuncs.c | 11 + src/backend/nodes/nodeFuncs.c | 76 + src/backend/nodes/outfuncs.c | 12 + src/backend/nodes/params.c | 2 + src/backend/nodes/readfuncs.c | 16 + src/backend/optimizer/path/allpaths.c | 9 +- src/backend/optimizer/path/clausesel.c | 12 + src/backend/optimizer/path/costsize.c | 218 +- src/backend/optimizer/plan/planagg.c | 2 + src/backend/optimizer/plan/planner.c | 1226 +++- src/backend/optimizer/prep/prepjointree.c | 1 + src/backend/optimizer/util/clauses.c | 41 +- src/backend/parser/parse_agg.c | 1 + src/backend/tcop/postgres.c | 11 +- src/backend/tcop/utility.c | 2 + src/backend/utils/adt/domains.c | 5 +- src/backend/utils/adt/ruleutils.c | 5 + src/backend/utils/cache/plancache.c | 180 +- src/backend/utils/cache/typcache.c | 56 +- src/include/executor/execExpr.h | 31 + src/include/nodes/execnodes.h | 19 +- src/include/nodes/nodes.h | 3 + src/include/nodes/params.h | 22 + src/include/nodes/plannodes.h | 2 + src/include/nodes/primnodes.h | 96 +- src/include/nodes/relation.h | 4 +- src/include/optimizer/planner.h | 11 +- src/include/optimizer/tlist.h | 8 +- src/include/tcop/tcopprot.h | 4 +- src/include/utils/plancache.h | 12 +- src/include/utils/typcache.h | 2 + src/pl/plpgsql/src/pl_exec.c | 18 + .../expected/precalculate_stable_functions.out | 6645 ++++++++++++++++++++ .../expected/precalculate_stable_functions_1.out | 6291 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/serial_schedule | 1 + .../regress/sql/precalculate_stable_functions.sql | 2117 +++++++ 52 files changed, 17162 insertions(+), 165 deletions(-) create mode 100644 src/test/regress/expected/precalculate_stable_functions.out create mode 100644 src/test/regress/expected/precalculate_stable_functions_1.out create mode 100644 src/test/regress/sql/precalculate_stable_functions.sql diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index fd229d1..7079ec2 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -337,6 +337,15 @@ CREATE [ OR REPLACE ] FUNCTION setval(). + + + Stable, immutable functions and other nonovolatile expressions are + precalculated (= calculated once for all output rows, but as many times + as expression is mentioned in query), if they don't return a set and + their arguments are constants or recursively precalculated expressions. + + + For additional details see . diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index bbc3766..4825d98 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1533,7 +1533,11 @@ CREATE FUNCTION test(int, int) RETURNS int For best optimization results, you should label your functions with the - strictest volatility category that is valid for them. + strictest volatility category that is valid for them. Stable, immutable + functions and other nonovolatile expressions are precalculated (= calculated + once for all output rows, but as many times as expression is mentioned in + query), if they don't return a set and their arguments are constants or + recursively precalculated expressions. diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 4d77411..9f2b2e5 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -327,7 +327,8 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, Assert(query->commandType == CMD_SELECT); /* plan the query */ - plan = pg_plan_query(query, CURSOR_OPT_PARALLEL_OK, params); + plan = pg_plan_query(query, CURSOR_OPT_PARALLEL_OK, + (ParamListInfoCommon) params); /* * Use a snapshot with an updated command ID to ensure this query sees diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 7e4fbaf..b8baae3 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -361,7 +361,8 @@ ExplainOneQuery(Query *query, int cursorOptions, INSTR_TIME_SET_CURRENT(planstart); /* plan the query */ - plan = pg_plan_query(query, cursorOptions, params); + plan = pg_plan_query(query, cursorOptions, + (ParamListInfoCommon) params); INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SUBTRACT(planduration, planstart); diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 9ad9915..4435ab5 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -1619,6 +1619,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt) pstmt->utilityStmt = (Node *) cstmt; pstmt->stmt_location = rs->stmt_location; pstmt->stmt_len = rs->stmt_len; + pstmt->hasCachedExpr = false; /* Execute statement */ ProcessUtility(pstmt, diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 76d6cf1..e66bead 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -89,7 +89,7 @@ PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params, elog(ERROR, "non-SELECT statement in DECLARE CURSOR"); /* Plan the query, applying the specified options */ - plan = pg_plan_query(query, cstmt->options, params); + plan = pg_plan_query(query, cstmt->options, (ParamListInfoCommon) params); /* * Create a portal and copy the plan and queryString into its memory. diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 6e90912..0ad37b3 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -243,7 +243,8 @@ ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause, entry->plansource->query_string); /* Replan if needed, and increment plan refcount for portal */ - cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL); + cplan = GetCachedPlan(entry->plansource, (ParamListInfoCommon) paramLI, + false, NULL, true); plan_list = cplan->stmt_list; /* @@ -397,6 +398,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params, palloc(offsetof(ParamListInfoData, params) + num_params * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ + paramLI->common.type = PARAM_LIST_INFO_DATA; paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; paramLI->paramCompile = NULL; @@ -670,7 +672,8 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, } /* Replan if needed, and acquire a transient refcount */ - cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv); + cplan = GetCachedPlan(entry->plansource, (ParamListInfoCommon) paramLI, + true, queryEnv, true); INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SUBTRACT(planduration, planstart); diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index f9ea73f..0a20ad7 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -188,6 +188,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, wrapper->utilityStmt = stmt; wrapper->stmt_location = stmt_location; wrapper->stmt_len = stmt_len; + wrapper->hasCachedExpr = false; /* do this step */ ProcessUtility(wrapper, diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 92ae382..7515860 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -1254,6 +1254,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) wrapper->utilityStmt = (Node *) atstmt; wrapper->stmt_location = -1; wrapper->stmt_len = -1; + wrapper->hasCachedExpr = false; /* ... and execute it */ ProcessUtility(wrapper, diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 55bb925..fc68782 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -858,6 +858,38 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } + case T_CachedExpr: + { + /* + * Allocate CachedExprState used by all steps of CachedExpr + * evaluation. + */ + scratch.d.cachedexpr.state = (CachedExprState *) palloc( + sizeof(CachedExprState)); + scratch.d.cachedexpr.state->isExecuted = false; + scratch.d.cachedexpr.state->resnull = false; + scratch.d.cachedexpr.state->resvalue = (Datum) 0; + scratch.d.cachedexpr.state->restypid = exprType( + (const Node *) node); + + /* add EEOP_CACHEDEXPR_IF_CACHED step */ + scratch.opcode = EEOP_CACHEDEXPR_IF_CACHED; + ExprEvalPushStep(state, &scratch); + + /* add subexpression steps */ + ExecInitExprRec((Expr *) ((CachedExpr *) node)->subexpr, state, + resv, resnull); + + /* add EEOP_CACHEDEXPR_SUBEXPR_END step */ + scratch.opcode = EEOP_CACHEDEXPR_SUBEXPR_END; + ExprEvalPushStep(state, &scratch); + + /* adjust jump target */ + scratch.d.cachedexpr.state->jumpdone = state->steps_len; + + break; + } + case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; @@ -2057,6 +2089,7 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } + /* note that DomainConstraintExpr nodes are handled within this block */ case T_CoerceToDomain: { CoerceToDomain *ctest = (CoerceToDomain *) node; @@ -2648,6 +2681,7 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, bool *domainnull = NULL; Datum *save_innermost_domainval; bool *save_innermost_domainnull; + List *constraints; ListCell *l; scratch->d.domaincheck.resulttype = ctest->resulttype; @@ -2685,15 +2719,16 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, constraint_ref, CurrentMemoryContext, false); + constraints = GetDomainConstraintExprList(constraint_ref); /* * Compile code to check each domain constraint. NOTNULL constraints can * just be applied on the resv/resnull value, but for CHECK constraints we * need more pushups. */ - foreach(l, constraint_ref->constraints) + foreach(l, constraints) { - DomainConstraintState *con = (DomainConstraintState *) lfirst(l); + DomainConstraintExpr *con = (DomainConstraintExpr *) lfirst(l); scratch->d.domaincheck.constraintname = con->name; diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 0c3f668..39c9bc5 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -68,6 +68,7 @@ #include "pgstat.h" #include "utils/builtins.h" #include "utils/date.h" +#include "utils/datum.h" #include "utils/lsyscache.h" #include "utils/timestamp.h" #include "utils/typcache.h" @@ -368,6 +369,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_WINDOW_FUNC, &&CASE_EEOP_SUBPLAN, &&CASE_EEOP_ALTERNATIVE_SUBPLAN, + &&CASE_EEOP_CACHEDEXPR_IF_CACHED, + &&CASE_EEOP_CACHEDEXPR_SUBEXPR_END, &&CASE_EEOP_LAST }; @@ -1543,6 +1546,55 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_CACHEDEXPR_IF_CACHED) + { + if (op->d.cachedexpr.state->isExecuted) + { + /* use saved result and skip subexpression evaluation */ + *op->resnull = op->d.cachedexpr.state->resnull; + if (!(*op->resnull)) + *op->resvalue = op->d.cachedexpr.state->resvalue; + + EEO_JUMP(op->d.cachedexpr.state->jumpdone); + } + + /* we are ready for subexpression evaluation */ + EEO_NEXT(); + } + + EEO_CASE(EEOP_CACHEDEXPR_SUBEXPR_END) + { + int16 restyplen; + bool restypbyval; + MemoryContext oldContext; + + /* save result */ + op->d.cachedexpr.state->resnull = *op->resnull; + if (!(*op->resnull)) + { + get_typlenbyval(op->d.cachedexpr.state->restypid, &restyplen, + &restypbyval); + + /* + * Switch per-query memory context. It is necessary to save the + * subexpression result between all tuples if its value datum is + * a pointer. + */ + oldContext = MemoryContextSwitchTo( + econtext->ecxt_per_query_memory); + + op->d.cachedexpr.state->resvalue = datumCopy(*op->resvalue, + restypbyval, + restyplen); + + /* switch memory context back */ + MemoryContextSwitchTo(oldContext); + } + op->d.cachedexpr.state->isExecuted = true; + + EEO_NEXT(); + } + EEO_CASE(EEOP_LAST) { /* unreachable */ diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index b344d4b..4f09bc1 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -207,6 +207,7 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->utilityStmt = NULL; pstmt->stmt_location = -1; pstmt->stmt_len = -1; + pstmt->hasCachedExpr = false; /* Return serialized copy of our dummy PlannedStmt. */ return nodeToString(pstmt); diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 527f7d8..f477d8d 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -502,6 +502,7 @@ init_execution_state(List *queryTree_list, stmt->utilityStmt = queryTree->utilityStmt; stmt->stmt_location = queryTree->stmt_location; stmt->stmt_len = queryTree->stmt_len; + stmt->hasCachedExpr = false; } else stmt = pg_plan_query(queryTree, @@ -912,6 +913,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache, palloc(offsetof(ParamListInfoData, params) + nargs * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ + paramLI->common.type = PARAM_LIST_INFO_DATA; paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; paramLI->paramCompile = NULL; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 977f317..5888ba1 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1202,7 +1202,8 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, */ /* Replan if needed, and increment plan refcount for portal */ - cplan = GetCachedPlan(plansource, paramLI, false, _SPI_current->queryEnv); + cplan = GetCachedPlan(plansource, (ParamListInfoCommon) paramLI, false, + _SPI_current->queryEnv, false); stmt_list = cplan->stmt_list; if (!plan->saved) @@ -1636,7 +1637,7 @@ SPI_plan_get_cached_plan(SPIPlanPtr plan) /* Get the generic plan for the query */ cplan = GetCachedPlan(plansource, NULL, plan->saved, - _SPI_current->queryEnv); + _SPI_current->queryEnv, false); Assert(cplan == plansource->gplan); /* Pop the error context stack */ @@ -2026,7 +2027,8 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, * Replan if needed, and increment plan refcount. If it's a saved * plan, the refcount must be backed by the CurrentResourceOwner. */ - cplan = GetCachedPlan(plansource, paramLI, plan->saved, _SPI_current->queryEnv); + cplan = GetCachedPlan(plansource, (ParamListInfoCommon) paramLI, + plan->saved, _SPI_current->queryEnv, false); stmt_list = cplan->stmt_list; /* @@ -2257,6 +2259,7 @@ _SPI_convert_params(int nargs, Oid *argtypes, paramLI = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) + nargs * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ + paramLI->common.type = PARAM_LIST_INFO_DATA; paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; paramLI->paramCompile = NULL; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 84d7171..c72f91d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -101,6 +101,7 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(utilityStmt); COPY_LOCATION_FIELD(stmt_location); COPY_LOCATION_FIELD(stmt_len); + COPY_SCALAR_FIELD(hasCachedExpr); return newnode; } @@ -1417,6 +1418,19 @@ _copyWindowFunc(const WindowFunc *from) } /* + * _copyCachedExpr + */ +static CachedExpr * +_copyCachedExpr(const CachedExpr *from) +{ + CachedExpr *newnode = makeNode(CachedExpr); + + COPY_NODE_FIELD(subexpr); + + return newnode; +} + +/* * _copyArrayRef */ static ArrayRef * @@ -4884,6 +4898,9 @@ copyObjectImpl(const void *from) case T_WindowFunc: retval = _copyWindowFunc(from); break; + case T_CachedExpr: + retval = _copyCachedExpr(from); + break; case T_ArrayRef: retval = _copyArrayRef(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 2e869a9..cb66eaa 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -264,6 +264,14 @@ _equalWindowFunc(const WindowFunc *a, const WindowFunc *b) } static bool +_equalCachedExpr(const CachedExpr *a, const CachedExpr *b) +{ + COMPARE_NODE_FIELD(subexpr); + + return true; +} + +static bool _equalArrayRef(const ArrayRef *a, const ArrayRef *b) { COMPARE_SCALAR_FIELD(refarraytype); @@ -3035,6 +3043,9 @@ equal(const void *a, const void *b) case T_WindowFunc: retval = _equalWindowFunc(a, b); break; + case T_CachedExpr: + retval = _equalCachedExpr(a, b); + break; case T_ArrayRef: retval = _equalArrayRef(a, b); break; diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index c2a93b2..5e4d2f7 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -66,6 +66,10 @@ exprType(const Node *expr) case T_WindowFunc: type = ((const WindowFunc *) expr)->wintype; break; + case T_CachedExpr: + type = + exprType((const Node *) ((const CachedExpr *) expr)->subexpr); + break; case T_ArrayRef: { const ArrayRef *arrayref = (const ArrayRef *) expr; @@ -286,6 +290,9 @@ exprTypmod(const Node *expr) return ((const Const *) expr)->consttypmod; case T_Param: return ((const Param *) expr)->paramtypmod; + case T_CachedExpr: + return + exprTypmod((const Node *) ((const CachedExpr *) expr)->subexpr); case T_ArrayRef: /* typmod is the same for array or element */ return ((const ArrayRef *) expr)->reftypmod; @@ -573,6 +580,11 @@ exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod) return true; } + if (expr && IsA(expr, CachedExpr)) + return exprIsLengthCoercion( + (const Node *) ((const CachedExpr *) expr)->subexpr, + coercedTypmod); + return false; } @@ -655,6 +667,11 @@ strip_implicit_coercions(Node *node) if (c->coercionformat == COERCE_IMPLICIT_CAST) return strip_implicit_coercions((Node *) c->arg); } + else if (IsA(node, CachedExpr)) + { + return strip_implicit_coercions( + (Node *) ((CachedExpr *) node)->subexpr); + } return node; } @@ -699,6 +716,8 @@ expression_returns_set_walker(Node *node, void *context) return false; if (IsA(node, WindowFunc)) return false; + if (IsA(node, CachedExpr)) + return false; return expression_tree_walker(node, expression_returns_set_walker, context); @@ -744,6 +763,10 @@ exprCollation(const Node *expr) case T_WindowFunc: coll = ((const WindowFunc *) expr)->wincollid; break; + case T_CachedExpr: + coll = exprCollation( + (const Node *) ((const CachedExpr *) expr)->subexpr); + break; case T_ArrayRef: coll = ((const ArrayRef *) expr)->refcollid; break; @@ -933,6 +956,10 @@ exprInputCollation(const Node *expr) case T_WindowFunc: coll = ((const WindowFunc *) expr)->inputcollid; break; + case T_CachedExpr: + coll = exprInputCollation( + (const Node *) ((const CachedExpr *) expr)->subexpr); + break; case T_FuncExpr: coll = ((const FuncExpr *) expr)->inputcollid; break; @@ -988,6 +1015,10 @@ exprSetCollation(Node *expr, Oid collation) case T_WindowFunc: ((WindowFunc *) expr)->wincollid = collation; break; + case T_CachedExpr: + exprSetCollation((Node *) ((CachedExpr *) expr)->subexpr, + collation); + break; case T_ArrayRef: ((ArrayRef *) expr)->refcollid = collation; break; @@ -1129,6 +1160,10 @@ exprSetInputCollation(Node *expr, Oid inputcollation) case T_WindowFunc: ((WindowFunc *) expr)->inputcollid = inputcollation; break; + case T_CachedExpr: + exprSetInputCollation((Node *) ((CachedExpr *) expr)->subexpr, + inputcollation); + break; case T_FuncExpr: ((FuncExpr *) expr)->inputcollid = inputcollation; break; @@ -1217,6 +1252,10 @@ exprLocation(const Node *expr) /* function name should always be the first thing */ loc = ((const WindowFunc *) expr)->location; break; + case T_CachedExpr: + loc = exprLocation( + (const Node *) ((const CachedExpr *) expr)->subexpr); + break; case T_ArrayRef: /* just use array argument's location */ loc = exprLocation((Node *) ((const ArrayRef *) expr)->refexpr); @@ -1590,6 +1629,9 @@ fix_opfuncids_walker(Node *node, void *context) { if (node == NULL) return false; + if (IsA(node, CachedExpr)) + return fix_opfuncids_walker((Node *) ((CachedExpr *) node)->subexpr, + context); if (IsA(node, OpExpr)) set_opfuncid((OpExpr *) node); else if (IsA(node, DistinctExpr)) @@ -1669,6 +1711,9 @@ check_functions_in_node(Node *node, check_function_callback checker, return true; } break; + case T_CachedExpr: + return check_functions_in_node( + (Node *) ((CachedExpr *) node)->subexpr, checker, context); case T_FuncExpr: { FuncExpr *expr = (FuncExpr *) node; @@ -1910,6 +1955,18 @@ expression_tree_walker(Node *node, return true; } break; + case T_CachedExpr: + { + /* + * cachedexpr is processed by walker, so its subexpr is + * processed too and we need to process sub-nodes of subexpr. + */ + if (expression_tree_walker( + (Node *) ((CachedExpr *) node)->subexpr, + walker, context)) + return true; + } + break; case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; @@ -2528,6 +2585,25 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; + case T_CachedExpr: + { + CachedExpr *expr = (CachedExpr *) node; + CachedExpr *newnode; + + FLATCOPY(newnode, expr, CachedExpr); + + /* + * expr is already mutated, so its subexpr is already mutated + * too and we need to mutate sub-nodes of subexpr. + */ + newnode->subexpr = (CacheableExpr *) expression_tree_mutator( + (Node *) expr->subexpr, + mutator, + context); + + return (Node *) newnode; + } + break; case T_ArrayRef: { ArrayRef *arrayref = (ArrayRef *) node; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index e468d7c..80084d5 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -286,6 +286,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_FIELD(utilityStmt); WRITE_LOCATION_FIELD(stmt_location); WRITE_LOCATION_FIELD(stmt_len); + WRITE_BOOL_FIELD(hasCachedExpr); } /* @@ -1180,6 +1181,14 @@ _outWindowFunc(StringInfo str, const WindowFunc *node) } static void +_outCachedExpr(StringInfo str, const CachedExpr *node) +{ + WRITE_NODE_TYPE("CACHEDEXPR"); + + WRITE_NODE_FIELD(subexpr); +} + +static void _outArrayRef(StringInfo str, const ArrayRef *node) { WRITE_NODE_TYPE("ARRAYREF"); @@ -3793,6 +3802,9 @@ outNode(StringInfo str, const void *obj) case T_WindowFunc: _outWindowFunc(str, obj); break; + case T_CachedExpr: + _outCachedExpr(str, obj); + break; case T_ArrayRef: _outArrayRef(str, obj); break; diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index 94acdf4..37451e8 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -46,6 +46,7 @@ copyParamList(ParamListInfo from) from->numParams * sizeof(ParamExternData); retval = (ParamListInfo) palloc(size); + retval->common.type = PARAM_LIST_INFO_DATA; retval->paramFetch = NULL; retval->paramFetchArg = NULL; retval->paramCompile = NULL; @@ -222,6 +223,7 @@ RestoreParamList(char **start_address) nparams * sizeof(ParamExternData); paramLI = (ParamListInfo) palloc(size); + paramLI->common.type = PARAM_LIST_INFO_DATA; paramLI->paramFetch = NULL; paramLI->paramFetchArg = NULL; paramLI->paramCompile = NULL; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 1133c70..7fb9aef 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -640,6 +640,19 @@ _readWindowFunc(void) } /* + * _readCachedExpr + */ +static CachedExpr * +_readCachedExpr(void) +{ + READ_LOCALS(CachedExpr); + + READ_NODE_FIELD(subexpr); + + READ_DONE(); +} + +/* * _readArrayRef */ static ArrayRef * @@ -1484,6 +1497,7 @@ _readPlannedStmt(void) READ_NODE_FIELD(utilityStmt); READ_LOCATION_FIELD(stmt_location); READ_LOCATION_FIELD(stmt_len); + READ_BOOL_FIELD(hasCachedExpr); READ_DONE(); } @@ -2482,6 +2496,8 @@ parseNodeString(void) return_value = _readGroupingFunc(); else if (MATCH("WINDOWFUNC", 10)) return_value = _readWindowFunc(); + else if (MATCH("CACHEDEXPR", 10)) + return_value = _readCachedExpr(); else if (MATCH("ARRAYREF", 8)) return_value = _readArrayRef(); else if (MATCH("FUNCEXPR", 8)) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 0e8463e..109591e 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -380,7 +380,11 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel, set_subquery_pathlist(root, rel, rti, rte); break; case RTE_FUNCTION: - set_function_size_estimates(root, rel); + { + rel->baserestrictinfo = replace_qual_cached_expressions( + rel->baserestrictinfo, root); + set_function_size_estimates(root, rel); + } break; case RTE_TABLEFUNC: set_tablefunc_size_estimates(root, rel); @@ -519,6 +523,9 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) */ check_index_predicates(root, rel); + rel->baserestrictinfo = replace_qual_cached_expressions( + rel->baserestrictinfo, root); + /* Mark rel with estimated output rows, width, etc */ set_baserel_size_estimates(root, rel); } diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index b4cbc34..ba7e03e 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -827,6 +827,18 @@ clause_selectivity(PlannerInfo *root, jointype, sjinfo); } + else if (IsA(clause, CachedExpr)) + { + /* + * Not sure this case is needed, but it can't hurt. + * Calculate selectivity of subexpression. + */ + s1 = clause_selectivity(root, + (Node *) ((CachedExpr *) clause)->subexpr, + varRelid, + jointype, + sjinfo); + } else { /* diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index c3daacd..405a903 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -143,6 +143,8 @@ static MergeScanSelCache *cached_scansel(PlannerInfo *root, PathKey *pathkey); static void cost_rescan(PlannerInfo *root, Path *path, Cost *rescan_startup_cost, Cost *rescan_total_cost); +static QualCost cost_eval_cacheable_expr(CacheableExpr *node, + PlannerInfo *root); static bool cost_qual_eval_walker(Node *node, cost_qual_eval_context *context); static void get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, @@ -3729,6 +3731,129 @@ cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root) *cost = context.total; } +/* + * cost_eval_cacheable_expr + * Evaluate the cost for expressions that can be cached. + * + * This function was created to not duplicate code for some expression and + * cached some expression. + */ +static QualCost +cost_eval_cacheable_expr(CacheableExpr *node, PlannerInfo *root) +{ + QualCost node_cost; + + node_cost.startup = node_cost.per_tuple = 0; + + /* + * For each operator or function node in the given tree, we charge the + * estimated execution cost given by pg_proc.procost (remember to multiply + * this by cpu_operator_cost). + * + * Vars and Consts are charged zero, and so are boolean operators (AND, + * OR, NOT). Simplistic, but a lot better than no model at all. + */ + if (IsA(node, FuncExpr)) + { + node_cost.per_tuple = get_func_cost(((FuncExpr *) node)->funcid) * + cpu_operator_cost; + } + else if (IsA(node, OpExpr) || + IsA(node, DistinctExpr) || + IsA(node, NullIfExpr)) + { + OpExpr *opexpr = (OpExpr *) node; + + /* rely on struct equivalence to treat these all alike */ + set_opfuncid(opexpr); + + node_cost.per_tuple = get_func_cost(opexpr->opfuncid) * + cpu_operator_cost; + } + else if (IsA(node, ScalarArrayOpExpr)) + { + /* + * Estimate that the operator will be applied to about half of the + * array elements before the answer is determined. + */ + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node; + Node *arraynode = (Node *) lsecond(saop->args); + + set_sa_opfuncid(saop); + node_cost.per_tuple = get_func_cost(saop->opfuncid) * + cpu_operator_cost * estimate_array_length(arraynode) * 0.5; + } + else if (IsA(node, CoerceViaIO)) + { + CoerceViaIO *iocoerce = (CoerceViaIO *) node; + Oid iofunc; + Oid typioparam; + bool typisvarlena; + + /* check the result type's input function */ + getTypeInputInfo(iocoerce->resulttype, + &iofunc, &typioparam); + node_cost.per_tuple = get_func_cost(iofunc) * cpu_operator_cost; + /* check the input type's output function */ + getTypeOutputInfo(exprType((Node *) iocoerce->arg), + &iofunc, &typisvarlena); + node_cost.per_tuple += get_func_cost(iofunc) * cpu_operator_cost; + } + else if (IsA(node, ArrayCoerceExpr)) + { + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; + QualCost perelemcost; + + cost_qual_eval_node(&perelemcost, (Node *) acoerce->elemexpr, root); + node_cost.startup = perelemcost.startup; + if (perelemcost.per_tuple > 0) + node_cost.per_tuple += perelemcost.per_tuple * + estimate_array_length((Node *) acoerce->arg); + } + else if (IsA(node, RowCompareExpr)) + { + /* Conservatively assume we will check all the columns */ + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *lc; + + foreach(lc, rcexpr->opnos) + { + Oid opid = lfirst_oid(lc); + + node_cost.per_tuple += get_func_cost(get_opcode(opid)) * + cpu_operator_cost; + } + } + else if (IsA(node, MinMaxExpr) || + IsA(node, SQLValueFunction) || + IsA(node, XmlExpr) || + IsA(node, CoerceToDomain)) + { + /* Treat all these as having cost 1 */ + node_cost.per_tuple = cpu_operator_cost; + } + else if (!(IsA(node, ArrayRef) || + IsA(node, BoolExpr) || + IsA(node, FieldSelect) || + IsA(node, RelabelType) || + IsA(node, ConvertRowtypeExpr) || + IsA(node, CaseExpr) || + IsA(node, CaseTestExpr) || + IsA(node, ArrayExpr) || + IsA(node, RowExpr) || + IsA(node, CoalesceExpr) || + IsA(node, NullTest) || + IsA(node, BooleanTest) || + IsA(node, CoerceToDomainValue))) + { + elog(ERROR, + "unrecognized type of cacheable node: %d", + (int) nodeTag(node)); + } + + return node_cost; +} + static bool cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) { @@ -3802,32 +3927,35 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) * moreover, since our rowcount estimates for functions tend to be pretty * phony, the results would also be pretty phony. */ - if (IsA(node, FuncExpr)) - { - context->total.per_tuple += - get_func_cost(((FuncExpr *) node)->funcid) * cpu_operator_cost; - } - else if (IsA(node, OpExpr) || - IsA(node, DistinctExpr) || - IsA(node, NullIfExpr)) + if (IsA(node, FuncExpr) || + IsA(node, OpExpr) || + IsA(node, DistinctExpr) || + IsA(node, NullIfExpr) || + IsA(node, ScalarArrayOpExpr) || + IsA(node, CoerceViaIO) || + IsA(node, ArrayCoerceExpr) || + IsA(node, RowCompareExpr) || + IsA(node, MinMaxExpr) || + IsA(node, SQLValueFunction) || + IsA(node, XmlExpr) || + IsA(node, CoerceToDomain)) { - /* rely on struct equivalence to treat these all alike */ - set_opfuncid((OpExpr *) node); - context->total.per_tuple += - get_func_cost(((OpExpr *) node)->opfuncid) * cpu_operator_cost; + QualCost node_cost = cost_eval_cacheable_expr( + (CacheableExpr *) node, context->root); + + context->total.startup += node_cost.startup; + context->total.per_tuple += node_cost.per_tuple; } - else if (IsA(node, ScalarArrayOpExpr)) + else if (IsA(node, CachedExpr)) { /* - * Estimate that the operator will be applied to about half of the - * array elements before the answer is determined. + * Calculate subexpression cost as usual and add it to startup cost + * (because subexpression will be executed only once for all tuples). */ - ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node; - Node *arraynode = (Node *) lsecond(saop->args); + QualCost node_cost = cost_eval_cacheable_expr( + ((CachedExpr *) node)->subexpr, context->root); - set_sa_opfuncid(saop); - context->total.per_tuple += get_func_cost(saop->opfuncid) * - cpu_operator_cost * estimate_array_length(arraynode) * 0.5; + context->total.startup += node_cost.startup + node_cost.per_tuple; } else if (IsA(node, Aggref) || IsA(node, WindowFunc)) @@ -3843,55 +3971,9 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) */ return false; /* don't recurse into children */ } - else if (IsA(node, CoerceViaIO)) - { - CoerceViaIO *iocoerce = (CoerceViaIO *) node; - Oid iofunc; - Oid typioparam; - bool typisvarlena; - - /* check the result type's input function */ - getTypeInputInfo(iocoerce->resulttype, - &iofunc, &typioparam); - context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost; - /* check the input type's output function */ - getTypeOutputInfo(exprType((Node *) iocoerce->arg), - &iofunc, &typisvarlena); - context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost; - } - else if (IsA(node, ArrayCoerceExpr)) - { - ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; - QualCost perelemcost; - - cost_qual_eval_node(&perelemcost, (Node *) acoerce->elemexpr, - context->root); - context->total.startup += perelemcost.startup; - if (perelemcost.per_tuple > 0) - context->total.per_tuple += perelemcost.per_tuple * - estimate_array_length((Node *) acoerce->arg); - } - else if (IsA(node, RowCompareExpr)) + else if (IsA(node, NextValueExpr)) { - /* Conservatively assume we will check all the columns */ - RowCompareExpr *rcexpr = (RowCompareExpr *) node; - ListCell *lc; - - foreach(lc, rcexpr->opnos) - { - Oid opid = lfirst_oid(lc); - - context->total.per_tuple += get_func_cost(get_opcode(opid)) * - cpu_operator_cost; - } - } - else if (IsA(node, MinMaxExpr) || - IsA(node, SQLValueFunction) || - IsA(node, XmlExpr) || - IsA(node, CoerceToDomain) || - IsA(node, NextValueExpr)) - { - /* Treat all these as having cost 1 */ + /* Treat this as having cost 1 */ context->total.per_tuple += cpu_operator_cost; } else if (IsA(node, CurrentOfExpr)) diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index 889e8af..f2670b2 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -38,6 +38,7 @@ #include "optimizer/pathnode.h" #include "optimizer/paths.h" #include "optimizer/planmain.h" +#include "optimizer/planner.h" #include "optimizer/subselect.h" #include "optimizer/tlist.h" #include "parser/parsetree.h" @@ -368,6 +369,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, subroot->plan_params = NIL; subroot->outer_params = NULL; subroot->init_plans = NIL; + subroot->hasCachedExpr = false; subroot->parse = parse = copyObject(root->parse); IncrementVarSublevelsUp((Node *) parse, 1, 1); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 382791f..88b3a84 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -56,6 +56,7 @@ #include "utils/selfuncs.h" #include "utils/lsyscache.h" #include "utils/syscache.h" +#include "utils/typcache.h" /* GUC parameters */ @@ -109,6 +110,18 @@ typedef struct int *tleref_to_colnum_map; } grouping_sets_data; +typedef struct replace_cached_expressions_context +{ + PlannerInfo *root; + + /* + * Pointers are nulls if the parent nodes don't use CaseTestExpr / + * CoerceToDomainValue nodes respectively. + */ + bool *innermost_nonconst_or_noncached_casetestexpr; + bool *innermost_nonconst_or_noncached_coercetodomainvalue; +} replace_cached_expressions_context; + /* Local functions */ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode); @@ -185,6 +198,8 @@ static PathTarget *make_sort_input_target(PlannerInfo *root, bool *have_postponed_srfs); static void adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel, List *targets, List *targets_contain_srfs); +static Node *replace_cached_expressions_mutator(Node *node, + replace_cached_expressions_context *context); /***************************************************************************** @@ -201,7 +216,7 @@ static void adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel, * *****************************************************************************/ PlannedStmt * -planner(Query *parse, int cursorOptions, ParamListInfo boundParams) +planner(Query *parse, int cursorOptions, ParamListInfoCommon boundParams) { PlannedStmt *result; @@ -213,7 +228,8 @@ planner(Query *parse, int cursorOptions, ParamListInfo boundParams) } PlannedStmt * -standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) +standard_planner(Query *parse, int cursorOptions, + ParamListInfoCommon boundParams) { PlannedStmt *result; PlannerGlobal *glob; @@ -480,6 +496,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->utilityStmt = parse->utilityStmt; result->stmt_location = parse->stmt_location; result->stmt_len = parse->stmt_len; + result->hasCachedExpr = root->hasCachedExpr; return result; } @@ -554,6 +571,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, else root->wt_param_id = -1; root->non_recursive_path = NULL; + root->hasCachedExpr = false; /* * If there is a WITH list, process each WITH query and build an initplan @@ -1220,6 +1238,7 @@ inheritance_planner(PlannerInfo *root) */ subroot = makeNode(PlannerInfo); memcpy(subroot, parent_root, sizeof(PlannerInfo)); + subroot->hasCachedExpr = false; /* * Generate modified query with this rel as target. We first apply @@ -6083,6 +6102,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) root->query_level = 1; root->planner_cxt = CurrentMemoryContext; root->wt_param_id = -1; + root->hasCachedExpr = false; /* Build a minimal RTE for the rel */ rte = makeNode(RangeTblEntry); @@ -6201,3 +6221,1205 @@ get_partitioned_child_rels_for_join(PlannerInfo *root, Relids join_relids) return result; } + +/* + * replace_pathtarget_cached_expressions + * Replace cached expresisons in a PathTarget tlist. + * + * As a notational convenience, returns the same PathTarget pointer passed in. + */ +PathTarget * +replace_pathtarget_cached_expressions(PathTarget *target, PlannerInfo *root) +{ + replace_cached_expressions_context context; + + context.root = root; + context.innermost_nonconst_or_noncached_casetestexpr = NULL; + context.innermost_nonconst_or_noncached_coercetodomainvalue = NULL; + + target->exprs = (List *) replace_cached_expressions_mutator( + (Node *) target->exprs, &context); + + return target; +} + +/* + * replace_qual_cached_expressions + * Replace cacehd expressions in a WHERE clause. The input can be either an + * implicitly-ANDed list of boolean expressions, or a list of RestrictInfo + * nodes. + */ +List * +replace_qual_cached_expressions(List *quals, PlannerInfo *root) +{ + replace_cached_expressions_context context; + + context.root = root; + context.innermost_nonconst_or_noncached_casetestexpr = NULL; + context.innermost_nonconst_or_noncached_coercetodomainvalue = NULL; + + return (List *) replace_cached_expressions_mutator((Node *) quals, + &context); +} + +/* + * Return true if node is null or const or CachedExpr or extern const parameter. + */ +static bool +is_cached_or_const(Expr *node, ParamListInfoCommon boundParams) +{ + if (node == NULL || IsA(node, Const) || IsA(node, CachedExpr)) + return true; + + if (IsA(node, Param)) + { + Param *param = (Param *) node; + int paramid = param->paramid; + ParamListInfoDataType boundParamsType; + + if (param->paramkind != PARAM_EXTERN || + paramid <= 0 || + boundParams == NULL) + return false; + + boundParamsType = boundParams->type; + + switch (boundParamsType) + { + case PARAM_LIST_INFO_DATA: + { + ParamListInfo params = (ParamListInfo) boundParams; + + return (paramid <= params->numParams && + params->params[paramid - 1].pflags & + PARAM_FLAG_CONST); + } + case PARAM_LIST_INFO_PRECALCULATION_DATA: + { + ParamListInfoPrecalculation params = + (ParamListInfoPrecalculation) boundParams; + + return (paramid <= params->numParams && + params->isConstParam[paramid - 1]); + } + default: + elog(ERROR, "unrecognized ParamListInfoData type: %d", + (int) boundParamsType); + break; + } + } + + return false; +} + +static Node * +replace_cached_expressions_mutator(Node *node, + replace_cached_expressions_context *context) +{ + ParamListInfoCommon boundParams = context->root->glob->boundParams; + + if (node == NULL) + return NULL; + + /* mutate certain types of nodes */ + if (IsA(node, CachedExpr)) + { + /* nothing to mutate */ + return node; + } + else if (IsA(node, RestrictInfo)) + { + RestrictInfo *rinfo = (RestrictInfo *) node; + + /* + * For an OR clause, recurse into the marked-up tree so that we replace + * cached expressions for contained RestrictInfos too. + */ + if (rinfo->orclause) + rinfo->orclause = (Expr *) replace_cached_expressions_mutator( + (Node *) rinfo->orclause, context); + else + rinfo->clause = (Expr *) replace_cached_expressions_mutator( + (Node *) rinfo->clause, context); + + /* do NOT recurse into children */ + return node; + } + else if (IsA(node, ArrayRef)) + { + /* + * ArrayRef is cached if all its subexpressions (refupperindexpr etc.) + * are consts or cached expressions too. (it returns array or array + * single element so we don't need to check if it returns set; and + * knowing its inputs its behaviour is quite defined so we don't need to + * check volatility) + */ + ArrayRef *aref = (ArrayRef *) node; + ListCell *indexpr; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + aref = (ArrayRef *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + /* check expressions of upper array indexes */ + foreach(indexpr, aref->refupperindexpr) + { + if (!is_cached_or_const(lfirst(indexpr), boundParams)) + has_nonconst_or_noncached_input = true; + } + + /* check expressions of lower array indexes */ + foreach(indexpr, aref->reflowerindexpr) + { + if (!is_cached_or_const(lfirst(indexpr), boundParams)) + has_nonconst_or_noncached_input = true; + } + + /* check expression of array value */ + if (!is_cached_or_const(aref->refexpr, boundParams)) + has_nonconst_or_noncached_input = true; + + /* check expression of source value */ + if (!is_cached_or_const(aref->refassgnexpr, boundParams)) + has_nonconst_or_noncached_input = true; + + if (has_nonconst_or_noncached_input) + { + /* return ArrayRef, which will not be cached */ + return (Node *) aref; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) aref; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, FuncExpr)) + { + /* + * Function is cached if: + * 1) it doesn't return set, + * 2) it's not volatile itself, + * 3) its arguments are constants or cached expressions too. + */ + FuncExpr *funcexpr; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + bool func_returns_set; + + /* firstly recurse into children */ + funcexpr = (FuncExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + func_returns_set = funcexpr->funcretset || + expression_returns_set((Node *) funcexpr->args); + + foreach(arg, funcexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (func_returns_set || + has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) funcexpr)) + { + /* return FuncExpr, which will not be cached */ + return (Node *) funcexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) funcexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, OpExpr)) + { + /* + * Operator is cached if: + * 1) its function doesn't return set, + * 1) its function is not volatile itself, + * 3) its arguments are constants or cached expressions too. + */ + OpExpr *opexpr = (OpExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + bool op_returns_set; + + /* rely on struct equivalence to treat these all alike */ + set_opfuncid(opexpr); + + /* firstly recurse into children */ + opexpr = (OpExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + op_returns_set = opexpr->opretset || + expression_returns_set((Node *) opexpr->args); + + foreach(arg, opexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (op_returns_set || + has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) opexpr)) + { + /* return OpExpr, which will not be cached */ + return (Node *) opexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) opexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, DistinctExpr)) + { + /* + * Operator of DistinctExpr is cached if: + * 1) its function doesn't return set, + * 1) its function is not volatile itself, + * 3) its arguments are constants or cached expressions too. + */ + DistinctExpr *distinctexpr = (DistinctExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + bool op_returns_set; + + /* rely on struct equivalence to treat these all alike */ + set_opfuncid((OpExpr *) distinctexpr); + + /* firstly recurse into children */ + distinctexpr = (DistinctExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + op_returns_set = distinctexpr->opretset || + expression_returns_set((Node *) distinctexpr->args); + + foreach(arg, distinctexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (op_returns_set || + has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) distinctexpr)) + { + /* return DistinctExpr, which will not be cached */ + return (Node *) distinctexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) distinctexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, NullIfExpr)) + { + /* + * Operator of NullIfExpr is cached if: + * 1) its function doesn't return set, + * 1) its function is not volatile itself, + * 3) its arguments are constants or cached expressions too. + */ + NullIfExpr *nullifexpr = (NullIfExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + bool op_returns_set; + + /* rely on struct equivalence to treat these all alike */ + set_opfuncid((OpExpr *) nullifexpr); + + /* firstly recurse into children */ + nullifexpr = (NullIfExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + op_returns_set = nullifexpr->opretset || + expression_returns_set((Node *) nullifexpr->args); + + foreach(arg, nullifexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (op_returns_set || + has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) nullifexpr)) + { + /* return NullIfExpr, which will not be cached */ + return (Node *) nullifexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) nullifexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, ScalarArrayOpExpr)) + { + /* + * Operator of ScalarArrayOpExpr is cached if: + * 1) its function is not volatile itself, + * 2) its arguments are constants or cached expressions too. + * (it returns boolean so we don't need to check if it returns set) + */ + ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + set_sa_opfuncid(saopexpr); + + /* firstly recurse into children */ + saopexpr = (ScalarArrayOpExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, saopexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) saopexpr)) + { + /* return ScalarArrayOpExpr, which will not be cached */ + return (Node *) saopexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) saopexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, BoolExpr)) + { + /* + * BoolExpr is cached if its arguments are constants or cached + * expressions too. (it returns boolean so we don't need to check if it + * returns set; and its too simple for evaluation so we don't need to + * check volatility) + */ + BoolExpr *boolexpr = (BoolExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + boolexpr = (BoolExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, boolexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return BoolExpr, which will not be cached */ + return (Node *) boolexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) boolexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, FieldSelect)) + { + /* + * FieldSelect is cached if its argument is const or cached expression + * too. (it returns one field from a tuple value so we don't need to + * check if it returns set; and knowing its argument its behaviour is + * quite defined so we don't need to check volatility) + */ + FieldSelect *fselect = (FieldSelect *) node; + + /* firstly recurse into children */ + fselect = (FieldSelect *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(fselect->arg, boundParams)) + { + /* return FieldSelect, which will not be cached */ + return (Node *) fselect; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) fselect; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, RelabelType)) + { + /* + * RelabelType is cached if its argument is const or cached expression + * too. (it returns its argument so we don't need to check if it returns + * set; and it is a no-op at runtime so we don't need to check + * volatility) + */ + RelabelType *relabel = (RelabelType *) node; + + /* firstly recurse into children */ + relabel = (RelabelType *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(relabel->arg, boundParams)) + { + /* return RelabelType, which will not be cached */ + return (Node *) relabel; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) relabel; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CoerceViaIO)) + { + /* + * CoerceViaIO is cached if: + * 1) its argument is const or cached expression too, + * 2) the source type's typoutput function and the destination type's + * typinput function are not volatile themselves. + * (it returns its argument with a type coercion so we don't need + * to check if it returns set) + */ + CoerceViaIO *iocoerce = (CoerceViaIO *) node; + + /* firstly recurse into children */ + iocoerce = (CoerceViaIO *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(iocoerce->arg, boundParams) || + contain_volatile_functions((Node *) iocoerce)) + { + /* return CoerceViaIO, which will not be cached */ + return (Node *) iocoerce; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) iocoerce; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, ArrayCoerceExpr)) + { + /* + * ArrayCoerceExpr is cached if: + * 1) its element-type coercion expression can be cached, + * 2) its argument is const or cached expression too. + * (it returns its argument with a type coercion so we don't need to + * check if it returns set) + */ + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; + Expr *elemexpr; + bool has_nonconst_or_noncached_input = false; + bool nonconst_or_noncached_arg; + replace_cached_expressions_context new_context; + + /* firstly recurse into children */ + acoerce = (ArrayCoerceExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + /* check arg and fill new context */ + nonconst_or_noncached_arg = !is_cached_or_const(acoerce->arg, + boundParams); + has_nonconst_or_noncached_input = nonconst_or_noncached_arg; + + new_context.root = context->root; + new_context.innermost_nonconst_or_noncached_casetestexpr = + &nonconst_or_noncached_arg; + new_context.innermost_nonconst_or_noncached_coercetodomainvalue = + context->innermost_nonconst_or_noncached_coercetodomainvalue; + + /* + * Recurse into element-type coercion expression with new context (it + * will be used by CaseTestExpr if it's used here). + */ + elemexpr = (Expr *) replace_cached_expressions_mutator( + (Node *) acoerce->elemexpr, + (void *) &new_context); + + /* check elemexpr */ + if (!is_cached_or_const(elemexpr, boundParams)) + has_nonconst_or_noncached_input = true; + + if (has_nonconst_or_noncached_input) + { + /* return ArrayCoerceExpr, which will not be cached */ + return (Node *) acoerce; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) acoerce; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, ConvertRowtypeExpr)) + { + /* + * ConvertRowtypeExpr is cached if its argument is const or cached + * expression too. (it returns its argument (row) maybe without values + * of some columns so we don't need to check if it returns set; and + * knowing its argument its behaviour is quite defined so we don't need + * to check volatility) + */ + ConvertRowtypeExpr *convexpr = (ConvertRowtypeExpr *) node; + + /* firstly recurse into children */ + convexpr = (ConvertRowtypeExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(convexpr->arg, boundParams)) + { + /* return ConvertRowtypeExpr, which will not be cached */ + return (Node *) convexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) convexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CaseExpr)) + { + /* + * CaseExpr is cached if all its arguments (= implicit equality + * comparison argument and WHEN clauses) and the default result + * expression are consts or cached expressions too. (it returns one of + * its arguments or the default result so we don't need to check if it + * returns set; and knowing its arguments its behaviour is quite defined + * so we don't need to check volatility) + */ + CaseExpr *caseexpr = (CaseExpr *) node; + CaseExpr *new_caseexpr; + bool has_nonconst_or_noncached_input = false; + bool nonconst_or_noncached_testvalue; + replace_cached_expressions_context new_context; + ListCell *cell; + + /* + * Recurse into node manually because we will need different context for + * its subnodes. + */ + new_caseexpr = (CaseExpr *) palloc(sizeof(CaseExpr)); + memcpy((new_caseexpr), (caseexpr), sizeof(CaseExpr)); + + /* recurse into arg */ + new_caseexpr->arg = (Expr *) replace_cached_expressions_mutator( + (Node *) new_caseexpr->arg, + context); + + /* check arg and fill new context */ + nonconst_or_noncached_testvalue = !is_cached_or_const(new_caseexpr->arg, + boundParams); + has_nonconst_or_noncached_input = nonconst_or_noncached_testvalue; + + new_context.root = context->root; + new_context.innermost_nonconst_or_noncached_casetestexpr = + &nonconst_or_noncached_testvalue; + new_context.innermost_nonconst_or_noncached_coercetodomainvalue = + context->innermost_nonconst_or_noncached_coercetodomainvalue; + + /* + * Recurse into args with new context (it will be used by CaseTestExpr + * if it's used in current WHEN clauses subtrees). + */ + new_caseexpr->args = (List *) replace_cached_expressions_mutator( + (Node *) new_caseexpr->args, + (void *) &new_context); + + /* check args */ + foreach(cell, new_caseexpr->args) + { + CaseWhen *casewhen = lfirst(cell); + + if (!is_cached_or_const(casewhen->expr, boundParams) || + !is_cached_or_const(casewhen->result, boundParams)) + has_nonconst_or_noncached_input = true; + } + + /* recurse into defresult */ + new_caseexpr->defresult = (Expr *) replace_cached_expressions_mutator( + (Node *) new_caseexpr->defresult, + context); + + /* check defresult */ + if (!is_cached_or_const(new_caseexpr->defresult, boundParams)) + has_nonconst_or_noncached_input = true; + + if (has_nonconst_or_noncached_input) + { + /* return CaseExpr, which will not be cached */ + return (Node *) new_caseexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) new_caseexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CaseTestExpr)) + { + /* + * CaseTestExpr is cached if we got in context that it is in CaseExpr/ + * ArrayCoerceExpr and arg of innermost CaseExpr/ArrayCoerceExpr is + * const or cached expression too. (it is a placeholder node for the + * test value of its CaseExpr/source element of its ArrayCoerceExpr so + * we don't need to check if it returns set and we don't need to check + * volatility) + */ + CaseTestExpr *casetest = (CaseTestExpr *) node; + + if (!context->innermost_nonconst_or_noncached_casetestexpr || + *(context->innermost_nonconst_or_noncached_casetestexpr)) + { + /* return CaseTestExpr, which will not be cached */ + return (Node *) casetest; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) casetest; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, ArrayExpr)) + { + /* + * ArrayExpr is cached if its elements are consts or cached expressions + * too. (it returns array so we don't need to check if it returns set; + * and knowing its elements its behaviour is quite defined so we don't + * need to check volatility) + */ + ArrayExpr *arrayexpr = (ArrayExpr *) node; + ListCell *element; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + arrayexpr = (ArrayExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(element, arrayexpr->elements) + { + if (!is_cached_or_const(lfirst(element), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return ArrayExpr, which will not be cached */ + return (Node *) arrayexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) arrayexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, RowExpr)) + { + /* + * RowExpr is cached if its arguments are consts or cached expressions + * too. (it returns tuple so we don't need to check if it returns set; + * and knowing its arguments its behaviour is quite defined so we don't + * need to check volatility) + */ + RowExpr *rowexpr = (RowExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + rowexpr = (RowExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, rowexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return RowExpr, which will not be cached */ + return (Node *) rowexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) rowexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, RowCompareExpr)) + { + /* + * RowCompareExpr is cached if: + * 1) its pairwise comparison operators are not volatile themselves, + * 2) its arguments are consts or cached expressions too. + * (it returns boolean so we don't need to check if it returns set) + */ + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + rcexpr = (RowCompareExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, rcexpr->largs) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + foreach(arg, rcexpr->rargs) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input || + contain_volatile_functions((Node *) rcexpr)) + { + /* return RowCompareExpr, which will not be cached */ + return (Node *) rcexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) rcexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CoalesceExpr)) + { + /* + * CoalesceExpr is cached if its arguments are consts or cached + * expressions too. (it returns one of its arguments so we don't need to + * check if it returns set; and knowing its arguments its behaviour is + * quite defined so we don't need to check volatility) + */ + CoalesceExpr *coalesce = (CoalesceExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + coalesce = (CoalesceExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, coalesce->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return CoalesceExpr, which will not be cached */ + return (Node *) coalesce; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) coalesce; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, MinMaxExpr)) + { + /* + * MinMaxExpr is cached if its arguments are consts or cached + * expressions too. (it returns one of its arguments so we don't need to + * check if it returns set; and it uses btree comparison functions so we + * don't need to check volatility) + */ + MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + minmaxexpr = (MinMaxExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, minmaxexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return MinMaxExpr, which will not be cached */ + return (Node *) minmaxexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) minmaxexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, SQLValueFunction)) + { + /* + * SQLValueFunction is always cached because all of these functions + * don't return a set and are stable. + */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) node; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + else if (IsA(node, XmlExpr)) + { + /* + * XmlExpr is cached if all its arguments are consts or cached + * expressions too. (it returns values of different types so we don't + * need to check if it returns set; and knowing its arguments its + * behaviour is quite defined so we don't need to check volatility) + */ + XmlExpr *xexpr = (XmlExpr *) node; + ListCell *arg; + bool has_nonconst_or_noncached_input = false; + + /* firstly recurse into children */ + xexpr = (XmlExpr *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + foreach(arg, xexpr->named_args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + foreach(arg, xexpr->args) + { + if (!is_cached_or_const(lfirst(arg), boundParams)) + has_nonconst_or_noncached_input = true; + } + + if (has_nonconst_or_noncached_input) + { + /* return XmlExpr, which will not be cached */ + return (Node *) xexpr; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) xexpr; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, NullTest)) + { + /* + * NullTest is cached if its argument is const or cached expression too. + * (it returns boolean so we don't need to check if it returns set; and + * knowing its argument its behaviour is quite defined so we don't need + * to check volatility) + */ + NullTest *nulltest = (NullTest *) node; + + /* firstly recurse into children */ + nulltest = (NullTest *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(nulltest->arg, boundParams)) + { + /* return NullTest, which will not be cached */ + return (Node *) nulltest; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) nulltest; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, BooleanTest)) + { + /* + * BooleanTest is cached if its argument is const or cached expression + * too. (it returns boolean so we don't need to check if it returns set; + * and knowing its argument its behaviour is quite defined so we don't + * need to check volatility) + */ + BooleanTest *btest = (BooleanTest *) node; + + /* firstly recurse into children */ + btest = (BooleanTest *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + if (!is_cached_or_const(btest->arg, boundParams)) + { + /* return BooleanTest, which will not be cached */ + return (Node *) btest; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) btest; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CoerceToDomain)) + { + /* + * CoerceToDomain is cached if: + * 1) its constraints can be cached, + * 2) its argument is const or cached expression too. + * (it returns its argument coercing a value to a domain type so we + * don't need to check if it returns set) + */ + CoerceToDomain *ctest = (CoerceToDomain *) node; + bool has_nonconst_or_noncached_input = false; + bool nonconst_or_noncached_value; + replace_cached_expressions_context new_context; + DomainConstraintRef *constraint_ref; + List *constraints; + ListCell *cell; + + /* firstly recurse into children */ + ctest = (CoerceToDomain *) expression_tree_mutator( + node, + replace_cached_expressions_mutator, + (void *) context); + + /* check arg and fill new context */ + nonconst_or_noncached_value = !is_cached_or_const(ctest->arg, + boundParams); + has_nonconst_or_noncached_input = nonconst_or_noncached_value; + + new_context.root = context->root; + new_context.innermost_nonconst_or_noncached_casetestexpr = + context->innermost_nonconst_or_noncached_casetestexpr; + new_context.innermost_nonconst_or_noncached_coercetodomainvalue = + &nonconst_or_noncached_value; + + /* get constraints and recurse into them with new context */ + constraint_ref = (DomainConstraintRef *) + palloc(sizeof(DomainConstraintRef)); + InitDomainConstraintRef(ctest->resulttype, + constraint_ref, + context->root->planner_cxt, + false); + constraints = GetDomainConstraintExprList(constraint_ref); + foreach(cell, constraints) + { + DomainConstraintExpr *con = (DomainConstraintExpr *) lfirst(cell); + Expr *check_expr = con->check_expr; + + switch (con->constrainttype) + { + case DOM_CONSTRAINT_NOTNULL: + /* OK */ + break; + case DOM_CONSTRAINT_CHECK: + check_expr = (Expr *) replace_cached_expressions_mutator( + (Node *) check_expr, + &new_context); + if (!is_cached_or_const(check_expr, boundParams)) + has_nonconst_or_noncached_input = true; + break; + default: + elog(ERROR, "unrecognized constraint type: %d", + (int) con->constrainttype); + break; + } + } + + if (has_nonconst_or_noncached_input) + { + /* return RowCompareExpr, which will not be cached */ + return (Node *) ctest; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) ctest; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + else if (IsA(node, CoerceToDomainValue)) + { + /* + * CoerceToDomainValue is cached if we got in context that it is in + * CoerceToDomain expression and arg of innermost CoerceToDomain + * expression is const or cached expression too. (it is a placeholder + * node for the value of its CoerceToDomain expression so we don't need + * to check if it returns set and we don't need to check volatility) + */ + CoerceToDomainValue *domval = (CoerceToDomainValue *) node; + + if (!context->innermost_nonconst_or_noncached_coercetodomainvalue || + *(context->innermost_nonconst_or_noncached_coercetodomainvalue)) + { + /* return CoerceToDomainValue, which will not be cached */ + return (Node *) domval; + } + else + { + /* create and return CachedExpr */ + CachedExpr *new_node = makeNode(CachedExpr); + new_node->subexpr = (CacheableExpr *) domval; + + context->root->hasCachedExpr = true; + + return (Node *) new_node; + } + } + + /* otherwise recurse into children */ + return expression_tree_mutator(node, replace_cached_expressions_mutator, + (void *) context); +} diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 1d7e499..099d7fb 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -918,6 +918,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, subroot->hasRecursion = false; subroot->wt_param_id = -1; subroot->non_recursive_path = NULL; + subroot->hasCachedExpr = false; /* No CTEs to worry about */ Assert(subquery->cteList == NIL); diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 9ca384d..5cacff9 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -62,7 +62,7 @@ typedef struct typedef struct { - ParamListInfo boundParams; + ParamListInfoCommon boundParams; PlannerInfo *root; List *active_fns; Node *case_val; @@ -980,6 +980,11 @@ contain_volatile_functions_walker(Node *node, void *context) /* NextValueExpr is volatile */ return true; } + else if (IsA(node, CachedExpr)) + { + /* CachedExpr is not volatile */ + return false; + } /* * See notes in contain_mutable_functions_walker about why we treat @@ -2513,7 +2518,13 @@ eval_const_expressions_mutator(Node *node, case T_Param: { Param *param = (Param *) node; - ParamListInfo paramLI = context->boundParams; + ParamListInfo paramLI; + + if (context->boundParams != NULL && + context->boundParams->type == PARAM_LIST_INFO_DATA) + paramLI = (ParamListInfo) context->boundParams; + else + paramLI = NULL; /* Look to see if we've been given a value for this Param */ if (param->paramkind == PARAM_EXTERN && @@ -2625,6 +2636,32 @@ eval_const_expressions_mutator(Node *node, return (Node *) newexpr; } + case T_CachedExpr: + { + CachedExpr *cachedexpr = (CachedExpr *) node; + CacheableExpr *new_subexpr = (CacheableExpr *) + eval_const_expressions_mutator((Node *) cachedexpr->subexpr, + context); + CachedExpr *new_cachedexpr; + + if (IsA(new_subexpr, Const)) + { + /* successfully simplified it */ + return (Node *) new_subexpr; + } + else + { + /* + * The expression cannot be simplified any further, so build + * and return a replacement CachedExpr node using the + * possibly-simplified arguments of subexpression. + */ + new_cachedexpr = makeNode(CachedExpr); + new_cachedexpr->subexpr = new_subexpr; + + return (Node *) new_cachedexpr; + } + } case T_FuncExpr: { FuncExpr *expr = (FuncExpr *) node; diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 4c4f4cd..9c51285 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -1111,6 +1111,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry) root->parse = qry; root->planner_cxt = CurrentMemoryContext; root->hasJoinRTEs = true; + root->hasCachedExpr = false; groupClauses = (List *) flatten_join_alias_vars(root, (Node *) groupClauses); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 1b24ddd..d7477d4 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -787,7 +787,8 @@ pg_rewrite_query(Query *query) * This is a thin wrapper around planner() and takes the same parameters. */ PlannedStmt * -pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams) +pg_plan_query(Query *querytree, int cursorOptions, + ParamListInfoCommon boundParams) { PlannedStmt *plan; @@ -848,7 +849,8 @@ pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams) * The result is a list of PlannedStmt nodes. */ List * -pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams) +pg_plan_queries(List *querytrees, int cursorOptions, + ParamListInfoCommon boundParams) { List *stmt_list = NIL; ListCell *query_list; @@ -867,6 +869,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams) stmt->utilityStmt = query->utilityStmt; stmt->stmt_location = query->stmt_location; stmt->stmt_len = query->stmt_len; + stmt->hasCachedExpr = false; } else { @@ -1644,6 +1647,7 @@ exec_bind_message(StringInfo input_message) params = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) + numParams * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ + params->common.type = PARAM_LIST_INFO_DATA; params->paramFetch = NULL; params->paramFetchArg = NULL; params->paramCompile = NULL; @@ -1794,7 +1798,8 @@ exec_bind_message(StringInfo input_message) * will be generated in MessageContext. The plan refcount will be * assigned to the Portal, so it will be released at portal destruction. */ - cplan = GetCachedPlan(psrc, params, false, NULL); + cplan = GetCachedPlan(psrc, (ParamListInfoCommon) params, false, NULL, + false); /* * Now we can define the portal. diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 4da1f8f..db31839 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1068,6 +1068,7 @@ ProcessUtilitySlow(ParseState *pstate, wrapper->utilityStmt = stmt; wrapper->stmt_location = pstmt->stmt_location; wrapper->stmt_len = pstmt->stmt_len; + wrapper->hasCachedExpr = false; ProcessUtility(wrapper, queryString, @@ -1148,6 +1149,7 @@ ProcessUtilitySlow(ParseState *pstate, wrapper->utilityStmt = stmt; wrapper->stmt_location = pstmt->stmt_location; wrapper->stmt_len = pstmt->stmt_len; + wrapper->hasCachedExpr = false; ProcessUtility(wrapper, queryString, PROCESS_UTILITY_SUBCOMMAND, diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c index 86f916f..ff7586a 100644 --- a/src/backend/utils/adt/domains.c +++ b/src/backend/utils/adt/domains.c @@ -138,7 +138,8 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) foreach(l, my_extra->constraint_ref.constraints) { - DomainConstraintState *con = (DomainConstraintState *) lfirst(l); + DomainConstraintState *con_state = (DomainConstraintState *) lfirst(l); + DomainConstraintExpr *con = con_state->expr; switch (con->constrainttype) { @@ -178,7 +179,7 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) my_extra->constraint_ref.tcache->typlen); econtext->domainValue_isNull = isnull; - if (!ExecCheck(con->check_exprstate, econtext)) + if (!ExecCheck(con_state->check_exprstate, econtext)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("value for domain %s violates check constraint \"%s\"", diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 8514c21..2e72e74 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7661,6 +7661,11 @@ get_rule_expr(Node *node, deparse_context *context, get_windowfunc_expr((WindowFunc *) node, context); break; + case T_CachedExpr: + get_rule_expr((Node *) ((CachedExpr *) node)->subexpr, context, + showimplicit); + break; + case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 853c1f6..25e4c7e 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -90,11 +90,12 @@ static CachedPlanSource *first_saved_plan = NULL; static void ReleaseGenericPlan(CachedPlanSource *plansource); static List *RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv); -static bool CheckCachedPlan(CachedPlanSource *plansource); +static bool CheckCachedPlan(CachedPlanSource *plansource, + ParamListInfoPrecalculation boundParams); static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist, - ParamListInfo boundParams, QueryEnvironment *queryEnv); + ParamListInfoCommon boundParams, QueryEnvironment *queryEnv); static bool choose_custom_plan(CachedPlanSource *plansource, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); static double cached_plan_cost(CachedPlan *plan, bool include_planner); static Query *QueryListGetPrimaryStmt(List *stmts); static void AcquireExecutorLocks(List *stmt_list, bool acquire); @@ -785,6 +786,65 @@ RevalidateCachedQuery(CachedPlanSource *plansource, } /* + * CheckNotConst: check if the bound params are not constants. + */ +static bool +CheckNotConst(ParamListInfoPrecalculation boundParams, int start_index) +{ + int index; + + if (boundParams == NULL) + return true; + + if (start_index < 0) + start_index = 0; + + for (index = start_index; index < boundParams->numParams; ++index) + { + if (boundParams->isConstParam[index]) + return false; + } + + return true; +} + +/* + * CheckBoundParams: check if bound params are compatible in the generic plan. + */ +static bool +CheckBoundParams(ParamListInfoPrecalculation firstBoundParams, + ParamListInfoPrecalculation secondBoundParams) +{ + int numCommonParams, + index; + + if (firstBoundParams == NULL || secondBoundParams == NULL) + numCommonParams = 0; + else if (firstBoundParams->numParams <= secondBoundParams->numParams) + numCommonParams = firstBoundParams->numParams; + else + numCommonParams = secondBoundParams->numParams; + + /* + * Check that the common parameters are equal (both are constants or both + * are not). + */ + for (index = 0; index < numCommonParams; ++index) + { + if (firstBoundParams->isConstParam[index] != + secondBoundParams->isConstParam[index]) + return false; + } + + /* + * Check that the other parameters are not constants, so they have not + * previously been precalculated and will not be precalculated. + */ + return (CheckNotConst(firstBoundParams, numCommonParams) && + CheckNotConst(secondBoundParams, numCommonParams)); +} + +/* * CheckCachedPlan: see if the CachedPlanSource's generic plan is valid. * * Caller must have already called RevalidateCachedQuery to verify that the @@ -794,7 +854,8 @@ RevalidateCachedQuery(CachedPlanSource *plansource, * (We must do this for the "true" result to be race-condition-free.) */ static bool -CheckCachedPlan(CachedPlanSource *plansource) +CheckCachedPlan(CachedPlanSource *plansource, + ParamListInfoPrecalculation boundParams) { CachedPlan *plan = plansource->gplan; @@ -845,8 +906,10 @@ CheckCachedPlan(CachedPlanSource *plansource) */ if (plan->is_valid) { - /* Successfully revalidated and locked the query. */ - return true; + /* + * Successfully revalidated and locked the query. Check boundParams. + */ + return CheckBoundParams(plan->boundParams, boundParams); } /* Oops, the race case happened. Release useless locks. */ @@ -879,7 +942,7 @@ CheckCachedPlan(CachedPlanSource *plansource) */ static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, - ParamListInfo boundParams, QueryEnvironment *queryEnv) + ParamListInfoCommon boundParams, QueryEnvironment *queryEnv) { CachedPlan *plan; List *plist; @@ -1002,6 +1065,35 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist, plan->is_saved = false; plan->is_valid = true; + /* + * Specify the precalculation parameters. If the plan is not one-shot, make + * a deep copy. + */ + if (boundParams != NULL && + boundParams->type == PARAM_LIST_INFO_PRECALCULATION_DATA) + { + ParamListInfoPrecalculation params = + (ParamListInfoPrecalculation) boundParams; + + if (!plansource->is_oneshot) + { + plan->boundParams = (ParamListInfoPrecalculation) palloc( + offsetof(ParamListInfoPrecalculationData, isConstParam) + + params->numParams * sizeof(bool)); + + memcpy(plan->boundParams, params, + sizeof(ParamListInfoPrecalculationData)); + } + else + { + plan->boundParams = params; + } + } + else + { + plan->boundParams = NULL; + } + /* assign generation number to new plan */ plan->generation = ++(plansource->generation); @@ -1016,7 +1108,8 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist, * This defines the policy followed by GetCachedPlan. */ static bool -choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams) +choose_custom_plan(CachedPlanSource *plansource, + ParamListInfoCommon boundParams) { double avg_custom_cost; @@ -1025,7 +1118,8 @@ choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams) return true; /* Otherwise, never any point in a custom plan if there's no parameters */ - if (boundParams == NULL) + if (boundParams == NULL || + boundParams->type != PARAM_LIST_INFO_DATA) return false; /* ... nor for transaction control statements */ if (IsTransactionStmtPlan(plansource)) @@ -1114,6 +1208,50 @@ cached_plan_cost(CachedPlan *plan, bool include_planner) } /* + * GetPrecalculationData: get ParamListInfoPrecalculationData from the source. + */ +static ParamListInfoPrecalculation +GetPrecalculationData(ParamListInfoCommon boundParams) +{ + ParamListInfoPrecalculation result; + ParamListInfoDataType boundParamsType; + + if (boundParams == NULL) + return NULL; + + boundParamsType = boundParams->type; + + switch (boundParamsType) + { + case PARAM_LIST_INFO_DATA: + { + ParamListInfo params = (ParamListInfo) boundParams; + int index; + + result = (ParamListInfoPrecalculation) palloc( + offsetof(ParamListInfoPrecalculationData, isConstParam) + + params->numParams * sizeof(bool)); + + result->common.type = PARAM_LIST_INFO_PRECALCULATION_DATA; + result->numParams = params->numParams; + for (index = 0; index < params->numParams; ++index) + result->isConstParam[index] = + params->params[index].pflags & PARAM_FLAG_CONST; + } + break; + case PARAM_LIST_INFO_PRECALCULATION_DATA: + result = (ParamListInfoPrecalculation) boundParams; + break; + default: + elog(ERROR, "unrecognized ParamListInfoData type: %d", + (int) boundParamsType); + break; + } + + return result; +} + +/* * GetCachedPlan: get a cached plan from a CachedPlanSource. * * This function hides the logic that decides whether to use a generic @@ -1130,14 +1268,22 @@ cached_plan_cost(CachedPlan *plan, bool include_planner) * * Note: if any replanning activity is required, the caller's memory context * is used for that work. + * + * Note: set genericPlanPrecalculateConstBoundParams to true only if you are + * sure that the bound parameters will remain (non)constant quite often for the + * next calls to this function. Otherwise the generic plan will be rebuilt each + * time when there's a bound parameter that was constant for the previous + * generic plan and is not constant now or vice versa. */ CachedPlan * -GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, - bool useResOwner, QueryEnvironment *queryEnv) +GetCachedPlan(CachedPlanSource *plansource, ParamListInfoCommon boundParams, + bool useResOwner, QueryEnvironment *queryEnv, + bool genericPlanPrecalculateConstBoundParams) { CachedPlan *plan = NULL; List *qlist; bool customplan; + ParamListInfoPrecalculation genericPlanBoundParams; /* Assert caller is doing things in a sane order */ Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); @@ -1154,7 +1300,13 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, if (!customplan) { - if (CheckCachedPlan(plansource)) + /* set the parameters for the generic plan */ + if (genericPlanPrecalculateConstBoundParams) + genericPlanBoundParams = GetPrecalculationData(boundParams); + else + genericPlanBoundParams = NULL; + + if (CheckCachedPlan(plansource, genericPlanBoundParams)) { /* We want a generic plan, and we already have a valid one */ plan = plansource->gplan; @@ -1163,7 +1315,9 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, else { /* Build a new generic plan */ - plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv); + plan = BuildCachedPlan(plansource, qlist, + (ParamListInfoCommon) genericPlanBoundParams, + queryEnv); /* Just make real sure plansource->gplan is clear */ ReleaseGenericPlan(plansource); /* Link the new generic plan into the plansource */ diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index f6450c4..b40bed9 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -946,7 +946,8 @@ load_domaintype_info(TypeCacheEntry *typentry) bool isNull; char *constring; Expr *check_expr; - DomainConstraintState *r; + DomainConstraintState *r_state; + DomainConstraintExpr *r; /* Ignore non-CHECK constraints (presently, shouldn't be any) */ if (c->contype != CONSTRAINT_CHECK) @@ -985,11 +986,14 @@ load_domaintype_info(TypeCacheEntry *typentry) /* ExecInitExpr will assume we've planned the expression */ check_expr = expression_planner(check_expr); - r = makeNode(DomainConstraintState); + r_state = makeNode(DomainConstraintState); + r_state->expr = makeNode(DomainConstraintExpr); + r = r_state->expr; + r->constrainttype = DOM_CONSTRAINT_CHECK; r->name = pstrdup(NameStr(c->conname)); r->check_expr = check_expr; - r->check_exprstate = NULL; + r_state->check_exprstate = NULL; MemoryContextSwitchTo(oldcxt); @@ -1006,7 +1010,7 @@ load_domaintype_info(TypeCacheEntry *typentry) ccons = (DomainConstraintState **) repalloc(ccons, cconslen * sizeof(DomainConstraintState *)); } - ccons[nccons++] = r; + ccons[nccons++] = r_state; } systable_endscan(scan); @@ -1043,7 +1047,8 @@ load_domaintype_info(TypeCacheEntry *typentry) */ if (notNull) { - DomainConstraintState *r; + DomainConstraintState *r_state; + DomainConstraintExpr *r; /* Create the DomainConstraintCache object and context if needed */ if (dcc == NULL) @@ -1063,15 +1068,17 @@ load_domaintype_info(TypeCacheEntry *typentry) /* Create node trees in DomainConstraintCache's context */ oldcxt = MemoryContextSwitchTo(dcc->dccContext); - r = makeNode(DomainConstraintState); + r_state = makeNode(DomainConstraintState); + r_state->expr = makeNode(DomainConstraintExpr); + r = r_state->expr; r->constrainttype = DOM_CONSTRAINT_NOTNULL; r->name = pstrdup("NOT NULL"); r->check_expr = NULL; - r->check_exprstate = NULL; + r_state->check_exprstate = NULL; /* lcons to apply the nullness check FIRST */ - dcc->constraints = lcons(r, dcc->constraints); + dcc->constraints = lcons(r_state, dcc->constraints); MemoryContextSwitchTo(oldcxt); } @@ -1100,7 +1107,7 @@ dcs_cmp(const void *a, const void *b) const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a; const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b; - return strcmp((*ca)->name, (*cb)->name); + return strcmp((*ca)->expr->name, (*cb)->expr->name); } /* @@ -1150,16 +1157,21 @@ prep_domain_constraints(List *constraints, MemoryContext execctx) foreach(lc, constraints) { - DomainConstraintState *r = (DomainConstraintState *) lfirst(lc); - DomainConstraintState *newr; + DomainConstraintState *r_state = (DomainConstraintState *) lfirst(lc); + DomainConstraintExpr *r = r_state->expr; + DomainConstraintState *newr_state; + DomainConstraintExpr *newr; + + newr_state = makeNode(DomainConstraintState); + newr_state->expr = makeNode(DomainConstraintExpr); + newr = newr_state->expr; - newr = makeNode(DomainConstraintState); newr->constrainttype = r->constrainttype; newr->name = r->name; newr->check_expr = r->check_expr; - newr->check_exprstate = ExecInitExpr(r->check_expr, NULL); + newr_state->check_exprstate = ExecInitExpr(r->check_expr, NULL); - result = lappend(result, newr); + result = lappend(result, newr_state); } MemoryContextSwitchTo(oldcxt); @@ -1278,6 +1290,22 @@ DomainHasConstraints(Oid type_id) return (typentry->domainData != NULL); } +/* + * Return list of DomainConstraintExpr of DomainConstraintState elements of the + * given list. + */ +List * +GetDomainConstraintExprList(DomainConstraintRef *ref) +{ + List *result = NIL; + ListCell *lc; + + foreach(lc, ref->constraints) + result = lappend(result, ((DomainConstraintState *) lfirst(lc))->expr); + + return result; +} + /* * array_element_has_equality and friends are helper routines to check diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 080252f..aedefdb 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -219,6 +219,16 @@ typedef enum ExprEvalOp EEOP_SUBPLAN, EEOP_ALTERNATIVE_SUBPLAN, + /* + * Evaluate CachedExpr. EEOP_CACHEDEXPR_IF_CACHED is used before + * subexpression evaluation (if subexpression was evaluated use cached value + * and jump to next state or get prepared to subexpression evaluation + * otherwise). EEOP_CACHEDEXPR_SUBEXPR_END is used after subexpression + * evaluation for caching its result. + */ + EEOP_CACHEDEXPR_IF_CACHED, + EEOP_CACHEDEXPR_SUBEXPR_END, + /* non-existent operation, used e.g. to check array lengths */ EEOP_LAST } ExprEvalOp; @@ -574,6 +584,13 @@ typedef struct ExprEvalStep /* out-of-line state, created by nodeSubplan.c */ AlternativeSubPlanState *asstate; } alternative_subplan; + + /* for EEOP_CACHEDEXPR_* */ + struct + { + /* steps for evaluation the same CachedExpr have the same state */ + struct CachedExprState *state; + } cachedexpr; } d; } ExprEvalStep; @@ -614,6 +631,20 @@ typedef struct ArrayRefState } ArrayRefState; +/* + * Non-inline data for EEOP_CACHEDEXPR_* operations (steps for evaluation the + * same CachedExpr have the same state). + */ +typedef struct CachedExprState +{ + bool isExecuted; + bool resnull; + Datum resvalue; + Oid restypid; /* for copying resvalue of subexpression */ + int jumpdone; /* jump here if result determined */ +} CachedExprState; + + /* functions in execExpr.c */ extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index c9a5279..d21d5cb 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -801,25 +801,14 @@ typedef struct AlternativeSubPlanState int active; /* list index of the one we're using */ } AlternativeSubPlanState; -/* - * DomainConstraintState - one item to check during CoerceToDomain - * - * Note: we consider this to be part of an ExprState tree, so we give it - * a name following the xxxState convention. But there's no directly - * associated plan-tree node. +/* ---------------- + * DomainConstraintState node + * ---------------- */ -typedef enum DomainConstraintType -{ - DOM_CONSTRAINT_NOTNULL, - DOM_CONSTRAINT_CHECK -} DomainConstraintType; - typedef struct DomainConstraintState { NodeTag type; - DomainConstraintType constrainttype; /* constraint type */ - char *name; /* name of constraint (for error msgs) */ - Expr *check_expr; /* for CHECK, a boolean expression */ + DomainConstraintExpr *expr; /* expression plan node */ ExprState *check_exprstate; /* check_expr's eval state, or NULL */ } DomainConstraintState; diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index c5b5115..31039be 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -149,6 +149,8 @@ typedef enum NodeTag T_Aggref, T_GroupingFunc, T_WindowFunc, + T_CacheableExpr, + T_CachedExpr, T_ArrayRef, T_FuncExpr, T_NamedArgExpr, @@ -180,6 +182,7 @@ typedef enum NodeTag T_NullTest, T_BooleanTest, T_CoerceToDomain, + T_DomainConstraintExpr, T_CoerceToDomainValue, T_SetToDefault, T_CurrentOfExpr, diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index b198db5..ce45e3e 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -96,6 +96,8 @@ typedef struct ParamExternData } ParamExternData; typedef struct ParamListInfoData *ParamListInfo; +typedef struct ParamListInfoCommonData *ParamListInfoCommon; +typedef struct ParamListInfoPrecalculationData *ParamListInfoPrecalculation; typedef ParamExternData *(*ParamFetchHook) (ParamListInfo params, int paramid, bool speculative, @@ -107,8 +109,20 @@ typedef void (*ParamCompileHook) (ParamListInfo params, struct Param *param, typedef void (*ParserSetupHook) (struct ParseState *pstate, void *arg); +typedef enum ParamListInfoDataType +{ + PARAM_LIST_INFO_DATA, /* for ParamListInfoData */ + PARAM_LIST_INFO_PRECALCULATION_DATA /* for ParamListInfoPrecalculationData */ +} ParamListInfoDataType; + +typedef struct ParamListInfoCommonData +{ + ParamListInfoDataType type; +} ParamListInfoCommonData; + typedef struct ParamListInfoData { + ParamListInfoCommonData common; ParamFetchHook paramFetch; /* parameter fetch hook */ void *paramFetchArg; ParamCompileHook paramCompile; /* parameter compile hook */ @@ -150,6 +164,14 @@ typedef struct ParamExecData } ParamExecData; +typedef struct ParamListInfoPrecalculationData +{ + ParamListInfoCommonData common; + int numParams; /* number of elements in isConstParam array */ + bool isConstParam[FLEXIBLE_ARRAY_MEMBER]; +} ParamListInfoPrecalculationData; + + /* Functions found in src/backend/nodes/params.c */ extern ParamListInfo copyParamList(ParamListInfo from); extern Size EstimateParamListSpace(ParamListInfo paramLI); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index d763da6..7a25c15 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -96,6 +96,8 @@ typedef struct PlannedStmt /* statement location in source string (copied from Query) */ int stmt_location; /* start location, or -1 if unknown */ int stmt_len; /* length in bytes; 0 means "rest of string" */ + + bool hasCachedExpr; /* true if any expressions are cached */ } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 074ae0a..5fa1dff 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -364,6 +364,38 @@ typedef struct WindowFunc int location; /* token location, or -1 if unknown */ } WindowFunc; +/* + * CacheableExpr - generic suberclass for expressions that can be cacheable. + * + * All expression node types that can be cacheable should derive from + * CacheableExpr (that is, have CacheableExpr as their first field). Since + * CacheableExpr only contains NodeTag, this is a formality, but it is an easy + * form of documentation. + * + * Expression is cached (= is are calculated once for all output rows, but as + * many times as expression is mentioned in query), if: + * - it doesn't return a set + * - it is not volatile itself + * - its arguments are constants or recursively precalculated expressions. + * + * In planner if expression can be cached it becomes a part of CachedExpr node. + */ +typedef struct CacheableExpr +{ + NodeTag type; +} CacheableExpr; + +/* + * CachedExpr - expression node for cached expressions (= they are calculated + * once for all output rows, but as many times as function is mentioned in + * query). + */ +typedef struct CachedExpr +{ + Expr xpr; + CacheableExpr *subexpr; /* expression to be cached */ +} CachedExpr; + /* ---------------- * ArrayRef: describes an array subscripting operation * @@ -395,7 +427,7 @@ typedef struct WindowFunc */ typedef struct ArrayRef { - Expr xpr; + CacheableExpr xpr; Oid refarraytype; /* type of the array proper */ Oid refelemtype; /* type of the array elements */ int32 reftypmod; /* typmod of the array (and elements too) */ @@ -445,7 +477,7 @@ typedef enum CoercionForm */ typedef struct FuncExpr { - Expr xpr; + CacheableExpr xpr; Oid funcid; /* PG_PROC OID of the function */ Oid funcresulttype; /* PG_TYPE OID of result value */ bool funcretset; /* true if function returns set */ @@ -492,7 +524,7 @@ typedef struct NamedArgExpr */ typedef struct OpExpr { - Expr xpr; + CacheableExpr xpr; Oid opno; /* PG_OPERATOR OID of the operator */ Oid opfuncid; /* PG_PROC OID of underlying function */ Oid opresulttype; /* PG_TYPE OID of result value */ @@ -535,7 +567,7 @@ typedef OpExpr NullIfExpr; */ typedef struct ScalarArrayOpExpr { - Expr xpr; + CacheableExpr xpr; Oid opno; /* PG_OPERATOR OID of the operator */ Oid opfuncid; /* PG_PROC OID of underlying function */ bool useOr; /* true for ANY, false for ALL */ @@ -558,7 +590,7 @@ typedef enum BoolExprType typedef struct BoolExpr { - Expr xpr; + CacheableExpr xpr; BoolExprType boolop; List *args; /* arguments to this expression */ int location; /* token location, or -1 if unknown */ @@ -738,7 +770,7 @@ typedef struct AlternativeSubPlan typedef struct FieldSelect { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ AttrNumber fieldnum; /* attribute number of field to extract */ Oid resulttype; /* type of the field (result type of this @@ -790,7 +822,7 @@ typedef struct FieldStore typedef struct RelabelType { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ Oid resulttype; /* output type of coercion expression */ int32 resulttypmod; /* output typmod (usually -1) */ @@ -810,7 +842,7 @@ typedef struct RelabelType typedef struct CoerceViaIO { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ Oid resulttype; /* output type of coercion */ /* output typmod is not stored, but is presumed -1 */ @@ -834,7 +866,7 @@ typedef struct CoerceViaIO typedef struct ArrayCoerceExpr { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression (yields an array) */ Expr *elemexpr; /* expression representing per-element work */ Oid resulttype; /* output type of coercion (an array type) */ @@ -859,7 +891,7 @@ typedef struct ArrayCoerceExpr typedef struct ConvertRowtypeExpr { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ Oid resulttype; /* output type (always a composite type) */ /* Like RowExpr, we deliberately omit a typmod and collation here */ @@ -906,7 +938,7 @@ typedef struct CollateExpr */ typedef struct CaseExpr { - Expr xpr; + CacheableExpr xpr; Oid casetype; /* type of expression result */ Oid casecollid; /* OID of collation, or InvalidOid if none */ Expr *arg; /* implicit equality comparison argument */ @@ -936,7 +968,7 @@ typedef struct CaseWhen */ typedef struct CaseTestExpr { - Expr xpr; + CacheableExpr xpr; Oid typeId; /* type for substituted value */ int32 typeMod; /* typemod for substituted value */ Oid collation; /* collation for the substituted value */ @@ -952,7 +984,7 @@ typedef struct CaseTestExpr */ typedef struct ArrayExpr { - Expr xpr; + CacheableExpr xpr; Oid array_typeid; /* type of expression result */ Oid array_collid; /* OID of collation, or InvalidOid if none */ Oid element_typeid; /* common type of array elements */ @@ -986,7 +1018,7 @@ typedef struct ArrayExpr */ typedef struct RowExpr { - Expr xpr; + CacheableExpr xpr; List *args; /* the fields */ Oid row_typeid; /* RECORDOID or a composite type's ID */ @@ -1034,7 +1066,7 @@ typedef enum RowCompareType typedef struct RowCompareExpr { - Expr xpr; + CacheableExpr xpr; RowCompareType rctype; /* LT LE GE or GT, never EQ or NE */ List *opnos; /* OID list of pairwise comparison ops */ List *opfamilies; /* OID list of containing operator families */ @@ -1048,7 +1080,7 @@ typedef struct RowCompareExpr */ typedef struct CoalesceExpr { - Expr xpr; + CacheableExpr xpr; Oid coalescetype; /* type of expression result */ Oid coalescecollid; /* OID of collation, or InvalidOid if none */ List *args; /* the arguments */ @@ -1066,7 +1098,7 @@ typedef enum MinMaxOp typedef struct MinMaxExpr { - Expr xpr; + CacheableExpr xpr; Oid minmaxtype; /* common type of arguments and result */ Oid minmaxcollid; /* OID of collation of result */ Oid inputcollid; /* OID of collation that function should use */ @@ -1107,7 +1139,7 @@ typedef enum SQLValueFunctionOp typedef struct SQLValueFunction { - Expr xpr; + CacheableExpr xpr; SQLValueFunctionOp op; /* which function this is */ Oid type; /* result type/typmod */ int32 typmod; @@ -1145,7 +1177,7 @@ typedef enum typedef struct XmlExpr { - Expr xpr; + CacheableExpr xpr; XmlExprOp op; /* xml function ID */ char *name; /* name in xml(NAME foo ...) syntaxes */ List *named_args; /* non-XML expressions for xml_attributes */ @@ -1183,7 +1215,7 @@ typedef enum NullTestType typedef struct NullTest { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ bool argisrow; /* T to perform field-by-field null checks */ @@ -1206,7 +1238,7 @@ typedef enum BoolTestType typedef struct BooleanTest { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ BoolTestType booltesttype; /* test type */ int location; /* token location, or -1 if unknown */ @@ -1223,7 +1255,7 @@ typedef struct BooleanTest */ typedef struct CoerceToDomain { - Expr xpr; + CacheableExpr xpr; Expr *arg; /* input expression */ Oid resulttype; /* domain type ID (result type) */ int32 resulttypmod; /* output typmod (currently always -1) */ @@ -1233,6 +1265,24 @@ typedef struct CoerceToDomain } CoerceToDomain; /* + * DomainConstraintExpr - one item to check during CoerceToDomain + */ + +typedef enum DomainConstraintType +{ + DOM_CONSTRAINT_NOTNULL, + DOM_CONSTRAINT_CHECK +} DomainConstraintType; + +typedef struct DomainConstraintExpr +{ + Expr xpr; + DomainConstraintType constrainttype; /* constraint type */ + char *name; /* name of constraint (for error msgs) */ + Expr *check_expr; /* for CHECK, a boolean expression */ +} DomainConstraintExpr; + +/* * Placeholder node for the value to be processed by a domain's check * constraint. This is effectively like a Param, but can be implemented more * simply since we need only one replacement value at a time. @@ -1243,7 +1293,7 @@ typedef struct CoerceToDomain */ typedef struct CoerceToDomainValue { - Expr xpr; + CacheableExpr xpr; Oid typeId; /* type for substituted value */ int32 typeMod; /* typemod for substituted value */ Oid collation; /* collation for the substituted value */ diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 3b9d303..4c3b85f 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -93,7 +93,7 @@ typedef struct PlannerGlobal { NodeTag type; - ParamListInfo boundParams; /* Param values provided to planner() */ + ParamListInfoCommon boundParams; /* Param values provided to planner() */ List *subplans; /* Plans for SubPlan nodes */ @@ -317,6 +317,8 @@ typedef struct PlannerInfo /* optional private data for join_search_hook, e.g., GEQO */ void *join_search_private; + + bool hasCachedExpr; /* true if any expressions are cached */ } PlannerInfo; diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index 2801bfd..c77ce78 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -21,7 +21,7 @@ /* Hook for plugins to get control in planner() */ typedef PlannedStmt *(*planner_hook_type) (Query *parse, int cursorOptions, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); extern PGDLLIMPORT planner_hook_type planner_hook; /* Hook for plugins to get control when grouping_planner() plans upper rels */ @@ -33,9 +33,9 @@ extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook; extern PlannedStmt *planner(Query *parse, int cursorOptions, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); extern PlannedStmt *standard_planner(Query *parse, int cursorOptions, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); extern PlannerInfo *subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, @@ -61,4 +61,9 @@ extern List *get_partitioned_child_rels(PlannerInfo *root, Index rti); extern List *get_partitioned_child_rels_for_join(PlannerInfo *root, Relids join_relids); +extern PathTarget *replace_pathtarget_cached_expressions(PathTarget *target, + PlannerInfo *root); + +extern List *replace_qual_cached_expressions(List *quals, PlannerInfo *root); + #endif /* PLANNER_H */ diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h index 0d3ec92..1b4fd8f 100644 --- a/src/include/optimizer/tlist.h +++ b/src/include/optimizer/tlist.h @@ -65,8 +65,12 @@ extern void split_pathtarget_at_srfs(PlannerInfo *root, PathTarget *target, PathTarget *input_target, List **targets, List **targets_contain_srfs); -/* Convenience macro to get a PathTarget with valid cost/width fields */ +/* + * Convenience macro to get a PathTarget with valid cost/width fields and + * cached expressions. + */ #define create_pathtarget(root, tlist) \ - set_pathtarget_cost_width(root, make_pathtarget_from_tlist(tlist)) + set_pathtarget_cost_width(root, replace_pathtarget_cached_expressions( \ + make_pathtarget_from_tlist(tlist), root)) #endif /* TLIST_H */ diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 62c7f6c..24ab0c8 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -58,9 +58,9 @@ extern List *pg_analyze_and_rewrite_params(RawStmt *parsetree, void *parserSetupArg, QueryEnvironment *queryEnv); extern PlannedStmt *pg_plan_query(Query *querytree, int cursorOptions, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); extern List *pg_plan_queries(List *querytrees, int cursorOptions, - ParamListInfo boundParams); + ParamListInfoCommon boundParams); extern bool check_max_stack_depth(int *newval, void **extra, GucSource source); extern void assign_max_stack_depth(int newval, void *extra); diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index 87fab19..2dadb88 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -138,6 +138,13 @@ typedef struct CachedPlan bool dependsOnRole; /* is plan specific to that role? */ TransactionId saved_xmin; /* if valid, replan when TransactionXmin * changes from this value */ + + /* + * Used to check whether the generic plan is valid for the new + * boundParams; NULL for the custom plans. + */ + ParamListInfoPrecalculation boundParams; + int generation; /* parent's generation number for this plan */ int refcount; /* count of live references to this struct */ MemoryContext context; /* context containing this CachedPlan */ @@ -177,9 +184,10 @@ extern List *CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv); extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource, - ParamListInfo boundParams, + ParamListInfoCommon boundParams, bool useResOwner, - QueryEnvironment *queryEnv); + QueryEnvironment *queryEnv, + bool genericPlanPrecalculateConstBoundParams); extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner); #endif /* PLANCACHE_H */ diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h index c203dab..6760c8c 100644 --- a/src/include/utils/typcache.h +++ b/src/include/utils/typcache.h @@ -167,6 +167,8 @@ extern void UpdateDomainConstraintRef(DomainConstraintRef *ref); extern bool DomainHasConstraints(Oid type_id); +extern List * GetDomainConstraintExprList(DomainConstraintRef *ref); + extern TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod); extern TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index dd575e7..97fc003 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3453,6 +3453,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate, /* initialize our ParamListInfo with appropriate hook functions */ estate->paramLI = (ParamListInfo) palloc(offsetof(ParamListInfoData, params)); + estate->paramLI->common.type = PARAM_LIST_INFO_DATA; estate->paramLI->paramFetch = plpgsql_param_fetch; estate->paramLI->paramFetchArg = (void *) estate; estate->paramLI->paramCompile = plpgsql_param_compile; @@ -6521,6 +6522,7 @@ exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) Query *query; CachedPlan *cplan; MemoryContext oldcontext; + ListCell *cell; /* * Initialize to "not simple". @@ -6602,6 +6604,22 @@ exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) /* Can't fail, because we checked for a single CachedPlanSource above */ Assert(cplan != NULL); + /* Check that there're no cached expressions in the plan. + * + * If CachedExpr will not be initialized by ExecInitCachedExpr possibly it + * will use cached value when it shouldn't (for example, snapshot has + * changed). + */ + foreach(cell, cplan->stmt_list) + { + if (((PlannedStmt *) cell->data.ptr_value)->hasCachedExpr) + { + /* Oops, release refcount and fail */ + ReleaseCachedPlan(cplan, true); + return; + } + } + /* Share the remaining work with replan code path */ exec_save_simple_expr(expr, cplan); diff --git a/src/test/regress/expected/precalculate_stable_functions.out b/src/test/regress/expected/precalculate_stable_functions.out new file mode 100644 index 0000000..6bb0c90 --- /dev/null +++ b/src/test/regress/expected/precalculate_stable_functions.out @@ -0,0 +1,6645 @@ +-- +-- PRECALCULATE STABLE FUNCTIONS +-- +-- Create types and tables for testing +CREATE TYPE my_integer AS (value integer); +CREATE TYPE composite_type AS (first integer, second integer[], third boolean); +CREATE TABLE x (x integer); +INSERT INTO x SELECT generate_series(1, 4) x; +CREATE TABLE wxyz (w integer, x integer[], y boolean, z integer); +CREATE TABLE wxyz_child () INHERITS (wxyz); +CREATE TABLE wxyz_child2 (a integer, b integer) INHERITS (wxyz); +CREATE TABLE no_columns (); +CREATE TABLE no_columns_child () INHERITS (no_columns); +CREATE TABLE no_columns_child2 (a integer, b integer) INHERITS (no_columns); +-- Create volatile functions for testing +CREATE OR REPLACE FUNCTION public.x_vlt ( +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_my_integer ( +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_array_integer ( +) +RETURNS int[] VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_boolean ( +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v boolean'; + RETURN TRUE; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz ( +) +RETURNS wxyz VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child ( +) +RETURNS wxyz_child VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child2 ( +) +RETURNS wxyz_child2 VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_oid ( +) +RETURNS oid VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_my_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_instruction_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_xml ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_xml_content ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt2 ( + integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_vlt ( + integer, + integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers volatile'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_vlt ( + my_integer, + my_integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer volatile'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_vlt ( + integer +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer volatile'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_vlt ( + my_integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer volatile'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Create stable functions for testing +CREATE OR REPLACE FUNCTION public.x_stl ( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_my_integer ( +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_array_integer ( +) +RETURNS int[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz ( +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child ( +) +RETURNS wxyz_child STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child2 ( +) +RETURNS wxyz_child2 STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_oid ( +) +RETURNS oid STABLE AS +$body$ +BEGIN + RAISE NOTICE 's oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_my_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_instruction_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_xml ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_xml_content ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2 ( + integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_strict ( + integer +) +RETURNS integer STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 's2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_boolean ( + boolean +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 boolean'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_integer ( + integer[] +) +RETURNS integer[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_oid ( + oid[] +) +RETURNS oid[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_oid'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_composite_type ( + composite_type +) +RETURNS composite_type STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 composite_type'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer ( + my_integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_no_columns ( + no_columns +) +RETURNS no_columns STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 no_columns'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_name ( + name +) +RETURNS name STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 name'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_xml ( + xml +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 xml'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_text ( + text +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 text'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_stl ( + integer, + integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers stable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_booleans_stl_strict ( + boolean, + boolean +) +RETURNS boolean STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans stable strict'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_stl ( + my_integer, + my_integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer stable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_stl ( + integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer stable'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_stl ( + my_integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer stable'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.stable_max( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN (SELECT max(x) from x); +END +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.simple( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN stable_max(); +END +$body$ +LANGUAGE 'plpgsql'; +-- Create immutable functions for testing +CREATE OR REPLACE FUNCTION public.x_imm2 ( + integer +) +RETURNS integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_imm2_strict ( + integer +) +RETURNS integer IMMUTABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'i2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_imm2_my_integer ( + my_integer +) +RETURNS my_integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_imm ( + integer, + integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_booleans_imm ( + boolean, + boolean +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_imm ( + my_integer, + my_integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer immutable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Create operators for testing +CREATE OPERATOR === ( + PROCEDURE = equal_integers_vlt, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ==== ( + PROCEDURE = equal_integers_stl, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ===== ( + PROCEDURE = equal_integers_imm, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ==== ( + PROCEDURE = equal_booleans_stl_strict, + LEFTARG = boolean, + RIGHTARG = boolean +); +CREATE OPERATOR ===== ( + PROCEDURE = equal_booleans_imm, + LEFTARG = boolean, + RIGHTARG = boolean +); +-- Create domains for testing +CREATE DOMAIN my_integer_no_check AS integer; +CREATE DOMAIN my_integer_not_null AS integer; +CREATE DOMAIN my_integer_vlt_check AS integer CHECK (VALUE === 1); +CREATE DOMAIN my_integer_stl_check AS integer CHECK (VALUE ==== 1); +CREATE DOMAIN my_integer_imm_check AS integer CHECK (VALUE ===== 1); +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_no_check ( + my_integer_no_check +) +RETURNS my_integer_no_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_no_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_not_null ( + my_integer_not_null +) +RETURNS my_integer_not_null STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_not_null'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_vlt_check ( + my_integer_vlt_check +) +RETURNS my_integer_vlt_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_stl_check ( + my_integer_stl_check +) +RETURNS my_integer_stl_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_imm_check ( + my_integer_imm_check +) +RETURNS my_integer_imm_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_imm_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_vlt_check ( + my_integer_vlt_check[] +) +RETURNS my_integer_vlt_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_stl_check ( + my_integer_stl_check[] +) +RETURNS my_integer_stl_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Functions testing +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl() FROM x; +NOTICE: s + x_stl +------- + 1 + 1 + 1 + 1 +(4 rows) + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 +(3 rows) + +SELECT x_stl() FROM x WHERE x_stl() < x; +NOTICE: s +NOTICE: s +NOTICE: s + x_stl +------- + 1 + 1 + 1 +(3 rows) + +-- JOIN/ON clause testing +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; +NOTICE: s +NOTICE: s + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 + x_vlt2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(1) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl()) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_stl()) FROM x; +NOTICE: s +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_stl2_strict +--------------- + + + + +(4 rows) + +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_imm2_strict +--------------- + + + + +(4 rows) + +-- Operators testing +SELECT 1 === 2 FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== 2 FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +NOTICE: s2 boolean + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; +NOTICE: s2 boolean +NOTICE: equal booleans immutable + ?column? +---------- + + + + +(4 rows) + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== 2) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT x_stl() ==== 1 FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- IS (NOT) DISTINCT FROM expression testing +-- create operator here because we will drop and reuse it several times +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- IS (NOT) DISTINCT FROM expressions with null arguments testing +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM 1) FROM x; +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM 1) FROM x; +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM x_stl2(NULL)) FROM x; +NOTICE: s2 +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM x_stl2(NULL)) FROM x; +NOTICE: s2 +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer immutable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- NULLIF expressions with null arguments testing +SELECT x_stl2(NULLIF(1, NULL)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(NULLIF(NULL::integer, NULL)) FROM x; +NOTICE: s2 + x_stl2 +-------- + + + + +(4 rows) + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions +-- testing +SELECT 1 === ANY ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 === ALL ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY ('{2, 3}') FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL ('{2, 3}') FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ===== ANY ('{2, 3}') FROM x; +NOTICE: equal integers immutable +NOTICE: equal integers immutable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ===== ALL ('{2, 3}') FROM x; +NOTICE: equal integers immutable + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer immutable +NOTICE: equal my_integer immutable + ?column? +---------- + f + f + f + f +(4 rows) + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions with +-- null arguments testing +SELECT 1 ==== ANY ('{2, NULL}') FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT NULL ==== ANY ('{2, 3}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT NULL ==== ANY ('{2, NULL}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL::integer ==== ANY (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT 1 ==== ALL ('{2, NULL}') FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT NULL ==== ALL ('{2, 3}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT NULL ==== ALL ('{2, NULL}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL::integer ==== ALL (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(1 IN (2, NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL IN (2, 3)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL IN (2, NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Boolean expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt(), 2]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[x_stl(), 2]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +-- Multidimensional ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[[x_vlt(), 2], [3, 4]]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[[x_stl(), 2], [3, 4]]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} +(4 rows) + +-- Array subscripting operations testing +SELECT x_stl2(('{1, 2}'::integer[])[1]) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_array_integer(('{1, 2}'::integer[])[:]) FROM x; +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +-- Mixed functions and array subscripting operations testing +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +NOTICE: s array_integer +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +NOTICE: s array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- FieldSelect expressions testing +SELECT x_stl2(('(1, {2}, TRUE, 3)'::wxyz).w) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(('(1)'::my_integer).value) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +NOTICE: s wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_my_integer()).value) FROM x; +NOTICE: s my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- ROW() expressions testing +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE, 3)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_composite_type((1, '{2}', TRUE)) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_composite_type(ROW(1, '{2}', TRUE)) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_composite_type((1, '{2}', TRUE)::composite_type) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- RelabelType expressions testing +-- should not be precalculated +SELECT x_stl2(x_vlt_oid()::integer) FROM x; +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_oid()::integer) FROM x; +NOTICE: s oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- CoerceViaIO expressions testing +SELECT x_stl2_my_integer('(1)'::text::my_integer) FROM x; +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; +NOTICE: s text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceViaIO expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; +NOTICE: s text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- ArrayCoerce expressions testing +-- Binary-coercible types: +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_vlt; +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; -- should not be precalculated +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile + my_integer +------------ + {(1),(2)} + {(1),(2)} + {(1),(2)} + {(1),(2)} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + my_integer +------------ + {(1),(2)} + {(1),(2)} + {(1),(2)} + {(1),(2)} +(4 rows) + +-- Mixed functions and ArrayCoerce expressions testing +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer stable +NOTICE: cast my_integer as integer stable +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_vlt_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +SELECT x_stl_array_integer()::my_integer[] FROM x; +NOTICE: s array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_stl_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +-- ConvertRowtypeExpr testing +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3)'::wxyz_child::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_no_columns('()'::no_columns_child::no_columns) FROM x; +NOTICE: s2 no_columns + x_stl2_no_columns +------------------- + () + () + () + () +(4 rows) + +SELECT x_stl2_no_columns('(1, 2)'::no_columns_child2::no_columns) FROM x; +NOTICE: s2 no_columns + x_stl2_no_columns +------------------- + () + () + () + () +(4 rows) + +-- Mixed functions and ConvertRowtypeExpr testing +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: s wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: s wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- CASE expressions testing +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; +NOTICE: s2 boolean +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; +NOTICE: s +NOTICE: s +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- RowCompareExpr testing +SELECT x_stl2_boolean((1, 2) < (1, 3)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and RowCompareExpr testing +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- COALESCE expressions testing +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; +NOTICE: s2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- GREATEST and LEAST functions testing +SELECT x_stl2(GREATEST(2, 1, 3)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, 1, 3)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and GREATEST and LEAST functions testing +-- should not be precalculated +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- SQLValueFunction testing +CREATE ROLE regress_testrol2 SUPERUSER; +CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2; +\c - +SET SESSION AUTHORIZATION regress_testrol1; +SET ROLE regress_testrol2; +SELECT x_stl2_boolean(date(now()) = current_date) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timetz = current_time) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timetz(2) = current_time(2)) FROM x; -- precision +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now() = current_timestamp) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- precision +SELECT x_stl2_boolean( + length(current_timestamp::text) >= length(current_timestamp(0)::text) +) +FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::time = localtime) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::time(2) = localtime(2)) FROM x; -- precision +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timestamp = localtimestamp) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- precision +SELECT x_stl2_boolean(now()::timestamp(2) = localtimestamp(2)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_name(current_role) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(current_user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(session_user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol1 + regress_testrol1 + regress_testrol1 + regress_testrol1 +(4 rows) + +SELECT x_stl2_name(current_catalog) FROM x; +NOTICE: s2 name + x_stl2_name +------------- + regression + regression + regression + regression +(4 rows) + +SELECT x_stl2_name(current_schema) FROM x; +NOTICE: s2 name + x_stl2_name +------------- + public + public + public + public +(4 rows) + +\c +DROP ROLE regress_testrol1, regress_testrol2; +-- Xml expressions testing +SELECT x_stl2_xml(XMLCONCAT('', 'foo')) FROM x; +NOTICE: s2 xml + x_stl2_xml +---------------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), 'cont', 'ent') +) +FROM x; +NOTICE: s2 xml + x_stl2_xml +------------------------------ + content + content + content + content +(4 rows) + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, 123 AS bar)) FROM x; +NOTICE: s2 xml + x_stl2_xml +------------------------------ + abc123 + abc123 + abc123 + abc123 +(4 rows) + +SELECT x_stl2_xml(XMLPARSE( + DOCUMENT 'Manual' +)) +FROM x; +NOTICE: s2 xml + x_stl2_xml +------------------------------------ + Manual + Manual + Manual + Manual +(4 rows) + +SELECT x_stl2_xml(XMLPARSE(CONTENT 'abcbarfoo')) FROM x; +NOTICE: s2 xml + x_stl2_xml +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_xml(XMLPI(name php, 'echo "hello world";')) FROM x; +NOTICE: s2 xml + x_stl2_xml +----------------------------- + + + + +(4 rows) + +SELECT x_stl2_xml(XMLROOT( + 'abc', + version '1.0', + standalone yes +)) +FROM x; +NOTICE: s2 xml + x_stl2_xml +-------------------------------------------------------------- + abc + abc + abc + abc +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE( + DOCUMENT 'Manual' AS text +)) +FROM x; +NOTICE: s2 text + x_stl2_text +--------------------------------------------------------- + Manual + Manual + Manual + Manual +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE( + CONTENT 'abcbarfoo' AS text +)) +FROM x; +NOTICE: s2 text + x_stl2_text +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_boolean('abcbarfoo' IS DOCUMENT) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +---------------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +----------------------------------------- + abcfoo + abcfoo + abcfoo + abcfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------ + Manual + Manual + Manual + Manual +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml + x_stl2_xml +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml + x_stl2_xml +----------------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------------------------ + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text + x_stl2_text +---------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text + x_stl2_text +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +---------------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +----------------------------------------- + abcfoo + abcfoo + abcfoo + abcfoo +(4 rows) + +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; +NOTICE: s text xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------ + Manual + Manual + Manual + Manual +(4 rows) + +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; +NOTICE: s xml content +NOTICE: s2 xml + x_stl2_xml +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; +NOTICE: s text xml instruction content +NOTICE: s2 xml + x_stl2_xml +----------------------------- + + + + +(4 rows) + +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------------------------ + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; +NOTICE: s xml +NOTICE: s2 text + x_stl2_text +---------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; +NOTICE: s xml content +NOTICE: s2 text + x_stl2_text +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; +NOTICE: s xml content +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- NullTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- BooleanTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- CoerceToDomain expressions testing +SELECT x_stl2_my_integer_no_check(1::my_integer_no_check) FROM x; +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(1::my_integer_not_null) FROM x; +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_vlt_check(1::my_integer_vlt_check) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check + x_stl2_my_integer_vlt_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(1::my_integer_stl_check) FROM x; +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(1::my_integer_imm_check) FROM x; +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +NOTICE: s +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +NOTICE: s +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; +NOTICE: s +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed ArrayCoerce and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_array_my_integer_vlt_check( + '{1, 1}'::integer[]::my_integer_vlt_check[] +) +FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check + x_stl2_array_my_integer_vlt_check +----------------------------------- + {1,1} + {1,1} + {1,1} + {1,1} +(4 rows) + +SELECT x_stl2_array_my_integer_stl_check( + '{1, 1}'::integer[]::my_integer_stl_check[] +) +FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 array_my_integer_stl_check + x_stl2_array_my_integer_stl_check +----------------------------------- + {1,1} + {1,1} + {1,1} + {1,1} +(4 rows) + +-- Tracking functions testing +SET track_functions TO 'all'; +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl() FROM x; +NOTICE: s + x_stl +------- + 1 + 1 + 1 + 1 +(4 rows) + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 +(3 rows) + +SELECT x_stl() FROM x WHERE x_stl() < x; +NOTICE: s +NOTICE: s +NOTICE: s + x_stl +------- + 1 + 1 + 1 +(3 rows) + +-- JOIN/ON clause testing +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; +NOTICE: s +NOTICE: s + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 + x_vlt2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(1) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl()) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_stl()) FROM x; +NOTICE: s +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_stl2_strict +--------------- + + + + +(4 rows) + +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_imm2_strict +--------------- + + + + +(4 rows) + +-- Operators testing +SELECT 1 === 2 FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== 2 FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +NOTICE: s2 boolean + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; +NOTICE: s2 boolean +NOTICE: equal booleans immutable + ?column? +---------- + + + + +(4 rows) + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== 2) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT x_stl() ==== 1 FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; -- should not be precalculated +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; -- should not be precalculated +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Mixed functions and boolean expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1} + {1} + {1} + {1} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1} + {1} + {1} + {1} +(4 rows) + +-- Mixed functions and array subscripting operations testing +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +NOTICE: s array_integer +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +NOTICE: s array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +NOTICE: s wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_my_integer()).value) FROM x; +NOTICE: s my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- Mixed functions and RelabelType expressions testing +SELECT x_stl2(x_vlt_oid()::integer) FROM x; -- should not be precalculated +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_oid()::integer) FROM x; +NOTICE: s oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceViaIO expressions testing +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; +NOTICE: s text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; +NOTICE: s text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- Mixed functions and ArrayCoerce expressions testing +-- Binary-coercible types: +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- Not binary-coercible types: +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer stable +NOTICE: cast my_integer as integer stable +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_vlt_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +SELECT x_stl_array_integer()::my_integer[] FROM x; +NOTICE: s array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_stl_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +-- Mixed functions and ConvertRowtypeExpr testing +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: s wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: s wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- Mixed functions and CASE expressions testing +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; +NOTICE: s2 boolean +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; +NOTICE: s +NOTICE: s +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and RowCompareExpr testing +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and COALESCE expressions testing +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; +NOTICE: s2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- Mixed functions and GREATEST and LEAST functions testing +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +---------------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +----------------------------------------- + abcfoo + abcfoo + abcfoo + abcfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml +NOTICE: v text xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------ + Manual + Manual + Manual + Manual +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml +NOTICE: v text xml content +NOTICE: s2 xml + x_stl2_xml +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml +NOTICE: v text xml instruction content +NOTICE: s2 xml + x_stl2_xml +----------------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml +NOTICE: v xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------------------------ + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text +NOTICE: v xml +NOTICE: s2 text + x_stl2_text +---------------- + foo + foo + foo + foo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text +NOTICE: v xml content +NOTICE: s2 text + x_stl2_text +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean +NOTICE: v xml content +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +---------------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +----------------------------------------- + abcfoo + abcfoo + abcfoo + abcfoo +(4 rows) + +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; +NOTICE: s text xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------ + Manual + Manual + Manual + Manual +(4 rows) + +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; +NOTICE: s xml content +NOTICE: s2 xml + x_stl2_xml +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; +NOTICE: s text xml instruction content +NOTICE: s2 xml + x_stl2_xml +----------------------------- + + + + +(4 rows) + +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: s xml +NOTICE: s2 xml + x_stl2_xml +------------------------------------------------------ + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; +NOTICE: s xml +NOTICE: s2 text + x_stl2_text +---------------- + foo + foo + foo + foo +(4 rows) + +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; +NOTICE: s xml content +NOTICE: s2 text + x_stl2_text +--------------------------------- + abcbarfoo + abcbarfoo + abcbarfoo + abcbarfoo +(4 rows) + +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; +NOTICE: s xml content +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and NullTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and BooleanTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +NOTICE: s +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +NOTICE: s +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; +NOTICE: s +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SET track_functions TO DEFAULT; +-- ROW() expressions with dropped columns testing +ALTER TABLE wxyz DROP COLUMN z; +-- Update some functions +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +-- ROW() expressions testing +SELECT x_stl2_wxyz((1, '{2}', TRUE)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz((1, '{2}', TRUE)::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- PL/pgSQL Simple expressions +-- Make sure precalculated stable functions can't be simple expressions: these +-- expressions are only initialized once per transaction and then executed +-- multiple times. +BEGIN; +SELECT simple(); + simple +-------- + 4 +(1 row) + +INSERT INTO x VALUES (5); +SELECT simple(); + simple +-------- + 5 +(1 row) + +ROLLBACK; +-- Prepared statements testing +PREPARE test_x_imm2 (integer) AS SELECT x_imm2(x_imm2($1)) FROM x; +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +-- Drop tables and domains for testing +DROP TABLE x; +DROP FUNCTION x_vlt_wxyz, x_vlt_wxyz_child, x_vlt_wxyz_child2; +DROP FUNCTION x_stl_wxyz, x_stl_wxyz_child, x_stl_wxyz_child2, x_stl2_wxyz; +DROP TABLE wxyz, wxyz_child, wxyz_child2; +DROP FUNCTION x_stl2_no_columns; +DROP TABLE no_columns, no_columns_child, no_columns_child2; +DROP FUNCTION x_stl2_my_integer_no_check; +DROP DOMAIN my_integer_no_check; +DROP FUNCTION x_stl2_my_integer_not_null; +DROP DOMAIN my_integer_not_null; +DROP FUNCTION x_stl2_my_integer_vlt_check; +DROP FUNCTION x_stl2_array_my_integer_vlt_check; +DROP DOMAIN my_integer_vlt_check; +DROP FUNCTION x_stl2_my_integer_stl_check; +DROP FUNCTION x_stl2_array_my_integer_stl_check; +DROP DOMAIN my_integer_stl_check; +DROP FUNCTION x_stl2_my_integer_imm_check; +DROP DOMAIN my_integer_imm_check; diff --git a/src/test/regress/expected/precalculate_stable_functions_1.out b/src/test/regress/expected/precalculate_stable_functions_1.out new file mode 100644 index 0000000..b640bd9 --- /dev/null +++ b/src/test/regress/expected/precalculate_stable_functions_1.out @@ -0,0 +1,6291 @@ +-- +-- PRECALCULATE STABLE FUNCTIONS +-- +-- Create types and tables for testing +CREATE TYPE my_integer AS (value integer); +CREATE TYPE composite_type AS (first integer, second integer[], third boolean); +CREATE TABLE x (x integer); +INSERT INTO x SELECT generate_series(1, 4) x; +CREATE TABLE wxyz (w integer, x integer[], y boolean, z integer); +CREATE TABLE wxyz_child () INHERITS (wxyz); +CREATE TABLE wxyz_child2 (a integer, b integer) INHERITS (wxyz); +CREATE TABLE no_columns (); +CREATE TABLE no_columns_child () INHERITS (no_columns); +CREATE TABLE no_columns_child2 (a integer, b integer) INHERITS (no_columns); +-- Create volatile functions for testing +CREATE OR REPLACE FUNCTION public.x_vlt ( +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_my_integer ( +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_array_integer ( +) +RETURNS int[] VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_boolean ( +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v boolean'; + RETURN TRUE; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz ( +) +RETURNS wxyz VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child ( +) +RETURNS wxyz_child VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child2 ( +) +RETURNS wxyz_child2 VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_oid ( +) +RETURNS oid VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_my_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_instruction_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_xml ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt_xml_content ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_vlt2 ( + integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_vlt ( + integer, + integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers volatile'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_vlt ( + my_integer, + my_integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer volatile'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_vlt ( + integer +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer volatile'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_vlt ( + my_integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer volatile'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Create stable functions for testing +CREATE OR REPLACE FUNCTION public.x_stl ( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_my_integer ( +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_array_integer ( +) +RETURNS int[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz ( +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child ( +) +RETURNS wxyz_child STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child2 ( +) +RETURNS wxyz_child2 STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_oid ( +) +RETURNS oid STABLE AS +$body$ +BEGIN + RAISE NOTICE 's oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_my_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_instruction_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_xml ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl_xml_content ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2 ( + integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_strict ( + integer +) +RETURNS integer STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 's2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_boolean ( + boolean +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 boolean'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_integer ( + integer[] +) +RETURNS integer[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_oid ( + oid[] +) +RETURNS oid[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_oid'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_composite_type ( + composite_type +) +RETURNS composite_type STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 composite_type'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer ( + my_integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_no_columns ( + no_columns +) +RETURNS no_columns STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 no_columns'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_name ( + name +) +RETURNS name STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 name'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_xml ( + xml +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 xml'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_text ( + text +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 text'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_stl ( + integer, + integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers stable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_booleans_stl_strict ( + boolean, + boolean +) +RETURNS boolean STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans stable strict'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_stl ( + my_integer, + my_integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer stable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_stl ( + integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer stable'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_stl ( + my_integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer stable'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.stable_max( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN (SELECT max(x) from x); +END +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.simple( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN stable_max(); +END +$body$ +LANGUAGE 'plpgsql'; +-- Create immutable functions for testing +CREATE OR REPLACE FUNCTION public.x_imm2 ( + integer +) +RETURNS integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_imm2_strict ( + integer +) +RETURNS integer IMMUTABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'i2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_imm2_my_integer ( + my_integer +) +RETURNS my_integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_integers_imm ( + integer, + integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_booleans_imm ( + boolean, + boolean +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.equal_my_integer_imm ( + my_integer, + my_integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer immutable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Create operators for testing +CREATE OPERATOR === ( + PROCEDURE = equal_integers_vlt, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ==== ( + PROCEDURE = equal_integers_stl, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ===== ( + PROCEDURE = equal_integers_imm, + LEFTARG = integer, + RIGHTARG = integer +); +CREATE OPERATOR ==== ( + PROCEDURE = equal_booleans_stl_strict, + LEFTARG = boolean, + RIGHTARG = boolean +); +CREATE OPERATOR ===== ( + PROCEDURE = equal_booleans_imm, + LEFTARG = boolean, + RIGHTARG = boolean +); +-- Create domains for testing +CREATE DOMAIN my_integer_no_check AS integer; +CREATE DOMAIN my_integer_not_null AS integer; +CREATE DOMAIN my_integer_vlt_check AS integer CHECK (VALUE === 1); +CREATE DOMAIN my_integer_stl_check AS integer CHECK (VALUE ==== 1); +CREATE DOMAIN my_integer_imm_check AS integer CHECK (VALUE ===== 1); +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_no_check ( + my_integer_no_check +) +RETURNS my_integer_no_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_no_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_not_null ( + my_integer_not_null +) +RETURNS my_integer_not_null STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_not_null'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_vlt_check ( + my_integer_vlt_check +) +RETURNS my_integer_vlt_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_stl_check ( + my_integer_stl_check +) +RETURNS my_integer_stl_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_imm_check ( + my_integer_imm_check +) +RETURNS my_integer_imm_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_imm_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_vlt_check ( + my_integer_vlt_check[] +) +RETURNS my_integer_vlt_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_stl_check ( + my_integer_stl_check[] +) +RETURNS my_integer_stl_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +-- Functions testing +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl() FROM x; +NOTICE: s + x_stl +------- + 1 + 1 + 1 + 1 +(4 rows) + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 +(3 rows) + +SELECT x_stl() FROM x WHERE x_stl() < x; +NOTICE: s +NOTICE: s +NOTICE: s + x_stl +------- + 1 + 1 + 1 +(3 rows) + +-- JOIN/ON clause testing +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; +NOTICE: s +NOTICE: s + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 + x_vlt2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(1) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl()) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_stl()) FROM x; +NOTICE: s +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_stl2_strict +--------------- + + + + +(4 rows) + +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_imm2_strict +--------------- + + + + +(4 rows) + +-- Operators testing +SELECT 1 === 2 FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== 2 FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +NOTICE: s2 boolean + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; +NOTICE: s2 boolean +NOTICE: equal booleans immutable + ?column? +---------- + + + + +(4 rows) + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== 2) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT x_stl() ==== 1 FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- IS (NOT) DISTINCT FROM expression testing +-- create operator here because we will drop and reuse it several times +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- IS (NOT) DISTINCT FROM expressions with null arguments testing +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM 1) FROM x; +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM 1) FROM x; +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM x_stl2(NULL)) FROM x; +NOTICE: s2 +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM x_stl2(NULL)) FROM x; +NOTICE: s2 +NOTICE: s2 +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; +NOTICE: equal my_integer immutable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- NULLIF expressions with null arguments testing +SELECT x_stl2(NULLIF(1, NULL)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(NULLIF(NULL::integer, NULL)) FROM x; +NOTICE: s2 + x_stl2 +-------- + + + + +(4 rows) + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions +-- testing +SELECT 1 === ANY ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 === ALL ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY ('{2, 3}') FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL ('{2, 3}') FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ===== ANY ('{2, 3}') FROM x; +NOTICE: equal integers immutable +NOTICE: equal integers immutable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ===== ALL ('{2, 3}') FROM x; +NOTICE: equal integers immutable + ?column? +---------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: equal my_integer immutable +NOTICE: equal my_integer immutable + ?column? +---------- + f + f + f + f +(4 rows) + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions with +-- null arguments testing +SELECT 1 ==== ANY ('{2, NULL}') FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT NULL ==== ANY ('{2, 3}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT NULL ==== ANY ('{2, NULL}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL::integer ==== ANY (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT 1 ==== ALL ('{2, NULL}') FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT NULL ==== ALL ('{2, 3}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT NULL ==== ALL ('{2, NULL}'::integer[]) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL::integer ==== ALL (NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(1 IN (2, NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL IN (2, 3)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL IN (2, NULL)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + + + + +(4 rows) + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Boolean expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt(), 2]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[x_stl(), 2]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +-- Multidimensional ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[[x_vlt(), 2], [3, 4]]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[[x_stl(), 2], [3, 4]]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} + {{1,2},{3,4}} +(4 rows) + +-- Array subscripting operations testing +SELECT x_stl2(('{1, 2}'::integer[])[1]) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_array_integer(('{1, 2}'::integer[])[:]) FROM x; +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +-- Mixed functions and array subscripting operations testing +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +NOTICE: s array_integer +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +NOTICE: s array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- FieldSelect expressions testing +SELECT x_stl2(('(1, {2}, TRUE, 3)'::wxyz).w) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(('(1)'::my_integer).value) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +NOTICE: s wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_my_integer()).value) FROM x; +NOTICE: s my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- ROW() expressions testing +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE, 3)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_composite_type((1, '{2}', TRUE)) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_composite_type(ROW(1, '{2}', TRUE)) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_composite_type((1, '{2}', TRUE)::composite_type) FROM x; +NOTICE: s2 composite_type + x_stl2_composite_type +----------------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- RelabelType expressions testing +-- should not be precalculated +SELECT x_stl2(x_vlt_oid()::integer) FROM x; +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_oid()::integer) FROM x; +NOTICE: s oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- CoerceViaIO expressions testing +SELECT x_stl2_my_integer('(1)'::text::my_integer) FROM x; +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; +NOTICE: s text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceViaIO expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; +NOTICE: s text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- ArrayCoerce expressions testing +-- Binary-coercible types: +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_vlt; +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; -- should not be precalculated +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile +NOTICE: cast integer as my_integer volatile + my_integer +------------ + {(1),(2)} + {(1),(2)} + {(1),(2)} + {(1),(2)} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + my_integer +------------ + {(1),(2)} + {(1),(2)} + {(1),(2)} + {(1),(2)} +(4 rows) + +-- Mixed functions and ArrayCoerce expressions testing +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer stable +NOTICE: cast my_integer as integer stable +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_vlt_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +SELECT x_stl_array_integer()::my_integer[] FROM x; +NOTICE: s array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_stl_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +-- ConvertRowtypeExpr testing +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3)'::wxyz_child::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_no_columns('()'::no_columns_child::no_columns) FROM x; +NOTICE: s2 no_columns + x_stl2_no_columns +------------------- + () + () + () + () +(4 rows) + +SELECT x_stl2_no_columns('(1, 2)'::no_columns_child2::no_columns) FROM x; +NOTICE: s2 no_columns + x_stl2_no_columns +------------------- + () + () + () + () +(4 rows) + +-- Mixed functions and ConvertRowtypeExpr testing +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: s wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: s wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- CASE expressions testing +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; +NOTICE: s2 boolean +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; +NOTICE: s +NOTICE: s +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- RowCompareExpr testing +SELECT x_stl2_boolean((1, 2) < (1, 3)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and RowCompareExpr testing +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- COALESCE expressions testing +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; +NOTICE: s2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- GREATEST and LEAST functions testing +SELECT x_stl2(GREATEST(2, 1, 3)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, 1, 3)) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and GREATEST and LEAST functions testing +-- should not be precalculated +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- SQLValueFunction testing +CREATE ROLE regress_testrol2 SUPERUSER; +CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2; +\c - +SET SESSION AUTHORIZATION regress_testrol1; +SET ROLE regress_testrol2; +SELECT x_stl2_boolean(date(now()) = current_date) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timetz = current_time) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timetz(2) = current_time(2)) FROM x; -- precision +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now() = current_timestamp) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- precision +SELECT x_stl2_boolean( + length(current_timestamp::text) >= length(current_timestamp(0)::text) +) +FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::time = localtime) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::time(2) = localtime(2)) FROM x; -- precision +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(now()::timestamp = localtimestamp) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- precision +SELECT x_stl2_boolean(now()::timestamp(2) = localtimestamp(2)) FROM x; +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_name(current_role) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(current_user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol2 + regress_testrol2 + regress_testrol2 + regress_testrol2 +(4 rows) + +SELECT x_stl2_name(session_user) FROM x; +NOTICE: s2 name + x_stl2_name +------------------ + regress_testrol1 + regress_testrol1 + regress_testrol1 + regress_testrol1 +(4 rows) + +SELECT x_stl2_name(current_catalog) FROM x; +NOTICE: s2 name + x_stl2_name +------------- + regression + regression + regression + regression +(4 rows) + +SELECT x_stl2_name(current_schema) FROM x; +NOTICE: s2 name + x_stl2_name +------------- + public + public + public + public +(4 rows) + +\c +DROP ROLE regress_testrol1, regress_testrol2; +-- Xml expressions testing +SELECT x_stl2_xml(XMLCONCAT('', 'foo')) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_xml(XMLCONCAT('', 'foo')) FRO... + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), 'cont', 'ent') +) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, 123 AS bar)) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE( + DOCUMENT 'Manual' +)) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE(CONTENT 'abcbarfoo')) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPI(name php, 'echo "hello world";')) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLROOT( + 'abc', + version '1.0', + standalone yes +)) +FROM x; +ERROR: unsupported XML feature +LINE 2: 'abc', + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_text(XMLSERIALIZE( + DOCUMENT 'Manual' AS text +)) +FROM x; +ERROR: unsupported XML feature +LINE 2: DOCUMENT 'Manual... + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_text(XMLSERIALIZE( + CONTENT 'abcbarfoo' AS text +)) +FROM x; +ERROR: unsupported XML feature +LINE 2: CONTENT 'abcbarfoo' AS text + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_boolean('abcbarfoo' IS DOCUMENT) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_boolean('abcbarfoo' IS D... + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; +NOTICE: v text xml +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; +NOTICE: v text xml content +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: v xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; +NOTICE: v xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; +NOTICE: v xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml_content() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; +NOTICE: v xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml_content() line 4 at RETURN +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; +NOTICE: s text xml +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: s xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_stl_xml() line 4 at RETURN +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; +NOTICE: s xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_stl_xml() line 4 at RETURN +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_stl_xml_content() line 4 at RETURN +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_stl_xml_content() line 4 at RETURN +-- NullTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- BooleanTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- CoerceToDomain expressions testing +SELECT x_stl2_my_integer_no_check(1::my_integer_no_check) FROM x; +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(1::my_integer_not_null) FROM x; +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_vlt_check(1::my_integer_vlt_check) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: s2 my_integer_vlt_check + x_stl2_my_integer_vlt_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(1::my_integer_stl_check) FROM x; +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(1::my_integer_imm_check) FROM x; +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +NOTICE: s +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +NOTICE: s +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; +NOTICE: s +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed ArrayCoerce and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_array_my_integer_vlt_check( + '{1, 1}'::integer[]::my_integer_vlt_check[] +) +FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 array_my_integer_vlt_check + x_stl2_array_my_integer_vlt_check +----------------------------------- + {1,1} + {1,1} + {1,1} + {1,1} +(4 rows) + +SELECT x_stl2_array_my_integer_stl_check( + '{1, 1}'::integer[]::my_integer_stl_check[] +) +FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 array_my_integer_stl_check + x_stl2_array_my_integer_stl_check +----------------------------------- + {1,1} + {1,1} + {1,1} + {1,1} +(4 rows) + +-- Tracking functions testing +SET track_functions TO 'all'; +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl() FROM x; +NOTICE: s + x_stl +------- + 1 + 1 + 1 + 1 +(4 rows) + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x_vlt +------- + 1 + 1 + 1 +(3 rows) + +SELECT x_stl() FROM x WHERE x_stl() < x; +NOTICE: s +NOTICE: s +NOTICE: s + x_stl +------- + 1 + 1 + 1 +(3 rows) + +-- JOIN/ON clause testing +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: v + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; +NOTICE: s +NOTICE: s + x | y +---+--- + 2 | 1 + 3 | 1 + 4 | 1 + 2 | 2 + 3 | 2 + 4 | 2 +(6 rows) + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 +NOTICE: v2 + x_vlt2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(1) FROM x; +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 +NOTICE: v +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl()) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2(x_stl()) FROM x; +NOTICE: s +NOTICE: i2 + x_imm2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict +NOTICE: v +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict +NOTICE: v +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: s2 strict + x_stl2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; +NOTICE: s2 strict +NOTICE: i2 strict + x_imm2_strict +--------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_stl2_strict +--------------- + + + + +(4 rows) + +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; +NOTICE: s2 + x_imm2_strict +--------------- + + + + +(4 rows) + +-- Operators testing +SELECT 1 === 2 FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: equal integers volatile + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== 2 FROM x; +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +NOTICE: s2 boolean + ?column? +---------- + + + + +(4 rows) + +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; +NOTICE: s2 boolean +NOTICE: equal booleans immutable + ?column? +---------- + + + + +(4 rows) + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== 2) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT x_stl() ==== 1 FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal booleans stable strict + equal_booleans_stl_strict +--------------------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + ?column? +---------- + t + t + t + t +(4 rows) + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + equal_my_integer_stl +---------------------- + + + + +(4 rows) + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable + nullif +-------- + (1) + (1) + (1) + (1) +(4 rows) + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean +NOTICE: equal integers volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean +NOTICE: equal my_integer volatile +NOTICE: equal my_integer volatile +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; +NOTICE: equal integers stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; -- should not be precalculated +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable +NOTICE: v +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; -- should not be precalculated +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; -- should not be precalculated +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable +NOTICE: v array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable +NOTICE: v my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; +NOTICE: s +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; +NOTICE: s array_integer +NOTICE: equal integers stable + ?column? +---------- + f + f + f + f +(4 rows) + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; +NOTICE: s my_integer +NOTICE: equal my_integer stable +NOTICE: equal my_integer stable + ?column? +---------- + f + f + f + f +(4 rows) + +-- Mixed functions and boolean expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and ARRAY[] expressions testing +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer +NOTICE: v +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1} + {1} + {1} + {1} +(4 rows) + +SELECT x_stl2_array_integer(ARRAY[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1} + {1} + {1} + {1} +(4 rows) + +-- Mixed functions and array subscripting operations testing +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 +NOTICE: v array_integer +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 +NOTICE: v array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer +NOTICE: v array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +NOTICE: s array_integer +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +NOTICE: s array_integer +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 +NOTICE: v wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 +NOTICE: v my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +NOTICE: s wxyz +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2((x_stl_my_integer()).value) FROM x; +NOTICE: s my_integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- Mixed functions and RelabelType expressions testing +SELECT x_stl2(x_vlt_oid()::integer) FROM x; -- should not be precalculated +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 +NOTICE: v oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_oid()::integer) FROM x; +NOTICE: s oid +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and CoerceViaIO expressions testing +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 +NOTICE: v text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; +NOTICE: s text integer +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer +NOTICE: v text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; +NOTICE: s text my_integer +NOTICE: s2 my_integer + x_stl2_my_integer +------------------- + (1) + (1) + (1) + (1) +(4 rows) + +-- Mixed functions and ArrayCoerce expressions testing +-- Binary-coercible types: +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid +NOTICE: v array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; +NOTICE: s array_integer +NOTICE: s2 array_oid + x_stl2_array_oid +------------------ + {2,3} + {2,3} + {2,3} + {2,3} +(4 rows) + +-- Not binary-coercible types: +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer +NOTICE: cast my_integer as integer volatile +NOTICE: cast my_integer as integer volatile +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; +NOTICE: cast my_integer as integer stable +NOTICE: cast my_integer as integer stable +NOTICE: s2 array_integer + x_stl2_array_integer +---------------------- + {1,2} + {1,2} + {1,2} + {1,2} +(4 rows) + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable +NOTICE: v array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_vlt_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +SELECT x_stl_array_integer()::my_integer[] FROM x; +NOTICE: s array_integer +NOTICE: cast integer as my_integer stable +NOTICE: cast integer as my_integer stable + x_stl_array_integer +--------------------- + {(2),(3)} + {(2),(3)} + {(2),(3)} + {(2),(3)} +(4 rows) + +-- Mixed functions and ConvertRowtypeExpr testing +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz +NOTICE: v wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz +NOTICE: v wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +NOTICE: s wxyz_child +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; +NOTICE: s wxyz_child2 +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) + (1,{2},t,3) +(4 rows) + +-- Mixed functions and CASE expressions testing +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 +NOTICE: v boolean +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: v +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; +NOTICE: s2 boolean +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; +NOTICE: s +NOTICE: s +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and RowCompareExpr testing +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and COALESCE expressions testing +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 +NOTICE: v2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; +NOTICE: s2 +NOTICE: s2 + x_stl2 +-------- + 2 + 2 + 2 + 2 +(4 rows) + +-- Mixed functions and GREATEST and LEAST functions testing +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; -- should not be precalculated +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 +NOTICE: v +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 3 + 3 + 3 + 3 +(4 rows) + +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; +NOTICE: s +NOTICE: s2 + x_stl2 +-------- + 1 + 1 + 1 + 1 +(4 rows) + +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; +NOTICE: v text xml +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; +NOTICE: v text xml content +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: v xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; +NOTICE: v xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; +NOTICE: v xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml_content() line 4 at RETURN +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; +NOTICE: v xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_vlt_xml_content() line 4 at RETURN +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; +ERROR: unsupported XML feature +LINE 1: SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; +NOTICE: s text xml +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; +NOTICE: s xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_stl_xml() line 4 at RETURN +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; +NOTICE: s xml +ERROR: unsupported XML feature +LINE 1: SELECT 'foo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'foo'::xml +CONTEXT: PL/pgSQL function x_stl_xml() line 4 at RETURN +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_stl_xml_content() line 4 at RETURN +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; +NOTICE: s xml content +ERROR: unsupported XML feature +LINE 1: SELECT 'abcbarfoo'::xml + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +QUERY: SELECT 'abcbarfoo'::xml +CONTEXT: PL/pgSQL function x_stl_xml_content() line 4 at RETURN +-- Mixed functions and NullTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean +NOTICE: v +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean +NOTICE: v wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; +NOTICE: s +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; +NOTICE: s wxyz +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- Mixed functions and BooleanTest expressions testing +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean +NOTICE: v boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + t + t + t + t +(4 rows) + +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; +NOTICE: s2 boolean +NOTICE: s2 boolean + x_stl2_boolean +---------------- + f + f + f + f +(4 rows) + +-- Mixed functions and CoerceToDomain expressions testing +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check +NOTICE: v +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null +NOTICE: v +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check +NOTICE: v +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check +NOTICE: v +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +NOTICE: s +NOTICE: s2 my_integer_no_check + x_stl2_my_integer_no_check +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +NOTICE: s +NOTICE: s2 my_integer_not_null + x_stl2_my_integer_not_null +---------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +NOTICE: s +NOTICE: equal integers stable +NOTICE: s2 my_integer_stl_check + x_stl2_my_integer_stl_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; +NOTICE: s +NOTICE: equal integers immutable +NOTICE: s2 my_integer_imm_check + x_stl2_my_integer_imm_check +----------------------------- + 1 + 1 + 1 + 1 +(4 rows) + +SET track_functions TO DEFAULT; +-- ROW() expressions with dropped columns testing +ALTER TABLE wxyz DROP COLUMN z; +-- Update some functions +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; +-- ROW() expressions testing +SELECT x_stl2_wxyz((1, '{2}', TRUE)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE)) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz((1, '{2}', TRUE)::wxyz) FROM x; +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- Mixed functions and ROW() expressions testing +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE)) FROM x; +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz +NOTICE: v +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE)) FROM x; +NOTICE: s +NOTICE: s2 wxyz + x_stl2_wxyz +------------- + (1,{2},t) + (1,{2},t) + (1,{2},t) + (1,{2},t) +(4 rows) + +-- PL/pgSQL Simple expressions +-- Make sure precalculated stable functions can't be simple expressions: these +-- expressions are only initialized once per transaction and then executed +-- multiple times. +BEGIN; +SELECT simple(); + simple +-------- + 4 +(1 row) + +INSERT INTO x VALUES (5); +SELECT simple(); + simple +-------- + 5 +(1 row) + +ROLLBACK; +-- Prepared statements testing +PREPARE test_x_imm2 (integer) AS SELECT x_imm2(x_imm2($1)) FROM x; +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +NOTICE: i2 +NOTICE: i2 + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + QUERY PLAN +--------------- + Seq Scan on x +(1 row) + +-- Drop tables and domains for testing +DROP TABLE x; +DROP FUNCTION x_vlt_wxyz, x_vlt_wxyz_child, x_vlt_wxyz_child2; +DROP FUNCTION x_stl_wxyz, x_stl_wxyz_child, x_stl_wxyz_child2, x_stl2_wxyz; +DROP TABLE wxyz, wxyz_child, wxyz_child2; +DROP FUNCTION x_stl2_no_columns; +DROP TABLE no_columns, no_columns_child, no_columns_child2; +DROP FUNCTION x_stl2_my_integer_no_check; +DROP DOMAIN my_integer_no_check; +DROP FUNCTION x_stl2_my_integer_not_null; +DROP DOMAIN my_integer_not_null; +DROP FUNCTION x_stl2_my_integer_vlt_check; +DROP FUNCTION x_stl2_array_my_integer_vlt_check; +DROP DOMAIN my_integer_vlt_check; +DROP FUNCTION x_stl2_my_integer_stl_check; +DROP FUNCTION x_stl2_array_my_integer_stl_check; +DROP DOMAIN my_integer_stl_check; +DROP FUNCTION x_stl2_my_integer_imm_check; +DROP DOMAIN my_integer_imm_check; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index e224977..0e893df 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -116,7 +116,7 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid c # ---------- # Another group of parallel tests # ---------- -test: identity partition_join partition_prune reloptions hash_part +test: identity partition_join partition_prune reloptions hash_part precalculate_stable_functions # event triggers cannot run concurrently with any test that runs DDL test: event_trigger diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 9fc5f1a..54470ea 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -184,5 +184,6 @@ test: partition_join test: partition_prune test: reloptions test: hash_part +test: precalculate_stable_functions test: event_trigger test: stats diff --git a/src/test/regress/sql/precalculate_stable_functions.sql b/src/test/regress/sql/precalculate_stable_functions.sql new file mode 100644 index 0000000..9437f24 --- /dev/null +++ b/src/test/regress/sql/precalculate_stable_functions.sql @@ -0,0 +1,2117 @@ +-- +-- PRECALCULATE STABLE FUNCTIONS +-- +-- Create types and tables for testing + +CREATE TYPE my_integer AS (value integer); +CREATE TYPE composite_type AS (first integer, second integer[], third boolean); + +CREATE TABLE x (x integer); +INSERT INTO x SELECT generate_series(1, 4) x; + +CREATE TABLE wxyz (w integer, x integer[], y boolean, z integer); +CREATE TABLE wxyz_child () INHERITS (wxyz); +CREATE TABLE wxyz_child2 (a integer, b integer) INHERITS (wxyz); + +CREATE TABLE no_columns (); +CREATE TABLE no_columns_child () INHERITS (no_columns); +CREATE TABLE no_columns_child2 (a integer, b integer) INHERITS (no_columns); + +-- Create volatile functions for testing + +CREATE OR REPLACE FUNCTION public.x_vlt ( +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_my_integer ( +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_array_integer ( +) +RETURNS int[] VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_boolean ( +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v boolean'; + RETURN TRUE; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz ( +) +RETURNS wxyz VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child ( +) +RETURNS wxyz_child VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_wxyz_child2 ( +) +RETURNS wxyz_child2 VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_oid ( +) +RETURNS oid VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_text_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_text_my_integer ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_text_xml_instruction_content ( +) +RETURNS text VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_xml ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt_xml_content ( +) +RETURNS xml VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_vlt2 ( + integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'v2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_integers_vlt ( + integer, + integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers volatile'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_my_integer_vlt ( + my_integer, + my_integer +) +RETURNS boolean VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer volatile'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_vlt ( + integer +) +RETURNS my_integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer volatile'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_vlt ( + my_integer +) +RETURNS integer VOLATILE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer volatile'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; + +-- Create stable functions for testing + +CREATE OR REPLACE FUNCTION public.x_stl ( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_my_integer ( +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's my_integer'; + RETURN '(1)'::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_array_integer ( +) +RETURNS int[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's array_integer'; + RETURN '{2, 3}'::integer[]; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_wxyz ( +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz'; + RETURN '(1, {2}, TRUE, 3)'::wxyz; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child ( +) +RETURNS wxyz_child STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child'; + RETURN '(1, {2}, TRUE, 3)'::wxyz_child; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_wxyz_child2 ( +) +RETURNS wxyz_child2 STABLE AS +$body$ +BEGIN + RAISE NOTICE 's wxyz_child2'; + RETURN '(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_oid ( +) +RETURNS oid STABLE AS +$body$ +BEGIN + RAISE NOTICE 's oid'; + RETURN 1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_text_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text integer'; + RETURN 1::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_text_my_integer ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text my_integer'; + RETURN '(1)'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_text_xml ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml'; + RETURN 'Manual'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_text_xml_instruction_content ( +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's text xml instruction content'; + RETURN 'echo "hello world";'::text; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_xml ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml'; + RETURN 'foo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl_xml_content ( +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's xml content'; + RETURN 'abcbarfoo'::xml; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2 ( + integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_strict ( + integer +) +RETURNS integer STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 's2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_boolean ( + boolean +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 boolean'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_array_integer ( + integer[] +) +RETURNS integer[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_array_oid ( + oid[] +) +RETURNS oid[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_oid'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_composite_type ( + composite_type +) +RETURNS composite_type STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 composite_type'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer ( + my_integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_no_columns ( + no_columns +) +RETURNS no_columns STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 no_columns'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_name ( + name +) +RETURNS name STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 name'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_xml ( + xml +) +RETURNS xml STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 xml'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_text ( + text +) +RETURNS text STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 text'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_integers_stl ( + integer, + integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers stable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_booleans_stl_strict ( + boolean, + boolean +) +RETURNS boolean STABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans stable strict'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_my_integer_stl ( + my_integer, + my_integer +) +RETURNS boolean STABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer stable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.cast_integer_as_my_integer_stl ( + integer +) +RETURNS my_integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast integer as my_integer stable'; + RETURN ROW($1)::my_integer; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.cast_my_integer_as_integer_stl ( + my_integer +) +RETURNS integer STABLE AS +$body$ +BEGIN + RAISE NOTICE 'cast my_integer as integer stable'; + RETURN $1.value; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.stable_max( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN (SELECT max(x) from x); +END +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.simple( +) +RETURNS integer STABLE AS +$body$ +BEGIN + RETURN stable_max(); +END +$body$ +LANGUAGE 'plpgsql'; + +-- Create immutable functions for testing + +CREATE OR REPLACE FUNCTION public.x_imm2 ( + integer +) +RETURNS integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_imm2_strict ( + integer +) +RETURNS integer IMMUTABLE STRICT AS +$body$ +BEGIN + RAISE NOTICE 'i2 strict'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_imm2_my_integer ( + my_integer +) +RETURNS my_integer IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'i2 my_integer'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_integers_imm ( + integer, + integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal integers immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_booleans_imm ( + boolean, + boolean +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal booleans immutable'; + RETURN $1 = $2; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.equal_my_integer_imm ( + my_integer, + my_integer +) +RETURNS boolean IMMUTABLE AS +$body$ +BEGIN + RAISE NOTICE 'equal my_integer immutable'; + RETURN $1.value = $2.value; +END; +$body$ +LANGUAGE 'plpgsql'; + +-- Create operators for testing + +CREATE OPERATOR === ( + PROCEDURE = equal_integers_vlt, + LEFTARG = integer, + RIGHTARG = integer +); + +CREATE OPERATOR ==== ( + PROCEDURE = equal_integers_stl, + LEFTARG = integer, + RIGHTARG = integer +); + +CREATE OPERATOR ===== ( + PROCEDURE = equal_integers_imm, + LEFTARG = integer, + RIGHTARG = integer +); + +CREATE OPERATOR ==== ( + PROCEDURE = equal_booleans_stl_strict, + LEFTARG = boolean, + RIGHTARG = boolean +); + +CREATE OPERATOR ===== ( + PROCEDURE = equal_booleans_imm, + LEFTARG = boolean, + RIGHTARG = boolean +); + +-- Create domains for testing + +CREATE DOMAIN my_integer_no_check AS integer; +CREATE DOMAIN my_integer_not_null AS integer; +CREATE DOMAIN my_integer_vlt_check AS integer CHECK (VALUE === 1); +CREATE DOMAIN my_integer_stl_check AS integer CHECK (VALUE ==== 1); +CREATE DOMAIN my_integer_imm_check AS integer CHECK (VALUE ===== 1); + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_no_check ( + my_integer_no_check +) +RETURNS my_integer_no_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_no_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_not_null ( + my_integer_not_null +) +RETURNS my_integer_not_null STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_not_null'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_vlt_check ( + my_integer_vlt_check +) +RETURNS my_integer_vlt_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_stl_check ( + my_integer_stl_check +) +RETURNS my_integer_stl_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_my_integer_imm_check ( + my_integer_imm_check +) +RETURNS my_integer_imm_check STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 my_integer_imm_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_vlt_check ( + my_integer_vlt_check[] +) +RETURNS my_integer_vlt_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_vlt_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION public.x_stl2_array_my_integer_stl_check ( + my_integer_stl_check[] +) +RETURNS my_integer_stl_check[] STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 array_my_integer_stl_check'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +-- Functions testing + +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +SELECT x_stl() FROM x; + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +SELECT x_stl() FROM x WHERE x_stl() < x; + +-- JOIN/ON clause testing + +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +SELECT x_stl2(1) FROM x; + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated + +SELECT x_stl2(x_stl()) FROM x; +SELECT x_imm2(x_stl()) FROM x; + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; + +-- Operators testing + +SELECT 1 === 2 FROM x; -- should not be precalculated +SELECT 1 ==== 2 FROM x; + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +SELECT x_stl2_boolean(1 ==== 2) FROM x; + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +SELECT x_stl() ==== 1 FROM x; + +-- IS (NOT) DISTINCT FROM expression testing + +-- create operator here because we will drop and reuse it several times +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; + +-- should not be precalculated +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT '(1)'::my_integer IS DISTINCT FROM '(2)'::my_integer FROM x; +SELECT '(1)'::my_integer IS NOT DISTINCT FROM '(2)'::my_integer FROM x; + +-- IS (NOT) DISTINCT FROM expressions with null arguments testing +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM 1) FROM x; +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM 1) FROM x; + +SELECT x_stl2_boolean(x_stl2(NULL) IS DISTINCT FROM x_stl2(NULL)) FROM x; +SELECT x_stl2_boolean(x_stl2(NULL) IS NOT DISTINCT FROM x_stl2(NULL)) FROM x; + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; + +-- NULLIF expressions testing + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT NULLIF('(1)'::my_integer, '(2)'::my_integer) FROM x; + +-- NULLIF expressions with null arguments testing +SELECT x_stl2(NULLIF(1, NULL)) FROM x; +SELECT x_stl2(NULLIF(NULL::integer, NULL)) FROM x; + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions +-- testing + +SELECT 1 === ANY ('{2, 3}') FROM x; -- should not be precalculated +SELECT 1 === ALL ('{2, 3}') FROM x; -- should not be precalculated + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +SELECT 1 ==== ANY ('{2, 3}') FROM x; +SELECT 1 ==== ALL ('{2, 3}') FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +SELECT 1 ===== ANY ('{2, 3}') FROM x; +SELECT 1 ===== ALL ('{2, 3}') FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_imm, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +-- "scalar op ANY/ALL (array)" / "scalar IN (2 or more values)" expressions with +-- null arguments testing +SELECT 1 ==== ANY ('{2, NULL}') FROM x; +SELECT x_stl2_boolean(1 ==== ANY (NULL)) FROM x; +SELECT NULL ==== ANY ('{2, 3}'::integer[]) FROM x; +SELECT NULL ==== ANY ('{2, NULL}'::integer[]) FROM x; +SELECT x_stl2_boolean(NULL::integer ==== ANY (NULL)) FROM x; + +SELECT 1 ==== ALL ('{2, NULL}') FROM x; +SELECT x_stl2_boolean(1 ==== ALL (NULL)) FROM x; +SELECT NULL ==== ALL ('{2, 3}'::integer[]) FROM x; +SELECT NULL ==== ALL ('{2, NULL}'::integer[]) FROM x; +SELECT x_stl2_boolean(NULL::integer ==== ALL (NULL)) FROM x; + +SELECT x_stl2_boolean(1 IN (2, NULL)) FROM x; +SELECT x_stl2_boolean(NULL IN (2, 3)) FROM x; +SELECT x_stl2_boolean(NULL IN (2, NULL)) FROM x; + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; + +-- should not be precalculated +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; + +-- should not be precalculated +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; + +-- should not be precalculated +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; + +-- should not be precalculated +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +-- Boolean expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; + +-- ARRAY[] expressions testing + +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt(), 2]) FROM x; + +SELECT x_stl2_array_integer(ARRAY[x_stl(), 2]) FROM x; + +-- Multidimensional ARRAY[] expressions testing + +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[[x_vlt(), 2], [3, 4]]) FROM x; + +SELECT x_stl2_array_integer(ARRAY[[x_stl(), 2], [3, 4]]) FROM x; + +-- Array subscripting operations testing + +SELECT x_stl2(('{1, 2}'::integer[])[1]) FROM x; +SELECT x_stl2_array_integer(('{1, 2}'::integer[])[:]) FROM x; + +-- Mixed functions and array subscripting operations testing + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; + +-- FieldSelect expressions testing + +SELECT x_stl2(('(1, {2}, TRUE, 3)'::wxyz).w) FROM x; +SELECT x_stl2(('(1)'::my_integer).value) FROM x; + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +SELECT x_stl2((x_stl_my_integer()).value) FROM x; + +-- ROW() expressions testing + +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)) FROM x; +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE, 3)) FROM x; +SELECT x_stl2_wxyz((1, '{2}', TRUE, 3)::wxyz) FROM x; + +SELECT x_stl2_composite_type((1, '{2}', TRUE)) FROM x; +SELECT x_stl2_composite_type(ROW(1, '{2}', TRUE)) FROM x; +SELECT x_stl2_composite_type((1, '{2}', TRUE)::composite_type) FROM x; + +-- Mixed functions and ROW() expressions testing + +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; + +-- RelabelType expressions testing + +-- should not be precalculated +SELECT x_stl2(x_vlt_oid()::integer) FROM x; + +SELECT x_stl2(x_stl_oid()::integer) FROM x; + +-- CoerceViaIO expressions testing + +SELECT x_stl2_my_integer('(1)'::text::my_integer) FROM x; + +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; + +-- Mixed functions and CoerceViaIO expressions testing + +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; + +-- ArrayCoerce expressions testing + +-- Binary-coercible types: + +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; + +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_vlt; + +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; -- should not be precalculated + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; + +SELECT '{1, 2}'::integer[]::my_integer[] FROM x; + +-- Mixed functions and ArrayCoerce expressions testing +-- Not binary-coercible types: +-- create cast here because we will drop and reuse it several times +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; + +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; + +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; + +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; + +SELECT x_stl_array_integer()::my_integer[] FROM x; + +-- ConvertRowtypeExpr testing + +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3)'::wxyz_child::wxyz) FROM x; +SELECT x_stl2_wxyz('(1, {2}, TRUE, 3, 4, 5)'::wxyz_child2::wxyz) FROM x; + +SELECT x_stl2_no_columns('()'::no_columns_child::no_columns) FROM x; +SELECT x_stl2_no_columns('(1, 2)'::no_columns_child2::no_columns) FROM x; + +-- Mixed functions and ConvertRowtypeExpr testing + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; + +-- CASE expressions testing + +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; + +-- RowCompareExpr testing + +SELECT x_stl2_boolean((1, 2) < (1, 3)) FROM x; + +-- Mixed functions and RowCompareExpr testing + +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; + +-- COALESCE expressions testing + +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; + +-- GREATEST and LEAST functions testing + +SELECT x_stl2(GREATEST(2, 1, 3)) FROM x; +SELECT x_stl2(LEAST(2, 1, 3)) FROM x; + +-- Mixed functions and GREATEST and LEAST functions testing + +-- should not be precalculated +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; + +-- should not be precalculated +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; + +-- SQLValueFunction testing + +CREATE ROLE regress_testrol2 SUPERUSER; +CREATE ROLE regress_testrol1 SUPERUSER LOGIN IN ROLE regress_testrol2; + +\c - +SET SESSION AUTHORIZATION regress_testrol1; +SET ROLE regress_testrol2; + +SELECT x_stl2_boolean(date(now()) = current_date) FROM x; + +SELECT x_stl2_boolean(now()::timetz = current_time) FROM x; +SELECT x_stl2_boolean(now()::timetz(2) = current_time(2)) FROM x; -- precision + +SELECT x_stl2_boolean(now() = current_timestamp) FROM x; + +-- precision +SELECT x_stl2_boolean( + length(current_timestamp::text) >= length(current_timestamp(0)::text) +) +FROM x; + +SELECT x_stl2_boolean(now()::time = localtime) FROM x; +SELECT x_stl2_boolean(now()::time(2) = localtime(2)) FROM x; -- precision + +SELECT x_stl2_boolean(now()::timestamp = localtimestamp) FROM x; + +-- precision +SELECT x_stl2_boolean(now()::timestamp(2) = localtimestamp(2)) FROM x; + +SELECT x_stl2_name(current_role) FROM x; +SELECT x_stl2_name(current_user) FROM x; +SELECT x_stl2_name(user) FROM x; +SELECT x_stl2_name(session_user) FROM x; +SELECT x_stl2_name(current_catalog) FROM x; +SELECT x_stl2_name(current_schema) FROM x; + +\c +DROP ROLE regress_testrol1, regress_testrol2; + +-- Xml expressions testing + +SELECT x_stl2_xml(XMLCONCAT('', 'foo')) FROM x; + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), 'cont', 'ent') +) +FROM x; + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, 123 AS bar)) FROM x; + +SELECT x_stl2_xml(XMLPARSE( + DOCUMENT 'Manual' +)) +FROM x; + +SELECT x_stl2_xml(XMLPARSE(CONTENT 'abcbarfoo')) FROM x; + +SELECT x_stl2_xml(XMLPI(name php, 'echo "hello world";')) FROM x; + +SELECT x_stl2_xml(XMLROOT( + 'abc', + version '1.0', + standalone yes +)) +FROM x; + +SELECT x_stl2_text(XMLSERIALIZE( + DOCUMENT 'Manual' AS text +)) +FROM x; + +SELECT x_stl2_text(XMLSERIALIZE( + CONTENT 'abcbarfoo' AS text +)) +FROM x; + +SELECT x_stl2_boolean('abcbarfoo' IS DOCUMENT) FROM x; + +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; + +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; + +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; + +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; + +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; + +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; + +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; + +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; + +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; + +-- NullTest expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; + +-- BooleanTest expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; + +-- CoerceToDomain expressions testing + +SELECT x_stl2_my_integer_no_check(1::my_integer_no_check) FROM x; +SELECT x_stl2_my_integer_not_null(1::my_integer_not_null) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_vlt_check(1::my_integer_vlt_check) FROM x; + +SELECT x_stl2_my_integer_stl_check(1::my_integer_stl_check) FROM x; +SELECT x_stl2_my_integer_imm_check(1::my_integer_imm_check) FROM x; + +-- Mixed functions and CoerceToDomain expressions testing + +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; + +-- Mixed ArrayCoerce and CoerceToDomain expressions testing + +-- should not be precalculated +SELECT x_stl2_array_my_integer_vlt_check( + '{1, 1}'::integer[]::my_integer_vlt_check[] +) +FROM x; + +SELECT x_stl2_array_my_integer_stl_check( + '{1, 1}'::integer[]::my_integer_stl_check[] +) +FROM x; + +-- Tracking functions testing + +SET track_functions TO 'all'; + +-- Simple functions testing +SELECT x_vlt() FROM x; -- should not be precalculated +SELECT x_stl() FROM x; + +-- WHERE clause testing +SELECT x_vlt() FROM x WHERE x_vlt() < x; -- should not be precalculated +SELECT x_stl() FROM x WHERE x_stl() < x; + +-- JOIN/ON clause testing + +-- should not be precalculated +SELECT * FROM x JOIN generate_series(1, 2) y ON x_vlt() < x; + +SELECT * FROM x JOIN generate_series(1, 2) y ON x_stl() < x; + +-- Functions with constant arguments testing +SELECT x_vlt2(1) FROM x; -- should not be precalculated +SELECT x_stl2(1) FROM x; + +-- Nested functions testing +SELECT x_stl2(x_vlt()) FROM x; -- should not be precalculated +SELECT x_imm2(x_vlt()) FROM x; -- should not be precalculated + +SELECT x_stl2(x_stl()) FROM x; +SELECT x_imm2(x_stl()) FROM x; + +-- Strict functions testing +SELECT x_stl2_strict(x_vlt()) FROM x; -- should not be precalculated +SELECT x_imm2_strict(x_vlt()) FROM x; -- should not be precalculated + +SELECT x_stl2_strict(x_stl2_strict(1)) FROM x; +SELECT x_imm2_strict(x_stl2_strict(1)) FROM x; + +-- Strict functions with null arguments testing +SELECT x_stl2_strict(x_stl2(NULL)) FROM x; +SELECT x_imm2_strict(x_stl2(NULL)) FROM x; + +-- Operators testing +SELECT 1 === 2 FROM x; -- should not be precalculated +SELECT 1 ==== 2 FROM x; + +-- Strict operators testing +SELECT x_stl2_boolean(NULL) ==== TRUE FROM x; +SELECT x_stl2_boolean(NULL) ===== TRUE FROM x; + +-- Mixed functions and operators testing +SELECT x_stl2_boolean(1 === 2) FROM x; -- should not be precalculated +SELECT x_stl2_boolean(1 ==== 2) FROM x; + +SELECT x_vlt() ==== 1 FROM x; -- should not be precalculated +SELECT x_stl() ==== 1 FROM x; + +-- Mixed functions and IS (NOT) DISTINCT FROM expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT equal_booleans_stl_strict( + ('(1)'::my_integer IS DISTINCT FROM '(1)'::my_integer), + ('(1)'::my_integer IS NOT DISTINCT FROM '(1)'::my_integer) +) +FROM x; + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; + +-- should not be precalculated +SELECT (x_vlt_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; + +SELECT (x_stl_my_integer() IS DISTINCT FROM '(1)'::my_integer) FROM x; +SELECT (x_stl_my_integer() IS NOT DISTINCT FROM '(1)'::my_integer) FROM x; + +-- Mixed functions and NULLIF expressions testing +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT equal_my_integer_stl( + NULLIF('(1)'::my_integer, '(2)'::my_integer), + NULLIF('(2)'::my_integer, '(2)'::my_integer) +) +FROM x; + +-- should not be precalculated +SELECT NULLIF(x_vlt_my_integer(), '(2)'::my_integer) FROM x; + +SELECT NULLIF(x_stl_my_integer(), '(2)'::my_integer) FROM x; + +-- Mixed functions and "scalar op ANY/ALL (array)" / "scalar IN (2 or more +-- values)" expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ANY ('{2, 3}')) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(1 === ALL ('{2, 3}')) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_vlt, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +-- should not be precalculated +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; + +SELECT x_stl2_boolean(1 ==== ANY ('{2, 3}')) FROM x; +SELECT x_stl2_boolean(1 ==== ALL ('{2, 3}')) FROM x; + +DROP OPERATOR = (my_integer, my_integer); +CREATE OPERATOR = ( + PROCEDURE = equal_my_integer_stl, + LEFTARG = my_integer, + RIGHTARG = my_integer +); + +SELECT x_stl2_boolean( + '(1)'::my_integer IN ('(2)'::my_integer, '(3)'::my_integer) +) +FROM x; + +SELECT x_vlt() ==== ANY ('{2, 3}') FROM x; -- should not be precalculated +SELECT x_vlt() ==== ALL ('{2, 3}') FROM x; -- should not be precalculated + +SELECT 1 ==== ANY (x_vlt_array_integer()) FROM x; -- should not be precalculated +SELECT 1 ==== ALL (x_vlt_array_integer()) FROM x; -- should not be precalculated + +-- should not be precalculated +SELECT x_vlt_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +SELECT x_stl() ==== ANY ('{2, 3}') FROM x; +SELECT x_stl() ==== ALL ('{2, 3}') FROM x; + +SELECT 1 ==== ANY (x_stl_array_integer()) FROM x; +SELECT 1 ==== ALL (x_stl_array_integer()) FROM x; + +SELECT x_stl_my_integer() IN ('(2)'::my_integer, '(3)'::my_integer) FROM x; + +-- Mixed functions and boolean expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() AND x_stl2_boolean(TRUE)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() OR x_stl2_boolean(TRUE)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(NOT x_vlt_boolean()) FROM x; + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) AND x_stl2_boolean(TRUE)) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) OR x_stl2_boolean(TRUE)) FROM x; +SELECT x_stl2_boolean(NOT x_stl2_boolean(TRUE)) FROM x; + +-- Mixed functions and ARRAY[] expressions testing + +-- should not be precalculated +SELECT x_stl2_array_integer(ARRAY[x_vlt()]) FROM x; + +SELECT x_stl2_array_integer(ARRAY[x_stl()]) FROM x; + +-- Mixed functions and array subscripting operations testing + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[x_vlt()]) FROM x; + +-- should not be precalculated +SELECT x_stl2((x_vlt_array_integer())[1]) FROM x; + +-- should not be precalculated +SELECT x_stl2_array_integer((x_vlt_array_integer())[:]) FROM x; + +-- should not be precalculated +SELECT x_stl2(('{1, 2}'::integer[])[x_vlt()]) FROM x; + +SELECT x_stl2((x_stl_array_integer())[x_stl()]) FROM x; +SELECT x_stl2((x_stl_array_integer())[1]) FROM x; +SELECT x_stl2_array_integer((x_stl_array_integer())[:]) FROM x; +SELECT x_stl2(('{1, 2}'::integer[])[x_stl()]) FROM x; + +-- Mixed functions and FieldSelect expressions testing +SELECT x_stl2((x_vlt_wxyz()).w) FROM x; -- should not be precalculated +SELECT x_stl2((x_vlt_my_integer()).value) FROM x; -- should not be precalculated + +SELECT x_stl2((x_stl_wxyz()).w) FROM x; +SELECT x_stl2((x_stl_my_integer()).value) FROM x; + +-- Mixed functions and ROW() expressions testing + +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE, 3)) FROM x; + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE, 3)) FROM x; + +-- Mixed functions and RelabelType expressions testing +SELECT x_stl2(x_vlt_oid()::integer) FROM x; -- should not be precalculated +SELECT x_stl2(x_stl_oid()::integer) FROM x; + +-- Mixed functions and CoerceViaIO expressions testing + +-- should not be precalculated +SELECT x_stl2(x_vlt_text_integer()::integer) FROM x; + +SELECT x_stl2(x_stl_text_integer()::integer) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer(x_vlt_text_my_integer()::my_integer) FROM x; + +SELECT x_stl2_my_integer(x_stl_text_my_integer()::my_integer) FROM x; + +-- Mixed functions and ArrayCoerce expressions testing +-- Binary-coercible types: + +-- should not be precalculated +SELECT x_stl2_array_oid(x_vlt_array_integer()::oid[]) FROM x; + +SELECT x_stl2_array_oid(x_stl_array_integer()::oid[]) FROM x; + +-- Not binary-coercible types: +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_vlt; + +-- should not be precalculated +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; + +DROP CAST (my_integer AS integer); +CREATE CAST (my_integer AS integer) + WITH FUNCTION cast_my_integer_as_integer_stl; + +SELECT x_stl2_array_integer('{(1), (2)}'::my_integer[]::integer[]) FROM x; + +DROP CAST (integer AS my_integer); +CREATE CAST (integer AS my_integer) + WITH FUNCTION cast_integer_as_my_integer_stl; + +-- should not be precalculated +SELECT x_vlt_array_integer()::my_integer[] FROM x; + +SELECT x_stl_array_integer()::my_integer[] FROM x; + +-- Mixed functions and ConvertRowtypeExpr testing + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child()::wxyz_child::wxyz) FROM x; + +-- should not be precalculated +SELECT x_stl2_wxyz(x_vlt_wxyz_child2()::wxyz_child2::wxyz) FROM x; + +SELECT x_stl2_wxyz(x_stl_wxyz_child()::wxyz_child::wxyz) FROM x; +SELECT x_stl2_wxyz(x_stl_wxyz_child2()::wxyz_child2::wxyz) FROM x; + +-- Mixed functions and CASE expressions testing + +-- should not be precalculated +SELECT x_stl2(CASE WHEN x_vlt_boolean() THEN x_vlt() ELSE x_vlt() END) FROM x; + +-- should not be precalculated +SELECT x_stl2(CASE x_vlt() WHEN x_vlt() THEN x_vlt() ELSE x_vlt() END) FROM x; + +SELECT x_stl2(CASE WHEN x_stl2_boolean(TRUE) THEN x_stl() ELSE x_stl() END) +FROM x; + +SELECT x_stl2(CASE x_stl() WHEN x_stl() THEN x_stl() ELSE x_stl() END) FROM x; + +-- Mixed functions and RowCompareExpr testing + +-- should not be precalculated +SELECT x_stl2_boolean((x_vlt(), 2) < (1, 3)) FROM x; + +SELECT x_stl2_boolean((x_stl(), 2) < (1, 3)) FROM x; + +-- Mixed functions and COALESCE expressions testing + +-- should not be precalculated +SELECT x_stl2(COALESCE(NULL, x_vlt2(NULL), 2)) FROM x; + +SELECT x_stl2(COALESCE(NULL, x_stl2(NULL), 2)) FROM x; + +-- Mixed functions and GREATEST and LEAST functions testing +SELECT x_stl2(GREATEST(2, x_vlt(), 3)) FROM x; -- should not be precalculated +SELECT x_stl2(LEAST(2, x_vlt(), 3)) FROM x; -- should not be precalculated + +SELECT x_stl2(GREATEST(2, x_stl(), 3)) FROM x; +SELECT x_stl2(LEAST(2, x_stl(), 3)) FROM x; + +-- Mixed functions and Xml expressions testing +-- should not be precalculated +SELECT x_stl2_xml(XMLCONCAT('', x_vlt_xml())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_vlt_xml()) +) +FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_vlt_xml() AS bar)) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_vlt_text_xml())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPARSE(CONTENT x_vlt_text_xml_content())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLPI(name php, x_vlt_text_xml_instruction_content())) FROM x; + +-- should not be precalculated +SELECT x_stl2_xml(XMLROOT(x_vlt_xml(), version '1.0', standalone yes)) FROM x; + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_vlt_xml() AS text)) FROM x; + +-- should not be precalculated +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_vlt_xml_content() AS text)) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_xml_content() IS DOCUMENT) FROM x; + +SELECT x_stl2_xml(XMLCONCAT('', x_stl_xml())) FROM x; + +SELECT x_stl2_xml( + XMLELEMENT(name foo, xmlattributes('bar' as bar), x_stl_xml()) +) +FROM x; + +SELECT x_stl2_xml(XMLFOREST('abc' AS foo, x_stl_xml() AS bar)) FROM x; + +SELECT x_stl2_xml(XMLPARSE(DOCUMENT x_stl_text_xml())) FROM x; + +SELECT x_stl2_xml(XMLPARSE(CONTENT x_stl_text_xml_content())) FROM x; + +SELECT x_stl2_xml(XMLPI(name php, x_stl_text_xml_instruction_content())) FROM x; + +SELECT x_stl2_xml(XMLROOT(x_stl_xml(), version '1.0', standalone yes)) FROM x; + +SELECT x_stl2_text(XMLSERIALIZE(DOCUMENT x_stl_xml() AS text)) FROM x; + +SELECT x_stl2_text(XMLSERIALIZE(CONTENT x_stl_xml_content() AS text)) FROM x; + +SELECT x_stl2_boolean(x_stl_xml_content() IS DOCUMENT) FROM x; + +-- Mixed functions and NullTest expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt() IS NOT NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NULL) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_wxyz() IS NOT NULL) FROM x; + +SELECT x_stl2_boolean(x_stl() IS NULL) FROM x; +SELECT x_stl2_boolean(x_stl() IS NOT NULL) FROM x; + +SELECT x_stl2_boolean(x_stl_wxyz() IS NULL) FROM x; +SELECT x_stl2_boolean(x_stl_wxyz() IS NOT NULL) FROM x; + +-- Mixed functions and BooleanTest expressions testing + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS TRUE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT TRUE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS FALSE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT FALSE) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS UNKNOWN) FROM x; + +-- should not be precalculated +SELECT x_stl2_boolean(x_vlt_boolean() IS NOT UNKNOWN) FROM x; + +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS TRUE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT TRUE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS FALSE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(TRUE) IS NOT FALSE) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS UNKNOWN) FROM x; +SELECT x_stl2_boolean(x_stl2_boolean(NULL) IS NOT UNKNOWN) FROM x; + +-- Mixed functions and CoerceToDomain expressions testing + +-- should not be precalculated +SELECT x_stl2_my_integer_no_check(x_vlt()::my_integer_no_check) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_not_null(x_vlt()::my_integer_not_null) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_stl_check(x_vlt()::my_integer_stl_check) FROM x; + +-- should not be precalculated +SELECT x_stl2_my_integer_imm_check(x_vlt()::my_integer_imm_check) FROM x; + +SELECT x_stl2_my_integer_no_check(x_stl()::my_integer_no_check) FROM x; +SELECT x_stl2_my_integer_not_null(x_stl()::my_integer_not_null) FROM x; +SELECT x_stl2_my_integer_stl_check(x_stl()::my_integer_stl_check) FROM x; +SELECT x_stl2_my_integer_imm_check(x_stl()::my_integer_imm_check) FROM x; + +SET track_functions TO DEFAULT; + +-- ROW() expressions with dropped columns testing + +ALTER TABLE wxyz DROP COLUMN z; + +-- Update some functions +CREATE OR REPLACE FUNCTION public.x_stl2_wxyz ( + wxyz +) +RETURNS wxyz STABLE AS +$body$ +BEGIN + RAISE NOTICE 's2 wxyz'; + RETURN $1; +END; +$body$ +LANGUAGE 'plpgsql'; + +-- ROW() expressions testing +SELECT x_stl2_wxyz((1, '{2}', TRUE)) FROM x; +SELECT x_stl2_wxyz(ROW(1, '{2}', TRUE)) FROM x; +SELECT x_stl2_wxyz((1, '{2}', TRUE)::wxyz) FROM x; + +-- Mixed functions and ROW() expressions testing + +-- should not be precalculated +SELECT x_stl2_wxyz((x_vlt(), '{2}', TRUE)) FROM x; + +SELECT x_stl2_wxyz((x_stl(), '{2}', TRUE)) FROM x; + +-- PL/pgSQL Simple expressions +-- Make sure precalculated stable functions can't be simple expressions: these +-- expressions are only initialized once per transaction and then executed +-- multiple times. + +BEGIN; +SELECT simple(); +INSERT INTO x VALUES (5); +SELECT simple(); +ROLLBACK; + +-- Prepared statements testing + +PREPARE test_x_imm2 (integer) AS SELECT x_imm2(x_imm2($1)) FROM x; +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); +EXPLAIN (COSTS OFF) EXECUTE test_x_imm2(2); + +-- Drop tables and domains for testing + +DROP TABLE x; + +DROP FUNCTION x_vlt_wxyz, x_vlt_wxyz_child, x_vlt_wxyz_child2; +DROP FUNCTION x_stl_wxyz, x_stl_wxyz_child, x_stl_wxyz_child2, x_stl2_wxyz; +DROP TABLE wxyz, wxyz_child, wxyz_child2; + +DROP FUNCTION x_stl2_no_columns; +DROP TABLE no_columns, no_columns_child, no_columns_child2; + +DROP FUNCTION x_stl2_my_integer_no_check; +DROP DOMAIN my_integer_no_check; + +DROP FUNCTION x_stl2_my_integer_not_null; +DROP DOMAIN my_integer_not_null; + +DROP FUNCTION x_stl2_my_integer_vlt_check; +DROP FUNCTION x_stl2_array_my_integer_vlt_check; +DROP DOMAIN my_integer_vlt_check; + +DROP FUNCTION x_stl2_my_integer_stl_check; +DROP FUNCTION x_stl2_array_my_integer_stl_check; +DROP DOMAIN my_integer_stl_check; + +DROP FUNCTION x_stl2_my_integer_imm_check; +DROP DOMAIN my_integer_imm_check; -- 2.7.4