From 92a3ae6ba89f4d4c97ae0cb6f02365ff6028f647 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 5 Oct 2023 13:13:13 +0530 Subject: [PATCH 01/34] =?UTF-8?q?Fixed=20error:=20=E2=80=9Clost=20connecti?= =?UTF-8?q?on=20to=20parallel=20worker=E2=80=9D=20when=20running=20paralle?= =?UTF-8?q?l=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/scripts/create_extension.sql | 7 +++++++ contrib/babelfishpg_tds/src/backend/tds/err_handler.c | 10 ++++++++++ contrib/babelfishpg_tds/src/backend/tds/tdsbulkload.c | 2 ++ contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c | 8 ++++++++ contrib/babelfishpg_tds/src/backend/tds/tdssqlbatch.c | 4 ++++ contrib/babelfishpg_tsql/src/iterative_exec.c | 5 +++++ contrib/babelfishpg_tsql/src/linked_servers.c | 2 ++ contrib/babelfishpg_tsql/src/pl_comp.c | 2 ++ contrib/babelfishpg_tsql/src/pl_handler.c | 7 +++++++ contrib/babelfishpg_tsql/src/pltsql_bulkcopy.c | 2 ++ contrib/babelfishpg_tsql/src/procedures.c | 2 ++ contrib/babelfishpg_tsql/src/rolecmds.c | 2 ++ 12 files changed, 53 insertions(+) diff --git a/.github/scripts/create_extension.sql b/.github/scripts/create_extension.sql index 1849f88b28..0151f29f0d 100644 --- a/.github/scripts/create_extension.sql +++ b/.github/scripts/create_extension.sql @@ -8,5 +8,12 @@ GRANT ALL ON SCHEMA sys to :user; ALTER USER :user CREATEDB; ALTER SYSTEM SET babelfishpg_tsql.database_name = :db; ALTER SYSTEM SET babelfishpg_tsql.migration_mode = :'migration_mode'; +ALTER SYSTEM SET parallel_setup_cost = 0; +ALTER SYSTEM SET parallel_tuple_cost = 0; +ALTER SYSTEM SET min_parallel_index_scan_size = 0; +ALTER SYSTEM SET min_parallel_table_scan_size = 0; +ALTER SYSTEM SET force_parallel_mode = 1; +ALTER SYSTEM SET max_parallel_workers_per_gather = 4; +ALTER SYSTEM SET log_min_messages = debug3; SELECT pg_reload_conf(); CALL SYS.INITIALIZE_BABELFISH(:'user'); diff --git a/contrib/babelfishpg_tds/src/backend/tds/err_handler.c b/contrib/babelfishpg_tds/src/backend/tds/err_handler.c index ab689023a2..fd48459422 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/err_handler.c +++ b/contrib/babelfishpg_tds/src/backend/tds/err_handler.c @@ -195,8 +195,12 @@ get_tsql_error_details(ErrorData *edata, /* Possible infinite loop of errors. Do not touch it further. */ if (!error_stack_full()) + { + HOLD_INTERRUPTS(); elog(LOG, "Unmapped error found. Code: %d, Message: %s, File: %s, Line: %d, Context: %s", edata->sqlerrcode, edata->message, edata->filename, edata->lineno, error_context); + RESUME_INTERRUPTS(); + } return false; } @@ -267,8 +271,12 @@ get_tsql_error_details(ErrorData *edata, /* Possible infinite loop of errors. Do not touch it further. */ if (!error_stack_full()) + { + HOLD_INTERRUPTS(); elog(LOG, "Unmapped error found. Code: %d, Message: %s, File: %s, Line: %d, Context: %s", edata->sqlerrcode, edata->message, edata->filename, edata->lineno, error_context); + RESUME_INTERRUPTS(); + } *tsql_error_code = ERRCODE_PLTSQL_ERROR_NOT_MAPPED; *tsql_error_severity = 16; @@ -356,9 +364,11 @@ emit_tds_log(ErrorData *edata) /* Log the internal error message */ ErrorData *next_edata; + HOLD_INTERRUPTS(); next_edata = CopyErrorData(); elog(LOG, "internal error occurred: %s", next_edata->message); FreeErrorData(next_edata); + RESUME_INTERRUPTS(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsbulkload.c b/contrib/babelfishpg_tds/src/backend/tds/tdsbulkload.c index a51ea08755..194ed67af2 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsbulkload.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsbulkload.c @@ -990,6 +990,7 @@ ProcessBCPRequest(TDSRequest request) int ret; HOLD_CANCEL_INTERRUPTS(); + HOLD_INTERRUPTS(); /* * Discard remaining TDS_BULK_LOAD packets only if End of @@ -1014,6 +1015,7 @@ ProcessBCPRequest(TDSRequest request) req->rowCount, req->colCount), errhidestmt(true))); + RESUME_INTERRUPTS(); PG_RE_THROW(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index 123714d08f..f69bdc6671 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -550,6 +550,7 @@ SPExecuteSQL(TDSRequestSP req) } PG_CATCH(); { + HOLD_INTERRUPTS(); if (TDS_DEBUG_ENABLED(TDS_DEBUG2)) ereport(LOG, (errmsg("sp_executesql statement: %s", s.data), @@ -558,6 +559,7 @@ SPExecuteSQL(TDSRequestSP req) TDSStatementExceptionCallback(NULL, NULL, false); PG_RE_THROW(); + RESUME_INTERRUPTS(); } PG_END_TRY(); @@ -749,6 +751,7 @@ SPExecute(TDSRequestSP req) } PG_CATCH(); { + HOLD_INTERRUPTS(); if (TDS_DEBUG_ENABLED(TDS_DEBUG2)) ereport(LOG, (errmsg("sp_execute handle: %d", req->handle), @@ -758,6 +761,7 @@ SPExecute(TDSRequestSP req) TDSStatementExceptionCallback(NULL, NULL, false); tvp_lookup_list = NIL; PG_RE_THROW(); + RESUME_INTERRUPTS(); } PG_END_TRY(); @@ -871,6 +875,7 @@ SPPrepExec(TDSRequestSP req) } PG_CATCH(); { + HOLD_INTERRUPTS(); if (TDS_DEBUG_ENABLED(TDS_DEBUG2)) ereport(LOG, (errmsg("sp_prepexec handle: %d, " @@ -881,6 +886,7 @@ SPPrepExec(TDSRequestSP req) TDSStatementExceptionCallback(NULL, NULL, false); tvp_lookup_list = NIL; PG_RE_THROW(); + RESUME_INTERRUPTS(); } PG_END_TRY(); @@ -1099,6 +1105,7 @@ SPCustomType(TDSRequestSP req) } PG_CATCH(); { + HOLD_INTERRUPTS(); if (TDS_DEBUG_ENABLED(TDS_DEBUG2)) ereport(LOG, (errmsg("stored procedure: %s", req->name.data), @@ -1108,6 +1115,7 @@ SPCustomType(TDSRequestSP req) tvp_lookup_list = NIL; PG_RE_THROW(); + RESUME_INTERRUPTS(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdssqlbatch.c b/contrib/babelfishpg_tds/src/backend/tds/tdssqlbatch.c index db10653445..8acf94c751 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdssqlbatch.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdssqlbatch.c @@ -94,9 +94,13 @@ ExecuteSQLBatch(char *query) PG_CATCH(); { if (TDS_DEBUG_ENABLED(TDS_DEBUG2)) + { + HOLD_INTERRUPTS(); ereport(LOG, (errmsg("sql_batch statement: %s", query), errhidestmt(true))); + RESUME_INTERRUPTS(); + } PG_RE_THROW(); } diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index 6a21c1b194..1f83bf5e6c 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -1141,6 +1141,7 @@ handle_error(PLtsql_execstate *estate, { elog(DEBUG1, "TSQL TXN Stop execution error mapping failed : %d current batch status : %d read only function : %d", last_error_mapping_failed, *terminate_batch, ro_func); FreeErrorData(edata); + RESUME_INTERRUPTS(); PG_RE_THROW(); } @@ -1149,6 +1150,7 @@ handle_error(PLtsql_execstate *estate, FlushErrorState(); FreeErrorData(edata); + RESUME_INTERRUPTS(); } /* @@ -1253,6 +1255,7 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, int last_error; bool error_mapped; + HOLD_INTERRUPTS(); support_tsql_trans = pltsql_support_tsql_transactions(); /* Close trigger nesting in engine */ @@ -1298,6 +1301,7 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, estate->simple_eval_estate = NULL; if (simple_econtext_stack == NULL || topEntry != simple_econtext_stack) pltsql_create_econtext(estate); + RESUME_INTERRUPTS(); PG_RE_THROW(); } @@ -1308,6 +1312,7 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { /* Cleanup SPI connections if they exist. */ AtEOXact_SPI(false); + RESUME_INTERRUPTS(); PG_RE_THROW(); } diff --git a/contrib/babelfishpg_tsql/src/linked_servers.c b/contrib/babelfishpg_tsql/src/linked_servers.c index fa39bdd13c..451840e5c1 100644 --- a/contrib/babelfishpg_tsql/src/linked_servers.c +++ b/contrib/babelfishpg_tsql/src/linked_servers.c @@ -864,7 +864,9 @@ linked_server_establish_connection(char *servername, LinkedServerProcess * lspro } PG_CATCH(); { + HOLD_INTERRUPTS(); LINKED_SERVER_DEBUG("LINKED SERVER: Failed to establish connection to remote server due to error"); + RESUME_INTERRUPTS(); PG_RE_THROW(); } diff --git a/contrib/babelfishpg_tsql/src/pl_comp.c b/contrib/babelfishpg_tsql/src/pl_comp.c index 081b95f37b..8f0a49c73c 100644 --- a/contrib/babelfishpg_tsql/src/pl_comp.c +++ b/contrib/babelfishpg_tsql/src/pl_comp.c @@ -1583,9 +1583,11 @@ pltsql_post_expand_star(ParseState *pstate, ColumnRef *cref, List *l) } PG_CATCH(); { + HOLD_INTERRUPTS(); elog(LOG, "Cache lookup failed in pltsql_post_expand_star for attribute %d of relation %u", attnum, relid); attopts = (Datum) 0; + RESUME_INTERRUPTS(); } PG_END_TRY(); if (!attopts) diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index edd3c09343..52c95b19a1 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -4053,6 +4053,8 @@ terminate_batch(bool send_error, bool compile_error) bool error_mapping_failed = false; int rc; + HOLD_INTERRUPTS(); + elog(DEBUG2, "TSQL TXN finish current batch, error : %d compilation error : %d", send_error, compile_error); /* @@ -4124,9 +4126,12 @@ terminate_batch(bool send_error, bool compile_error) AbortCurTransaction = false; if (!send_error) + { + RESUME_INTERRUPTS(); ereport(ERROR, (errcode(ERRCODE_TRANSACTION_ROLLBACK), errmsg("Uncommittable transaction is detected at the end of the batch. The transaction is rolled back."))); + } } else if (send_error && !IsTransactionBlockActive()) { @@ -4141,6 +4146,8 @@ terminate_batch(bool send_error, bool compile_error) MemoryContextSwitchTo(oldcontext); } } + + RESUME_INTERRUPTS(); if (send_error) { PG_RE_THROW(); diff --git a/contrib/babelfishpg_tsql/src/pltsql_bulkcopy.c b/contrib/babelfishpg_tsql/src/pltsql_bulkcopy.c index 163be672f0..9384ba5adc 100644 --- a/contrib/babelfishpg_tsql/src/pltsql_bulkcopy.c +++ b/contrib/babelfishpg_tsql/src/pltsql_bulkcopy.c @@ -110,11 +110,13 @@ BulkCopy(BulkCopyStmt *stmt, uint64 *processed) } PG_CATCH(); { + HOLD_INTERRUPTS(); /* For exact row which caused error, we have BulkCopyErrorCallback. */ elog(WARNING, "Error while executing Bulk Copy. Error occured while processing at " "implicit Batch number: %d, Rows inserted in total: %ld", stmt->cur_batch_num, stmt->rows_processed); if (rel != NULL) table_close(rel, NoLock); + RESUME_INTERRUPTS(); PG_RE_THROW(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index 0295855fb3..adf66b9b3d 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -508,6 +508,7 @@ sp_describe_first_result_set_internal(PG_FUNCTION_ARGS) } PG_CATCH(); { + HOLD_INTERRUPTS(); query = psprintf("DROP VIEW %s", sp_describe_first_result_set_view_name); if ((rc = SPI_execute(query, false, 1)) < 0) @@ -516,6 +517,7 @@ sp_describe_first_result_set_internal(PG_FUNCTION_ARGS) pfree(query); pfree(sp_describe_first_result_set_view_name); SPI_finish(); + RESUME_INTERRUPTS(); PG_RE_THROW(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 380ded6ff2..edd0d1b682 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -2150,6 +2150,7 @@ babelfish_add_domain_mapping_entry_internal(PG_FUNCTION_ARGS) MemoryContext ectx; ErrorData *edata; + HOLD_INTERRUPTS(); ectx = MemoryContextSwitchTo(ccxt); table_close(bbf_domain_mapping_rel, RowExclusiveLock); heap_freetuple(tuple); @@ -2159,6 +2160,7 @@ babelfish_add_domain_mapping_entry_internal(PG_FUNCTION_ARGS) FlushErrorState(); MemoryContextSwitchTo(ectx); + RESUME_INTERRUPTS(); ereport(ERROR, (errcode(edata->sqlerrcode), errmsg("Domain mapping entry could not be added due to following reason: %s", From 6b2a5096fabc4ee940a701ce53fd9da58511543d Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 12 Oct 2023 18:18:51 +0530 Subject: [PATCH 02/34] Re-enable parallel query tests marked for BABEL-4393 --- test/JDBC/parallel_query_jdbc_schedule | 50 +++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index a4abceef5c..a7fa5d2c3d 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -7,31 +7,31 @@ # These tests are crashing/failing with parallel query mode is on. # Group 1: lost connection to parallel worker BABEL-4393 -ignore#!#BABEL-3702-vu-verify -ignore#!#BABEL-728-vu-verify -ignore#!#BABEL-728 -ignore#!#BABEL-735 -ignore#!#BABEL-OPENJSON -ignore#!#Test-sp_addrolemember-vu-prepare -ignore#!#Test-sp_addrolemember-vu-verify -ignore#!#Test-sp_addrolemember-vu-cleanup -ignore#!#Test-sp_droprolemember-vu-prepare -ignore#!#Test-sp_droprolemember-vu-verify -ignore#!#Test-sp_droprolemember-vu-cleanup -ignore#!#TestDatetime-numeric-dateaddfunction-vu-prepare -ignore#!#TestDatetime-numeric-dateaddfunction-vu-verify -ignore#!#TestDatetime-numeric-representation-vu-prepare -ignore#!#TestDatetime-numeric-representation-vu-verify -ignore#!#babel_datatype_sqlvariant-vu-verify -ignore#!#babel_datatype_sqlvariant -ignore#!#babel_function -ignore#!#babel_function_string-vu-verify -ignore#!#babel_function_string -ignore#!#cast_numeric_types_to_datetime-vu-verify -ignore#!#cast_numeric_types_to_smalldatetime-vu-verify -ignore#!#sys-eomonth-vu-verify -ignore#!#babel_datetime2 -ignore#!#babel_collation +# ignore#!#BABEL-3702-vu-verify +# ignore#!#BABEL-728-vu-verify +# ignore#!#BABEL-728 +# ignore#!#BABEL-735 +# ignore#!#BABEL-OPENJSON +# ignore#!#Test-sp_addrolemember-vu-prepare +# ignore#!#Test-sp_addrolemember-vu-verify +# ignore#!#Test-sp_addrolemember-vu-cleanup +# ignore#!#Test-sp_droprolemember-vu-prepare +# ignore#!#Test-sp_droprolemember-vu-verify +# ignore#!#Test-sp_droprolemember-vu-cleanup +# ignore#!#TestDatetime-numeric-dateaddfunction-vu-prepare +# ignore#!#TestDatetime-numeric-dateaddfunction-vu-verify +# ignore#!#TestDatetime-numeric-representation-vu-prepare +# ignore#!#TestDatetime-numeric-representation-vu-verify +# ignore#!#babel_datatype_sqlvariant-vu-verify +# ignore#!#babel_datatype_sqlvariant +# ignore#!#babel_function +# ignore#!#babel_function_string-vu-verify +# ignore#!#babel_function_string +# ignore#!#cast_numeric_types_to_datetime-vu-verify +# ignore#!#cast_numeric_types_to_smalldatetime-vu-verify +# ignore#!#sys-eomonth-vu-verify +# ignore#!#babel_datetime2 +# ignore#!#babel_collation # Group 2: cannot start subtransactions during a parallel operation BABEL-4394 ignore#!#babel_format_standard_date_time From eabf316018d355ffe741f9d4521c7e02715f74c7 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 12 Oct 2023 20:17:16 +0530 Subject: [PATCH 03/34] Fix test cases --- test/JDBC/parallel_query_jdbc_schedule | 35 +++++++------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index a7fa5d2c3d..83c8f8295a 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -6,32 +6,13 @@ # 5. To add a test, add test name (without extension, , and . For example if test file name is TestBigInt.txt write TestBigInt) on a new line # These tests are crashing/failing with parallel query mode is on. -# Group 1: lost connection to parallel worker BABEL-4393 -# ignore#!#BABEL-3702-vu-verify -# ignore#!#BABEL-728-vu-verify -# ignore#!#BABEL-728 -# ignore#!#BABEL-735 -# ignore#!#BABEL-OPENJSON -# ignore#!#Test-sp_addrolemember-vu-prepare -# ignore#!#Test-sp_addrolemember-vu-verify -# ignore#!#Test-sp_addrolemember-vu-cleanup -# ignore#!#Test-sp_droprolemember-vu-prepare -# ignore#!#Test-sp_droprolemember-vu-verify -# ignore#!#Test-sp_droprolemember-vu-cleanup -# ignore#!#TestDatetime-numeric-dateaddfunction-vu-prepare -# ignore#!#TestDatetime-numeric-dateaddfunction-vu-verify -# ignore#!#TestDatetime-numeric-representation-vu-prepare -# ignore#!#TestDatetime-numeric-representation-vu-verify -# ignore#!#babel_datatype_sqlvariant-vu-verify -# ignore#!#babel_datatype_sqlvariant -# ignore#!#babel_function -# ignore#!#babel_function_string-vu-verify -# ignore#!#babel_function_string -# ignore#!#cast_numeric_types_to_datetime-vu-verify -# ignore#!#cast_numeric_types_to_smalldatetime-vu-verify -# ignore#!#sys-eomonth-vu-verify -# ignore#!#babel_datetime2 -# ignore#!#babel_collation +# Group 1: BABEL-4481 +ignore#!#Test-sp_addrolemember-vu-prepare +ignore#!#Test-sp_addrolemember-vu-verify +ignore#!#Test-sp_addrolemember-vu-cleanup +ignore#!#Test-sp_droprolemember-vu-prepare +ignore#!#Test-sp_droprolemember-vu-verify +ignore#!#Test-sp_droprolemember-vu-cleanup # Group 2: cannot start subtransactions during a parallel operation BABEL-4394 ignore#!#babel_format_standard_date_time @@ -345,6 +326,8 @@ ignore#!#getdate-vu-prepare ignore#!#getdate-vu-verify ignore#!#getdate-vu-cleanup ignore#!#getdatetest +ignore#!#TestDatetime-numeric-representation-vu-prepare +ignore#!#TestDatetime-numeric-representation-vu-verify # Taking too much time to complete. (TIME-OUT FAILURES) ignore#!#BABEL-SP_TABLE_PRIVILIGES-vu-verify From 9225395e8153147df2c442d16731f74374e8cac5 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Wed, 18 Oct 2023 10:53:14 +0530 Subject: [PATCH 04/34] Address review comments --- .../babelfishpg_tds/src/backend/tds/tdsrpc.c | 8 +++---- contrib/babelfishpg_tsql/src/iterative_exec.c | 24 ++++++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index f69bdc6671..2d1040e767 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -558,8 +558,8 @@ SPExecuteSQL(TDSRequestSP req) errdetail_params(req->nTotalParams))); TDSStatementExceptionCallback(NULL, NULL, false); - PG_RE_THROW(); RESUME_INTERRUPTS(); + PG_RE_THROW(); } PG_END_TRY(); @@ -760,8 +760,8 @@ SPExecute(TDSRequestSP req) TDSStatementExceptionCallback(NULL, NULL, false); tvp_lookup_list = NIL; - PG_RE_THROW(); RESUME_INTERRUPTS(); + PG_RE_THROW(); } PG_END_TRY(); @@ -885,8 +885,8 @@ SPPrepExec(TDSRequestSP req) TDSStatementExceptionCallback(NULL, NULL, false); tvp_lookup_list = NIL; - PG_RE_THROW(); RESUME_INTERRUPTS(); + PG_RE_THROW(); } PG_END_TRY(); @@ -1114,8 +1114,8 @@ SPCustomType(TDSRequestSP req) tvp_lookup_list = NIL; - PG_RE_THROW(); RESUME_INTERRUPTS(); + PG_RE_THROW(); } PG_END_TRY(); diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index 553e371e1e..d245d8998f 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -1135,7 +1135,9 @@ handle_error(PLtsql_execstate *estate, /* Mark transaction for termination */ if (IsTransactionBlockActive() && (last_error_mapping_failed || abort_transaction(estate, edata, override_flag))) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN Mark transaction for rollback error mapping failed : %d", last_error_mapping_failed); + RESUME_INTERRUPTS(); AbortCurTransaction = true; } @@ -1148,9 +1150,10 @@ handle_error(PLtsql_execstate *estate, /* In case of errors which terminate execution, let outer layer handle it */ if (last_error_mapping_failed || abort_execution(estate, edata, terminate_batch, override_flag) || ro_func) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN Stop execution error mapping failed : %d current batch status : %d read only function : %d", last_error_mapping_failed, *terminate_batch, ro_func); - FreeErrorData(edata); RESUME_INTERRUPTS(); + FreeErrorData(edata); PG_RE_THROW(); } @@ -1159,7 +1162,6 @@ handle_error(PLtsql_execstate *estate, FlushErrorState(); FreeErrorData(edata); - RESUME_INTERRUPTS(); } /* @@ -1264,7 +1266,6 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, int last_error; bool error_mapped; - HOLD_INTERRUPTS(); support_tsql_trans = pltsql_support_tsql_transactions(); /* Close trigger nesting in engine */ @@ -1282,7 +1283,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { if (internal_sp_started) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN PG semantics : Rollback internal savepoint"); + RESUME_INTERRUPTS(); RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(cur_ctxt); CurrentResourceOwner = oldowner; @@ -1291,7 +1294,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { if (is_part_of_pltsql_trycatch_block(estate)) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN PG semantics : Rollback current transaction"); + RESUME_INTERRUPTS(); HoldPinnedPortals(); SPI_setCurrentInternalTxnMode(true); AbortCurrentTransaction(); @@ -1302,7 +1307,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, } else { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN PG semantics : Mark transaction for rollback"); + RESUME_INTERRUPTS(); AbortCurTransaction = true; } /* Recreate evaluation context in case needed */ @@ -1310,7 +1317,6 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, estate->simple_eval_estate = NULL; if (simple_econtext_stack == NULL || topEntry != simple_econtext_stack) pltsql_create_econtext(estate); - RESUME_INTERRUPTS(); PG_RE_THROW(); } @@ -1321,7 +1327,6 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { /* Cleanup SPI connections if they exist. */ AtEOXact_SPI(false); - RESUME_INTERRUPTS(); PG_RE_THROW(); } @@ -1332,7 +1337,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, before_lxid == MyProc->lxid && before_subtxn_id == GetCurrentSubTransactionId()) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback internal savepoint"); + RESUME_INTERRUPTS(); /* Rollback internal savepoint if it is current savepoint */ RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(cur_ctxt); @@ -1344,8 +1351,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, * In case of no transaction, rollback the whole transaction to * match auto commit behavior */ - + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback current transaction"); + RESUME_INTERRUPTS(); /* Hold portals to make sure that cursors work */ HoldPinnedPortals(); AbortCurrentTransaction(); @@ -1358,7 +1366,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, * Trigger must run inside an explicit transaction In case of * error, rollback the transaction */ + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback internal transaction"); + RESUME_INTERRUPTS(); HoldPinnedPortals(); pltsql_rollback_txn(); estate->tsql_trigger_flags &= ~TSQL_TRAN_STARTED; @@ -1377,7 +1387,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, if (pltsql_implicit_transactions && IsTransactionBlockActive() && (estate->impl_txn_type == PLTSQL_IMPL_TRAN_START)) { + HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback implicit transaction"); + RESUME_INTERRUPTS(); pltsql_rollback_txn(); MemoryContextSwitchTo(cur_ctxt); } From c5ddb5db66e7e60311e515d8faec7fb8f7972415 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Wed, 18 Oct 2023 11:21:28 +0530 Subject: [PATCH 05/34] Address review comments --- contrib/babelfishpg_tsql/src/procedures.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index adf66b9b3d..ed975c3f0e 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -508,11 +508,14 @@ sp_describe_first_result_set_internal(PG_FUNCTION_ARGS) } PG_CATCH(); { - HOLD_INTERRUPTS(); query = psprintf("DROP VIEW %s", sp_describe_first_result_set_view_name); + HOLD_INTERRUPTS(); if ((rc = SPI_execute(query, false, 1)) < 0) + { + RESUME_INTERRUPTS(); elog(ERROR, "SPI_execute failed: %s", SPI_result_code_string(rc)); + } pfree(query); pfree(sp_describe_first_result_set_view_name); From 4a8dc87c33c42d8fcd4b906e447c89cdf660bc18 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 19 Oct 2023 18:06:18 +0530 Subject: [PATCH 06/34] Resolve TDS protocol violation occurring due to parallel query enforced --- .../src/backend/tds/tdsprinttup.c | 10 +++- .../src/backend/tds/tdsresponse.c | 60 ++++++++++++++----- .../babelfishpg_tds/src/backend/tds/tdsrpc.c | 13 ++-- .../src/include/tds_response.h | 6 +- 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsprinttup.c b/contrib/babelfishpg_tds/src/backend/tds/tdsprinttup.c index 006f2bca15..bc1b9251cb 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsprinttup.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsprinttup.c @@ -60,6 +60,13 @@ TdsPrinttupStartup(DestReceiver *self, int operation, TupleDesc typeinfo) { DR_printtup *myState = (DR_printtup *) self; Portal portal = myState->portal; + PlannedStmt *plannedStmt = PortalGetPrimaryStmt(portal); + List *targetList = NIL; + + if (portal->strategy != PORTAL_MULTI_QUERY) + { + targetList = FetchStatementTargetList((Node *) plannedStmt); + } /* * Create I/O buffer to be used for all messages. This cannot be inside @@ -78,7 +85,8 @@ TdsPrinttupStartup(DestReceiver *self, int operation, TupleDesc typeinfo) ALLOCSET_DEFAULT_SIZES); TdsSendRowDescription(typeinfo, - FetchPortalTargetList(portal), + plannedStmt, + targetList, portal->formats); return; } diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 24e4be415d..27ba123376 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -26,6 +26,7 @@ #include "miscadmin.h" #include "nodes/pathnodes.h" #include "parser/parse_coerce.h" +#include "parser/parsetree.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -401,9 +402,28 @@ PrintTupPrepareInfo(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) } } +static Node * +FindVarFromOutertree(Plan *plan, AttrNumber attno) +{ + TargetEntry *tle; + Plan *outerplan = outerPlan(plan); + /* Lefttree must not be NULL */ + Assert(outerplan); + tle = get_tle_by_resno(outerplan->targetlist, attno); + if (IsA(tle->expr, Var)) + { + Var *var = (Var *)tle->expr; + if (var->varno == OUTER_VAR) + { + return FindVarFromOutertree(outerplan, var->varattno); + } + } + return (Node *)tle->expr; +} + /* look for a typmod to return from a numeric expression */ static int32 -resolve_numeric_typmod_from_exp(Node *expr) +resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) { if (expr == NULL) return -1; @@ -434,6 +454,13 @@ resolve_numeric_typmod_from_exp(Node *expr) { Var *var = (Var *) expr; + /* If this var referes to tuple returned by its outer plan then find the original tle from it */ + if (var->varno == OUTER_VAR) + { + Assert(plannedstmt); + return (resolve_numeric_typmod_from_exp(plannedstmt, + FindVarFromOutertree(plannedstmt->planTree, var->varattno))); + } return var->vartypmod; } case T_OpExpr: @@ -464,8 +491,8 @@ resolve_numeric_typmod_from_exp(Node *expr) { arg1 = linitial(op->args); arg2 = lsecond(op->args); - typmod1 = resolve_numeric_typmod_from_exp(arg1); - typmod2 = resolve_numeric_typmod_from_exp(arg2); + typmod1 = resolve_numeric_typmod_from_exp(plannedstmt, arg1); + typmod2 = resolve_numeric_typmod_from_exp(plannedstmt, arg2); scale1 = (typmod1 - VARHDRSZ) & 0xffff; precision1 = ((typmod1 - VARHDRSZ) >> 16) & 0xffff; scale2 = (typmod2 - VARHDRSZ) & 0xffff; @@ -474,7 +501,7 @@ resolve_numeric_typmod_from_exp(Node *expr) else if (list_length(op->args) == 1) { arg1 = linitial(op->args); - typmod1 = resolve_numeric_typmod_from_exp(arg1); + typmod1 = resolve_numeric_typmod_from_exp(plannedstmt, arg1); scale1 = (typmod1 - VARHDRSZ) & 0xffff; precision1 = ((typmod1 - VARHDRSZ) >> 16) & 0xffff; scale2 = 0; @@ -653,7 +680,7 @@ resolve_numeric_typmod_from_exp(Node *expr) Assert(nullif->args != NIL); arg1 = linitial(nullif->args); - return resolve_numeric_typmod_from_exp(arg1); + return resolve_numeric_typmod_from_exp(plannedstmt, arg1); } case T_CoalesceExpr: { @@ -676,7 +703,7 @@ resolve_numeric_typmod_from_exp(Node *expr) foreach(lc, coale->args) { arg = lfirst(lc); - arg_typmod = resolve_numeric_typmod_from_exp(arg); + arg_typmod = resolve_numeric_typmod_from_exp(plannedstmt, arg); /* return -1 if we fail to resolve one of the arg's typmod */ if (arg_typmod == -1) return -1; @@ -717,7 +744,7 @@ resolve_numeric_typmod_from_exp(Node *expr) { casewhen = lfirst(lc); casewhen_result = (Node *) casewhen->result; - typmod = resolve_numeric_typmod_from_exp(casewhen_result); + typmod = resolve_numeric_typmod_from_exp(plannedstmt, casewhen_result); /* * return -1 if we fail to resolve one of the result's @@ -752,7 +779,7 @@ resolve_numeric_typmod_from_exp(Node *expr) Assert(aggref->args != NIL); te = (TargetEntry *) linitial(aggref->args); - typmod = resolve_numeric_typmod_from_exp((Node *) te->expr); + typmod = resolve_numeric_typmod_from_exp(plannedstmt, (Node *) te->expr); aggFuncName = get_func_name(aggref->aggfnoid); scale = (typmod - VARHDRSZ) & 0xffff; @@ -798,7 +825,7 @@ resolve_numeric_typmod_from_exp(Node *expr) { PlaceHolderVar *phv = (PlaceHolderVar *) expr; - return resolve_numeric_typmod_from_exp((Node *) phv->phexpr); + return resolve_numeric_typmod_from_exp(plannedstmt, (Node *) phv->phexpr); } case T_RelabelType: { @@ -807,7 +834,7 @@ resolve_numeric_typmod_from_exp(Node *expr) if (rlt->resulttypmod != -1) return rlt->resulttypmod; else - return resolve_numeric_typmod_from_exp((Node *) rlt->arg); + return resolve_numeric_typmod_from_exp(plannedstmt, (Node *) rlt->arg); } /* TODO handle more Expr types if needed */ default: @@ -1562,8 +1589,8 @@ TdsGetGenericTypmod(Node *expr) * for a relation. (used for keyset and dynamic cursors) */ void -PrepareRowDescription(TupleDesc typeinfo, List *targetlist, int16 *formats, - bool extendedInfo, bool fetchPkeys) +PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *targetlist, + int16 *formats, bool extendedInfo, bool fetchPkeys) { int natts = typeinfo->natts; int attno; @@ -1782,7 +1809,7 @@ PrepareRowDescription(TupleDesc typeinfo, List *targetlist, int16 *formats, * than -1. */ if (atttypmod == -1 && tle != NULL) - atttypmod = resolve_numeric_typmod_from_exp((Node *) tle->expr); + atttypmod = resolve_numeric_typmod_from_exp(plannedstmt, (Node *) tle->expr); /* * Get the precision and scale out of the typmod value if @@ -2558,7 +2585,7 @@ TdsSendInfoOrError(int token, int number, int state, int class, } void -TdsSendRowDescription(TupleDesc typeinfo, +TdsSendRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *targetlist, int16 *formats) { TDSRequest request = TdsRequestCtrl->request; @@ -2567,7 +2594,7 @@ TdsSendRowDescription(TupleDesc typeinfo, Assert(typeinfo != NULL); /* Prepare the column metadata first */ - PrepareRowDescription(typeinfo, targetlist, formats, false, false); + PrepareRowDescription(typeinfo, plannedstmt, targetlist, formats, false, false); /* * If fNoMetadata flags is set in RPC header flag, the server doesn't need @@ -3293,7 +3320,8 @@ TDSStatementExceptionCallback(PLtsql_execstate *estate, PLtsql_stmt *stmt, bool void SendColumnMetadata(TupleDesc typeinfo, List *targetlist, int16 *formats) { - TdsSendRowDescription(typeinfo, targetlist, formats); + /* This will only be used for sp_preapre request hence do not need to pass plannedstmt */ + TdsSendRowDescription(typeinfo, NULL, targetlist, formats); TdsPrintTupShutdown(); } diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index 2d1040e767..623976d1a8 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -2234,10 +2234,15 @@ static void SendCursorResponse(TDSRequestSP req) { int cmd_type = TDS_CMD_UNKNOWN; - Portal portal; - /* fetch the portal */ - portal = GetPortalFromCursorHandle(req->cursorHandle, false); + Portal portal = GetPortalFromCursorHandle(req->cursorHandle, false); + PlannedStmt *plannedStmt = PortalGetPrimaryStmt(portal); + List *targetList = NIL; + + if (portal->strategy != PORTAL_MULTI_QUERY) + { + targetList = FetchStatementTargetList((Node *) plannedStmt); + } /* * If we are in aborted transaction state, we can't run @@ -2266,7 +2271,7 @@ SendCursorResponse(TDSRequestSP req) * break the protocol. We also need to fetch the primary keys for dynamic * and keyset cursors (XXX: these cursors are not yet implemented). */ - PrepareRowDescription(portal->tupDesc, FetchPortalTargetList(portal), + PrepareRowDescription(portal->tupDesc, plannedStmt, targetList, portal->formats, true, (req->scrollopt & (SP_CURSOR_SCROLLOPT_DYNAMIC | SP_CURSOR_SCROLLOPT_KEYSET))); diff --git a/contrib/babelfishpg_tds/src/include/tds_response.h b/contrib/babelfishpg_tds/src/include/tds_response.h index 92504287dc..698b52fa20 100644 --- a/contrib/babelfishpg_tds/src/include/tds_response.h +++ b/contrib/babelfishpg_tds/src/include/tds_response.h @@ -70,8 +70,8 @@ extern void TdsSendDone(int tag, int status, extern void SendColumnMetadataToken(int natts, bool sendRowStat); extern void SendTabNameToken(void); extern void SendColInfoToken(int natts, bool sendRowStat); -extern void PrepareRowDescription(TupleDesc typeinfo, List *targetlist, int16 *formats, - bool extendedInfo, bool fetchPkeys); +extern void PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *targetlist, + int16 *formats, bool extendedInfo, bool fetchPkeys); extern void SendReturnValueTokenInternal(ParameterToken token, uint8 status, FmgrInfo *finfo, Datum datum, bool isNull, bool forceCoercion); @@ -85,7 +85,7 @@ extern void TdsSendEnvChangeBinary(int envid, void *old, int old_nbytes); extern void TdsSendReturnStatus(int status); extern void TdsSendHandle(void); -extern void TdsSendRowDescription(TupleDesc typeinfo, +extern void TdsSendRowDescription(TupleDesc typeinfo, PlannedStmt *PlannedStmt, List *targetlist, int16 *formats); extern bool TdsPrintTup(TupleTableSlot *slot, DestReceiver *self); extern void TdsPrintTupShutdown(void); From 8e007d787c6eeae9144cd2494301102c3d05e5fa Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Fri, 20 Oct 2023 18:55:28 +0530 Subject: [PATCH 07/34] Addressed review comment --- contrib/babelfishpg_tsql/src/iterative_exec.c | 12 ++++++------ contrib/babelfishpg_tsql/src/rolecmds.c | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index d245d8998f..e7cca86fec 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -1285,9 +1285,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN PG semantics : Rollback internal savepoint"); - RESUME_INTERRUPTS(); RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); CurrentResourceOwner = oldowner; } else if (!IsTransactionBlockActive()) @@ -1296,13 +1296,13 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN PG semantics : Rollback current transaction"); - RESUME_INTERRUPTS(); HoldPinnedPortals(); SPI_setCurrentInternalTxnMode(true); AbortCurrentTransaction(); StartTransactionCommand(); SPI_setCurrentInternalTxnMode(false); MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); } } else @@ -1339,10 +1339,10 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback internal savepoint"); - RESUME_INTERRUPTS(); /* Rollback internal savepoint if it is current savepoint */ RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); CurrentResourceOwner = oldowner; } else if (!IsTransactionBlockActive()) @@ -1353,12 +1353,12 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, */ HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback current transaction"); - RESUME_INTERRUPTS(); /* Hold portals to make sure that cursors work */ HoldPinnedPortals(); AbortCurrentTransaction(); StartTransactionCommand(); MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); } else if (estate->tsql_trigger_flags & TSQL_TRAN_STARTED) { @@ -1368,11 +1368,11 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, */ HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback internal transaction"); - RESUME_INTERRUPTS(); HoldPinnedPortals(); pltsql_rollback_txn(); estate->tsql_trigger_flags &= ~TSQL_TRAN_STARTED; MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); } @@ -1389,9 +1389,9 @@ dispatch_stmt_handle_error(PLtsql_execstate *estate, { HOLD_INTERRUPTS(); elog(DEBUG1, "TSQL TXN TSQL semantics : Rollback implicit transaction"); - RESUME_INTERRUPTS(); pltsql_rollback_txn(); MemoryContextSwitchTo(cur_ctxt); + RESUME_INTERRUPTS(); } estate->impl_txn_type = PLTSQL_IMPL_TRAN_OFF; diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index aa03b99eae..eb30b2dfee 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -2156,7 +2156,6 @@ babelfish_add_domain_mapping_entry_internal(PG_FUNCTION_ARGS) MemoryContext ectx; ErrorData *edata; - HOLD_INTERRUPTS(); ectx = MemoryContextSwitchTo(ccxt); table_close(bbf_domain_mapping_rel, RowExclusiveLock); heap_freetuple(tuple); @@ -2166,7 +2165,6 @@ babelfish_add_domain_mapping_entry_internal(PG_FUNCTION_ARGS) FlushErrorState(); MemoryContextSwitchTo(ectx); - RESUME_INTERRUPTS(); ereport(ERROR, (errcode(edata->sqlerrcode), errmsg("Domain mapping entry could not be added due to following reason: %s", From 7741ad1af2dcdc96776eeaf71420f9d221bd0faa Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Mon, 23 Oct 2023 11:08:43 +0530 Subject: [PATCH 08/34] Resolve infinite recursion --- .../src/backend/tds/tdsresponse.c | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 27ba123376..b5074ebeab 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -129,6 +129,7 @@ static void FillTabNameWithoutNumParts(StringInfo buf, uint8 numParts, TdsRelati static void SetTdsEstateErrorData(void); static void ResetTdsEstateErrorData(void); static void SetAttributesForColmetada(TdsColumnMetaData *col); +static int32 resolve_numeric_typmod_from_exp(Plan *plan, Node *expr); static inline void SendPendingDone(bool more) @@ -402,8 +403,8 @@ PrintTupPrepareInfo(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) } } -static Node * -FindVarFromOutertree(Plan *plan, AttrNumber attno) +static int32 +resolve_numeric_typmod_outer_var(Plan *plan, AttrNumber attno) { TargetEntry *tle; Plan *outerplan = outerPlan(plan); @@ -415,15 +416,15 @@ FindVarFromOutertree(Plan *plan, AttrNumber attno) Var *var = (Var *)tle->expr; if (var->varno == OUTER_VAR) { - return FindVarFromOutertree(outerplan, var->varattno); + return resolve_numeric_typmod_outer_var(outerplan, var->varattno); } } - return (Node *)tle->expr; + return resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); } /* look for a typmod to return from a numeric expression */ static int32 -resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) +resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) { if (expr == NULL) return -1; @@ -457,9 +458,8 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) /* If this var referes to tuple returned by its outer plan then find the original tle from it */ if (var->varno == OUTER_VAR) { - Assert(plannedstmt); - return (resolve_numeric_typmod_from_exp(plannedstmt, - FindVarFromOutertree(plannedstmt->planTree, var->varattno))); + Assert(plan); + return (resolve_numeric_typmod_outer_var(plan, var->varattno)); } return var->vartypmod; } @@ -491,8 +491,8 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) { arg1 = linitial(op->args); arg2 = lsecond(op->args); - typmod1 = resolve_numeric_typmod_from_exp(plannedstmt, arg1); - typmod2 = resolve_numeric_typmod_from_exp(plannedstmt, arg2); + typmod1 = resolve_numeric_typmod_from_exp(plan, arg1); + typmod2 = resolve_numeric_typmod_from_exp(plan, arg2); scale1 = (typmod1 - VARHDRSZ) & 0xffff; precision1 = ((typmod1 - VARHDRSZ) >> 16) & 0xffff; scale2 = (typmod2 - VARHDRSZ) & 0xffff; @@ -501,7 +501,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) else if (list_length(op->args) == 1) { arg1 = linitial(op->args); - typmod1 = resolve_numeric_typmod_from_exp(plannedstmt, arg1); + typmod1 = resolve_numeric_typmod_from_exp(plan, arg1); scale1 = (typmod1 - VARHDRSZ) & 0xffff; precision1 = ((typmod1 - VARHDRSZ) >> 16) & 0xffff; scale2 = 0; @@ -680,7 +680,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) Assert(nullif->args != NIL); arg1 = linitial(nullif->args); - return resolve_numeric_typmod_from_exp(plannedstmt, arg1); + return resolve_numeric_typmod_from_exp(plan, arg1); } case T_CoalesceExpr: { @@ -703,7 +703,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) foreach(lc, coale->args) { arg = lfirst(lc); - arg_typmod = resolve_numeric_typmod_from_exp(plannedstmt, arg); + arg_typmod = resolve_numeric_typmod_from_exp(plan, arg); /* return -1 if we fail to resolve one of the arg's typmod */ if (arg_typmod == -1) return -1; @@ -744,7 +744,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) { casewhen = lfirst(lc); casewhen_result = (Node *) casewhen->result; - typmod = resolve_numeric_typmod_from_exp(plannedstmt, casewhen_result); + typmod = resolve_numeric_typmod_from_exp(plan, casewhen_result); /* * return -1 if we fail to resolve one of the result's @@ -779,7 +779,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) Assert(aggref->args != NIL); te = (TargetEntry *) linitial(aggref->args); - typmod = resolve_numeric_typmod_from_exp(plannedstmt, (Node *) te->expr); + typmod = resolve_numeric_typmod_from_exp(plan, (Node *) te->expr); aggFuncName = get_func_name(aggref->aggfnoid); scale = (typmod - VARHDRSZ) & 0xffff; @@ -825,7 +825,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) { PlaceHolderVar *phv = (PlaceHolderVar *) expr; - return resolve_numeric_typmod_from_exp(plannedstmt, (Node *) phv->phexpr); + return resolve_numeric_typmod_from_exp(plan, (Node *) phv->phexpr); } case T_RelabelType: { @@ -834,7 +834,7 @@ resolve_numeric_typmod_from_exp(PlannedStmt *plannedstmt, Node *expr) if (rlt->resulttypmod != -1) return rlt->resulttypmod; else - return resolve_numeric_typmod_from_exp(plannedstmt, (Node *) rlt->arg); + return resolve_numeric_typmod_from_exp(plan, (Node *) rlt->arg); } /* TODO handle more Expr types if needed */ default: @@ -1809,7 +1809,9 @@ PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *target * than -1. */ if (atttypmod == -1 && tle != NULL) - atttypmod = resolve_numeric_typmod_from_exp(plannedstmt, (Node *) tle->expr); + atttypmod = plannedstmt ? + resolve_numeric_typmod_from_exp(plannedstmt->planTree, (Node *) tle->expr) : + resolve_numeric_typmod_from_exp(NULL, (Node *) tle->expr); /* * Get the precision and scale out of the typmod value if From dcf94a3c94f3f9f1c1f5c2bbb881d9275a3ca081 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Mon, 23 Oct 2023 18:38:49 +0530 Subject: [PATCH 09/34] Handle Append and MergeAppend plan node differently --- .../src/backend/tds/tdsresponse.c | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index b5074ebeab..478a229a57 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -130,6 +130,7 @@ static void SetTdsEstateErrorData(void); static void ResetTdsEstateErrorData(void); static void SetAttributesForColmetada(TdsColumnMetaData *col); static int32 resolve_numeric_typmod_from_exp(Plan *plan, Node *expr); +static int32 resolve_numeric_typmod_outer_var(Plan *plan, AttrNumber attno); static inline void SendPendingDone(bool more) @@ -403,12 +404,70 @@ PrintTupPrepareInfo(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) } } +static int32 +resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) +{ + ListCell *lc; + uint8_t max_precision = 0, + max_scale = 0, + precision = 0, + scale = 0, + integralDigitCount = 0; + int32 typmod = -1, + result_typmod = -1; + List *planlist = NIL; + if (IsA(plan, Append)) + { + planlist = ((Append *) plan)->appendplans; + } + else if(IsA(plan, MergeAppend)) + { + planlist = ((MergeAppend *) plan)->mergeplans; + } + + Assert(planlist != NIL); + foreach(lc, ((Append *) plan)->appendplans) + { + Plan *outerplan = (Plan *) lfirst(lc); + TargetEntry *tle = get_tle_by_resno(outerplan->targetlist, attno); + if (IsA(tle->expr, Var)) + { + Var *var = (Var *)tle->expr; + if (var->varno == OUTER_VAR) + { + typmod = resolve_numeric_typmod_outer_var(outerplan, var->varattno); + } + } + typmod = resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); + if (typmod == -1) + continue; + scale = (typmod - VARHDRSZ) & 0xffff; + precision = ((typmod - VARHDRSZ) >> 16) & 0xffff; + integralDigitCount = Max(precision - scale, max_precision - max_scale); + max_scale = Max(max_scale, scale); + max_precision = integralDigitCount + max_scale; + result_typmod = ((max_precision << 16) | max_scale) + VARHDRSZ; + } + /* If max_precision is still default then use tds specific defaults */ + if (result_typmod == -1) + { + result_typmod = ((tds_default_numeric_precision << 16) | tds_default_numeric_scale) + VARHDRSZ; + } + return result_typmod; +} + static int32 resolve_numeric_typmod_outer_var(Plan *plan, AttrNumber attno) { - TargetEntry *tle; - Plan *outerplan = outerPlan(plan); - /* Lefttree must not be NULL */ + TargetEntry *tle; + Plan *outerplan = NULL; + + if (IsA(plan, Append) || IsA(plan, MergeAppend)) + return resolve_numeric_typmod_from_append_or_mergeappend(plan, attno); + else + outerplan = outerPlan(plan); + + /* outerplan must not be NULL */ Assert(outerplan); tle = get_tle_by_resno(outerplan->targetlist, attno); if (IsA(tle->expr, Var)) From dd1bc908804bab09a44826c328dc5db4a22737a3 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Mon, 23 Oct 2023 18:46:32 +0530 Subject: [PATCH 10/34] Update schedule file for parallel testing --- test/JDBC/parallel_query_jdbc_schedule | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index 83c8f8295a..a491161258 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -316,11 +316,6 @@ ignore#!#babel_money # BABEL-4423 ignore#!#BABEL-IDENTITY -# BABEL-4424 -ignore#!#TestDecimal -ignore#!#TestNumeric -ignore#!#numericOverflow - # BABEL-4425 - Taking too much time to run. ignore#!#getdate-vu-prepare ignore#!#getdate-vu-verify From 38c48fcbf57e8237ee329758d668d1b1b2da4d9c Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Mon, 23 Oct 2023 20:35:24 +0530 Subject: [PATCH 11/34] Fix test cases --- test/JDBC/expected/BABEL-3943.out | 7 +------ test/JDBC/expected/babel_613.out | 14 +++++++------- test/JDBC/input/BABEL-3943.mix | 5 ----- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/test/JDBC/expected/BABEL-3943.out b/test/JDBC/expected/BABEL-3943.out index 7210ff5444..d4e5339c23 100644 --- a/test/JDBC/expected/BABEL-3943.out +++ b/test/JDBC/expected/BABEL-3943.out @@ -16,7 +16,6 @@ GO -- tsql --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and ISNULL([owner_amounts].[active], 0) = 1 AND [owner_amounts].[tax] is not null GO ~~START~~ @@ -25,7 +24,6 @@ numeric ~~END~~ --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as smallint) = 1 AND [owner_amounts].[tax] is not null GO ~~START~~ @@ -34,7 +32,6 @@ numeric ~~END~~ --- TODO: Fix BABEL-4359 SELECT TOP 1 [owner_amounts].[tax] FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as smallint) = 1 GO ~~START~~ @@ -43,16 +40,14 @@ numeric ~~END~~ --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as int) = 1 AND [owner_amounts].[tax] is not null GO ~~START~~ numeric -0E-8 +0.000000 ~~END~~ --- TODO: Fix BABEL-4359 SELECT TOP 1 [owner_amounts].[tax] FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as int) = 1 GO ~~START~~ diff --git a/test/JDBC/expected/babel_613.out b/test/JDBC/expected/babel_613.out index 76c4a668b8..096d1ca11f 100644 --- a/test/JDBC/expected/babel_613.out +++ b/test/JDBC/expected/babel_613.out @@ -159,14 +159,14 @@ select b from t1; go ~~START~~ numeric -4.00000000 -10.12340000 -1.20000000 +4.0000 +10.1234 +1.2000 -16.00000000 -10.12300000 -6.00000000 -101.12300000 +16.0000 +10.1230 +6.0000 +101.1230 ~~END~~ diff --git a/test/JDBC/input/BABEL-3943.mix b/test/JDBC/input/BABEL-3943.mix index b7577ad318..6c9796f8a6 100644 --- a/test/JDBC/input/BABEL-3943.mix +++ b/test/JDBC/input/BABEL-3943.mix @@ -14,23 +14,18 @@ select 0,1,862 from generate_series(1,200000); GO -- tsql --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and ISNULL([owner_amounts].[active], 0) = 1 AND [owner_amounts].[tax] is not null GO --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as smallint) = 1 AND [owner_amounts].[tax] is not null GO --- TODO: Fix BABEL-4359 SELECT TOP 1 [owner_amounts].[tax] FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as smallint) = 1 GO --- TODO: Fix BABEL-4359 SELECT avg([owner_amounts].[tax]) FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as int) = 1 AND [owner_amounts].[tax] is not null GO --- TODO: Fix BABEL-4359 SELECT TOP 1 [owner_amounts].[tax] FROM [owner_amounts] WHERE moment_id = 862 and cast([owner_amounts].[active] as int) = 1 GO From 5742ab2432d969ff4f1b84d82b7e91487fd21fd7 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 24 Oct 2023 16:16:58 +0530 Subject: [PATCH 12/34] Ignore test time out issue --- test/JDBC/parallel_query_jdbc_schedule | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index a491161258..02205e5dbb 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -340,3 +340,6 @@ ignore#!#TestSimpleErrors ignore#!#ISC-Views ignore#!#TestSimpleErrorsWithXactAbort ignore#!#BABEL-2513 +ignore#!#Test-sp_rename-dep-vu-prepare +ignore#!#Test-sp_rename-dep-vu-verify +ignore#!#Test-sp_rename-dep-vu-cleanup From 9f17a66a5b28039cf720fca173805970c353c08c Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 24 Oct 2023 12:01:00 +0000 Subject: [PATCH 13/34] Fixed union all test cases --- test/JDBC/expected/babel_613.out | 16 ++++++++++------ test/JDBC/input/babel_613.sql | 8 ++++++-- test/JDBC/parallel_query_jdbc_schedule | 13 +------------ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/test/JDBC/expected/babel_613.out b/test/JDBC/expected/babel_613.out index 096d1ca11f..888b9c1720 100644 --- a/test/JDBC/expected/babel_613.out +++ b/test/JDBC/expected/babel_613.out @@ -154,18 +154,22 @@ numeric -- test Union All -select a from t1 Union All -select b from t1; +select * from + ( + select a as col from t1 Union All + select b as col from t1 + ) dummy +order by col go ~~START~~ numeric + +1.2000 4.0000 +6.0000 +10.1230 10.1234 -1.2000 - 16.0000 -10.1230 -6.0000 101.1230 ~~END~~ diff --git a/test/JDBC/input/babel_613.sql b/test/JDBC/input/babel_613.sql index 4c09aa5e77..fd66c3d4d6 100644 --- a/test/JDBC/input/babel_613.sql +++ b/test/JDBC/input/babel_613.sql @@ -60,8 +60,12 @@ select coalesce(a, b) from t1; go -- test Union All -select a from t1 Union All -select b from t1; +select * from + ( + select a as col from t1 Union All + select b as col from t1 + ) dummy +order by col go -- test overflow from multiplication of columns diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index 02205e5dbb..2d3cbf2f41 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -28,18 +28,7 @@ ignore#!#BABEL-3512 ignore#!#BABEL-3592 ignore#!#BABEL-4294-vu-verify -# Group 4: Incorrect precision BABEL-4396 -ignore#!#BABEL-3943 -ignore#!#BABEL-785 -ignore#!#TestDecimal-vu-verify -ignore#!#TestNumeric-vu-verify -ignore#!#babel_613 -ignore#!#babel_datatype -ignore#!#babel_isnull -ignore#!#BABEL-3006 -ignore#!#BABEL-3147-vu-verify - -# Group 5: Need ORDER BY +# Group 4: Need ORDER BY ignore#!#BABEL-2514 ignore#!#BABEL-2998 ignore#!#BABEL-328-vu-verify From 72eeb5dd6aa86abb7c6581c7a2ab3d6b80437948 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Wed, 25 Oct 2023 09:56:21 +0530 Subject: [PATCH 14/34] Handle more cases to hold interrupts --- contrib/babelfishpg_tds/src/backend/tds/err_handler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/babelfishpg_tds/src/backend/tds/err_handler.c b/contrib/babelfishpg_tds/src/backend/tds/err_handler.c index fd48459422..29165031c7 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/err_handler.c +++ b/contrib/babelfishpg_tds/src/backend/tds/err_handler.c @@ -309,7 +309,9 @@ emit_tds_log(ErrorData *edata) if (edata->elevel < ERROR) { + HOLD_INTERRUPTS(); elog(DEBUG5, "suppressing informational client message < ERROR"); + RESUME_INTERRUPTS(); /* reset the flag */ tds_disable_error_log_hook = false; From 09c468074c6c962b4ce84afe8783eb5187dce00e Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 26 Oct 2023 10:28:17 +0530 Subject: [PATCH 15/34] Additional test cases --- .../src/backend/tds/tdsresponse.c | 20 +- test/JDBC/expected/BABEL-4424.out | 190 ++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 78 +++++++ 3 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 test/JDBC/expected/BABEL-4424.out create mode 100644 test/JDBC/input/BABEL-4424.sql diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 6a73014b59..7db95fe85c 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -408,12 +408,12 @@ static int32 resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) { ListCell *lc; - uint8_t max_precision = 0, + int32 max_precision = 0, max_scale = 0, precision = 0, scale = 0, - integralDigitCount = 0; - int32 typmod = -1, + integralDigitCount = 0, + typmod = -1, result_typmod = -1; List *planlist = NIL; if (IsA(plan, Append)) @@ -428,8 +428,14 @@ resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) Assert(planlist != NIL); foreach(lc, ((Append *) plan)->appendplans) { - Plan *outerplan = (Plan *) lfirst(lc); - TargetEntry *tle = get_tle_by_resno(outerplan->targetlist, attno); + TargetEntry *tle; + Plan *outerplan = (Plan *) lfirst(lc); + + /* if outerplan is SubqueryScan then use actual subplan */ + if (IsA(outerplan, SubqueryScan)) + outerplan = ((SubqueryScan *)outerplan)->subplan; + + tle = get_tle_by_resno(outerplan->targetlist, attno); if (IsA(tle->expr, Var)) { Var *var = (Var *)tle->expr; @@ -467,6 +473,10 @@ resolve_numeric_typmod_outer_var(Plan *plan, AttrNumber attno) else outerplan = outerPlan(plan); + /* if outerplan is SubqueryScan then use actual subplan */ + if (IsA(outerplan, SubqueryScan)) + outerplan = ((SubqueryScan *)outerplan)->subplan; + /* outerplan must not be NULL */ Assert(outerplan); tle = get_tle_by_resno(outerplan->targetlist, attno); diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out new file mode 100644 index 0000000000..4f242ed4f1 --- /dev/null +++ b/test/JDBC/expected/BABEL-4424.out @@ -0,0 +1,190 @@ +create table babel_4359_t1 (a numeric(6,4), b numeric(6,3), c numeric); +go + +insert into babel_4359_t1 values (4, 16, 1111); +insert into babel_4359_t1 values (10.1234, 10.123, 222222); +insert into babel_4359_t1 values (1.2, 6, 33333333333333333); +insert into babel_4359_t1 values (NULL, 101.123, 444444444444444444); +insert into babel_4359_t1 values (10.123, NULL, 444444444444444444.44); +insert into babel_4359_t1 values (10.12, 10.1234, NULL); +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select * from + ( + select a as col from babel_4359_t1 Union All + select b as col from babel_4359_t1 + ) dummy +order by col +go +~~START~~ +numeric + + +1.2000 +4.0000 +6.0000 +10.1200 +10.1230 +10.1230 +10.1230 +10.1234 +16.0000 +101.1230 +~~END~~ + + +select * from + ( + select a as col from babel_4359_t1 union all + select b as col from babel_4359_t1 union all + select c as col from babel_4359_t1 + ) dummy +order by col +go +~~START~~ +numeric + + + +1.2000 +4.0000 +6.0000 +10.1200 +10.1230 +10.1230 +10.1230 +10.1234 +16.0000 +101.1230 +1111.0000 +222222.0000 +33333333333333333.0000 +444444444444444444.0000 +444444444444444444.0000 +~~END~~ + + + +select * from + ( + select avg(a) as col from t1 union all + select avg(b) as col from t1 + ) dummy +order by col +select * from + ( + select a + b as col from babel_4359_t1 Union All + select b + c as col from babel_4359_t1 + ) dummy +order by col +go +~~START~~ +numeric +5.107800 +33.311500 +~~END~~ + +~~START~~ +numeric + + + + +7.2000 +20.0000 +20.2430 +20.2464 +1127.0000 +222232.1230 +33333333333333339.0000 +444444444444444545.1230 +~~END~~ + + +select * from + ( + (select a as col from babel_4359_t1 order by a) union all + (select b as col from babel_4359_t1 order by a) union all + (select c as col from babel_4359_t1 order by a) + ) dummy +order by col +go +~~START~~ +numeric + + + +1.2000 +4.0000 +6.0000 +10.1200 +10.1230 +10.1230 +10.1230 +10.1234 +16.0000 +101.1230 +1111.0000 +222222.0000 +33333333333333333.0000 +444444444444444444.0000 +444444444444444444.0000 +~~END~~ + + + +select * from + ( + (select min(a) as col from babel_4359_t1 ) union all + (select min(b) as col from babel_4359_t1 ) union all + (select min(c) as col from babel_4359_t1 ) + ) dummy +order by col +select min(col) from + ( + (select min(a) as col from babel_4359_t1 ) union all + (select min(b) as col from babel_4359_t1 ) union all + (select min(c) as col from babel_4359_t1 ) + ) dummy +go +~~START~~ +numeric +1.2000 +6.0000 +1111.0000 +~~END~~ + +~~START~~ +numeric +1.2000 +~~END~~ + + +select * from + ( + select max(a + b) as col from babel_4359_t1 Union All + select min(b + c) as col from babel_4359_t1 + ) dummy +order by col +go +~~START~~ +numeric +20.2464 +1127.0000 +~~END~~ + + +drop table babel_4359_t1 +go diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql new file mode 100644 index 0000000000..613017c307 --- /dev/null +++ b/test/JDBC/input/BABEL-4424.sql @@ -0,0 +1,78 @@ +create table babel_4359_t1 (a numeric(6,4), b numeric(6,3), c numeric); +go + +insert into babel_4359_t1 values (4, 16, 1111); +insert into babel_4359_t1 values (10.1234, 10.123, 222222); +insert into babel_4359_t1 values (1.2, 6, 33333333333333333); +insert into babel_4359_t1 values (NULL, 101.123, 444444444444444444); +insert into babel_4359_t1 values (10.123, NULL, 444444444444444444.44); +insert into babel_4359_t1 values (10.12, 10.1234, NULL); +go + +select * from + ( + select a as col from babel_4359_t1 Union All + select b as col from babel_4359_t1 + ) dummy +order by col +go + +select * from + ( + select a as col from babel_4359_t1 union all + select b as col from babel_4359_t1 union all + select c as col from babel_4359_t1 + ) dummy +order by col +go + +select * from + ( + select avg(a) as col from t1 union all + select avg(b) as col from t1 + ) dummy +order by col + +select * from + ( + select a + b as col from babel_4359_t1 Union All + select b + c as col from babel_4359_t1 + ) dummy +order by col +go + +select * from + ( + (select a as col from babel_4359_t1 order by a) union all + (select b as col from babel_4359_t1 order by a) union all + (select c as col from babel_4359_t1 order by a) + ) dummy +order by col +go + +select * from + ( + (select min(a) as col from babel_4359_t1 ) union all + (select min(b) as col from babel_4359_t1 ) union all + (select min(c) as col from babel_4359_t1 ) + ) dummy +order by col + +select min(col) from + ( + (select min(a) as col from babel_4359_t1 ) union all + (select min(b) as col from babel_4359_t1 ) union all + (select min(c) as col from babel_4359_t1 ) + ) dummy +go + +select * from + ( + select max(a + b) as col from babel_4359_t1 Union All + select min(b + c) as col from babel_4359_t1 + ) dummy +order by col +go + +drop table babel_4359_t1 +go \ No newline at end of file From c4804461a1628db05e231323966660539f33f230 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 26 Oct 2023 11:09:55 +0530 Subject: [PATCH 16/34] Additional test cases for mergeappend node --- test/JDBC/expected/BABEL-4424.out | 41 +++++++++++++++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 26 ++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index 4f242ed4f1..c1c6132f91 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -186,5 +186,46 @@ numeric ~~END~~ +create table events (event_id numeric(6,3) primary key); +create table other_events (event_id numeric(6,5) primary key); +create table other_events_2 (event_id numeric); +go + +insert into events values (100.123), (10.12); +insert into other_events values (1.123456); +insert into other_events_2 values (111111111111111111), (NULL); +go +~~ROW COUNT: 2~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 2~~ + + +-- merge append node +select event_id + from ((select event_id from events order by event_id) + union all + (select event_id from other_events order by event_id) + union all + (select event_id from other_events_2 order by event_id)) ss +order by event_id; +go +~~START~~ +numeric + +1.12346 +10.12000 +100.12300 +111111111111111111.00000 +~~END~~ + + drop table babel_4359_t1 go +drop table events; +go +drop table other_events; +go +drop table other_events_2; +go diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index 613017c307..8d289e0e33 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -74,5 +74,31 @@ select * from order by col go +create table events (event_id numeric(6,3) primary key); +create table other_events (event_id numeric(6,5) primary key); +create table other_events_2 (event_id numeric); +go + +insert into events values (100.123), (10.12); +insert into other_events values (1.123456); +insert into other_events_2 values (111111111111111111), (NULL); +go + +-- merge append node +select event_id + from ((select event_id from events order by event_id) + union all + (select event_id from other_events order by event_id) + union all + (select event_id from other_events_2 order by event_id)) ss +order by event_id; +go + drop table babel_4359_t1 +go +drop table events; +go +drop table other_events; +go +drop table other_events_2; go \ No newline at end of file From 69f165ee1abfbe7db7e2dace2408cee106d820ae Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 26 Oct 2023 12:24:44 +0530 Subject: [PATCH 17/34] Additional test cases for mergeappend node --- test/JDBC/expected/BABEL-4424.out | 8 ++++---- test/JDBC/input/BABEL-4424.sql | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index c1c6132f91..f1c796cb6c 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -79,8 +79,8 @@ numeric select * from ( - select avg(a) as col from t1 union all - select avg(b) as col from t1 + select avg(a) as col from babel_4359_t1 union all + select avg(b) as col from babel_4359_t1 ) dummy order by col select * from @@ -92,8 +92,8 @@ order by col go ~~START~~ numeric -5.107800 -33.311500 +7.113280 +28.673800 ~~END~~ ~~START~~ diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index 8d289e0e33..fef107b127 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -28,8 +28,8 @@ go select * from ( - select avg(a) as col from t1 union all - select avg(b) as col from t1 + select avg(a) as col from babel_4359_t1 union all + select avg(b) as col from babel_4359_t1 ) dummy order by col From 6432276123229df16a3b1e2448fb71af17d566f2 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 31 Oct 2023 19:03:18 +0530 Subject: [PATCH 18/34] Another fixes --- .../src/backend/tds/tdsresponse.c | 17 +- contrib/babelfishpg_tsql/src/hooks.c | 3 +- test/JDBC/expected/BABEL-4424.out | 164 ++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 108 ++++++++++++ 4 files changed, 289 insertions(+), 3 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 7db95fe85c..6c104deacd 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -452,6 +452,15 @@ resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) integralDigitCount = Max(precision - scale, max_precision - max_scale); max_scale = Max(max_scale, scale); max_precision = integralDigitCount + max_scale; + /* + * If max_precision is more than TDS_MAX_NUM_PRECISION then adjust precision + * to TDS_MAX_NUM_PRECISION at the cost of scale. + */ + if (max_precision > TDS_MAX_NUM_PRECISION) + { + max_scale = Max(0, scale - (max_precision - TDS_MAX_NUM_PRECISION)); + max_precision = TDS_MAX_NUM_PRECISION; + } result_typmod = ((max_precision << 16) | max_scale) + VARHDRSZ; } /* If max_precision is still default then use tds specific defaults */ @@ -641,10 +650,13 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) scale = Min(precision, TDS_MAX_NUM_PRECISION) - integralDigitCount; /* - * precisionn adjustment to TDS_MAX_NUM_PRECISION + * precision adjustment to TDS_MAX_NUM_PRECISION */ if (precision > TDS_MAX_NUM_PRECISION) + { + scale = Max(0, scale - (precision - TDS_MAX_NUM_PRECISION)); precision = TDS_MAX_NUM_PRECISION; + } break; case NUMERIC_MUL_OID: scale = scale1 + scale2; @@ -656,7 +668,10 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) * function */ if (has_aggregate_operand && precision > TDS_MAX_NUM_PRECISION) + { + scale = Max(0, scale - (precision - TDS_MAX_NUM_PRECISION)); precision = TDS_MAX_NUM_PRECISION; + } break; case NUMERIC_DIV_OID: scale = Max(6, scale1 + precision2 + 1); diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 93a6ee1ff3..4b8f1e2a47 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -2902,8 +2902,7 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume if (sql_dialect != SQL_DIALECT_TSQL) return false; - total_digit_count = (dscale == 0) ? (weight * numeric_base) : - ((weight + 1) * numeric_base); + total_digit_count = weight * numeric_base; /* * calculating exact #digits in the first partially filled numeric block, diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index f1c796cb6c..ed14281f46 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -229,3 +229,167 @@ drop table other_events; go drop table other_events_2; go + +create table babel_4424_t1 (a numeric(38,0)); +go + +create table babel_4424_t2 (a numeric(6,4)); +go + +insert into babel_4424_t1 values (9999999999999999999999999999999999999); +insert into babel_4424_t2 values (99.9999); +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select * from + ( + select a col from babel_4424_t1 + union all + select a col from babel_4424_t2 + )dummy +order by col; +go +~~START~~ +numeric +99 +9999999999999999999999999999999999999 +~~END~~ + + +select * from + ( select a + a from babel_4424_t1 ) dummy +go +~~START~~ +numeric +19999999999999999999999999999999999998 +~~END~~ + + +select * from + ( + select a col from babel_4424_t1 + union all + select a + a col from babel_4424_t1 + )dummy +order by col; +go +~~START~~ +numeric +9999999999999999999999999999999999999 +19999999999999999999999999999999999998 +~~END~~ + + +select * from + ( + select a + a col from babel_4424_t1 + union all + select a col from babel_4424_t2 + )dummy +order by col; +go +~~START~~ +numeric +99 +19999999999999999999999999999999999998 +~~END~~ + + +create table babel_4424_t3 (a numeric(37,1)); +GO + +create table babel_4424_t4 (a numeric(38,1)); +GO + +insert into babel_4424_t3 values (999999999999999999999999999999999999.9); +go +~~ROW COUNT: 1~~ + + +insert into babel_4424_t4 values (9999999999999999999999999999999999999.9); +go +~~ROW COUNT: 1~~ + + +select * from (select a + a from babel_4424_t3) dummy; +go +~~START~~ +numeric +1999999999999999999999999999999999999.8 +~~END~~ + + +select * from + ( + select a col from babel_4424_t3 + union all + select a col from babel_4424_t2 + ) dummy +order by col; +GO +~~START~~ +numeric +99.99 +999999999999999999999999999999999999.90 +~~END~~ + + +select * from + ( + select a col from babel_4424_t3 + union all + select a col from babel_4424_t4 + ) dummy +order by col; +GO +~~START~~ +numeric +999999999999999999999999999999999999.9 +9999999999999999999999999999999999999.9 +~~END~~ + + +DROP TABLE babel_4424_t1; +go +DROP TABLE babel_4424_t2; +go +DROP TABLE babel_4424_t3; +go +DROP TABLE babel_4424_t4; +go + +create table babel_4424_t1 (a numeric(38,0) primary key); +go + +create table babel_4424_t2(a numeric(6,3) primary key); +go + +insert into babel_4424_t1 values (99999999999999999999999999999999999999); +insert into babel_4424_t2 values (99.9999); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +-- index scan + append +select * from + ( + select a col from babel_4424_t1 where a = 1 + union all + select a col from babel_4424_t2 where a = 1 + ) dummy +order by col; +go +~~START~~ +numeric +~~END~~ + + +DROP TABLE babel_4424_t1; +go +DROP TABLE babel_4424_t2; +go diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index fef107b127..3dad73f8bf 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -101,4 +101,112 @@ go drop table other_events; go drop table other_events_2; +go + +create table babel_4424_t1 (a numeric(38,0)); +go + +create table babel_4424_t2 (a numeric(6,4)); +go + +insert into babel_4424_t1 values (9999999999999999999999999999999999999); +insert into babel_4424_t2 values (99.9999); +go + +select * from + ( + select a col from babel_4424_t1 + union all + select a col from babel_4424_t2 + )dummy +order by col; +go + +select * from + ( select a + a from babel_4424_t1 ) dummy +go + +select * from + ( + select a col from babel_4424_t1 + union all + select a + a col from babel_4424_t1 + )dummy +order by col; +go + +select * from + ( + select a + a col from babel_4424_t1 + union all + select a col from babel_4424_t2 + )dummy +order by col; +go + +create table babel_4424_t3 (a numeric(37,1)); +GO + +create table babel_4424_t4 (a numeric(38,1)); +GO + +insert into babel_4424_t3 values (999999999999999999999999999999999999.9); +go + +insert into babel_4424_t4 values (9999999999999999999999999999999999999.9); +go + +select * from (select a + a from babel_4424_t3) dummy; +go + +select * from + ( + select a col from babel_4424_t3 + union all + select a col from babel_4424_t2 + ) dummy +order by col; +GO + +select * from + ( + select a col from babel_4424_t3 + union all + select a col from babel_4424_t4 + ) dummy +order by col; +GO + +DROP TABLE babel_4424_t1; +go +DROP TABLE babel_4424_t2; +go +DROP TABLE babel_4424_t3; +go +DROP TABLE babel_4424_t4; +go + +create table babel_4424_t1 (a numeric(38,0) primary key); +go + +create table babel_4424_t2(a numeric(6,3) primary key); +go + +insert into babel_4424_t1 values (99999999999999999999999999999999999999); +insert into babel_4424_t2 values (99.9999); +GO + +-- index scan + append +select * from + ( + select a col from babel_4424_t1 where a = 1 + union all + select a col from babel_4424_t2 where a = 1 + ) dummy +order by col; +go + +DROP TABLE babel_4424_t1; +go +DROP TABLE babel_4424_t2; go \ No newline at end of file From 459fe61be3fe5b005292a520a8dc7e83ea8992b4 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 2 Nov 2023 17:05:21 +0530 Subject: [PATCH 19/34] Fix new test cases --- contrib/babelfishpg_tsql/src/hooks.c | 9 ++---- test/JDBC/expected/BABEL-4424.out | 41 ++++++++++++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 26 ++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 4b8f1e2a47..38a9b785e0 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -2930,13 +2930,10 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume } /* - * calculating exact #digits in last block if decimal point exists If - * dscale is an exact multiple of numeric_base, last block is not - * partially filled, then, ignore as those digits are already added to - * total_digit_count Else, add the remainder digits + * Add dscale or display scale, the nominal precision expressed as number + * of digits after the decimal point. */ - if (dscale > 0) - total_digit_count += (dscale % numeric_base); + total_digit_count += dscale; return (total_digit_count > TDS_NUMERIC_MAX_PRECISION); } diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index ed14281f46..6c7f2e2644 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -352,6 +352,43 @@ numeric ~~END~~ +create table babel_4424_t5 (a numeric(38, 37)); +GO + +create table babel_4424_t6 (a numeric(10, 10)); +GO + +insert into babel_4424_t5 values (9.99999999999999999999999999999999999); +insert into babel_4424_t6 values (0.9999999999); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select * from ( select a +a from babel_4424_t5) dummy; +GO +~~START~~ +numeric +19.999999999999999999999999999999999980 +~~END~~ + + +select * from + ( + select a + a col from babel_4424_t5 + union all + select a + a col from babel_4424_t6 + ) dummy +order by col; +GO +~~START~~ +numeric +1.999999999800000000000000000000000000 +19.999999999999999999999999999999999980 +~~END~~ + + DROP TABLE babel_4424_t1; go DROP TABLE babel_4424_t2; @@ -360,6 +397,10 @@ DROP TABLE babel_4424_t3; go DROP TABLE babel_4424_t4; go +DROP TABLE babel_4424_t5; +go +DROP TABLE babel_4424_t6; +go create table babel_4424_t1 (a numeric(38,0) primary key); go diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index 3dad73f8bf..ed9818672f 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -177,6 +177,28 @@ select * from order by col; GO +create table babel_4424_t5 (a numeric(38, 37)); +GO + +create table babel_4424_t6 (a numeric(10, 10)); +GO + +insert into babel_4424_t5 values (9.99999999999999999999999999999999999); +insert into babel_4424_t6 values (0.9999999999); +GO + +select * from ( select a +a from babel_4424_t5) dummy; +GO + +select * from + ( + select a + a col from babel_4424_t5 + union all + select a + a col from babel_4424_t6 + ) dummy +order by col; +GO + DROP TABLE babel_4424_t1; go DROP TABLE babel_4424_t2; @@ -185,6 +207,10 @@ DROP TABLE babel_4424_t3; go DROP TABLE babel_4424_t4; go +DROP TABLE babel_4424_t5; +go +DROP TABLE babel_4424_t6; +go create table babel_4424_t1 (a numeric(38,0) primary key); go From 61b78cffdf1b9b0e2bb0d8818d843792d5d97f85 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Fri, 3 Nov 2023 17:38:38 +0530 Subject: [PATCH 20/34] Test cases fixes --- .../src/backend/tds/tdsresponse.c | 3 --- contrib/babelfishpg_tsql/src/hooks.c | 24 +++++++++++++------ test/JDBC/expected/BABEL-4424.out | 21 +++++++++++----- test/JDBC/input/BABEL-4424.sql | 9 ++++--- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 6c104deacd..021b176183 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -653,10 +653,7 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) * precision adjustment to TDS_MAX_NUM_PRECISION */ if (precision > TDS_MAX_NUM_PRECISION) - { - scale = Max(0, scale - (precision - TDS_MAX_NUM_PRECISION)); precision = TDS_MAX_NUM_PRECISION; - } break; case NUMERIC_MUL_OID: scale = scale1 + scale2; diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 38a9b785e0..e82bccb7e5 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -2898,10 +2898,22 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume { int partially_filled_numeric_block = 0; int total_digit_count = 0; + static const int32 scales[DEC_DIGITS] = { + 1000, + 100, + 10, + 1, + }; if (sql_dialect != SQL_DIALECT_TSQL) return false; + if (weight < 0) + { + /* weight < 0 means the integral part of the number is 0 */ + total_digit_count = 1 + dscale; + return (total_digit_count > TDS_NUMERIC_MAX_PRECISION); + } total_digit_count = weight * numeric_base; /* @@ -2915,18 +2927,16 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume /* * check if the first numeric block is partially filled If yes, add those - * digit count Else if fully filled, Ignore as those digits are already + * digit count Else if fully filled, Ignore as those digits might be already * added to total_digit_count */ - if (partially_filled_numeric_block < pow(10, numeric_base - 1)) + for (int i = 0; i < DEC_DIGITS; i++) { - if (partially_filled_numeric_block > 0) + if (partially_filled_numeric_block >= scales[i]) { - int log_10 = (int) log10(partially_filled_numeric_block); // keep compiler happy - total_digit_count += log_10 + 1; + total_digit_count += (4 - i); + break; } - else - total_digit_count += 1; } /* diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index 6c7f2e2644..8fa3786fb7 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -366,26 +366,35 @@ GO ~~ROW COUNT: 1~~ -select * from ( select a +a from babel_4424_t5) dummy; +select * from ( select a + a from babel_4424_t5) dummy; GO ~~START~~ numeric -19.999999999999999999999999999999999980 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select * from ( select a + a from babel_4424_t6) dummy; +GO +~~START~~ +numeric +1.9999999998 ~~END~~ select * from ( - select a + a col from babel_4424_t5 + select a col from babel_4424_t5 union all - select a + a col from babel_4424_t6 + select a col from babel_4424_t6 ) dummy order by col; GO ~~START~~ numeric -1.999999999800000000000000000000000000 -19.999999999999999999999999999999999980 +0.9999999999000000000000000000000000000 +9.9999999999999999999999999999999999900 ~~END~~ diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index ed9818672f..eccf17ee06 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -187,14 +187,17 @@ insert into babel_4424_t5 values (9.99999999999999999999999999999999999); insert into babel_4424_t6 values (0.9999999999); GO -select * from ( select a +a from babel_4424_t5) dummy; +select * from ( select a + a from babel_4424_t5) dummy; +GO + +select * from ( select a + a from babel_4424_t6) dummy; GO select * from ( - select a + a col from babel_4424_t5 + select a col from babel_4424_t5 union all - select a + a col from babel_4424_t6 + select a col from babel_4424_t6 ) dummy order by col; GO From b1d32877826d77264c93b25e11ce26dba1592749 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 7 Nov 2023 09:48:08 +0530 Subject: [PATCH 21/34] Fixed errors --- contrib/babelfishpg_tsql/src/hooks.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 90b21d2d71..6e3ff655c5 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -2906,12 +2906,6 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume { int partially_filled_numeric_block = 0; int total_digit_count = 0; - static const int32 scales[DEC_DIGITS] = { - 1000, - 100, - 10, - 1, - }; if (sql_dialect != SQL_DIALECT_TSQL) return false; @@ -2938,13 +2932,15 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume * digit count Else if fully filled, Ignore as those digits might be already * added to total_digit_count */ - for (int i = 0; i < DEC_DIGITS; i++) + if (partially_filled_numeric_block < pow(10, numeric_base - 1)) { - if (partially_filled_numeric_block >= scales[i]) + if (partially_filled_numeric_block > 0) { - total_digit_count += (4 - i); - break; + int log_10 = (int) log10(partially_filled_numeric_block); // keep compiler happy + total_digit_count += log_10 + 1; } + else + total_digit_count += 1; } /* From 4a47172d33005d2a329488748a21896791e76b3e Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 7 Nov 2023 13:52:18 +0530 Subject: [PATCH 22/34] Fixed test cases --- contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 021b176183..2121211779 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -665,10 +665,7 @@ resolve_numeric_typmod_from_exp(Plan *plan, Node *expr) * function */ if (has_aggregate_operand && precision > TDS_MAX_NUM_PRECISION) - { - scale = Max(0, scale - (precision - TDS_MAX_NUM_PRECISION)); precision = TDS_MAX_NUM_PRECISION; - } break; case NUMERIC_DIV_OID: scale = Max(6, scale1 + precision2 + 1); From 0ac1f178af116352650c94bec945f83cd759937e Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Tue, 7 Nov 2023 17:24:57 +0530 Subject: [PATCH 23/34] Fixed test cases --- contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 2121211779..fe32e1a38f 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -458,7 +458,7 @@ resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) */ if (max_precision > TDS_MAX_NUM_PRECISION) { - max_scale = Max(0, scale - (max_precision - TDS_MAX_NUM_PRECISION)); + max_scale = Max(0, max_scale - (max_precision - TDS_MAX_NUM_PRECISION)); max_precision = TDS_MAX_NUM_PRECISION; } result_typmod = ((max_precision << 16) | max_scale) + VARHDRSZ; From 86333358050d1fbef74e0924e85cdb61160ec9e1 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Wed, 8 Nov 2023 16:31:38 +0530 Subject: [PATCH 24/34] Donot override typmod --- contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index fe32e1a38f..80e3b7a546 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -443,8 +443,15 @@ resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) { typmod = resolve_numeric_typmod_outer_var(outerplan, var->varattno); } + else + { + typmod = resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); + } + } + else + { + typmod = resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); } - typmod = resolve_numeric_typmod_from_exp(outerplan, (Node *)tle->expr); if (typmod == -1) continue; scale = (typmod - VARHDRSZ) & 0xffff; From ce3e193ac8056dcfa9bfe10dcfaeff34beef2b80 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Wed, 8 Nov 2023 20:01:57 +0530 Subject: [PATCH 25/34] Additional test cases --- test/JDBC/expected/BABEL-4424.out | 280 ++++++++++++++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 115 +++++++++++- 2 files changed, 394 insertions(+), 1 deletion(-) diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index 8fa3786fb7..a3cf1aac85 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -443,3 +443,283 @@ DROP TABLE babel_4424_t1; go DROP TABLE babel_4424_t2; go + + +create table babel_4424_t1 (n3_0 numeric(3,0), n3_1 numeric(3,1), n6_0 numeric(6,0), n10_0 numeric(10,0), n10_9 numeric(10, 9), + n15_0 numeric(15,0), n16_15 numeric(16,15), n20_2 numeric(20,2), n25_5 numeric(25,0), n30_10 numeric(30, 10), + n30_29 numeric(30,29), n38_37 numeric(38,37)); +insert into babel_4424_t1 (n3_0) values (999); +insert into babel_4424_t1 (n3_1) values (99.9); +insert into babel_4424_t1 (n6_0) values (999999); +insert into babel_4424_t1 (n10_0) values (9999999999); +insert into babel_4424_t1 (n10_9) values (9.999999999); +insert into babel_4424_t1 (n15_0) values (999999999999999); +insert into babel_4424_t1 (n16_15) values (9.999999999999999); +insert into babel_4424_t1 (n20_2) values (999999999999999999.99); +insert into babel_4424_t1 (n25_5) values (99999999999999999999.99999); +insert into babel_4424_t1 (n30_10) values (99999999999999999999.9999999999); +insert into babel_4424_t1 (n30_29) values (9.99999999999999999999999999999); +insert into babel_4424_t1 (n38_37) values (9.9999999999999999999999999999999999999); +insert into babel_4424_t1 (n3_0, n3_1, n6_0, n10_0, n10_9, n15_0, n16_15, n20_2, n25_5, n30_10, n30_29, n38_37) +values (999, 99.9, 999999, 9999999999, 9.999999999, 999999999999999, 9.999999999999999, 999999999999999999.99, +99999999999999999999.99999, 99999999999999999999.9999999999, 9.99999999999999999999999999999, 9.9999999999999999999999999999999999999); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +select n38_37 + 100 from babel_4424_t1 where n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select n38_37 + n38_37 from babel_4424_t1 where n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select sum(n38_37) from babel_4424_t1 where n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select avg(n38_37) from babel_4424_t1 where n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select n30_29 * 100 from babel_4424_t1 where n30_29 is not null; +GO +~~START~~ +numeric +999.99999999999999999999999999900 +999.99999999999999999999999999900 +~~END~~ + + +select n30_29 + n30_29 from babel_4424_t1 where n30_29 is not null; +GO +~~START~~ +numeric +19.99999999999999999999999999998 +19.99999999999999999999999999998 +~~END~~ + + +select n30_29 + n38_37 from babel_4424_t1 where n30_29 is not null and n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select n3_0 * n3_0 from babel_4424_t1 where n3_0 is not null; +GO +~~START~~ +numeric +998001 +998001 +~~END~~ + + +select n3_0 * n3_1 from babel_4424_t1 where n3_0 is not null and n3_1 is not null; +GO +~~START~~ +numeric +99800.1 +~~END~~ + + +select n3_0 + n6_0 from babel_4424_t1 where n3_0 is not null and n6_0 is not null; +GO +~~START~~ +numeric +1000998 +~~END~~ + + +select n6_0 + n10_9 from babel_4424_t1 where n6_0 is not null and n10_9 is not null; +GO +~~START~~ +numeric +1000008.999999999 +~~END~~ + + +select n15_0 * n15_0 from babel_4424_t1 where n15_0 is not null; +GO +~~START~~ +numeric +999999999999998000000000000001 +999999999999998000000000000001 +~~END~~ + + +select n15_0 + n38_37 from babel_4424_t1 where n15_0 is not null and n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select n15_0 + n16_15 from babel_4424_t1 where n15_0 is not null and n16_15 is not null; +GO +~~START~~ +numeric +1000000000000008.999999999999999 +~~END~~ + + +select avg(n16_15) from babel_4424_t1 where n16_15 is not null; +GO +~~START~~ +numeric +9.999999999999999 +~~END~~ + + +select n16_15 * n16_15 from babel_4424_t1 where n16_15 is not null; +GO +~~START~~ +numeric +99.999999999999980000000000000001 +99.999999999999980000000000000001 +~~END~~ + + +select n15_0 + n16_15 + n30_10 from babel_4424_t1 where n15_0 is not null and n16_15 is not null and n30_10 is not null; +GO +~~START~~ +numeric +100001000000000000008.999999999899999 +~~END~~ + + +select n20_2 + n38_37 from babel_4424_t1 where n20_2 is not null and n38_37 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select n25_5 + n30_10 from babel_4424_t1 where n25_5 is not null and n30_10 is not null; +GO +~~START~~ +numeric +199999999999999999999.9999999999 +~~END~~ + + +select n30_29 + n30_10 from babel_4424_t1 where n30_29 is not null and n30_10 is not null; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + +select * from +( + select n3_0 col from babel_4424_t1 where n3_0 is not null + union all + select n3_1 col from babel_4424_t1 where n3_1 is not null + union all + select n6_0 col from babel_4424_t1 where n6_0 is not null + union all + select n10_0 col from babel_4424_t1 where n10_0 is not null + union all + select n10_9 col from babel_4424_t1 where n10_9 is not null + union all + select n15_0 col from babel_4424_t1 where n15_0 is not null + union all + select n16_15 col from babel_4424_t1 where n16_15 is not null + union all + select n20_2 col from babel_4424_t1 where n20_2 is not null + union all + select n25_5 col from babel_4424_t1 where n25_5 is not null + union all + select n30_10 col from babel_4424_t1 where n30_10 is not null + union all + select n30_29 col from babel_4424_t1 where n30_29 is not null + union all + select n38_37 col from babel_4424_t1 where n38_37 is not null +) dummy +order by col; +GO +~~START~~ +numeric +9.9999999990000 +9.9999999990000 +9.9999999999999 +9.9999999999999 +9.9999999999999 +9.9999999999999 +9.9999999999999 +9.9999999999999 +99.9000000000000 +99.9000000000000 +999.0000000000000 +999.0000000000000 +999999.0000000000000 +999999.0000000000000 +9999999999.0000000000000 +9999999999.0000000000000 +999999999999999.0000000000000 +999999999999999.0000000000000 +999999999999999999.9900000000000 +999999999999999999.9900000000000 +99999999999999999999.9999999999000 +99999999999999999999.9999999999000 +100000000000000000000.0000000000000 +100000000000000000000.0000000000000 +~~END~~ + + +DROP table babel_4424_t1; +GO diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index eccf17ee06..6633d93697 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -238,4 +238,117 @@ go DROP TABLE babel_4424_t1; go DROP TABLE babel_4424_t2; -go \ No newline at end of file +go + +create table babel_4424_t1 (n3_0 numeric(3,0), n3_1 numeric(3,1), n6_0 numeric(6,0), n10_0 numeric(10,0), n10_9 numeric(10, 9), + n15_0 numeric(15,0), n16_15 numeric(16,15), n20_2 numeric(20,2), n25_5 numeric(25,0), n30_10 numeric(30, 10), + n30_29 numeric(30,29), n38_37 numeric(38,37)); + +insert into babel_4424_t1 (n3_0) values (999); +insert into babel_4424_t1 (n3_1) values (99.9); +insert into babel_4424_t1 (n6_0) values (999999); +insert into babel_4424_t1 (n10_0) values (9999999999); +insert into babel_4424_t1 (n10_9) values (9.999999999); +insert into babel_4424_t1 (n15_0) values (999999999999999); +insert into babel_4424_t1 (n16_15) values (9.999999999999999); +insert into babel_4424_t1 (n20_2) values (999999999999999999.99); +insert into babel_4424_t1 (n25_5) values (99999999999999999999.99999); +insert into babel_4424_t1 (n30_10) values (99999999999999999999.9999999999); +insert into babel_4424_t1 (n30_29) values (9.99999999999999999999999999999); +insert into babel_4424_t1 (n38_37) values (9.9999999999999999999999999999999999999); +insert into babel_4424_t1 (n3_0, n3_1, n6_0, n10_0, n10_9, n15_0, n16_15, n20_2, n25_5, n30_10, n30_29, n38_37) +values (999, 99.9, 999999, 9999999999, 9.999999999, 999999999999999, 9.999999999999999, 999999999999999999.99, +99999999999999999999.99999, 99999999999999999999.9999999999, 9.99999999999999999999999999999, 9.9999999999999999999999999999999999999); +GO + +select n38_37 + 100 from babel_4424_t1 where n38_37 is not null; +GO + +select n38_37 + n38_37 from babel_4424_t1 where n38_37 is not null; +GO + +select sum(n38_37) from babel_4424_t1 where n38_37 is not null; +GO + +select avg(n38_37) from babel_4424_t1 where n38_37 is not null; +GO + +select n30_29 * 100 from babel_4424_t1 where n30_29 is not null; +GO + +select n30_29 + n30_29 from babel_4424_t1 where n30_29 is not null; +GO + +select n30_29 + n38_37 from babel_4424_t1 where n30_29 is not null and n38_37 is not null; +GO + +select n3_0 * n3_0 from babel_4424_t1 where n3_0 is not null; +GO + +select n3_0 * n3_1 from babel_4424_t1 where n3_0 is not null and n3_1 is not null; +GO + +select n3_0 + n6_0 from babel_4424_t1 where n3_0 is not null and n6_0 is not null; +GO + +select n6_0 + n10_9 from babel_4424_t1 where n6_0 is not null and n10_9 is not null; +GO + +select n15_0 * n15_0 from babel_4424_t1 where n15_0 is not null; +GO + +select n15_0 + n38_37 from babel_4424_t1 where n15_0 is not null and n38_37 is not null; +GO + +select n15_0 + n16_15 from babel_4424_t1 where n15_0 is not null and n16_15 is not null; +GO + +select avg(n16_15) from babel_4424_t1 where n16_15 is not null; +GO + +select n16_15 * n16_15 from babel_4424_t1 where n16_15 is not null; +GO + +select n15_0 + n16_15 + n30_10 from babel_4424_t1 where n15_0 is not null and n16_15 is not null and n30_10 is not null; +GO + +select n20_2 + n38_37 from babel_4424_t1 where n20_2 is not null and n38_37 is not null; +GO + +select n25_5 + n30_10 from babel_4424_t1 where n25_5 is not null and n30_10 is not null; +GO + +select n30_29 + n30_10 from babel_4424_t1 where n30_29 is not null and n30_10 is not null; +GO + +select * from +( + select n3_0 col from babel_4424_t1 where n3_0 is not null + union all + select n3_1 col from babel_4424_t1 where n3_1 is not null + union all + select n6_0 col from babel_4424_t1 where n6_0 is not null + union all + select n10_0 col from babel_4424_t1 where n10_0 is not null + union all + select n10_9 col from babel_4424_t1 where n10_9 is not null + union all + select n15_0 col from babel_4424_t1 where n15_0 is not null + union all + select n16_15 col from babel_4424_t1 where n16_15 is not null + union all + select n20_2 col from babel_4424_t1 where n20_2 is not null + union all + select n25_5 col from babel_4424_t1 where n25_5 is not null + union all + select n30_10 col from babel_4424_t1 where n30_10 is not null + union all + select n30_29 col from babel_4424_t1 where n30_29 is not null + union all + select n38_37 col from babel_4424_t1 where n38_37 is not null +) dummy +order by col; +GO + +DROP table babel_4424_t1; +GO \ No newline at end of file From 7a682e073e358b05a790fb9797f5ae08b3b6bc7e Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Fri, 10 Nov 2023 11:21:42 +0530 Subject: [PATCH 26/34] Addressed test cases --- .../src/backend/tds/tdsresponse.c | 2 +- .../babelfishpg_tds/src/backend/tds/tdsrpc.c | 2 +- test/JDBC/expected/BABEL-4424.out | 124 +++++++++++++++++- test/JDBC/input/BABEL-4424.sql | 25 ++++ 4 files changed, 150 insertions(+), 3 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 80e3b7a546..7100ba4dbd 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -426,7 +426,7 @@ resolve_numeric_typmod_from_append_or_mergeappend(Plan *plan, AttrNumber attno) } Assert(planlist != NIL); - foreach(lc, ((Append *) plan)->appendplans) + foreach(lc, planlist) { TargetEntry *tle; Plan *outerplan = (Plan *) lfirst(lc); diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index 9cd79c9ed5..363afd7fc8 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -2342,7 +2342,7 @@ SendCursorResponse(TDSRequestSP req) if (portal->strategy != PORTAL_MULTI_QUERY) { targetList = FetchStatementTargetList((Node *) plannedStmt); - } + } /* * If we are in aborted transaction state, we can't run diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index a3cf1aac85..553d524703 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -238,11 +238,17 @@ go insert into babel_4424_t1 values (9999999999999999999999999999999999999); insert into babel_4424_t2 values (99.9999); +insert into babel_4424_t1 values (1111111111111111111111111111111111111); +insert into babel_4424_t2 values (11.1111); go ~~ROW COUNT: 1~~ ~~ROW COUNT: 1~~ +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + select * from ( @@ -254,7 +260,9 @@ order by col; go ~~START~~ numeric +11 99 +1111111111111111111111111111111111111 9999999999999999999999999999999999999 ~~END~~ @@ -265,6 +273,7 @@ go ~~START~~ numeric 19999999999999999999999999999999999998 +2222222222222222222222222222222222222 ~~END~~ @@ -278,6 +287,8 @@ order by col; go ~~START~~ numeric +1111111111111111111111111111111111111 +2222222222222222222222222222222222222 9999999999999999999999999999999999999 19999999999999999999999999999999999998 ~~END~~ @@ -293,7 +304,9 @@ order by col; go ~~START~~ numeric +11 99 +2222222222222222222222222222222222222 19999999999999999999999999999999999998 ~~END~~ @@ -305,20 +318,27 @@ create table babel_4424_t4 (a numeric(38,1)); GO insert into babel_4424_t3 values (999999999999999999999999999999999999.9); +insert into babel_4424_t3 values (111111111111111111111111111111111111.1); go ~~ROW COUNT: 1~~ +~~ROW COUNT: 1~~ + insert into babel_4424_t4 values (9999999999999999999999999999999999999.9); +insert into babel_4424_t4 values (1111111111111111111111111111111111111.1); go ~~ROW COUNT: 1~~ +~~ROW COUNT: 1~~ + select * from (select a + a from babel_4424_t3) dummy; go ~~START~~ numeric 1999999999999999999999999999999999999.8 +222222222222222222222222222222222222.2 ~~END~~ @@ -332,7 +352,9 @@ order by col; GO ~~START~~ numeric +11.11 99.99 +111111111111111111111111111111111111.10 999999999999999999999999999999999999.90 ~~END~~ @@ -347,7 +369,9 @@ order by col; GO ~~START~~ numeric +111111111111111111111111111111111111.1 999999999999999999999999999999999999.9 +1111111111111111111111111111111111111.1 9999999999999999999999999999999999999.9 ~~END~~ @@ -360,11 +384,17 @@ GO insert into babel_4424_t5 values (9.99999999999999999999999999999999999); insert into babel_4424_t6 values (0.9999999999); +insert into babel_4424_t5 values (1.11111111111111111111111111111111111); +insert into babel_4424_t6 values (0.1111111111); GO ~~ROW COUNT: 1~~ ~~ROW COUNT: 1~~ +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + select * from ( select a + a from babel_4424_t5) dummy; GO @@ -380,6 +410,7 @@ GO ~~START~~ numeric 1.9999999998 +0.2222222222 ~~END~~ @@ -393,7 +424,9 @@ order by col; GO ~~START~~ numeric +0.1111111111000000000000000000000000000 0.9999999999000000000000000000000000000 +1.1111111111111111111111111111111111100 9.9999999999999999999999999999999999900 ~~END~~ @@ -419,11 +452,17 @@ go insert into babel_4424_t1 values (99999999999999999999999999999999999999); insert into babel_4424_t2 values (99.9999); +insert into babel_4424_t1 values (11111111111111111111111111111111111111); +insert into babel_4424_t2 values (11.1111); GO ~~ROW COUNT: 1~~ ~~ROW COUNT: 1~~ +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + -- index scan + append select * from @@ -491,6 +530,49 @@ GO ~~ROW COUNT: 1~~ +insert into babel_4424_t1 (n3_0) values (111); +insert into babel_4424_t1 (n3_1) values (11.1); +insert into babel_4424_t1 (n6_0) values (111111); +insert into babel_4424_t1 (n10_0) values (1111111111); +insert into babel_4424_t1 (n10_9) values (1.111111111); +insert into babel_4424_t1 (n15_0) values (111111111111111); +insert into babel_4424_t1 (n16_15) values (1.111111111111111); +insert into babel_4424_t1 (n20_2) values (111111111111111111.11); +insert into babel_4424_t1 (n25_5) values (11111111111111111111.11111); +insert into babel_4424_t1 (n30_10) values (11111111111111111111.1111111111); +insert into babel_4424_t1 (n30_29) values (1.11111111111111111111111111111); +insert into babel_4424_t1 (n38_37) values (1.1111111111111111111111111111111111111); +insert into babel_4424_t1 (n3_0, n3_1, n6_0, n10_0, n10_9, n15_0, n16_15, n20_2, n25_5, n30_10, n30_29, n38_37) +values (111, 11.1, 111111, 1111111111, 1.111111111, 111111111111111, 1.111111111111111, 111111111111111111.11, +11111111111111111111.11111, 11111111111111111111.1111111111, 1.11111111111111111111111111111, 1.1111111111111111111111111111111111111); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + select n38_37 + 100 from babel_4424_t1 where n38_37 is not null; GO ~~START~~ @@ -533,6 +615,8 @@ GO numeric 999.99999999999999999999999999900 999.99999999999999999999999999900 +111.11111111111111111111111111100 +111.11111111111111111111111111100 ~~END~~ @@ -542,6 +626,8 @@ GO numeric 19.99999999999999999999999999998 19.99999999999999999999999999998 +2.22222222222222222222222222222 +2.22222222222222222222222222222 ~~END~~ @@ -560,6 +646,8 @@ GO numeric 998001 998001 +12321 +12321 ~~END~~ @@ -568,6 +656,7 @@ GO ~~START~~ numeric 99800.1 +1232.1 ~~END~~ @@ -576,6 +665,7 @@ GO ~~START~~ numeric 1000998 +111222 ~~END~~ @@ -584,6 +674,7 @@ GO ~~START~~ numeric 1000008.999999999 +111112.111111111 ~~END~~ @@ -593,6 +684,8 @@ GO numeric 999999999999998000000000000001 999999999999998000000000000001 +12345679012345654320987654321 +12345679012345654320987654321 ~~END~~ @@ -610,6 +703,7 @@ GO ~~START~~ numeric 1000000000000008.999999999999999 +111111111111112.111111111111111 ~~END~~ @@ -617,7 +711,7 @@ select avg(n16_15) from babel_4424_t1 where n16_15 is not null; GO ~~START~~ numeric -9.999999999999999 +5.555555555555555 ~~END~~ @@ -627,6 +721,8 @@ GO numeric 99.999999999999980000000000000001 99.999999999999980000000000000001 +1.234567901234567654320987654321 +1.234567901234567654320987654321 ~~END~~ @@ -635,6 +731,7 @@ GO ~~START~~ numeric 100001000000000000008.999999999899999 +11111222222222222223.222222222211111 ~~END~~ @@ -652,6 +749,7 @@ GO ~~START~~ numeric 199999999999999999999.9999999999 +22222222222222222222.1111111111 ~~END~~ @@ -694,6 +792,14 @@ order by col; GO ~~START~~ numeric +1.1111111110000 +1.1111111110000 +1.1111111111111 +1.1111111111111 +1.1111111111111 +1.1111111111111 +1.1111111111111 +1.1111111111111 9.9999999990000 9.9999999990000 9.9999999999999 @@ -702,18 +808,34 @@ numeric 9.9999999999999 9.9999999999999 9.9999999999999 +11.1000000000000 +11.1000000000000 99.9000000000000 99.9000000000000 +111.0000000000000 +111.0000000000000 999.0000000000000 999.0000000000000 +111111.0000000000000 +111111.0000000000000 999999.0000000000000 999999.0000000000000 +1111111111.0000000000000 +1111111111.0000000000000 9999999999.0000000000000 9999999999.0000000000000 +111111111111111.0000000000000 +111111111111111.0000000000000 999999999999999.0000000000000 999999999999999.0000000000000 +111111111111111111.1100000000000 +111111111111111111.1100000000000 999999999999999999.9900000000000 999999999999999999.9900000000000 +11111111111111111111.0000000000000 +11111111111111111111.0000000000000 +11111111111111111111.1111111111000 +11111111111111111111.1111111111000 99999999999999999999.9999999999000 99999999999999999999.9999999999000 100000000000000000000.0000000000000 diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index 6633d93697..eb5f91720a 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -111,6 +111,8 @@ go insert into babel_4424_t1 values (9999999999999999999999999999999999999); insert into babel_4424_t2 values (99.9999); +insert into babel_4424_t1 values (1111111111111111111111111111111111111); +insert into babel_4424_t2 values (11.1111); go select * from @@ -151,9 +153,11 @@ create table babel_4424_t4 (a numeric(38,1)); GO insert into babel_4424_t3 values (999999999999999999999999999999999999.9); +insert into babel_4424_t3 values (111111111111111111111111111111111111.1); go insert into babel_4424_t4 values (9999999999999999999999999999999999999.9); +insert into babel_4424_t4 values (1111111111111111111111111111111111111.1); go select * from (select a + a from babel_4424_t3) dummy; @@ -185,6 +189,8 @@ GO insert into babel_4424_t5 values (9.99999999999999999999999999999999999); insert into babel_4424_t6 values (0.9999999999); +insert into babel_4424_t5 values (1.11111111111111111111111111111111111); +insert into babel_4424_t6 values (0.1111111111); GO select * from ( select a + a from babel_4424_t5) dummy; @@ -223,6 +229,8 @@ go insert into babel_4424_t1 values (99999999999999999999999999999999999999); insert into babel_4424_t2 values (99.9999); +insert into babel_4424_t1 values (11111111111111111111111111111111111111); +insert into babel_4424_t2 values (11.1111); GO -- index scan + append @@ -261,6 +269,23 @@ values (999, 99.9, 999999, 9999999999, 9.999999999, 999999999999999, 9.999999999 99999999999999999999.99999, 99999999999999999999.9999999999, 9.99999999999999999999999999999, 9.9999999999999999999999999999999999999); GO +insert into babel_4424_t1 (n3_0) values (111); +insert into babel_4424_t1 (n3_1) values (11.1); +insert into babel_4424_t1 (n6_0) values (111111); +insert into babel_4424_t1 (n10_0) values (1111111111); +insert into babel_4424_t1 (n10_9) values (1.111111111); +insert into babel_4424_t1 (n15_0) values (111111111111111); +insert into babel_4424_t1 (n16_15) values (1.111111111111111); +insert into babel_4424_t1 (n20_2) values (111111111111111111.11); +insert into babel_4424_t1 (n25_5) values (11111111111111111111.11111); +insert into babel_4424_t1 (n30_10) values (11111111111111111111.1111111111); +insert into babel_4424_t1 (n30_29) values (1.11111111111111111111111111111); +insert into babel_4424_t1 (n38_37) values (1.1111111111111111111111111111111111111); +insert into babel_4424_t1 (n3_0, n3_1, n6_0, n10_0, n10_9, n15_0, n16_15, n20_2, n25_5, n30_10, n30_29, n38_37) +values (111, 11.1, 111111, 1111111111, 1.111111111, 111111111111111, 1.111111111111111, 111111111111111111.11, +11111111111111111111.11111, 11111111111111111111.1111111111, 1.11111111111111111111111111111, 1.1111111111111111111111111111111111111); +GO + select n38_37 + 100 from babel_4424_t1 where n38_37 is not null; GO From 02c5670e5b37c62164653c55b01e6ec6cd9acc1e Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Fri, 10 Nov 2023 14:30:28 +0530 Subject: [PATCH 27/34] Resolved comments --- .../src/backend/tds/tdsresponse.c | 12 +++++-- contrib/babelfishpg_tsql/src/hooks.c | 4 +-- test/JDBC/expected/BABEL-4424.out | 36 +++++++++++++++++++ test/JDBC/input/BABEL-4424.sql | 21 +++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 7100ba4dbd..e9c451443c 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -1894,9 +1894,15 @@ PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *target * than -1. */ if (atttypmod == -1 && tle != NULL) - atttypmod = plannedstmt ? - resolve_numeric_typmod_from_exp(plannedstmt->planTree, (Node *) tle->expr) : - resolve_numeric_typmod_from_exp(NULL, (Node *) tle->expr); + { + if (!plannedstmt) + { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("Internal error detected while calculating the precision of numeric expression"))); + } + atttypmod = resolve_numeric_typmod_from_exp(plannedstmt->planTree, (Node *) tle->expr); + } /* * Get the precision and scale out of the typmod value if diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 7a0695c424..e32e0fdb5c 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -2907,7 +2907,7 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume if (weight < 0) { /* weight < 0 means the integral part of the number is 0 */ - total_digit_count = 1 + dscale; + total_digit_count = dscale; return (total_digit_count > TDS_NUMERIC_MAX_PRECISION); } total_digit_count = weight * numeric_base; @@ -2933,8 +2933,6 @@ pltsql_detect_numeric_overflow(int weight, int dscale, int first_block, int nume int log_10 = (int) log10(partially_filled_numeric_block); // keep compiler happy total_digit_count += log_10 + 1; } - else - total_digit_count += 1; } /* diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index 553d524703..f3ae8ac1b6 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -843,5 +843,41 @@ numeric ~~END~~ +DROP table babel_4424_t1; +GO + +create table babel_4424_t1 (a numeric(38,38)); +GO + +insert into babel_4424_t1 values (0.1111111111111111111111111111111111111111); +go +~~ROW COUNT: 1~~ + + +select a + a from babel_4424_t1; +GO +~~START~~ +numeric +0.22222222222222222222222222222222222222 +~~END~~ + + +truncate table test; +GO + +insert into test values (0.99999999999999999999999999999999999999) +GO +~~ROW COUNT: 1~~ + + +select a + a from test; +GO +~~START~~ +numeric +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Arithmetic overflow error for data type numeric.)~~ + + DROP table babel_4424_t1; GO diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index eb5f91720a..43709508e1 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -375,5 +375,26 @@ select * from order by col; GO +DROP table babel_4424_t1; +GO + +create table babel_4424_t1 (a numeric(38,38)); +GO + +insert into babel_4424_t1 values (0.1111111111111111111111111111111111111111); +go + +select a + a from babel_4424_t1; +GO + +truncate table test; +GO + +insert into test values (0.99999999999999999999999999999999999999) +GO + +select a + a from test; +GO + DROP table babel_4424_t1; GO \ No newline at end of file From 829e1c9ddab7b8548484282b49f9ee1f87b6f216 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Fri, 10 Nov 2023 15:38:31 +0530 Subject: [PATCH 28/34] Fixed output file --- test/JDBC/expected/BABEL-4424.out | 6 +++--- test/JDBC/input/BABEL-4424.sql | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/JDBC/expected/BABEL-4424.out b/test/JDBC/expected/BABEL-4424.out index f3ae8ac1b6..5659724c1a 100644 --- a/test/JDBC/expected/BABEL-4424.out +++ b/test/JDBC/expected/BABEL-4424.out @@ -862,15 +862,15 @@ numeric ~~END~~ -truncate table test; +truncate table babel_4424_t1; GO -insert into test values (0.99999999999999999999999999999999999999) +insert into babel_4424_t1 values (0.99999999999999999999999999999999999999) GO ~~ROW COUNT: 1~~ -select a + a from test; +select a + a from babel_4424_t1; GO ~~START~~ numeric diff --git a/test/JDBC/input/BABEL-4424.sql b/test/JDBC/input/BABEL-4424.sql index 43709508e1..8c75c00c51 100644 --- a/test/JDBC/input/BABEL-4424.sql +++ b/test/JDBC/input/BABEL-4424.sql @@ -387,13 +387,13 @@ go select a + a from babel_4424_t1; GO -truncate table test; +truncate table babel_4424_t1; GO -insert into test values (0.99999999999999999999999999999999999999) +insert into babel_4424_t1 values (0.99999999999999999999999999999999999999) GO -select a + a from test; +select a + a from babel_4424_t1; GO DROP table babel_4424_t1; From d4127456bd027fcd4530617c44719dc4a57c05a0 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Thu, 16 Nov 2023 10:36:49 +0530 Subject: [PATCH 29/34] Addressed comments --- contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index e9c451443c..3b779eef0c 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -1899,7 +1899,8 @@ PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *target { ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("Internal error detected while calculating the precision of numeric expression"))); + errmsg("Internal error detected while calculating the precision of numeric expression"), + errhint("plannedstmt is NULL while calculating the precision of numeric expression when it contains outer var"))); } atttypmod = resolve_numeric_typmod_from_exp(plannedstmt->planTree, (Node *) tle->expr); } From e29ac8c10b36b100b6747884efb7f8c3910a0792 Mon Sep 17 00:00:00 2001 From: Sai Rohan Basa <108261379+basasairohan@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:09:28 +0530 Subject: [PATCH 30/34] Initial commit for Babelfish v3.5 (#2027) 1/ Update Github action scripts 2/ Create 15_5 upgrade test folder. 3/ Bump Babelfish version string in babelfish_version.h 4/ Add upgrade script babelfishpg_tsql--3.4.0--3.5.0.sql Signed-off-by: Sai Rohan Basa --- .../upgrade-test-configuration.yml | 12 +- .github/template/version-branch-template.yml | 6 + contrib/babelfishpg_tsql/Version.config | 2 +- .../babelfishpg_tsql--2.8.0--3.0.0.sql | 83 +++ .../babelfishpg_tsql--3.4.0--3.5.0.sql | 49 ++ .../babelfishpg_tsql/src/babelfish_version.h | 4 +- test/JDBC/upgrade/14_11/schedule | 420 +++++++++++++++ test/JDBC/upgrade/15_5/schedule | 492 ++++++++++++++++++ .../expected_drop.out | 1 + 9 files changed, 1065 insertions(+), 4 deletions(-) create mode 100644 contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--2.8.0--3.0.0.sql create mode 100644 contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.4.0--3.5.0.sql create mode 100644 test/JDBC/upgrade/14_11/schedule create mode 100644 test/JDBC/upgrade/15_5/schedule diff --git a/.github/configuration/upgrade-test-configuration.yml b/.github/configuration/upgrade-test-configuration.yml index 376b296d60..c4f427795f 100644 --- a/.github/configuration/upgrade-test-configuration.yml +++ b/.github/configuration/upgrade-test-configuration.yml @@ -84,6 +84,16 @@ upgrade-version: [[ upgrade-type: major } ], +[ + { + version: '14.11', + upgrade-type: null + }, + { + version: target.latest, + upgrade-type: major + } +], [ { version: 15.2, @@ -96,7 +106,7 @@ upgrade-version: [[ ], [ { - version: 15.4, + version: 15.5, upgrade-type: null }, { diff --git a/.github/template/version-branch-template.yml b/.github/template/version-branch-template.yml index 9371c177e8..b11bdf69b1 100644 --- a/.github/template/version-branch-template.yml +++ b/.github/template/version-branch-template.yml @@ -35,6 +35,9 @@ engine_branch: BABEL_2_6_STABLE__PG_14_9 extension_branch: BABEL_2_6_STABLE '14.10': + engine_branch: BABEL_2_7_STABLE__PG_14_10 + extension_branch: BABEL_2_7_STABLE +'14.11': engine_branch: BABEL_2_X_DEV__PG_14_X extension_branch: BABEL_2_X_DEV '15.2': @@ -46,6 +49,9 @@ '15.4': engine_branch: BABEL_3_3_STABLE__PG_15_4 extension_branch: BABEL_3_3_STABLE +'15.5': + engine_branch: BABEL_3_4_STABLE__PG_15_5 + extension_branch: BABEL_3_4_STABLE 'source.latest': engine_branch: latest extension_branch: latest diff --git a/contrib/babelfishpg_tsql/Version.config b/contrib/babelfishpg_tsql/Version.config index 32377081fe..ec4d6a892b 100644 --- a/contrib/babelfishpg_tsql/Version.config +++ b/contrib/babelfishpg_tsql/Version.config @@ -2,6 +2,6 @@ # places during the build process PGTSQL_MAJOR_VERSION=3 -PGTSQL_MINOR_VERSION=4 +PGTSQL_MINOR_VERSION=5 PGTSQL_MICRO_VERSION=0 diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--2.8.0--3.0.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--2.8.0--3.0.0.sql new file mode 100644 index 0000000000..235479aa19 --- /dev/null +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--2.8.0--3.0.0.sql @@ -0,0 +1,83 @@ +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION ""babelfishpg_tsql"" UPDATE TO '3.0.0'" to load this file. \quit + +-- add 'sys' to search path for the convenience +SELECT set_config('search_path', 'sys, '||current_setting('search_path'), false); + +-- please add your SQL here + +CREATE OR REPLACE FUNCTION sys.datepart_internal(IN datepart PG_CATALOG.TEXT, IN arg anyelement,IN df_tz INTEGER DEFAULT 0) RETURNS INTEGER AS $$ +DECLARE + result INTEGER; + first_day DATE; + first_week_end INTEGER; + day INTEGER; +BEGIN + CASE datepart + WHEN 'dow' THEN + result = (date_part(datepart, arg)::INTEGER - current_setting('babelfishpg_tsql.datefirst')::INTEGER + 7) % 7 + 1; + WHEN 'tsql_week' THEN + first_day = make_date(date_part('year', arg)::INTEGER, 1, 1); + first_week_end = 8 - sys.datepart_internal('dow', first_day)::INTEGER; + day = date_part('doy', arg)::INTEGER; + IF day <= first_week_end THEN + result = 1; + ELSE + result = 2 + (day - first_week_end - 1) / 7; + END IF; + WHEN 'second' THEN + result = TRUNC(date_part(datepart, arg))::INTEGER; + WHEN 'millisecond' THEN + result = right(date_part(datepart, arg)::TEXT, 3)::INTEGER; + WHEN 'microsecond' THEN + result = right(date_part(datepart, arg)::TEXT, 6)::INTEGER; + WHEN 'nanosecond' THEN + -- Best we can do - Postgres does not support nanosecond precision + result = right(date_part('microsecond', arg)::TEXT, 6)::INTEGER * 1000; + WHEN 'tzoffset' THEN + -- timezone for datetimeoffset + result = df_tz; + ELSE + result = date_part(datepart, arg)::INTEGER; + END CASE; + RETURN result; +EXCEPTION WHEN invalid_parameter_value or feature_not_supported THEN + -- date_part() throws an exception when trying to get day/month/year etc. from + -- TIME, so we just need to catch the exception in this case + -- date_part() returns 0 when trying to get hour/minute/second etc. from + -- DATE, which is the desirable behavior for datepart() as well. + -- If the date argument data type does not have the specified datepart, + -- date_part() will return the default value for that datepart. + CASE datepart + -- Case for datepart is year, yy and yyyy, all mappings are defined in gram.y. + WHEN 'year' THEN RETURN 1900; + -- Case for datepart is quater, qq and q + WHEN 'quarter' THEN RETURN 1; + -- Case for datepart is month, mm and m + WHEN 'month' THEN RETURN 1; + -- Case for datepart is day, dd and d + WHEN 'day' THEN RETURN 1; + -- Case for datepart is dayofyear, dy + WHEN 'doy' THEN RETURN 1; + -- Case for datepart is y(also refers to dayofyear) + WHEN 'y' THEN RETURN 1; + -- Case for datepart is week, wk and ww + WHEN 'tsql_week' THEN RETURN 1; + -- Case for datepart is iso_week, isowk and isoww + WHEN 'week' THEN RETURN 1; + -- Case for datepart is tzoffset and tz + WHEN 'tzoffset' THEN RETURN 0; + -- Case for datepart is weekday and dw, return dow according to datefirst + WHEN 'dow' THEN + RETURN (1 - current_setting('babelfishpg_tsql.datefirst')::INTEGER + 7) % 7 + 1 ; + ELSE + RAISE EXCEPTION '''%'' is not a recognized datepart option', datepart; + RETURN -1; + END CASE; +END; +$$ +STRICT +LANGUAGE plpgsql IMMUTABLE; + +-- Reset search_path to not affect any subsequent scripts +SELECT set_config('search_path', trim(leading 'sys, ' from current_setting('search_path')), false); \ No newline at end of file diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.4.0--3.5.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.4.0--3.5.0.sql new file mode 100644 index 0000000000..7b1076d53a --- /dev/null +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.4.0--3.5.0.sql @@ -0,0 +1,49 @@ +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION ""babelfishpg_tsql"" UPDATE TO '3.4.0'" to load this file. \quit + +-- add 'sys' to search path for the convenience +SELECT set_config('search_path', 'sys, '||current_setting('search_path'), false); + +-- Drops an object if it does not have any dependent objects. +-- Is a temporary procedure for use by the upgrade script. Will be dropped at the end of the upgrade. +-- Please have this be one of the first statements executed in this upgrade script. +CREATE OR REPLACE PROCEDURE babelfish_drop_deprecated_object(object_type varchar, schema_name varchar, object_name varchar) AS +$$ +DECLARE + error_msg text; + query1 text; + query2 text; +BEGIN + + query1 := pg_catalog.format('alter extension babelfishpg_tsql drop %s %s.%s', object_type, schema_name, object_name); + query2 := pg_catalog.format('drop %s %s.%s', object_type, schema_name, object_name); + + execute query1; + execute query2; +EXCEPTION + when object_not_in_prerequisite_state then --if 'alter extension' statement fails + GET STACKED DIAGNOSTICS error_msg = MESSAGE_TEXT; + raise warning '%', error_msg; + when dependent_objects_still_exist then --if 'drop view' statement fails + GET STACKED DIAGNOSTICS error_msg = MESSAGE_TEXT; + raise warning '%', error_msg; +end +$$ +LANGUAGE plpgsql; + +-- Please add your SQLs here +/* + * Note: These SQL statements may get executed multiple times specially when some features get backpatched. + * So make sure that any SQL statement (DDL/DML) being added here can be executed multiple times without affecting + * final behaviour. + */ + +-- Drops the temporary procedure used by the upgrade script. +-- Please have this be one of the last statements executed in this upgrade script. +DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar); + +-- After upgrade, always run analyze for all babelfish catalogs. +CALL sys.analyze_babelfish_catalogs(); + +-- Reset search_path to not affect any subsequent scripts +SELECT set_config('search_path', trim(leading 'sys, ' from current_setting('search_path')), false); diff --git a/contrib/babelfishpg_tsql/src/babelfish_version.h b/contrib/babelfishpg_tsql/src/babelfish_version.h index 639fa5876b..d27676f062 100644 --- a/contrib/babelfishpg_tsql/src/babelfish_version.h +++ b/contrib/babelfishpg_tsql/src/babelfish_version.h @@ -8,7 +8,7 @@ *------------------------------------------------------------------------- */ -#define BABELFISH_VERSION_STR "3.4.0" -#define BABELFISH_INTERNAL_VERSION_STR "Babelfish 15.5.0.0" +#define BABELFISH_VERSION_STR "3.5.0" +#define BABELFISH_INTERNAL_VERSION_STR "Babelfish 15.6.0.0" #define BABEL_COMPATIBILITY_VERSION "12.0.2000.8" #define BABEL_COMPATIBILITY_MAJOR_VERSION "12" diff --git a/test/JDBC/upgrade/14_11/schedule b/test/JDBC/upgrade/14_11/schedule new file mode 100644 index 0000000000..1064d1bdec --- /dev/null +++ b/test/JDBC/upgrade/14_11/schedule @@ -0,0 +1,420 @@ +# Schedule File for JDBC Test Framework for local run +# 1. Lines starting with '#' will be treated as comments +# 2. To run a postgres command: cmd#!#postgresql#!# +# 3. To run a T-SQL command: cmd#!#sqlserver#!# +# 4. Keyword "all" is equivalent to running all test files in +# input folder +# 5. To add a test, add test name (without extension, -vu-prepare, -vu-verify and -vu-cleanup. For example if test file name is TestBigInt-vu-prepare.txt write TestBigInt) on a new line + +# This should be the first test to check there are no duplicated object_ids +BABEL-3613 + +babelfish_cast_floor +babel_try_parse +TestBigInt +TestBinary +TestBIT +TestChar +TestDatetime2 +TestDatetime +TestDate +TestDecimal +TestFloat +TestImage +TestInt +TestMoney +TestNumeric +TestReal +TestSmallDatetime +TestSmallInt +TestSmallMoney +TestSQLVariant +TestText +TestTime +TestTinyInt +TestUDD +TestUniqueIdentifier +TestVarChar +TestXML +sys-assembly_types +sys-database_mirroring +sys-databases +sys-numbered_procedures +BABEL-3121 +sys-events +sys-suser_sid +sys-trigger_events +BABEL-2688 +BABEL-328 +BABEL-3166 +BABEL-3192 +BABEL-3221 +BABEL-3204 +BABEL-3234 +BABEL-3402 +cast_numeric_types_to_datetime +cast_numeric_types_to_smalldatetime +routines_definition +column_domain_usage +constraint_column_usage +select-strip-parens-before-15_5 +sp_describe_first_result_set +sys-host_name +SYSTEM_USER +indexproperty +sys-all_parameters +msdb-dbo-syspolicy_configuration +sys-all_views +datepart +sys-server_principals +fulltextserviceproperty +is_srvrolemember +msdb-dbo-fn_syspolicy_is_automation_enabled +objectproperty +objectpropertyex +sys-column-property +sys-configurations +sys-datefirst +sys-lock_timeout +sys-max_connections +sys-original_login +sys-schema-name +sys-objects +sys-procedures +sys-sysdatabases +sys-sysobjects +sys-trigger_nestlevel +schema_resolution_proc +BABEL-404 +BABEL-493 +BABEL-621 +BABEL-775 +BABEL-1206 +BABEL-1251 +BABEL-1319 +BABEL-1444 +BABEL-1465 +BABEL-1466 +BABEL-1654 +BABEL-1715 +BABEL-2086 +BABEL-3314 +BABEL-TABLEOPTIONS +BABEL-2765 +BABEL-2819 +BABEL-2917 +BABEL-2955 +BABEL-3358 +BABEL-3747 +BABEL-3781 +temp-tables +table-variable +TestNotNull +Test-Identity +Test-Computed-Columns +BABEL-1189 +BABEL-1062 +BABEL-1243 +BABEL-1493 +BABEL-1963 +BABEL-2203 +BABEL-2208 +BABEL-2257 +BABEL-2449 +BABEL-2535 +BABEL-2787-2 +BABEL-2787 +BABEL-2805 +BABEL-2812 +BABEL-2845 +BABEL-2884 +BABEL-2944 +BABEL-3116 +BABEL-3117 +BABEL-3118 +BABEL-3249 +BABEL-3486 +BABEL-3474 +BABEL-3614 +BABEL-3646 +BABEL-3748 +BABEL-383 +BABEL-405 +BABEL-937 +forjson +forjson-subquery +forjson-datatypes +forxml +forxml-subquery +BABEL-PROCID +babel_trigger +insteadoftriggers_with_transaction +insteadof_nested_trigger_inside_proc +insteadof_nested_trigger_with_dml +nested_trigger_inside_proc +nested_trigger_with_dml +triggers_with_transaction +Test-sp_addrole +Test-sp_addrolemember +Test-sp_droprole +Test-sp_droprolemember +Test-sp_helpdbfixedrole +Test-sp_helpsrvrolemember +Test-sp_helpuser +Test-sp_set_session_context +Test-sp_set_session_context-dep +TestTableType +BABEL-CROSS-DB +BABEL-LOGIN +BABEL-USER +BABEL-ROLE +babelfish_sysdatabases +babelfish_namespace_ext +babelfish_authid_login_ext +babelfish_authid_user_ext +babelfish_inconsistent_metadata +babelfish_migration_mode +schema_resolution_func +BABEL-3147 +collation_tests_arabic +collation_tests_greek +collation_tests_mongolian +collation_tests_polish +collation_tests +babel_datetime +babel_char +BABEL-SQUARE +BABEL-728 +babel_function_string +BABEL-1566 +BABEL-3360 +BABEL-3380 +babel_isnumeric +HAS_DBACCESS +BABEL-1475 +BABEL-1510 +BABEL-3213 +BABEL-3010 +BABEL-3369 +BABEL-3370 +BABEL-RAND +BABEL-741 +BABEL-ROLE-MEMBER +tdscollation +BABEL-EXTENDEDPROPERTY +BABEL-EXECUTE_AS_CALLER +sys-filegroups +sys-filetables +sys-fulltext_indexes +sys-hash_indexes +sys-plan_guides +sp_tablecollations +sys-assemblies +BABEL-LOGIN-USER-EXT +bitwise_not-operator +BABEL-1683 +BABEL-1953 +schema_resolution_trigger +sys_all_objects-dep +sys-columns-dep +sys-databases-dep +sys-foreign_key_columns-dep +sys-foreign_keys-dep +sys-identity_columns-dep +sys-indexes-dep +sys-key_constraints-dep +sys-schemas-dep +sys-sp_tables_view-dep +sys-sysforeignkeys-dep +sys-tables-dep +sys-types-before-dep +sys-views-dep +sys-check_constraints-dep +sys-computed_columns-dep +sys-default_constraints-dep +sys-index_columns-dep +sys-sp_databases-dep +sys-syscolumns-dep +sys-dm_exec_connections-dep +sys-dm_exec_sessions-dep +sys-table_types-before-dep +sys-all_sql_modules-dep +sys-sql_modules-dep +sys-system_sql_modules-dep +sys-triggers-dep +sys-proc_param_helper-dep +sys-sp_pkeys +sys-sp_statistics +BABEL-APPLOCK +BABEL-1438 +BABEL-SP_DATATYPE_INFO +BABEL-SPCOLUMNS +BABEL-SP_TABLES +BABEL-SP_SPECIAL_COLUMNS +BABEL-SP_TABLE_PRIVILIGES +BABEL-SP_FKEYS +BABEL-SP_STORED_PROCEDURES +BABEL-SP_SPROC_COLUMNS +BABEL-3000 +sys-sp_pkeys-dep +sys-sp_statistics-dep +BABEL-SPCOLUMNS-dep +BABEL-SP_COLUMNS_MANAGED-dep +BABEL-SP_SPECIAL_COLUMNS-dep +BABEL-SP_SPECIAL_COLUMNS_100-dep +BABEL-SP_FKEYS-dep +BABEL-SP_STORED_PROCEDURES-dep +BABEL-SP_SPROC_COLUMNS-dep +BABEL-SP_SPROC_COLUMNS_100-dep +BABEL-3000-dep +Test-sp_helprole-dep +Test-sp_helprolemember-dep +format +format-dep +msdb-dbo-syspolicy_system_health_state +dateadd_internal_df +sys-all_columns +sys-all_columns-dep +sys-all_sql_modules +sys-assembly_modules +sys-change_tracking_databases +sys-change_tracking_tables +sys-check_constraints +sys-columns +sys-computed_columns +sys-data_spaces +sys-database_files +sys-database_filestream_options +sys-database_recovery_status +sys-default_constraints +sys-dm_exec_connections +sys-dm_exec_sessions +sys-dm_hadr_cluster +sys-dm_hadr_database_replica_states +sys-dm_os_host_info +sys-endpoints +sys-extended_properties +sys-filetable_system_defined_objects +sys-foreign_key_columns +sys-foreign_keys +sys-fulltext_catalogs +sys-fulltext_index_columns +sys-fulltext_languages +sys-fulltext_stoplists +sys-identity_columns +sys-index_columns +sys-indexes +sys-key_constraints +sys-master_files +sys-nestlevel-dep +sys-partitions +sys-partitions-dep +sys-registered_search_property_lists +sys-schemas +sys-selective_xml_index_paths +sys-sid_binary +sys-sp_databases +sys-sp_tables_view +sys-spatial_index_tessellations +sys-spatial_indexes +sys-stats +sys-synonyms +sys-syscharsets +sys-syscolumns +sys-sysforeignkeys +sys-syslanguages +sys-system_sql_modules +sys-sql_modules +sys-table_types +sys-tables +sys-triggers +sys-types +sys-views +sys-xml_indexes +sys-xml_schema_collections +sys_all_objects +sys_babelfish_configurations_view +BABEL-1249 +BABEL-1291 +BABEL-1994-CHAR +BABEL-1994-VARCHAR +BABEL-889 +babel_417 +babel_datatype_sqlvariant +babel_sqlvariant_cast_compare +BABEL-3347 +BABEL-3144 +sys-all_parameters-dep +BABEL-3556 +BABEL-3588 +BABEL-3268 +BABEL-3513 +BABEL_GRANT_CONNECT +BABEL-sp_helpdb +BABEL-2795 +babelfish_integrity_checker +get_tds_id +BABEL-PG-SYSTEM-FUNCTIONS +BABEL-3655 +BABEL-3702 +openjson +sys-table_types_internal +sys-table_types_internal-dep +BABEL-CHECK-CONSTRAINT +BABEL-3640 +sys-sysindexes +sys-system_objects +ISC-Views +ISC-Tables +ISC-Columns +#ISC-Check-Constraints +ISC-Table_Constraints +sys_server_principals_dep +sys_database_principals_dep +datediff_big +atn2 +app_name +str +ISC-sequences +jira-BABEL-3504-upgrade +case_insensitive_collation +sys-has_perms_by_name +sys-has_perms_by_name-dep +BABEL_OBJECT_ID +BABEL_SCHEMATA +isc-schemata-dep +AVG-Aggregate-common +AVG-Aggregate-Dep +bbf_view_def +BABEL-3802 +BABEL-3914 +BABEL_OBJECT_NAME +sys-systypes +BABEL_OBJECT_DEFINITION +datediff_internal_date +Test-sp_rename +Test-sp_rename-dep +BABEL-3657 +BABEL-733 +BABEL-3938 +BABEL-NEXT-VALUE-FOR +BABEL-4098 +TestVariableDataLength +binary-index +BABEL-4078 +BABEL-3215 +orderby +babel_int4_varbinary_div +babel_varbinary_int4_div +sys-sql_expression_dependencies +smalldatetimefromparts-dep +BABEL_4330 +BABEL-4231 +BABEL-4384 +GRANT_SCHEMA +default_params +BABEL-3326 +cast_eliminate +TestDatatypeAggSort +babel_index_nulls_order-before-15-5 +BABEL-2999 diff --git a/test/JDBC/upgrade/15_5/schedule b/test/JDBC/upgrade/15_5/schedule new file mode 100644 index 0000000000..efe73dc34b --- /dev/null +++ b/test/JDBC/upgrade/15_5/schedule @@ -0,0 +1,492 @@ +# Schedule File for JDBC Test Framework for local run +# 1. Lines starting with '#' will be treated as comments +# 2. To run a postgres command: cmd#!#postgresql#!# +# 3. To run a T-SQL command: cmd#!#sqlserver#!# +# 4. Keyword "all" is equivalent to running all test files in input folder +# 5. To add a test, add test name (without extension, , and . For example if test file name is TestBigInt.txt write TestBigInt) on a new line + +# This should be the first test to check there are no duplicated object_ids +BABEL-3613 + +app_name +atn2 +ATTIMEZONE-dep +AVG-Aggregate-common +AVG-Aggregate-Dep +BABEL-1062 +BABEL-1189 +BABEL-1206 +BABEL-1243 +BABEL-1249 +BABEL-1251 +BABEL-1291 +BABEL-1319 +BABEL-1438 +BABEL-1444 +BABEL-1465 +BABEL-1466 +BABEL-1475 +BABEL-1493 +BABEL-1510 +BABEL-1566 +BABEL-1625 +BABEL-1654 +BABEL-1683 +BABEL-1715 +BABEL-1953 +BABEL-1963 +BABEL-1994-CHAR +BABEL-1994-VARCHAR +BABEL-2086 +BABEL-2170 +BABEL-2203 +BABEL-2208 +BABEL-2257 +BABEL-2449 +BABEL-2535 +BABEL-2688 +BABEL-2765 +BABEL-2787 +BABEL-2787-2 +BABEL-2795 +BABEL-2805 +BABEL-2812 +BABEL-2819 +BABEL-2845 +BABEL-2877 +BABEL-2884 +BABEL-2917 +BABEL-2944 +BABEL-2955 +BABEL-3000 +BABEL-3000-dep +BABEL-3010 +BABEL-3116 +BABEL-3117 +BABEL-3118 +BABEL-3121 +BABEL-3144 +BABEL-3147 +BABEL-3166 +BABEL-3192 +BABEL-3204 +BABEL-3213 +BABEL-3215 +BABEL-3221 +BABEL-3234 +BABEL-3249 +BABEL-3268 +BABEL-328 +BABEL-3314 +BABEL-3326 +BABEL-3347 +BABEL-3358 +BABEL-3360 +BABEL-3369 +BABEL-3370 +BABEL-3380 +BABEL-3392 +BABEL-3402 +BABEL-3474 +BABEL-3478 +BABEL-3486 +BABEL-3513 +BABEL-3556 +BABEL-3588 +BABEL-3614 +BABEL-3640 +BABEL-3646 +BABEL-3655 +BABEL-3657 +BABEL-3696 +BABEL-3697 +BABEL-3702 +BABEL-3725 +BABEL-3747 +BABEL-3748 +BABEL-3781 +BABEL-3801 +BABEL-3802 +BABEL-3818 +BABEL-3828 +BABEL-383 +BABEL-3844 +BABEL-3914 +BABEL-3938 +BABEL-3952 +BABEL-3953-datetrunc +BABEL-404 +BABEL-405 +BABEL-4078 +BABEL-4098 +BABEL-4214 +babel_417 +BABEL-493 +BABEL_539 +BABEL-621 +BABEL-728 +BABEL-733 +BABEL-741 +BABEL-745 +BABEL-775 +BABEL-889 +BABEL-937 +BABEL-APPLOCK +babel_char +BABEL-CHECK-CONSTRAINT +babel_context_info +BABEL-CROSS-DB +babel_datatype_sqlvariant +babel_datetime +Babel_domain_mapping_test +BABEL-EXECUTE_AS_CALLER +BABEL-EXTENDEDPROPERTY +BABEL-EXTENDEDPROPERTY-v2 +babel_int4_varbinary_div +babelfish_authid_login_ext +babelfish_authid_user_ext +babelfish_cast_floor +babelfish_inconsistent_metadata +babelfish_integrity_checker +babelfish_migration_mode +babelfish_namespace_ext +babelfish_sysdatabases +babel_function_string +BABEL_GRANT_CONNECT +babel_isnumeric +BABEL_COL_NAME +BABEL-LOGIN +BABEL-LOGIN-USER-EXT +BABEL-NEXT-VALUE-FOR +BABEL_OBJECT_DEFINITION +BABEL_OBJECT_ID +BABEL_OBJECT_NAME +BABEL-PG-SYSTEM-FUNCTIONS +BABEL-PROCID +BABEL-RAND +BABEL-ROLE +BABEL-ROLE-MEMBER +BABEL_SCHEMATA +BABEL-SPCOLUMNS +BABEL-SPCOLUMNS-dep +BABEL-SP_COLUMNS_MANAGED-dep +BABEL-SP_DATATYPE_INFO +BABEL-SP_FKEYS +BABEL-SP_FKEYS-dep +BABEL-sp_helpdb +BABEL-SP_SPECIAL_COLUMNS +BABEL-SP_SPECIAL_COLUMNS_100-dep +BABEL-SP_SPECIAL_COLUMNS-dep +BABEL-SP_SPROC_COLUMNS +BABEL-SP_SPROC_COLUMNS_100-dep +BABEL-SP_SPROC_COLUMNS-dep +BABEL-SP_STORED_PROCEDURES +BABEL-SP_STORED_PROCEDURES-dep +BABEL-SP_TABLE_PRIVILIGES +BABEL-SP_TABLES +babel_sqlvariant_cast_compare +BABEL-SQUARE +BABEL-TABLEOPTIONS +babel_trigger +babel_try_parse +BABEL-USER +babel_varbinary_int4_div +bbf_view_def +binary-index +bitwise_not-operator +case_insensitive_collation +cast_numeric_types_to_datetime +cast_numeric_types_to_smalldatetime +col_length +collation_tests +collation_tests_arabic +collation_tests_greek +collation_tests_mongolian +collation_tests_polish +column_domain_usage +constraint_column_usage +dateadd_internal_df +datediff_big +datediff_internal_date +datepart +datetime2fromparts-after-15-2 +forjson +forjson-datatypes +forjson-subquery +forjson-nesting +format +format-dep +forxml +forxml-subquery +fulltextserviceproperty +FULLTEXT_INDEX +fts-contains +get_tds_id +HAS_DBACCESS +identity_function +indexproperty +insteadof_nested_trigger_inside_proc +insteadof_nested_trigger_with_dml +insteadoftriggers_with_transaction +ISC-Columns +isc-schemata-dep +ISC-sequences +ISC-Table_Constraints +ISC-Tables +ISC-Views +is_srvrolemember +jira-BABEL-3504-upgrade +key_column_usage +linked_servers +msdb-dbo-fn_syspolicy_is_automation_enabled +msdb-dbo-syspolicy_configuration +msdb-dbo-syspolicy_system_health_state +nested_trigger_inside_proc +nested_trigger_with_dml +objectpropertyex +openjson +openquery_upgrd_before_15_4 +orderby +routines_definition +rowcount +schema_resolution_func +schema_resolution_proc +schema_resolution_trigger +select-strip-parens +sp_describe_first_result_set +sp_tablecollations +smalldatetimefromparts-dep +str +switchoffset-dep +sys-all_columns +sys-all_columns-dep +sys_all_objects +sys_all_objects-dep +sys-all_parameters +sys-all_parameters-dep +sys-all_sql_modules +sys-all_sql_modules-dep +sys-all_views +sys-assemblies +sys-assembly_modules +sys-assembly_types +sys_babelfish_configurations_view +sys-change_tracking_databases +sys-change_tracking_tables +sys-check_constraints +sys-check_constraints-dep +sys-column-property +sys-columns +sys-columns-dep +sys-computed_columns +sys-computed_columns-dep +sys-configurations +sys-database_files +sys-database_filestream_options +sys-database_mirroring +sys_database_principals_dep +sys_syslogins_dep +sys-database_recovery_status +sys-databases +sys-databases-dep +sys-data_spaces +sys-datefirst +sys-default_constraints +sys-default_constraints-dep +sys-dm_exec_connections +sys-dm_exec_connections-dep +sys-dm_exec_sessions +sys-dm_exec_sessions-dep +sys-dm_hadr_cluster +sys-dm_hadr_database_replica_states +sys-dm_os_host_info +sys-endpoints +sys-eomonth +sys-events +sys-extended_properties +sys-sql_expression_dependencies +sys-filegroups +sys-filetables +sys-filetable_system_defined_objects +sys-foreign_key_columns +sys-foreign_key_columns-dep +sys-foreign_keys +sys-foreign_keys-dep +sys-fulltext_catalogs +sys-fulltext_index_columns +sys-fulltext_indexes +sys-fulltext_languages +sys-fulltext_stoplists +sys-hash_indexes +sys-has_perms_by_name +sys-has_perms_by_name-dep +sys-host_name +sys-identity_columns +sys-identity_columns-dep +sys-index_columns +sys-index_columns-dep +sys-indexes +sys-indexes-dep +sys-key_constraints +sys-key_constraints-dep +sys-lock_timeout +sys-master_files +sys-max_connections +sys-nestlevel-dep +sys-numbered_procedures +sys-objects +sys-original_login +sys-parsename +sys-partitions +sys-partitions-dep +sys-plan_guides +sys-procedures +sys-proc_param_helper-dep +sys-registered_search_property_lists +sys-schema-name +sys-schemas +sys-schemas-dep +sys-selective_xml_index_paths +sys-server_principals +sys_server_role_members +sys_server_principals_dep +sys-sid_binary +sys-spatial_indexes +sys-spatial_index_tessellations +sys-sp_databases +sys-sp_databases-dep +sys-sp_pkeys +sys-sp_pkeys-dep +sys-sp_statistics +sys-sp_statistics-dep +sys-sp_tables_view +sys-sp_tables_view-dep +sys-sql_modules +sys-sql_modules-dep +sys-stats +sys-suser_sid +sys-suser_sname +sys-synonyms +sys-syscharsets +sys-syscolumns +sys-syscolumns-dep +sys-sysdatabases +sys-sysforeignkeys +sys-sysforeignkeys-dep +sys-sysindexes +sys-syslanguages +sys-sysobjects +sys-system_objects +sys-system_sql_modules +sys-system_sql_modules-dep +sys-systypes +sys_sysusers_dep +sys-tables +sys-tables-dep +sys-table_types +sys-table_types-dep +sys-table_types_internal +sys-table_types_internal-dep +SYSTEM_USER +sys-trigger_events +sys-trigger_nestlevel +sys-triggers +sys-triggers-dep +sys-types +sys-types-dep +sys-userid +sys-views +sys-views-dep +sys-xml_indexes +sys-xml_schema_collections +table-variable +tdscollation +temp-tables +TestBigInt +TestBinary +TestBIT +TestChar +Test-Computed-Columns +TestDate +TestDatetime +TestDatetime2 +TestDatetime-numeric-dateaddfunction +TestDatetime-numeric-representation +TestDecimal +TestFloat +Test-Identity +TestImage +TestInt +TestMoney +TestNotNull +TestNumeric +TestReal +TestRowVersion +TestSmallDatetime +TestSmallInt +TestSmallMoney +TestSpatialPoint +Test-sp_addrole +Test-sp_addrolemember +Test-sp_babelfish_volatility +Test-sp_droprole +Test-sp_droprolemember +Test-sp_execute_postgresql +Test-sp_helpdbfixedrole +Test-sp_helprole-dep +Test-sp_helprolemember-dep +Test-sp_helpsrvrolemember +Test-sp_helpuser +Test-sp_rename +Test-sp_rename-dep +Test-sp_set_session_context +Test-sp_set_session_context-dep +TestSQLVariant +TestTableType +TestText +TestTime +TestTinyInt +TestUDD +TestUniqueIdentifier +Test_user_from_win_login +TestVarChar +TestVariableDataLength +test_windows_alter_login +test_windows_alter_user +test_windows_login +test_windows_sp_helpuser +TestXML +timefromparts +todatetimeoffset-dep +triggers_with_transaction +typeid-typename +typeid-typename-dep +unquoted_string +doublequoted_string +alter_authorization_change_db_owner +sp_changedbowner +datetimeoffset-timezone +BABEL-4046 +host_id +linked_srv_4229 +BABEL-4175 +sp_who +BABEL_4330 +kill +BABEL-4217 +Test_ISNULL +BABEL-4270 +BABEL-4410 +BABEL-4231 +typeproperty-dep +sys_asymmetric_keys +sys_certificates +sys_database_permissions +BABEL-4279 +BABEL-4484 +pivot +#AUTO_ANALYZE #uncomment this test when preparing for new minor version +cast_eliminate +TestDatatypeAggSort +babel_index_nulls_order +BABEL-2999 diff --git a/test/python/expected/sql_validation_framework/expected_drop.out b/test/python/expected/sql_validation_framework/expected_drop.out index 1f91543291..44393848c0 100644 --- a/test/python/expected/sql_validation_framework/expected_drop.out +++ b/test/python/expected/sql_validation_framework/expected_drop.out @@ -42,6 +42,7 @@ Unexpected drop found for procedure sys.babelfish_drop_deprecated_object in file Unexpected drop found for procedure sys.babelfish_drop_deprecated_object in file babelfishpg_tsql--3.1.0--3.2.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_object in file babelfishpg_tsql--3.2.0--3.3.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_object in file babelfishpg_tsql--3.3.0--3.4.0.sql +Unexpected drop found for procedure sys.babelfish_drop_deprecated_object in file babelfishpg_tsql--3.4.0--3.5.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_table in file babelfishpg_tsql--2.1.0--2.2.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_view in file babelfishpg_tsql--1.0.0--1.1.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_view in file babelfishpg_tsql--2.1.0--2.2.0.sql From ecfc7901ba377a23addf84a2d0615f558c6a23f4 Mon Sep 17 00:00:00 2001 From: Jake Owen Date: Fri, 17 Nov 2023 15:20:00 -0500 Subject: [PATCH 31/34] Reimplement datediff and dateadd in c to improve performance (#1998) This change reimplements the datediff, datediff_big, and dateadd functions in C to improve performance by 65% compared to the original implementation. Task: BABEL-4496 Signed-off-by: Jake Owen --- contrib/babelfishpg_common/src/datetime.c | 589 +++++++++++++++++- contrib/babelfishpg_common/src/datetime.h | 6 + .../babelfishpg_common/src/datetimeoffset.c | 105 ++++ contrib/babelfishpg_tds/error_mapping.txt | 5 +- .../babelfishpg_tsql/sql/sys_functions.sql | 415 ++---------- .../babelfishpg_tsql--3.3.0--3.4.0.sql | 172 +++++ contrib/babelfishpg_tsql/src/err_handler.c | 5 +- contrib/babelfishpg_tsql/src/err_handler.h | 3 + test/JDBC/expected/BABEL-2812-vu-verify.out | 10 +- test/JDBC/expected/BABEL-3474-vu-verify.out | 36 +- .../expected/TestErrorHelperFunctions.out | 4 + ...tErrorHelperFunctionsUpgrade-vu-verify.out | 12 +- .../expected/babel_datetime-vu-verify.out | 3 +- test/JDBC/expected/babel_datetime.out | 2 +- test/JDBC/expected/babel_datetime2.out | 4 +- test/JDBC/expected/babel_smalldatetime.out | 12 +- .../babel_smalldatetime_before_15-5.out | 383 ++++++++++++ test/JDBC/expected/dateadd-vu-cleanup.out | 29 + test/JDBC/expected/dateadd-vu-prepare.out | 29 + test/JDBC/expected/dateadd-vu-verify.out | 185 ++++++ test/JDBC/expected/datediff-vu-cleanup.out | 47 ++ test/JDBC/expected/datediff-vu-prepare.out | 60 ++ test/JDBC/expected/datediff-vu-verify.out | 182 ++++++ test/JDBC/expected/datediff_big-vu-verify.out | 115 +++- ..._date-before-14_10-or-15_5-vu-cleanup.out} | 0 ..._date-before-14_10-or-15_5-vu-prepare.out} | 0 ...l_date-before-14_10-or-15_5-vu-verify.out} | 0 ...leanup__13_4__babel_datetime-vu-verify.out | 2 +- ...leanup__13_5__babel_datetime-vu-verify.out | 2 +- ...leanup__13_6__babel_datetime-vu-verify.out | 2 +- ...leanup__13_7__babel_datetime-vu-verify.out | 2 +- ...leanup__13_8__babel_datetime-vu-verify.out | 2 +- ...leanup__13_9__babel_datetime-vu-verify.out | 2 +- ...leanup__14_3__babel_datetime-vu-verify.out | 2 +- test/JDBC/input/babel_datetime-vu-verify.sql | 1 - .../input/babel_smalldatetime_before_15-5.sql | 102 +++ .../dateFunctions/dateadd-vu-cleanup.sql | 29 + .../dateFunctions/dateadd-vu-prepare.sql | 29 + .../input/dateFunctions/dateadd-vu-verify.sql | 90 +++ .../dateFunctions/datediff-vu-cleanup.sql | 47 ++ .../dateFunctions/datediff-vu-prepare.sql | 60 ++ .../dateFunctions/datediff-vu-verify.sql | 85 +++ .../functions/datediff_big-vu-verify.sql | 36 ++ ..._date-before-14_10-or-15_5-vu-cleanup.sql} | 0 ..._date-before-14_10-or-15_5-vu-prepare.sql} | 0 ...l_date-before-14_10-or-15_5-vu-verify.sql} | 0 test/JDBC/jdbc_schedule | 4 + test/JDBC/upgrade/14_10/schedule | 1 - test/JDBC/upgrade/14_11/schedule | 1 - test/JDBC/upgrade/14_7/schedule | 2 +- test/JDBC/upgrade/14_8/schedule | 2 +- test/JDBC/upgrade/14_9/schedule | 4 +- test/JDBC/upgrade/15_2/schedule | 2 +- test/JDBC/upgrade/15_3/schedule | 2 +- test/JDBC/upgrade/15_4/schedule | 2 +- test/JDBC/upgrade/15_5/schedule | 5 - test/JDBC/upgrade/latest/schedule | 3 +- test/JDBC/upgrade/master/schedule | 3 +- .../expected_create.out | 2 - .../expected_dependency.out | 3 +- 60 files changed, 2483 insertions(+), 459 deletions(-) create mode 100644 test/JDBC/expected/babel_smalldatetime_before_15-5.out create mode 100644 test/JDBC/expected/dateadd-vu-cleanup.out create mode 100644 test/JDBC/expected/dateadd-vu-prepare.out create mode 100644 test/JDBC/expected/dateadd-vu-verify.out create mode 100644 test/JDBC/expected/datediff-vu-cleanup.out create mode 100644 test/JDBC/expected/datediff-vu-prepare.out create mode 100644 test/JDBC/expected/datediff-vu-verify.out rename test/JDBC/expected/{datediff_internal_date-vu-cleanup.out => datediff_internal_date-before-14_10-or-15_5-vu-cleanup.out} (100%) rename test/JDBC/expected/{datediff_internal_date-vu-prepare.out => datediff_internal_date-before-14_10-or-15_5-vu-prepare.out} (100%) rename test/JDBC/expected/{datediff_internal_date-vu-verify.out => datediff_internal_date-before-14_10-or-15_5-vu-verify.out} (100%) create mode 100644 test/JDBC/input/babel_smalldatetime_before_15-5.sql create mode 100644 test/JDBC/input/dateFunctions/dateadd-vu-cleanup.sql create mode 100644 test/JDBC/input/dateFunctions/dateadd-vu-prepare.sql create mode 100644 test/JDBC/input/dateFunctions/dateadd-vu-verify.sql create mode 100644 test/JDBC/input/dateFunctions/datediff-vu-cleanup.sql create mode 100644 test/JDBC/input/dateFunctions/datediff-vu-prepare.sql create mode 100644 test/JDBC/input/dateFunctions/datediff-vu-verify.sql rename test/JDBC/input/functions/{datediff_internal_date-vu-cleanup.sql => datediff_internal_date-before-14_10-or-15_5-vu-cleanup.sql} (100%) rename test/JDBC/input/functions/{datediff_internal_date-vu-prepare.sql => datediff_internal_date-before-14_10-or-15_5-vu-prepare.sql} (100%) rename test/JDBC/input/functions/{datediff_internal_date-vu-verify.sql => datediff_internal_date-before-14_10-or-15_5-vu-verify.sql} (100%) diff --git a/contrib/babelfishpg_common/src/datetime.c b/contrib/babelfishpg_common/src/datetime.c index 97d74acf14..7bcacd2ef5 100644 --- a/contrib/babelfishpg_common/src/datetime.c +++ b/contrib/babelfishpg_common/src/datetime.c @@ -15,7 +15,8 @@ #include "utils/numeric.h" #include "utils/timestamp.h" #include "libpq/pqformat.h" - +#include "parser/scansup.h" +#include "common/int.h" #include "miscadmin.h" #include "datetime.h" @@ -52,9 +53,15 @@ PG_FUNCTION_INFO_V1(datetime_to_float4); PG_FUNCTION_INFO_V1(datetime_to_float8); PG_FUNCTION_INFO_V1(datetime_to_numeric); +PG_FUNCTION_INFO_V1(dateadd_datetime); +PG_FUNCTION_INFO_V1(timestamp_diff); +PG_FUNCTION_INFO_V1(timestamp_diff_big); + void CheckDatetimeRange(const Timestamp time); void CheckDatetimePrecision(fsec_t fsec); +#define DTK_NANO 32 + Datum datetime_in_str(char *str) { @@ -797,4 +804,582 @@ datetime_to_numeric(PG_FUNCTION_ARGS) Timestamp timestamp_left = PG_GETARG_TIMESTAMP(0); float8 result = calculateDaysFromDefaultDatetime(timestamp_left); PG_RETURN_NUMERIC(DirectFunctionCall1(float8_numeric, Float8GetDatum(result))); -} \ No newline at end of file +} + +/* + * Returns the difference of two timestamps based on a provided unit + * INT64 representation for bigints + */ +Datum +timestamp_diff(PG_FUNCTION_ARGS) +{ + + text *field = PG_GETARG_TEXT_PP(0); + Timestamp timestamp1 = PG_GETARG_TIMESTAMP(1); + Timestamp timestamp2 = PG_GETARG_TIMESTAMP(2); + int32 diff = -1; + int tm1Valid; + int tm2Valid; + int32 yeardiff; + int32 monthdiff; + int32 daydiff; + int32 hourdiff; + int32 minutediff; + int32 seconddiff; + int32 millisecdiff; + int32 microsecdiff; + struct pg_tm tt1, + *tm1 = &tt1; + fsec_t fsec1; + struct pg_tm tt2, + *tm2 = &tt2; + fsec_t fsec2; + int type, + val; + char *lowunits; + bool overflow = false; + bool validDateDiff = true; + + tm1Valid = timestamp2tm(timestamp1, NULL, tm1, &fsec1, NULL, NULL); + tm2Valid = timestamp2tm(timestamp2, NULL, tm2, &fsec2, NULL, NULL); + + lowunits = downcase_truncate_identifier(VARDATA_ANY(field), + VARSIZE_ANY_EXHDR(field), + false); + + type = DecodeUnits(0, lowunits, &val); + + // Decode units does not handle doy properly + if(strncmp(lowunits, "doy", 3) == 0) { + type = UNITS; + val = DTK_DOY; + } + + if(strncmp(lowunits, "nanosecond", 11) == 0) { + type = UNITS; + val = DTK_NANO; + } + if(strncmp(lowunits, "weekday", 7) == 0) { + type = UNITS; + val = DTK_DAY; + } + + if(type == UNITS) { + if(tm1Valid == 0 && tm2Valid == 0) { + switch(val) { + case DTK_YEAR: + diff = tm2->tm_year - tm1->tm_year; + break; + case DTK_QUARTER: + yeardiff = tm2->tm_year - tm1->tm_year; + monthdiff = tm2->tm_mon - tm1->tm_mon; + diff = (yeardiff * 12 + monthdiff) / 3; + break; + case DTK_MONTH: + yeardiff = tm2->tm_year - tm1->tm_year; + monthdiff = tm2->tm_mon - tm1->tm_mon; + diff = yeardiff * 12 + monthdiff; + break; + case DTK_WEEK: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + diff = daydiff / 7; + if(daydiff % 7 >= 4) + diff++; + break; + case DTK_DAY: + case DTK_DOY: + diff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + break; + case DTK_HOUR: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + diff = hourdiff; + break; + case DTK_MINUTE: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int32_multiply_add(hourdiff, 60, &minutediff))); + diff = minutediff; + break; + case DTK_SECOND: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int32_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int32_multiply_add(minutediff, 60, &seconddiff))); + diff = seconddiff; + break; + case DTK_MILLISEC: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + millisecdiff = (fsec2 / 1000) - (fsec1 / 1000); + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int32_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int32_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int32_multiply_add(seconddiff, 1000, &millisecdiff))); + diff = millisecdiff; + break; + case DTK_MICROSEC: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + microsecdiff = fsec2 - fsec1; + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int32_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int32_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int32_multiply_add(seconddiff, 1000000, µsecdiff))); + diff = microsecdiff; + break; + case DTK_NANO: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + microsecdiff = fsec2 - fsec1; + overflow = (overflow || !(int32_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int32_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int32_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int32_multiply_add(seconddiff, 1000000, µsecdiff))); + overflow = (overflow || (pg_mul_s32_overflow(microsecdiff, 1000, &diff))); + break; + default: + validDateDiff = false; + break; + } + } + else { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range"))); + } + } else { + validDateDiff = false; + } + + if(!validDateDiff) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\'%s\' is not a recognized %s option", lowunits, "datediff"))); + } + if(overflow) { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart"))); + } + + PG_RETURN_INT32(diff); +} + +/* + * Returns the difference of two timestamps based on a provided unit + * INT64 representation for bigints + */ +Datum +timestamp_diff_big(PG_FUNCTION_ARGS) +{ + text *field = PG_GETARG_TEXT_PP(0); + Timestamp timestamp1 = PG_GETARG_TIMESTAMP(1); + Timestamp timestamp2 = PG_GETARG_TIMESTAMP(2); + int64 diff = -1; + int tm1Valid; + int tm2Valid; + int64 yeardiff; + int64 monthdiff; + int64 daydiff; + int64 hourdiff; + int64 minutediff; + int64 seconddiff; + int64 millisecdiff; + int64 microsecdiff; + struct pg_tm tt1, + *tm1 = &tt1; + fsec_t fsec1; + struct pg_tm tt2, + *tm2 = &tt2; + fsec_t fsec2; + int type, + val; + char *lowunits; + bool overflow = false; + bool validDateDiff = true; + + tm1Valid = timestamp2tm(timestamp1, NULL, tm1, &fsec1, NULL, NULL); + tm2Valid = timestamp2tm(timestamp2, NULL, tm2, &fsec2, NULL, NULL); + + lowunits = downcase_truncate_identifier(VARDATA_ANY(field), + VARSIZE_ANY_EXHDR(field), + false); + + type = DecodeUnits(0, lowunits, &val); + + // Decode units does not handle doy or nano properly + if(strncmp(lowunits, "doy", 3) == 0) { + type = UNITS; + val = DTK_DOY; + } + if(strncmp(lowunits, "nanosecond", 11) == 0) { + type = UNITS; + val = DTK_NANO; + } + if(strncmp(lowunits, "weekday", 7) == 0) { + type = UNITS; + val = DTK_DAY; + } + + if(type == UNITS) { + if(tm1Valid == 0 && tm2Valid == 0) { + switch(val) + { + case DTK_YEAR: + diff = tm2->tm_year - tm1->tm_year; + break; + case DTK_QUARTER: + yeardiff = tm2->tm_year - tm1->tm_year; + monthdiff = tm2->tm_mon - tm1->tm_mon; + diff = (yeardiff * 12 + monthdiff) / 3; + break; + case DTK_MONTH: + yeardiff = tm2->tm_year - tm1->tm_year; + monthdiff = tm2->tm_mon - tm1->tm_mon; + diff = yeardiff * 12 + monthdiff; + break; + case DTK_WEEK: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + diff = daydiff / 7; + if(daydiff % 7 >= 4) + diff++; + break; + case DTK_DAY: + case DTK_DOY: + diff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + break; + case DTK_HOUR: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + diff = hourdiff; + break; + case DTK_MINUTE: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int64_multiply_add(hourdiff, 60, &minutediff))); + diff = minutediff; + break; + case DTK_SECOND: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int64_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int64_multiply_add(minutediff, 60, &seconddiff))); + diff = seconddiff; + break; + case DTK_MILLISEC: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + millisecdiff = (fsec2 / 1000) - (fsec1 / 1000); + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int64_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int64_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int64_multiply_add(seconddiff, 1000, &millisecdiff))); + diff = millisecdiff; + break; + case DTK_MICROSEC: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + microsecdiff = fsec2 - fsec1; + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int64_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int64_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int64_multiply_add(seconddiff, 1000000, µsecdiff))); + diff = microsecdiff; + break; + case DTK_NANO: + daydiff = days_in_date(tm2->tm_mday, tm2->tm_mon, tm2->tm_year) - days_in_date(tm1->tm_mday, tm1->tm_mon, tm1->tm_year); + hourdiff = tm2->tm_hour - tm1->tm_hour; + minutediff = tm2->tm_min - tm1->tm_min; + seconddiff = tm2->tm_sec - tm1->tm_sec; + microsecdiff = fsec2 - fsec1; + overflow = (overflow || !(int64_multiply_add(daydiff, 24, &hourdiff))); + overflow = (overflow || !(int64_multiply_add(hourdiff, 60, &minutediff))); + overflow = (overflow || !(int64_multiply_add(minutediff, 60, &seconddiff))); + overflow = (overflow || !(int64_multiply_add(seconddiff, 1000000, µsecdiff))); + overflow = (overflow || (pg_mul_s64_overflow(microsecdiff, 1000, &diff))); + break; + default: + validDateDiff = false; + } + } + else { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range"))); + } + } else { + validDateDiff = false; + } + + if(!validDateDiff) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\'%s\' is not a recognized %s option", lowunits, "datediff"))); + } + if(overflow) { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart"))); + } + + PG_RETURN_INT64(diff); +} + +bool +int64_multiply_add(int64 val, int64 multiplier, int64 *sum) +{ + int64 product; + + if (pg_mul_s64_overflow(val, multiplier, &product) || + pg_add_s64_overflow(*sum, product, sum)) + return false; + return true; +} + +bool +int32_multiply_add(int32 val, int32 multiplier, int32 *sum) +{ + int32 product; + + if (pg_mul_s32_overflow(val, multiplier, &product) || + pg_add_s32_overflow(*sum, product, sum)) + return false; + return true; +} + +int days_in_date(int day, int month, int year) { + int n1 = year * 365 + day; + for(int i = 1; i < month; i++) { + if(i == 2) + n1 += 28; + else if(i == 4 || i == 6 || i == 9 || i == 11) + n1 += 30; + else + n1 += 31; + } + if(month <= 2) + year -= 1; + n1 += (year / 4 - year / 100 + year / 400); + return n1; +} + +char *datetypeName(int num) { + char* ret; + switch(num) { + case 0: + ret = "time"; + break; + case 1: + ret = "date"; + break; + case 2: + ret = "smalldatetime"; + break; + case 3: + ret = "datetime"; + break; + case 4: + ret = "datetime2"; + break; + default: + ret = "unknown"; + } + return ret; +} + +Datum +dateadd_datetime(PG_FUNCTION_ARGS) { + text *field = PG_GETARG_TEXT_PP(0); + int num = PG_GETARG_INT32(1); + enum Datetimetype { + TIME, + DATE, + SMALLDATETIME, + DATETIME, + DATETIME2 + }; + Timestamp timestamp; + enum Datetimetype dttype = PG_GETARG_INT32(3); + char *lowunits; + int type, + val; + Timestamp result; + Interval *interval; + bool validDateAdd = true; + bool incompatibleDatePart = false; + + switch(dttype) { + case TIME: + timestamp = DirectFunctionCall1(time_datetime, (TimeADT) PG_GETARG_TIMEADT(2)); + break; + case DATE: + timestamp = DirectFunctionCall1(date_datetime, (DateADT) PG_GETARG_DATEADT(2)); + break; + default: + timestamp = PG_GETARG_TIMESTAMP(2); + } + + lowunits = downcase_truncate_identifier(VARDATA_ANY(field), + VARSIZE_ANY_EXHDR(field), + false); + + type = DecodeUnits(0, lowunits, &val); + + if(strncmp(lowunits, "doy", 3) == 0 || strncmp(lowunits, "dayofyear", 9) == 0) { + type = UNITS; + val = DTK_DOY; + } + if(strncmp(lowunits, "nanosecond", 11) == 0) { + type = UNITS; + val = DTK_NANO; + } + if(strncmp(lowunits, "weekday", 7) == 0) { + type = UNITS; + val = DTK_DAY; + } + + + if(type == UNITS) { + switch(val) { + case DTK_YEAR: + if(dttype == TIME) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, num, 0, 0, 0, 0, 0, 0); + break; + case DTK_QUARTER: + if(dttype == TIME) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, num * 3, 0, 0, 0, 0, 0); + break; + case DTK_MONTH: + if(dttype == TIME) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, num, 0, 0, 0, 0, 0); + break; + case DTK_WEEK: + if(dttype == TIME) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, num, 0, 0, 0, 0); + break; + case DTK_DAY: + case DTK_DOY: + if(dttype == TIME) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, num, 0, 0, 0); + break; + case DTK_HOUR: + if(dttype == DATE) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, num, 0, 0); + break; + case DTK_MINUTE: + if(dttype == DATE) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, num, 0); + break; + case DTK_SECOND: + if(dttype == DATE) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum(num)); + break; + case DTK_MILLISEC: + if(dttype == DATE) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.001)); + break; + case DTK_MICROSEC: + if(dttype == SMALLDATETIME || dttype == DATETIME || dttype == DATE) { + incompatibleDatePart = true; + break; + } + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.000001)); + break; + case DTK_NANO: + if(dttype == SMALLDATETIME || dttype == DATETIME || dttype == DATE) { + incompatibleDatePart = true; + break; + } + num = num / 1000 * 1000; // Floors the number to avoid incorrect rounding + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.000000001)); + break; + default: + validDateAdd = false; + break; + } + } else { + validDateAdd = false; + } + + if(incompatibleDatePart) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("The datepart %s is not supported by date function %s for data type %s.", lowunits, "dateadd", datetypeName(dttype)))); + } + + if(!validDateAdd) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\'%s\' is not a recognized %s option", lowunits, "dateadd"))); + } + + PG_TRY(); + { + result = DirectFunctionCall2(timestamp_pl_interval, timestamp, PointerGetDatum(interval)); + + /* + * This check is required because the range of valid timestamps + * is greater than the range of valid datetimes + */ + CheckDatetimeRange(result); + } + PG_CATCH(); + { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("Adding a value to a \'%s\' column caused an overflow.", datetypeName(dttype)))); + } + PG_END_TRY(); + + PG_RETURN_TIMESTAMP(result); +} diff --git a/contrib/babelfishpg_common/src/datetime.h b/contrib/babelfishpg_common/src/datetime.h index 4d50efa658..592677cb05 100644 --- a/contrib/babelfishpg_common/src/datetime.h +++ b/contrib/babelfishpg_common/src/datetime.h @@ -32,6 +32,12 @@ extern Timestamp initializeToDefaultDatetime(void); extern double calculateDaysFromDefaultDatetime(Timestamp timestamp_left); extern int roundFractionalSeconds(int fractseconds); +extern int days_in_date(int day, int month, int year); +extern char* datetypeName(int num); + +extern bool int64_multiply_add(int64 val, int64 multiplier, int64 *sum); +extern bool int32_multiply_add(int32 val, int32 multiplier, int32 *sum); + /* Range-check a datetime */ #define IS_VALID_DATETIME(t) (MIN_DATETIME <= (t) && (t) < END_DATETIME) diff --git a/contrib/babelfishpg_common/src/datetimeoffset.c b/contrib/babelfishpg_common/src/datetimeoffset.c index 78242fac67..1041e0e2c5 100644 --- a/contrib/babelfishpg_common/src/datetimeoffset.c +++ b/contrib/babelfishpg_common/src/datetimeoffset.c @@ -13,6 +13,7 @@ #include "utils/datetime.h" #include "libpq/pqformat.h" #include "utils/timestamp.h" +#include "parser/scansup.h" #include "fmgr.h" #include "miscadmin.h" @@ -63,6 +64,9 @@ PG_FUNCTION_INFO_V1(datetimeoffset_datetime2); PG_FUNCTION_INFO_V1(datetimeoffset_scale); PG_FUNCTION_INFO_V1(get_datetimeoffset_tzoffset_internal); +PG_FUNCTION_INFO_V1(dateadd_datetimeoffset); + +#define DTK_NANO 32 /* datetimeoffset_in() @@ -832,3 +836,104 @@ EncodeDatetimeoffsetTimezone(char *str, int tz, int style) *tmp = '\0'; } + +Datum +dateadd_datetimeoffset(PG_FUNCTION_ARGS) { + text *field = PG_GETARG_TEXT_PP(0); + int num = PG_GETARG_INT32(1); + tsql_datetimeoffset *init_startdate = PG_GETARG_DATETIMEOFFSET(2); + bool validDateAdd = true; + char *lowunits; + int type, + val; + tsql_datetimeoffset *result; + Interval *interval; + int timezone = DirectFunctionCall1(get_datetimeoffset_tzoffset_internal, DatetimeoffsetGetDatum(init_startdate)) * 2; + tsql_datetimeoffset *startdate = (tsql_datetimeoffset *) DirectFunctionCall2(datetimeoffset_pl_interval, DatetimeoffsetGetDatum(init_startdate), DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, timezone, 0)); + + + lowunits = downcase_truncate_identifier(VARDATA_ANY(field), + VARSIZE_ANY_EXHDR(field), + false); + + type = DecodeUnits(0, lowunits, &val); + + if(strncmp(lowunits, "doy", 3) == 0 || strncmp(lowunits, "dayofyear", 9) == 0) { + type = UNITS; + val = DTK_DOY; + } + + if(strncmp(lowunits, "nanosecond", 11) == 0) { + type = UNITS; + val = DTK_NANO; + } + if(strncmp(lowunits, "weekday", 7) == 0) { + type = UNITS; + val = DTK_DAY; + } + + if(type == UNITS) { + switch(val) { + case DTK_YEAR: + interval = (Interval *) DirectFunctionCall7(make_interval, num, 0, 0, 0, 0, 0, 0); + break; + case DTK_QUARTER: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, num * 3, 0, 0, 0, 0, 0); + break; + case DTK_MONTH: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, num, 0, 0, 0, 0, 0); + break; + case DTK_WEEK: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, num, 0, 0, 0, 0); + break; + case DTK_DAY: + case DTK_DOY: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, num, 0, 0, 0); + break; + case DTK_HOUR: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, num, 0, 0); + break; + case DTK_MINUTE: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, num, 0); + break; + case DTK_SECOND: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum(num)); + break; + case DTK_MILLISEC: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.001)); + break; + case DTK_MICROSEC: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.000001)); + break; + case DTK_NANO: + interval = (Interval *) DirectFunctionCall7(make_interval, 0, 0, 0, 0, 0, 0, Float8GetDatum((float) num * 0.000000001)); + break; + default: + validDateAdd = false; + break; + } + } else { + validDateAdd = false; + } + + if(!validDateAdd) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\'%s\' is not a recognized %s option", lowunits, "dateadd"))); + } + + PG_TRY(); + { + result = (tsql_datetimeoffset *) DirectFunctionCall2(datetimeoffset_pl_interval, DatetimeoffsetGetDatum(startdate), PointerGetDatum(interval)); + + } + PG_CATCH(); + { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("Adding a value to a \'%s\' column caused an overflow.", "datetimeoffset"))); + } + PG_END_TRY(); + + PG_RETURN_DATETIMEOFFSET(result); +} \ No newline at end of file diff --git a/contrib/babelfishpg_tds/error_mapping.txt b/contrib/babelfishpg_tds/error_mapping.txt index 631eb52cfb..6f6f6ee4ca 100644 --- a/contrib/babelfishpg_tds/error_mapping.txt +++ b/contrib/babelfishpg_tds/error_mapping.txt @@ -179,4 +179,7 @@ XX000 ERRCODE_INTERNAL_ERROR "The table-valued parameter \"%s\" must be declared 0A000 ERRCODE_FEATURE_NOT_SUPPORTED "Column name or number of supplied values does not match table definition." SQL_ERROR_213 16 42501 ERRCODE_INSUFFICIENT_PRIVILEGE "Only members of the sysadmin role can execute this stored procedure." SQL_ERROR_15003 16 42809 ERRCODE_WRONG_OBJECT_TYPE "The target \"%s\" of the OUTPUT INTO clause cannot be a view or common table expression." SQL_ERROR_330 16 - +22008 ERRCODE_DATETIME_VALUE_OUT_OF_RANGE "The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart" SQL_ERROR_535 16 +22023 ERRCODE_INVALID_PARAMETER_VALUE "\'%s\' is not a recognized %s option" SQL_ERROR_155 15 +22023 ERRCODE_INVALID_PARAMETER_VALUE "The datepart %s is not supported by date function %s for data type %s." SQL_ERROR_9810 16 +22008 ERRCODE_DATETIME_VALUE_OUT_OF_RANGE "Adding a value to a \'%s\' column caused an overflow." SQL_ERROR_517 16 diff --git a/contrib/babelfishpg_tsql/sql/sys_functions.sql b/contrib/babelfishpg_tsql/sql/sys_functions.sql index aa97647955..e4a7070b54 100644 --- a/contrib/babelfishpg_tsql/sql/sys_functions.sql +++ b/contrib/babelfishpg_tsql/sql/sys_functions.sql @@ -1556,7 +1556,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal_date(datepart, startdate, enddate) AS INTEGER); + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1565,7 +1565,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP) AS INTEGER); + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1574,7 +1574,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal_df(datepart, startdate, enddate) AS INTEGER); + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1583,7 +1583,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP) AS INTEGER); + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1592,7 +1592,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP) AS INTEGER); + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1601,7 +1601,7 @@ CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdat AS $body$ BEGIN - return CAST(sys.datediff_internal(datepart, startdate, enddate) AS INTEGER); + return sys.datediff_internal(datepart, startdate, enddate); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1611,7 +1611,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal_date(datepart, startdate, enddate); + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1620,7 +1620,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1629,7 +1629,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal_df(datepart, startdate, enddate); + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1638,7 +1638,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1647,7 +1647,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1656,7 +1656,7 @@ CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN star AS $body$ BEGIN - return sys.datediff_internal(datepart, startdate, enddate); + return sys.datediff_internal_big(datepart, startdate, enddate); END $body$ LANGUAGE plpgsql IMMUTABLE; @@ -1883,384 +1883,51 @@ LANGUAGE plpgsql IMMUTABLE; but the error shows : operator does not exist: sys.datetimeoffset + interval. As the result, we should not use '+' directly but should keep using OPERATOR(sys.+) when input date is in datetimeoffset type. */ -CREATE OR REPLACE FUNCTION sys.dateadd_internal_df(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate datetimeoffset) RETURNS datetimeoffset AS $$ -DECLARE - timezone INTEGER; -BEGIN - timezone = sys.babelfish_get_datetimeoffset_tzoffset(startdate)::INTEGER * 2; - startdate = startdate OPERATOR(sys.+) make_interval(mins => timezone); - CASE datepart - WHEN 'year' THEN - RETURN startdate OPERATOR(sys.+) make_interval(years => num); - WHEN 'quarter' THEN - RETURN startdate OPERATOR(sys.+) make_interval(months => num * 3); - WHEN 'month' THEN - RETURN startdate OPERATOR(sys.+) make_interval(months => num); - WHEN 'dayofyear', 'y' THEN - RETURN startdate OPERATOR(sys.+) make_interval(days => num); - WHEN 'day' THEN - RETURN startdate OPERATOR(sys.+) make_interval(days => num); - WHEN 'week' THEN - RETURN startdate OPERATOR(sys.+) make_interval(weeks => num); - WHEN 'weekday' THEN - RETURN startdate OPERATOR(sys.+) make_interval(days => num); - WHEN 'hour' THEN - RETURN startdate OPERATOR(sys.+) make_interval(hours => num); - WHEN 'minute' THEN - RETURN startdate OPERATOR(sys.+) make_interval(mins => num); - WHEN 'second' THEN - RETURN startdate OPERATOR(sys.+) make_interval(secs => num); - WHEN 'millisecond' THEN - RETURN startdate OPERATOR(sys.+) make_interval(secs => (num::numeric) * 0.001); - WHEN 'microsecond' THEN - RETURN startdate OPERATOR(sys.+) make_interval(secs => (num::numeric) * 0.000001); - WHEN 'nanosecond' THEN - -- Best we can do - Postgres does not support nanosecond precision - RETURN startdate OPERATOR(sys.+) make_interval(secs => TRUNC((num::numeric)* 0.000000001, 6)); - ELSE - RAISE EXCEPTION '"%" is not a recognized dateadd option.', datepart; - END CASE; -END; -$$ +CREATE OR REPLACE FUNCTION sys.dateadd_internal_df(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate datetimeoffset) +RETURNS datetimeoffset AS +'babelfishpg_common', 'dateadd_datetimeoffset' STRICT -LANGUAGE plpgsql IMMUTABLE; +LANGUAGE C IMMUTABLE PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.dateadd_internal(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate ANYELEMENT) RETURNS ANYELEMENT AS $$ BEGIN - IF pg_typeof(startdate) = 'date'::regtype AND - datepart IN ('hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond') THEN - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type date.', datepart; + IF pg_typeof(startdate) = 'time'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 0); END IF; - IF pg_typeof(startdate) = 'time'::regtype AND - datepart IN ('year', 'quarter', 'month', 'doy', 'day', 'week', 'weekday') THEN - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type time.', datepart; + IF pg_typeof(startdate) = 'date'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 1); END IF; - - CASE datepart - WHEN 'year' THEN - RETURN startdate + make_interval(years => num); - WHEN 'quarter' THEN - RETURN startdate + make_interval(months => num * 3); - WHEN 'month' THEN - RETURN startdate + make_interval(months => num); - WHEN 'dayofyear', 'y' THEN - RETURN startdate + make_interval(days => num); - WHEN 'day' THEN - RETURN startdate + make_interval(days => num); - WHEN 'week' THEN - RETURN startdate + make_interval(weeks => num); - WHEN 'weekday' THEN - RETURN startdate + make_interval(days => num); - WHEN 'hour' THEN - RETURN startdate + make_interval(hours => num); - WHEN 'minute' THEN - RETURN startdate + make_interval(mins => num); - WHEN 'second' THEN - RETURN startdate + make_interval(secs => num); - WHEN 'millisecond' THEN - RETURN startdate + make_interval(secs => (num::numeric) * 0.001); - WHEN 'microsecond' THEN - IF pg_typeof(startdate) = 'time'::regtype THEN - RETURN startdate + make_interval(secs => (num::numeric) * 0.000001); - ELSIF pg_typeof(startdate) = 'sys.datetime2'::regtype THEN - RETURN startdate + make_interval(secs => (num::numeric) * 0.000001); - ELSIF pg_typeof(startdate) = 'sys.smalldatetime'::regtype THEN - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type smalldatetime.', datepart; - ELSE - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type datetime.', datepart; - END IF; - WHEN 'nanosecond' THEN - IF pg_typeof(startdate) = 'time'::regtype THEN - RETURN startdate + make_interval(secs => TRUNC((num::numeric)* 0.000000001, 6)); - ELSIF pg_typeof(startdate) = 'sys.datetime2'::regtype THEN - RETURN startdate + make_interval(secs => TRUNC((num::numeric)* 0.000000001, 6)); - ELSIF pg_typeof(startdate) = 'sys.smalldatetime'::regtype THEN - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type smalldatetime.', datepart; - ELSE - RAISE EXCEPTION 'The datepart % is not supported by date function dateadd for data type datetime.', datepart; - END IF; - ELSE - RAISE EXCEPTION '''%'' is not a recognized dateadd option.', datepart; - END CASE; + IF pg_typeof(startdate) = 'sys.smalldatetime'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 2); + END IF; + IF (pg_typeof(startdate) = 'sys.datetime'::regtype or pg_typeof(startdate) = 'timestamp'::regtype) THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 3); + END IF; + IF pg_typeof(startdate) = 'sys.datetime2'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 4); + END IF; END; $$ STRICT LANGUAGE plpgsql IMMUTABLE; -CREATE OR REPLACE FUNCTION sys.datediff_internal_df(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) RETURNS BIGINT AS $$ -DECLARE - result BIGINT; - year_diff BIGINT; - month_diff BIGINT; - day_diff BIGINT; - hour_diff BIGINT; - minute_diff BIGINT; - second_diff BIGINT; - millisecond_diff BIGINT; - microsecond_diff BIGINT; - y1 BIGINT; - m1 BIGINT; - d1 BIGINT; - y2 BIGINT; - m2 BIGINT; - d2 BIGINT; -BEGIN - CASE datepart - WHEN 'year' THEN - year_diff = sys.datepart('year', enddate) - sys.datepart('year', startdate); - result = year_diff; - WHEN 'quarter' THEN - year_diff = sys.datepart('year', enddate) - sys.datepart('year', startdate); - month_diff = sys.datepart('month', enddate) - sys.datepart('month', startdate); - result = (year_diff * 12 + month_diff) / 3; - WHEN 'month' THEN - year_diff = sys.datepart('year', enddate) - sys.datepart('year', startdate); - month_diff = sys.datepart('month', enddate) - sys.datepart('month', startdate); - result = year_diff * 12 + month_diff; - WHEN 'doy', 'y' THEN - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - result = day_diff; - WHEN 'day' THEN - y1 = sys.datepart('year', enddate); - m1 = sys.datepart('month', enddate); - d1 = sys.datepart('day', enddate); - y2 = sys.datepart('year', startdate); - m2 = sys.datepart('month', startdate); - d2 = sys.datepart('day', startdate); - result = sys.num_days_in_date(d1, m1, y1) - sys.num_days_in_date(d2, m2, y2); - WHEN 'week' THEN - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - result = day_diff / 7; - WHEN 'hour' THEN - y1 = sys.datepart('year', enddate); - m1 = sys.datepart('month', enddate); - d1 = sys.datepart('day', enddate); - y2 = sys.datepart('year', startdate); - m2 = sys.datepart('month', startdate); - d2 = sys.datepart('day', startdate); - day_diff = sys.num_days_in_date(d1, m1, y1) - sys.num_days_in_date(d2, m2, y2); - hour_diff = sys.datepart('hour', enddate) - sys.datepart('hour', startdate); - result = day_diff * 24 + hour_diff; - WHEN 'minute' THEN - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - hour_diff = sys.datepart('hour', enddate OPERATOR(sys.-) startdate); - minute_diff = sys.datepart('minute', enddate OPERATOR(sys.-) startdate); - result = (day_diff * 24 + hour_diff) * 60 + minute_diff; - WHEN 'second' THEN - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - hour_diff = sys.datepart('hour', enddate OPERATOR(sys.-) startdate); - minute_diff = sys.datepart('minute', enddate OPERATOR(sys.-) startdate); - second_diff = TRUNC(sys.datepart('second', enddate OPERATOR(sys.-) startdate)); - result = ((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60 + second_diff; - WHEN 'millisecond' THEN - -- millisecond result from date_part by default contains second value, - -- so we do not need to add second_diff again - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - hour_diff = sys.datepart('hour', enddate OPERATOR(sys.-) startdate); - minute_diff = sys.datepart('minute', enddate OPERATOR(sys.-) startdate); - second_diff = TRUNC(sys.datepart('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(sys.datepart('millisecond', enddate OPERATOR(sys.-) startdate)); - result = (((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000 + millisecond_diff; - WHEN 'microsecond' THEN - -- microsecond result from date_part by default contains second and millisecond values, - -- so we do not need to add second_diff and millisecond_diff again - day_diff = sys.datepart('day', enddate OPERATOR(sys.-) startdate); - hour_diff = sys.datepart('hour', enddate OPERATOR(sys.-) startdate); - minute_diff = sys.datepart('minute', enddate OPERATOR(sys.-) startdate); - second_diff = TRUNC(sys.datepart('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(sys.datepart('millisecond', enddate OPERATOR(sys.-) startdate)); - microsecond_diff = TRUNC(sys.datepart('microsecond', enddate OPERATOR(sys.-) startdate)); - result = ((((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000) * 1000 + microsecond_diff; - WHEN 'nanosecond' THEN - -- Best we can do - Postgres does not support nanosecond precision - day_diff = sys.datepart('day', enddate - startdate); - hour_diff = sys.datepart('hour', enddate OPERATOR(sys.-) startdate); - minute_diff = sys.datepart('minute', enddate OPERATOR(sys.-) startdate); - second_diff = TRUNC(sys.datepart('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(sys.datepart('millisecond', enddate OPERATOR(sys.-) startdate)); - microsecond_diff = TRUNC(sys.datepart('microsecond', enddate OPERATOR(sys.-) startdate)); - result = (((((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000) * 1000 + microsecond_diff) * 1000; - ELSE - RAISE EXCEPTION '"%" is not a recognized datediff option.', datepart; - END CASE; - - return result; -END; -$$ +CREATE OR REPLACE FUNCTION sys.dateadd_internal_datetime(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate ANYELEMENT, IN datetimetype INT) +RETURNS TIMESTAMP AS +'babelfishpg_common', 'dateadd_datetime' STRICT -LANGUAGE plpgsql IMMUTABLE; - -CREATE OR REPLACE FUNCTION sys.datediff_internal_date(IN datepart PG_CATALOG.TEXT, IN startdate PG_CATALOG.date, IN enddate PG_CATALOG.date) RETURNS BIGINT AS $$ -DECLARE - result BIGINT; - year_diff BIGINT; - month_diff BIGINT; - day_diff BIGINT; - hour_diff BIGINT; - minute_diff BIGINT; - second_diff BIGINT; - millisecond_diff BIGINT; - microsecond_diff BIGINT; -BEGIN - CASE datepart - WHEN 'year' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - result = year_diff; - WHEN 'quarter' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - month_diff = date_part('month', enddate)::BIGINT - date_part('month', startdate)::BIGINT; - result = (year_diff * 12 + month_diff) / 3; - WHEN 'month' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - month_diff = date_part('month', enddate)::BIGINT - date_part('month', startdate)::BIGINT; - result = year_diff * 12 + month_diff; - -- for all intervals smaller than month, (DATE - DATE) already returns the integer number of days - -- between the dates, so just use that directly as the day_diff. There is no finer resolution - -- than days with the DATE type anyways. - WHEN 'doy', 'y' THEN - day_diff = enddate - startdate; - result = day_diff; - WHEN 'day' THEN - day_diff = enddate - startdate; - result = day_diff; - WHEN 'week' THEN - day_diff = enddate - startdate; - result = day_diff / 7; - WHEN 'hour' THEN - day_diff = enddate - startdate; - result = day_diff * 24; - WHEN 'minute' THEN - day_diff = enddate - startdate; - result = day_diff * 24 * 60; - WHEN 'second' THEN - day_diff = enddate - startdate; - result = day_diff * 24 * 60 * 60; - WHEN 'millisecond' THEN - -- millisecond result from date_part by default contains second value, - -- so we do not need to add second_diff again - day_diff = enddate - startdate; - result = day_diff * 24 * 60 * 60 * 1000; - WHEN 'microsecond' THEN - -- microsecond result from date_part by default contains second and millisecond values, - -- so we do not need to add second_diff and millisecond_diff again - day_diff = enddate - startdate; - result = day_diff * 24 * 60 * 60 * 1000 * 1000; - WHEN 'nanosecond' THEN - -- Best we can do - Postgres does not support nanosecond precision - day_diff = enddate - startdate; - result = day_diff * 24 * 60 * 60 * 1000 * 1000 * 1000; - ELSE - RAISE EXCEPTION '"%" is not a recognized datediff option.', datepart; - END CASE; +LANGUAGE C IMMUTABLE PARALLEL SAFE; - return result; -END; -$$ +CREATE OR REPLACE FUNCTION sys.datediff_internal_big(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) +RETURNS BIGINT AS +'babelfishpg_common', 'timestamp_diff_big' STRICT -LANGUAGE plpgsql IMMUTABLE; - -CREATE OR REPLACE FUNCTION sys.datediff_internal(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) RETURNS BIGINT AS $$ -DECLARE - result BIGINT; - year_diff BIGINT; - month_diff BIGINT; - day_diff BIGINT; - hour_diff BIGINT; - minute_diff BIGINT; - second_diff BIGINT; - millisecond_diff BIGINT; - microsecond_diff BIGINT; - y1 BIGINT; - m1 BIGINT; - d1 BIGINT; - y2 BIGINT; - m2 BIGINT; - d2 BIGINT; -BEGIN - CASE datepart - WHEN 'year' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - result = year_diff; - WHEN 'quarter' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - month_diff = date_part('month', enddate)::BIGINT - date_part('month', startdate)::BIGINT; - result = (year_diff * 12 + month_diff) / 3; - WHEN 'month' THEN - year_diff = date_part('year', enddate)::BIGINT - date_part('year', startdate)::BIGINT; - month_diff = date_part('month', enddate)::BIGINT - date_part('month', startdate)::BIGINT; - result = year_diff * 12 + month_diff; - WHEN 'doy', 'y' THEN - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - result = day_diff; - WHEN 'day' THEN - y1 = date_part('year', enddate)::BIGINT; - m1 = date_part('month', enddate)::BIGINT; - d1 = date_part('day', enddate)::BIGINT; - y2 = date_part('year', startdate)::BIGINT; - m2 = date_part('month', startdate)::BIGINT; - d2 = date_part('day', startdate)::BIGINT; - result = sys.num_days_in_date(d1, m1, y1) - sys.num_days_in_date(d2, m2, y2); - WHEN 'week' THEN - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - result = day_diff / 7; - WHEN 'hour' THEN - y1 = date_part('year', enddate)::BIGINT; - m1 = date_part('month', enddate)::BIGINT; - d1 = date_part('day', enddate)::BIGINT; - y2 = date_part('year', startdate)::BIGINT; - m2 = date_part('month', startdate)::BIGINT; - d2 = date_part('day', startdate)::BIGINT; - day_diff = sys.num_days_in_date(d1, m1, y1) - sys.num_days_in_date(d2, m2, y2); - hour_diff = date_part('hour', enddate)::BIGINT - date_part('hour', startdate)::BIGINT; - result = day_diff * 24 + hour_diff; - WHEN 'minute' THEN - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - hour_diff = date_part('hour', enddate OPERATOR(sys.-) startdate)::BIGINT; - minute_diff = date_part('minute', enddate OPERATOR(sys.-) startdate)::BIGINT; - result = (day_diff * 24 + hour_diff) * 60 + minute_diff; - WHEN 'second' THEN - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - hour_diff = date_part('hour', enddate OPERATOR(sys.-) startdate)::BIGINT; - minute_diff = date_part('minute', enddate OPERATOR(sys.-) startdate)::BIGINT; - second_diff = TRUNC(date_part('second', enddate OPERATOR(sys.-) startdate)); - result = ((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60 + second_diff; - WHEN 'millisecond' THEN - -- millisecond result from date_part by default contains second value, - -- so we do not need to add second_diff again - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - hour_diff = date_part('hour', enddate OPERATOR(sys.-) startdate)::BIGINT; - minute_diff = date_part('minute', enddate OPERATOR(sys.-) startdate)::BIGINT; - second_diff = TRUNC(date_part('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(date_part('millisecond', enddate OPERATOR(sys.-) startdate)); - result = (((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000 + millisecond_diff; - WHEN 'microsecond' THEN - -- microsecond result from date_part by default contains second and millisecond values, - -- so we do not need to add second_diff and millisecond_diff again - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - hour_diff = date_part('hour', enddate OPERATOR(sys.-) startdate)::BIGINT; - minute_diff = date_part('minute', enddate OPERATOR(sys.-) startdate)::BIGINT; - second_diff = TRUNC(date_part('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(date_part('millisecond', enddate OPERATOR(sys.-) startdate)); - microsecond_diff = TRUNC(date_part('microsecond', enddate OPERATOR(sys.-) startdate)); - result = ((((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000) * 1000 + microsecond_diff; - WHEN 'nanosecond' THEN - -- Best we can do - Postgres does not support nanosecond precision - day_diff = date_part('day', enddate OPERATOR(sys.-) startdate)::BIGINT; - hour_diff = date_part('hour', enddate OPERATOR(sys.-) startdate)::BIGINT; - minute_diff = date_part('minute', enddate OPERATOR(sys.-) startdate)::BIGINT; - second_diff = TRUNC(date_part('second', enddate OPERATOR(sys.-) startdate)); - millisecond_diff = TRUNC(date_part('millisecond', enddate OPERATOR(sys.-) startdate)); - microsecond_diff = TRUNC(date_part('microsecond', enddate OPERATOR(sys.-) startdate)); - result = (((((day_diff * 24 + hour_diff) * 60 + minute_diff) * 60) * 1000) * 1000 + microsecond_diff) * 1000; - ELSE - RAISE EXCEPTION '"%" is not a recognized datediff option.', datepart; - END CASE; +LANGUAGE C IMMUTABLE PARALLEL SAFE; - return result; -END; -$$ +CREATE OR REPLACE FUNCTION sys.datediff_internal(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) +RETURNS INT AS +'babelfishpg_common', 'timestamp_diff' STRICT -LANGUAGE plpgsql IMMUTABLE; +LANGUAGE C IMMUTABLE PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.datename(IN dp PG_CATALOG.TEXT, IN arg anyelement) RETURNS TEXT AS $BODY$ diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql index 05f0aadbbc..fe14153457 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql @@ -4329,6 +4329,178 @@ AS 'babelfishpg_tsql', 'sysdatetimeoffset' LANGUAGE C STABLE; GRANT EXECUTE ON FUNCTION sys.sysdatetimeoffset() TO PUBLIC; +ALTER FUNCTION sys.datediff_internal(PG_CATALOG.TEXT, anyelement, anyelement) RENAME TO datediff_internal_deprecated_3_4_0; +CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'datediff_internal_deprecated_3_4_0'); + +ALTER FUNCTION sys.datediff_internal_df(PG_CATALOG.TEXT, anyelement, anyelement) RENAME TO datediff_internal_df_deprecated_in_3_4_0; +CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'datediff_internal_df_deprecated_in_3_4_0'); + +ALTER FUNCTION sys.datediff_internal_date(PG_CATALOG.TEXT, PG_CATALOG.date, PG_CATALOG.date) RENAME TO datediff_internal_date_deprecated_in_3_4_0; +CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'datediff_internal_date_deprecated_in_3_4_0'); + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate PG_CATALOG.date, IN enddate PG_CATALOG.date) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetime, IN enddate sys.datetime) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetimeoffset, IN enddate sys.datetimeoffset) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetime2, IN enddate sys.datetime2) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate sys.smalldatetime, IN enddate sys.smalldatetime) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff(IN datepart PG_CATALOG.TEXT, IN startdate PG_CATALOG.time, IN enddate PG_CATALOG.time) RETURNS INTEGER +AS +$body$ +BEGIN + return sys.datediff_internal(datepart, startdate, enddate); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +-- datediff big +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate PG_CATALOG.date, IN enddate PG_CATALOG.date) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetime, IN enddate sys.datetime) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetimeoffset, IN enddate sys.datetimeoffset) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate sys.datetime2, IN enddate sys.datetime2) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate sys.smalldatetime, IN enddate sys.smalldatetime) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate::TIMESTAMP, enddate::TIMESTAMP); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.datediff_big(IN datepart PG_CATALOG.TEXT, IN startdate PG_CATALOG.time, IN enddate PG_CATALOG.time) RETURNS BIGINT +AS +$body$ +BEGIN + return sys.datediff_internal_big(datepart, startdate, enddate); +END +$body$ +LANGUAGE plpgsql IMMUTABLE; + + +/* + This function is needed when input date is datetimeoffset type. When running the following query in postgres using tsql dialect, it faied. + select dateadd(minute, -70, '2016-12-26 00:30:05.523456+8'::datetimeoffset); + We tried to merge this function with sys.dateadd_internal by using '+' when adding interval to datetimeoffset, + but the error shows : operator does not exist: sys.datetimeoffset + interval. As the result, we should not use '+' directly + but should keep using OPERATOR(sys.+) when input date is in datetimeoffset type. +*/ +CREATE OR REPLACE FUNCTION sys.dateadd_internal_df(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate datetimeoffset) +RETURNS datetimeoffset AS +'babelfishpg_common', 'dateadd_datetimeoffset' +STRICT +LANGUAGE C IMMUTABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.dateadd_internal(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate ANYELEMENT) RETURNS ANYELEMENT AS $$ +BEGIN + IF pg_typeof(startdate) = 'time'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 0); + END IF; + IF pg_typeof(startdate) = 'date'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 1); + END IF; + IF pg_typeof(startdate) = 'sys.smalldatetime'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 2); + END IF; + IF (pg_typeof(startdate) = 'sys.datetime'::regtype or pg_typeof(startdate) = 'timestamp'::regtype) THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 3); + END IF; + IF pg_typeof(startdate) = 'sys.datetime2'::regtype THEN + return sys.dateadd_internal_datetime(datepart, num, startdate, 4); + END IF; +END; +$$ +STRICT +LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION sys.dateadd_internal_datetime(IN datepart PG_CATALOG.TEXT, IN num INTEGER, IN startdate ANYELEMENT, IN datetimetype INT) +RETURNS TIMESTAMP AS +'babelfishpg_common', 'dateadd_datetime' +STRICT +LANGUAGE C IMMUTABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.datediff_internal_big(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) +RETURNS BIGINT AS +'babelfishpg_common', 'timestamp_diff_big' +STRICT +LANGUAGE C IMMUTABLE PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.datediff_internal(IN datepart PG_CATALOG.TEXT, IN startdate anyelement, IN enddate anyelement) +RETURNS INT AS +'babelfishpg_common', 'timestamp_diff' +STRICT +LANGUAGE C IMMUTABLE PARALLEL SAFE; + -- Drops the temporary procedure used by the upgrade script. -- Please have this be one of the last statements executed in this upgrade script. DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar); diff --git a/contrib/babelfishpg_tsql/src/err_handler.c b/contrib/babelfishpg_tsql/src/err_handler.c index d4242adc76..631745e6dc 100644 --- a/contrib/babelfishpg_tsql/src/err_handler.c +++ b/contrib/babelfishpg_tsql/src/err_handler.c @@ -131,7 +131,10 @@ is_ignorable_error(int pg_error_code, uint8_t override_flag) case SQL_ERROR_8145: case SQL_ERROR_8146: case SQL_ERROR_213: - case SQL_ERROR_6615: + case SQL_ERROR_6615: + case SQL_ERROR_155: + case SQL_ERROR_9810: + case SQL_ERROR_535: case SQL_ERROR_15003: { elog(DEBUG1, "TSQL TXN is_ignorable_error %d", latest_error_code); diff --git a/contrib/babelfishpg_tsql/src/err_handler.h b/contrib/babelfishpg_tsql/src/err_handler.h index 687bd393eb..1e4c6049b7 100644 --- a/contrib/babelfishpg_tsql/src/err_handler.h +++ b/contrib/babelfishpg_tsql/src/err_handler.h @@ -38,6 +38,7 @@ uint8_t override_txn_behaviour(PLtsql_stmt *stmt); #define SQL_ERROR_141 141 #define SQL_ERROR_142 142 #define SQL_ERROR_153 153 +#define SQL_ERROR_155 155 #define SQL_ERROR_180 180 #define SQL_ERROR_201 201 #define SQL_ERROR_206 206 @@ -58,6 +59,7 @@ uint8_t override_txn_behaviour(PLtsql_stmt *stmt); #define SQL_ERROR_512 512 #define SQL_ERROR_515 515 #define SQL_ERROR_517 517 +#define SQL_ERROR_535 535 #define SQL_ERROR_545 545 #define SQL_ERROR_547 547 #define SQL_ERROR_550 550 @@ -135,6 +137,7 @@ uint8_t override_txn_behaviour(PLtsql_stmt *stmt); #define SQL_ERROR_9441 9441 #define SQL_ERROR_9451 9451 #define SQL_ERROR_9809 9809 +#define SQL_ERROR_9810 9810 #define SQL_ERROR_10610 10610 #define SQL_ERROR_10727 10727 #define SQL_ERROR_10733 10733 diff --git a/test/JDBC/expected/BABEL-2812-vu-verify.out b/test/JDBC/expected/BABEL-2812-vu-verify.out index af56128db0..7752d63442 100644 --- a/test/JDBC/expected/BABEL-2812-vu-verify.out +++ b/test/JDBC/expected/BABEL-2812-vu-verify.out @@ -282,7 +282,7 @@ SELECT * FROM babel_2812_vu_v32 GO ~~START~~ int -51 +52 ~~END~~ SELECT * FROM babel_2812_vu_v33 @@ -323,9 +323,9 @@ int -- should overflow SELECT * FROM babel_2812_vu_v38 GO -~~ERROR (Code: 8115)~~ +~~ERROR (Code: 535)~~ -~~ERROR (Message: integer out of range)~~ +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ -- smaller interval for millisecond SELECT * FROM babel_2812_vu_v39 @@ -338,9 +338,9 @@ int -- should overflow SELECT * FROM babel_2812_vu_v40 GO -~~ERROR (Code: 8115)~~ +~~ERROR (Code: 535)~~ -~~ERROR (Message: integer out of range)~~ +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ -- microsecond and nanosecond can only handle diff of 0 for date type SELECT * FROM babel_2812_vu_v41 diff --git a/test/JDBC/expected/BABEL-3474-vu-verify.out b/test/JDBC/expected/BABEL-3474-vu-verify.out index 6e252d5191..17a5ee899f 100644 --- a/test/JDBC/expected/BABEL-3474-vu-verify.out +++ b/test/JDBC/expected/BABEL-3474-vu-verify.out @@ -30,7 +30,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v4 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type datetime.)~~ @@ -39,7 +39,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v5 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -78,7 +78,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v9 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type datetime.)~~ @@ -87,7 +87,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v10 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -96,7 +96,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v11 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart day is not supported by date function dateadd for data type time.)~~ @@ -105,7 +105,7 @@ GO SELECT * FROM BABEL_3474_vu_prepare_v12 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart second is not supported by date function dateadd for data type date.)~~ @@ -164,7 +164,7 @@ GO EXEC BABEL_3474_vu_prepare_p4 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type datetime.)~~ @@ -173,7 +173,7 @@ GO EXEC BABEL_3474_vu_prepare_p5 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -212,7 +212,7 @@ GO EXEC BABEL_3474_vu_prepare_p9 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type datetime.)~~ @@ -221,7 +221,7 @@ GO EXEC BABEL_3474_vu_prepare_p10 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -230,7 +230,7 @@ GO EXEC BABEL_3474_vu_prepare_p11 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart day is not supported by date function dateadd for data type time.)~~ @@ -239,7 +239,7 @@ GO EXEC BABEL_3474_vu_prepare_p12 GO -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart second is not supported by date function dateadd for data type date.)~~ @@ -300,7 +300,7 @@ SELECT BABEL_3474_vu_prepare_f4() GO ~~START~~ datetime -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type datetime.)~~ @@ -311,7 +311,7 @@ SELECT BABEL_3474_vu_prepare_f5() GO ~~START~~ smalldatetime -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart microsecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -352,7 +352,7 @@ SELECT BABEL_3474_vu_prepare_f9() GO ~~START~~ datetime -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type datetime.)~~ @@ -363,7 +363,7 @@ SELECT BABEL_3474_vu_prepare_f10() GO ~~START~~ smalldatetime -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart nanosecond is not supported by date function dateadd for data type smalldatetime.)~~ @@ -374,7 +374,7 @@ SELECT BABEL_3474_vu_prepare_f11() GO ~~START~~ time -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart day is not supported by date function dateadd for data type time.)~~ @@ -385,7 +385,7 @@ SELECT BABEL_3474_vu_prepare_f12() GO ~~START~~ date -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 9810)~~ ~~ERROR (Message: The datepart second is not supported by date function dateadd for data type date.)~~ diff --git a/test/JDBC/expected/TestErrorHelperFunctions.out b/test/JDBC/expected/TestErrorHelperFunctions.out index 17c0a6f492..049b0a2c38 100644 --- a/test/JDBC/expected/TestErrorHelperFunctions.out +++ b/test/JDBC/expected/TestErrorHelperFunctions.out @@ -202,6 +202,10 @@ XX000#!#The table-valued parameter "%s" must be declared with the READONLY optio 0A000#!#Column name or number of supplied values does not match table definition.#!##!#213 42501#!#Only members of the sysadmin role can execute this stored procedure.#!##!#15003 42809#!#The target "%s" of the OUTPUT INTO clause cannot be a view or common table expression.#!##!#330 +22008#!#The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart#!##!#535 +22023#!#'%s' is not a recognized %s option#!##!#155 +22023#!#The datepart %s is not supported by date function %s for data type %s.#!##!#9810 +22008#!#Adding a value to a '%s' column caused an overflow.#!##!#517 ~~END~~ diff --git a/test/JDBC/expected/TestErrorHelperFunctionsUpgrade-vu-verify.out b/test/JDBC/expected/TestErrorHelperFunctionsUpgrade-vu-verify.out index 67cd5e10de..b33c88085d 100644 --- a/test/JDBC/expected/TestErrorHelperFunctionsUpgrade-vu-verify.out +++ b/test/JDBC/expected/TestErrorHelperFunctionsUpgrade-vu-verify.out @@ -33,6 +33,7 @@ int 512 515 517 +535 545 547 550 @@ -111,6 +112,7 @@ int 9441 9451 9809 +9810 10610 10727 10733 @@ -307,6 +309,10 @@ int 213 15003 330 +535 +155 +9810 +517 ~~END~~ @@ -473,6 +479,10 @@ int 213 15003 330 +535 +155 +9810 +517 ~~END~~ @@ -480,6 +490,6 @@ EXEC TestErrorHelperFunctionsUpgrade_VU_PREPARE_PROC GO ~~START~~ int -159 +163 ~~END~~ diff --git a/test/JDBC/expected/babel_datetime-vu-verify.out b/test/JDBC/expected/babel_datetime-vu-verify.out index 5dc05ac267..d6df7886af 100644 --- a/test/JDBC/expected/babel_datetime-vu-verify.out +++ b/test/JDBC/expected/babel_datetime-vu-verify.out @@ -376,8 +376,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ - +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) select pg_typeof(c1) FROM (SELECT cast('2016-12-26 23:30:05' as datetime) as C1 UNION SELECT cast('2016-12-26 23:30:05' as smalldatetime) as C1) T diff --git a/test/JDBC/expected/babel_datetime.out b/test/JDBC/expected/babel_datetime.out index fc88466a1b..804bba9f28 100644 --- a/test/JDBC/expected/babel_datetime.out +++ b/test/JDBC/expected/babel_datetime.out @@ -420,7 +420,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/babel_datetime2.out b/test/JDBC/expected/babel_datetime2.out index df31d17cd4..fdb49852f8 100644 --- a/test/JDBC/expected/babel_datetime2.out +++ b/test/JDBC/expected/babel_datetime2.out @@ -658,9 +658,9 @@ datetime2 -- out of range select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime2)); go -~~ERROR (Code: 33557097)~~ +~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime2)~~ +~~ERROR (Message: Adding a value to a 'datetime2' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/babel_smalldatetime.out b/test/JDBC/expected/babel_smalldatetime.out index 9e3dd9dd9c..46224c22a2 100644 --- a/test/JDBC/expected/babel_smalldatetime.out +++ b/test/JDBC/expected/babel_smalldatetime.out @@ -372,9 +372,19 @@ text May ~~END~~ +~~START~~ +smalldatetime +2016-12-26 23:30:00.0 +~~END~~ + +~~START~~ +smalldatetime +2016-12-27 00:25:00.0 +~~END~~ + ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: operator is not unique: smalldatetime + interval)~~ +~~ERROR (Message: data out of range for smalldatetime)~~ -- Clean up diff --git a/test/JDBC/expected/babel_smalldatetime_before_15-5.out b/test/JDBC/expected/babel_smalldatetime_before_15-5.out new file mode 100644 index 0000000000..9e3dd9dd9c --- /dev/null +++ b/test/JDBC/expected/babel_smalldatetime_before_15-5.out @@ -0,0 +1,383 @@ +-- Testing rounding behaviour when inserting into the table +create table smalldatetime_testing ( sm smalldatetime ); +INSERT INTO smalldatetime_testing VALUES('23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.999'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:30.000'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:29.998'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:29.999'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:30.000'); +INSERT INTO smalldatetime_testing VALUES('2000-01-01 00:00:29.998'); +INSERT INTO smalldatetime_testing VALUES('2000-01-01 00:00:29.999'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:30.000'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:29.999'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:29.998'); +select * from smalldatetime_testing; +go +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +smalldatetime +1900-01-01 23:40:00.0 +1992-05-23 23:40:00.0 +1992-05-23 23:40:00.0 +1992-05-23 23:41:00.0 +1992-05-23 23:41:00.0 +2002-05-23 23:41:00.0 +2002-05-23 23:42:00.0 +2002-05-23 23:42:00.0 +2000-01-01 00:00:00.0 +2000-01-01 00:01:00.0 +2000-01-01 00:00:00.0 +2000-01-01 00:00:00.0 +1999-12-31 23:59:00.0 +~~END~~ + + +-- Test comparision with datetime/smalldatetime/date +select * from smalldatetime_testing where sm >= cast('2000-01-01 00:00:59' as smalldatetime); +select * from smalldatetime_testing where sm >= cast('1992-05-23 23:40:00' as datetime) + and sm < cast('1992-05-23 23:41:00' as datetime); +select * from smalldatetime_testing where sm < cast(cast('1992-05-24' as date) as smalldatetime); +go +~~START~~ +smalldatetime +2002-05-23 23:41:00.0 +2002-05-23 23:42:00.0 +2002-05-23 23:42:00.0 +2000-01-01 00:01:00.0 +~~END~~ + +~~START~~ +smalldatetime +1992-05-23 23:40:00.0 +1992-05-23 23:40:00.0 +~~END~~ + +~~START~~ +smalldatetime +1900-01-01 23:40:00.0 +1992-05-23 23:40:00.0 +1992-05-23 23:40:00.0 +1992-05-23 23:41:00.0 +1992-05-23 23:41:00.0 +~~END~~ + + +-- Test rounding for 23:59:59 +SELECT CAST('1992-05-09 23:59:59' AS SMALLDATETIME); +SELECT CAST('2002-05-09 23:59:59' AS SMALLDATETIME); +SELECT CAST('1999-12-31 23:59:59' AS SMALLDATETIME); +go +~~START~~ +smalldatetime +1992-05-10 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2002-05-10 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2000-01-01 00:00:00.0 +~~END~~ + + +-- Test type cast to/from other time formats +-- Cast to smalldatetime +select CAST(CAST('00:00:00.234' AS time) AS smalldatetime); +select CAST(CAST('01:02:03.456' AS time) AS smalldatetime); +select CAST(CAST('2020-03-15' AS date) AS smalldatetime); +select CAST(CAST('2020-03-15' AS datetime) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.998' AS datetime) AS smalldatetime); +select CAST(CAST('1980-07-08 23:59:29.123456 +8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.123456 +8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('1980-07-08 23:59:29.123456 -8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.123456 -8:00' AS datetimeoffset) AS smalldatetime); +go +~~START~~ +smalldatetime +1900-01-01 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +1900-01-01 01:02:00.0 +~~END~~ + +~~START~~ +smalldatetime +2020-03-15 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2020-03-15 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2010-07-08 23:59:00.0 +~~END~~ + +~~START~~ +smalldatetime +1980-07-08 23:59:00.0 +~~END~~ + +~~START~~ +smalldatetime +2010-07-08 23:59:00.0 +~~END~~ + +~~START~~ +smalldatetime +1980-07-08 23:59:00.0 +~~END~~ + +~~START~~ +smalldatetime +2010-07-08 23:59:00.0 +~~END~~ + +-- Cast from smalldatetime +select CAST(CAST('2010-07-08' AS smalldatetime) AS time); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS time); +select CAST(CAST('2010-07-08 23:59:31.998' AS smalldatetime) AS time); +select CAST(CAST('1980-07-08 23:59:29.998' AS smalldatetime) AS time); +select CAST(CAST('1980-07-08 23:59:31.998' AS smalldatetime) AS time); +select CAST(CAST('2020-03-15' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:30.000' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS datetime); +select CAST(CAST('1992-07-08 23:59:29.998' AS smalldatetime) AS datetime); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS datetimeoffset); +select CAST(CAST('1990-07-08 23:59:29.998' AS smalldatetime) AS datetimeoffset); +go +~~START~~ +time +00:00:00.0000000 +~~END~~ + +~~START~~ +time +23:59:00.0000000 +~~END~~ + +~~START~~ +time +00:00:00.0000000 +~~END~~ + +~~START~~ +time +23:59:00.0000000 +~~END~~ + +~~START~~ +time +00:00:00.0000000 +~~END~~ + +~~START~~ +date +2020-03-15 +~~END~~ + +~~START~~ +date +2010-07-08 +~~END~~ + +~~START~~ +date +2010-07-09 +~~END~~ + +~~START~~ +datetime +2010-07-08 23:59:00.0 +~~END~~ + +~~START~~ +datetime +1992-07-08 23:59:00.0 +~~END~~ + +~~START~~ +datetimeoffset +2010-07-08 23:59:00.0000000 +00:00 +~~END~~ + +~~START~~ +datetimeoffset +1990-07-08 23:59:00.0000000 +00:00 +~~END~~ + + +-- Test smalldatetime value ranges +select cast('1900-01-01' as smalldatetime); +select cast('2079-06-06' as smalldatetime); +select cast('1899-12-31 23:59:29.999' as smalldatetime); +select cast('2079-06-06 23:59:29.998' as smalldatetime); +select CAST(CAST('1899-12-31 23:59:30.000' AS datetime) AS smalldatetime); +select CAST(CAST('1899-12-31 23:59:30.000 +0:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2079-06-06 23:59:30.000 +1:00' AS datetimeoffset) AS smalldatetime); +select cast('1899-12-31' as smalldatetime); -- out of range +select cast('2079-06-07' as smalldatetime); -- out of range +select cast('2079-06-06 23:59:29.999' as smalldatetime); -- out of range +select CAST(CAST('2099-03-15' AS date) AS smalldatetime); -- out of range +select CAST(CAST('1800-03-15 23:59:29.998' AS datetime) AS smalldatetime);-- out of range +select CAST(CAST('2099-03-15 23:59:29.998' AS datetime) AS smalldatetime);-- out of range +select CAST(CAST('1899-12-31 23:59:30.000 +1:00' AS datetimeoffset) AS smalldatetime);-- out of range +select CAST(CAST('2099-03-15 23:59:29.998 +6:00' AS datetimeoffset) AS smalldatetime);-- out of range +go +~~START~~ +smalldatetime +1900-01-01 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2079-06-06 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +1900-01-01 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +2079-06-06 23:59:00.0 +~~END~~ + +~~START~~ +smalldatetime +1900-01-01 00:00:00.0 +~~END~~ + +~~START~~ +smalldatetime +1900-01-01 00:00:00.0 +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: data out of range for smalldatetime)~~ + + +-- Test smalldatetime default value +create table t1 (a smalldatetime, b int); +insert into t1 (b) values (1); +select a from t1 where b = 1; +go +~~ROW COUNT: 1~~ + +~~START~~ +smalldatetime + +~~END~~ + + +-- Test smalldatetime as parameter for time related functions +select day(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select month(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select year(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(quarter, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(hour, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(dayofyear, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(second, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(year, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(dw, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(month, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select dateadd(second, 56, cast('2016-12-26 23:29:29' as smalldatetime)); +select dateadd(minute, 56, cast('2016-12-26 23:29:29' as smalldatetime)); +select dateadd(year, 150, cast('2016-12-26 23:29:29' as smalldatetime)); -- Expect error +go +~~START~~ +int +23 +~~END~~ + +~~START~~ +int +5 +~~END~~ + +~~START~~ +int +2002 +~~END~~ + +~~START~~ +int +2 +~~END~~ + +~~START~~ +int +23 +~~END~~ + +~~START~~ +int +143 +~~END~~ + +~~START~~ +int +0 +~~END~~ + +~~START~~ +text +2002 +~~END~~ + +~~START~~ +text +Thursday +~~END~~ + +~~START~~ +text +May +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: operator is not unique: smalldatetime + interval)~~ + + +-- Clean up +drop table smalldatetime_testing; +drop table t1; +go diff --git a/test/JDBC/expected/dateadd-vu-cleanup.out b/test/JDBC/expected/dateadd-vu-cleanup.out new file mode 100644 index 0000000000..5e7690b0cb --- /dev/null +++ b/test/JDBC/expected/dateadd-vu-cleanup.out @@ -0,0 +1,29 @@ +DROP PROCEDURE dateadd_p1 +GO + +DROP PROCEDURE dateadd_p2 +GO + +DROP PROCEDURE dateadd_p3 +GO + +DROP PROCEDURE dateadd_p4 +GO + +DROP PROCEDURE dateadd_p5 +GO + +DROP PROCEDURE dateadd_p6 +GO + +DROP PROCEDURE dateadd_p7 +GO + +DROP PROCEDURE dateadd_p8 +GO + +DROP PROCEDURE dateadd_p9 +GO + +DROP PROCEDURE dateadd_p10 +GO diff --git a/test/JDBC/expected/dateadd-vu-prepare.out b/test/JDBC/expected/dateadd-vu-prepare.out new file mode 100644 index 0000000000..eb893e92e0 --- /dev/null +++ b/test/JDBC/expected/dateadd-vu-prepare.out @@ -0,0 +1,29 @@ +CREATE PROCEDURE dateadd_p1 as (select dateadd(day, 2, cast('1900-01-01' as date))); +GO + +CREATE PROCEDURE dateadd_p2 as (select dateadd(hour, 2, cast('01:01:21' as time))); +GO + +CREATE PROCEDURE dateadd_p3 as (select dateadd(hour, 5, cast('01:01:21 +10:00' as datetimeoffset))); +GO + +CREATE PROCEDURE dateadd_p4 as (select dateadd(second, 1, cast('1999-12-31 23:59:59' as datetime))); +GO + +CREATE PROCEDURE dateadd_p5 as (select dateadd(millisecond, 1, cast('1999-12-31 23:59:59' as datetime))); +GO + +CREATE PROCEDURE dateadd_p6 as (select dateadd(millisecond, 1, cast('1999-12-31 23:59:59' as datetime2))); +GO + +CREATE PROCEDURE dateadd_p7 as (select dateadd(day, 2, cast('01:01:21' as time))); +GO + +CREATE PROCEDURE dateadd_p8 as (select dateadd(hour, 2, cast('1900-01-01' as date))); +GO + +CREATE PROCEDURE dateadd_p9 as (select dateadd(minute, -70, cast('2016-12-26 00:30:05.523456+8' as datetimeoffset))); +GO + +CREATE PROCEDURE dateadd_p10 as (select sys.dateadd_internal_datetime('day', 1, cast('2016-12-26 00:30:05' as datetime), 3)); +GO diff --git a/test/JDBC/expected/dateadd-vu-verify.out b/test/JDBC/expected/dateadd-vu-verify.out new file mode 100644 index 0000000000..b74a4cf799 --- /dev/null +++ b/test/JDBC/expected/dateadd-vu-verify.out @@ -0,0 +1,185 @@ +exec dateadd_p1 +GO +~~START~~ +date +1900-01-03 +~~END~~ + + +exec dateadd_p2 +GO +~~START~~ +time +03:01:21.0000000 +~~END~~ + + +exec dateadd_p3 +GO +~~START~~ +datetimeoffset +1900-01-01 06:01:21.0000000 +10:00 +~~END~~ + + +exec dateadd_p4 +GO +~~START~~ +datetime +2000-01-01 00:00:00.0 +~~END~~ + + +exec dateadd_p5 +GO +~~START~~ +datetime +1999-12-31 23:59:59.0 +~~END~~ + + +exec dateadd_p6 +GO +~~START~~ +datetime2 +1999-12-31 23:59:59.0010000 +~~END~~ + + +exec dateadd_p7 +GO +~~ERROR (Code: 9810)~~ + +~~ERROR (Message: The datepart day is not supported by date function dateadd for data type time.)~~ + + +exec dateadd_p8 +GO +~~ERROR (Code: 9810)~~ + +~~ERROR (Message: The datepart hour is not supported by date function dateadd for data type date.)~~ + + +exec dateadd_p9 +GO +~~START~~ +datetimeoffset +2016-12-25 23:20:05.5234560 +08:00 +~~END~~ + + +exec dateadd_p10 +GO +~~START~~ +datetime +2016-12-27 00:30:05.0 +~~END~~ + + +begin transaction +go + +SELECT dateadd(fakeoption, 2, cast('1900-01-01' as date)); +go +~~ERROR (Code: 155)~~ + +~~ERROR (Message: 'fakeoption' is not a recognized dateadd option)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT dateadd(day, 2, cast('01:01:21' as time)); +go +~~ERROR (Code: 9810)~~ + +~~ERROR (Message: The datepart day is not supported by date function dateadd for data type time.)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-300,getdate()); +go +~~START~~ +datetime +~~ERROR (Code: 517)~~ + +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-30000000, cast('1900-01-01' as datetime)); +go +~~ERROR (Code: 517)~~ + +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(year,-300000000,cast('1900-01-01' as datetime)); +go +~~ERROR (Code: 517)~~ + +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + diff --git a/test/JDBC/expected/datediff-vu-cleanup.out b/test/JDBC/expected/datediff-vu-cleanup.out new file mode 100644 index 0000000000..64b76e5988 --- /dev/null +++ b/test/JDBC/expected/datediff-vu-cleanup.out @@ -0,0 +1,47 @@ +DROP PROCEDURE datediff_p1 +GO + +DROP PROCEDURE datediff_p2 +GO + +DROP PROCEDURE datediff_p3 +GO + +DROP PROCEDURE datediff_p4 +GO + +DROP PROCEDURE datediff_p5 +GO + +DROP PROCEDURE datediff_p6 +GO + +DROP PROCEDURE datediff_p7 +GO + +DROP PROCEDURE datediff_p8 +GO + +DROP PROCEDURE datediff_p9 +GO + +DROP PROCEDURE datediff_p10 +GO + +DROP PROCEDURE datediff_p11 +GO + +DROP PROCEDURE datediff_p12 +GO + +DROP PROCEDURE datediff_p13 +GO + +DROP PROCEDURE datediff_p14 +GO + +DROP PROCEDURE datediff_p15 +GO + +DROP PROCEDURE datediff_p16 +GO diff --git a/test/JDBC/expected/datediff-vu-prepare.out b/test/JDBC/expected/datediff-vu-prepare.out new file mode 100644 index 0000000000..bad18b9072 --- /dev/null +++ b/test/JDBC/expected/datediff-vu-prepare.out @@ -0,0 +1,60 @@ +-- 123 +CREATE PROCEDURE datediff_p1 as (select datediff(year, cast('1900-01-01' as datetime), cast('2023-01-02' as datetime))); +GO + +-- -30 +CREATE PROCEDURE datediff_p2 as (select datediff(year, cast('2020-01-01' as datetime), cast('1990-01-02' as datetime))); +GO + +-- -120 +CREATE PROCEDURE datediff_p3 as (select datediff(quarter, cast('2020-01-01' as datetime), cast('1990-01-02' as datetime))); +GO + +-- 24 +CREATE PROCEDURE datediff_p4 as (select datediff(month, cast('2020-01-01' as datetime), cast('2022-01-02' as datetime))); +GO + +-- 105 +CREATE PROCEDURE datediff_p5 as (select datediff(week, cast('2020-01-01' as datetime2), cast('2022-01-02' as datetime2))); +GO + +-- -10957 +CREATE PROCEDURE datediff_p6 as (select datediff(day, cast('2020-01-01' as smalldatetime), cast('1990-01-01' as smalldatetime))); +GO + +-- -262963 +CREATE PROCEDURE datediff_p7 as (select datediff(hour, cast('2020-01-01 01:01:20.99' as smalldatetime), cast('1990-01-01 06:01:20.99' as smalldatetime))); +GO +-- -15777780 +CREATE PROCEDURE datediff_p8 as (select datediff(minute, cast('2020-01-01 01:01:20.99' as datetime), cast('1990-01-01 06:01:20.99' as smalldatetime))); +GO + +-- 157885200 +CREATE PROCEDURE datediff_p9 as (select datediff(second, cast('2000-01-01 01:01:20.99' as datetime), cast('2005-01-01 10:01:20.99' as datetime))); +GO + +-- 32400000 +CREATE PROCEDURE datediff_p10 as (select datediff(millisecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 10:01:20.99' as datetime))); +GO + +-- 1200000000 +CREATE PROCEDURE datediff_p11 as (select datediff(microsecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- overflow +CREATE PROCEDURE datediff_p12 as (select datediff(nanosecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- 1200000000000 +CREATE PROCEDURE datediff_p13 as (select datediff_big(nanosecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- 15 +CREATE PROCEDURE datediff_p14 as (select datediff(hour, cast('2020-01-01 01:01:20.99 +10:00' as datetimeoffset), cast('2020-01-01 06:01:20.99' as datetimeoffset))); +GO + +CREATE PROCEDURE datediff_p15 as (select datediff(dayofyear, cast('2020-01-01 01:01:20.99 +10:00' as datetimeoffset), cast('2023-01-01 06:01:20.99' as datetimeoffset))); +GO + +CREATE PROCEDURE datediff_p16 as (select sys.datediff_internal_big('week', cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 01:01:20.99' as datetime))); +GO diff --git a/test/JDBC/expected/datediff-vu-verify.out b/test/JDBC/expected/datediff-vu-verify.out new file mode 100644 index 0000000000..1ea3659990 --- /dev/null +++ b/test/JDBC/expected/datediff-vu-verify.out @@ -0,0 +1,182 @@ +-- 123 +exec datediff_p1 +GO +~~START~~ +int +123 +~~END~~ + + +-- -30 +exec datediff_p2 +GO +~~START~~ +int +-30 +~~END~~ + + +-- -120 +exec datediff_p3 +GO +~~START~~ +int +-120 +~~END~~ + + +-- 24 +exec datediff_p4 +GO +~~START~~ +int +24 +~~END~~ + + +-- 105 +exec datediff_p5 +GO +~~START~~ +int +105 +~~END~~ + + +-- -10957 +exec datediff_p6 +GO +~~START~~ +int +-10957 +~~END~~ + + +-- -262963 +exec datediff_p7 +GO +~~START~~ +int +-262963 +~~END~~ + + +-- -15777780 +exec datediff_p8 +GO +~~START~~ +int +-15777780 +~~END~~ + + +-- 157885200 +exec datediff_p9 +GO +~~START~~ +int +157885200 +~~END~~ + + +-- 32400000 +exec datediff_p10 +GO +~~START~~ +int +32400000 +~~END~~ + + +-- 1200000000 +exec datediff_p11 +GO +~~START~~ +int +1200000000 +~~END~~ + + +-- overflow +exec datediff_p12 +GO +~~ERROR (Code: 535)~~ + +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ + + +-- 1200000000000 +exec datediff_p13 +GO +~~START~~ +bigint +1200000000000 +~~END~~ + + +-- 15 +exec datediff_p14 +GO +~~START~~ +int +15 +~~END~~ + + +exec datediff_p15 +GO +~~START~~ +int +1097 +~~END~~ + + +exec datediff_p16 +GO +~~START~~ +bigint +0 +~~END~~ + + +begin transaction +go + +SELECT DATEDIFF(fakeoption, cast('2023-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go +~~ERROR (Code: 155)~~ + +~~ERROR (Message: 'fakeoption' is not a recognized datediff option)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEDIFF(nanosecond, cast('1900-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go +~~ERROR (Code: 535)~~ + +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO diff --git a/test/JDBC/expected/datediff_big-vu-verify.out b/test/JDBC/expected/datediff_big-vu-verify.out index cba97675d7..310c4dad30 100644 --- a/test/JDBC/expected/datediff_big-vu-verify.out +++ b/test/JDBC/expected/datediff_big-vu-verify.out @@ -2,22 +2,22 @@ SELECT * FROM datediff_big_vu_prepare_v1 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -1000#!#4000#!#12000#!#365243#!#365243#!#52177#!#8765832#!#525949920#!#31556995200#!#31556995200000#!#31556995200000000#!#6311433600000000000 +1000#!#4000#!#12000#!#365243#!#365243#!#52178#!#8765832#!#525949920#!#31556995200#!#31556995200000#!#31556995200000000#!#6311433600000000000 ~~END~~ SELECT * FROM datediff_big_vu_prepare_v2 GO -~~ERROR (Code: 8115)~~ +~~ERROR (Code: 535)~~ -~~ERROR (Message: bigint out of range)~~ +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ SELECT * FROM datediff_big_vu_prepare_v3 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -200#!#803#!#2411#!#73413#!#73413#!#10487#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 +200#!#803#!#2411#!#73413#!#73413#!#10488#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 ~~END~~ @@ -25,7 +25,7 @@ SELECT * FROM datediff_big_vu_prepare_v4 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -200#!#803#!#2411#!#73413#!#73413#!#10487#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 +200#!#803#!#2411#!#73413#!#73413#!#10488#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 ~~END~~ @@ -33,7 +33,7 @@ SELECT * FROM datediff_big_vu_prepare_v5 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -100#!#396#!#1189#!#36160#!#36160#!#5165#!#867840#!#52070401#!#3124224060#!#3124224060000#!#3124224060000000#!#3124224060000000000 +100#!#396#!#1189#!#36160#!#36160#!#5166#!#867840#!#52070401#!#3124224060#!#3124224060000#!#3124224060000000#!#3124224060000000000 ~~END~~ @@ -55,16 +55,18 @@ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#! SELECT * FROM datediff_big_vu_prepare_v8 GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: unit "year" not supported for type time without time zone)~~ +~~START~~ +bigint +0 +~~END~~ SELECT * FROM datediff_big_vu_prepare_v9 GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: operator is not unique: time without time zone sys.- time without time zone)~~ +~~START~~ +bigint +51 +~~END~~ SELECT * FROM datediff_big_vu_prepare_v10 @@ -95,22 +97,22 @@ EXEC datediff_big_vu_prepare_p1 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -1000#!#4000#!#12000#!#365243#!#365243#!#52177#!#8765832#!#525949920#!#31556995200#!#31556995200000#!#31556995200000000#!#6311433600000000000 +1000#!#4000#!#12000#!#365243#!#365243#!#52178#!#8765832#!#525949920#!#31556995200#!#31556995200000#!#31556995200000000#!#6311433600000000000 ~~END~~ EXEC datediff_big_vu_prepare_p2 GO -~~ERROR (Code: 8115)~~ +~~ERROR (Code: 535)~~ -~~ERROR (Message: bigint out of range)~~ +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ EXEC datediff_big_vu_prepare_p3 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -200#!#803#!#2411#!#73413#!#73413#!#10487#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 +200#!#803#!#2411#!#73413#!#73413#!#10488#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 ~~END~~ @@ -118,7 +120,7 @@ EXEC datediff_big_vu_prepare_p4 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -200#!#803#!#2411#!#73413#!#73413#!#10487#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 +200#!#803#!#2411#!#73413#!#73413#!#10488#!#1761912#!#105714720#!#6342883200#!#6342883200000#!#6342883200000000#!#6342883200000000000 ~~END~~ @@ -126,7 +128,7 @@ EXEC datediff_big_vu_prepare_p5 GO ~~START~~ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint -100#!#396#!#1189#!#36160#!#36160#!#5165#!#867840#!#52070401#!#3124224060#!#3124224060000#!#3124224060000000#!#3124224060000000000 +100#!#396#!#1189#!#36160#!#36160#!#5166#!#867840#!#52070401#!#3124224060#!#3124224060000#!#3124224060000000#!#3124224060000000000 ~~END~~ @@ -148,16 +150,18 @@ bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#!#bigint#! EXEC datediff_big_vu_prepare_p8 GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: unit "year" not supported for type time without time zone)~~ +~~START~~ +bigint +0 +~~END~~ EXEC datediff_big_vu_prepare_p9 GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: unit "year" not supported for type time without time zone)~~ +~~START~~ +bigint +0 +~~END~~ EXEC datediff_big_vu_prepare_p10 @@ -190,3 +194,66 @@ bigint#!#bigint#!#bigint#!#bigint 0#!#366#!#739013#!#3652424 ~~END~~ + +begin transaction +go + +SELECT DATEDIFF_BIG(fakeoption, cast('2023-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go +~~ERROR (Code: 155)~~ + +~~ERROR (Message: 'fakeoption' is not a recognized datediff option)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEDIFF_BIG(nanosecond, cast('1900-01-01 01:01:20.98' as datetime), cast('3000-01-01 01:01:20.98' as datetime)) +go +~~ERROR (Code: 535)~~ + +~~ERROR (Message: The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-30000000, cast('1900-01-01' as datetime)); +go +~~ERROR (Code: 517)~~ + +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ + + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO +~~START~~ +text +compile time error +~~END~~ + + +if (@@trancount > 0) rollback tran +GO diff --git a/test/JDBC/expected/datediff_internal_date-vu-cleanup.out b/test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-cleanup.out similarity index 100% rename from test/JDBC/expected/datediff_internal_date-vu-cleanup.out rename to test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-cleanup.out diff --git a/test/JDBC/expected/datediff_internal_date-vu-prepare.out b/test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-prepare.out similarity index 100% rename from test/JDBC/expected/datediff_internal_date-vu-prepare.out rename to test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-prepare.out diff --git a/test/JDBC/expected/datediff_internal_date-vu-verify.out b/test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-verify.out similarity index 100% rename from test/JDBC/expected/datediff_internal_date-vu-verify.out rename to test/JDBC/expected/datediff_internal_date-before-14_10-or-15_5-vu-verify.out diff --git a/test/JDBC/expected/latest__verification_cleanup__13_4__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_4__babel_datetime-vu-verify.out index beb8038af8..9e181de4a0 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_4__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_4__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__13_5__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_5__babel_datetime-vu-verify.out index beb8038af8..9e181de4a0 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_5__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_5__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__13_6__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_6__babel_datetime-vu-verify.out index de673fd4ae..4107ba9510 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_6__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_6__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__13_7__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_7__babel_datetime-vu-verify.out index beb8038af8..9e181de4a0 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_7__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_7__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__13_8__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_8__babel_datetime-vu-verify.out index beb8038af8..9e181de4a0 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_8__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_8__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__13_9__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_9__babel_datetime-vu-verify.out index de673fd4ae..4107ba9510 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_9__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_9__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/expected/latest__verification_cleanup__14_3__babel_datetime-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__14_3__babel_datetime-vu-verify.out index de673fd4ae..4107ba9510 100644 --- a/test/JDBC/expected/latest__verification_cleanup__14_3__babel_datetime-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__14_3__babel_datetime-vu-verify.out @@ -377,7 +377,7 @@ select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go ~~ERROR (Code: 517)~~ -~~ERROR (Message: data out of range for datetime)~~ +~~ERROR (Message: Adding a value to a 'datetime' column caused an overflow.)~~ -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) diff --git a/test/JDBC/input/babel_datetime-vu-verify.sql b/test/JDBC/input/babel_datetime-vu-verify.sql index 55395a3fda..af11f60a3a 100644 --- a/test/JDBC/input/babel_datetime-vu-verify.sql +++ b/test/JDBC/input/babel_datetime-vu-verify.sql @@ -128,7 +128,6 @@ go -- out of range select dateadd(year, 150, cast('9900-12-26 23:29:29' as datetime)) go - -- Test data type precedence TODO Fix [BABEL-883] missing TDS support for type regtype (was pg_typeof produces error in sqlcmd) select pg_typeof(c1) FROM (SELECT cast('2016-12-26 23:30:05' as datetime) as C1 UNION SELECT cast('2016-12-26 23:30:05' as smalldatetime) as C1) T go diff --git a/test/JDBC/input/babel_smalldatetime_before_15-5.sql b/test/JDBC/input/babel_smalldatetime_before_15-5.sql new file mode 100644 index 0000000000..390b458771 --- /dev/null +++ b/test/JDBC/input/babel_smalldatetime_before_15-5.sql @@ -0,0 +1,102 @@ +-- Testing rounding behaviour when inserting into the table +create table smalldatetime_testing ( sm smalldatetime ); +INSERT INTO smalldatetime_testing VALUES('23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.998'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:29.999'); +INSERT INTO smalldatetime_testing VALUES('1992-05-23 23:40:30.000'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:29.998'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:29.999'); +INSERT INTO smalldatetime_testing VALUES('2002-05-23 23:41:30.000'); +INSERT INTO smalldatetime_testing VALUES('2000-01-01 00:00:29.998'); +INSERT INTO smalldatetime_testing VALUES('2000-01-01 00:00:29.999'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:30.000'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:29.999'); +INSERT INTO smalldatetime_testing VALUES('1999-12-31 23:59:29.998'); +select * from smalldatetime_testing; +go + +-- Test comparision with datetime/smalldatetime/date +select * from smalldatetime_testing where sm >= cast('2000-01-01 00:00:59' as smalldatetime); +select * from smalldatetime_testing where sm >= cast('1992-05-23 23:40:00' as datetime) + and sm < cast('1992-05-23 23:41:00' as datetime); +select * from smalldatetime_testing where sm < cast(cast('1992-05-24' as date) as smalldatetime); +go + +-- Test rounding for 23:59:59 +SELECT CAST('1992-05-09 23:59:59' AS SMALLDATETIME); +SELECT CAST('2002-05-09 23:59:59' AS SMALLDATETIME); +SELECT CAST('1999-12-31 23:59:59' AS SMALLDATETIME); +go + +-- Test type cast to/from other time formats +-- Cast to smalldatetime +select CAST(CAST('00:00:00.234' AS time) AS smalldatetime); +select CAST(CAST('01:02:03.456' AS time) AS smalldatetime); +select CAST(CAST('2020-03-15' AS date) AS smalldatetime); +select CAST(CAST('2020-03-15' AS datetime) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.998' AS datetime) AS smalldatetime); +select CAST(CAST('1980-07-08 23:59:29.123456 +8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.123456 +8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('1980-07-08 23:59:29.123456 -8:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2010-07-08 23:59:29.123456 -8:00' AS datetimeoffset) AS smalldatetime); +go +-- Cast from smalldatetime +select CAST(CAST('2010-07-08' AS smalldatetime) AS time); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS time); +select CAST(CAST('2010-07-08 23:59:31.998' AS smalldatetime) AS time); +select CAST(CAST('1980-07-08 23:59:29.998' AS smalldatetime) AS time); +select CAST(CAST('1980-07-08 23:59:31.998' AS smalldatetime) AS time); +select CAST(CAST('2020-03-15' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:30.000' AS smalldatetime) AS date); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS datetime); +select CAST(CAST('1992-07-08 23:59:29.998' AS smalldatetime) AS datetime); +select CAST(CAST('2010-07-08 23:59:29.998' AS smalldatetime) AS datetimeoffset); +select CAST(CAST('1990-07-08 23:59:29.998' AS smalldatetime) AS datetimeoffset); +go + +-- Test smalldatetime value ranges +select cast('1900-01-01' as smalldatetime); +select cast('2079-06-06' as smalldatetime); +select cast('1899-12-31 23:59:29.999' as smalldatetime); +select cast('2079-06-06 23:59:29.998' as smalldatetime); +select CAST(CAST('1899-12-31 23:59:30.000' AS datetime) AS smalldatetime); +select CAST(CAST('1899-12-31 23:59:30.000 +0:00' AS datetimeoffset) AS smalldatetime); +select CAST(CAST('2079-06-06 23:59:30.000 +1:00' AS datetimeoffset) AS smalldatetime); +select cast('1899-12-31' as smalldatetime); -- out of range +select cast('2079-06-07' as smalldatetime); -- out of range +select cast('2079-06-06 23:59:29.999' as smalldatetime); -- out of range +select CAST(CAST('2099-03-15' AS date) AS smalldatetime); -- out of range +select CAST(CAST('1800-03-15 23:59:29.998' AS datetime) AS smalldatetime);-- out of range +select CAST(CAST('2099-03-15 23:59:29.998' AS datetime) AS smalldatetime);-- out of range +select CAST(CAST('1899-12-31 23:59:30.000 +1:00' AS datetimeoffset) AS smalldatetime);-- out of range +select CAST(CAST('2099-03-15 23:59:29.998 +6:00' AS datetimeoffset) AS smalldatetime);-- out of range +go + +-- Test smalldatetime default value +create table t1 (a smalldatetime, b int); +insert into t1 (b) values (1); +select a from t1 where b = 1; +go + +-- Test smalldatetime as parameter for time related functions +select day(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select month(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select year(cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(quarter, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(hour, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(dayofyear, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datepart(second, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(year, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(dw, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select datename(month, cast('2002-05-23 23:41:29.998' as smalldatetime)); +select dateadd(second, 56, cast('2016-12-26 23:29:29' as smalldatetime)); +select dateadd(minute, 56, cast('2016-12-26 23:29:29' as smalldatetime)); +select dateadd(year, 150, cast('2016-12-26 23:29:29' as smalldatetime)); -- Expect error +go + +-- Clean up +drop table smalldatetime_testing; +drop table t1; +go diff --git a/test/JDBC/input/dateFunctions/dateadd-vu-cleanup.sql b/test/JDBC/input/dateFunctions/dateadd-vu-cleanup.sql new file mode 100644 index 0000000000..64afaa6c7e --- /dev/null +++ b/test/JDBC/input/dateFunctions/dateadd-vu-cleanup.sql @@ -0,0 +1,29 @@ +DROP PROCEDURE dateadd_p1 +GO + +DROP PROCEDURE dateadd_p2 +GO + +DROP PROCEDURE dateadd_p3 +GO + +DROP PROCEDURE dateadd_p4 +GO + +DROP PROCEDURE dateadd_p5 +GO + +DROP PROCEDURE dateadd_p6 +GO + +DROP PROCEDURE dateadd_p7 +GO + +DROP PROCEDURE dateadd_p8 +GO + +DROP PROCEDURE dateadd_p9 +GO + +DROP PROCEDURE dateadd_p10 +GO \ No newline at end of file diff --git a/test/JDBC/input/dateFunctions/dateadd-vu-prepare.sql b/test/JDBC/input/dateFunctions/dateadd-vu-prepare.sql new file mode 100644 index 0000000000..eb893e92e0 --- /dev/null +++ b/test/JDBC/input/dateFunctions/dateadd-vu-prepare.sql @@ -0,0 +1,29 @@ +CREATE PROCEDURE dateadd_p1 as (select dateadd(day, 2, cast('1900-01-01' as date))); +GO + +CREATE PROCEDURE dateadd_p2 as (select dateadd(hour, 2, cast('01:01:21' as time))); +GO + +CREATE PROCEDURE dateadd_p3 as (select dateadd(hour, 5, cast('01:01:21 +10:00' as datetimeoffset))); +GO + +CREATE PROCEDURE dateadd_p4 as (select dateadd(second, 1, cast('1999-12-31 23:59:59' as datetime))); +GO + +CREATE PROCEDURE dateadd_p5 as (select dateadd(millisecond, 1, cast('1999-12-31 23:59:59' as datetime))); +GO + +CREATE PROCEDURE dateadd_p6 as (select dateadd(millisecond, 1, cast('1999-12-31 23:59:59' as datetime2))); +GO + +CREATE PROCEDURE dateadd_p7 as (select dateadd(day, 2, cast('01:01:21' as time))); +GO + +CREATE PROCEDURE dateadd_p8 as (select dateadd(hour, 2, cast('1900-01-01' as date))); +GO + +CREATE PROCEDURE dateadd_p9 as (select dateadd(minute, -70, cast('2016-12-26 00:30:05.523456+8' as datetimeoffset))); +GO + +CREATE PROCEDURE dateadd_p10 as (select sys.dateadd_internal_datetime('day', 1, cast('2016-12-26 00:30:05' as datetime), 3)); +GO diff --git a/test/JDBC/input/dateFunctions/dateadd-vu-verify.sql b/test/JDBC/input/dateFunctions/dateadd-vu-verify.sql new file mode 100644 index 0000000000..6a8c2d0a6a --- /dev/null +++ b/test/JDBC/input/dateFunctions/dateadd-vu-verify.sql @@ -0,0 +1,90 @@ +exec dateadd_p1 +GO + +exec dateadd_p2 +GO + +exec dateadd_p3 +GO + +exec dateadd_p4 +GO + +exec dateadd_p5 +GO + +exec dateadd_p6 +GO + +exec dateadd_p7 +GO + +exec dateadd_p8 +GO + +exec dateadd_p9 +GO + +exec dateadd_p10 +GO + +begin transaction +go + +SELECT dateadd(fakeoption, 2, cast('1900-01-01' as date)); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT dateadd(day, 2, cast('01:01:21' as time)); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-300,getdate()); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-30000000, cast('1900-01-01' as datetime)); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(year,-300000000,cast('1900-01-01' as datetime)); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + diff --git a/test/JDBC/input/dateFunctions/datediff-vu-cleanup.sql b/test/JDBC/input/dateFunctions/datediff-vu-cleanup.sql new file mode 100644 index 0000000000..675b046c78 --- /dev/null +++ b/test/JDBC/input/dateFunctions/datediff-vu-cleanup.sql @@ -0,0 +1,47 @@ +DROP PROCEDURE datediff_p1 +GO + +DROP PROCEDURE datediff_p2 +GO + +DROP PROCEDURE datediff_p3 +GO + +DROP PROCEDURE datediff_p4 +GO + +DROP PROCEDURE datediff_p5 +GO + +DROP PROCEDURE datediff_p6 +GO + +DROP PROCEDURE datediff_p7 +GO + +DROP PROCEDURE datediff_p8 +GO + +DROP PROCEDURE datediff_p9 +GO + +DROP PROCEDURE datediff_p10 +GO + +DROP PROCEDURE datediff_p11 +GO + +DROP PROCEDURE datediff_p12 +GO + +DROP PROCEDURE datediff_p13 +GO + +DROP PROCEDURE datediff_p14 +GO + +DROP PROCEDURE datediff_p15 +GO + +DROP PROCEDURE datediff_p16 +GO \ No newline at end of file diff --git a/test/JDBC/input/dateFunctions/datediff-vu-prepare.sql b/test/JDBC/input/dateFunctions/datediff-vu-prepare.sql new file mode 100644 index 0000000000..40cc2b58d4 --- /dev/null +++ b/test/JDBC/input/dateFunctions/datediff-vu-prepare.sql @@ -0,0 +1,60 @@ +-- 123 +CREATE PROCEDURE datediff_p1 as (select datediff(year, cast('1900-01-01' as datetime), cast('2023-01-02' as datetime))); +GO + +-- -30 +CREATE PROCEDURE datediff_p2 as (select datediff(year, cast('2020-01-01' as datetime), cast('1990-01-02' as datetime))); +GO + +-- -120 +CREATE PROCEDURE datediff_p3 as (select datediff(quarter, cast('2020-01-01' as datetime), cast('1990-01-02' as datetime))); +GO + +-- 24 +CREATE PROCEDURE datediff_p4 as (select datediff(month, cast('2020-01-01' as datetime), cast('2022-01-02' as datetime))); +GO + +-- 105 +CREATE PROCEDURE datediff_p5 as (select datediff(week, cast('2020-01-01' as datetime2), cast('2022-01-02' as datetime2))); +GO + +-- -10957 +CREATE PROCEDURE datediff_p6 as (select datediff(day, cast('2020-01-01' as smalldatetime), cast('1990-01-01' as smalldatetime))); +GO + +-- -262963 +CREATE PROCEDURE datediff_p7 as (select datediff(hour, cast('2020-01-01 01:01:20.99' as smalldatetime), cast('1990-01-01 06:01:20.99' as smalldatetime))); +GO +-- -15777780 +CREATE PROCEDURE datediff_p8 as (select datediff(minute, cast('2020-01-01 01:01:20.99' as datetime), cast('1990-01-01 06:01:20.99' as smalldatetime))); +GO + +-- 157885200 +CREATE PROCEDURE datediff_p9 as (select datediff(second, cast('2000-01-01 01:01:20.99' as datetime), cast('2005-01-01 10:01:20.99' as datetime))); +GO + +-- 32400000 +CREATE PROCEDURE datediff_p10 as (select datediff(millisecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 10:01:20.99' as datetime))); +GO + +-- 1200000000 +CREATE PROCEDURE datediff_p11 as (select datediff(microsecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- overflow +CREATE PROCEDURE datediff_p12 as (select datediff(nanosecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- 1200000000000 +CREATE PROCEDURE datediff_p13 as (select datediff_big(nanosecond, cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 1:21:20.99' as datetime))); +GO + +-- 15 +CREATE PROCEDURE datediff_p14 as (select datediff(hour, cast('2020-01-01 01:01:20.99 +10:00' as datetimeoffset), cast('2020-01-01 06:01:20.99' as datetimeoffset))); +GO + +CREATE PROCEDURE datediff_p15 as (select datediff(dayofyear, cast('2020-01-01 01:01:20.99 +10:00' as datetimeoffset), cast('2023-01-01 06:01:20.99' as datetimeoffset))); +GO + +CREATE PROCEDURE datediff_p16 as (select sys.datediff_internal_big('week', cast('2005-01-01 01:01:20.99' as datetime), cast('2005-01-01 01:01:20.99' as datetime))); +GO \ No newline at end of file diff --git a/test/JDBC/input/dateFunctions/datediff-vu-verify.sql b/test/JDBC/input/dateFunctions/datediff-vu-verify.sql new file mode 100644 index 0000000000..2792eef63c --- /dev/null +++ b/test/JDBC/input/dateFunctions/datediff-vu-verify.sql @@ -0,0 +1,85 @@ +-- 123 +exec datediff_p1 +GO + +-- -30 +exec datediff_p2 +GO + +-- -120 +exec datediff_p3 +GO + +-- 24 +exec datediff_p4 +GO + +-- 105 +exec datediff_p5 +GO + +-- -10957 +exec datediff_p6 +GO + +-- -262963 +exec datediff_p7 +GO + +-- -15777780 +exec datediff_p8 +GO + +-- 157885200 +exec datediff_p9 +GO + +-- 32400000 +exec datediff_p10 +GO + +-- 1200000000 +exec datediff_p11 +GO + +-- overflow +exec datediff_p12 +GO + +-- 1200000000000 +exec datediff_p13 +GO + +-- 15 +exec datediff_p14 +GO + +exec datediff_p15 +GO + +exec datediff_p16 +GO + +begin transaction +go + +SELECT DATEDIFF(fakeoption, cast('2023-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEDIFF(nanosecond, cast('1900-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO diff --git a/test/JDBC/input/functions/datediff_big-vu-verify.sql b/test/JDBC/input/functions/datediff_big-vu-verify.sql index 29bba9a252..b969588987 100644 --- a/test/JDBC/input/functions/datediff_big-vu-verify.sql +++ b/test/JDBC/input/functions/datediff_big-vu-verify.sql @@ -72,3 +72,39 @@ GO EXEC datediff_big_vu_prepare_p13 GO + +begin transaction +go + +SELECT DATEDIFF_BIG(fakeoption, cast('2023-01-01 01:01:20.98' as datetime), cast('2023-01-01 01:01:20.98' as datetime)) +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEDIFF_BIG(nanosecond, cast('1900-01-01 01:01:20.98' as datetime), cast('3000-01-01 01:01:20.98' as datetime)) +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO + +begin transaction +go + +SELECT DATEADD(YY,-30000000, cast('1900-01-01' as datetime)); +go + +if (@@trancount > 0) select cast('compile time error' as text) else select cast('runtime error' as text) +GO + +if (@@trancount > 0) rollback tran +GO \ No newline at end of file diff --git a/test/JDBC/input/functions/datediff_internal_date-vu-cleanup.sql b/test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-cleanup.sql similarity index 100% rename from test/JDBC/input/functions/datediff_internal_date-vu-cleanup.sql rename to test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-cleanup.sql diff --git a/test/JDBC/input/functions/datediff_internal_date-vu-prepare.sql b/test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-prepare.sql similarity index 100% rename from test/JDBC/input/functions/datediff_internal_date-vu-prepare.sql rename to test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-prepare.sql diff --git a/test/JDBC/input/functions/datediff_internal_date-vu-verify.sql b/test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-verify.sql similarity index 100% rename from test/JDBC/input/functions/datediff_internal_date-vu-verify.sql rename to test/JDBC/input/functions/datediff_internal_date-before-14_10-or-15_5-vu-verify.sql diff --git a/test/JDBC/jdbc_schedule b/test/JDBC/jdbc_schedule index 827dc396b2..ac6f8bf86b 100644 --- a/test/JDBC/jdbc_schedule +++ b/test/JDBC/jdbc_schedule @@ -136,9 +136,13 @@ ignore#!#test_windows_login_before_15_2-vu-cleanup ignore#!#datediff_internal_date-before-14_7-or-15_2-vu-prepare ignore#!#datediff_internal_date-before-14_7-or-15_2-vu-verify ignore#!#datediff_internal_date-before-14_7-or-15_2-vu-cleanup +ignore#!#datediff_internal_date-before-14_10-or-15_5-vu-prepare +ignore#!#datediff_internal_date-before-14_10-or-15_5-vu-verify +ignore#!#datediff_internal_date-before-14_10-or-15_5-vu-cleanup ignore#!#datetime2fromparts-vu-prepare ignore#!#datetime2fromparts-vu-verify ignore#!#datetime2fromparts-vu-cleanup +ignore#!#babel_smalldatetime_before_15-5 # These tests are meant for only upgrade ignore#!#openquery_upgrd-vu-prepare diff --git a/test/JDBC/upgrade/14_10/schedule b/test/JDBC/upgrade/14_10/schedule index 1064d1bdec..4dd95acdc3 100644 --- a/test/JDBC/upgrade/14_10/schedule +++ b/test/JDBC/upgrade/14_10/schedule @@ -391,7 +391,6 @@ BABEL-3914 BABEL_OBJECT_NAME sys-systypes BABEL_OBJECT_DEFINITION -datediff_internal_date Test-sp_rename Test-sp_rename-dep BABEL-3657 diff --git a/test/JDBC/upgrade/14_11/schedule b/test/JDBC/upgrade/14_11/schedule index 1064d1bdec..4dd95acdc3 100644 --- a/test/JDBC/upgrade/14_11/schedule +++ b/test/JDBC/upgrade/14_11/schedule @@ -391,7 +391,6 @@ BABEL-3914 BABEL_OBJECT_NAME sys-systypes BABEL_OBJECT_DEFINITION -datediff_internal_date Test-sp_rename Test-sp_rename-dep BABEL-3657 diff --git a/test/JDBC/upgrade/14_7/schedule b/test/JDBC/upgrade/14_7/schedule index d71c279168..4ceb592efb 100644 --- a/test/JDBC/upgrade/14_7/schedule +++ b/test/JDBC/upgrade/14_7/schedule @@ -186,7 +186,7 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 datepart datetime2fromparts forjson diff --git a/test/JDBC/upgrade/14_8/schedule b/test/JDBC/upgrade/14_8/schedule index deb6e59d05..527fc5e57a 100644 --- a/test/JDBC/upgrade/14_8/schedule +++ b/test/JDBC/upgrade/14_8/schedule @@ -184,7 +184,7 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 datepart datetime2fromparts forjson diff --git a/test/JDBC/upgrade/14_9/schedule b/test/JDBC/upgrade/14_9/schedule index fa471c060f..367c135afa 100644 --- a/test/JDBC/upgrade/14_9/schedule +++ b/test/JDBC/upgrade/14_9/schedule @@ -371,7 +371,7 @@ ISC-Columns ISC-Table_Constraints sys_server_principals_dep sys_database_principals_dep -datediff_big +datediff_big-before-15_5 atn2 app_name str @@ -391,7 +391,7 @@ BABEL-3914 BABEL_OBJECT_NAME sys-systypes BABEL_OBJECT_DEFINITION -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 Test-sp_rename Test-sp_rename-dep BABEL-3657 diff --git a/test/JDBC/upgrade/15_2/schedule b/test/JDBC/upgrade/15_2/schedule index 2d053948d7..6fc69d7750 100644 --- a/test/JDBC/upgrade/15_2/schedule +++ b/test/JDBC/upgrade/15_2/schedule @@ -186,7 +186,7 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 datepart datetime2fromparts forjson diff --git a/test/JDBC/upgrade/15_3/schedule b/test/JDBC/upgrade/15_3/schedule index 73a390d814..9844bb1691 100644 --- a/test/JDBC/upgrade/15_3/schedule +++ b/test/JDBC/upgrade/15_3/schedule @@ -195,7 +195,7 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 datepart datetime2fromparts-after-15-2 forjson diff --git a/test/JDBC/upgrade/15_4/schedule b/test/JDBC/upgrade/15_4/schedule index b18a4b72b0..bf4ba49923 100644 --- a/test/JDBC/upgrade/15_4/schedule +++ b/test/JDBC/upgrade/15_4/schedule @@ -198,7 +198,7 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff_internal_date-before-14_10-or-15_5 datepart datetime2fromparts-after-15-2 forjson diff --git a/test/JDBC/upgrade/15_5/schedule b/test/JDBC/upgrade/15_5/schedule index efe73dc34b..eab7f39361 100644 --- a/test/JDBC/upgrade/15_5/schedule +++ b/test/JDBC/upgrade/15_5/schedule @@ -50,7 +50,6 @@ BABEL-2787 BABEL-2787-2 BABEL-2795 BABEL-2805 -BABEL-2812 BABEL-2819 BABEL-2845 BABEL-2877 @@ -87,7 +86,6 @@ BABEL-3370 BABEL-3380 BABEL-3392 BABEL-3402 -BABEL-3474 BABEL-3478 BABEL-3486 BABEL-3513 @@ -137,7 +135,6 @@ BABEL-CHECK-CONSTRAINT babel_context_info BABEL-CROSS-DB babel_datatype_sqlvariant -babel_datetime Babel_domain_mapping_test BABEL-EXECUTE_AS_CALLER BABEL-EXTENDEDPROPERTY @@ -206,8 +203,6 @@ collation_tests_polish column_domain_usage constraint_column_usage dateadd_internal_df -datediff_big -datediff_internal_date datepart datetime2fromparts-after-15-2 forjson diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index efe73dc34b..9743239b1d 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -207,7 +207,8 @@ column_domain_usage constraint_column_usage dateadd_internal_df datediff_big -datediff_internal_date +datediff +dateadd datepart datetime2fromparts-after-15-2 forjson diff --git a/test/JDBC/upgrade/master/schedule b/test/JDBC/upgrade/master/schedule index e228922a6b..e9845c928f 100644 --- a/test/JDBC/upgrade/master/schedule +++ b/test/JDBC/upgrade/master/schedule @@ -162,7 +162,8 @@ collation_tests_mongolian collation_tests_polish dateadd_internal_df datediff_big -datediff_internal_date +datediff +dateadd datepart datetime2fromparts-after-15-2 forjson diff --git a/test/python/expected/sql_validation_framework/expected_create.out b/test/python/expected/sql_validation_framework/expected_create.out index 0aa3907ff7..26777ae841 100644 --- a/test/python/expected/sql_validation_framework/expected_create.out +++ b/test/python/expected/sql_validation_framework/expected_create.out @@ -14,7 +14,6 @@ Could not find tests for function sys.columns_internal Could not find tests for function sys.date_bucket_internal_helper Could not find tests for function sys.dateadd_internal Could not find tests for function sys.datediff_internal -Could not find tests for function sys.datediff_internal_df Could not find tests for function sys.datepart_internal Could not find tests for function sys.default_domain Could not find tests for function sys.get_current_full_xact_id @@ -116,7 +115,6 @@ Could not find upgrade tests for function sys.cursor_status Could not find upgrade tests for function sys.date_bucket_internal_helper Could not find upgrade tests for function sys.dateadd_internal Could not find upgrade tests for function sys.datediff_internal -Could not find upgrade tests for function sys.datediff_internal_df Could not find upgrade tests for function sys.datepart_internal Could not find upgrade tests for function sys.default_domain Could not find upgrade tests for function sys.error_line diff --git a/test/python/expected/upgrade_validation/expected_dependency.out b/test/python/expected/upgrade_validation/expected_dependency.out index 904cd2cc24..af4fc3240a 100644 --- a/test/python/expected/upgrade_validation/expected_dependency.out +++ b/test/python/expected/upgrade_validation/expected_dependency.out @@ -313,11 +313,12 @@ Function sys.date2smalldatetime(date) Function sys.date_bucket_internal_helper(text,integer,boolean,boolean,anyelement) Function sys.date_sqlvariant(date) Function sys.dateadd_internal(text,integer,anyelement) +Function sys.dateadd_internal_datetime(text,integer,anyelement,integer) Function sys.datediff(text,sys.datetime2,sys.datetime2) Function sys.datediff(text,sys.smalldatetime,sys.smalldatetime) Function sys.datediff(text,time without time zone,time without time zone) Function sys.datediff_internal(text,anyelement,anyelement) -Function sys.datediff_internal_df(text,anyelement,anyelement) +Function sys.datediff_internal_big(text,anyelement,anyelement) Function sys.datefirst() Function sys.datefromparts(integer,integer,integer) Function sys.datename(text,text) From 2aaac7eb2339846120e6809b05d34e0df2ba7bd7 Mon Sep 17 00:00:00 2001 From: Walt Boettge Date: Fri, 17 Nov 2023 15:00:02 -0600 Subject: [PATCH 32/34] Fix test output plan verification (#2022) Test BABEL-4281 gives the memory usage with STATISTICS PROFILE. During testing, this value can change, causing test failures. Switching to SHOWPLAN_ALL will give a plan without outputing memory usage. Signed-off-by: Walt Boettge --- test/JDBC/expected/BABEL-4281.out | 33 ++++++++++++++----------------- test/JDBC/input/BABEL-4281.sql | 9 ++++++--- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/JDBC/expected/BABEL-4281.out b/test/JDBC/expected/BABEL-4281.out index 585637ac54..d3a6d420a0 100644 --- a/test/JDBC/expected/BABEL-4281.out +++ b/test/JDBC/expected/BABEL-4281.out @@ -51,40 +51,37 @@ off ~~END~~ -SET BABELFISH_STATISTICS PROFILE ON +SET BABELFISH_SHOWPLAN_ALL ON GO select a, count(*) from t_babel4281 group by a order by 2; -- should not crash GO -~~START~~ -int#!#int -~~END~~ - ~~START~~ text Query Text: select a, count(*) from t_babel4281 group by a order by 2 -Sort (actual rows=0 loops=1) +Sort Sort Key: (count(*)) NULLS FIRST - Sort Method: quicksort Memory: 25kB - -> Finalize HashAggregate (actual rows=0 loops=1) + -> Finalize HashAggregate Group Key: a - Batches: 1 Memory Usage: 40kB - -> Gather (actual rows=0 loops=1) + -> Gather Workers Planned: 2 - Workers Launched: 2 - -> Partial HashAggregate (actual rows=0 loops=3) + -> Partial HashAggregate Group Key: a - Batches: 1 Memory Usage: 40kB - Worker 0: Batches: 1 Memory Usage: 40kB - Worker 1: Batches: 1 Memory Usage: 40kB - -> Parallel Seq Scan on t_babel4281 (actual rows=0 loops=3) + -> Parallel Seq Scan on t_babel4281 ~~END~~ - -- set configurations back -SET BABELFISH_STATISTICS PROFILE OFF +SET BABELFISH_SHOWPLAN_ALL OFF +GO + +-- Verify Output +select a, count(*) from t_babel4281 group by a order by 2; -- should not crash GO +~~START~~ +int#!#int +~~END~~ + select set_config('babelfishpg_tsql.explain_timing', 'on', false); GO diff --git a/test/JDBC/input/BABEL-4281.sql b/test/JDBC/input/BABEL-4281.sql index 94f52e8180..7113fd6373 100644 --- a/test/JDBC/input/BABEL-4281.sql +++ b/test/JDBC/input/BABEL-4281.sql @@ -21,15 +21,18 @@ GO select set_config('babelfishpg_tsql.explain_costs', 'off', false); GO -SET BABELFISH_STATISTICS PROFILE ON +SET BABELFISH_SHOWPLAN_ALL ON GO select a, count(*) from t_babel4281 group by a order by 2; -- should not crash GO - -- set configurations back -SET BABELFISH_STATISTICS PROFILE OFF +SET BABELFISH_SHOWPLAN_ALL OFF +GO + +-- Verify Output +select a, count(*) from t_babel4281 group by a order by 2; -- should not crash GO select set_config('babelfishpg_tsql.explain_timing', 'on', false); From 70b845f5ccdd4da19fab2dd6627910e7d3192180 Mon Sep 17 00:00:00 2001 From: Sandeep Kumawat <2025sandeepkumawat@gmail.com> Date: Mon, 20 Nov 2023 10:41:06 +0530 Subject: [PATCH 33/34] fix jdbc tests fails locally with error " 'tds_fdw' extension does not exists". (#2029) Some tests listed in issue BABEL-4540 failing with error " 'tds_fdw' extension does not exists". This is because of tds_fdw extension is not installed locally. However while running jdbc test check in GitHub we install 'tds_fdw' extension in GitHub check. These tests are running now as expected in parallel query mode. Removed these tests from ignore file. One of the test four-part-names-vu-verify still failing due to time-out. Included this test to appropriate group. Task: BABEL-4540 Signed-off-by: Sandeep Kumawat --- test/JDBC/parallel_query_jdbc_schedule | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index 5762855b2a..61b0f29ff2 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -61,23 +61,6 @@ ignore#!#babel_datetime-vu-verify ignore#!#babel_datetime ignore#!#BABEL-2812-vu-verify -# "tds_fdw" does not exist - JIRA-4540 -ignore#!#BABEL-4168-vu-prepare -ignore#!#BABEL-4168-vu-verify -ignore#!#BABEL-4168-vu-cleanup -ignore#!#four-part-names-vu-prepare -ignore#!#four-part-names-vu-verify -ignore#!#four-part-names-vu-cleanup -ignore#!#linked_servers-vu-prepare -ignore#!#linked_servers-vu-verify -ignore#!#linked_servers-vu-cleanup -ignore#!#linked_srv_4229-vu-prepare -ignore#!#linked_srv_4229-vu-verify -ignore#!#linked_srv_4229-vu-cleanup -ignore#!#openquery-vu-prepare -ignore#!#openquery-vu-verify -ignore#!#openquery-vu-cleanup - # relation "onek" does not exist: JIRA-4541 ignore#!#pgr_select ignore#!#pgr_select_distinct @@ -298,3 +281,4 @@ ignore#!#TestSimpleErrorsWithXactAbort ignore#!#BABEL-2513 ignore#!#TestDatetime-numeric-representation-vu-prepare ignore#!#TestDatetime-numeric-representation-vu-verify +ignore#!#four-part-names-vu-verify From 4b3e6517a1f7542e701c194bb6cda304d9861274 Mon Sep 17 00:00:00 2001 From: Dipesh Dhameliya Date: Mon, 20 Nov 2023 16:05:36 +0530 Subject: [PATCH 34/34] Additional checks --- contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 3b779eef0c..4cbe2c48ef 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -1895,7 +1895,7 @@ PrepareRowDescription(TupleDesc typeinfo, PlannedStmt *plannedstmt, List *target */ if (atttypmod == -1 && tle != NULL) { - if (!plannedstmt) + if (!plannedstmt || !plannedstmt->planTree) { ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),