diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index f4314166823003179eb03ea1a6fab9693b004b39..5bd6d02cf7833cd5fa2cf090ea6633fdefb91c29 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); @@ -678,7 +687,7 @@ static void contain_unsupport_node(Node* node, bool* has_unsupport_default_node) %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 @@ -29320,7 +29329,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)); @@ -29353,6 +29371,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, @@ -29383,6 +29411,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, @@ -29879,12 +29917,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); @@ -30193,11 +30271,6 @@ func_expr_common_subexpr: } ; -default_on_err_expr: - DEFAULT a_expr ON CONVERSION_P ERROR_P { - $$ = $2; - } - ; /* * SQL/XML support */ @@ -34926,18 +34999,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; -void contain_unsupport_node(Node* node, bool* has_unsupport_default_node) + 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 && IsA(node, ColumnRef)) { - *has_unsupport_default_node = true; - return; + if (node == NULL) + return false; + + if (IsA(node, ColumnRef)) { + return true; } - (void)raw_expression_tree_walker(node, (bool (*)())contain_unsupport_node, (void*)has_unsupport_default_node); + + 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 2c7e489253b26de60efd4e4fbe723061dae1f366..acc489904a69e0b5f0e70fef19fbaf8a6cbca85b 100644 --- a/src/test/regress/expected/cast.out +++ b/src/test/regress/expected/cast.out @@ -3534,3 +3534,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 838f0cec22c03b32549675315a0298ae11ed91fb..bdd1f66d767cbd6f8867891556af9e51289a7b49 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 47eba3240b6ab5742e1f040fb3c79efd26b7a3e3..90051b704ada8b85b98ea0e426a45b87e01786a3 100644 --- a/src/test/regress/expected/to_number_default.out +++ b/src/test/regress/expected/to_number_default.out @@ -257,20 +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 -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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 @@ -845,20 +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 -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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 ----------- @@ -1265,26 +1251,29 @@ select * from tnb; (1 row) select to_number('asd' default num on conversion error)from tnb; -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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: default argument must be a literal or bind -CONTEXT: referenced column: to_number +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; - to_number ------------ - 123123 -(1 row) - +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 ----------- @@ -1292,20 +1281,31 @@ select to_number('asd' default '123'::text||'123' on conversion error)from tnb; (1 row) drop table tnb; -create table tnbde(shuzi float); -insert into tnbde values(123.123); -insert into tnbde values(12375675); -select to_number('asdad' default shuzi on conversion error) from tnbde; -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_number -select * from tnbde; - shuzi ----------- - 123.123 - 12375675 +--参数引用 +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) -drop table tnbde; 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)); @@ -1400,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 efcd1ad7b402bf1102e773925b10041b3cea6881..d341162b0dc6b901d04438fc5a7b668f502cb3f3 100644 --- a/src/test/regress/expected/to_timestamp_default.out +++ b/src/test/regress/expected/to_timestamp_default.out @@ -1504,6 +1504,10 @@ SELECT TO_TIMESTAMP (null DEFAULT '11-09-11 14:10:10.123000' ON CONVERSION ERROR (1 row) +<<<<<<< HEAD +--to_timestamp default +======= +>>>>>>> master drop table tspc; ERROR: table "tspc" does not exist create table tspc(tx varchar2(40)); @@ -1515,6 +1519,27 @@ select * from tspc; (1 row) select to_timestamp('asd' default tx on conversion error)from tspc; +<<<<<<< HEAD +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:... + ^ +======= ERROR: default argument must be a literal or bind CONTEXT: referenced column: to_timestamp select to_timestamp('asd' default tx||' 13:45:22.123123' on conversion error,'yyyy-mm-dd hh24:mi:ss.ff')from tspc; @@ -1529,6 +1554,7 @@ CONTEXT: referenced column: to_timestamp 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: default argument must be a literal or bind CONTEXT: referenced column: to_timestamp +>>>>>>> master 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 --------------------- @@ -1536,16 +1562,28 @@ select to_timestamp('asd' default '2025-09-01'::text||' 13:45:22.123123' on conv (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; - to_timestamp +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 -(1 row) + 2025-09-01 13:45:22 +(2 rows) -drop table tspc; -create table tspc(tx varchar2(20)); -insert into tspc values('2025-09-01 11:24:02'); -insert into tspc values('2024-11-05 10:27:12'); -select to_timestamp('VFDVA' default tx on conversion error, 'YYYY-MM-DD HH24:MI:SS')from tspc; -ERROR: default argument must be a literal or bind -CONTEXT: referenced column: to_timestamp -drop table tspc; diff --git a/src/test/regress/sql/cast.sql b/src/test/regress/sql/cast.sql index 4d28f439f00d057e7932841bee1636ebe306a174..116d1aa15f2f68f3a719267e4d506f12e68e3c05 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 1ae372e89197659ea4c61e7a792751f0e5ab7111..49b7436caab4303a9cc766780b5ed68380af549e 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 14c2f14d7971b62a3acf37cc0d9fcf8befabc87e..a8db32b1ab436d0271c09740bda373625167eab2 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; --to_number default drop table tnb; diff --git a/src/test/regress/sql/to_timestamp_default.sql b/src/test/regress/sql/to_timestamp_default.sql index 6f2dd75aa53f4414a679c26bffd089d94fea572f..389fb29b660a5ee444e6027e59f643a48d0046ca 100644 --- a/src/test/regress/sql/to_timestamp_default.sql +++ b/src/test/regress/sql/to_timestamp_default.sql @@ -403,6 +403,7 @@ 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'); @@ -415,10 +416,22 @@ select to_timestamp('asd' default (tx::text)::text||' 13:45:22.123123' on conver 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 +); -create table tspc(tx varchar2(20)); -insert into tspc values('2025-09-01 11:24:02'); -insert into tspc values('2024-11-05 10:27:12'); -select to_timestamp('VFDVA' default tx on conversion error, 'YYYY-MM-DD HH24:MI:SS')from tspc; -drop table tspc; +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;