From 0854f7a0b8e4e37295709b6eced1816b80befe32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=97=E9=87=8C=E5=AF=BB=E4=BB=96=E5=8D=83=E7=99=BE?= =?UTF-8?q?=E5=BA=A6?= <783479891@qq.com> Date: Fri, 14 Mar 2025 17:52:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dexpr=20DEFAULT=20func=5Farg?= =?UTF-8?q?=5Fexpr=20......=E5=87=BD=E6=95=B0=E4=B8=ADfunc=5Farg=5Fexpr?= =?UTF-8?q?=E4=B8=BA=E5=88=97=E6=97=B6=E5=AF=BC=E8=87=B4=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93core=E5=92=8C=E7=BB=93=E6=9E=9C=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/gram.y | 193 +++++++++++++++-- src/test/regress/expected/cast.out | 67 ++++++ .../regress/expected/func_to_binary_float.out | 203 ++++++++++-------- .../regress/expected/to_number_default.out | 124 +++++++---- .../regress/expected/to_timestamp_default.out | 63 ++++++ src/test/regress/sql/cast.sql | 37 ++++ src/test/regress/sql/func_to_binary_float.sql | 36 ++++ src/test/regress/sql/to_number_default.sql | 35 +++ src/test/regress/sql/to_timestamp_default.sql | 33 +++ 9 files changed, 644 insertions(+), 147 deletions(-) diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 5984f6278e..290286b715 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -280,6 +280,15 @@ static Node *MakeSqlLoadNode(char *colname); static void checkDeleteRelationError(); static TypeName *ParseFloatByExtentedPrecision(int ival, int location, core_yyscan_t yyscanner); static void CheckTypmodScale(List* arglist, int location, core_yyscan_t yyscanner); +static bool manual_expression_tree_walker(Node* node, bool (*walker)(Node*, void*), void* context); +static bool check_column_ref(Node *node, void *context); +static bool contains_column_ref(Node *expr); +static bool contains_sublink(Node *expr); +static bool check_sublink(Node *node, void *context); +static bool contains_funccall(Node *expr); +static bool check_funccall(Node *node, void *context); +static bool contains_typecast(Node *expr); +static bool check_typecast(Node *node, void *context); /* start with .. connect by related utilities */ static bool IsConnectByRootIdent(Node* node); @@ -677,7 +686,7 @@ static char* IdentResolveToChar(char *ident, core_yyscan_t yyscanner); %type def_arg columnElem where_clause where_or_current_clause start_with_expr connect_by_expr a_expr b_expr c_expr c_expr_noparen AexprConst indirection_el siblings_clause columnref in_expr start_with_clause having_clause func_table array_expr set_ident_expr set_expr set_expr_extension - ExclusionWhereClause func_table_with_table default_on_err_expr + ExclusionWhereClause func_table_with_table %type ExclusionConstraintList ExclusionConstraintElem %type func_arg_list %type func_arg_expr on_error_clause opt_on_error_clause @@ -29319,7 +29328,16 @@ func_application_special: func_name '(' ')' FuncCall *n = makeNode(FuncCall); n->funcname = $1; - + if (contains_column_ref($5)||contains_sublink($5)||contains_funccall($5)||contains_typecast($5)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } + if (!IsA($5, A_Const) && !IsA($5, A_Expr) && !IsA($5, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } n->args = lappend($3, $5); // is DEFAULT gramy n->args = lappend(n->args, makeBoolAConst(TRUE, -1)); @@ -29350,6 +29368,16 @@ func_application_special: func_name '(' ')' FuncCall *n = makeNode(FuncCall); n->funcname = $1; + if (contains_column_ref($5)||contains_sublink($5)||contains_funccall($5)||contains_typecast($5)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } + if (!IsA($5, A_Const) && !IsA($5, A_Expr) && !IsA($5, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } // args: // input_expr, default_val, // is DEFAULT gramy, default expr is column ref, @@ -29378,6 +29406,16 @@ func_application_special: func_name '(' ')' FuncCall *n = makeNode(FuncCall); n->funcname = $1; + if (contains_column_ref($5)||contains_sublink($5)||contains_funccall($5)||contains_typecast($5)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } + if (!IsA($5, A_Const) && !IsA($5, A_Expr) && !IsA($5, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } // args: // input_expr, default_val, // is DEFAULT gramy, default expr is column ref, @@ -29872,12 +29910,52 @@ func_expr_common_subexpr: { $$ = makeTypeCast($3, $5, $6, NULL, NULL, @1); } | CAST '(' a_expr AS Typename opt_default_fmt_clause opt_default_nls_clause ')' { $$ = makeTypeCast($3, $5, $6, $7, NULL, @1); } - | CAST '(' a_expr AS Typename default_on_err_expr opt_default_fmt_clause ')' - { $$ = makeTypeCast($3, $5, $7, NULL, $6, @1); } - | CAST '(' a_expr AS Typename default_on_err_expr opt_default_fmt_clause opt_default_nls_clause ')' - { $$ = makeTypeCast($3, $5, $7, $8, $6, @1); } - | CAST '(' a_expr AS Typename default_on_err_expr ')' - { $$ = makeTypeCast($3, $5, NULL, NULL, $6, @1); } + | CAST '(' a_expr AS Typename DEFAULT a_expr ON CONVERSION_P ERROR_P opt_default_fmt_clause ')' + { + if (contains_column_ref($7)||contains_sublink($7)||contains_funccall($7)||contains_typecast($7)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + } + if (!IsA($7, A_Const) && !IsA($7, A_Expr) && !IsA($7, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + } + $$ = makeTypeCast($3, $5, $11, NULL, $7, @1); + } + | CAST '(' a_expr AS Typename DEFAULT a_expr ON CONVERSION_P ERROR_P opt_default_fmt_clause opt_default_nls_clause ')' + { + if (contains_column_ref($7)||contains_sublink($7)||contains_funccall($7)||contains_typecast($7)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + } + if (!IsA($7, A_Const) && !IsA($7, A_Expr) && !IsA($7, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + } + $$ = makeTypeCast($3, $5, $11, NULL, $7, @1); + } + | CAST '(' a_expr AS Typename DEFAULT a_expr ON CONVERSION_P ERROR_P ')' + { + if (contains_column_ref($7)||contains_sublink($7)||contains_funccall($7)||contains_typecast($7)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + if (contains_column_ref($7)||contains_sublink($7)||contains_funccall($7)){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@5))); + } + if (!IsA($7, A_Const) && !IsA($7, A_Expr) && !IsA($7, ParamRef)) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This argument must be a literal or bind variable."),parser_errposition(@7))); + } + $$ = makeTypeCast($3, $5, NULL, NULL, $7, @1); + } | EXTRACT '(' extract_list ')' { FuncCall *n = makeNode(FuncCall); @@ -30186,11 +30264,6 @@ func_expr_common_subexpr: } ; -default_on_err_expr: - DEFAULT a_expr ON CONVERSION_P ERROR_P { - $$ = $2; - } - ; /* * SQL/XML support */ @@ -34919,6 +34992,100 @@ static char* IdentResolveToChar(char *ident, core_yyscan_t yyscanner) } } +static bool manual_expression_tree_walker(Node* node, bool (*walker)(Node*, void*), void* context) +{ + if (node == NULL) + return false; + + if (walker(node, context)) + return true; + + if (IsA(node, A_Expr)) { + A_Expr *expr = (A_Expr *) node; + + if (expr->lexpr && manual_expression_tree_walker(expr->lexpr, walker, context)) + return true; + + if (expr->rexpr && manual_expression_tree_walker(expr->rexpr, walker, context)) + return true; + } + + return false; +} + +static bool check_column_ref(Node *node, void *context) +{ + if (node == NULL) + return false; + + if (IsA(node, ColumnRef)) { + return true; + } + + return false; +} + +static bool check_sublink(Node *node, void *context) +{ + if (node == NULL) + return false; + + if (IsA(node, SubLink)) { + return true; + } + + return false; +} + +static bool check_funccall(Node *node, void *context) +{ + if (node == NULL) + return false; + + if (IsA(node, FuncCall)) { + return true; + } + + return false; +} + +static bool check_typecast(Node *node, void *context) +{ + if (node == NULL) + return false; + + if (IsA(node, TypeCast)) + { + TypeCast *typeCast = (TypeCast *) node; + + if (typeCast->arg && !IsA(typeCast->arg, A_Const)) + { + return true; + } + } + + return false; +} + +static bool contains_column_ref(Node *expr) +{ + return manual_expression_tree_walker(expr, check_column_ref, NULL); +} + +static bool contains_sublink(Node *expr) +{ + return manual_expression_tree_walker(expr, check_sublink, NULL); +} + +static bool contains_funccall(Node *expr) +{ + return manual_expression_tree_walker(expr, check_funccall, NULL); +} + +static bool contains_typecast(Node *expr) +{ + return manual_expression_tree_walker(expr, check_typecast, NULL); +} /* * Must undefine this stuff before including scan.c, since it has different * definitions for these macros. diff --git a/src/test/regress/expected/cast.out b/src/test/regress/expected/cast.out index fc0a56e981..95240dffb9 100644 --- a/src/test/regress/expected/cast.out +++ b/src/test/regress/expected/cast.out @@ -3544,3 +3544,70 @@ SELECT cast ('01-Dec-03 14:10:10.123000' as timestamp DEFAULT '11-Dec-11 14:10:1 2001-12-03 14:10:10.123 (1 row) +--cast +drop table tnb; +ERROR: table "tnb" does not exist +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; + num +----- + 123 +(1 row) + +select cast('asd' as numeric default num on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default num on conversion error... + ^ +select cast('asd' as numeric default num||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default num||'123' on conversio... + ^ +select cast('asd' as numeric default to_char(num)||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default to_char(num)||'123' on ... + ^ +select cast('asd' as numeric default num::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default num::text||'123' on con... + ^ +select cast('asd' as numeric default (num::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default (num::text)::text||'123... + ^ +select cast('asd' as numeric default ('123'::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select cast('asd' as numeric default ('123'::text)::text||'1... + ^ +select cast('asd' as numeric default '123'::text||'123' on conversion error)from tnb; + numeric +--------- + 123123 +(1 row) + +drop table tnb; +--参数引用 +drop table employees; +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); +NOTICE: CREATE TABLE will create implicit sequence "employees_id_seq" for serial column "employees.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "employees_pkey" for table "employees" +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (cast('asd' as numeric default $1 on conversion error), $2); +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (cast('asd' as numeric default $1||'123' on conversion error), $2); +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; +SELECT * FROM employees; + id | name | age +----+--------+----- + 1 | 123 | 30 + 2 | 123123 | 28 +(2 rows) + +drop table employees; diff --git a/src/test/regress/expected/func_to_binary_float.out b/src/test/regress/expected/func_to_binary_float.out index 838f0cec22..bdd1f66d76 100644 --- a/src/test/regress/expected/func_to_binary_float.out +++ b/src/test/regress/expected/func_to_binary_float.out @@ -177,18 +177,9 @@ SELECT TO_BINARY_FLOAT(c1 DEFAULT NULL ON CONVERSION ERROR) FROM tbf ORDER By c1 (8 rows) SELECT TO_BINARY_FLOAT(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error, column can't be default param - to_binary_float ------------------ - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(3.14 DEFAULT c1 ON CONVERSION ERROR) ... + ^ SELECT TO_BINARY_FLOAT(c2 DEFAULT 3.14 ON CONVERSION ERROR) FROM tbf ORDER By c1; to_binary_float ----------------- @@ -466,73 +457,29 @@ ERROR: number overflow at or near "1.79E+309" LINE 1: SELECT TO_BINARY_FLOAT(1.79E+309 DEFAULT y ON CONVERSION ERR... ^ SELECT TO_BINARY_FLOAT(c3 DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; - to_binary_float ------------------ - 1.23 - 3.14157 - 2.02405e+11 - - - NaN - Infinity - Infinity -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(c3 DEFAULT c4 ON CONVERSION ERROR) FR... + ^ SELECT TO_BINARY_FLOAT(c4 DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(c4 DEFAULT c3 ON CONVERSION ERROR) FR... + ^ SELECT TO_BINARY_FLOAT(3.14 DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; - to_binary_float ------------------ - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(3.14 DEFAULT c3 ON CONVERSION ERROR) ... + ^ SELECT TO_BINARY_FLOAT(3.14 DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; - to_binary_float ------------------ - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(3.14 DEFAULT c4 ON CONVERSION ERROR) ... + ^ SELECT TO_BINARY_FLOAT(3.14E+100 DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; - to_binary_float ------------------ - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(3.14E+100 DEFAULT c3 ON CONVERSION ER... + ^ SELECT TO_BINARY_FLOAT(3.14E+100 DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; - to_binary_float ------------------ - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity -(8 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(3.14E+100 DEFAULT c4 ON CONVERSION ER... + ^ SELECT TO_BINARY_FLOAT(3.14E+400 DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- overflow ERROR: number overflow at or near "3.14E+400" LINE 1: SELECT TO_BINARY_FLOAT(3.14E+400 DEFAULT c3 ON CONVERSION ER... @@ -542,29 +489,37 @@ ERROR: number overflow at or near "3.14E+400" LINE 1: SELECT TO_BINARY_FLOAT(3.14E+400 DEFAULT c4 ON CONVERSION ER... ^ SELECT TO_BINARY_FLOAT('3.14' DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14' DEFAULT c3 ON CONVERSION ERROR... + ^ SELECT TO_BINARY_FLOAT('3.14' DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14' DEFAULT c4 ON CONVERSION ERROR... + ^ SELECT TO_BINARY_FLOAT('3.14E+100' DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14E+100' DEFAULT c3 ON CONVERSION ... + ^ SELECT TO_BINARY_FLOAT('3.14E+100' DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14E+100' DEFAULT c4 ON CONVERSION ... + ^ SELECT TO_BINARY_FLOAT('3.14E+400' DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14E+400' DEFAULT c3 ON CONVERSION ... + ^ SELECT TO_BINARY_FLOAT('3.14E+400' DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER By c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT('3.14E+400' DEFAULT c4 ON CONVERSION ... + ^ SELECT TO_BINARY_FLOAT(NULL DEFAULT c3 ON CONVERSION ERROR) FROM tbf ORDER BY c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(NULL DEFAULT c3 ON CONVERSION ERROR) ... + ^ SELECT TO_BINARY_FLOAT(NULL DEFAULT c4 ON CONVERSION ERROR) FROM tbf ORDER BY c1; -- error -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_binary_float +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_BINARY_FLOAT(NULL DEFAULT c4 ON CONVERSION ERROR) ... + ^ SELECT TO_BINARY_FLOAT(3.14E+400 DEFAULT ab ON CONVERSION ERROR) FROM tbf ORDER BY c1; -- overflow ERROR: number overflow at or near "3.14E+400" LINE 1: SELECT TO_BINARY_FLOAT(3.14E+400 DEFAULT ab ON CONVERSION ER... @@ -674,6 +629,73 @@ SELECT TO_BINARY_FLOAT(NULL DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR) (1 row) +--to_binary_float +drop table tnb; +ERROR: table "tnb" does not exist +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; + num +----- + 123 +(1 row) + +select to_binary_float('asd' default num on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default num on conversion error... + ^ +select to_binary_float('asd' default num||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default num||'123' on conversio... + ^ +select to_binary_float('asd' default to_char(num)||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default to_char(num)||'123' on ... + ^ +select to_binary_float('asd' default num::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default num::text||'123' on con... + ^ +select to_binary_float('asd' default (num::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default (num::text)::text||'123... + ^ +select to_binary_float('asd' default ('123'::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_binary_float('asd' default ('123'::text)::text||'1... + ^ +select to_binary_float('asd' default '123'::text||'123' on conversion error)from tnb; + to_binary_float +----------------- + 123123 +(1 row) + +drop table tnb; +--参数引用 +drop table employees; +ERROR: table "employees" does not exist +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); +NOTICE: CREATE TABLE will create implicit sequence "employees_id_seq" for serial column "employees.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "employees_pkey" for table "employees" +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_binary_float('asd' default $1 on conversion error), $2); +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_binary_float('asd' default $1||'123' on conversion error), $2); +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; +SELECT * FROM employees; + id | name | age +----+--------+----- + 1 | 123 | 30 + 2 | 123123 | 28 +(2 rows) + -- test zero SELECT TO_BINARY_FLOAT(0); to_binary_float @@ -829,3 +851,4 @@ DROP TABLE tbf; DROP TABLE tbf2; DROP TABLE t_ne; drop schema if exists func_tbf cascade; +NOTICE: drop cascades to table employees diff --git a/src/test/regress/expected/to_number_default.out b/src/test/regress/expected/to_number_default.out index 43be63f8b0..90051b704a 100644 --- a/src/test/regress/expected/to_number_default.out +++ b/src/test/regress/expected/to_number_default.out @@ -257,29 +257,13 @@ SELECT TO_NUMBER(c1 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1; (7 rows) SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef - to_number ------------ - 1 - 2 - 3 - 4 - 5 - 6 - 7 -(7 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR) FROM ... + ^ SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef - to_number ------------ - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 -(7 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM t... + ^ SELECT to_number('<1234>' DEFAULT 999 ON CONVERSION ERROR,'PR9999999'); ERROR: "9" must be ahead of "PR" CONTEXT: referenced column: to_number @@ -854,29 +838,13 @@ SELECT TO_NUMBER(c1 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber OR (7 rows) SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef - to_number ------------ - 1 - 2 - 3 - 4 - 5 - 6 - 7 -(7 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR, '99D9... + ^ SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef - to_number ------------ - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 - 3.14 -(7 rows) - +ERROR: This argument must be a literal or bind variable. +LINE 1: SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR, '99D99... + ^ SELECT TO_NUMBER(c2 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1; to_number ----------- @@ -1271,6 +1239,73 @@ SELECT TO_NUMBER(NULL DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR); (1 row) +--to_number default +drop table tnb; +ERROR: table "tnb" does not exist +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; + num +----- + 123 +(1 row) + +select to_number('asd' default num on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default num on conversion error)from ... + ^ +select to_number('asd' default num||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default num||'123' on conversion erro... + ^ +select to_number('asd' default to_char(num)||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default to_char(num)||'123' on conver... + ^ +select to_number('asd' default num::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default num::text||'123' on conversio... + ^ +select to_number('asd' default (num::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default (num::text)::text||'123' on c... + ^ +select to_number('asd' default ('123'::text)::text||'123' on conversion error)from tnb; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_number('asd' default ('123'::text)::text||'123' on... + ^ +select to_number('asd' default '123'::text||'123' on conversion error)from tnb; + to_number +----------- + 123123 +(1 row) + +drop table tnb; +--参数引用 +drop table employees; +ERROR: table "employees" does not exist +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); +NOTICE: CREATE TABLE will create implicit sequence "employees_id_seq" for serial column "employees.id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "employees_pkey" for table "employees" +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_number('asd' default $1 on conversion error), $2); +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_number('asd' default $1||'123' on conversion error), $2); +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; +SELECT * FROM employees; + id | name | age +----+--------+----- + 1 | 123 | 30 + 2 | 123123 | 28 +(2 rows) + CREATE TABLE tonumber_exec (c1 int, func_info text, res float4); PREPARE default_param_text2(int, text, text) AS INSERT INTO tonumber_exec VALUES ($1, CONCAT('TO_NUMBER(', $2, ' DEFAULT ', $3, ' ON CONVERSION ERROR)'), TO_NUMBER($2 DEFAULT $3 ON CONVERSION ERROR)); @@ -1365,3 +1400,4 @@ SELECT * FROM tonumber_exec ORDER BY c1; DROP TABLE tonumber; DROP TABLE tonumber_exec; drop schema if exists func_to_number cascade; +NOTICE: drop cascades to table employees diff --git a/src/test/regress/expected/to_timestamp_default.out b/src/test/regress/expected/to_timestamp_default.out index 567024e277..35939c3b0a 100644 --- a/src/test/regress/expected/to_timestamp_default.out +++ b/src/test/regress/expected/to_timestamp_default.out @@ -1512,3 +1512,66 @@ SELECT TO_TIMESTAMP (null DEFAULT '11-09-11 14:10:10.123000' ON CONVERSION ERROR (1 row) +--to_timestamp default +drop table tspc; +ERROR: table "tspc" does not exist +create table tspc(tx varchar2(40)); +insert into tspc values('2025-09-01'); +select * from tspc; + tx +------------ + 2025-09-01 +(1 row) + +select to_timestamp('asd' default tx on conversion error)from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default tx on conversion error)fro... + ^ +select to_timestamp('asd' default tx||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default tx||' 13:45:22.123123' on ... + ^ +select to_timestamp('asd' default to_char(tx)||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default to_char(tx)||' 13:45:22.12... + ^ +select to_timestamp('asd' default tx::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default tx::text||' 13:45:22.12312... + ^ +select to_timestamp('asd' default (tx::text)::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default (tx::text)::text||' 13:45:... + ^ +select to_timestamp('asd' default '2025-09-01'::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; + to_timestamp +--------------------- + 2025-09-01 13:45:22 +(1 row) + +select to_timestamp('asd' default (select '2025-09-01')::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +ERROR: This argument must be a literal or bind variable. +LINE 1: select to_timestamp('asd' default (select '2025-09-01')::tex... + ^ +drop table tspc; +--参数引用 +drop table employees; +ERROR: table "employees" does not exist +CREATE TABLE employees ( + date TEXT +); +PREPARE insert_employee1 (TEXT) AS +INSERT INTO employees (date) VALUES (to_timestamp('asd' default $1 on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')); +PREPARE insert_employee2 (TEXT) AS +INSERT INTO employees (date) VALUES (to_timestamp('asd' default $1||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')); +EXECUTE insert_employee1('2025-09-01 13:45:22.123123'); +EXECUTE insert_employee2('2025-09-01'); +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; +SELECT * FROM employees; + date +--------------------- + 2025-09-01 13:45:22 + 2025-09-01 13:45:22 +(2 rows) + diff --git a/src/test/regress/sql/cast.sql b/src/test/regress/sql/cast.sql index 4d28f439f0..116d1aa15f 100755 --- a/src/test/regress/sql/cast.sql +++ b/src/test/regress/sql/cast.sql @@ -1150,3 +1150,40 @@ SELECT cast ('01-Sep-03 14:10:10.123000' as timestamp DEFAULT '11-Sep-11 14:10:1 SELECT cast ('01-Oct-03 14:10:10.123000' as timestamp DEFAULT '11-Oct-11 14:10:10.123000' ON CONVERSION ERROR,'DD-Mon-RR HH24:MI:SS.FF'); SELECT cast ('01-Nov-03 14:10:10.123000' as timestamp DEFAULT '11-Nov-11 14:10:10.123000' ON CONVERSION ERROR,'DD-Mon-RR HH24:MI:SS.FF'); SELECT cast ('01-Dec-03 14:10:10.123000' as timestamp DEFAULT '11-Dec-11 14:10:10.123000' ON CONVERSION ERROR,'DD-Mon-RR HH24:MI:SS.FF'); + +--cast +drop table tnb; +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; +select cast('asd' as numeric default num on conversion error)from tnb; +select cast('asd' as numeric default num||'123' on conversion error)from tnb; +select cast('asd' as numeric default to_char(num)||'123' on conversion error)from tnb; +select cast('asd' as numeric default num::text||'123' on conversion error)from tnb; +select cast('asd' as numeric default (num::text)::text||'123' on conversion error)from tnb; +select cast('asd' as numeric default ('123'::text)::text||'123' on conversion error)from tnb; +select cast('asd' as numeric default '123'::text||'123' on conversion error)from tnb; +drop table tnb; + +--参数引用 +drop table employees; +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); + +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (cast('asd' as numeric default $1 on conversion error), $2); + +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (cast('asd' as numeric default $1||'123' on conversion error), $2); + +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); + +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; + +SELECT * FROM employees; +drop table employees; diff --git a/src/test/regress/sql/func_to_binary_float.sql b/src/test/regress/sql/func_to_binary_float.sql index 1ae372e891..49b7436caa 100644 --- a/src/test/regress/sql/func_to_binary_float.sql +++ b/src/test/regress/sql/func_to_binary_float.sql @@ -119,6 +119,42 @@ SELECT TO_BINARY_FLOAT(NULL DEFAULT '1.79769313486231E+100' ON CONVERSION ERROR) SELECT TO_BINARY_FLOAT(NULL DEFAULT 1.79769313486231E+310 ON CONVERSION ERROR); -- error: overflow SELECT TO_BINARY_FLOAT(NULL DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR); -- NULL +--to_binary_float +drop table tnb; +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; +select to_binary_float('asd' default num on conversion error)from tnb; +select to_binary_float('asd' default num||'123' on conversion error)from tnb; +select to_binary_float('asd' default to_char(num)||'123' on conversion error)from tnb; +select to_binary_float('asd' default num::text||'123' on conversion error)from tnb; +select to_binary_float('asd' default (num::text)::text||'123' on conversion error)from tnb; +select to_binary_float('asd' default ('123'::text)::text||'123' on conversion error)from tnb; +select to_binary_float('asd' default '123'::text||'123' on conversion error)from tnb; +drop table tnb; + +--参数引用 +drop table employees; +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); + +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_binary_float('asd' default $1 on conversion error), $2); + +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_binary_float('asd' default $1||'123' on conversion error), $2); + +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); + +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; + +SELECT * FROM employees; + -- test zero SELECT TO_BINARY_FLOAT(0); SELECT TO_BINARY_FLOAT('test' DEFAULT 0 ON CONVERSION ERROR); diff --git a/src/test/regress/sql/to_number_default.sql b/src/test/regress/sql/to_number_default.sql index 76df3a529e..4e036b784e 100644 --- a/src/test/regress/sql/to_number_default.sql +++ b/src/test/regress/sql/to_number_default.sql @@ -231,6 +231,41 @@ SELECT TO_NUMBER(NULL DEFAULT 1.79769313486231E+310 ON CONVERSION ERROR); SELECT TO_NUMBER(NULL DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR); +--to_number default +drop table tnb; +create table tnb(num varchar2(40)); +insert into tnb values('123'); +select * from tnb; +select to_number('asd' default num on conversion error)from tnb; +select to_number('asd' default num||'123' on conversion error)from tnb; +select to_number('asd' default to_char(num)||'123' on conversion error)from tnb; +select to_number('asd' default num::text||'123' on conversion error)from tnb; +select to_number('asd' default (num::text)::text||'123' on conversion error)from tnb; +select to_number('asd' default ('123'::text)::text||'123' on conversion error)from tnb; +select to_number('asd' default '123'::text||'123' on conversion error)from tnb; +drop table tnb; + +--参数引用 +drop table employees; +CREATE TABLE employees ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL +); + +PREPARE insert_employee1 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_number('asd' default $1 on conversion error), $2); + +PREPARE insert_employee2 (TEXT, INT) AS +INSERT INTO employees (name, age) VALUES (to_number('asd' default $1||'123' on conversion error), $2); + +EXECUTE insert_employee1('123', 30); +EXECUTE insert_employee2('123', 28); + +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; + +SELECT * FROM employees; CREATE TABLE tonumber_exec (c1 int, func_info text, res float4); diff --git a/src/test/regress/sql/to_timestamp_default.sql b/src/test/regress/sql/to_timestamp_default.sql index 30e04c05e9..389fb29b66 100644 --- a/src/test/regress/sql/to_timestamp_default.sql +++ b/src/test/regress/sql/to_timestamp_default.sql @@ -402,3 +402,36 @@ SELECT TO_TIMESTAMP (null ) ; SELECT TO_TIMESTAMP (null DEFAULT '11-Sep-11 14:10:10.123000'on conversion error); SELECT TO_TIMESTAMP (null DEFAULT '11-09-11 14:10:10.123000' ON CONVERSION ERROR,'DD-MM-RR HH24:MI:SS.FF') ; SELECT TO_TIMESTAMP (null DEFAULT '11-09-11 14:10:10.123000' ON CONVERSION ERROR,'DD-MM-RR HH24:MI:SS.FF','NLS_DATE_LANGUAGE = American') ; + +--to_timestamp default +drop table tspc; +create table tspc(tx varchar2(40)); +insert into tspc values('2025-09-01'); +select * from tspc; +select to_timestamp('asd' default tx on conversion error)from tspc; +select to_timestamp('asd' default tx||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +select to_timestamp('asd' default to_char(tx)||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +select to_timestamp('asd' default tx::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +select to_timestamp('asd' default (tx::text)::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +select to_timestamp('asd' default '2025-09-01'::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +select to_timestamp('asd' default (select '2025-09-01')::text||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; +drop table tspc; +--参数引用 +drop table employees; +CREATE TABLE employees ( + date TEXT +); + +PREPARE insert_employee1 (TEXT) AS +INSERT INTO employees (date) VALUES (to_timestamp('asd' default $1 on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')); + +PREPARE insert_employee2 (TEXT) AS +INSERT INTO employees (date) VALUES (to_timestamp('asd' default $1||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')); + +EXECUTE insert_employee1('2025-09-01 13:45:22.123123'); +EXECUTE insert_employee2('2025-09-01'); + +DEALLOCATE insert_employee1; +DEALLOCATE insert_employee2; + +SELECT * FROM employees; -- Gitee