From f9734a3ed163521ce9a9fbc69f11c33dda7430d5 Mon Sep 17 00:00:00 2001 From: Parikshit Sarode Date: Fri, 20 Oct 2023 18:16:07 +0530 Subject: [PATCH 1/6] Fix crash in pgstat_init_function_usage (#1935) Crash in pgstat_init_function_usage_wrapper due to the ReleaseSysCache is being called even if proctup is Invalid. ReleaseSysCache on proctup should only be called when proctup is validated by HeapTupleIsValid. Task: BABEL-4466 Signed-off-by: Parikshit Sarode pasarode@amazon.com --- contrib/babelfishpg_tsql/src/hooks.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index eb82f8699c..1a368916bf 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -798,12 +798,10 @@ pgstat_init_function_usage_wrapper(FunctionCallInfo fcinfo, { Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup); pre_wrapper_pgstat_init_function_usage(NameStr(proc->proname)); + ReleaseSysCache(proctup); } - - ReleaseSysCache(proctup); } } - } static Node * From 5634be1ca21525973c95e38644583680f9f86d63 Mon Sep 17 00:00:00 2001 From: Zhibai Song Date: Fri, 20 Oct 2023 11:22:26 -0700 Subject: [PATCH 2/6] Fix the issue DISABLE trigger not work for instead of triggers (#1939) previously our support for ENABLE/DISABLE trigger syntax has a issue that it's not working for instead of triggers. This commit fix this issue. Task: BABEL-3326 Signed-off-by: Zhibai Song Co-authored-by: Zhibai Song --- test/JDBC/expected/BABEL-3326-vu-cleanup.out | 18 ++++ test/JDBC/expected/BABEL-3326-vu-prepare.out | 38 +++++++ test/JDBC/expected/BABEL-3326-vu-verify.out | 100 +++++++++++++++++++ test/JDBC/input/BABEL-3326-vu-cleanup.mix | 18 ++++ test/JDBC/input/BABEL-3326-vu-prepare.mix | 36 ++++++- test/JDBC/input/BABEL-3326-vu-verify.mix | 44 ++++++++ 6 files changed, 253 insertions(+), 1 deletion(-) diff --git a/test/JDBC/expected/BABEL-3326-vu-cleanup.out b/test/JDBC/expected/BABEL-3326-vu-cleanup.out index fe0ead6d05..942e153a59 100644 --- a/test/JDBC/expected/BABEL-3326-vu-cleanup.out +++ b/test/JDBC/expected/BABEL-3326-vu-cleanup.out @@ -20,6 +20,24 @@ GO DROP TABLE babel_3326_Employees GO +drop trigger babel_3326_t1_trigger +GO + +drop trigger babel_3326_t2_trigger +GO + +drop trigger babel_3326_t3_trigger +GO + +drop table babel_3326_t1; +GO + +drop table babel_3326_t2; +GO + +drop table babel_3326_t3; +GO + DROP USER babel_3326_u1 GO diff --git a/test/JDBC/expected/BABEL-3326-vu-prepare.out b/test/JDBC/expected/BABEL-3326-vu-prepare.out index 6449985b68..f8289d5611 100644 --- a/test/JDBC/expected/BABEL-3326-vu-prepare.out +++ b/test/JDBC/expected/BABEL-3326-vu-prepare.out @@ -118,3 +118,41 @@ FOR INSERT AS SELECT 'Trigger db.TR_ins Invoked' GO + +create table babel_3326_t1 (a varchar) +GO + +create trigger babel_3326_t1_trigger on babel_3326_t1 instead of insert as +begin + select count(*) from inserted; +end; +GO + +create table babel_3326_t2 (a varchar) +GO + +insert into babel_3326_t2 values ('1'); +GO +~~ROW COUNT: 1~~ + + +create trigger babel_3326_t2_trigger on babel_3326_t2 instead of delete as +begin + select count(*) from deleted; +end; +GO + +create table babel_3326_t3 (a varchar) +GO + +insert into babel_3326_t3 values ('2'); +GO +~~ROW COUNT: 1~~ + + +create trigger babel_3326_t3_trigger on babel_3326_t3 instead of update as +begin + select count(*) from deleted; + select count(*) from inserted; +end; +GO diff --git a/test/JDBC/expected/BABEL-3326-vu-verify.out b/test/JDBC/expected/BABEL-3326-vu-verify.out index 742555b07e..060c98bf7a 100644 --- a/test/JDBC/expected/BABEL-3326-vu-verify.out +++ b/test/JDBC/expected/BABEL-3326-vu-verify.out @@ -1028,3 +1028,103 @@ GO ~~ERROR (Message: 'DDL trigger' is not currently supported in Babelfish.)~~ + +-- The instead of trigger is on and there'll no rows will be inserted +insert into babel_3326_t1 values ('1'); +GO +~~START~~ +int +1 +~~END~~ + +~~ROW COUNT: 1~~ + + +DISABLE trigger babel_3326_t1_trigger on babel_3326_t1 +GO + +insert into babel_3326_t1 values ('1'); +GO +~~ROW COUNT: 1~~ + + +-- The instead of trigger is disabled and new rows are inserted into the table +select * from babel_3326_t1; +GO +~~START~~ +varchar +1 +~~END~~ + + +delete from babel_3326_t2; +GO +~~START~~ +int +1 +~~END~~ + +~~ROW COUNT: 1~~ + + +select * from babel_3326_t2; +GO +~~START~~ +varchar +1 +~~END~~ + + +DISABLE trigger babel_3326_t2_trigger on babel_3326_t2 +GO + +delete from babel_3326_t2; +GO +~~ROW COUNT: 1~~ + + +select * from babel_3326_t2; +GO +~~START~~ +varchar +~~END~~ + + +update babel_3326_t3 set a = '3'; +GO +~~START~~ +int +1 +~~END~~ + +~~START~~ +int +1 +~~END~~ + +~~ROW COUNT: 1~~ + + +select * from babel_3326_t3; +GO +~~START~~ +varchar +2 +~~END~~ + + +DISABLE trigger babel_3326_t3_trigger on babel_3326_t3 +GO + +update babel_3326_t3 set a = '3'; +GO +~~ROW COUNT: 1~~ + + +select * from babel_3326_t3; +GO +~~START~~ +varchar +3 +~~END~~ + diff --git a/test/JDBC/input/BABEL-3326-vu-cleanup.mix b/test/JDBC/input/BABEL-3326-vu-cleanup.mix index ce0014ff8f..901226912a 100644 --- a/test/JDBC/input/BABEL-3326-vu-cleanup.mix +++ b/test/JDBC/input/BABEL-3326-vu-cleanup.mix @@ -20,6 +20,24 @@ GO DROP TABLE babel_3326_Employees GO +drop trigger babel_3326_t1_trigger +GO + +drop trigger babel_3326_t2_trigger +GO + +drop trigger babel_3326_t3_trigger +GO + +drop table babel_3326_t1; +GO + +drop table babel_3326_t2; +GO + +drop table babel_3326_t3; +GO + DROP USER babel_3326_u1 GO diff --git a/test/JDBC/input/BABEL-3326-vu-prepare.mix b/test/JDBC/input/BABEL-3326-vu-prepare.mix index 57cfc8d868..719b674752 100644 --- a/test/JDBC/input/BABEL-3326-vu-prepare.mix +++ b/test/JDBC/input/BABEL-3326-vu-prepare.mix @@ -113,4 +113,38 @@ CREATE TRIGGER [db].[TR_ins_안녕하세요_babel_3326_Employees] ON [db].[babel FOR INSERT AS SELECT 'Trigger db.TR_ins Invoked' -GO \ No newline at end of file +GO + +create table babel_3326_t1 (a varchar) +GO + +create trigger babel_3326_t1_trigger on babel_3326_t1 instead of insert as +begin + select count(*) from inserted; +end; +GO + +create table babel_3326_t2 (a varchar) +GO + +insert into babel_3326_t2 values ('1'); +GO + +create trigger babel_3326_t2_trigger on babel_3326_t2 instead of delete as +begin + select count(*) from deleted; +end; +GO + +create table babel_3326_t3 (a varchar) +GO + +insert into babel_3326_t3 values ('2'); +GO + +create trigger babel_3326_t3_trigger on babel_3326_t3 instead of update as +begin + select count(*) from deleted; + select count(*) from inserted; +end; +GO diff --git a/test/JDBC/input/BABEL-3326-vu-verify.mix b/test/JDBC/input/BABEL-3326-vu-verify.mix index a3dc44062e..150cc6a508 100644 --- a/test/JDBC/input/BABEL-3326-vu-verify.mix +++ b/test/JDBC/input/BABEL-3326-vu-verify.mix @@ -581,3 +581,47 @@ GO ENABLE TRIGGER [TR_ins_안녕하세요_babel_3326_Employees], TR_upd_abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz_babel_3326_Employees ON ALL SERVER GO + +-- The instead of trigger is on and there'll no rows will be inserted +insert into babel_3326_t1 values ('1'); +GO + +DISABLE trigger babel_3326_t1_trigger on babel_3326_t1 +GO + +insert into babel_3326_t1 values ('1'); +GO + +-- The instead of trigger is disabled and new rows are inserted into the table +select * from babel_3326_t1; +GO + +delete from babel_3326_t2; +GO + +select * from babel_3326_t2; +GO + +DISABLE trigger babel_3326_t2_trigger on babel_3326_t2 +GO + +delete from babel_3326_t2; +GO + +select * from babel_3326_t2; +GO + +update babel_3326_t3 set a = '3'; +GO + +select * from babel_3326_t3; +GO + +DISABLE trigger babel_3326_t3_trigger on babel_3326_t3 +GO + +update babel_3326_t3 set a = '3'; +GO + +select * from babel_3326_t3; +GO \ No newline at end of file From a9e5826b203e5797fc245bf020ab157a594f968e Mon Sep 17 00:00:00 2001 From: Ashish Prasad <56514722+hash-16@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:40:04 +0530 Subject: [PATCH 3/6] Revert Sequences scripting (#1940) Revert Support for SSMS scripting PR Signed-off-by: Ashish Prasad --- contrib/babelfishpg_tsql/sql/sys_views.sql | 36 -------- .../babelfishpg_tsql--3.3.0--3.4.0.sql | 35 ------- .../expected/sys_sequences-vu-cleanup.out | 27 ------ .../expected/sys_sequences-vu-prepare.out | 91 ------------------- .../JDBC/expected/sys_sequences-vu-verify.out | 44 --------- .../input/views/sys_sequences-vu-cleanup.sql | 27 ------ .../input/views/sys_sequences-vu-prepare.sql | 91 ------------------- .../input/views/sys_sequences-vu-verify.sql | 17 ---- test/JDBC/upgrade/latest/schedule | 1 - test/python/SMO_script.ps1 | 3 - .../expected/pyodbc/ddl_all_objects.out | 9 -- test/python/expected/pyodbc/ddl_sequence.out | 74 --------------- test/python/expected/pyodbc/ddl_triggers.out | 18 ---- test/python/input/ddl_sequence.sql | 85 ----------------- 14 files changed, 558 deletions(-) delete mode 100644 test/JDBC/expected/sys_sequences-vu-cleanup.out delete mode 100644 test/JDBC/expected/sys_sequences-vu-prepare.out delete mode 100644 test/JDBC/expected/sys_sequences-vu-verify.out delete mode 100644 test/JDBC/input/views/sys_sequences-vu-cleanup.sql delete mode 100644 test/JDBC/input/views/sys_sequences-vu-prepare.sql delete mode 100644 test/JDBC/input/views/sys_sequences-vu-verify.sql delete mode 100644 test/python/expected/pyodbc/ddl_sequence.out delete mode 100644 test/python/input/ddl_sequence.sql diff --git a/contrib/babelfishpg_tsql/sql/sys_views.sql b/contrib/babelfishpg_tsql/sql/sys_views.sql index 6e7c48ebfe..52f63d6c59 100644 --- a/contrib/babelfishpg_tsql/sql/sys_views.sql +++ b/contrib/babelfishpg_tsql/sql/sys_views.sql @@ -3043,42 +3043,6 @@ SELECT WHERE FALSE; GRANT SELECT ON sys.sql_expression_dependencies TO PUBLIC; - -create or replace view sys.sequences as -select - CAST(p.relname as sys.nvarchar(128)) as name - , CAST(p.oid as int) as object_id - , CAST(null as int) as principal_id - , CAST(s.schema_id as int) as schema_id - , CAST(0 as int) as parent_object_id - , CAST('SO' as sys.bpchar(2)) as type - , CAST('SEQUENCE_OBJECT' as sys.nvarchar(60)) as type_desc - , CAST(null as sys.datetime) as create_date - , CAST(null as sys.datetime) as modify_date - , CAST(0 as sys.bit) as is_ms_shipped - , CAST(0 as sys.bit) as is_published - , CAST(0 as sys.bit) as is_schema_published - , CAST(ps.seqstart as sys.sql_variant ) as start_value - , CAST(ps.seqincrement as sys.sql_variant ) as increment - , CAST(ps.seqmin as sys.sql_variant ) as minimum_value - , CAST(ps.seqmax as sys.sql_variant ) as maximum_value - , CASE ps.seqcycle when 't' then CAST(1 as sys.bit) else CAST(0 as sys.bit) end as is_cycling - , CAST(0 as sys.bit ) as is_cached - , CAST(ps.seqcache as int ) as cache_size - , CAST(ps.seqtypid as int ) as system_type_id - , CAST(ps.seqtypid as int ) as user_type_id - , CAST(0 as sys.tinyint ) as precision - , CAST(0 as sys.tinyint ) as scale - , CAST('ABC' as sys.sql_variant ) as current_value - , CAST(0 as sys.bit ) as is_exhausted - , CAST('ABC' as sys.sql_variant ) as last_used_value -from pg_class p -inner join pg_sequence ps on ps.seqrelid = p.oid -inner join sys.schemas s on s.schema_id = p.relnamespace -and p.relkind = 'S' -and has_schema_privilege(s.schema_id, 'USAGE'); -GRANT SELECT ON sys.sequences TO PUBLIC; - CREATE OR REPLACE VIEW sys.database_permissions AS SELECT 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 4a2ea9151e..25946badd2 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 @@ -1290,41 +1290,6 @@ OR Ext.type = 'R'; GRANT SELECT ON sys.server_principals TO PUBLIC; -create or replace view sys.sequences as -select - CAST(p.relname as sys.nvarchar(128)) as name - , CAST(p.oid as int) as object_id - , CAST(null as int) as principal_id - , CAST(s.schema_id as int) as schema_id - , CAST(0 as int) as parent_object_id - , CAST('SO' as char(2)) as type - , CAST('SEQUENCE_OBJECT' as sys.nvarchar(60)) as type_desc - , CAST(null as sys.datetime) as create_date - , CAST(null as sys.datetime) as modify_date - , CAST(0 as sys.bit) as is_ms_shipped - , CAST(0 as sys.bit) as is_published - , CAST(0 as sys.bit) as is_schema_published - , CAST(ps.seqstart as sys.sql_variant ) as start_value - , CAST(ps.seqincrement as sys.sql_variant ) as increment - , CAST(ps.seqmin as sys.sql_variant ) as minimum_value - , CAST(ps.seqmax as sys.sql_variant ) as maximum_value - , CASE ps.seqcycle when 't' then CAST(1 as sys.bit) else CAST(0 as sys.bit) end as is_cycling - , CAST(0 as sys.bit ) as is_cached - , CAST(ps.seqcache as int ) as cache_size - , CAST(ps.seqtypid as int ) as system_type_id - , CAST(ps.seqtypid as int ) as user_type_id - , CAST(0 as sys.tinyint ) as precision - , CAST(0 as sys.tinyint ) as scale - , CAST('ABC' as sys.sql_variant ) as current_value - , CAST(0 as sys.bit ) as is_exhausted - , CAST('ABC' as sys.sql_variant ) as last_used_value -from pg_class p -inner join pg_sequence ps on ps.seqrelid = p.oid -inner join sys.schemas s on s.schema_id = p.relnamespace -and p.relkind = 'S' -and has_schema_privilege(s.schema_id, 'USAGE'); -GRANT SELECT ON sys.sequences TO PUBLIC; - create or replace view sys.schemas as select CAST(ext.orig_name as sys.SYSNAME) as name diff --git a/test/JDBC/expected/sys_sequences-vu-cleanup.out b/test/JDBC/expected/sys_sequences-vu-cleanup.out deleted file mode 100644 index de5f33a723..0000000000 --- a/test/JDBC/expected/sys_sequences-vu-cleanup.out +++ /dev/null @@ -1,27 +0,0 @@ -USE master -GO - -DROP VIEW sys_sequences_vu_prepare_view -GO - -DROP PROC sys_sequences_vu_prepare_proc -GO - -DROP FUNCTION sys_sequences_vu_prepare_func -GO - -DROP FUNCTION sys_sequences_vu_prepare_func1 -GO - -DROP FUNCTION sys_sequences_vu_prepare_func2 -GO - -DROP sequence IF EXISTS test_seq -GO - -DROP sequence IF EXISTS sch.ははははははははははははははははは -GO - -DROP schema IF EXISTS sch -GO - diff --git a/test/JDBC/expected/sys_sequences-vu-prepare.out b/test/JDBC/expected/sys_sequences-vu-prepare.out deleted file mode 100644 index 5d75e42632..0000000000 --- a/test/JDBC/expected/sys_sequences-vu-prepare.out +++ /dev/null @@ -1,91 +0,0 @@ -USE master -GO - -Create sequence test_seq as int -GO - -Create schema sch -GO - -Create sequence sch.ははははははははははははははははは -GO - -CREATE VIEW sys_sequences_vu_prepare_view AS -select - name - , principal_id - , parent_object_id - , type - , type_desc - , create_date - , modify_date - , is_ms_shipped - , is_published - , is_schema_published - , start_value - , increment - , minimum_value - , maximum_value - , is_cycling - , is_cached - , cache_size - , system_type_id - , user_type_id - , precision - , scale - , current_value - , is_exhausted - , last_used_value FROM sys.sequences -GO - -CREATE PROC sys_sequences_vu_prepare_proc AS -SELECT - name - , principal_id - , parent_object_id - , type - , type_desc - , create_date - , modify_date - , is_ms_shipped - , is_published - , is_schema_published - , start_value - , increment - , minimum_value - , maximum_value - , is_cycling - , is_cached - , cache_size - , system_type_id - , user_type_id - , precision - , scale - , current_value - , is_exhausted - , last_used_value FROM sys.sequences -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE is_cycling= 0) -END -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func1() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE name='TEST_SEq'); -END -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func2() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE name='ははははははははははははははははは'); -END -GO diff --git a/test/JDBC/expected/sys_sequences-vu-verify.out b/test/JDBC/expected/sys_sequences-vu-verify.out deleted file mode 100644 index d25fc91980..0000000000 --- a/test/JDBC/expected/sys_sequences-vu-verify.out +++ /dev/null @@ -1,44 +0,0 @@ -USE master -GO - -SELECT * FROM sys_sequences_vu_prepare_view -GO -~~START~~ -nvarchar#!#int#!#int#!#char#!#nvarchar#!#datetime#!#datetime#!#bit#!#bit#!#bit#!#sql_variant#!#sql_variant#!#sql_variant#!#sql_variant#!#bit#!#bit#!#int#!#int#!#int#!#tinyint#!#tinyint#!#sql_variant#!#bit#!#sql_variant -test_seq#!##!#0#!#SO#!#SEQUENCE_OBJECT#!##!##!#0#!#0#!#0#!#1#!#1#!#1#!#2147483647#!#0#!#0#!#1#!#23#!#23#!#0#!#0#!#ABC#!#0#!#ABC -ははははははははははははははははは#!##!#0#!#SO#!#SEQUENCE_OBJECT#!##!##!#0#!#0#!#0#!#1#!#1#!#1#!#9223372036854775807#!#0#!#0#!#1#!#20#!#20#!#0#!#0#!#ABC#!#0#!#ABC -~~END~~ - - -EXEC sys_sequences_vu_prepare_proc -GO -~~START~~ -nvarchar#!#int#!#int#!#char#!#nvarchar#!#datetime#!#datetime#!#bit#!#bit#!#bit#!#sql_variant#!#sql_variant#!#sql_variant#!#sql_variant#!#bit#!#bit#!#int#!#int#!#int#!#tinyint#!#tinyint#!#sql_variant#!#bit#!#sql_variant -test_seq#!##!#0#!#SO#!#SEQUENCE_OBJECT#!##!##!#0#!#0#!#0#!#1#!#1#!#1#!#2147483647#!#0#!#0#!#1#!#23#!#23#!#0#!#0#!#ABC#!#0#!#ABC -ははははははははははははははははは#!##!#0#!#SO#!#SEQUENCE_OBJECT#!##!##!#0#!#0#!#0#!#1#!#1#!#1#!#9223372036854775807#!#0#!#0#!#1#!#20#!#20#!#0#!#0#!#ABC#!#0#!#ABC -~~END~~ - - -SELECT sys_sequences_vu_prepare_func() -GO -~~START~~ -int -2 -~~END~~ - - -SELECT sys_sequences_vu_prepare_func1() -GO -~~START~~ -int -1 -~~END~~ - - -SELECT sys_sequences_vu_prepare_func2() -GO -~~START~~ -int -1 -~~END~~ - diff --git a/test/JDBC/input/views/sys_sequences-vu-cleanup.sql b/test/JDBC/input/views/sys_sequences-vu-cleanup.sql deleted file mode 100644 index de5f33a723..0000000000 --- a/test/JDBC/input/views/sys_sequences-vu-cleanup.sql +++ /dev/null @@ -1,27 +0,0 @@ -USE master -GO - -DROP VIEW sys_sequences_vu_prepare_view -GO - -DROP PROC sys_sequences_vu_prepare_proc -GO - -DROP FUNCTION sys_sequences_vu_prepare_func -GO - -DROP FUNCTION sys_sequences_vu_prepare_func1 -GO - -DROP FUNCTION sys_sequences_vu_prepare_func2 -GO - -DROP sequence IF EXISTS test_seq -GO - -DROP sequence IF EXISTS sch.ははははははははははははははははは -GO - -DROP schema IF EXISTS sch -GO - diff --git a/test/JDBC/input/views/sys_sequences-vu-prepare.sql b/test/JDBC/input/views/sys_sequences-vu-prepare.sql deleted file mode 100644 index 080946dd49..0000000000 --- a/test/JDBC/input/views/sys_sequences-vu-prepare.sql +++ /dev/null @@ -1,91 +0,0 @@ -USE master -GO - -Create sequence test_seq as int -GO - -Create schema sch -GO - -Create sequence sch.ははははははははははははははははは -GO - -CREATE VIEW sys_sequences_vu_prepare_view AS -select - name - , principal_id - , parent_object_id - , type - , type_desc - , create_date - , modify_date - , is_ms_shipped - , is_published - , is_schema_published - , start_value - , increment - , minimum_value - , maximum_value - , is_cycling - , is_cached - , cache_size - , system_type_id - , user_type_id - , precision - , scale - , current_value - , is_exhausted - , last_used_value FROM sys.sequences -GO - -CREATE PROC sys_sequences_vu_prepare_proc AS -SELECT - name - , principal_id - , parent_object_id - , type - , type_desc - , create_date - , modify_date - , is_ms_shipped - , is_published - , is_schema_published - , start_value - , increment - , minimum_value - , maximum_value - , is_cycling - , is_cached - , cache_size - , system_type_id - , user_type_id - , precision - , scale - , current_value - , is_exhausted - , last_used_value FROM sys.sequences -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE is_cycling= 0) -END -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func1() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE name='TEST_SEq'); -END -GO - -CREATE FUNCTION sys_sequences_vu_prepare_func2() -RETURNS INT -AS -BEGIN - RETURN (SELECT COUNT(*) FROM sys.sequences WHERE name='ははははははははははははははははは'); -END -GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_sequences-vu-verify.sql b/test/JDBC/input/views/sys_sequences-vu-verify.sql deleted file mode 100644 index fa0b3317c3..0000000000 --- a/test/JDBC/input/views/sys_sequences-vu-verify.sql +++ /dev/null @@ -1,17 +0,0 @@ -USE master -GO - -SELECT * FROM sys_sequences_vu_prepare_view -GO - -EXEC sys_sequences_vu_prepare_proc -GO - -SELECT sys_sequences_vu_prepare_func() -GO - -SELECT sys_sequences_vu_prepare_func1() -GO - -SELECT sys_sequences_vu_prepare_func2() -GO \ No newline at end of file diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index 8b078d6380..333688f59a 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -468,7 +468,6 @@ Test_ISNULL BABEL-4270 BABEL-4410 BABEL-4231 -sys_sequences sys_asymmetric_keys sys_certificates sys_database_permissions diff --git a/test/python/SMO_script.ps1 b/test/python/SMO_script.ps1 index 0116d148ec..753ab495a3 100644 --- a/test/python/SMO_script.ps1 +++ b/test/python/SMO_script.ps1 @@ -29,7 +29,6 @@ if($script_flag -eq $var_one) $Objects += $db.Views $Objects += $db.StoredProcedures $Objects += $db.UserDefinedFunctions - $Objects += $db.Sequences $Objects += $db.Tables.Indexes $Objects += $db.Tables.Triggers foreach ($CurrentObject in $Objects) @@ -55,9 +54,7 @@ else $Objects += $db.UserDefinedFunctions $SubObjects += $db.Tables.Indexes $SubObjects += $db.Tables.Triggers - $SubObjects += $db.Sequences $SubObjects += $db.Users - foreach ($CurrentObject in $Objects) { if ($CurrentObject.schema -ne $schm -and $CurrentObject.schema -ne $dtb -and $CurrentObject.schema -ne $null -and -not $CurrentObject.IsSystemObject ) diff --git a/test/python/expected/pyodbc/ddl_all_objects.out b/test/python/expected/pyodbc/ddl_all_objects.out index d83312f059..29e0d7d419 100644 --- a/test/python/expected/pyodbc/ddl_all_objects.out +++ b/test/python/expected/pyodbc/ddl_all_objects.out @@ -139,15 +139,6 @@ SET QUOTED_IDENTIFIER ON create function routines_fc6(@fc6_a char) RETURNS char AS BEGIN return @fc6_a END; GO -CREATE SEQUENCE [dbo].[babel_1654_vu_prepare_t_id_seq] - AS [int] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 2147483647 - NO CACHE -GO - ALTER TABLE [dbo].[babel_1654_vu_prepare_t] ADD CONSTRAINT [babel_1654_vu_prepare_t_pkey] PRIMARY KEY NONCLUSTERED ( [id] diff --git a/test/python/expected/pyodbc/ddl_sequence.out b/test/python/expected/pyodbc/ddl_sequence.out deleted file mode 100644 index 6f8eabc83a..0000000000 --- a/test/python/expected/pyodbc/ddl_sequence.out +++ /dev/null @@ -1,74 +0,0 @@ -CREATE SEQUENCE [dbo].[test] - AS [bigint] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 9223372036854775807 - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[isc_sequences_seq1] - AS [bigint] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 5 - CYCLE - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[isc_sequences_seq2] - AS [smallint] - START WITH 2 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 5 - CYCLE - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[isc_sequences_seq3] - AS [smallint] - START WITH 3 - INCREMENT BY 3 - MINVALUE 3 - MAXVALUE 10 - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[isc_sequences_seq4] - AS [int] - START WITH 4 - INCREMENT BY 2 - MINVALUE 2 - MAXVALUE 10 - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[test] - AS [bigint] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 9223372036854775807 - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[test1] - AS [bigint] - START WITH 5 - INCREMENT BY 5 - MINVALUE 1 - MAXVALUE 9223372036854775807 - NO CACHE -GO - -CREATE SEQUENCE [Test_Seq].[test2] - AS [bigint] - START WITH 24329 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 9223372036854775807 - NO CACHE -GO - diff --git a/test/python/expected/pyodbc/ddl_triggers.out b/test/python/expected/pyodbc/ddl_triggers.out index b0fd8b87c6..034cae9ca5 100644 --- a/test/python/expected/pyodbc/ddl_triggers.out +++ b/test/python/expected/pyodbc/ddl_triggers.out @@ -73,21 +73,3 @@ CREATE TRIGGER babel_1654_vu_prepare_trig_t on babel_1654_vu_prepare_t after upd ALTER TABLE [dbo].[babel_1654_vu_prepare_t] ENABLE TRIGGER [babel_1654_vu_prepare_trig_t] GO -CREATE SEQUENCE [dbo].[babel_1654_vu_prepare_employeedata_id_seq] - AS [int] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 2147483647 - NO CACHE -GO - -CREATE SEQUENCE [dbo].[babel_1654_vu_prepare_t_id_seq] - AS [int] - START WITH 1 - INCREMENT BY 1 - MINVALUE 1 - MAXVALUE 2147483647 - NO CACHE -GO - diff --git a/test/python/input/ddl_sequence.sql b/test/python/input/ddl_sequence.sql deleted file mode 100644 index 757a23e022..0000000000 --- a/test/python/input/ddl_sequence.sql +++ /dev/null @@ -1,85 +0,0 @@ -DROP sequence IF EXISTS Test_Seq.test -GO - -DROP sequence IF EXISTS Test_Seq.test1 -GO - -DROP sequence IF EXISTS Test_Seq.test2 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq1 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq2 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq3 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq4 -GO - -DROP sequence IF EXISTS test -GO - -DROP schema IF EXISTS Test_Seq -GO - - -Create sequence test -go - -Create schema Test_Seq -GO - -CREATE SEQUENCE Test_Seq.test START WITH 1 INCREMENT BY 1 ; -GO - -CREATE SEQUENCE Test_Seq.test1 START WITH 5 INCREMENT BY 5 ; -GO - -CREATE SEQUENCE Test_Seq.test2 START WITH 24329 INCREMENT BY 1 ; -GO - -create sequence Test_Seq.isc_sequences_seq1 start with 1 minvalue 1 maxvalue 5 cycle; -go - -create sequence Test_Seq.isc_sequences_seq2 as tinyint start with 2 minvalue 1 maxvalue 5 cycle; -go - -create sequence Test_Seq.isc_sequences_seq3 as smallint start with 3 increment by 3 minvalue 3 maxvalue 10; -go - -create sequence Test_Seq.isc_sequences_seq4 as int start with 4 increment by 2 minvalue 2 maxvalue 10; -go - ---DROP - -DROP sequence IF EXISTS Test_Seq.test -GO - -DROP sequence IF EXISTS test -GO - -DROP sequence IF EXISTS Test_Seq.test1 -GO - -DROP sequence IF EXISTS Test_Seq.test2 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq1 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq2 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq3 -GO - -DROP sequence IF EXISTS Test_Seq.isc_sequences_seq4 -GO - -DROP schema IF EXISTS Test_Seq -GO - - From 3d46cd6b9281d735b9c485f6b327b138cf4b1fea Mon Sep 17 00:00:00 2001 From: Ashish Prasad <56514722+hash-16@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:41:16 +0530 Subject: [PATCH 4/6] Fix Implicit cast from datetimeoffset to other date/time datatypes. (#1927) Due to implicit cast from datetimeoffset to datetime we are getting wrong output --- AT TIME ZONE returns datetimeoffset DECLARE @lvDateEastern DATETIME, @lvDateUTC DATETIME SET @lvDateUTC = '2021-01-01' SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' SELECT @lvDateUTC, @lvDateEastern @lvDateUTC @lvDateEastern ----------------------- ----------------------- 2021-01-01 00:00:00.000 2021-01-01 00:00:00.000 Expected ----------------------- ----------------------- 2021-01-01 00:00:00.000 2020-12-31 19:00:00.000 The above same issue is occuring when we are doing implicit cast from datetimeoffset to time,date,smalldatetime,datetime2. Fixed this issue by excluding the timezone offset addition/subtraction to the original timestamp . Issues Resolved : BABEL-986 Signed-off-by: Ashish Prasad --- .../babelfishpg_common/src/datetimeoffset.c | 10 +-- test/JDBC/expected/BABEL-3474-vu-verify.out | 2 +- .../expected/TestDatetimeoffset-vu-verify.out | 16 ++-- .../babel_datatype_sqlvariant-vu-verify.out | 2 +- .../expected/babel_datatype_sqlvariant.out | 2 +- .../expected/babel_datetime-vu-verify.out | 6 +- test/JDBC/expected/babel_datetime.out | 6 +- test/JDBC/expected/babel_datetime2.out | 10 +-- test/JDBC/expected/babel_datetimeoffset.out | 87 +++++++++++++++++-- test/JDBC/expected/babel_smalldatetime.out | 13 +-- ...up__13_6__TestDatetimeoffset-vu-verify.out | 16 ++-- ...leanup__13_6__babel_datetime-vu-verify.out | 6 +- ...up__13_9__TestDatetimeoffset-vu-verify.out | 16 ++-- ...leanup__13_9__babel_datetime-vu-verify.out | 6 +- ...up__14_3__TestDatetimeoffset-vu-verify.out | 16 ++-- ...leanup__14_3__babel_datetime-vu-verify.out | 6 +- test/JDBC/input/babel_datetimeoffset.sql | 39 +++++++++ 17 files changed, 182 insertions(+), 77 deletions(-) diff --git a/contrib/babelfishpg_common/src/datetimeoffset.c b/contrib/babelfishpg_common/src/datetimeoffset.c index 0e279d7508..78242fac67 100644 --- a/contrib/babelfishpg_common/src/datetimeoffset.c +++ b/contrib/babelfishpg_common/src/datetimeoffset.c @@ -516,7 +516,7 @@ datetimeoffset_smalldatetime(PG_FUNCTION_ARGS) tsql_datetimeoffset *df = PG_GETARG_DATETIMEOFFSET(0); Timestamp result; - datetimeoffset_timestamp_internal(df, &result); + result = df->tsql_ts; CheckSmalldatetimeRange(result); AdjustTimestampForSmallDatetime(&result); @@ -549,7 +549,7 @@ datetimeoffset_datetime(PG_FUNCTION_ARGS) tsql_datetimeoffset *df = PG_GETARG_DATETIMEOFFSET(0); Timestamp result; - datetimeoffset_timestamp_internal(df, &result); + result = df->tsql_ts; CheckDatetimeRange(result); PG_RETURN_TIMESTAMP(result); @@ -581,7 +581,7 @@ datetimeoffset_datetime2(PG_FUNCTION_ARGS) tsql_datetimeoffset *df = PG_GETARG_DATETIMEOFFSET(0); Timestamp result; - datetimeoffset_timestamp_internal(df, &result); + result = df->tsql_ts; CheckDatetime2Range(result); PG_RETURN_TIMESTAMP(result); @@ -648,7 +648,7 @@ datetimeoffset_date(PG_FUNCTION_ARGS) fsec_t fsec; DateADT result; - datetimeoffset_timestamp_internal(df, &time); + time = df->tsql_ts; if (timestamp2tm(time, NULL, tm, &fsec, NULL, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), @@ -669,7 +669,7 @@ datetimeoffset_time(PG_FUNCTION_ARGS) Timestamp time; TimeADT result; - datetimeoffset_timestamp_internal(df, &time); + time = df->tsql_ts; if (time < 0) result = time - (time / USECS_PER_DAY * USECS_PER_DAY) + USECS_PER_DAY; else diff --git a/test/JDBC/expected/BABEL-3474-vu-verify.out b/test/JDBC/expected/BABEL-3474-vu-verify.out index 0d3ed8025a..6e252d5191 100644 --- a/test/JDBC/expected/BABEL-3474-vu-verify.out +++ b/test/JDBC/expected/BABEL-3474-vu-verify.out @@ -396,7 +396,7 @@ SELECT BABEL_3474_vu_prepare_f13() GO ~~START~~ date -2016-12-26 +2016-12-27 ~~END~~ DROP FUNCTION BABEL_3474_vu_prepare_f13 diff --git a/test/JDBC/expected/TestDatetimeoffset-vu-verify.out b/test/JDBC/expected/TestDatetimeoffset-vu-verify.out index 2b51164ec6..3499bd7a22 100644 --- a/test/JDBC/expected/TestDatetimeoffset-vu-verify.out +++ b/test/JDBC/expected/TestDatetimeoffset-vu-verify.out @@ -293,14 +293,14 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime); go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99' AS datetime2) AS datetimeoffset); @@ -314,7 +314,7 @@ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -1900-05-06 21:59:29.9980000 +1900-05-06 13:59:29.9980000 ~~END~~ @@ -381,7 +381,7 @@ select CAST(CAST('1900-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99 +0' AS datetimeoffset) AS time); @@ -416,7 +416,7 @@ select CAST(CAST('2050-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ @@ -425,21 +425,21 @@ select CAST(CAST('2000-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS smalldate go ~~START~~ smalldatetime -2000-06-07 09:29:00.0 +2000-06-06 23:59:00.0 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -2079-06-06 15:59:00.0 +2079-06-06 23:59:00.0 ~~END~~ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -1900-05-06 21:59:00.0 +1900-05-06 13:59:00.0 ~~END~~ select CAST(CAST('2020-03-15 23:59:29.99' AS smalldatetime) AS datetimeoffset); diff --git a/test/JDBC/expected/babel_datatype_sqlvariant-vu-verify.out b/test/JDBC/expected/babel_datatype_sqlvariant-vu-verify.out index c6588ecccd..b3b227cc38 100644 --- a/test/JDBC/expected/babel_datatype_sqlvariant-vu-verify.out +++ b/test/JDBC/expected/babel_datatype_sqlvariant-vu-verify.out @@ -249,7 +249,7 @@ select cast(cast(cast('2020-10-05 09:00:00-9:00' as datetimeoffset) as sql_varia go ~~START~~ datetime2 -2020-10-05 18:00:00.0000000 +2020-10-05 09:00:00.0000000 ~~END~~ -- datetime2 2 datetimeoffset diff --git a/test/JDBC/expected/babel_datatype_sqlvariant.out b/test/JDBC/expected/babel_datatype_sqlvariant.out index 7171622f31..113efdfc51 100644 --- a/test/JDBC/expected/babel_datatype_sqlvariant.out +++ b/test/JDBC/expected/babel_datatype_sqlvariant.out @@ -456,7 +456,7 @@ select cast(cast(cast('2020-10-05 09:00:00-9:00' as datetimeoffset) as sql_varia go ~~START~~ datetime2 -2020-10-05 18:00:00.0000000 +2020-10-05 09:00:00.0000000 ~~END~~ -- datetime2 2 datetimeoffset diff --git a/test/JDBC/expected/babel_datetime-vu-verify.out b/test/JDBC/expected/babel_datetime-vu-verify.out index 99dde07be1..5dc05ac267 100644 --- a/test/JDBC/expected/babel_datetime-vu-verify.out +++ b/test/JDBC/expected/babel_datetime-vu-verify.out @@ -194,21 +194,21 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:12.347 +2079-06-06 23:59:12.347 ~~END~~ -- out of range diff --git a/test/JDBC/expected/babel_datetime.out b/test/JDBC/expected/babel_datetime.out index d1f3e83c60..fc88466a1b 100644 --- a/test/JDBC/expected/babel_datetime.out +++ b/test/JDBC/expected/babel_datetime.out @@ -238,21 +238,21 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:12.347 +2079-06-06 23:59:12.347 ~~END~~ -- out of range diff --git a/test/JDBC/expected/babel_datetime2.out b/test/JDBC/expected/babel_datetime2.out index afb056714c..df31d17cd4 100644 --- a/test/JDBC/expected/babel_datetime2.out +++ b/test/JDBC/expected/babel_datetime2.out @@ -423,35 +423,35 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -2079-06-06 15:59:29.9980000 +2079-06-06 23:59:29.9980000 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime2); go ~~START~~ datetime2 -2079-06-07 09:29:29.9980000 +2079-06-06 23:59:29.9980000 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime2); go ~~START~~ datetime2 -2079-06-07 09:29:12.3456780 +2079-06-06 23:59:12.3456780 ~~END~~ select CAST(CAST('0001-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime2); go ~~START~~ datetime2 -0001-06-07 09:29:12.3456780 +0001-06-06 23:59:12.3456780 ~~END~~ select CAST(CAST('0001-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime2(5)); go ~~START~~ datetime2 -0001-06-07 09:29:12.34568 +0001-06-06 23:59:12.34568 ~~END~~ diff --git a/test/JDBC/expected/babel_datetimeoffset.out b/test/JDBC/expected/babel_datetimeoffset.out index 9bb85835a5..24fa9a2eeb 100644 --- a/test/JDBC/expected/babel_datetimeoffset.out +++ b/test/JDBC/expected/babel_datetimeoffset.out @@ -343,14 +343,14 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime); go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99' AS datetime2) AS datetimeoffset); @@ -364,7 +364,7 @@ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -1900-05-06 21:59:29.9980000 +1900-05-06 13:59:29.9980000 ~~END~~ @@ -431,7 +431,7 @@ select CAST(CAST('1900-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99 +0' AS datetimeoffset) AS time); @@ -466,7 +466,7 @@ select CAST(CAST('2050-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ @@ -475,21 +475,21 @@ select CAST(CAST('2000-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS smalldate go ~~START~~ smalldatetime -2000-06-07 09:29:00.0 +2000-06-06 23:59:00.0 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -2079-06-06 15:59:00.0 +2079-06-06 23:59:00.0 ~~END~~ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -1900-05-06 21:59:00.0 +1900-05-06 13:59:00.0 ~~END~~ select CAST(CAST('2020-03-15 23:59:29.99' AS smalldatetime) AS datetimeoffset); @@ -932,11 +932,82 @@ DECLARE @dto datetimeoffset = CAST('1930-05-06 13:39:29.123456 +0:00' AS datetim exec cmp_datetimeoffset @dto; go +DECLARE @lvDateEastern DATETIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go +~~START~~ +datetime#!#datetime +2021-01-01 00:00:00.0#!#2020-12-31 19:00:00.0 +~~END~~ + + +DECLARE @lvDateEastern DATETIME2, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go +~~START~~ +datetime#!#datetime2 +2021-01-01 00:00:00.0#!#2020-12-31 19:00:00.0000000 +~~END~~ + + +DECLARE @lvDateEastern SMALLDATETIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go +~~START~~ +datetime#!#smalldatetime +2021-01-01 00:00:00.0#!#2020-12-31 19:00:00.0 +~~END~~ + + +DECLARE @lvDateEastern DATE, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go +~~START~~ +datetime#!#date +2021-01-01 00:00:00.0#!#2020-12-31 +~~END~~ + + +DECLARE @lvDateEastern TIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go +~~START~~ +datetime#!#time +2021-01-01 00:00:00.0#!#19:00:00.0000000 +~~END~~ + + +Create table implicit_cast ( a datetime) +go +insert into implicit_cast values (cast('1900-05-06 13:59:29.998 -8:00' as datetimeoffset)) +go +~~ROW COUNT: 1~~ + +Select * from implicit_cast +go +~~START~~ +datetime +1900-05-06 13:59:29.997 +~~END~~ + + -- Clean up drop table datetimeoffset_testing; go drop table t1; go +drop table implicit_cast; +go drop procedure cast_datetimeoffset; go drop procedure cmp_datetimeoffset; diff --git a/test/JDBC/expected/babel_smalldatetime.out b/test/JDBC/expected/babel_smalldatetime.out index a0db023e2c..9e3dd9dd9c 100644 --- a/test/JDBC/expected/babel_smalldatetime.out +++ b/test/JDBC/expected/babel_smalldatetime.out @@ -149,22 +149,22 @@ smalldatetime ~~START~~ smalldatetime -1980-07-08 15:59:00.0 +1980-07-08 23:59:00.0 ~~END~~ ~~START~~ smalldatetime -2010-07-08 15:59:00.0 +2010-07-08 23:59:00.0 ~~END~~ ~~START~~ smalldatetime -1980-07-09 07:59:00.0 +1980-07-08 23:59:00.0 ~~END~~ ~~START~~ smalldatetime -2010-07-09 07:59:00.0 +2010-07-08 23:59:00.0 ~~END~~ -- Cast from smalldatetime @@ -289,11 +289,6 @@ smalldatetime 1900-01-01 00:00:00.0 ~~END~~ -~~START~~ -smalldatetime -2079-06-06 23:00:00.0 -~~END~~ - ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: data out of range for smalldatetime)~~ diff --git a/test/JDBC/expected/latest__verification_cleanup__13_6__TestDatetimeoffset-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_6__TestDatetimeoffset-vu-verify.out index 0941ca14c3..ff7b640414 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_6__TestDatetimeoffset-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_6__TestDatetimeoffset-vu-verify.out @@ -293,14 +293,14 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime); go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99' AS datetime2) AS datetimeoffset); @@ -314,7 +314,7 @@ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -1900-05-06 21:59:29.9980000 +1900-05-06 13:59:29.9980000 ~~END~~ @@ -381,7 +381,7 @@ select CAST(CAST('1900-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99 +0' AS datetimeoffset) AS time); @@ -416,7 +416,7 @@ select CAST(CAST('2050-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ @@ -425,21 +425,21 @@ select CAST(CAST('2000-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS smalldate go ~~START~~ smalldatetime -2000-06-07 09:29:00.0 +2000-06-06 23:59:00.0 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -2079-06-06 15:59:00.0 +2079-06-06 23:59:00.0 ~~END~~ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -1900-05-06 21:59:00.0 +1900-05-06 13:59:00.0 ~~END~~ select CAST(CAST('2020-03-15 23:59:29.99' AS smalldatetime) AS datetimeoffset); 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 beb8038af8..de673fd4ae 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 @@ -194,21 +194,21 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:12.347 +2079-06-06 23:59:12.347 ~~END~~ -- out of range diff --git a/test/JDBC/expected/latest__verification_cleanup__13_9__TestDatetimeoffset-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__13_9__TestDatetimeoffset-vu-verify.out index 0941ca14c3..ff7b640414 100644 --- a/test/JDBC/expected/latest__verification_cleanup__13_9__TestDatetimeoffset-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__13_9__TestDatetimeoffset-vu-verify.out @@ -293,14 +293,14 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime); go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99' AS datetime2) AS datetimeoffset); @@ -314,7 +314,7 @@ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -1900-05-06 21:59:29.9980000 +1900-05-06 13:59:29.9980000 ~~END~~ @@ -381,7 +381,7 @@ select CAST(CAST('1900-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99 +0' AS datetimeoffset) AS time); @@ -416,7 +416,7 @@ select CAST(CAST('2050-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ @@ -425,21 +425,21 @@ select CAST(CAST('2000-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS smalldate go ~~START~~ smalldatetime -2000-06-07 09:29:00.0 +2000-06-06 23:59:00.0 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -2079-06-06 15:59:00.0 +2079-06-06 23:59:00.0 ~~END~~ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -1900-05-06 21:59:00.0 +1900-05-06 13:59:00.0 ~~END~~ select CAST(CAST('2020-03-15 23:59:29.99' AS smalldatetime) AS datetimeoffset); 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 beb8038af8..de673fd4ae 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 @@ -194,21 +194,21 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:12.347 +2079-06-06 23:59:12.347 ~~END~~ -- out of range diff --git a/test/JDBC/expected/latest__verification_cleanup__14_3__TestDatetimeoffset-vu-verify.out b/test/JDBC/expected/latest__verification_cleanup__14_3__TestDatetimeoffset-vu-verify.out index 0941ca14c3..ff7b640414 100644 --- a/test/JDBC/expected/latest__verification_cleanup__14_3__TestDatetimeoffset-vu-verify.out +++ b/test/JDBC/expected/latest__verification_cleanup__14_3__TestDatetimeoffset-vu-verify.out @@ -293,14 +293,14 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime); go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99' AS datetime2) AS datetimeoffset); @@ -314,7 +314,7 @@ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS datetime2 go ~~START~~ datetime2 -1900-05-06 21:59:29.9980000 +1900-05-06 13:59:29.9980000 ~~END~~ @@ -381,7 +381,7 @@ select CAST(CAST('1900-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ select CAST(CAST('1920-05-25 00:59:29.99 +0' AS datetimeoffset) AS time); @@ -416,7 +416,7 @@ select CAST(CAST('2050-05-06 23:59:29.998+8:00' AS datetimeoffset) AS time); go ~~START~~ time -15:59:29.9980000 +23:59:29.9980000 ~~END~~ @@ -425,21 +425,21 @@ select CAST(CAST('2000-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS smalldate go ~~START~~ smalldatetime -2000-06-07 09:29:00.0 +2000-06-06 23:59:00.0 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -2079-06-06 15:59:00.0 +2079-06-06 23:59:00.0 ~~END~~ select CAST(CAST('1900-05-06 13:59:29.998 -8:00' AS datetimeoffset) AS smalldatetime); go ~~START~~ smalldatetime -1900-05-06 21:59:00.0 +1900-05-06 13:59:00.0 ~~END~~ select CAST(CAST('2020-03-15 23:59:29.99' AS smalldatetime) AS datetimeoffset); 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 beb8038af8..de673fd4ae 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 @@ -194,21 +194,21 @@ select CAST(CAST('2079-06-06 23:59:29.998 +8:00' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-06 15:59:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:29.998 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:29.997 +2079-06-06 23:59:29.997 ~~END~~ select CAST(CAST('2079-06-06 23:59:12.345678 -9:30' AS datetimeoffset) AS datetime) go ~~START~~ datetime -2079-06-07 09:29:12.347 +2079-06-06 23:59:12.347 ~~END~~ -- out of range diff --git a/test/JDBC/input/babel_datetimeoffset.sql b/test/JDBC/input/babel_datetimeoffset.sql index fde4171098..3001f08b24 100644 --- a/test/JDBC/input/babel_datetimeoffset.sql +++ b/test/JDBC/input/babel_datetimeoffset.sql @@ -337,11 +337,50 @@ DECLARE @dto datetimeoffset = CAST('1930-05-06 13:39:29.123456 +0:00' AS datetim exec cmp_datetimeoffset @dto; go +DECLARE @lvDateEastern DATETIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go + +DECLARE @lvDateEastern DATETIME2, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go + +DECLARE @lvDateEastern SMALLDATETIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go + +DECLARE @lvDateEastern DATE, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go + +DECLARE @lvDateEastern TIME, @lvDateUTC DATETIME +SET @lvDateUTC = '2021-01-01' +SET @lvDateEastern = @lvDateUTC AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' +SELECT @lvDateUTC, @lvDateEastern +go + +Create table implicit_cast ( a datetime) +go +insert into implicit_cast values (cast('1900-05-06 13:59:29.998 -8:00' as datetimeoffset)) +go +Select * from implicit_cast +go + -- Clean up drop table datetimeoffset_testing; go drop table t1; go +drop table implicit_cast; +go drop procedure cast_datetimeoffset; go drop procedure cmp_datetimeoffset; From 2ad73513196586b8a94155756f74d289292ed7e4 Mon Sep 17 00:00:00 2001 From: Aditya Verma <45755382+aadityavermaa@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:58:13 +0530 Subject: [PATCH 5/6] Support for DBCC CHECKIDENT (#1646) This update introduces support for the `DBCC CHECKIDENT` command within Babelfish, allowing users to reset the current value of an identity column directly through T-SQL. Previously, this operation required the use of the `Setval()` command from the PostgreSQL endpoint. Notably, this marks the initial implementation of a DBCC command in Babelfish, encompassing the introduction of syntax for DBCC commands. The design has been built with scalability in mind, making it easier to incorporate additional DBCC commands in the future. Issues Resolved BABEL-3201 Signed-off-by: Sandeep Kumawat --- contrib/babelfishpg_tsql/antlr/TSqlLexer.g4 | 29 + contrib/babelfishpg_tsql/antlr/TSqlParser.g4 | 72 +- contrib/babelfishpg_tsql/src/codegen.c | 1 + contrib/babelfishpg_tsql/src/iterative_exec.c | 3 + contrib/babelfishpg_tsql/src/pl_exec-2.c | 360 +++++++- contrib/babelfishpg_tsql/src/pl_funcs-2.c | 27 + contrib/babelfishpg_tsql/src/pl_funcs.c | 2 + contrib/babelfishpg_tsql/src/pltsql.h | 35 + contrib/babelfishpg_tsql/src/stmt_walker.c | 2 + contrib/babelfishpg_tsql/src/stmt_walker.h | 2 + contrib/babelfishpg_tsql/src/tsqlIface.cpp | 117 ++- contrib/babelfishpg_tsql/src/tsqlNodes.h | 1 + .../src/tsqlUnsupportedFeatureHandler.cpp | 25 +- test/JDBC/expected/BABEL-3201-vu-cleanup.out | 59 ++ test/JDBC/expected/BABEL-3201-vu-prepare.out | 163 ++++ test/JDBC/expected/BABEL-3201-vu-verify.out | 813 ++++++++++++++++++ test/JDBC/expected/BABEL-UNSUPPORTED.out | 2 +- test/JDBC/input/BABEL-3201-vu-cleanup.sql | 59 ++ test/JDBC/input/BABEL-3201-vu-prepare.sql | 123 +++ test/JDBC/input/BABEL-3201-vu-verify.mix | 487 +++++++++++ test/python/expected/pyodbc/BABEL-3201.out | 56 ++ test/python/input/isolation/BABEL-3201.spec | 42 + 22 files changed, 2470 insertions(+), 10 deletions(-) create mode 100644 test/JDBC/expected/BABEL-3201-vu-cleanup.out create mode 100644 test/JDBC/expected/BABEL-3201-vu-prepare.out create mode 100644 test/JDBC/expected/BABEL-3201-vu-verify.out create mode 100644 test/JDBC/input/BABEL-3201-vu-cleanup.sql create mode 100644 test/JDBC/input/BABEL-3201-vu-prepare.sql create mode 100644 test/JDBC/input/BABEL-3201-vu-verify.mix create mode 100644 test/python/expected/pyodbc/BABEL-3201.out create mode 100644 test/python/input/isolation/BABEL-3201.spec diff --git a/contrib/babelfishpg_tsql/antlr/TSqlLexer.g4 b/contrib/babelfishpg_tsql/antlr/TSqlLexer.g4 index d52ea2f0a8..53707785c5 100644 --- a/contrib/babelfishpg_tsql/antlr/TSqlLexer.g4 +++ b/contrib/babelfishpg_tsql/antlr/TSqlLexer.g4 @@ -155,16 +155,22 @@ CHANGETABLE: C H A N G E T A B L E; CHANGE_RETENTION: C H A N G E UNDERLINE R E T E N T I O N; CHANGE_TRACKING: C H A N G E UNDERLINE T R A C K I N G; CHECK: C H E C K; +CHECKDB: C H E C K D B; +CHECKFILEGROUP: C H E C K F I L E G R O U P; +CHECKIDENT: C H E C K I D E N T; CHECKPOINT: C H E C K P O I N T; CHECKSUM: C H E C K S U M; CHECKSUM_AGG: C H E C K S U M UNDERLINE A G G; +CHECKTABLE: C H E C K T A B L E; CHECK_EXPIRATION: C H E C K UNDERLINE E X P I R A T I O N; CHECK_POLICY: C H E C K UNDERLINE P O L I C Y; CLASSIFIER: C L A S S I F I E R; CLASSIFIER_FUNCTION: C L A S S I F I E R UNDERLINE F U N C T I O N; CLEANUP: C L E A N U P; +CLEANTABLE: C L E A N T A B L E; CLEANUP_POLICY: C L E A N U P UNDERLINE P O L I C Y; CLEAR: C L E A R; +CLONEDATABASE: C L O N E D A T A B A S E; CLOSE: C L O S E; CLUSTER: C L U S T E R; CLUSTERED: C L U S T E R E D; @@ -248,6 +254,7 @@ DATE_CORRELATION_OPTIMIZATION: D A T E UNDERLINE C O R R E L DAY: D A Y; DAYS: D A Y S; DBCC: D B C C; +DBREINDEX: D B R E I N D E X; DB_CHAINING: D B UNDERLINE C H A I N I N G; DB_FAILOVER: D B UNDERLINE F A I L O V E R; DDL: D D L; @@ -298,6 +305,7 @@ DOLLAR_ROWGUID: DOLLAR R O W G U I D; DOLLAR_TO_ID: DOLLAR T O UNDERLINE I D; // graph DOUBLE: D O U B L E; DROP: D R O P; +DROPCLEANBUFFERS: D R O P C L E A N B U F F E R S; DTC_SUPPORT: D T C UNDERLINE S U P P O R T; DUMP: D U M P; DYNAMIC: D Y N A M I C; @@ -387,6 +395,9 @@ FORMAT: F O R M A T; FORWARD_ONLY: F O R W A R D UNDERLINE O N L Y; FORMAT_OPTIONS: F O R M A T UNDERLINE O P T I O N S; FORMAT_TYPE: F O R M A T UNDERLINE T Y P E; +FREEPROCCACHE: F R E E P R O C C A C H E; +FREESESSIONCACHE: F R E E S E S S I O N C A C H E; +FREESYSTEMCACHE: F R E E S Y S T E M C A C H E; FREETEXT: F R E E T E X T; FREETEXTTABLE: F R E E T E X T T A B L E; FROM: F R O M; @@ -424,6 +435,7 @@ HASHED: H A S H E D; HAVING: H A V I N G; HEALTHCHECKTIMEOUT: H E A L T H C H E C K T I M E O U T; HEALTH_CHECK_TIMEOUT: H E A L T H UNDERLINE C H E C K UNDERLINE T I M E O U T; +HELP: H E L P; HIDDEN_RENAMED: H I D D E N; HIGH: H I G H; HINT: H I N T; @@ -433,6 +445,7 @@ HOLDLOCK: H O L D L O C K; HONOR_BROKER_PRIORITY: H O N O R UNDERLINE B R O K E R UNDERLINE P R I O R I T Y; HOUR: H O U R; HOURS: H O U R S; +INDEXDEFRAG: I N D E X D E F R A G; IDENTITY: I D E N T I T Y; IDENTITYCOL: I D E N T I T Y C O L; IDENTITY_INSERT: I D E N T I T Y UNDERLINE I N S E R T; @@ -455,6 +468,7 @@ INIT: I N I T; INITIATOR: I N I T I A T O R; INNER: I N N E R; INPUT: I N P U T; +INPUTBUFFER: I N P U T B U F F E R; INSENSITIVE: I N S E N S I T I V E; INSERT: I N S E R T; INSERTED: I N S E R T E D; @@ -603,6 +617,7 @@ NONE: N O N E; NON_TRANSACTED_ACCESS: N O N UNDERLINE T R A N S A C T E D UNDERLINE A C C E S S; NORECOMPUTE: N O R E C O M P U T E; NORECOVERY: N O R E C O V E R Y; +NORESEED: N O R E S E E D; NOREWIND: N O R E W I N D; NOSKIP: N O S K I P; NOT: N O T; @@ -643,6 +658,7 @@ OPENDATASOURCE: O P E N D A T A S O U R C E; OPENJSON: O P E N J S O N; OPENQUERY: O P E N Q U E R Y; OPENROWSET: O P E N R O W S E T; +OPENTRAN: O P E N T R A N; OPENXML: O P E N X M L; OPEN_EXISTING: O P E N UNDERLINE E X I S T I N G; OPERATIONS: O P E R A T I O N S; @@ -655,6 +671,7 @@ ORDER: O R D E R; OUT: O U T; OUTER: O U T E R; OUTPUT: O U T P U T; +OUTPUTBUFFER: O U T P U T B U F F E R; OVER: O V E R; OVERRIDE: O V E R R I D E; OWNER: O W N E R; @@ -711,6 +728,7 @@ PRIVATE: P R I V A T E; PRIVATE_KEY: P R I V A T E UNDERLINE K E Y; PRIVILEGES: P R I V I L E G E S; PROC: P R O C; +PROCCACHE: P R O C C A C H E; PROCEDURE: P R O C E D U R E; PROCEDURE_CACHE: P R O C E D U R E UNDERLINE C A C H E; PROCEDURE_NAME: P R O C E D U R E UNDERLINE N A M E; @@ -781,6 +799,7 @@ REQUEST_MEMORY_GRANT_TIMEOUT_SEC: R E Q U E S T UNDERLINE M E M REQUIRED: R E Q U I R E D; REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT: R E Q U I R E D UNDERLINE S Y N C H R O N I Z E D UNDERLINE S E C O N D A R I E S UNDERLINE T O UNDERLINE C O M M I T; RESAMPLE: R E S A M P L E; +RESEED: R E S E E D; RESERVE_DISK_SPACE: R E S E R V E UNDERLINE D I S K UNDERLINE S P A C E; RESET: R E S E T; RESOURCE: R E S O U R C E; @@ -871,10 +890,14 @@ SETS: S E T S; SETTINGS: S E T T I N G S; SETUSER: S E T U S E R; SHARE: S H A R E; +SHOWCONTIG: S H O W C O N T I G; SHOWPLAN: S H O W P L A N; SHOWPLAN_ALL: S H O W P L A N UNDERLINE A L L; SHOWPLAN_TEXT: S H O W P L A N UNDERLINE T E X T; SHOWPLAN_XML: S H O W P L A N UNDERLINE X M L; +SHOW_STATISTICS: S H O W UNDERLINE S T A T I S T I C S; +SHRINKDATABASE: S H R I N K D A T A B A S E; +SHRINKFILE: S H R I N K F I L E; SHRINKLOG: S H R I N K L O G; SHUTDOWN: S H U T D O W N; SID: S I D; @@ -899,6 +922,7 @@ SQL: S Q L; SQLDUMPERFLAGS: S Q L D U M P E R F L A G S; SQLDUMPERPATH: S Q L D U M P E R P A T H; SQLDUMPERTIMEOUT: S Q L D U M P E R T I M E O U T S; +SQLPERF: S Q L P E R F; STALE_CAPTURE_POLICY_THRESHOLD: S T A L E UNDERLINE C A P T U R E UNDERLINE P O L I C Y UNDERLINE T H R E S H O L D; STALE_QUERY_THRESHOLD_DAYS: S T A L E UNDERLINE Q U E R Y UNDERLINE T H R E S H O L D UNDERLINE D A Y S; STANDBY: S T A N D B Y; @@ -970,7 +994,10 @@ TOSTRING: T O S T R I N G; TOTAL_COMPILE_CPU_TIME_MS: T O T A L UNDERLINE C O M P I L E UNDERLINE C P U UNDERLINE T I M E UNDERLINE M S; TOTAL_EXECUTION_CPU_TIME_MS: T O T A L UNDERLINE E X E C U T I O N UNDERLINE C P U UNDERLINE T I M E UNDERLINE M S; TRACE: T R A C E; +TRACEOFF: T R A C E O F F; +TRACEON: T R A C E O N; TRACKING: T R A C K I N G; +TRACESTATUS: T R A C E S T A T U S; TRACK_CAUSALITY: T R A C K UNDERLINE C A U S A L I T Y; TRACK_COLUMNS_UPDATED: T R A C K UNDERLINE C O L U M N S UNDERLINE U P D A T E D; TRAN: T R A N; @@ -1009,6 +1036,7 @@ UNPIVOT: U N P I V O T; UNSAFE: U N S A F E; UOW: U O W; UPDATE: U P D A T E; +UPDATEUSAGE: U P D A T E U S A G E; UPDATETEXT: U P D A T E T E X T; UPDLOCK: U P D L O C K; URL: U R L; @@ -1016,6 +1044,7 @@ USE: U S E; USE_TYPE_DEFAULT: U S E UNDERLINE T Y P E UNDERLINE D E F A U L T; USED: U S E D; USER: U S E R; +USEROPTIONS: U S E R O P T I O N S; USING: U S I N G; VALIDATION: V A L I D A T I O N; VALID_XML: V A L I D UNDERLINE X M L; diff --git a/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 b/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 index 93267cdeaa..58b6428f33 100644 --- a/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 +++ b/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 @@ -3094,19 +3094,53 @@ shutdown_statement ; dbcc_statement - : DBCC name=dbcc_command ( LR_BRACKET expression_list RR_BRACKET )? (WITH dbcc_options)? SEMI? + : DBCC CHECKIDENT ( LR_BRACKET table_name_string ( (COMMA NORESEED) | (COMMA RESEED (COMMA MINUS? new_value=(DECIMAL | FLOAT))?) )? RR_BRACKET ) (WITH dbcc_options)? SEMI? + | DBCC name=dbcc_command ( LR_BRACKET expression_list RR_BRACKET )? (WITH dbcc_options)? SEMI? //These are dbcc commands with strange syntax that doesn't fit the regular dbcc syntax | DBCC SHRINKLOG ( LR_BRACKET SIZE EQUAL (constant_expression| id | DEFAULT) (KB | MB | GB | TB)? RR_BRACKET )? (WITH dbcc_options)? SEMI? - ; + ; dbcc_command - : ID | keyword + : ID + | CHECKDB + | CHECKFILEGROUP + | CHECKTABLE + | CLEANTABLE + | CLONEDATABASE + | DBREINDEX + | DROPCLEANBUFFERS + | FREEPROCCACHE + | FREESESSIONCACHE + | FREESYSTEMCACHE + | HELP + | INDEXDEFRAG + | INPUTBUFFER + | OPENTRAN + | OUTPUTBUFFER + | PROCCACHE + | SHOW_STATISTICS + | SHOWCONTIG + | SHRINKDATABASE + | SHRINKFILE + | SQLPERF + | TRACEOFF + | TRACEON + | TRACESTATUS + | UPDATEUSAGE + | USEROPTIONS ; dbcc_options : ID (COMMA ID)? ; + +table_name_string + : table = id + | char_string + ; + + execute_as_clause : (EXECUTE|EXEC) AS (CALLER | SELF | OWNER | char_string) ; @@ -4271,15 +4305,20 @@ keyword | CHANGETABLE | CHANGE_RETENTION | CHANGE_TRACKING + | CHECKDB + | CHECKFILEGROUP | CHECKSUM | CHECKSUM_AGG + | CHECKTABLE | CHECK_EXPIRATION | CHECK_POLICY | CLASSIFIER | CLASSIFIER_FUNCTION + | CLEANTABLE | CLEANUP | CLEANUP_POLICY - | CLEAR + | CLEAR + | CLONEDATABASE | CLUSTER | COALESCE | COLLECTION @@ -4343,6 +4382,7 @@ keyword | DATE_FORMAT | DAY | DAYS + | DBREINDEX | DB_CHAINING | DB_FAILOVER | DDL @@ -4376,6 +4416,7 @@ keyword | DISTRIBUTED_AGG | DISTRIBUTION | DOCUMENT + | DROPCLEANBUFFERS | DTC_SUPPORT | DYNAMIC | EDGE @@ -4449,6 +4490,9 @@ keyword | FORMAT_OPTIONS | FORMAT_TYPE | FORWARD_ONLY + | FREEPROCCACHE + | FREESESSIONCACHE + | FREESYSTEMCACHE | FULLSCAN | FULLTEXT | GB @@ -4477,6 +4521,7 @@ keyword | HASHED | HEALTHCHECKTIMEOUT | HEALTH_CHECK_TIMEOUT + | HELP | HIDDEN_RENAMED | HIGH | HINT @@ -4499,10 +4544,12 @@ keyword | INCLUDE_NULL_VALUES | INCREMENT | INCREMENTAL + | INDEXDEFRAG | INFINITE | INIT | INITIATOR | INPUT + | INPUTBUFFER | INSENSITIVE | INSERTED | INSTEAD @@ -4668,6 +4715,7 @@ keyword | ONLY | ON_FAILURE | OPENJSON + | OPENTRAN | OPEN_EXISTING | OPERATIONS | OPERATION_MODE @@ -4675,6 +4723,7 @@ keyword | OPTIMIZE | OUT | OUTPUT + | OUTPUTBUFFER | OVERRIDE | OWNER | OWNERSHIP @@ -4722,6 +4771,7 @@ keyword | PRIVATE | PRIVATE_KEY | PRIVILEGES + | PROCCACHE | PROCEDURE_CACHE | PROCEDURE_NAME | PROCESS @@ -4850,10 +4900,14 @@ keyword | SETS | SETTINGS | SHARE + | SHOWCONTIG | SHOWPLAN | SHOWPLAN_ALL | SHOWPLAN_TEXT | SHOWPLAN_XML + | SHOW_STATISTICS + | SHRINKDATABASE + | SHRINKFILE | SHRINKLOG | SID | SIGNATURE @@ -4876,6 +4930,7 @@ keyword | SQLDUMPERFLAGS | SQLDUMPERPATH | SQLDUMPERTIMEOUT + | SQLPERF | STALE_CAPTURE_POLICY_THRESHOLD | STALE_QUERY_THRESHOLD_DAYS | STANDBY @@ -4937,6 +4992,9 @@ keyword | TOTAL_COMPILE_CPU_TIME_MS | TOTAL_EXECUTION_CPU_TIME_MS | TRACE + | TRACEOFF + | TRACEON + | TRACESTATUS | TRACKING | TRACK_CAUSALITY | TRACK_COLUMNS_UPDATED @@ -4966,8 +5024,10 @@ keyword | UNMASK | UNSAFE | UOW + | UPDATEUSAGE | URL | USED + | USEROPTIONS | USE_TYPE_DEFAULT | USING | VALIDATION @@ -5103,8 +5163,8 @@ id | DOUBLE_QUOTE_ID // this is a double-quoted identifier in case of SET QUOTED_IDENTIFIER ON | SQUARE_BRACKET_ID | keyword - | DOLLAR_IDENTITY - | DOLLAR_ROWGUID + | DOLLAR_IDENTITY + | DOLLAR_ROWGUID | id colon_colon id ; diff --git a/contrib/babelfishpg_tsql/src/codegen.c b/contrib/babelfishpg_tsql/src/codegen.c index c6726ba373..d039264383 100644 --- a/contrib/babelfishpg_tsql/src/codegen.c +++ b/contrib/babelfishpg_tsql/src/codegen.c @@ -302,6 +302,7 @@ stmt_default_act(Walker_context *ctx, PLtsql_stmt *stmt) case PLTSQL_STMT_GRANTDB: case PLTSQL_STMT_GRANTSCHEMA: case PLTSQL_STMT_INSERT_BULK: + case PLTSQL_STMT_DBCC: case PLTSQL_STMT_SET_EXPLAIN_MODE: /* TSQL-only executable node */ case PLTSQL_STMT_SAVE_CTX: diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index 24ca677e44..6b0be3f33b 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -837,6 +837,9 @@ dispatch_stmt(PLtsql_execstate *estate, PLtsql_stmt *stmt) } exec_stmt_restore_ctx_partial(estate, (PLtsql_stmt_restore_ctx_partial *) stmt); break; + case PLTSQL_STMT_DBCC: + exec_stmt_dbcc(estate, (PLtsql_stmt_dbcc *) stmt); + break; case PLTSQL_STMT_KILL: exec_stmt_kill(estate, (PLtsql_stmt_kill *) stmt); break; diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index ef9c40a9e4..a30afeb1f4 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -10,6 +10,7 @@ #include "executor/tstoreReceiver.h" #include "nodes/parsenodes.h" #include "utils/acl.h" +#include "storage/lmgr.h" #include "storage/procarray.h" #include "pltsql_bulkcopy.h" #include "table_variable_mvcc.h" @@ -53,6 +54,7 @@ static int exec_stmt_grantdb(PLtsql_execstate *estate, PLtsql_stmt_grantdb *stmt static int exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt); static int exec_stmt_insert_execute_select(PLtsql_execstate *estate, PLtsql_expr *expr); static int exec_stmt_insert_bulk(PLtsql_execstate *estate, PLtsql_stmt_insert_bulk *expr); +static int exec_stmt_dbcc(PLtsql_execstate *estate, PLtsql_stmt_dbcc *stmt); extern Datum pltsql_inline_handler(PG_FUNCTION_ARGS); static char *transform_tsql_temp_tables(char *dynstmt); @@ -91,7 +93,7 @@ extern void pltsql_commit_not_required_impl_txn(PLtsql_execstate *estate); int execute_batch(PLtsql_execstate *estate, char *batch, InlineCodeBlockArgs *args, List *params); Oid get_role_oid(const char *rolename, bool missing_ok); bool is_member_of_role(Oid member, Oid role); - +void exec_stmt_dbcc_checkident(PLtsql_stmt_dbcc *stmt); extern PLtsql_function *find_cached_batch(int handle); extern SPIPlanPtr prepare_stmt_exec(PLtsql_execstate *estate, PLtsql_function *func, PLtsql_stmt_exec *stmt, bool keepplan); @@ -235,6 +237,9 @@ exec_tsql_stmt(PLtsql_execstate *estate, PLtsql_stmt *stmt, PLtsql_stmt *save_es rc = exec_stmt_insert_bulk(estate, (PLtsql_stmt_insert_bulk *) stmt); break; + case PLTSQL_STMT_DBCC: + rc = exec_stmt_dbcc(estate, (PLtsql_stmt_dbcc *) stmt); + break; default: estate->err_stmt = save_estmt; elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); @@ -3113,6 +3118,359 @@ exec_stmt_insert_bulk(PLtsql_execstate *estate, PLtsql_stmt_insert_bulk *stmt) return PLTSQL_RC_OK; } + +int exec_stmt_dbcc(PLtsql_execstate *estate, PLtsql_stmt_dbcc *stmt) +{ + switch (stmt->dbcc_stmt_type) + { + case PLTSQL_DBCC_CHECKIDENT: + exec_stmt_dbcc_checkident(stmt); + break; + default: + Assert(0); + } + return PLTSQL_RC_OK; +} + + +void exec_stmt_dbcc_checkident(PLtsql_stmt_dbcc *stmt) +{ + struct dbcc_checkident dbcc_stmt = stmt->dbcc_stmt_data.dbcc_checkident; + Relation rel; + TupleDesc tupdesc; + char *db_name = NULL; + char *max_identity_value_str = NULL; + char *query = NULL; + char *attname; + char *token; + const char *schema_name; + const char *nsp_name; + const char *user; + const char *guest_role_name; + const char *dbo_role_name; + const char *login; + int64 max_identity_value = 0; + int64 cur_identity_value = 0; + int attnum; + int rc = 0; + int64 reseed_value = 0; + Oid nsp_oid; + Oid table_oid; + Oid seqid = InvalidOid; + Oid current_user_id = GetUserId(); + volatile bool cur_value_is_null = true; + bool login_is_db_owner; + char message[200]; + bool is_float_value; + bool is_cross_db = false; + + + if(dbcc_stmt.new_reseed_value) + { + /* If float value is passed as reseed_value, only part before decimal is considered */ + is_float_value = strchr(dbcc_stmt.new_reseed_value, '.') != NULL; + + if (is_float_value) + { + if (dbcc_stmt.new_reseed_value[0] == '.' || + (dbcc_stmt.new_reseed_value[0] == '-' && dbcc_stmt.new_reseed_value[1] == '.')) + reseed_value = 0; + else + { + token = strtok(dbcc_stmt.new_reseed_value, "."); + reseed_value = pg_strtoint64(token); + pfree(token); + } + } + else + reseed_value = pg_strtoint64(dbcc_stmt.new_reseed_value); + } + + db_name = get_cur_db_name(); + if (dbcc_stmt.db_name) + { + if (!DbidIsValid(get_db_id(dbcc_stmt.db_name))) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", dbcc_stmt.db_name))); + } + if (pg_strncasecmp(db_name, dbcc_stmt.db_name, NAMEDATALEN) != 0) + { + is_cross_db = true; + pfree(db_name); + db_name = pstrdup(dbcc_stmt.db_name); + } + } + + user = get_user_for_database(db_name); + login_is_db_owner = 0 == strncmp(GetUserNameFromId(GetSessionUserId(), false), + get_owner_of_db(db_name), NAMEDATALEN); + + /* Raise an error if the login does not have access to the database */ + if(is_cross_db) + { + if (user) + SetCurrentRoleId(GetSessionUserId(), false); + else + { + login = GetUserNameFromId(GetSessionUserId(), false); + pfree(db_name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("The server principal \"%s\" is not able to access " + "the database \"%s\" under the current security context", + login, dbcc_stmt.db_name))); + } + } + + /* get physical schema name from logical schema name */ + if (dbcc_stmt.schema_name) + { + schema_name = dbcc_stmt.schema_name; + nsp_name = get_physical_schema_name(db_name, dbcc_stmt.schema_name); + } + else + { + /* + * If schema_name is not provided, find default schema for current user + * and get physical schema name + */ + guest_role_name = get_guest_role_name(db_name); + dbo_role_name = get_dbo_role_name(db_name); + + /* user will never be null here as cross-db calls are already handled */ + Assert(user != NULL); + + schema_name = get_authid_user_ext_schema_name((const char *) db_name, user); + if ((dbo_role_name && strcmp(user, dbo_role_name) == 0)) + { + nsp_name = get_dbo_schema_name(db_name); + } + else if ((guest_role_name && strcmp(user, guest_role_name) == 0)) + { + nsp_name = get_guest_schema_name(db_name); + } + else + { + nsp_name = get_physical_schema_name(db_name, schema_name); + } + } + pfree(db_name); + + /* + * get schema oid from physical schema name, it will return InvalidOid if + * user don't have lookup access + */ + nsp_oid = get_namespace_oid(nsp_name, false); + + if(!OidIsValid(nsp_oid)) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_SCHEMA), + errmsg("schema \"%s\" does not exist", schema_name))); + } + + /* Permission check */ + if (!(pg_namespace_ownercheck(nsp_oid, GetUserId()) || + has_privs_of_role(GetSessionUserId(), get_role_oid("sysadmin", false)) || + login_is_db_owner)) + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA, nsp_name); + + table_oid = get_relname_relid(dbcc_stmt.table_name, nsp_oid); + if(!OidIsValid(table_oid)) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("relation \"%s\" does not exist", dbcc_stmt.table_name))); + } + + rel = RelationIdGetRelation(table_oid); + tupdesc = RelationGetDescr(rel); + + /* Find Identity column in table and associated sequence */ + for (attnum = 0; attnum < tupdesc->natts; attnum++) + { + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum); + + if (attr->attidentity) + { + attname = NameStr(attr->attname); + seqid = getIdentitySequence(table_oid, attnum + 1, false); + break; + } + } + + RelationClose(rel); + + if (!OidIsValid(seqid)) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("'%s.%s' does not contain an identity column.", + nsp_name, dbcc_stmt.table_name))); + } + + PG_TRY(); + { + cur_identity_value = DirectFunctionCall1(pg_sequence_last_value, + ObjectIdGetDatum(seqid)); + cur_value_is_null = false; + } + PG_CATCH(); + { + FlushErrorState(); + } + PG_END_TRY(); + + PG_TRY(); + { + /* + * Acquiring an AccessExclusiveLock on the table is essential when + * reseeding the identity current value to new_ressed_value to + * ensure concurrency control. + */ + if(dbcc_stmt.new_reseed_value) + { + LockRelationOid(table_oid, AccessExclusiveLock); + } + else + { + LockRelationOid(table_oid, ShareLock); + } + + /* + * If cur_value_is_null is true, then the function pg_sequence_last_value + * has returned a NULL value, which means either no rows have been + * inserted into the table yet, or TRUNCATE TABLE command has been used + * to delete all rows. In this case, after DBCC CHECKIDENT the next + * row inserted will have new_reseed_value as the identity value. + */ + if (cur_value_is_null) + { + if (dbcc_stmt.new_reseed_value) + { + snprintf(message, sizeof(message), "Checking identity information: current identity value 'NULL'.\n"); + + DirectFunctionCall3(setval3_oid, + ObjectIdGetDatum(seqid), + Int64GetDatum(reseed_value), + BoolGetDatum(false)); + } + else + { + snprintf(message, sizeof(message), "Checking identity information: current identity value 'NULL', current column value 'NULL'.\n"); + } + } + + else + { + if (dbcc_stmt.new_reseed_value) + { + /* + * Print informational messages if NO_INFOMSGS is not passed as a + * DBCC command option. + */ + if (!dbcc_stmt.no_infomsgs) + snprintf(message, sizeof(message), "Checking identity information: current identity value '%ld'.\n", cur_identity_value); + + DirectFunctionCall2(setval_oid, + ObjectIdGetDatum(seqid), + Int64GetDatum(reseed_value)); + } + else + { + SPI_connect(); + query = psprintf("SELECT MAX(%s) FROM %s.%s", attname, + schema_name, dbcc_stmt.table_name); + rc = SPI_execute(query, true, 0); + + if (rc != SPI_OK_SELECT) + elog(ERROR, "SPI_execute failed: %s", SPI_result_code_string(rc)); + + max_identity_value_str = SPI_getvalue(SPI_tuptable->vals[0], + SPI_tuptable->tupdesc, 1); + + SPI_freetuptable(SPI_tuptable); + + if(max_identity_value_str) + max_identity_value = pg_strtoint64(max_identity_value_str); + + if (!dbcc_stmt.no_infomsgs) + snprintf(message, sizeof(message), "Checking identity information: current identity value '%ld', current column value '%s'.\n", + cur_identity_value, + max_identity_value_str ? max_identity_value_str : "NULL"); + + /* + * RESEED option only resets the identity column value if the + * current identity value for a table is less than the maximum + * identity value stored in the identity column. + */ + if (dbcc_stmt.is_reseed && max_identity_value_str && + cur_identity_value < max_identity_value) + { + DirectFunctionCall2(setval_oid, + ObjectIdGetDatum(seqid), + Int64GetDatum(max_identity_value)); + } + } + } + + if (is_cross_db) + SetCurrentRoleId(current_user_id, false); + } + PG_CATCH(); + { + if (is_cross_db) + SetCurrentRoleId(current_user_id, false); + + if(query) + pfree(query); + if (max_identity_value_str) + pfree(max_identity_value_str); + + if(rc != 0) + { + SPI_finish(); + /* running 'SELECT MAX' query above holds a AccessShareLock on table, we want to unlock that as well */ + UnlockRelationOid(table_oid, AccessShareLock); + } + if(!dbcc_stmt.new_reseed_value) + { + UnlockRelationOid(table_oid, ShareLock); + } + + PG_RE_THROW(); + } + PG_END_TRY(); + + if(query) + pfree(query); + if (max_identity_value_str) + pfree(max_identity_value_str); + if(rc != 0) + { + SPI_finish(); + /* running 'SELECT MAX' query above holds a AccessShareLock on table, we want to unlock that as well */ + UnlockRelationOid(table_oid, AccessShareLock); + } + + if(!dbcc_stmt.new_reseed_value) + { + UnlockRelationOid(table_oid, ShareLock); + } + + if (!dbcc_stmt.no_infomsgs) + { + strcat(message, "DBCC execution completed. If DBCC printed error messages, contact your system administrator."); + /* send message to user */ + if (*pltsql_protocol_plugin_ptr && (*pltsql_protocol_plugin_ptr)->send_info) + ((*pltsql_protocol_plugin_ptr)->send_info) (0, 1, 0, message, 0); + } + +} + + uint64 execute_bulk_load_insert(int ncol, int nrow, Datum *Values, bool *Nulls) diff --git a/contrib/babelfishpg_tsql/src/pl_funcs-2.c b/contrib/babelfishpg_tsql/src/pl_funcs-2.c index c095a74a9f..bc8975d0a9 100644 --- a/contrib/babelfishpg_tsql/src/pl_funcs-2.c +++ b/contrib/babelfishpg_tsql/src/pl_funcs-2.c @@ -513,6 +513,11 @@ free_stmt2(PLtsql_stmt *stmt) { break; } + case PLTSQL_STMT_DBCC: + { + /* Nothing to free */ + break; + } default: elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); break; @@ -541,6 +546,7 @@ void dump_stmt_try_catch(PLtsql_stmt_try_catch *stmt_try_catch); void dump_stmt_query_set(PLtsql_stmt_query_set *query_set); void dump_stmt_exec_batch(PLtsql_stmt_exec_batch *exec_batch); void get_grantees_names(List *grantees, StringInfo grantees_names); +void dump_stmt_dbcc(PLtsql_stmt_dbcc *stmt_dbcc); void dump_stmt_print(PLtsql_stmt_print *stmt_print) @@ -679,6 +685,22 @@ dump_stmt_insert_bulk(PLtsql_stmt_insert_bulk *stmt_insert_bulk) printf("INSERT BULK %s\n", stmt_insert_bulk->table_name); } +void +dump_stmt_dbcc(PLtsql_stmt_dbcc *stmt_dbcc) +{ + printf("DBCC "); + switch (stmt_dbcc->dbcc_stmt_type) + { + case PLTSQL_DBCC_CHECKIDENT: + printf("CHECKIDENT"); + break; + default: + elog(ERROR, "unrecognized dbcc statement type: %d", stmt_dbcc->dbcc_stmt_type); + break; + } + printf(" STATEMENT\n"); +} + void dump_stmt_try_catch(PLtsql_stmt_try_catch *stmt_try_catch) { @@ -811,6 +833,11 @@ dump_stmt2(PLtsql_stmt *stmt) dump_stmt_insert_bulk((PLtsql_stmt_insert_bulk *) stmt); break; } + case PLTSQL_STMT_DBCC: + { + dump_stmt_dbcc((PLtsql_stmt_dbcc *) stmt); + break; + } default: elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); break; diff --git a/contrib/babelfishpg_tsql/src/pl_funcs.c b/contrib/babelfishpg_tsql/src/pl_funcs.c index a6cf523b03..9bf8a20010 100644 --- a/contrib/babelfishpg_tsql/src/pl_funcs.c +++ b/contrib/babelfishpg_tsql/src/pl_funcs.c @@ -344,6 +344,8 @@ pltsql_stmt_typename(PLtsql_stmt *stmt) return "RESTORE_CONTEXT_FULL"; case PLTSQL_STMT_RESTORE_CTX_PARTIAL: return "RESTORE_CONTEXT_PARTIAL"; + case PLTSQL_STMT_DBCC: + return "DBCC"; default: return "Add try catch"; } diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index e5cc3adfcb..622a57a2ec 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -116,6 +116,12 @@ typedef enum PLtsql_promise_type PLTSQL_PROMISE_TG_TAG } PLtsql_promise_type; + +typedef enum PLtsql_dbcc_stmt_type +{ + PLTSQL_DBCC_CHECKIDENT +} PLtsql_dbcc_stmt_type; + /* * Variants distinguished in PLtsql_type structs */ @@ -186,6 +192,7 @@ typedef enum PLtsql_stmt_type PLTSQL_STMT_RESTORE_CTX_PARTIAL, PLTSQL_STMT_INSERT_BULK, PLTSQL_STMT_GRANTDB, + PLTSQL_STMT_DBCC, PLTSQL_STMT_GRANTSCHEMA } PLtsql_stmt_type; @@ -933,6 +940,34 @@ typedef struct PLtsql_stmt_insert_bulk bool keep_nulls; } PLtsql_stmt_insert_bulk; +/* + * DBCC statement type + */ +typedef union PLtsql_dbcc_stmt_data +{ + struct dbcc_checkident + { + char *db_name; + char *schema_name; + char *table_name; + bool is_reseed; + char *new_reseed_value; + bool no_infomsgs; + } dbcc_checkident; + +} PLtsql_dbcc_stmt_data; + +/* + * DBCC statement + */ +typedef struct PLtsql_stmt_dbcc +{ + PLtsql_stmt_type cmd_type; + int lineno; + PLtsql_dbcc_stmt_type dbcc_stmt_type; + PLtsql_dbcc_stmt_data dbcc_stmt_data; +} PLtsql_stmt_dbcc; + /* * RETURN statement */ diff --git a/contrib/babelfishpg_tsql/src/stmt_walker.c b/contrib/babelfishpg_tsql/src/stmt_walker.c index b33cb42234..7bc1bbd01b 100644 --- a/contrib/babelfishpg_tsql/src/stmt_walker.c +++ b/contrib/babelfishpg_tsql/src/stmt_walker.c @@ -108,6 +108,7 @@ stmt_walker(PLtsql_stmt *stmt, WalkerFunc walker, void *context) case PLTSQL_STMT_SET_EXPLAIN_MODE: case PLTSQL_STMT_GRANTDB: case PLTSQL_STMT_GRANTSCHEMA: + case PLTSQL_STMT_DBCC: break; /* TSQL-only executable node */ case PLTSQL_STMT_SAVE_CTX: @@ -206,6 +207,7 @@ general_walker_func(PLtsql_stmt *stmt, void *context) DISPATCH(INSERT_BULK, insert_bulk) DISPATCH(SET_EXPLAIN_MODE, set_explain_mode) DISPATCH(GRANTDB, grantdb) + DISPATCH(DBCC, dbcc) DISPATCH(GRANTSCHEMA, grantschema) /* TSQL-only executable node */ diff --git a/contrib/babelfishpg_tsql/src/stmt_walker.h b/contrib/babelfishpg_tsql/src/stmt_walker.h index 98f143c5eb..36efeeb289 100644 --- a/contrib/babelfishpg_tsql/src/stmt_walker.h +++ b/contrib/babelfishpg_tsql/src/stmt_walker.h @@ -87,6 +87,7 @@ typedef bool (*Stmt_usedb_act) ACTION_SIGNITURE(usedb); typedef bool (*Stmt_insert_bulk_act) ACTION_SIGNITURE(insert_bulk); typedef bool (*Stmt_set_explain_mode) ACTION_SIGNITURE(set_explain_mode); typedef bool (*Stmt_grantdb_act) ACTION_SIGNITURE(grantdb); +typedef bool (*Stmt_dbcc_act) ACTION_SIGNITURE(dbcc); typedef bool (*Stmt_grantschema_act) ACTION_SIGNITURE(grantschema); /* TSQL-only executable node */ @@ -138,6 +139,7 @@ typedef struct Walker_context Stmt_insert_bulk_act insert_bulk_act; Stmt_set_explain_mode set_explain_mode_act; Stmt_grantdb_act grantdb_act; + Stmt_dbcc_act dbcc_act; Stmt_grantschema_act grantschema_act; /* TSQL-only executable node */ diff --git a/contrib/babelfishpg_tsql/src/tsqlIface.cpp b/contrib/babelfishpg_tsql/src/tsqlIface.cpp index db21d4f1b1..aa2a12d2c8 100644 --- a/contrib/babelfishpg_tsql/src/tsqlIface.cpp +++ b/contrib/babelfishpg_tsql/src/tsqlIface.cpp @@ -112,6 +112,7 @@ std::vector makeAnother(TSqlParser::Another_statementContext *ctx PLtsql_stmt *makeExecBodyBatch(TSqlParser::Execute_body_batchContext *ctx); PLtsql_stmt *makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type); PLtsql_stmt *makeInsertBulkStatement(TSqlParser::Dml_statementContext *ctx); +PLtsql_stmt *makeDbccCheckidentStatement(TSqlParser::Dbcc_statementContext *ctx); PLtsql_stmt *makeSetExplainModeStatement(TSqlParser::Set_statementContext *ctx, bool is_explain_only); PLtsql_expr *makeTsqlExpr(const std::string &fragment, bool addSelect); PLtsql_expr *makeTsqlExpr(ParserRuleContext *ctx, bool addSelect); @@ -2118,6 +2119,19 @@ class tsqlBuilder : public tsqlCommonMutator clear_rewritten_query_fragment(); } + void enterDbcc_statement(TSqlParser::Dbcc_statementContext *ctx) override + { + if (ctx->CHECKIDENT()) + graft(makeDbccCheckidentStatement(ctx), peekContainer()); + + clear_rewritten_query_fragment(); + } + + void exitDbcc_statement(TSqlParser::Dbcc_statementContext *ctx) override + { + // TO-DO + } + ////////////////////////////////////////////////////////////////////////////// // Special handling of non-statement context ////////////////////////////////////////////////////////////////////////////// @@ -5089,7 +5103,6 @@ makeInsertBulkStatement(TSqlParser::Dml_statementContext *ctx) } } } - attachPLtsql_fragment(ctx, (PLtsql_stmt *) stmt); return (PLtsql_stmt *) stmt; } @@ -5870,6 +5883,108 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) return (PLtsql_stmt *) result; } +PLtsql_stmt* +makeDbccCheckidentStatement(TSqlParser::Dbcc_statementContext *ctx) +{ + PLtsql_stmt_dbcc *stmt = (PLtsql_stmt_dbcc *) palloc0(sizeof(*stmt)); + + std::string new_reseed_value; + std::string input_str; + int i; + char *db_name = NULL; + char *schema_name = NULL; + char *table_name = NULL; + char *input_str_to_split; + char **splited_object_name; + bool is_reseed = true; + bool no_infomsgs = false; + + stmt->cmd_type = PLTSQL_STMT_DBCC; + stmt->dbcc_stmt_type = PLTSQL_DBCC_CHECKIDENT; + + if (ctx->table_name_string()) + { + if(ctx->table_name_string()->table) + { + input_str = stripQuoteFromId(ctx->table_name_string()->table); + } + if (ctx->table_name_string()->char_string()) + { + input_str = ctx->table_name_string()->char_string()->STRING()->getSymbol()->getText(); + if (input_str.length() <= 2) + throw PGErrorWrapperException(ERROR, ERRCODE_INVALID_PARAMETER_VALUE, + "Parameter 1 is incorrect for this DBCC statement", + getLineAndPos(ctx->table_name_string())); + input_str = input_str.substr(1, input_str.length()-2); + } + if (ctx->RESEED()) + { + if (ctx->new_value) + { + if(ctx->MINUS()) + stmt->dbcc_stmt_data.dbcc_checkident.new_reseed_value = pstrdup((ctx->new_value->getText().insert(0,"-")).c_str()); + else + stmt->dbcc_stmt_data.dbcc_checkident.new_reseed_value = pstrdup((ctx->new_value->getText()).c_str()); + } + } + else if (ctx->NORESEED()) + { + is_reseed = false; + } + + if(ctx->dbcc_options()) + { + if (pg_strcasecmp(::getFullText(ctx->dbcc_options()).c_str(), "NO_INFOMSGS") == 0) + { + no_infomsgs = true; + } + else + { + throw PGErrorWrapperException(ERROR, ERRCODE_SYNTAX_ERROR, + format_errmsg("\'%s\' is not a recognized option", + ::getFullText(ctx->dbcc_options()).c_str()), + getLineAndPos(ctx->dbcc_options())); + } + } + } + + input_str_to_split = pstrdup(input_str.c_str()); + + /* strip trailing whitespace from input string */ + i = strlen(input_str_to_split); + while (i > 0 && isspace((unsigned char) input_str_to_split[i - 1])) + input_str_to_split[--i] = '\0'; + + splited_object_name = split_object_name(input_str_to_split); + db_name = !strcmp(splited_object_name[1], "")? NULL : splited_object_name[1]; + schema_name = !strcmp(splited_object_name[2], "")? NULL : splited_object_name[2]; + table_name = !strcmp(splited_object_name[3], "")? NULL : splited_object_name[3]; + + if(db_name) + { + stmt->dbcc_stmt_data.dbcc_checkident.db_name = pstrdup(downcase_truncate_identifier(db_name, strlen(db_name), true)); + pfree(db_name); + } + if(schema_name) + { + stmt->dbcc_stmt_data.dbcc_checkident.schema_name = pstrdup(downcase_truncate_identifier(schema_name, strlen(schema_name), true)); + pfree(schema_name); + } + if(table_name) + { + stmt->dbcc_stmt_data.dbcc_checkident.table_name = pstrdup(downcase_truncate_identifier(table_name, strlen(table_name), true)); + pfree(table_name); + } + stmt->dbcc_stmt_data.dbcc_checkident.is_reseed = is_reseed; + stmt->dbcc_stmt_data.dbcc_checkident.no_infomsgs = no_infomsgs; + + pfree(splited_object_name); + pfree(input_str_to_split); + + attachPLtsql_fragment(ctx, (PLtsql_stmt *) stmt); + return (PLtsql_stmt *) stmt; +} + // helper function to create target row PLtsql_row * create_select_target_row(const char *refname, size_t nfields, int lineno) diff --git a/contrib/babelfishpg_tsql/src/tsqlNodes.h b/contrib/babelfishpg_tsql/src/tsqlNodes.h index cb0195dce0..14139a7273 100644 --- a/contrib/babelfishpg_tsql/src/tsqlNodes.h +++ b/contrib/babelfishpg_tsql/src/tsqlNodes.h @@ -49,6 +49,7 @@ typedef enum pltsql_stmt_type PLTSQL_STMT_DEALLOCATE, PLTSQL_STMT_INSERT_BULK, PLTSQL_STMT_GRANTDB, + PLTSQL_STMT_DBCC, PLTSQL_STMT_GRANTSCHEMA } PLtsql_stmt_type; diff --git a/contrib/babelfishpg_tsql/src/tsqlUnsupportedFeatureHandler.cpp b/contrib/babelfishpg_tsql/src/tsqlUnsupportedFeatureHandler.cpp index a6897b1598..81cae20279 100644 --- a/contrib/babelfishpg_tsql/src/tsqlUnsupportedFeatureHandler.cpp +++ b/contrib/babelfishpg_tsql/src/tsqlUnsupportedFeatureHandler.cpp @@ -150,7 +150,7 @@ class TsqlUnsupportedFeatureHandlerImpl : public TsqlUnsupportedFeatureHandler antlrcpp::Any visitReconfigure_statement(TSqlParser::Reconfigure_statementContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_RECONFIGURE, "RECONFIGURE", getLineAndPos(ctx)); return visitChildren(ctx); } antlrcpp::Any visitShutdown_statement(TSqlParser::Shutdown_statementContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_SHUTDOWN, "SHUTDOWN", getLineAndPos(ctx)); return visitChildren(ctx); } - antlrcpp::Any visitDbcc_statement(TSqlParser::Dbcc_statementContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_DBCC, "DBCC", getLineAndPos(ctx)); return visitChildren(ctx); } + antlrcpp::Any visitDbcc_statement(TSqlParser::Dbcc_statementContext *ctx) override; antlrcpp::Any visitBackup_statement(TSqlParser::Backup_statementContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_BACKUP, "BACKUP", getLineAndPos(ctx)); return visitChildren(ctx); } antlrcpp::Any visitRestore_statement(TSqlParser::Restore_statementContext *ctx) override { handle(INSTR_UNSUPPORTED_TSQL_RESTORE, "RESTORE", getLineAndPos(ctx)); return visitChildren(ctx); } antlrcpp::Any visitCheckpoint_statement(TSqlParser::Checkpoint_statementContext *ctx) override; @@ -1255,6 +1255,29 @@ antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitTransaction_statement(TSql return visitChildren(ctx); } +antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitDbcc_statement(TSqlParser::Dbcc_statementContext *ctx) +{ + + if (ctx->dbcc_command()) + { + if (ctx->dbcc_command()->ID()) + { + throw PGErrorWrapperException(ERROR, ERRCODE_SYNTAX_ERROR, + "Incorrect DBCC statement. Check the documentation for the " + "correct DBCC syntax and options.", + getLineAndPos(ctx->dbcc_command())); + } + else + { + throw PGErrorWrapperException(ERROR, ERRCODE_FEATURE_NOT_SUPPORTED, + format_errmsg("DBCC %s is not yet supported in Babelfish", + ::getFullText(ctx->dbcc_command()).c_str()), + getLineAndPos(ctx->dbcc_command())); + } + } + return visitChildren(ctx); +} + antlrcpp::Any TsqlUnsupportedFeatureHandlerImpl::visitSecurity_statement(TSqlParser::Security_statementContext *ctx) { if (ctx->execute_as_statement()) diff --git a/test/JDBC/expected/BABEL-3201-vu-cleanup.out b/test/JDBC/expected/BABEL-3201-vu-cleanup.out new file mode 100644 index 0000000000..455056962a --- /dev/null +++ b/test/JDBC/expected/BABEL-3201-vu-cleanup.out @@ -0,0 +1,59 @@ +DROP TABLE babel_3201_t_int; +GO + +DROP TABLE babel_dbcc_check_t1; +GO + +DROP TABLE [babel_dbcc_check_t2 .with .dot_an_spaces]; +GO + +DROP TABLE [babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces"; +GO + +DROP SCHEMA [babel_dbcc_check_schema .with .dot_and_spaces] +GO + +DROP TABLE babel_3201_t_tinyint; +GO + +DROP TABLE babel_3201_t_smallint; +GO + +DROP TABLE babel_3201_t_bigint; +GO + +DROP TABLE babel_3201_t_numeric; +GO + +DROP TABLE babel_3201_t_decimal; +GO + +DROP TABLE babel_3201_t1; +GO + +DROP TABLE babel_3201_t2; +GO + +DROP TABLE babel_3201_sch1.babel_3201_t2; +GO + +DROP TABLE babel_3201_test_locks; +GO + +DROP PROCEDURE babel_3201_proc1; +GO + +DROP PROCEDURE babel_3201_proc2; +GO + +DROP LOGIN babel_3201_log1; +GO + +DROP LOGIN babel_3201_test_locks; +GO + +DROP SCHEMA babel_3201_sch1; +GO + +DROP DATABASE babel_3201_db1; +GO diff --git a/test/JDBC/expected/BABEL-3201-vu-prepare.out b/test/JDBC/expected/BABEL-3201-vu-prepare.out new file mode 100644 index 0000000000..4bef6e6006 --- /dev/null +++ b/test/JDBC/expected/BABEL-3201-vu-prepare.out @@ -0,0 +1,163 @@ +CREATE SCHEMA babel_3201_sch1; +GO + +CREATE TABLE babel_3201_sch1.babel_3201_t2(a varchar(20), b int identity); +GO + +CREATE TABLE babel_3201_t_int( a int identity, b int); +GO + +CREATE TABLE babel_dbcc_check_t1 (a int identity, b int); +GO + +CREATE TABLE [babel_dbcc_check_t2 .with .dot_an_spaces] (a int identity, b int); +GO + +CREATE SCHEMA [babel_dbcc_check_schema .with .dot_and_spaces] +GO + +CREATE TABLE [babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces" (a int identity, b int); +GO + +CREATE TABLE babel_3201_t_tinyint( a tinyint identity(5,1), b int); +GO + +CREATE TABLE babel_3201_t_smallint( a smallint identity(10,10), b int); +GO + +CREATE TABLE babel_3201_t_bigint( a bigint identity(3,3), b int); +GO + +CREATE TABLE babel_3201_t_numeric( a numeric identity(4,2), b int); +GO + +CREATE TABLE babel_3201_t_decimal( a decimal identity(7,3), b int); +GO + +CREATE TABLE babel_3201_t1( a int identity, b int); +GO + +CREATE TABLE babel_3201_t2( a int, b int); +GO + +CREATE TABLE babel_3201_test_locks (a int identity, b int); +GO + +INSERT INTO babel_3201_test_locks VALUES (10); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_sch1.babel_3201_t2 VALUES ('string 1'); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_tinyint VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_tinyint VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_tinyint VALUES (7); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_smallint VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_smallint VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_smallint VALUES (7); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_int VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_int VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_int VALUES (7); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_bigint VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_bigint VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_bigint VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_numeric VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_numeric VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_numeric VALUES (7); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_decimal VALUES (5); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_decimal VALUES (6); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO babel_3201_t_decimal VALUES (7); +GO +~~ROW COUNT: 1~~ + + +CREATE PROCEDURE babel_3201_proc1 +AS +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 30) +GO + +CREATE PROCEDURE babel_3201_proc2 +AS +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 257) +GO + +CREATE LOGIN babel_3201_log1 WITH PASSWORD='12345678'; +GO + +CREATE LOGIN babel_3201_test_locks WITH PASSWORD='123456'; +GO + +ALTER SERVER ROLE sysadmin ADD MEMBER babel_3201_test_locks +GO diff --git a/test/JDBC/expected/BABEL-3201-vu-verify.out b/test/JDBC/expected/BABEL-3201-vu-verify.out new file mode 100644 index 0000000000..762aed89fd --- /dev/null +++ b/test/JDBC/expected/BABEL-3201-vu-verify.out @@ -0,0 +1,813 @@ +DBCC CHECKIDENT(babel_3201_t_int, NORESEED); +GO + +-- test with mixed case in table name +DBCC CHECKIDENT(BABEL_3201_t_iNt, NORESEED); +GO +DBCC CHECKIDENT(BABEL_3201_T_INT, NORESEED); +GO + +-- test with table in quotes (+mixed cases) +DBCC CHECKIDENT('babel_3201_t_int', NORESEED); +GO +DBCC CHECKIDENT('baBEl_3201_T_inT', NORESEED); +GO + +-- test with table in brackets (+mixed case) +DBCC CHECKIDENT([babel_3201_t_int], NORESEED); +GO +DBCC CHECKIDENT([baBEL_3201_t_InT], NORESEED); +GO + +-- test with table in brackets with quotes (+mixed case) +DBCC CHECKIDENT('[babel_3201_t_int]', NORESEED); +GO +DBCC CHECKIDENT('[BABEL_3201_t_int]', NORESEED); +GO + +-- test when trailing space - should work +DBCC CHECKIDENT('babel_3201_t_int ', NORESEED); +GO +DBCC CHECKIDENT('babel_3201_T_INT ', NORESEED); +GO + +-- test when leading space - should throw error +DBCC CHECKIDENT(' babel_3201_t_int ', NORESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation " babel_3201_t_int" does not exist)~~ + + +-- test when table name is empty in quotes +DBCC CHECKIDENT('', NORESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Parameter 1 is incorrect for this DBCC statement)~~ + + +-- same as DBCC CHECKIDENT(, RESEED), identity value is not changed +-- if current identity value for a table is less than the maximum identity value +-- stored in the identity column +DBCC CHECKIDENT(babel_3201_t_int); +GO + + +DBCC CHECKIDENT(babel_3201_t_int, RESEED); +GO + +INSERT INTO babel_3201_t_int VALUES (8); +GO +~~ROW COUNT: 1~~ + + +SELECT * FROM babel_3201_t_int; +GO +~~START~~ +int#!#int +1#!#5 +2#!#6 +3#!#7 +4#!#8 +~~END~~ + + +DBCC CHECKIDENT('babel_3201_sch1.babel_3201_t2'); +GO + +-- Set identity value to 5 which is less than the maximum value(which is 9) of the identity +-- column, using RESEED option in this case should will reset the identity value +-- to maximum value of the identity column. Value inserted in next insert will +-- be (max_identity_col_value + increament). +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 5); +GO +INSERT INTO babel_3201_t_bigint VALUES (8); +GO +~~ROW COUNT: 1~~ + +SELECT * from babel_3201_t_bigint; +GO +~~START~~ +bigint#!#int +3#!#5 +6#!#6 +9#!#6 +8#!#8 +~~END~~ + + +-- This will reset the current identity value(currently 8) to the maximum value of the identity column (currently 9) +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED); +GO +INSERT INTO babel_3201_t_bigint VALUES (9); +GO +~~ROW COUNT: 1~~ + +SELECT * from babel_3201_t_bigint; +GO +~~START~~ +bigint#!#int +3#!#5 +6#!#6 +9#!#6 +8#!#8 +12#!#9 +~~END~~ + + +-- no rows have been inserted in the table; both current identity value current +-- column value should be NULL (TO-DO) +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, NORESEED); +SELECT * FROM babel_3201_t1; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value 'NULL', current column value 'NULL'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +int#!#int +~~END~~ + + +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, RESEED); +SELECT * FROM babel_3201_t1; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value 'NULL', current column value 'NULL'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +int#!#int +~~END~~ + + +-- current identity value should be NULL (TO-DO), identity value inserted in +-- next INSERT operation should be new_reseed_value. +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, RESEED, 5); +INSERT INTO babel_3201_t1 VALUES (50); +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value 'NULL'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~ROW COUNT: 1~~ + + +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, NORESEED); +select * from babel_3201_t1; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '5', current column value '5'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +int#!#int +5#!#50 +~~END~~ + + +-- Remove all rows in table using TRUNCATE TABLE, Identity value will become NULL +-- next insert operation should be default identity value if no new_reseed_value is provided. +TRUNCATE TABLE babel_3201_t_int; +GO +dbcc checkident(babel_3201_t_int, NORESEED); +GO +INSERT INTO babel_3201_t_int values(15); +GO +~~ROW COUNT: 1~~ + + +select * from babel_3201_t_int; +-- Remove all rows in table using TRUNCATE TABLE, identity value inserted in +-- next INSERT operation should be new_reseed_value. +TRUNCATE TABLE babel_3201_t_int; +GO +~~START~~ +int#!#int +1#!#15 +~~END~~ + +DBCC CHECKIDENT(babel_3201_t_int, RESEED, 10); +GO +INSERT INTO babel_3201_t_int VALUES (5); +GO +~~ROW COUNT: 1~~ + +SELECT * FROM babel_3201_t_int; +GO +~~START~~ +int#!#int +10#!#5 +~~END~~ + + + +-- Remove all rows in table using DELETE TABLE, identity value inserted in next +-- INSERT operation should be (new_reseed_value + increment). +DELETE FROM babel_3201_t_bigint; +GO +~~ROW COUNT: 5~~ + +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 10); +GO +INSERT INTO babel_3201_t_bigint VALUES (5); +GO +~~ROW COUNT: 1~~ + +SELECT * FROM babel_3201_t_bigint; +GO +~~START~~ +bigint#!#int +13#!#5 +~~END~~ + + +-- Remove all rows in table using DELETE TABLE current identity will not become default identity value, +-- identity value inserted in next operation should use (default identity value + increament) if no new_reseed_value is provided. +DELETE FROM babel_3201_t_bigint; +GO +~~ROW COUNT: 1~~ + +dbcc checkident(babel_3201_t_bigint, NORESEED); +GO +INSERT INTO babel_3201_t_bigint VALUES (5); +GO +~~ROW COUNT: 1~~ + +SELECT * FROM babel_3201_t_bigint; +GO +~~START~~ +bigint#!#int +16#!#5 +~~END~~ + + +-- If some rows are present already in the table, identity value inserted in next +-- INSERT operation should be (new_reseed_value + increament) +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 27); +GO +INSERT INTO babel_3201_t_bigint VALUES (32); +GO +~~ROW COUNT: 1~~ + +SELECT * FROM babel_3201_t_bigint; +GO +~~START~~ +bigint#!#int +16#!#5 +30#!#32 +~~END~~ + + +-- Incorrect DBCC command option +DBCC CHECKIDENT(babel_3201_t1) WITH NO_INFO; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: 'NO_INFO' is not a recognized option)~~ + + +-- Invalid parameter 1 +DBCC CHECKIDENT(5); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '5' at line 2 and character position 16)~~ + + +DBCC CHECKIDENT(babel_3201_t_int, RESEED, ) WITH NO_INFOMSGS; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near ')' at line 1 and character position 42)~~ + + +-- Invalid keyword +DBCC CHECKIDENT(babel_3201_t1, RESEE); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near 'RESEE' at line 2 and character position 31)~~ + + +-- Invalid datatype +DBCC CHECKIDENT(babel_3201_t1, RESEED, 1313abc); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near 'abc' at line 2 and character position 43)~~ + + +-- Unsupported DBCC command +DBCC CHECKTABLE(babel_3201_t1); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: DBCC CHECKTABLE is not yet supported in Babelfish)~~ + + +-- Invalid DBCC command +DBCC FAKE_COMMAND(t1); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Incorrect DBCC statement. Check the documentation for the correct DBCC syntax and options.)~~ + + +-- Database undefined +DBCC CHECKIDENT('fake_db.dbo.babel_3201_t1', NORESEED); +GO +~~ERROR (Code: 911)~~ + +~~ERROR (Message: database "fake_db" does not exist)~~ + + +-- Schema undefined +DBCC CHECKIDENT('fake_schema.babel_3201_t1', NORESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: schema "master_fake_schema" does not exist)~~ + + +-- Table undefined +DBCC CHECKIDENT(fake_babel_3201_t1, RESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "fake_babel_3201_t1" does not exist)~~ + + +-- Table does not have identity column +DBCC CHECKIDENT(babel_3201_t2, RESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: 'master_dbo.babel_3201_t2' does not contain an identity column.)~~ + + +-- new_reseed_value as expression is not allowed +DBCC CHECKIDENT(babel_3201_t2, RESEED, 4+5); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '+' at line 2 and character position 40)~~ + + +-- new_reseed_value is out of tinyint datatype range +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 256); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 256 is out of bounds for sequence "babel_3201_t_tinyint_a_seq" (5..255))~~ + + +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, -1); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value -1 is out of bounds for sequence "babel_3201_t_tinyint_a_seq" (5..255))~~ + + +-- new_reseed_value is out of smallint datatype range +DBCC CHECKIDENT(babel_3201_t_smallint, RESEED, 32768); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 32768 is out of bounds for sequence "babel_3201_t_smallint_a_seq" (10..32767))~~ + + +DBCC CHECKIDENT(babel_3201_t_smallint, RESEED, -32769); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value -32769 is out of bounds for sequence "babel_3201_t_smallint_a_seq" (10..32767))~~ + + + +-- new_reseed_value is out of int datatype range +DBCC CHECKIDENT(babel_3201_t_int, RESEED, 2147483648); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 2147483648 is out of bounds for sequence "babel_3201_t_int_a_seq" (1..2147483647))~~ + + +DBCC CHECKIDENT(babel_3201_t_int, RESEED, -2147483649); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value -2147483649 is out of bounds for sequence "babel_3201_t_int_a_seq" (1..2147483647))~~ + + +-- new_reseed_value is out of bigint datatype range +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 9223372036854775808); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: value "9223372036854775808" is out of range for type bigint)~~ + + +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, -9223372036854775809); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: value "-9223372036854775809" is out of range for type bigint)~~ + + +-- numeric/decimal datatypes are internally converted to bigint, so allowed +-- range is same as that of bigint +DBCC CHECKIDENT(babel_3201_t_numeric, RESEED, 9223372036854775808); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: value "9223372036854775808" is out of range for type bigint)~~ + + +-- When new_reseed_value is a float value, only value before the decimal is used +DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 15.65); +GO + +-- When reseed_value is negative and zero, bbf currently does not support reseed to negative/zero value +dbcc checkident(babel_3201_t_decimal, reseed, -10) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value -10 is out of bounds for sequence "babel_3201_t_decimal_a_seq" (7..9223372036854775807))~~ + +dbcc checkident(babel_3201_t_decimal, reseed, 0) +Go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 0 is out of bounds for sequence "babel_3201_t_decimal_a_seq" (7..9223372036854775807))~~ + +dbcc checkident(babel_3201_t_decimal, reseed, .123) +Go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 0 is out of bounds for sequence "babel_3201_t_decimal_a_seq" (7..9223372036854775807))~~ + +dbcc checkident(babel_3201_t_decimal, reseed, -.123) +Go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 0 is out of bounds for sequence "babel_3201_t_decimal_a_seq" (7..9223372036854775807))~~ + +dbcc checkident(babel_3201_t_decimal, reseed, .) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '.' at line 1 and character position 46)~~ + +dbcc checkident(babel_3201_t_decimal, reseed, -) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near ')' at line 1 and character position 47)~~ + +dbcc checkident(babel_3201_t_decimal, reseed, .-); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '.' at line 1 and character position 46)~~ + + +SELECT * FROM babel_3201_t_decimal; +GO +~~START~~ +bigint#!#int +7#!#5 +10#!#6 +13#!#7 +~~END~~ + + +begin tran; +DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 10); +INSERT INTO babel_3201_t_decimal VALUES (9); +commit; +go +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '15'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~ROW COUNT: 1~~ + + +SELECT * FROM babel_3201_t_decimal; +GO +~~START~~ +bigint#!#int +7#!#5 +10#!#6 +13#!#7 +13#!#9 +~~END~~ + + +BEGIN TRAN; + DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 133ac); + INSERT INTO babel_3201_t_decimal VALUES (10); +COMMIT; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near 'ac' at line 2 and character position 53)~~ + + +SELECT * FROM babel_3201_t_decimal; +GO +~~START~~ +bigint#!#int +7#!#5 +10#!#6 +13#!#7 +13#!#9 +~~END~~ + + +BEGIN TRAN; + DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 20); + INSERT INTO babel_3201_t_decimal VALUES (11); +ROLLBACK; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '13'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~ROW COUNT: 1~~ + + +-- Check current_identity value after tran rollback +-- babelfish does not support rolling-back dbcc changes after transection rollback. +-- Current identity value will be = reseed_value inside the rollbacked transection + increament = 20+3=23 +BEGIN TRAN; +dbcc checkident(babel_3201_t_decimal, noreseed); +SELECT * FROM babel_3201_t_decimal; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '23', current column value '13'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +bigint#!#int +7#!#5 +10#!#6 +13#!#7 +13#!#9 +~~END~~ + + +EXEC babel_3201_proc1; +GO + +INSERT INTO babel_3201_t_tinyint VALUES (10); +GO +~~ROW COUNT: 1~~ + + +SELECT * FROM babel_3201_t_tinyint; +GO +~~START~~ +smallint#!#int +5#!#5 +6#!#6 +7#!#7 +31#!#10 +~~END~~ + + +EXEC babel_3201_proc2; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: setval: value 257 is out of bounds for sequence "babel_3201_t_tinyint_a_seq" (5..255))~~ + + +-- testing different scenarios of 3-part name +DBCC CHECKIDENT('dbo.babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('..babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('master.dbo.babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('[master]."dbo".[babel_dbcc_check_t1]') +GO + +DBCC CHECKIDENT('"master".[dbo]."babel_dbcc_check_t1"') +GO + +DBCC CHECKIDENT('master..babel_dbcc_check_t1') +GO + +-- with mixed case names of db, schema, and table. +DBCC CHECKIDENT('dbo.BABEL_DBCC_check_t1') +GO +DBCC CHECKIDENT('master.DBO.BABEL_dbcc_check_t1') +GO +DBCC CHECKIDENT('[MASTER]."dBo".[babel_dbcc_CHECK_t1]') +GO + +-- schema and object name containing spaces and dots +DBCC CHECKIDENT('[babel_dbcc_check_t2 .with .dot_an_spaces]'); +GO + +DBCC CHECKIDENT('master.."babel_dbcc_check_t2 .with .dot_an_spaces"'); +GO + +DBCC CHECKIDENT('[babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces"'); +GO + +-- schema and object name containing spaces and dots + mixed case +DBCC CHECKIDENT('[BABEL_DBCC_CHECK_T2 .with .dOT_AN_SPACES]'); +GO + +DBCC CHECKIDENT('MASTer.."babel_dbcc_CHECK_T2 .with .dot_an_SPACES"'); +GO + +DBCC CHECKIDENT('[babel_DBCC_CHECK_schema .with .DOT_and_spaces]."babel_dbcc_CHECK_T3 .with .dot_and_spaces"'); +GO + +-- db name longer then 63 and doing cross db call +CREATE DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +USE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +CREATE TABLE babel_3201_longer__name_db_table (a int identity, b int); +GO + +USE master; +go + +DBCC CHECKIDENT('babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij.dbo.babel_3201_longer__name_db_table', noreseed); +GO + +-- db name longer and mixed case as well. +DBCC CHECKIDENT('bAbEl_dBcC_ChEcKiDeNt_dAtAbAsE_LoNgEr_tHaN_63_0AbCdEfGiJ1AbCdEfGiJ2AbCdEfGiJ3AbCdEfGiJ4AbCdEfGiJ5AbCdEfGiJ6AbCdEfGiJ7AbCdEfGiJ8AbCdEfGhIj9aBcDeFgHiJ.dbo.babel_3201_longer__name_db_table', noreseed); +GO + +-- drop this db because of single_db mode +DROP DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +-- create database to test cross db behavior. +CREATE DATABASE babel_3201_db1; +GO + +USE babel_3201_db1 +GO + +CREATE TABLE babel_3201_db1_database_table1(a int identity, b int); +GO + +CREATE USER babel_3201_db1_log1_usr1 FOR LOGIN babel_3201_log1 +GO + +-- tsql user=babel_3201_log1 password=12345678 +-- Should throw - must be owner of schema dbo +DBCC CHECKIDENT('babel_3201_db1..babel_3201_db1_database_table1', NORESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema dbo)~~ + + +-- tsql +USE babel_3201_db1 +GO +DROP USER babel_3201_db1_log1_usr1 +GO + + +-- tsql user=babel_3201_log1 password=12345678 +-- Should throw - The server principal "babel_3201_log1" is not able to access the database "babel_3201_db1" under the current security context +DBCC CHECKIDENT('babel_3201_db1..babel_3201_db1_database_table1', NORESEED); +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: The server principal "babel_3201_log1" is not able to access the database "babel_3201_db1" under the current security context)~~ + + +-- tsql +USE babel_3201_db1 +GO +GRANT CONNECT TO GUEST; +GO + +-- tsql user=babel_3201_log1 password=12345678 +-- Permission Check +USE babel_3201_db1; +GO + +-- should throw error - must be owner of schema master_dbo +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema master_dbo)~~ + + +-- tsql +USE master; +GO + +ALTER SERVER ROLE sysadmin ADD MEMBER babel_3201_log1; +GO + +-- tsql user=babel_3201_log1 password=12345678 +USE babel_3201_db1; +GO + +-- This should work correctly +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO + +-- tsql +-- test locks in two connections transaction. +BEGIN TRAN +DBCC CHECKIDENT('babel_3201_test_locks', noreseed) +GO + + +-- tsql user=babel_3201_test_locks password=123456 +-- This reseed the identity values while the other transaction is not yet completed. +BEGIN TRAN +DBCC CHECKIDENT('babel_3201_test_locks', reseed, 101); +SELECT * FROM babel_3201_test_locks; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '1'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +int#!#int +1#!#10 +~~END~~ + + +-- tsql +-- This will show the changed values of ident +DBCC CHECKIDENT('babel_3201_test_locks', noreseed); +SELECT * FROM babel_3201_test_locks; +COMMIT; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Checking identity information: current identity value '101', current column value '1'. +DBCC execution completed. If DBCC printed error messages, contact your system administrator. Server SQLState: S0001)~~ + +~~START~~ +int#!#int +1#!#10 +~~END~~ + + +-- tsql +-- test with user name longer then 64 chars. +USE MASTER +GO +CREATE USER babel_3201_db1_log1_user_name_longer_then_64_char_abdhcdjddjdhskdsh FOR LOGIN babel_3201_log1 +GO + +-- tsql user=babel_3201_log1 password=12345678 +USE babel_3201_db1; +GO +CREATE SCHEMA [babel_3201_user_schema] +GO +CREATE TABLE [babel_3201_db1].[babel_3201_user_schema].[babel_3201_user_table] (a int identity, b int); +GO +-- This should work correctly +DBCC CHECKIDENT('[babel_3201_db1].[babel_3201_user_schema].[babel_3201_user_table]', NORESEED); +GO +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO + +-- tsql +USE master; +GO +DROP USER babel_3201_db1_log1_user_name_longer_then_64_char_abdhcdjddjdhskdsh +GO diff --git a/test/JDBC/expected/BABEL-UNSUPPORTED.out b/test/JDBC/expected/BABEL-UNSUPPORTED.out index 6306a0b153..bfdd35f053 100644 --- a/test/JDBC/expected/BABEL-UNSUPPORTED.out +++ b/test/JDBC/expected/BABEL-UNSUPPORTED.out @@ -2537,7 +2537,7 @@ DBCC CLONEDATABASE (d12608, d12608_clone); GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: 'DBCC' is not currently supported in Babelfish)~~ +~~ERROR (Message: DBCC CLONEDATABASE is not yet supported in Babelfish)~~ DROP DATABASE d12608; GO diff --git a/test/JDBC/input/BABEL-3201-vu-cleanup.sql b/test/JDBC/input/BABEL-3201-vu-cleanup.sql new file mode 100644 index 0000000000..455056962a --- /dev/null +++ b/test/JDBC/input/BABEL-3201-vu-cleanup.sql @@ -0,0 +1,59 @@ +DROP TABLE babel_3201_t_int; +GO + +DROP TABLE babel_dbcc_check_t1; +GO + +DROP TABLE [babel_dbcc_check_t2 .with .dot_an_spaces]; +GO + +DROP TABLE [babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces"; +GO + +DROP SCHEMA [babel_dbcc_check_schema .with .dot_and_spaces] +GO + +DROP TABLE babel_3201_t_tinyint; +GO + +DROP TABLE babel_3201_t_smallint; +GO + +DROP TABLE babel_3201_t_bigint; +GO + +DROP TABLE babel_3201_t_numeric; +GO + +DROP TABLE babel_3201_t_decimal; +GO + +DROP TABLE babel_3201_t1; +GO + +DROP TABLE babel_3201_t2; +GO + +DROP TABLE babel_3201_sch1.babel_3201_t2; +GO + +DROP TABLE babel_3201_test_locks; +GO + +DROP PROCEDURE babel_3201_proc1; +GO + +DROP PROCEDURE babel_3201_proc2; +GO + +DROP LOGIN babel_3201_log1; +GO + +DROP LOGIN babel_3201_test_locks; +GO + +DROP SCHEMA babel_3201_sch1; +GO + +DROP DATABASE babel_3201_db1; +GO diff --git a/test/JDBC/input/BABEL-3201-vu-prepare.sql b/test/JDBC/input/BABEL-3201-vu-prepare.sql new file mode 100644 index 0000000000..0a033d32e1 --- /dev/null +++ b/test/JDBC/input/BABEL-3201-vu-prepare.sql @@ -0,0 +1,123 @@ +CREATE SCHEMA babel_3201_sch1; +GO + +CREATE TABLE babel_3201_sch1.babel_3201_t2(a varchar(20), b int identity); +GO + +CREATE TABLE babel_3201_t_int( a int identity, b int); +GO + +CREATE TABLE babel_dbcc_check_t1 (a int identity, b int); +GO + +CREATE TABLE [babel_dbcc_check_t2 .with .dot_an_spaces] (a int identity, b int); +GO + +CREATE SCHEMA [babel_dbcc_check_schema .with .dot_and_spaces] +GO + +CREATE TABLE [babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces" (a int identity, b int); +GO + +CREATE TABLE babel_3201_t_tinyint( a tinyint identity(5,1), b int); +GO + +CREATE TABLE babel_3201_t_smallint( a smallint identity(10,10), b int); +GO + +CREATE TABLE babel_3201_t_bigint( a bigint identity(3,3), b int); +GO + +CREATE TABLE babel_3201_t_numeric( a numeric identity(4,2), b int); +GO + +CREATE TABLE babel_3201_t_decimal( a decimal identity(7,3), b int); +GO + +CREATE TABLE babel_3201_t1( a int identity, b int); +GO + +CREATE TABLE babel_3201_t2( a int, b int); +GO + +CREATE TABLE babel_3201_test_locks (a int identity, b int); +GO + +INSERT INTO babel_3201_test_locks VALUES (10); +GO + +INSERT INTO babel_3201_sch1.babel_3201_t2 VALUES ('string 1'); +GO + +INSERT INTO babel_3201_t_tinyint VALUES (5); +GO + +INSERT INTO babel_3201_t_tinyint VALUES (6); +GO + +INSERT INTO babel_3201_t_tinyint VALUES (7); +GO + +INSERT INTO babel_3201_t_smallint VALUES (5); +GO + +INSERT INTO babel_3201_t_smallint VALUES (6); +GO + +INSERT INTO babel_3201_t_smallint VALUES (7); +GO + +INSERT INTO babel_3201_t_int VALUES (5); +GO + +INSERT INTO babel_3201_t_int VALUES (6); +GO + +INSERT INTO babel_3201_t_int VALUES (7); +GO + +INSERT INTO babel_3201_t_bigint VALUES (5); +GO + +INSERT INTO babel_3201_t_bigint VALUES (6); +GO + +INSERT INTO babel_3201_t_bigint VALUES (6); +GO + +INSERT INTO babel_3201_t_numeric VALUES (5); +GO + +INSERT INTO babel_3201_t_numeric VALUES (6); +GO + +INSERT INTO babel_3201_t_numeric VALUES (7); +GO + +INSERT INTO babel_3201_t_decimal VALUES (5); +GO + +INSERT INTO babel_3201_t_decimal VALUES (6); +GO + +INSERT INTO babel_3201_t_decimal VALUES (7); +GO + +CREATE PROCEDURE babel_3201_proc1 +AS +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 30) +GO + +CREATE PROCEDURE babel_3201_proc2 +AS +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 257) +GO + +CREATE LOGIN babel_3201_log1 WITH PASSWORD='12345678'; +GO + +CREATE LOGIN babel_3201_test_locks WITH PASSWORD='123456'; +GO + +ALTER SERVER ROLE sysadmin ADD MEMBER babel_3201_test_locks +GO diff --git a/test/JDBC/input/BABEL-3201-vu-verify.mix b/test/JDBC/input/BABEL-3201-vu-verify.mix new file mode 100644 index 0000000000..bb3bf5124b --- /dev/null +++ b/test/JDBC/input/BABEL-3201-vu-verify.mix @@ -0,0 +1,487 @@ +DBCC CHECKIDENT(babel_3201_t_int, NORESEED); +GO + +-- test with mixed case in table name +DBCC CHECKIDENT(BABEL_3201_t_iNt, NORESEED); +GO +DBCC CHECKIDENT(BABEL_3201_T_INT, NORESEED); +GO + +-- test with table in quotes (+mixed cases) +DBCC CHECKIDENT('babel_3201_t_int', NORESEED); +GO +DBCC CHECKIDENT('baBEl_3201_T_inT', NORESEED); +GO + +-- test with table in brackets (+mixed case) +DBCC CHECKIDENT([babel_3201_t_int], NORESEED); +GO +DBCC CHECKIDENT([baBEL_3201_t_InT], NORESEED); +GO + +-- test with table in brackets with quotes (+mixed case) +DBCC CHECKIDENT('[babel_3201_t_int]', NORESEED); +GO +DBCC CHECKIDENT('[BABEL_3201_t_int]', NORESEED); +GO + +-- test when trailing space - should work +DBCC CHECKIDENT('babel_3201_t_int ', NORESEED); +GO +DBCC CHECKIDENT('babel_3201_T_INT ', NORESEED); +GO + +-- test when leading space - should throw error +DBCC CHECKIDENT(' babel_3201_t_int ', NORESEED); +GO + +-- test when table name is empty in quotes +DBCC CHECKIDENT('', NORESEED); +GO + +-- same as DBCC CHECKIDENT(, RESEED), identity value is not changed +-- if current identity value for a table is less than the maximum identity value +-- stored in the identity column +DBCC CHECKIDENT(babel_3201_t_int); +GO + + +DBCC CHECKIDENT(babel_3201_t_int, RESEED); +GO + +INSERT INTO babel_3201_t_int VALUES (8); +GO + +SELECT * FROM babel_3201_t_int; +GO + +DBCC CHECKIDENT('babel_3201_sch1.babel_3201_t2'); +GO + +-- Set identity value to 5 which is less than the maximum value(which is 9) of the identity +-- column, using RESEED option in this case should will reset the identity value +-- to maximum value of the identity column. Value inserted in next insert will +-- be (max_identity_col_value + increament). +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 5); +GO +INSERT INTO babel_3201_t_bigint VALUES (8); +GO +SELECT * from babel_3201_t_bigint; +GO + +-- This will reset the current identity value(currently 8) to the maximum value of the identity column (currently 9) +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED); +GO +INSERT INTO babel_3201_t_bigint VALUES (9); +GO +SELECT * from babel_3201_t_bigint; +GO + +-- no rows have been inserted in the table; both current identity value current +-- column value should be NULL (TO-DO) +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, NORESEED); +SELECT * FROM babel_3201_t1; +COMMIT; +GO + +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, RESEED); +SELECT * FROM babel_3201_t1; +COMMIT; +GO + +-- current identity value should be NULL (TO-DO), identity value inserted in +-- next INSERT operation should be new_reseed_value. +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, RESEED, 5); +INSERT INTO babel_3201_t1 VALUES (50); +COMMIT; +GO + +BEGIN TRAN; +DBCC CHECKIDENT(babel_3201_t1, NORESEED); +select * from babel_3201_t1; +COMMIT; +GO + +-- Remove all rows in table using TRUNCATE TABLE, Identity value will become NULL +-- next insert operation should be default identity value if no new_reseed_value is provided. +TRUNCATE TABLE babel_3201_t_int; +GO +dbcc checkident(babel_3201_t_int, NORESEED); +GO +INSERT INTO babel_3201_t_int values(15); +GO +select * from babel_3201_t_int; + +-- Remove all rows in table using TRUNCATE TABLE, identity value inserted in +-- next INSERT operation should be new_reseed_value. +TRUNCATE TABLE babel_3201_t_int; +GO +DBCC CHECKIDENT(babel_3201_t_int, RESEED, 10); +GO +INSERT INTO babel_3201_t_int VALUES (5); +GO +SELECT * FROM babel_3201_t_int; +GO + + +-- Remove all rows in table using DELETE TABLE, identity value inserted in next +-- INSERT operation should be (new_reseed_value + increment). +DELETE FROM babel_3201_t_bigint; +GO +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 10); +GO +INSERT INTO babel_3201_t_bigint VALUES (5); +GO +SELECT * FROM babel_3201_t_bigint; +GO + +-- Remove all rows in table using DELETE TABLE current identity will not become default identity value, +-- identity value inserted in next operation should use (default identity value + increament) if no new_reseed_value is provided. +DELETE FROM babel_3201_t_bigint; +GO +dbcc checkident(babel_3201_t_bigint, NORESEED); +GO +INSERT INTO babel_3201_t_bigint VALUES (5); +GO +SELECT * FROM babel_3201_t_bigint; +GO + +-- If some rows are present already in the table, identity value inserted in next +-- INSERT operation should be (new_reseed_value + increament) +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 27); +GO +INSERT INTO babel_3201_t_bigint VALUES (32); +GO +SELECT * FROM babel_3201_t_bigint; +GO + +-- Incorrect DBCC command option +DBCC CHECKIDENT(babel_3201_t1) WITH NO_INFO; +GO + +-- Invalid parameter 1 +DBCC CHECKIDENT(5); +GO + +DBCC CHECKIDENT(babel_3201_t_int, RESEED, ) WITH NO_INFOMSGS; +GO + +-- Invalid keyword +DBCC CHECKIDENT(babel_3201_t1, RESEE); +GO + +-- Invalid datatype +DBCC CHECKIDENT(babel_3201_t1, RESEED, 1313abc); +GO + +-- Unsupported DBCC command +DBCC CHECKTABLE(babel_3201_t1); +GO + +-- Invalid DBCC command +DBCC FAKE_COMMAND(t1); +GO + +-- Database undefined +DBCC CHECKIDENT('fake_db.dbo.babel_3201_t1', NORESEED); +GO + +-- Schema undefined +DBCC CHECKIDENT('fake_schema.babel_3201_t1', NORESEED); +GO + +-- Table undefined +DBCC CHECKIDENT(fake_babel_3201_t1, RESEED); +GO + +-- Table does not have identity column +DBCC CHECKIDENT(babel_3201_t2, RESEED); +GO + +-- new_reseed_value as expression is not allowed +DBCC CHECKIDENT(babel_3201_t2, RESEED, 4+5); +GO + +-- new_reseed_value is out of tinyint datatype range +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, 256); +GO + +DBCC CHECKIDENT(babel_3201_t_tinyint, RESEED, -1); +GO + +-- new_reseed_value is out of smallint datatype range +DBCC CHECKIDENT(babel_3201_t_smallint, RESEED, 32768); +GO + +DBCC CHECKIDENT(babel_3201_t_smallint, RESEED, -32769); +GO + + +-- new_reseed_value is out of int datatype range +DBCC CHECKIDENT(babel_3201_t_int, RESEED, 2147483648); +GO + +DBCC CHECKIDENT(babel_3201_t_int, RESEED, -2147483649); +GO + +-- new_reseed_value is out of bigint datatype range +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, 9223372036854775808); +GO + +DBCC CHECKIDENT(babel_3201_t_bigint, RESEED, -9223372036854775809); +GO + +-- numeric/decimal datatypes are internally converted to bigint, so allowed +-- range is same as that of bigint +DBCC CHECKIDENT(babel_3201_t_numeric, RESEED, 9223372036854775808); +GO + +-- When new_reseed_value is a float value, only value before the decimal is used +DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 15.65); +GO + +-- When reseed_value is negative and zero, bbf currently does not support reseed to negative/zero value +dbcc checkident(babel_3201_t_decimal, reseed, -10) +GO +dbcc checkident(babel_3201_t_decimal, reseed, 0) +Go +dbcc checkident(babel_3201_t_decimal, reseed, .123) +Go +dbcc checkident(babel_3201_t_decimal, reseed, -.123) +Go +dbcc checkident(babel_3201_t_decimal, reseed, .) +GO +dbcc checkident(babel_3201_t_decimal, reseed, -) +GO +dbcc checkident(babel_3201_t_decimal, reseed, .-); +GO + +SELECT * FROM babel_3201_t_decimal; +GO + +begin tran; +DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 10); +INSERT INTO babel_3201_t_decimal VALUES (9); +commit; +go + +SELECT * FROM babel_3201_t_decimal; +GO + +BEGIN TRAN; + DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 133ac); + INSERT INTO babel_3201_t_decimal VALUES (10); +COMMIT; +GO + +SELECT * FROM babel_3201_t_decimal; +GO + +BEGIN TRAN; + DBCC CHECKIDENT(babel_3201_t_decimal, RESEED, 20); + INSERT INTO babel_3201_t_decimal VALUES (11); +ROLLBACK; +GO + +-- Check current_identity value after tran rollback +-- babelfish does not support rolling-back dbcc changes after transection rollback. +-- Current identity value will be = reseed_value inside the rollbacked transection + increament = 20+3=23 +BEGIN TRAN; +dbcc checkident(babel_3201_t_decimal, noreseed); +SELECT * FROM babel_3201_t_decimal; +COMMIT; +GO + +EXEC babel_3201_proc1; +GO + +INSERT INTO babel_3201_t_tinyint VALUES (10); +GO + +SELECT * FROM babel_3201_t_tinyint; +GO + +EXEC babel_3201_proc2; +GO + +-- testing different scenarios of 3-part name +DBCC CHECKIDENT('dbo.babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('..babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('master.dbo.babel_dbcc_check_t1') +GO + +DBCC CHECKIDENT('[master]."dbo".[babel_dbcc_check_t1]') +GO + +DBCC CHECKIDENT('"master".[dbo]."babel_dbcc_check_t1"') +GO + +DBCC CHECKIDENT('master..babel_dbcc_check_t1') +GO + +-- with mixed case names of db, schema, and table. +DBCC CHECKIDENT('dbo.BABEL_DBCC_check_t1') +GO +DBCC CHECKIDENT('master.DBO.BABEL_dbcc_check_t1') +GO +DBCC CHECKIDENT('[MASTER]."dBo".[babel_dbcc_CHECK_t1]') +GO + +-- schema and object name containing spaces and dots +DBCC CHECKIDENT('[babel_dbcc_check_t2 .with .dot_an_spaces]'); +GO + +DBCC CHECKIDENT('master.."babel_dbcc_check_t2 .with .dot_an_spaces"'); +GO + +DBCC CHECKIDENT('[babel_dbcc_check_schema .with .dot_and_spaces]."babel_dbcc_check_t3 .with .dot_and_spaces"'); +GO + +-- schema and object name containing spaces and dots + mixed case +DBCC CHECKIDENT('[BABEL_DBCC_CHECK_T2 .with .dOT_AN_SPACES]'); +GO + +DBCC CHECKIDENT('MASTer.."babel_dbcc_CHECK_T2 .with .dot_an_SPACES"'); +GO + +DBCC CHECKIDENT('[babel_DBCC_CHECK_schema .with .DOT_and_spaces]."babel_dbcc_CHECK_T3 .with .dot_and_spaces"'); +GO + +-- db name longer then 63 and doing cross db call +CREATE DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +USE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +CREATE TABLE babel_3201_longer__name_db_table (a int identity, b int); +GO + +USE master; +go + +DBCC CHECKIDENT('babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij.dbo.babel_3201_longer__name_db_table', noreseed); +GO + +-- db name longer and mixed case as well. +DBCC CHECKIDENT('bAbEl_dBcC_ChEcKiDeNt_dAtAbAsE_LoNgEr_tHaN_63_0AbCdEfGiJ1AbCdEfGiJ2AbCdEfGiJ3AbCdEfGiJ4AbCdEfGiJ5AbCdEfGiJ6AbCdEfGiJ7AbCdEfGiJ8AbCdEfGhIj9aBcDeFgHiJ.dbo.babel_3201_longer__name_db_table', noreseed); +GO + +-- drop this db because of single_db mode +DROP DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij +GO + +-- create database to test cross db behavior. +CREATE DATABASE babel_3201_db1; +GO + +USE babel_3201_db1 +GO + +CREATE TABLE babel_3201_db1_database_table1(a int identity, b int); +GO + +CREATE USER babel_3201_db1_log1_usr1 FOR LOGIN babel_3201_log1 +GO + +-- Should throw - must be owner of schema dbo +-- tsql user=babel_3201_log1 password=12345678 +DBCC CHECKIDENT('babel_3201_db1..babel_3201_db1_database_table1', NORESEED); +GO + +-- tsql +USE babel_3201_db1 +GO +DROP USER babel_3201_db1_log1_usr1 +GO + + +-- Should throw - The server principal "babel_3201_log1" is not able to access the database "babel_3201_db1" under the current security context +-- tsql user=babel_3201_log1 password=12345678 +DBCC CHECKIDENT('babel_3201_db1..babel_3201_db1_database_table1', NORESEED); +GO + +-- tsql +USE babel_3201_db1 +GO +GRANT CONNECT TO GUEST; +GO + +-- Permission Check +-- tsql user=babel_3201_log1 password=12345678 +USE babel_3201_db1; +GO + +-- should throw error - must be owner of schema master_dbo +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO + +-- tsql +USE master; +GO + +ALTER SERVER ROLE sysadmin ADD MEMBER babel_3201_log1; +GO + +-- tsql user=babel_3201_log1 password=12345678 +USE babel_3201_db1; +GO + +-- This should work correctly +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO + +-- test locks in two connections transaction. +-- tsql +BEGIN TRAN +DBCC CHECKIDENT('babel_3201_test_locks', noreseed) +GO + + +-- tsql user=babel_3201_test_locks password=123456 +-- This reseed the identity values while the other transaction is not yet completed. +BEGIN TRAN +DBCC CHECKIDENT('babel_3201_test_locks', reseed, 101); +SELECT * FROM babel_3201_test_locks; +COMMIT; +GO + +-- tsql +-- This will show the changed values of ident +DBCC CHECKIDENT('babel_3201_test_locks', noreseed); +SELECT * FROM babel_3201_test_locks; +COMMIT; +GO + +-- test with user name longer then 64 chars. +-- tsql +USE MASTER +GO +CREATE USER babel_3201_db1_log1_user_name_longer_then_64_char_abdhcdjddjdhskdsh FOR LOGIN babel_3201_log1 +GO + +-- tsql user=babel_3201_log1 password=12345678 +USE babel_3201_db1; +GO +CREATE SCHEMA [babel_3201_user_schema] +GO +CREATE TABLE [babel_3201_db1].[babel_3201_user_schema].[babel_3201_user_table] (a int identity, b int); +GO +-- This should work correctly +DBCC CHECKIDENT('[babel_3201_db1].[babel_3201_user_schema].[babel_3201_user_table]', NORESEED); +GO +DBCC CHECKIDENT('master.dbo.babel_3201_t_tinyint', RESEED, 10) +GO + +-- tsql +USE master; +GO +DROP USER babel_3201_db1_log1_user_name_longer_then_64_char_abdhcdjddjdhskdsh +GO diff --git a/test/python/expected/pyodbc/BABEL-3201.out b/test/python/expected/pyodbc/BABEL-3201.out new file mode 100644 index 0000000000..8135cf099f --- /dev/null +++ b/test/python/expected/pyodbc/BABEL-3201.out @@ -0,0 +1,56 @@ + +starting permutation : { s1dbcc_noreseed s2i s2s s1c s2c } +step s1dbcc_noreseed: dbcc checkident(dbcc_test_locks, NORESEED) +step s2i: INSERT INTO dbcc_test_locks VALUES (9); +~~ROW COUNT: 1~~ + +step s2s: SELECT * from dbcc_test_locks; +~~START~~ +int#!#int +1#!#5 +2#!#7 +3#!#9 +~~END~~ + +step s1c: COMMIT; +step s2c: COMMIT; + +starting permutation : { s1dbcc_reseed_without_new_reseed_value s2i s2s s1c s2c } +step s1dbcc_reseed_without_new_reseed_value: dbcc checkident(dbcc_test_locks, RESEED) +step s2i: INSERT INTO dbcc_test_locks VALUES (9); +~~ROW COUNT: 1~~ + +step s2s: SELECT * from dbcc_test_locks; +~~START~~ +int#!#int +1#!#5 +2#!#7 +3#!#9 +~~END~~ + +step s1c: COMMIT; +step s2c: COMMIT; + +starting permutation : { s1dbcc_reseed_with_new_value s2s s1c s2i s2s s2c } +step s1dbcc_reseed_with_new_value: dbcc checkident(dbcc_test_locks, RESEED, 10) +step s2s: SELECT * from dbcc_test_locks; +step s1c: COMMIT; +step s2s: <... completed> +~~START~~ +int#!#int +1#!#5 +2#!#7 +~~END~~ + +step s2i: INSERT INTO dbcc_test_locks VALUES (9); +~~ROW COUNT: 1~~ + +step s2s: SELECT * from dbcc_test_locks; +~~START~~ +int#!#int +1#!#5 +2#!#7 +11#!#9 +~~END~~ + +step s2c: COMMIT; diff --git a/test/python/input/isolation/BABEL-3201.spec b/test/python/input/isolation/BABEL-3201.spec new file mode 100644 index 0000000000..4ebe71dc3e --- /dev/null +++ b/test/python/input/isolation/BABEL-3201.spec @@ -0,0 +1,42 @@ +setup +{ + + create table dbcc_test_locks (a int identity, b int); + INSERT INTO dbcc_test_locks VALUES (5); + INSERT INTO dbcc_test_locks VALUES (7); + +} + +teardown +{ + drop table dbcc_test_locks; +} + +session s1 +setup { + BEGIN TRAN TR1; + } +step s1dbcc_noreseed { dbcc checkident(dbcc_test_locks, NORESEED) } +step s1dbcc_reseed_without_new_reseed_value { dbcc checkident(dbcc_test_locks, RESEED) } +step s1dbcc_reseed_with_new_value { dbcc checkident(dbcc_test_locks, RESEED, 10) } +step s1i { INSERT INTO dbcc_test_locks VALUES (8); } +step s1s { SELECT * FROM dbcc_test_locks; } +step s1c { COMMIT; } + +session s2 +setup { + BEGIN TRAN TR2; + } +step s2s { SELECT * from dbcc_test_locks; } +step s2i { INSERT INTO dbcc_test_locks VALUES (9); } +step s2c { COMMIT; } + +# till TR1 is commited, TR2 should be able to insert/read data from table t2 in case of noreeseed +permutation s1dbcc_noreseed s2i s2s s1c s2c + +# till TR1 is commited, TR-2 should be able to insert/read data from table t2 in case of reeseed without new value. +permutation s1dbcc_reseed_without_new_reseed_value s2i s2s s1c s2c + +# till TR1 is commited, TR-2 should NOT be able to read data from table t2 in case of reeseed with new value. +permutation s1dbcc_reseed_with_new_value s2s s1c s2i s2s s2c + From 3a0259b46975b2ed0327b8922a22df72436e4a25 Mon Sep 17 00:00:00 2001 From: Anikait Agrawal <54908236+Anikait143@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:04:53 +0530 Subject: [PATCH 6/6] Implemented TDS Receiver Support for Spatial Datatypes and Tested both Sender and Receiver functions with JDBC, ODBC and DOTNET Drivers (#1921) This commit contains Receiver Support for GEOGRAPHY and GEOGRAPHY datatype for Point Type and also tested the Sender and Receiver functions with JDBC, ODBC and DOTNET drivers. Added CAST (Varbinary to Geometry/Geography and vice-versa) required by JDBC driver to receiver Geometry/Geography as Varbinary. Introduced appropriate error messages when an unsupported functionality(such as LINESTRING) is queried. Added Receiver function required by DOTNET driver to receiver Geometry/Geography as CLRUDT types. Added new tests in TestSpatialPoint-vu-* to test receiver function for JDBC driver. Added logic to parse the geometry/geography inputs in JDBCPreparedStatement.java file. Added new tests TestPoint.txt to test Sender and Receiver functions for DOTNET driver. Added logic to parse the geometry/geography inputs in PrepareExecBinding.cs file. Added new tests geometry.cpp and geography.cpp to test Sender and Receiver functions for ODBC driver. Added some sender function tests in test_data_types.cpp file for ODBC driver. Tested the changes with valgrind and didn't see any memory issues. Task: BABEL- 4369 Authored-by: Anikait Agrawal agraani@amazon.com Signed-off-by: Anikait Agrawal agraani@amazon.com --- contrib/babelfishpg_common/Makefile | 14 +- contrib/babelfishpg_common/sql/geography.sql | 274 +++++++---- contrib/babelfishpg_common/sql/geometry.sql | 110 ++++- .../upgrades/spatial_types--3.2.0--3.3.0.sql | 385 +++++++++++---- .../src/backend/tds/tds_data_map.c | 4 +- .../src/backend/tds/tdsresponse.c | 4 +- .../babelfishpg_tds/src/backend/tds/tdsrpc.c | 47 ++ .../src/backend/tds/tdstypeio.c | 118 +++-- .../src/include/tds_iofuncmap.h | 4 +- .../babelfishpg_tds/src/include/tds_request.h | 4 +- .../expected/TestSpatialPoint-vu-cleanup.out | 14 - .../expected/TestSpatialPoint-vu-prepare.out | 450 ++++++++++-------- .../expected/TestSpatialPoint-vu-verify.out | 47 +- ...up.sql => TestSpatialPoint-vu-cleanup.txt} | 14 - .../datatypes/TestSpatialPoint-vu-prepare.sql | 240 ---------- .../datatypes/TestSpatialPoint-vu-prepare.txt | 180 +++++++ .../com/sqlsamples/JDBCPreparedStatement.java | 28 ++ test/dotnet/ExpectedOutput/TestPoint.out | 50 ++ test/dotnet/dotnet.csproj | 1 + test/dotnet/input/Datatypes/TestPoint.txt | 49 ++ test/dotnet/src/PrepareExecBinding.cs | 77 +++ test/odbc/mssqlodbc/test_data_types.cpp | 90 ++++ test/odbc/psqlodbc/test/geography.cpp | 127 +++++ test/odbc/psqlodbc/test/geometry.cpp | 127 +++++ .../expected_dependency.out | 12 +- 25 files changed, 1748 insertions(+), 722 deletions(-) rename test/JDBC/input/datatypes/{TestSpatialPoint-vu-cleanup.sql => TestSpatialPoint-vu-cleanup.txt} (92%) delete mode 100644 test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.sql create mode 100644 test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt create mode 100644 test/dotnet/ExpectedOutput/TestPoint.out create mode 100644 test/dotnet/input/Datatypes/TestPoint.txt create mode 100644 test/odbc/psqlodbc/test/geography.cpp create mode 100644 test/odbc/psqlodbc/test/geometry.cpp diff --git a/contrib/babelfishpg_common/Makefile b/contrib/babelfishpg_common/Makefile index 3512f4ba32..21c47f2e59 100644 --- a/contrib/babelfishpg_common/Makefile +++ b/contrib/babelfishpg_common/Makefile @@ -52,7 +52,8 @@ include $(PGXS) MODULEPATH = $$libdir/$(EXTENSION)-$(BBFPGCMN_MAJOR_VERSION) -UPGRADES = $(patsubst sql/upgrades/%.sql,sql/%.sql,$(wildcard sql/upgrades/*.sql)) +UPGRADES = $(patsubst sql/upgrades/babelfishpg_common--%.sql,sql/babelfishpg_common--%.sql,$(wildcard sql/upgrades/babelfishpg_common--*.sql)) +GENERATED_UPGRADES = sql/$(EXTENSION)--3.2.0--3.3.0.sql ifdef PREV_EXTVERSION DATA = sql/$(EXTENSION)--$(PREV_EXTVERSION).sql @@ -60,7 +61,8 @@ endif DATA_built = \ $(EXTENSION).control \ - sql/$(EXTENSION)--$(EXTVERSION).sql $(UPGRADES) + sql/$(EXTENSION)--$(EXTVERSION).sql $(UPGRADES) \ + $(GENERATED_UPGRADES) #include ../Makefile.common @@ -78,7 +80,7 @@ include $(PGXS) ifeq ($(GE91),yes) all: sql/$(EXTENSION)--$(EXTVERSION).sql $(UPGRADES) -all: sql/upgrades/$(EXTENSION)--3.2.0--3.3.0.sql sql/upgrades/babelfishpg_upgrades.in +all: $(GENERATED_UPGRADES) endif $(EXTENSION).control: $(EXTENSION).control.in @@ -96,18 +98,18 @@ ifeq (,$(filter $(FLAG_TO_CHECK),$(PG_CPPFLAGS))) sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).in cpp $< | sed 's/^# /-- /g' > $@ - sql/upgrades/$(EXTENSION)--3.2.0--3.3.0.sql: sql/upgrades/babelfishpg_upgrades.in + sql/$(EXTENSION)--3.2.0--3.3.0.sql: sql/upgrades/babelfishpg_upgrades.in cpp -D PREV_VERSION=3.2.0 -D CUR_VERSION=3.3.0 $< | sed 's/^# /-- /g' > $@ else # The flag is present build the .in file including the spatial type files sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).in cpp -D ENABLE_SPATIAL_TYPES=1 $< | sed 's/^# /-- /g' > $@ - sql/upgrades/$(EXTENSION)--3.2.0--3.3.0.sql: sql/upgrades/babelfishpg_upgrades.in + sql/$(EXTENSION)--3.2.0--3.3.0.sql: sql/upgrades/babelfishpg_upgrades.in cpp -D ENABLE_SPATIAL_TYPES=1 -D PREV_VERSION=3.2.0 -D CUR_VERSION=3.3.0 $< | sed 's/^# /-- /g' > $@ endif -sql/%.sql: sql/upgrades/%.sql +sql/babelfishpg_common--%.sql: sql/upgrades/babelfishpg_common--%.sql cp $< $@ diff --git a/contrib/babelfishpg_common/sql/geography.sql b/contrib/babelfishpg_common/sql/geography.sql index 451b5a84b2..b79eb1493b 100644 --- a/contrib/babelfishpg_common/sql/geography.sql +++ b/contrib/babelfishpg_common/sql/geography.sql @@ -55,18 +55,127 @@ CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.GEOGRAPHY, integer, boolean) CREATE CAST (sys.GEOGRAPHY AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(sys.GEOGRAPHY, integer, boolean) AS IMPLICIT; +CREATE OR REPLACE FUNCTION sys.get_valid_srids() + RETURNS integer[] + AS $$ + DECLARE + valid_srids integer[] := ARRAY[ + 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, + 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, + 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, + 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, + 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, + 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, + 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, + 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, + 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, + 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, + 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, + 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, + 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, + 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, + 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, + 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, + 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, + 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, + 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, + 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, + 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 + ]; + BEGIN + RETURN valid_srids; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(bytea) RETURNS sys.GEOGRAPHY - AS '$libdir/postgis-3','geography_from_binary' - LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + AS $$ + DECLARE + len integer; + varBin bytea; + geomType bytea; + srid integer; + newVarBin bytea; + lat float8; + byte_position integer := 6; + coord_NaN bytea := E'\\x000000000000f87f'; + input_coord bytea; + reversed_bytea bytea := E'\\x'; + i integer := 14; + isNaN integer = 0; + valid_srids integer[]; + BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; + varBin := $1; + len := LENGTH(varBin); + IF len >= 22 THEN + -- General Logic: We are preprocessing it by removing 2 constant Geometry Type bytes -> 01 0c (for 2-D Point Type) Then adding 5 Bytes -> 01 (little endianess) + 4 Bytes (Geography Type). It is expected by the driver + -- Here we are calculating SRID which is initially in little endian order + srid := (get_byte(varBin, 3) << 24) | (get_byte(varBin, 2) << 16) | (get_byte(varBin, 1) << 8) | get_byte(varBin, 0); + -- Here we are calculating value of latitude which is initially in little endian order to check if it lies in the range [-90, 90] + WHILE i > 6 LOOP + reversed_bytea := reversed_bytea || substring(varBin from i for 1); + i = i - 1; + END LOOP; + lat := varbinaryfloat8(CAST (reversed_bytea AS bbf_varbinary)); + WHILE byte_position < len LOOP + -- Get the coordinate to check if it is NaN + input_coord := substring(varBin from byte_position + 1 for 8); + IF encode(input_coord, 'hex') = encode(coord_NaN, 'hex') THEN + isNaN := 1; + END IF; + byte_position := byte_position + 8; + END LOOP; + geomType := substring(varBin from 5 for 2); + varBin := substring(varBin from 1 for 4) || substring(varBin from 7); + IF srid = ANY(valid_srids) AND isNaN = 0 THEN + IF encode(geomType, 'hex') = encode(E'\\x010c', 'hex') THEN + IF lat >= -90.0 AND lat <= 90.0 THEN + newVarBin := E'\\x0101000020' || varBin; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geography.'; + END IF; + ELSE + RAISE EXCEPTION 'Unsupported geometry type'; + END IF; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geography.'; + END IF; + -- Call the underlying function after preprocessing + RETURN (SELECT sys.GEOGRAPHY_helper(newVarBin)); + ELSE + RAISE EXCEPTION 'Invalid Geography'; + END IF; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.bytea(sys.GEOGRAPHY) RETURNS bytea AS '$libdir/postgis-3','LWGEOM_to_bytea' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.bbf_varbinary) + RETURNS sys.GEOGRAPHY + AS $$ + DECLARE + varBin bytea; + BEGIN + varBin := (SELECT CAST ($1 AS bytea)); + -- Call the underlying function after preprocessing + RETURN (SELECT CAST (varBin AS GEOGRAPHY)); + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.bbf_varbinary(sys.GEOGRAPHY) + RETURNS sys.bbf_varbinary + AS '$libdir/postgis-3','LWGEOM_to_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + CREATE CAST (bytea AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(bytea) AS IMPLICIT; CREATE CAST (sys.GEOGRAPHY AS bytea) WITH FUNCTION sys.bytea(sys.GEOGRAPHY) AS IMPLICIT; +CREATE CAST (sys.bbf_varbinary AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(sys.bbf_varbinary) AS IMPLICIT; +CREATE CAST (sys.GEOGRAPHY AS sys.bbf_varbinary) WITH FUNCTION sys.bbf_varbinary(sys.GEOGRAPHY) AS IMPLICIT; CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.GEOMETRY) RETURNS sys.GEOGRAPHY @@ -93,42 +202,34 @@ CREATE OR REPLACE FUNCTION sys.Geography__stgeomfromtext(text, integer) AS $$ DECLARE srid integer; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + Geomtype text; + geom sys.GEOGRAPHY; + valid_srids integer[]; lat float8; - BEGIN + BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $2; - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); - IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN - -- Call the underlying function after preprocessing - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - RETURN (SELECT sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2))); - ELSEIF lat < -90.0 OR lat > 90.0 THEN - RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + geom = (SELECT sys.stgeogfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); + IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN + -- Call the underlying function after preprocessing + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN (SELECT sys.Geography__STFlipCoordinates(geom)); + END IF; + ELSEIF lat < -90.0 OR lat > 90.0 THEN + RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + ELSE + RAISE EXCEPTION 'Inavalid SRID'; + END IF; ELSE - RAISE EXCEPTION 'Inavalid SRID'; + RAISE EXCEPTION '% is not supported', Geomtype; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -138,7 +239,7 @@ CREATE OR REPLACE FUNCTION sys.STAsText(sys.GEOGRAPHY) AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STAsText_helper(sys.Geography__STFlipCoordinates($1))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -154,30 +255,10 @@ CREATE OR REPLACE FUNCTION sys.Geography__Point(float8, float8, srid integer) DECLARE srid integer; lat float8; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + valid_srids integer[]; BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $3; lat := $1; IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN @@ -196,7 +277,7 @@ CREATE OR REPLACE FUNCTION sys.STAsBinary(sys.GEOGRAPHY) AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STAsBinary_helper(sys.Geography__STFlipCoordinates($1))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -206,53 +287,55 @@ CREATE OR REPLACE FUNCTION sys.Geography__STPointFromText(text, integer) AS $$ DECLARE srid integer; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + Geomtype text; + geom sys.GEOGRAPHY; + valid_srids integer[]; lat float8; BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $2; - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); - IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN - -- Call the underlying function after preprocessing - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - RETURN (SELECT sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2))); - ELSEIF lat < -90.0 OR lat > 90.0 THEN - RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + geom = (SELECT sys.stgeogfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); + IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN + -- Call the underlying function after preprocessing + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN (SELECT sys.Geography__STFlipCoordinates(geom)); + END IF; + ELSEIF lat < -90.0 OR lat > 90.0 THEN + RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + ELSE + RAISE EXCEPTION 'Inavalid SRID'; + END IF; ELSE - RAISE EXCEPTION 'Inavalid SRID'; + RAISE EXCEPTION '% is not supported', Geomtype; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.ST_GeometryType(sys.GEOGRAPHY) + RETURNS text + AS '$libdir/postgis-3', 'geometry_geometrytype' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.ST_zmflag(sys.GEOGRAPHY) + RETURNS smallint + AS '$libdir/postgis-3', 'LWGEOM_zmflag' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + -- Minimum distance CREATE OR REPLACE FUNCTION sys.STDistance(geog1 sys.GEOGRAPHY, geog2 sys.GEOGRAPHY) RETURNS float8 AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we're flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STDistance_helper(sys.Geography__STFlipCoordinates($1), sys.Geography__STFlipCoordinates($2))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -298,3 +381,8 @@ CREATE OR REPLACE FUNCTION sys.STDistance_helper(geog1 sys.GEOGRAPHY, geog2 sys. AS '$libdir/postgis-3', 'LWGEOM_distance_ellipsoid' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOGRAPHY_helper(bytea) + RETURNS sys.GEOGRAPHY + AS '$libdir/postgis-3','geography_from_binary' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + diff --git a/contrib/babelfishpg_common/sql/geometry.sql b/contrib/babelfishpg_common/sql/geometry.sql index 82c8e6e81a..1f7772b3ed 100644 --- a/contrib/babelfishpg_common/sql/geometry.sql +++ b/contrib/babelfishpg_common/sql/geometry.sql @@ -73,11 +73,23 @@ CREATE OR REPLACE FUNCTION sys.Geometry__stgeomfromtext(text, integer) AS $$ DECLARE srid integer; + Geomtype text; + geom sys.GEOMETRY; BEGIN srid := $2; IF srid >= 0 AND srid <= 999999 THEN -- Call the underlying function after preprocessing - RETURN (SELECT sys.stgeomfromtext_helper($1, $2)); + geom = (SELECT sys.stgeomfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN geom; + END IF; + ELSE + RAISE EXCEPTION '% is not supported', Geomtype; + END IF; ELSE RAISE EXCEPTION 'SRID value should be between 0 and 999999'; END IF; @@ -96,15 +108,74 @@ CREATE OR REPLACE FUNCTION sys.text(sys.GEOMETRY) LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.GEOMETRY(bytea) - RETURNS sys.GEOMETRY - AS '$libdir/postgis-3','LWGEOM_from_bytea' - LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + RETURNS sys.GEOMETRY + AS $$ + DECLARE + len integer; + varBin bytea; + geomType bytea; + srid integer; + byte_position integer := 6; + coord_NaN bytea := E'\\x000000000000f87f'; + input_coord bytea; + isNaN integer = 0; + newVarBin bytea; + BEGIN + varBin := $1; + len := LENGTH(varBin); + IF len >= 22 THEN + -- We are preprocessing it by removing 2 constant Geometry Type bytes -> 01 0c (for 2-D Point Type) + -- Then adding 5 Bytes -> 01 (little endianess) + 4 Bytes (Geometry Type) + srid := (get_byte(varBin, 3) << 24) | (get_byte(varBin, 2) << 16) | (get_byte(varBin, 1) << 8) | get_byte(varBin, 0); + WHILE byte_position < len LOOP + -- Get the coordinate to check if it is NaN + input_coord := substring(varBin from byte_position + 1 for 8); + IF encode(input_coord, 'hex') = encode(coord_NaN, 'hex') THEN + isNaN := 1; + END IF; + byte_position := byte_position + 8; + END LOOP; + geomType := substring(varBin from 5 for 2); + varBin := substring(varBin from 1 for 4) || substring(varBin from 7); + IF srid >= 0 AND srid <= 999999 AND isNaN = 0 THEN + IF encode(geomType, 'hex') = encode(E'\\x010c', 'hex') THEN + newVarBin := E'\\x0101000020' || varBin; + ELSE + RAISE EXCEPTION 'Unsupported geometry type'; + END IF; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geometry.'; + END IF; + -- Call the underlying function after preprocessing + RETURN (SELECT sys.GEOMETRY_helper(newVarBin)); + ELSE + RAISE EXCEPTION 'Invalid Geometry'; + END IF; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.bytea(sys.GEOMETRY) RETURNS bytea AS '$libdir/postgis-3','LWGEOM_to_bytea' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOMETRY(sys.bbf_varbinary) + RETURNS sys.GEOMETRY + AS $$ + DECLARE + varBin bytea; + BEGIN + varBin := (SELECT CAST ($1 AS bytea)); + -- Call the underlying function after preprocessing + RETURN (SELECT CAST (varBin AS GEOMETRY)); + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.bbf_varbinary(sys.GEOMETRY) + RETURNS sys.bbf_varbinary + AS '$libdir/postgis-3','LWGEOM_to_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + CREATE OR REPLACE FUNCTION sys.GEOMETRY(text) RETURNS sys.GEOMETRY AS '$libdir/postgis-3','parse_WKT_lwgeom' @@ -114,6 +185,8 @@ CREATE CAST (text AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(text) AS IMPLICIT; CREATE CAST (sys.GEOMETRY AS text) WITH FUNCTION sys.text(sys.GEOMETRY) AS IMPLICIT; CREATE CAST (bytea AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(bytea) AS IMPLICIT; CREATE CAST (sys.GEOMETRY AS bytea) WITH FUNCTION sys.bytea(sys.GEOMETRY) AS IMPLICIT; +CREATE CAST (sys.bbf_varbinary AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(sys.bbf_varbinary) AS IMPLICIT; +CREATE CAST (sys.GEOMETRY AS sys.bbf_varbinary) WITH FUNCTION sys.bbf_varbinary(sys.GEOMETRY) AS IMPLICIT; -- Availability: 3.2.0 current supported in APG CREATE OR REPLACE FUNCTION sys.Geometry__Point(float8, float8, srid integer) @@ -142,17 +215,39 @@ CREATE OR REPLACE FUNCTION sys.Geometry__STPointFromText(text, integer) AS $$ DECLARE srid integer; + Geomtype text; + geom sys.GEOMETRY; BEGIN srid := $2; IF srid >= 0 AND srid <= 999999 THEN -- Call the underlying function after preprocessing - RETURN (SELECT sys.stgeomfromtext_helper($1, $2)); + geom = (SELECT sys.stgeomfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN geom; + END IF; + ELSE + RAISE EXCEPTION '% is not supported', Geomtype; + END IF; ELSE RAISE EXCEPTION 'SRID value should be between 0 and 999999'; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.ST_GeometryType(sys.GEOMETRY) + RETURNS text + AS '$libdir/postgis-3', 'geometry_geometrytype' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.ST_zmflag(sys.GEOMETRY) + RETURNS smallint + AS '$libdir/postgis-3', 'LWGEOM_zmflag' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + -- Minimum distance. 2D only. CREATE OR REPLACE FUNCTION sys.STDistance(geom1 sys.GEOMETRY, geom2 sys.GEOMETRY) RETURNS float8 @@ -180,3 +275,8 @@ CREATE OR REPLACE FUNCTION sys.GeomPoint_helper(float8, float8, srid integer) AS '$libdir/postgis-3', 'ST_Point' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOMETRY_helper(bytea) + RETURNS sys.GEOMETRY + AS '$libdir/postgis-3','LWGEOM_from_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + diff --git a/contrib/babelfishpg_common/sql/upgrades/spatial_types--3.2.0--3.3.0.sql b/contrib/babelfishpg_common/sql/upgrades/spatial_types--3.2.0--3.3.0.sql index 0e5755a0ad..d50f098ab9 100644 --- a/contrib/babelfishpg_common/sql/upgrades/spatial_types--3.2.0--3.3.0.sql +++ b/contrib/babelfishpg_common/sql/upgrades/spatial_types--3.2.0--3.3.0.sql @@ -77,11 +77,23 @@ CREATE OR REPLACE FUNCTION sys.Geometry__stgeomfromtext(text, integer) AS $$ DECLARE srid integer; + Geomtype text; + geom sys.GEOMETRY; BEGIN srid := $2; IF srid >= 0 AND srid <= 999999 THEN -- Call the underlying function after preprocessing - RETURN (SELECT sys.stgeomfromtext_helper($1, $2)); + geom = (SELECT sys.stgeomfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN geom; + END IF; + ELSE + RAISE EXCEPTION '% is not supported', Geomtype; + END IF; ELSE RAISE EXCEPTION 'SRID value should be between 0 and 999999'; END IF; @@ -100,15 +112,74 @@ CREATE OR REPLACE FUNCTION sys.text(sys.GEOMETRY) LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.GEOMETRY(bytea) - RETURNS sys.GEOMETRY - AS '$libdir/postgis-3','LWGEOM_from_bytea' - LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + RETURNS sys.GEOMETRY + AS $$ + DECLARE + len integer; + varBin bytea; + geomType bytea; + srid integer; + byte_position integer := 6; + coord_NaN bytea := E'\\x000000000000f87f'; + input_coord bytea; + isNaN integer = 0; + newVarBin bytea; + BEGIN + varBin := $1; + len := LENGTH(varBin); + IF len >= 22 THEN + -- We are preprocessing it by removing 2 constant Geometry Type bytes -> 01 0c (for 2-D Point Type) + -- Then adding 5 Bytes -> 01 (little endianess) + 4 Bytes (Geometry Type) + srid := (get_byte(varBin, 3) << 24) | (get_byte(varBin, 2) << 16) | (get_byte(varBin, 1) << 8) | get_byte(varBin, 0); + WHILE byte_position < len LOOP + -- Get the coordinate to check if it is NaN + input_coord := substring(varBin from byte_position + 1 for 8); + IF encode(input_coord, 'hex') = encode(coord_NaN, 'hex') THEN + isNaN := 1; + END IF; + byte_position := byte_position + 8; + END LOOP; + geomType := substring(varBin from 5 for 2); + varBin := substring(varBin from 1 for 4) || substring(varBin from 7); + IF srid >= 0 AND srid <= 999999 AND isNaN = 0 THEN + IF encode(geomType, 'hex') = encode(E'\\x010c', 'hex') THEN + newVarBin := E'\\x0101000020' || varBin; + ELSE + RAISE EXCEPTION 'Unsupported geometry type'; + END IF; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geometry.'; + END IF; + -- Call the underlying function after preprocessing + RETURN (SELECT sys.GEOMETRY_helper(newVarBin)); + ELSE + RAISE EXCEPTION 'Invalid Geometry'; + END IF; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.bytea(sys.GEOMETRY) RETURNS bytea AS '$libdir/postgis-3','LWGEOM_to_bytea' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOMETRY(sys.bbf_varbinary) + RETURNS sys.GEOMETRY + AS $$ + DECLARE + varBin bytea; + BEGIN + varBin := (SELECT CAST ($1 AS bytea)); + -- Call the underlying function after preprocessing + RETURN (SELECT CAST (varBin AS GEOMETRY)); + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.bbf_varbinary(sys.GEOMETRY) + RETURNS sys.bbf_varbinary + AS '$libdir/postgis-3','LWGEOM_to_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + CREATE OR REPLACE FUNCTION sys.GEOMETRY(text) RETURNS sys.GEOMETRY AS '$libdir/postgis-3','parse_WKT_lwgeom' @@ -118,6 +189,8 @@ CREATE CAST (text AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(text) AS IMPLICIT; CREATE CAST (sys.GEOMETRY AS text) WITH FUNCTION sys.text(sys.GEOMETRY) AS IMPLICIT; CREATE CAST (bytea AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(bytea) AS IMPLICIT; CREATE CAST (sys.GEOMETRY AS bytea) WITH FUNCTION sys.bytea(sys.GEOMETRY) AS IMPLICIT; +CREATE CAST (sys.bbf_varbinary AS sys.GEOMETRY) WITH FUNCTION sys.GEOMETRY(sys.bbf_varbinary) AS IMPLICIT; +CREATE CAST (sys.GEOMETRY AS sys.bbf_varbinary) WITH FUNCTION sys.bbf_varbinary(sys.GEOMETRY) AS IMPLICIT; -- Availability: 3.2.0 current supported in APG CREATE OR REPLACE FUNCTION sys.Geometry__Point(float8, float8, srid integer) @@ -146,17 +219,39 @@ CREATE OR REPLACE FUNCTION sys.Geometry__STPointFromText(text, integer) AS $$ DECLARE srid integer; + Geomtype text; + geom sys.GEOMETRY; BEGIN srid := $2; IF srid >= 0 AND srid <= 999999 THEN -- Call the underlying function after preprocessing - RETURN (SELECT sys.stgeomfromtext_helper($1, $2)); + geom = (SELECT sys.stgeomfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN geom; + END IF; + ELSE + RAISE EXCEPTION '% is not supported', Geomtype; + END IF; ELSE RAISE EXCEPTION 'SRID value should be between 0 and 999999'; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.ST_GeometryType(sys.GEOMETRY) + RETURNS text + AS '$libdir/postgis-3', 'geometry_geometrytype' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.ST_zmflag(sys.GEOMETRY) + RETURNS smallint + AS '$libdir/postgis-3', 'LWGEOM_zmflag' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + -- Minimum distance. 2D only. CREATE OR REPLACE FUNCTION sys.STDistance(geom1 sys.GEOMETRY, geom2 sys.GEOMETRY) RETURNS float8 @@ -183,7 +278,12 @@ CREATE OR REPLACE FUNCTION sys.GeomPoint_helper(float8, float8, srid integer) RETURNS sys.GEOMETRY AS '$libdir/postgis-3', 'ST_Point' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; - + +CREATE OR REPLACE FUNCTION sys.GEOMETRY_helper(bytea) + RETURNS sys.GEOMETRY + AS '$libdir/postgis-3','LWGEOM_from_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + CREATE OR REPLACE FUNCTION sys.geographyin(cstring, oid, integer) RETURNS sys.GEOGRAPHY AS '$libdir/postgis-3','geography_in' @@ -241,18 +341,127 @@ CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.GEOGRAPHY, integer, boolean) CREATE CAST (sys.GEOGRAPHY AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(sys.GEOGRAPHY, integer, boolean) AS IMPLICIT; +CREATE OR REPLACE FUNCTION sys.get_valid_srids() + RETURNS integer[] + AS $$ + DECLARE + valid_srids integer[] := ARRAY[ + 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, + 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, + 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, + 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, + 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, + 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, + 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, + 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, + 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, + 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, + 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, + 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, + 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, + 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, + 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, + 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, + 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, + 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, + 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, + 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, + 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 + ]; + BEGIN + RETURN valid_srids; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(bytea) RETURNS sys.GEOGRAPHY - AS '$libdir/postgis-3','geography_from_binary' - LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + AS $$ + DECLARE + len integer; + varBin bytea; + geomType bytea; + srid integer; + newVarBin bytea; + lat float8; + byte_position integer := 6; + coord_NaN bytea := E'\\x000000000000f87f'; + input_coord bytea; + reversed_bytea bytea := E'\\x'; + i integer := 14; + isNaN integer = 0; + valid_srids integer[]; + BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; + varBin := $1; + len := LENGTH(varBin); + IF len >= 22 THEN + -- General Logic: We are preprocessing it by removing 2 constant Geometry Type bytes -> 01 0c (for 2-D Point Type) Then adding 5 Bytes -> 01 (little endianess) + 4 Bytes (Geography Type). It is expected by the driver + -- Here we are calculating SRID which is initially in little endian order + srid := (get_byte(varBin, 3) << 24) | (get_byte(varBin, 2) << 16) | (get_byte(varBin, 1) << 8) | get_byte(varBin, 0); + -- Here we are calculating value of latitude which is initially in little endian order to check if it lies in the range [-90, 90] + WHILE i > 6 LOOP + reversed_bytea := reversed_bytea || substring(varBin from i for 1); + i = i - 1; + END LOOP; + lat := varbinaryfloat8(CAST (reversed_bytea AS bbf_varbinary)); + WHILE byte_position < len LOOP + -- Get the coordinate to check if it is NaN + input_coord := substring(varBin from byte_position + 1 for 8); + IF encode(input_coord, 'hex') = encode(coord_NaN, 'hex') THEN + isNaN := 1; + END IF; + byte_position := byte_position + 8; + END LOOP; + geomType := substring(varBin from 5 for 2); + varBin := substring(varBin from 1 for 4) || substring(varBin from 7); + IF srid = ANY(valid_srids) AND isNaN = 0 THEN + IF encode(geomType, 'hex') = encode(E'\\x010c', 'hex') THEN + IF lat >= -90.0 AND lat <= 90.0 THEN + newVarBin := E'\\x0101000020' || varBin; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geography.'; + END IF; + ELSE + RAISE EXCEPTION 'Unsupported geometry type'; + END IF; + ELSE + RAISE EXCEPTION 'Error converting data type varbinary to geography.'; + END IF; + -- Call the underlying function after preprocessing + RETURN (SELECT sys.GEOGRAPHY_helper(newVarBin)); + ELSE + RAISE EXCEPTION 'Invalid Geography'; + END IF; + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.bytea(sys.GEOGRAPHY) RETURNS bytea AS '$libdir/postgis-3','LWGEOM_to_bytea' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.bbf_varbinary) + RETURNS sys.GEOGRAPHY + AS $$ + DECLARE + varBin bytea; + BEGIN + varBin := (SELECT CAST ($1 AS bytea)); + -- Call the underlying function after preprocessing + RETURN (SELECT CAST (varBin AS GEOGRAPHY)); + END; + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.bbf_varbinary(sys.GEOGRAPHY) + RETURNS sys.bbf_varbinary + AS '$libdir/postgis-3','LWGEOM_to_bytea' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + CREATE CAST (bytea AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(bytea) AS IMPLICIT; CREATE CAST (sys.GEOGRAPHY AS bytea) WITH FUNCTION sys.bytea(sys.GEOGRAPHY) AS IMPLICIT; +CREATE CAST (sys.bbf_varbinary AS sys.GEOGRAPHY) WITH FUNCTION sys.GEOGRAPHY(sys.bbf_varbinary) AS IMPLICIT; +CREATE CAST (sys.GEOGRAPHY AS sys.bbf_varbinary) WITH FUNCTION sys.bbf_varbinary(sys.GEOGRAPHY) AS IMPLICIT; CREATE OR REPLACE FUNCTION sys.GEOGRAPHY(sys.GEOMETRY) RETURNS sys.GEOGRAPHY @@ -279,42 +488,34 @@ CREATE OR REPLACE FUNCTION sys.Geography__stgeomfromtext(text, integer) AS $$ DECLARE srid integer; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + Geomtype text; + geom sys.GEOGRAPHY; + valid_srids integer[]; lat float8; - BEGIN + BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $2; - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); - IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN - -- Call the underlying function after preprocessing - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - RETURN (SELECT sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2))); - ELSEIF lat < -90.0 OR lat > 90.0 THEN - RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + geom = (SELECT sys.stgeogfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); + IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN + -- Call the underlying function after preprocessing + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN (SELECT sys.Geography__STFlipCoordinates(geom)); + END IF; + ELSEIF lat < -90.0 OR lat > 90.0 THEN + RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + ELSE + RAISE EXCEPTION 'Inavalid SRID'; + END IF; ELSE - RAISE EXCEPTION 'Inavalid SRID'; + RAISE EXCEPTION '% is not supported', Geomtype; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -324,7 +525,7 @@ CREATE OR REPLACE FUNCTION sys.STAsText(sys.GEOGRAPHY) AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STAsText_helper(sys.Geography__STFlipCoordinates($1))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -340,30 +541,10 @@ CREATE OR REPLACE FUNCTION sys.Geography__Point(float8, float8, srid integer) DECLARE srid integer; lat float8; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + valid_srids integer[]; BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $3; lat := $1; IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN @@ -382,7 +563,7 @@ CREATE OR REPLACE FUNCTION sys.STAsBinary(sys.GEOGRAPHY) AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STAsBinary_helper(sys.Geography__STFlipCoordinates($1))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -392,53 +573,55 @@ CREATE OR REPLACE FUNCTION sys.Geography__STPointFromText(text, integer) AS $$ DECLARE srid integer; - valid_srids integer[] := ARRAY[ - 4120, 4121, 4122, 4123, 4124, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4141, - 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, - 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4173, 4174, 4175, 4176, 4178, 4179, 4180, 4181, - 4182, 4183, 4184, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4218, 4219, 4220, 4221, 4222, 4223, - 4224, 4225, 4227, 4229, 4230, 4231, 4232, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, - 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4261, 4262, 4263, 4265, 4266, 4267, 4268, - 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4288, - 4289, 4292, 4293, 4295, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4322, 4324, 4326, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, 4632, 4633, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4646, 4657, 4658, 4659, 4660, - 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4682, 4683, 4684, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, - 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4813, 4814, 4815, 4816, 4817, 4818, 4820, 4821, - 4895, 4898, 4900, 4901, 4902, 4903, 4904, 4907, 4909, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 4947, 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, 4971, 4973, 4975, 4977, 4979, - 4981, 4983, 4985, 4987, 4989, 4991, 4993, 4995, 4997, 4999, 7843, 7844, 104001 - ]; + Geomtype text; + geom sys.GEOGRAPHY; + valid_srids integer[]; lat float8; BEGIN + -- Call the function to retrieve the valid SRIDs + SELECT sys.get_valid_srids() INTO valid_srids; srid := $2; - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); - IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN - -- Call the underlying function after preprocessing - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) - RETURN (SELECT sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2))); - ELSEIF lat < -90.0 OR lat > 90.0 THEN - RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + geom = (SELECT sys.stgeogfromtext_helper($1, $2)); + Geomtype = (SELECT sys.ST_GeometryType(geom)); + IF Geomtype = 'ST_Point' THEN + lat = (SELECT sys.lat(sys.Geography__STFlipCoordinates(sys.stgeogfromtext_helper($1, $2)))); + IF srid = ANY(valid_srids) AND lat >= -90.0 AND lat <= 90.0 THEN + -- Call the underlying function after preprocessing + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + IF (SELECT sys.ST_Zmflag(geom)) = 1 OR (SELECT sys.ST_Zmflag(geom)) = 2 OR (SELECT sys.ST_Zmflag(geom)) = 3 THEN + RAISE EXCEPTION 'Unsupported flags'; + ELSE + RETURN (SELECT sys.Geography__STFlipCoordinates(geom)); + END IF; + ELSEIF lat < -90.0 OR lat > 90.0 THEN + RAISE EXCEPTION 'Latitude values must be between -90 and 90 degrees'; + ELSE + RAISE EXCEPTION 'Inavalid SRID'; + END IF; ELSE - RAISE EXCEPTION 'Inavalid SRID'; + RAISE EXCEPTION '% is not supported', Geomtype; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.ST_GeometryType(sys.GEOGRAPHY) + RETURNS text + AS '$libdir/postgis-3', 'geometry_geometrytype' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OR REPLACE FUNCTION sys.ST_zmflag(sys.GEOGRAPHY) + RETURNS smallint + AS '$libdir/postgis-3', 'LWGEOM_zmflag' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; + -- Minimum distance CREATE OR REPLACE FUNCTION sys.STDistance(geog1 sys.GEOGRAPHY, geog2 sys.GEOGRAPHY) RETURNS float8 AS $$ BEGIN -- Call the underlying function after preprocessing - -- Here we flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) + -- Here we are flipping the coordinates since Geography Datatype stores the point from STGeomFromText and STPointFromText in Reverse Order i.e. (long, lat) RETURN (SELECT sys.STDistance_helper(sys.Geography__STFlipCoordinates($1), sys.Geography__STFlipCoordinates($2))); END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; @@ -484,3 +667,7 @@ CREATE OR REPLACE FUNCTION sys.STDistance_helper(geog1 sys.GEOGRAPHY, geog2 sys. AS '$libdir/postgis-3', 'LWGEOM_distance_ellipsoid' LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; +CREATE OR REPLACE FUNCTION sys.GEOGRAPHY_helper(bytea) + RETURNS sys.GEOGRAPHY + AS '$libdir/postgis-3','geography_from_binary' + LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE; diff --git a/contrib/babelfishpg_tds/src/backend/tds/tds_data_map.c b/contrib/babelfishpg_tds/src/backend/tds/tds_data_map.c index 07698a0992..d5d9891345 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tds_data_map.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tds_data_map.c @@ -182,8 +182,8 @@ TdsIoFunctionRawData TdsIoFunctionRawData_data[] = {"sys", "fixeddecimal", TDS_TYPE_MONEYN, 8, 1, TDS_SEND_MONEY, TDS_RECV_INVALID}, {"sys", "rowversion", TDS_TYPE_BINARY, 8, 2, TDS_SEND_BINARY, TDS_RECV_BINARY}, {"sys", "timestamp", TDS_TYPE_BINARY, 8, 2, TDS_SEND_BINARY, TDS_RECV_BINARY}, - {"sys", "geometry", TDS_TYPE_SPATIAL, -1, 2, TDS_SEND_GEOMETRY, TDS_RECV_GEOMETRY}, - {"sys", "geography", TDS_TYPE_SPATIAL, -1, 2, TDS_SEND_GEOGRAPHY, TDS_RECV_GEOGRAPHY}, + {"sys", "geometry", TDS_TYPE_GEOMETRY, -1, 2, TDS_SEND_GEOMETRY, TDS_RECV_GEOMETRY}, + {"sys", "geography", TDS_TYPE_GEOGRAPHY, -1, 2, TDS_SEND_GEOGRAPHY, TDS_RECV_GEOGRAPHY}, /* Mapping TDS listener sender to basic Postgres datatypes. */ {"pg_catalog", "oid", TDS_TYPE_INTEGER, 4, 1, TDS_SEND_INTEGER, TDS_RECV_INVALID}, diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c index 24e4be415d..6baaaeb264 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c @@ -1923,10 +1923,10 @@ PrepareRowDescription(TupleDesc typeinfo, List *targetlist, int16 *formats, } break; case TDS_SEND_GEOMETRY: - SetColMetadataForGeometryType(col, TDS_TYPE_SPATIAL, TDS_MAXLEN_POINT, "", "geometry"); + SetColMetadataForGeometryType(col, TDS_TYPE_CLRUDT, TDS_MAXLEN_POINT, "", "geometry"); break; case TDS_SEND_GEOGRAPHY: - SetColMetadataForGeographyType(col, TDS_TYPE_SPATIAL, TDS_MAXLEN_POINT, "", "geography"); + SetColMetadataForGeographyType(col, TDS_TYPE_CLRUDT, TDS_MAXLEN_POINT, "", "geography"); break; default: diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index 123714d08f..64aeab3797 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -1787,6 +1787,53 @@ ReadParameters(TDSRequestSP request, uint64_t offset, StringInfo message, int *p CheckPLPStatusNotOK(temp, retStatus); } break; + case TDS_TYPE_CLRUDT: + { + uint16_t len; + uint8_t typenamelen; + StringInfoData typeName; + + initStringInfo(&typeName); + + memcpy(&len, &message->data[offset], sizeof(len)); + offset += sizeof(len); + + temp->maxLen = len; + + /* Read the type name for the given CLR-UDT */ + memcpy(&typenamelen, &message->data[offset], sizeof(typenamelen)); + offset += sizeof(typenamelen); + + TdsUTF16toUTF8StringInfo(&typeName, &(message->data[offset]), 2*typenamelen); + offset += 2*typenamelen; + + if (!(pg_strcasecmp(typeName.data, "geometry") == 0 || pg_strcasecmp(typeName.data, "geography") == 0)) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. " + "UdtTypeName is incorrect."))); + } + + /* Set column metadata for given CLR-UDT type depending upon the underlying typename. */ + if (pg_strcasecmp(typeName.data, "geometry") == 0) + { + SetColMetadataForGeometryType(&temp->paramMeta, tdsType, TDS_MAXLEN_POINT, "", "geometry"); + temp->type = TDS_TYPE_GEOMETRY; + tdsType = TDS_TYPE_GEOMETRY; + } + else + { + SetColMetadataForGeographyType(&temp->paramMeta, tdsType, TDS_MAXLEN_POINT, "", "geography"); + temp->type = TDS_TYPE_GEOGRAPHY; + tdsType = TDS_TYPE_GEOGRAPHY; + } + + resetStringInfo(&typeName); + retStatus = ReadPlp(temp, message, &offset); + CheckPLPStatusNotOK(temp, retStatus); + } + break; default: ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdstypeio.c b/contrib/babelfishpg_tds/src/backend/tds/tdstypeio.c index 38191c77fa..1fd7a98e32 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdstypeio.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdstypeio.c @@ -51,6 +51,8 @@ #define TDS_RETURN_DATUM(x) return ((Datum) (x)) #define VARCHAR_MAX 2147483647 +/* TODO: need to add for other geometry types when introduced */ +#define POINTTYPE 1 #define GetPgOid(pgTypeOid, finfo) \ do { \ @@ -128,6 +130,7 @@ Datum TdsTypeSmallMoneyToDatum(StringInfo buf); Datum TdsTypeXMLToDatum(StringInfo buf); Datum TdsTypeUIDToDatum(StringInfo buf); Datum TdsTypeSqlVariantToDatum(StringInfo buf); +Datum TdsTypeSpatialToDatum(StringInfo buf); static void FetchTvpTypeOid(const ParameterToken token, char *tvpName); @@ -1448,6 +1451,59 @@ TdsTypeUIDToDatum(StringInfo buf) PG_RETURN_POINTER(uuid); } +/* Helper Function to convert Spatial Type values into Datum. */ +Datum +TdsTypeSpatialToDatum(StringInfo buf) +{ + bytea *result; + int32 geomType = 0; + int nbytes, + npoints; + StringInfo destBuf = makeStringInfo(); + + /* + * Here the incoming buf format is -> 4 Byte SRID + 2 Byte Geometry Type + (16 Bytes)*npoints + * But Driver expects -> 4 Byte SRID + 4 Byte Type + 4 Byte npoints + (16 Bytes)*npoints + */ + /* We are copying first 4 Byte SRID from buf */ + appendBinaryStringInfo(destBuf, buf->data + buf->cursor, 4); + + npoints = (buf->len - buf->cursor - 6)/16; + nbytes = buf->len - buf->cursor + 6; + result = (bytea *) palloc0(nbytes + VARHDRSZ); + SET_VARSIZE(result, nbytes + VARHDRSZ); + + /* Here we are handling the 8 bytes (4 Byte Type + 4 Byte npoints) which driver expects for 2-D point */ + if (buf->data[buf->cursor + 4] == 1 && buf->data[buf->cursor + 5] == 12) + { + geomType = (int32) POINTTYPE; + + enlargeStringInfo(destBuf, sizeof(uint32_t)); + memcpy(destBuf->data + destBuf->len, (char *) &geomType, sizeof(uint32_t)); + destBuf->len += sizeof(uint32_t); + destBuf->data[destBuf->len] = '\0'; + + enlargeStringInfo(destBuf, sizeof(uint32_t)); + memcpy(destBuf->data + destBuf->len, (char *) &npoints, sizeof(uint32_t)); + destBuf->len += sizeof(uint32_t); + destBuf->data[destBuf->len] = '\0'; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Unsupported geometry type"))); + } + + /* We are copying the remaining bytes (16 Bytes)*npoints from buf */ + appendBinaryStringInfo(destBuf, buf->data + buf->cursor + 6, buf->len - 6); + + memcpy(VARDATA(result), &destBuf->data[0], nbytes); + buf->cursor += nbytes - 6; + + PG_RETURN_BYTEA_P(result); +} + StringInfo TdsGetPlpStringInfoBufferFromToken(const char *message, const ParameterToken token) { @@ -2007,24 +2063,15 @@ TdsRecvTypeDatetime2(const char *message, const ParameterToken token) * Geometry data type * -------------------------------- */ -/* - * It is a Placeholder Function for now - * TODO: Will need to address it in subsequent Code Changes -*/ Datum TdsRecvTypeGeometry(const char *message, const ParameterToken token) { - Datum result = 0; - - /* Decode binary and convert if needed */ - StringInfo buf = TdsGetStringInfoBufferFromToken(message, token); - - /* Return in Datum val */ + Datum result; + StringInfo buf = TdsGetPlpStringInfoBufferFromToken(message, token); - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("Prepared Queries for Geometry DataType Currently not Supported in BabelFish"))); + result = TdsTypeSpatialToDatum(buf); + pfree(buf->data); pfree(buf); return result; } @@ -2033,25 +2080,16 @@ TdsRecvTypeGeometry(const char *message, const ParameterToken token) * TdsRecvTypeGeography - converts external binary format to * Geography data type * -------------------------------- - */ -/* - * It is a Placeholder Function for now - * TODO: Will need to address it in subsequent Code Changes -*/ + */ Datum TdsRecvTypeGeography(const char *message, const ParameterToken token) { - Datum result = 0; - - /* Decode binary and convert if needed */ - StringInfo buf = TdsGetStringInfoBufferFromToken(message, token); - - /* Return in Datum val */ + Datum result; + StringInfo buf = TdsGetPlpStringInfoBufferFromToken(message, token); - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("Prepared Queries for Geography DataType Currently not Supported in BabelFish"))); + result = TdsTypeSpatialToDatum(buf); + pfree(buf->data); pfree(buf); return result; } @@ -2426,8 +2464,9 @@ TdsRecvTypeTable(const char *message, const ParameterToken token) case TDS_TYPE_SQLVARIANT: values[i] = TdsTypeSqlVariantToDatum(temp); break; - case TDS_TYPE_SPATIAL: - break; + case TDS_TYPE_CLRUDT: + values[i] = TdsTypeSpatialToDatum(temp); + break; } /* Build a string for bind parameters. */ if (colMetaData[currentColumn].columnTdsType != TDS_TYPE_NVARCHAR || row->isNull[currentColumn] == 'n') @@ -4187,7 +4226,7 @@ TdsSendSpatialHelper(FmgrInfo *finfo, Datum value, void *vMetaData, int TdsInstr * Row chunck length expected by the driver is: * 16 * (No. of Points) + 6 * 16 -> 2 8-Byte float coordinates (TODO: Need to change when Z and M flags are defined for N-dimension Points) - * 6 -> 4 Byte SRID + 2 Byte (01 0C) + * 6 -> 4 Byte SRID + 2 Byte Geometry Type (01 0C -> for Point Type) */ len = npoints*16 + 6; buf = (char *) palloc0(len); @@ -4198,12 +4237,19 @@ TdsSendSpatialHelper(FmgrInfo *finfo, Datum value, void *vMetaData, int TdsInstr *((int32_t*)buf) = srid; itr = buf + 4; - /* Driver Expects 01 0C as 2 constant Bytes */ - /* TODO: Will need to verify for Different Geometry Data Types */ - *itr = 1; - itr++; - *itr = 12; - itr++; + /* Driver Expects 01 0C for 2-D Point Type as 2 constant Bytes to identify the Geometry Type */ + /* TODO: Will need to introduce for Different Geometry Data Types */ + switch (*((uint32_t*)gser->data)) + { + case POINTTYPE: + *itr = 1; + itr++; + *itr = 12; + itr++; + break; + default: + elog(ERROR, "Unsupported geometry type"); + } /* Data part of the Row has length 16 * (No. of Points) */ /* diff --git a/contrib/babelfishpg_tds/src/include/tds_iofuncmap.h b/contrib/babelfishpg_tds/src/include/tds_iofuncmap.h index 0bb5305a3e..5726cddc60 100644 --- a/contrib/babelfishpg_tds/src/include/tds_iofuncmap.h +++ b/contrib/babelfishpg_tds/src/include/tds_iofuncmap.h @@ -117,7 +117,9 @@ #define TDS_TYPE_SQLVARIANT 98 /* 0x62 */ #define TDS_TYPE_DATETIMEOFFSET 43 /* 0x2B */ #define TDS_TYPE_SMALLDATETIME 58 /* 0x3A */ -#define TDS_TYPE_SPATIAL 240 /* 0xF0 */ +#define TDS_TYPE_CLRUDT 240 /* 0xF0 */ +#define TDS_TYPE_GEOMETRY 254 /* 0xFE */ +#define TDS_TYPE_GEOGRAPHY 255 /* 0xFF */ /* * macros for supporting sqlvariant datatype on TDS side diff --git a/contrib/babelfishpg_tds/src/include/tds_request.h b/contrib/babelfishpg_tds/src/include/tds_request.h index 3b508e05bc..e76a18034d 100644 --- a/contrib/babelfishpg_tds/src/include/tds_request.h +++ b/contrib/babelfishpg_tds/src/include/tds_request.h @@ -333,7 +333,7 @@ SetTvpRowData(ParameterToken temp, const StringInfo message, uint64_t *offset) *offset += rowData->columnValues[i].len; } break; - case TDS_TYPE_SPATIAL: + case TDS_TYPE_CLRUDT: { retStatus = ReadPlp(temp, message, offset); CheckPLPStatusNotOKForTVP(temp, retStatus); @@ -651,7 +651,7 @@ SetColMetadataForTvp(ParameterToken temp, const StringInfo message, uint64_t *of memcpy(&colmetadata[i].maxLen, &messageData[*offset], sizeof(uint32_t)); *offset += sizeof(uint32_t); break; - case TDS_TYPE_SPATIAL: + case TDS_TYPE_CLRUDT: colmetadata[i].maxLen = messageData[(*offset)++]; break; default: diff --git a/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out b/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out index d2f24215ac..5ad69e2c46 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out @@ -1,41 +1,27 @@ DROP VIEW IF EXISTS TextFromGeom -GO DROP VIEW IF EXISTS BinaryFromGeom -GO DROP VIEW IF EXISTS CoordsFromGeom -GO DROP VIEW IF EXISTS point_distances_geom -GO DROP VIEW IF EXISTS TextFromGeog -GO DROP VIEW IF EXISTS BinaryFromGeog -GO DROP VIEW IF EXISTS CoordsFromGeog -GO DROP VIEW IF EXISTS TransformFromGeog -GO DROP VIEW IF EXISTS point_distances_geog -GO DROP TABLE IF EXISTS SPATIALPOINTGEOM_dt -GO DROP TABLE IF EXISTS TypeTable -GO DROP TYPE IF EXISTS geom -GO DROP TABLE IF EXISTS SPATIALPOINTGEOG_dt -GO DROP TABLE IF EXISTS SPATIALPOINT_dt -GO diff --git a/test/JDBC/expected/TestSpatialPoint-vu-prepare.out b/test/JDBC/expected/TestSpatialPoint-vu-prepare.out index bc11ee4221..d3c1cda6a0 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-prepare.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-prepare.out @@ -1,334 +1,378 @@ CREATE TABLE SPATIALPOINTGEOM_dt (location geometry) -GO +#Geometry Test Cases --- Geometry Test Cases --- Positive Test for STGeomFromText with SRID 4326 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Positive Test for STGeomFromText with SRID 4326 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO + +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326) ) ~~ROW COUNT: 1~~ --- Positive Test for STGeomFromText with SRID 0 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 0) ) -GO +#Positive Test for STGeomFromText with SRID 0 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 0) ) ~~ROW COUNT: 1~~ --- Negative Test for STGeomFromText when SRID is not provided -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)') ) -GO +#Negative Test for STGeomFromText when SRID is not provided +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)') ) ~~ERROR (Code: 8146)~~ ~~ERROR (Message: function geometry__stgeomfromtext has no parameters and arguments were supplied.)~~ --- Negative Test for STGeomFromText when SRID >= 10^6 --- SRID should be between 0 to 999999 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) -GO +#Negative Test for STGeomFromText when SRID >= 10^6 +#SRID should be between 0 to 999999 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: SRID value should be between 0 and 999999)~~ --- Negative Test for STGeomFromText with SRID < 0 --- SRID should be between 0 to 999999 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', -1) ) -GO +#Negative Test for STGeomFromText with SRID < 0 +#SRID should be between 0 to 999999 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', -1) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: SRID value should be between 0 and 999999)~~ --- Negative Test for STGeomFromText when a coordinate is missing -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(1.0 )', 4326) ) -GO +#Negative Test for STGeomFromText when a coordinate is missing +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(1.0 )', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: parse error - invalid geometry)~~ --- Negative Test for STGeomFromText when invalid type is provided -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Pnt', 4326) ) -GO +#Negative Test for STGeomFromText when invalid type is provided +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Pnt', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: parse error - invalid geometry)~~ --- Test for STGeomFromText when null Point is Given -> Returns NBCRow -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText(null, 4326) ) -GO +#Test for STGeomFromText when null Point is Given -> Returns NBCRow +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText(null, 4326) ) ~~ROW COUNT: 1~~ +#Negative Test for STGeomFromText when Incorrect cast is provided +#INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- -- Negative Test for STGeomFromText when Incorrect cast is provided --- INSERT INTO SPATIALPOINTGEOM_dt (location) --- VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- GO --- Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STPointFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STPointFromText('Point(47.65100 -22.34900)', 4326) ) ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STPointFromText('Point(1.0 2.0)', 4326) ) -GO + +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STPointFromText('Point(1.0 2.0)', 4326) ) ~~ROW COUNT: 1~~ --- Positive Test for Point with SRID 4326 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::Point(47.65100, -22.34900, 4326) ) -GO + +#Positive Test for Point with SRID 4326 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::Point(47.65100, -22.34900, 4326) ) ~~ROW COUNT: 1~~ -CREATE VIEW TextFromGeom AS -SELECT STAsText(location) AS TextRepresentation -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW BinaryFromGeom AS -SELECT STAsBinary(location) AS BinaryRepresentation -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW CoordsFromGeom AS -SELECT STX(location), STY(location) AS Coordinates -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW point_distances_geom AS -SELECT - p1.location AS point1, - p2.location AS point2, - STDistance( p1.location, p2.location ) AS distance -FROM - SPATIALPOINTGEOM_dt p1 -CROSS JOIN - SPATIALPOINTGEOM_dt p2 -WHERE - p1.location <> p2.location; -GO +#Tests for Geometry type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINTGEOM_dt(location) values(?) #!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):4326 +~~ROW COUNT: 1~~ + +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0):4326 +~~ROW COUNT: 1~~ + +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):0 +~~ROW COUNT: 1~~ + +#Negative Test for STGeomFromText when SRID >= 10^6 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):1000000000 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geometry.)~~ + +#Negative Test for STGeomFromText with SRID < 0 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):-1 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geometry.)~~ + +#Negative Test for STGeomFromText when SRID is NULL +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900): +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geometry.)~~ + +#Negative Test for STGeomFromText when a coordinate is missing +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 ):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geometry.)~~ + +#Negative Test when an unsupported feature in queried +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +prepst#!#exec#!#GEOMETRY|-|location|-|LINESTRING(1 2, 3 4):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +#Negative Test for STGeomFromText when invalid type is provided +prepst#!#exec#!#GEOMETRY|-|location|-|Pnt:4326 +~~ERROR (Code: 0)~~ + +~~ERROR (Message: Illegal character in Well-Known text at position 3.)~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +#Negative Test for STGeomFromText when Null geometry is provided +prepst#!#exec#!#GEOMETRY|-|location|-|:4326 +~~ERROR (Code: 0)~~ + +~~ERROR (Message: Illegal character in Well-Known text at position 0.)~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + + +CREATE VIEW TextFromGeom AS SELECT STAsText(location) AS TextRepresentation FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW BinaryFromGeom AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW CoordsFromGeom AS SELECT STX(location), STY(location) AS Coordinates FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW point_distances_geom AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location <> p2.location; CREATE TABLE SPATIALPOINTGEOG_dt (location geography) -GO --- Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything --- TODO: Make it similar to T-SQL -CREATE TYPE geom -FROM geometry NOT NULL ; -GO +#Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything +#TODO: Make it similar to T-SQL +CREATE TYPE geom FROM geometry NOT NULL ; CREATE TABLE TypeTable(ID INT PRIMARY KEY, Shape geom) -GO -INSERT INTO TypeTable(ID, Shape) -VALUES(1, geometry::Point(1, 2, 4326)); -GO +INSERT INTO TypeTable(ID, Shape) VALUES(1, geometry::Point(1, 2, 4326)); ~~ROW COUNT: 1~~ +#Geography Test Cases --- Geography Test Cases --- Positive Test for STGeomFromText with SRID 4326 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Positive Test for STGeomFromText with SRID 4326 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO + +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(1.0 2.0)', 4326) ) ~~ROW COUNT: 1~~ --- Negative Test for STGeomFromText for Geography with SRID 0 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 0) ) -GO +#Negative Test for STGeomFromText for Geography with SRID 0 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 0) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Inavalid SRID)~~ --- Negative Test for STGeomFromText for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -122.34900)', 4326) ) -GO +#Negative Test for STGeomFromText for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -122.34900)', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Latitude values must be between -90 and 90 degrees)~~ --- Negative Test for STGeomFromText when SRID is not provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)') ) -GO +#Negative Test for STGeomFromText when SRID is not provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)') ) ~~ERROR (Code: 8146)~~ ~~ERROR (Message: function geography__stgeomfromtext has no parameters and arguments were supplied.)~~ --- Negative Test for STGeomFromText when cast is not provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Negative Test for STGeomFromText when cast is not provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( STGeomFromText('Point(47.65100 -22.34900)', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: function stgeomfromtext(unknown, integer) does not exist)~~ +#Negative Test for STGeomFromText when incorrect cast is provided +#INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- -- Negative Test for STGeomFromText when incorrect cast is provided --- INSERT INTO SPATIALPOINTGEOG_dt (location) --- VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- GO --- Negative Test for STGeomFromText when SRID >= 10^6 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) -GO +#Negative Test for STGeomFromText when SRID >= 10^6 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Inavalid SRID)~~ --- Negative Test for STGeomFromText with SRID < 0 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', -1) ) -GO +#Negative Test for STGeomFromText with SRID < 0 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', -1) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Inavalid SRID)~~ --- Negative Test for STGeomFromText when a coordinate is missing -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(1.0 )', 4326) ) -GO +#Negative Test for STGeomFromText when a coordinate is missing +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(1.0 )', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: parse error - invalid geometry)~~ --- Negative Test for STGeomFromText when invalid type is provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Pnt', 4326) ) -GO +#Negative Test for STGeomFromText when invalid type is provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Pnt', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: parse error - invalid geometry)~~ --- Test for STGeomFromText when null Point is Given -> Returns NBCRow -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText(null, 4326) ) -GO +#Test for STGeomFromText when null Point is Given -> Returns NBCRow +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText(null, 4326) ) ~~ROW COUNT: 1~~ --- Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(47.65100 -22.34900)', 4326) ) ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(1.0 2.0)', 4326) ) -GO + +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(1.0 2.0)', 4326) ) ~~ROW COUNT: 1~~ --- Negative Test for STPointFromText for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(47.65100 122.34900)', 4326) ) -GO +#Negative Test for STPointFromText for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(47.65100 122.34900)', 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Latitude values must be between -90 and 90 degrees)~~ --- Positive Test for Point with SRID 4326 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::Point(47.65100, -22.34900, 4326) ) -GO +#Positive Test for Point with SRID 4326 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::Point(47.65100, -22.34900, 4326) ) ~~ROW COUNT: 1~~ --- Negative Test for Point for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::Point(147.65100, -22.34900, 4326) ) -GO +#Negative Test for Point for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::Point(147.65100, -22.34900, 4326) ) ~~ERROR (Code: 33557097)~~ ~~ERROR (Message: Latitude values must be between -90 and 90 degrees)~~ -CREATE VIEW TextFromGeog AS -SELECT STAsText(location) AS TextRepresentation -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW BinaryFromGeog AS -SELECT STAsBinary(location) AS BinaryRepresentation -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW CoordsFromGeog AS -SELECT long(location), lat(location) AS Coordinates -FROM SPATIALPOINTGEOG_dt; -GO - - -CREATE VIEW TransformFromGeog AS -SELECT ST_Transform(location, 4326) AS Modified_points -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW point_distances_geog AS -SELECT - p1.location AS point1, - p2.location AS point2, - STDistance( p1.location, p2.location ) AS distance -FROM - SPATIALPOINTGEOG_dt p1 -CROSS JOIN - SPATIALPOINTGEOG_dt p2 -WHERE - p1.location <> p2.location; -GO - -CREATE TABLE SPATIALPOINT_dt (GeomColumn geometry, GeogColumn geography) -GO -INSERT INTO SPATIALPOINT_dt (GeomColumn) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO +#Tests for Geography type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINTGEOG_dt(location) values(?) #!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):4326 +~~ROW COUNT: 1~~ + +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0):4326 +~~ROW COUNT: 1~~ + +#Negative Test for STGeomFromText for Geography with SRID 0 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):0 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test for STGeomFromText for Geography when lat > 90 or < -90 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -122.34900):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test for STGeomFromText when SRID >= 10^6 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):1000000000 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test for STGeomFromText with SRID < 0 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):-1 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test for STGeomFromText with SRID is NULL +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900): +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test for STGeomFromText when a coordinate is missing +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 ):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Error converting data type varbinary to geography.)~~ + +#Negative Test when an unsupported feature in queried +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +prepst#!#exec#!#GEOGRAPHY|-|location|-|LINESTRING(1 2, 3 4):4326 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +#Negative Test for STGeomFromText when invalid type is provided +prepst#!#exec#!#GEOGRAPHY|-|location|-|Pnt:4326 +~~ERROR (Code: 0)~~ + +~~ERROR (Message: Illegal character in Well-Known text at position 3.)~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + +#Negative Test for STGeomFromText when Null geography is provided +prepst#!#exec#!#GEOGRAPHY|-|location|-|:4326 +~~ERROR (Code: 0)~~ + +~~ERROR (Message: Illegal character in Well-Known text at position 0.)~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Unsupported geometry type)~~ + + +CREATE VIEW TextFromGeog AS SELECT STAsText(location) AS TextRepresentation FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW BinaryFromGeog AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW CoordsFromGeog AS SELECT long(location), lat(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; + + +CREATE VIEW TransformFromGeog AS SELECT ST_Transform(location, 4326) AS Modified_points FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW point_distances_geog AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOG_dt p1 CROSS JOIN SPATIALPOINTGEOG_dt p2 WHERE p1.location <> p2.location; + +CREATE TABLE SPATIALPOINT_dt (PrimaryKey int, GeomColumn geometry, GeogColumn geography) + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeomColumn) VALUES ( 1, geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) +~~ROW COUNT: 1~~ + + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeogColumn) VALUES ( 2, geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) +~~ROW COUNT: 1~~ + + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeomColumn, GeogColumn) VALUES ( 3, geometry::STGeomFromText('Point(1.0 2.0)', 4326), geography::STGeomFromText('Point(1.0 2.0)', 4326) ) +~~ROW COUNT: 1~~ + + + +#Tests for Spatial type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeomColumn) values(?, ?) #!#int|-|PrimaryKey|-|4#!#GEOMETRY|-|GeomColumn|-|Point(47.65100 -22.34900):4326 ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINT_dt (GeogColumn) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeogColumn) values(?, ?) #!#int|-|PrimaryKey|-|5#!#GEOGRAPHY|-|GeogColumn|-|Point(47.65100 -22.34900):4326 ~~ROW COUNT: 1~~ -INSERT INTO SPATIALPOINT_dt (GeomColumn, GeogColumn) -VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326), geography::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeomColumn, GeogColumn) values(?, ?, ?) #!#int|-|PrimaryKey|-|6#!#GEOMETRY|-|GeomColumn|-|Point(1.0 2.0):4326#!#GEOGRAPHY|-|GeogColumn|-|Point(1.0 2.0):4326 ~~ROW COUNT: 1~~ diff --git a/test/JDBC/expected/TestSpatialPoint-vu-verify.out b/test/JDBC/expected/TestSpatialPoint-vu-verify.out index 0217f0f9ca..effe3902e8 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-verify.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-verify.out @@ -72,6 +72,9 @@ POINT(47.651 -22.349) POINT(47.651 -22.349) POINT(1 2) POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) ~~END~~ @@ -86,6 +89,9 @@ varbinary 010100000017D9CEF753D34740D34D6210585936C0 0101000000000000000000F03F0000000000000040 010100000017D9CEF753D34740D34D6210585936C0 +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 ~~END~~ @@ -100,6 +106,9 @@ float#!#float 47.651#!#-22.349 1.0#!#2.0 47.651#!#-22.349 +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 ~~END~~ @@ -124,6 +133,9 @@ E6100000010C000000000000F03F0000000000000040 E6100000010C17D9CEF753D34740D34D6210585936C0 E6100000010C000000000000F03F0000000000000040 E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +00000000010C17D9CEF753D34740D34D6210585936C0 ~~END~~ @@ -210,6 +222,8 @@ POINT(1 2) POINT(47.651 -22.349) POINT(1 2) POINT(-22.349 47.651) +POINT(47.651 -22.349) +POINT(1 2) ~~END~~ @@ -223,6 +237,8 @@ varbinary 010100000017D9CEF753D34740D34D6210585936C0 0101000000000000000000F03F0000000000000040 0101000000D34D6210585936C017D9CEF753D34740 +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 ~~END~~ @@ -236,6 +252,8 @@ float#!#float 47.651#!#-22.349 1.0#!#2.0 -22.349#!#47.651 +47.651#!#-22.349 +1.0#!#2.0 ~~END~~ @@ -249,6 +267,8 @@ E6100000010C0000000000000040000000000000F03F E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010C0000000000000040000000000000F03F ~~END~~ @@ -259,19 +279,33 @@ geography#!#geography#!#float E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.0424362254827898E7 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.0424362254827898E7 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.0424362254827898E7 +E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.0424362254827898E7 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.0424362254827898E7 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.0424362254827898E7 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 ~~END~~ @@ -285,15 +319,20 @@ E6100000010C0000000000000040000000000000F03F E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010C0000000000000040000000000000F03F ~~END~~ SELECT * FROM SPATIALPOINT_dt; GO ~~START~~ -geometry#!#geography -E6100000010C17D9CEF753D34740D34D6210585936C0#!# -#!#E6100000010CD34D6210585936C017D9CEF753D34740 -E6100000010C000000000000F03F0000000000000040#!#E6100000010C0000000000000040000000000000F03F +int#!#geometry#!#geography +1#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!# +2#!##!#E6100000010CD34D6210585936C017D9CEF753D34740 +3#!#E6100000010C000000000000F03F0000000000000040#!#E6100000010C0000000000000040000000000000F03F +4#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!# +5#!##!#E6100000010CD34D6210585936C017D9CEF753D34740 +6#!#E6100000010C000000000000F03F0000000000000040#!#E6100000010C0000000000000040000000000000F03F ~~END~~ diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.sql b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt similarity index 92% rename from test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.sql rename to test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt index d2f24215ac..5ad69e2c46 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.sql +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt @@ -1,41 +1,27 @@ DROP VIEW IF EXISTS TextFromGeom -GO DROP VIEW IF EXISTS BinaryFromGeom -GO DROP VIEW IF EXISTS CoordsFromGeom -GO DROP VIEW IF EXISTS point_distances_geom -GO DROP VIEW IF EXISTS TextFromGeog -GO DROP VIEW IF EXISTS BinaryFromGeog -GO DROP VIEW IF EXISTS CoordsFromGeog -GO DROP VIEW IF EXISTS TransformFromGeog -GO DROP VIEW IF EXISTS point_distances_geog -GO DROP TABLE IF EXISTS SPATIALPOINTGEOM_dt -GO DROP TABLE IF EXISTS TypeTable -GO DROP TYPE IF EXISTS geom -GO DROP TABLE IF EXISTS SPATIALPOINTGEOG_dt -GO DROP TABLE IF EXISTS SPATIALPOINT_dt -GO diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.sql b/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.sql deleted file mode 100644 index 99096829d1..0000000000 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.sql +++ /dev/null @@ -1,240 +0,0 @@ -CREATE TABLE SPATIALPOINTGEOM_dt (location geometry) -GO - --- Geometry Test Cases - --- Positive Test for STGeomFromText with SRID 4326 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO - --- Positive Test for STGeomFromText with SRID 0 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 0) ) -GO - --- Negative Test for STGeomFromText when SRID is not provided -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)') ) -GO - --- Negative Test for STGeomFromText when SRID >= 10^6 --- SRID should be between 0 to 999999 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) -GO - --- Negative Test for STGeomFromText with SRID < 0 --- SRID should be between 0 to 999999 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', -1) ) -GO - --- Negative Test for STGeomFromText when a coordinate is missing -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Point(1.0 )', 4326) ) -GO - --- Negative Test for STGeomFromText when invalid type is provided -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText('Pnt', 4326) ) -GO - --- Test for STGeomFromText when null Point is Given -> Returns NBCRow -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STGeomFromText(null, 4326) ) -GO - --- -- Negative Test for STGeomFromText when Incorrect cast is provided --- INSERT INTO SPATIALPOINTGEOM_dt (location) --- VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- GO - --- Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STPointFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::STPointFromText('Point(1.0 2.0)', 4326) ) -GO - --- Positive Test for Point with SRID 4326 -INSERT INTO SPATIALPOINTGEOM_dt (location) -VALUES ( geometry::Point(47.65100, -22.34900, 4326) ) -GO - -CREATE VIEW TextFromGeom AS -SELECT STAsText(location) AS TextRepresentation -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW BinaryFromGeom AS -SELECT STAsBinary(location) AS BinaryRepresentation -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW CoordsFromGeom AS -SELECT STX(location), STY(location) AS Coordinates -FROM SPATIALPOINTGEOM_dt; -GO - -CREATE VIEW point_distances_geom AS -SELECT - p1.location AS point1, - p2.location AS point2, - STDistance( p1.location, p2.location ) AS distance -FROM - SPATIALPOINTGEOM_dt p1 -CROSS JOIN - SPATIALPOINTGEOM_dt p2 -WHERE - p1.location <> p2.location; -GO - -CREATE TABLE SPATIALPOINTGEOG_dt (location geography) -GO - --- Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything --- TODO: Make it similar to T-SQL -CREATE TYPE geom -FROM geometry NOT NULL ; -GO - -CREATE TABLE TypeTable(ID INT PRIMARY KEY, Shape geom) -GO - -INSERT INTO TypeTable(ID, Shape) -VALUES(1, geometry::Point(1, 2, 4326)); -GO - --- Geography Test Cases - --- Positive Test for STGeomFromText with SRID 4326 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO - --- Negative Test for STGeomFromText for Geography with SRID 0 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 0) ) -GO - --- Negative Test for STGeomFromText for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -122.34900)', 4326) ) -GO - --- Negative Test for STGeomFromText when SRID is not provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)') ) -GO - --- Negative Test for STGeomFromText when cast is not provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO - --- -- Negative Test for STGeomFromText when incorrect cast is provided --- INSERT INTO SPATIALPOINTGEOG_dt (location) --- VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) --- GO - --- Negative Test for STGeomFromText when SRID >= 10^6 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) -GO - --- Negative Test for STGeomFromText with SRID < 0 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', -1) ) -GO - --- Negative Test for STGeomFromText when a coordinate is missing -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Point(1.0 )', 4326) ) -GO - --- Negative Test for STGeomFromText when invalid type is provided -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText('Pnt', 4326) ) -GO - --- Test for STGeomFromText when null Point is Given -> Returns NBCRow -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STGeomFromText(null, 4326) ) -GO - --- Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(1.0 2.0)', 4326) ) -GO - --- Negative Test for STPointFromText for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::STPointFromText('Point(47.65100 122.34900)', 4326) ) -GO - --- Positive Test for Point with SRID 4326 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::Point(47.65100, -22.34900, 4326) ) -GO - --- Negative Test for Point for Geography when lat > 90 or < -90 -INSERT INTO SPATIALPOINTGEOG_dt (location) -VALUES ( geography::Point(147.65100, -22.34900, 4326) ) -GO - -CREATE VIEW TextFromGeog AS -SELECT STAsText(location) AS TextRepresentation -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW BinaryFromGeog AS -SELECT STAsBinary(location) AS BinaryRepresentation -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW CoordsFromGeog AS -SELECT long(location), lat(location) AS Coordinates -FROM SPATIALPOINTGEOG_dt; -GO - - -CREATE VIEW TransformFromGeog AS -SELECT ST_Transform(location, 4326) AS Modified_points -FROM SPATIALPOINTGEOG_dt; -GO - -CREATE VIEW point_distances_geog AS -SELECT - p1.location AS point1, - p2.location AS point2, - STDistance( p1.location, p2.location ) AS distance -FROM - SPATIALPOINTGEOG_dt p1 -CROSS JOIN - SPATIALPOINTGEOG_dt p2 -WHERE - p1.location <> p2.location; -GO - -CREATE TABLE SPATIALPOINT_dt (GeomColumn geometry, GeogColumn geography) -GO -INSERT INTO SPATIALPOINT_dt (GeomColumn) -VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINT_dt (GeogColumn) -VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) -GO -INSERT INTO SPATIALPOINT_dt (GeomColumn, GeogColumn) -VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326), geography::STGeomFromText('Point(1.0 2.0)', 4326) ) -GO diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt b/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt new file mode 100644 index 0000000000..2f21076b80 --- /dev/null +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt @@ -0,0 +1,180 @@ +CREATE TABLE SPATIALPOINTGEOM_dt (location geometry) + +#Geometry Test Cases + +#Positive Test for STGeomFromText with SRID 4326 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(1.0 2.0)', 4326) ) + +#Positive Test for STGeomFromText with SRID 0 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 0) ) + +#Negative Test for STGeomFromText when SRID is not provided +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)') ) + +#Negative Test for STGeomFromText when SRID >= 10^6 +#SRID should be between 0 to 999999 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) + +#Negative Test for STGeomFromText with SRID < 0 +#SRID should be between 0 to 999999 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', -1) ) + +#Negative Test for STGeomFromText when a coordinate is missing +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Point(1.0 )', 4326) ) + +#Negative Test for STGeomFromText when invalid type is provided +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText('Pnt', 4326) ) + +#Test for STGeomFromText when null Point is Given -> Returns NBCRow +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STGeomFromText(null, 4326) ) + +#Negative Test for STGeomFromText when Incorrect cast is provided +#INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +#Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STPointFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STPointFromText('Point(1.0 2.0)', 4326) ) + + +#Positive Test for Point with SRID 4326 +INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::Point(47.65100, -22.34900, 4326) ) + +#Tests for Geometry type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINTGEOM_dt(location) values(@location) #!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):0 +#Negative Test for STGeomFromText when SRID >= 10^6 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):1000000000 +#Negative Test for STGeomFromText with SRID < 0 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):-1 +#Negative Test for STGeomFromText when SRID is NULL +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900): +#Negative Test for STGeomFromText when a coordinate is missing +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 ):4326 +#Negative Test when an unsupported feature in queried +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|LINESTRING(1 2, 3 4):4326 +#Negative Test for STGeomFromText when invalid type is provided +prepst#!#exec#!#GEOMETRY|-|location|-|Pnt:4326 +#Negative Test for STGeomFromText when Null geometry is provided +prepst#!#exec#!#GEOMETRY|-|location|-|:4326 + +CREATE VIEW TextFromGeom AS SELECT STAsText(location) AS TextRepresentation FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW BinaryFromGeom AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW CoordsFromGeom AS SELECT STX(location), STY(location) AS Coordinates FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW point_distances_geom AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location <> p2.location; + +CREATE TABLE SPATIALPOINTGEOG_dt (location geography) + +#Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything +#TODO: Make it similar to T-SQL +CREATE TYPE geom FROM geometry NOT NULL ; + +CREATE TABLE TypeTable(ID INT PRIMARY KEY, Shape geom) + +INSERT INTO TypeTable(ID, Shape) VALUES(1, geometry::Point(1, 2, 4326)); + +#Geography Test Cases + +#Positive Test for STGeomFromText with SRID 4326 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(1.0 2.0)', 4326) ) + +#Negative Test for STGeomFromText for Geography with SRID 0 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 0) ) + +#Negative Test for STGeomFromText for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -122.34900)', 4326) ) + +#Negative Test for STGeomFromText when SRID is not provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)') ) + +#Negative Test for STGeomFromText when cast is not provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +#Negative Test for STGeomFromText when incorrect cast is provided +#INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +#Negative Test for STGeomFromText when SRID >= 10^6 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', 1000000000 ) ) + +#Negative Test for STGeomFromText with SRID < 0 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(47.65100 -22.34900)', -1) ) + +#Negative Test for STGeomFromText when a coordinate is missing +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Point(1.0 )', 4326) ) + +#Negative Test for STGeomFromText when invalid type is provided +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText('Pnt', 4326) ) + +#Test for STGeomFromText when null Point is Given -> Returns NBCRow +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STGeomFromText(null, 4326) ) + +#Positive Test for STPointFromText with SRID 4326. Rest are same as STGeomFromText +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(1.0 2.0)', 4326) ) + +#Negative Test for STPointFromText for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::STPointFromText('Point(47.65100 122.34900)', 4326) ) + +#Positive Test for Point with SRID 4326 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::Point(47.65100, -22.34900, 4326) ) + +#Negative Test for Point for Geography when lat > 90 or < -90 +INSERT INTO SPATIALPOINTGEOG_dt (location) VALUES ( geography::Point(147.65100, -22.34900, 4326) ) + +#Tests for Geography type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINTGEOG_dt(location) values(@location) #!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):4326 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0):4326 +#Negative Test for STGeomFromText for Geography with SRID 0 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):0 +#Negative Test for STGeomFromText for Geography when lat > 90 or < -90 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -122.34900):4326 +#Negative Test for STGeomFromText when SRID >= 10^6 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):1000000000 +#Negative Test for STGeomFromText with SRID < 0 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):-1 +#Negative Test for STGeomFromText with SRID is NULL +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900): +#Negative Test for STGeomFromText when a coordinate is missing +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 ):4326 +#Negative Test when an unsupported feature in queried +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +prepst#!#exec#!#GEOGRAPHY|-|location|-|LINESTRING(1 2, 3 4):4326 +#Negative Test for STGeomFromText when invalid type is provided +prepst#!#exec#!#GEOGRAPHY|-|location|-|Pnt:4326 +#Negative Test for STGeomFromText when Null geography is provided +prepst#!#exec#!#GEOGRAPHY|-|location|-|:4326 + +CREATE VIEW TextFromGeog AS SELECT STAsText(location) AS TextRepresentation FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW BinaryFromGeog AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW CoordsFromGeog AS SELECT long(location), lat(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; + + +CREATE VIEW TransformFromGeog AS SELECT ST_Transform(location, 4326) AS Modified_points FROM SPATIALPOINTGEOG_dt; + +CREATE VIEW point_distances_geog AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOG_dt p1 CROSS JOIN SPATIALPOINTGEOG_dt p2 WHERE p1.location <> p2.location; + +CREATE TABLE SPATIALPOINT_dt (PrimaryKey int, GeomColumn geometry, GeogColumn geography) + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeomColumn) VALUES ( 1, geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeogColumn) VALUES ( 2, geography::STGeomFromText('Point(47.65100 -22.34900)', 4326) ) + +INSERT INTO SPATIALPOINT_dt (PrimaryKey, GeomColumn, GeogColumn) VALUES ( 3, geometry::STGeomFromText('Point(1.0 2.0)', 4326), geography::STGeomFromText('Point(1.0 2.0)', 4326) ) + + +#Tests for Spatial type Prepared Statements +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeomColumn) values(@PrimaryKey, @GeomColumn) #!#int|-|PrimaryKey|-|4#!#GEOMETRY|-|GeomColumn|-|Point(47.65100 -22.34900):4326 +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeogColumn) values(@PrimaryKey, @GeogColumn) #!#int|-|PrimaryKey|-|5#!#GEOGRAPHY|-|GeogColumn|-|Point(47.65100 -22.34900):4326 +prepst#!#INSERT INTO SPATIALPOINT_dt(PrimaryKey, GeomColumn, GeogColumn) values(@PrimaryKey, @GeomColumn, @GeogColumn) #!#int|-|PrimaryKey|-|6#!#GEOMETRY|-|GeomColumn|-|Point(1.0 2.0):4326#!#GEOGRAPHY|-|GeogColumn|-|Point(1.0 2.0):4326 diff --git a/test/JDBC/src/main/java/com/sqlsamples/JDBCPreparedStatement.java b/test/JDBC/src/main/java/com/sqlsamples/JDBCPreparedStatement.java index 12a88c348f..a64c2d405e 100644 --- a/test/JDBC/src/main/java/com/sqlsamples/JDBCPreparedStatement.java +++ b/test/JDBC/src/main/java/com/sqlsamples/JDBCPreparedStatement.java @@ -2,6 +2,8 @@ import com.microsoft.sqlserver.jdbc.SQLServerDataTable; import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; +import com.microsoft.sqlserver.jdbc.Geometry; +import com.microsoft.sqlserver.jdbc.Geography; import microsoft.sql.DateTimeOffset; import org.apache.logging.log4j.Logger; @@ -185,6 +187,30 @@ static void set_bind_values(String[] result, PreparedStatement pstmt, BufferedWr SQLServerPreparedStatement ssPstmt = (SQLServerPreparedStatement) pstmt; ssPstmt.setStructured(j - 1, parameter[1], sourceDataTable); pstmt = ssPstmt; + } else if (parameter[0].equalsIgnoreCase("geometry")) { + String[] arguments = parameter[2].split(":", 2); + String geoWKT = arguments[0]; + int srid = -1; + try{ + srid = Integer.parseInt(arguments[1]); + } finally { + Geometry geomWKT = Geometry.STGeomFromText(geoWKT, srid); + SQLServerPreparedStatement ssPstmt = (SQLServerPreparedStatement) pstmt; + ssPstmt.setGeometry(j - 1, geomWKT); + pstmt = ssPstmt; + } + } else if (parameter[0].equalsIgnoreCase("geography")) { + String[] arguments = parameter[2].split(":", 2); + String geoWKT = arguments[0]; + int srid = -1; + try{ + srid = Integer.parseInt(arguments[1]); + } finally { + Geography geogWKT = Geography.STGeomFromText(geoWKT, srid); + SQLServerPreparedStatement ssPstmt = (SQLServerPreparedStatement) pstmt; + ssPstmt.setGeography(j - 1, geogWKT); + pstmt = ssPstmt; + } } } catch (SQLException se) { handleSQLExceptionWithFile(se, bw, logger); @@ -194,6 +220,8 @@ static void set_bind_values(String[] result, PreparedStatement pstmt, BufferedWr logger.error("IO Exception: " + e.getMessage(), e); } catch (ParseException e) { logger.error("Parse Exception: " + e.getMessage(), e); + } catch (NumberFormatException e) { + logger.error("Number Format Exception: " + e.getMessage(), e); } } } diff --git a/test/dotnet/ExpectedOutput/TestPoint.out b/test/dotnet/ExpectedOutput/TestPoint.out new file mode 100644 index 0000000000..402c335bfc --- /dev/null +++ b/test/dotnet/ExpectedOutput/TestPoint.out @@ -0,0 +1,50 @@ +#Q#CREATE TABLE POINTGEOM_dt(location GEOMETRY); +#Q#INSERT INTO POINTGEOM_dt(location) values(@location) +#Q#INSERT INTO POINTGEOM_dt(location) values(@location) +#Q#INSERT INTO POINTGEOM_dt(location) values(@location) +#Q#INSERT INTO POINTGEOM_dt(location) values(@location) +#E#Unsupported geometry type +#Q#INSERT INTO POINTGEOM_dt(location) values(@location) +#E#Unsupported geometry type +#Q#CREATE TABLE POINTGEOG_dt(location GEOGRAPHY); +#Q#INSERT INTO POINTGEOG_dt(location) values(@location) +#Q#INSERT INTO POINTGEOG_dt(location) values(@location) +#Q#INSERT INTO POINTGEOG_dt(location) values(@location) +#E#Unsupported geometry type +#Q#INSERT INTO POINTGEOG_dt(location) values(@location) +#E#Unsupported geometry type +#Q#CREATE TABLE POINT_dt(geom GEOMETRY, geog GEOGRAPHY); +#Q#INSERT INTO POINT_dt(geom) values(@geom) +#Q#INSERT INTO POINT_dt(geog) values(@geog) +#Q#INSERT INTO POINT_dt(geom, geog) values(@geom, @geog) +#Q#INSERT INTO POINTGEOM_dt(location) values(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326)) +#Q#INSERT INTO POINTGEOM_dt(location) values(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0)) +#Q#INSERT INTO POINTGEOM_dt(location) values(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326)) +#Q#INSERT INTO POINTGEOM_dt(location) values(geometry::Point(47.65100, -22.34900, 4326)) +#Q#INSERT INTO POINTGEOG_dt(location) values(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326)) +#Q#INSERT INTO POINTGEOG_dt(location) values(geography::STPointFromText('Point(47.65100 -22.34900)', 4326)) +#Q#INSERT INTO POINTGEOG_dt(location) values(geography::Point(47.65100, -22.34900, 4326)) +#Q#SELECT STAsText(location) FROM POINTGEOM_dt; +#D#text +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +#Q#SELECT STAsText(location) FROM POINTGEOG_dt; +#D#text +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(-22.349 47.651) +#Q#SELECT STAsText(geom), STAsText(geog) FROM POINT_dt; +#D#text#!#text +POINT(47.651 -22.349)#!# +#!#POINT(47.651 -22.349) +POINT(1 2)#!#POINT(1 2) +#Q#DROP TABLE IF EXISTS POINTGEOM_dt; +#Q#DROP TABLE IF EXISTS POINTGEOG_dt; +#Q#DROP TABLE IF EXISTS POINT_dt; diff --git a/test/dotnet/dotnet.csproj b/test/dotnet/dotnet.csproj index bb2a7c168f..c5e9aed6b8 100644 --- a/test/dotnet/dotnet.csproj +++ b/test/dotnet/dotnet.csproj @@ -11,6 +11,7 @@ + all diff --git a/test/dotnet/input/Datatypes/TestPoint.txt b/test/dotnet/input/Datatypes/TestPoint.txt new file mode 100644 index 0000000000..78d9906534 --- /dev/null +++ b/test/dotnet/input/Datatypes/TestPoint.txt @@ -0,0 +1,49 @@ +CREATE TABLE POINTGEOM_dt(location GEOMETRY); +prepst#!#INSERT INTO POINTGEOM_dt(location) values(@location) #!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):0 +prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +prepst#!#exec#!#GEOMETRY|-|location|-|LINESTRING(1 2, 3 4):4326 +#next six lines are not allowed +#prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):1000000000 +#prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):-1 +#prepst#!#exec#!#GEOMETRY|-|location|-|Point(47.65100 -22.34900): +#prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 ):4326 +#prepst#!#exec#!#GEOMETRY|-|location|-|Pnt:4326 +#prepst#!#exec#!#GEOMETRY|-|location|-|:4326 +CREATE TABLE POINTGEOG_dt(location GEOGRAPHY); +prepst#!#INSERT INTO POINTGEOG_dt(location) values(@location) #!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):4326 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0):4326 +prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 2.0 3.0 4.0):4326 +prepst#!#exec#!#GEOGRAPHY|-|location|-|LINESTRING(1 2, 3 4):4326 +#next eight lines are not allowed +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):0 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -122.34900):4326 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):1000000000 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900):-1 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(47.65100 -22.34900): +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Point(1.0 ):4326 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|Pnt:4326 +#prepst#!#exec#!#GEOGRAPHY|-|location|-|:4326 +CREATE TABLE POINT_dt(geom GEOMETRY, geog GEOGRAPHY); +prepst#!#INSERT INTO POINT_dt(geom) values(@geom) #!#GEOMETRY|-|geom|-|Point(47.65100 -22.34900):4326 +prepst#!#INSERT INTO POINT_dt(geog) values(@geog) #!#GEOGRAPHY|-|geog|-|Point(47.65100 -22.34900):4326 +prepst#!#INSERT INTO POINT_dt(geom, geog) values(@geom, @geog) #!#GEOMETRY|-|geom|-|Point(1.0 2.0):4326#!#GEOGRAPHY|-|geog|-|Point(1.0 2.0):4326 + + +INSERT INTO POINTGEOM_dt(location) values(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326)) +INSERT INTO POINTGEOM_dt(location) values(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0)) +INSERT INTO POINTGEOM_dt(location) values(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326)) +INSERT INTO POINTGEOM_dt(location) values(geometry::Point(47.65100, -22.34900, 4326)) + +INSERT INTO POINTGEOG_dt(location) values(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326)) +INSERT INTO POINTGEOG_dt(location) values(geography::STPointFromText('Point(47.65100 -22.34900)', 4326)) +INSERT INTO POINTGEOG_dt(location) values(geography::Point(47.65100, -22.34900, 4326)) + +SELECT STAsText(location) FROM POINTGEOM_dt; +SELECT STAsText(location) FROM POINTGEOG_dt; +SELECT STAsText(geom), STAsText(geog) FROM POINT_dt; + +DROP TABLE IF EXISTS POINTGEOM_dt; +DROP TABLE IF EXISTS POINTGEOG_dt; +DROP TABLE IF EXISTS POINT_dt; diff --git a/test/dotnet/src/PrepareExecBinding.cs b/test/dotnet/src/PrepareExecBinding.cs index 058f6652a4..642f206252 100644 --- a/test/dotnet/src/PrepareExecBinding.cs +++ b/test/dotnet/src/PrepareExecBinding.cs @@ -5,6 +5,7 @@ using System.Data.OleDb; using System.Data.SqlClient; using System.Data.SqlTypes; +using Microsoft.SqlServer.Types; using System.IO; using System.Text; @@ -114,6 +115,42 @@ public static DbCommand SetBindParams(string[] result, sqlCmd.Parameters[param[1].Trim()].Size = 1000; } break; + case "geometry": + { + if (ConfigSetup.Database.Equals("oledb", StringComparison.InvariantCulture)) + { + testUtils.PrintToLogsOrConsole("GEOMETRY NOT SUPPORTED BY OLEDB", logger, "error"); + break; + } + string[] arguments = param[2].Split(':', 2); + string geoWKT = arguments[0]; + int srid = (int)GetSqlDbValue("int", arguments[1]); + + ((SqlParameter)sqlCmd.Parameters[param[1].Trim()]).SqlDbType = SqlDbType.Udt; + ((SqlParameter) sqlCmd.Parameters[param[1].Trim()]).UdtTypeName = "Geometry"; + + sqlCmd.Parameters[param[1].Trim()].Value = SqlGeometry.STGeomFromText(new SqlChars(new SqlString(geoWKT)), srid); + sqlCmd.Parameters[param[1].Trim()].Size = 65535; + } + break; + case "geography": + { + if (ConfigSetup.Database.Equals("oledb", StringComparison.InvariantCulture)) + { + testUtils.PrintToLogsOrConsole("GEOGRAPHY NOT SUPPORTED BY OLEDB", logger, "error"); + break; + } + string[] arguments = param[2].Split(':', 2); + string geoWKT = arguments[0]; + int srid = (int)GetSqlDbValue("int", arguments[1]); + + ((SqlParameter)sqlCmd.Parameters[param[1].Trim()]).SqlDbType = SqlDbType.Udt; + ((SqlParameter)sqlCmd.Parameters[param[1].Trim()]).UdtTypeName = "Geography"; + + sqlCmd.Parameters[param[1].Trim()].Value = SqlGeography.STGeomFromText(new SqlChars(new SqlString(geoWKT)), srid); + sqlCmd.Parameters[param[1].Trim()].Size = 65535; + } + break; default: throw new Exception("DATATYPE NOT SUPPORTED:- " + param[0]); } @@ -233,6 +270,42 @@ public static DbCommand SetBindParams(string[] result, parameter.Size = 1000; } break; + case "geometry": + { + if (ConfigSetup.Database.Equals("oledb", StringComparison.InvariantCulture)) + { + testUtils.PrintToLogsOrConsole("GEOMETRY NOT SUPPORTED BY OLEDB", logger, "error"); + break; + } + string[] arguments = param[2].Split(':', 2); + string geoWKT = arguments[0]; + int srid = (int)GetSqlDbValue("int", arguments[1]);; + + ((SqlParameter)parameter).SqlDbType = SqlDbType.Udt; + ((SqlParameter)parameter).UdtTypeName = "Geometry"; + + parameter.Value = SqlGeometry.STGeomFromText(new SqlChars(new SqlString(geoWKT)), srid); + parameter.Size = 65535; + } + break; + case "geography": + { + if (ConfigSetup.Database.Equals("oledb", StringComparison.InvariantCulture)) + { + testUtils.PrintToLogsOrConsole("GEOGRAPHY NOT SUPPORTED BY OLEDB", logger, "error"); + break; + } + string[] arguments = param[2].Split(':', 2); + string geoWKT = arguments[0]; + int srid = (int)GetSqlDbValue("int", arguments[1]); + + ((SqlParameter)parameter).SqlDbType = SqlDbType.Udt; + ((SqlParameter)parameter).UdtTypeName = "Geography"; + + parameter.Value = SqlGeography.STGeomFromText(new SqlChars(new SqlString(geoWKT)), srid); + parameter.Size = 65535; + } + break; default: throw new Exception("DATATYPE NOT SUPPORTED:- " + param[0]); } @@ -377,6 +450,10 @@ public static SqlDbType GetSqlDbType(string type) return SqlDbType.Structured; case "udt": return SqlDbType.Udt; + case "geometry": + return SqlDbType.Udt; + case "geography": + return SqlDbType.Udt; default: throw new Exception("DATA TYPE NOT SUPPORTED " + type); } diff --git a/test/odbc/mssqlodbc/test_data_types.cpp b/test/odbc/mssqlodbc/test_data_types.cpp index cf4f184f71..cce92a31c3 100644 --- a/test/odbc/mssqlodbc/test_data_types.cpp +++ b/test/odbc/mssqlodbc/test_data_types.cpp @@ -448,3 +448,93 @@ TEST_F(MSSQL_Data_Types, Varchar) { DataTypesTestCommon(TEST_TABLE, TABLE_COLUMNS, INSERTED_VALUES, EXPECTED_VALUES); } + +// Test retrieval of type Geometry +// This test differs from others in the following: +// 1. the way the INSERTED_VALUES are defined - they already contain the 'order of insertion' values +// 2. the way the INSERTED_VALUES are inserted - loop through the 'literal' inserted values since they 'hard code' the 'order of insertions' values +// The reason it was done this way is because in SQL Server you have to call function to convert wkt to geometry type so it contains additional '()' which causes error while processing parameters +// For example, if I had to insert Point(1.0 2.0) it will be done using geometry::STGeomFromText('Point(1.0 2.0)', 4326), which causes error in processInsertedValuesString. +TEST_F(MSSQL_Data_Types, Geometry) { + OdbcHandler odbcHandler(Drivers::GetDriver(ServerType::MSSQL)); + + const string TEST_TABLE = "POINTGEOM_dt"; + const string ORDER_BY_COLS = "OrderOfInsertion"; + const vector> TABLE_COLUMNS = { + {"location", "GEOMETRY"}, + {ORDER_BY_COLS, "INT"} + }; + + const vector INSERTED_VALUES = { + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326), 1)", "(geometry::STGeomFromText('Point(1.0 2.0)', 4326), 2)", + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0), 3)", "(geometry::STGeomFromText(NULL, 4326), 4)", + "(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326), 5)", "(geometry::Point(47.65100, -22.34900, 4326), 6)" + }; + + vector> expectedValues = { + {"E6100000010C17D9CEF753D34740D34D6210585936C0", "E6100000010C000000000000F03F0000000000000040", "00000000010C17D9CEF753D34740D34D6210585936C0", + NULL_STR, "E6100000010C17D9CEF753D34740D34D6210585936C0", "E6100000010C17D9CEF753D34740D34D6210585936C0"} + }; + + DatabaseObjects dbObjects(Drivers::GetDriver(ServerType::MSSQL)); + ASSERT_NO_FATAL_FAILURE(dbObjects.CreateTable(TEST_TABLE, TABLE_COLUMNS)); + + ASSERT_NO_FATAL_FAILURE(odbcHandler.Connect(true)); + + for (short i = 0; i < INSERTED_VALUES.size(); i++) { + ASSERT_NO_FATAL_FAILURE(odbcHandler.ExecQuery(InsertStatement(TEST_TABLE, INSERTED_VALUES[i]))); + + } + ASSERT_NO_FATAL_FAILURE(odbcHandler.ExecQuery(SelectStatement(TEST_TABLE, { "*" }, { ORDER_BY_COLS }))); + + SQLSMALLINT sNumResults; + SQLNumResultCols(odbcHandler.GetStatementHandle(), &sNumResults); + ASSERT_EQ(sNumResults, TABLE_COLUMNS.size()); + + fetchAndCompare(odbcHandler, expectedValues); +} + +// Test retrieval of type Geography +// This test differs from others in the following: +// 1. the way the INSERTED_VALUES are defined - they already contain the 'order of insertion' values +// 2. the way the INSERTED_VALUES are inserted - loop through the 'literal' inserted values since they 'hard code' the 'order of insertions' values +// The reason it was done this way is because in SQL Server you have to call function to convert wkt to geography type so it contains additional '()' which causes error while processing parameters +// For example, if I had to insert Point(1.0 2.0) it will be done using geography::STGeomFromText('Point(1.0 2.0)', 4326), which causes error in processInsertedValuesString. +TEST_F(MSSQL_Data_Types, Geography) { + OdbcHandler odbcHandler(Drivers::GetDriver(ServerType::MSSQL)); + + const string TEST_TABLE = "POINTGEOG_dt"; + const string ORDER_BY_COLS = "OrderOfInsertion"; + const vector> TABLE_COLUMNS = { + {"location", "GEOGRAPHY"}, + {ORDER_BY_COLS, "INT"} + }; + + const vector INSERTED_VALUES = { + "(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326), 1)", "(geography::STGeomFromText('Point(1.0 2.0)', 4326), 2)", + "(geography::STGeomFromText(NULL, 4326), 3)", "(geography::STPointFromText('Point(1.0 2.0)', 4326), 4)", + "(geography::STPointFromText('Point(47.65100 -22.34900)', 4326), 5)", "(geography::Point(47.65100, -22.34900, 4326), 6)" + }; + + vector> expectedValues = { + {"E6100000010CD34D6210585936C017D9CEF753D34740", "E6100000010C0000000000000040000000000000F03F", NULL_STR, "E6100000010C0000000000000040000000000000F03F", + "E6100000010CD34D6210585936C017D9CEF753D34740", "E6100000010C17D9CEF753D34740D34D6210585936C0"} + }; + + DatabaseObjects dbObjects(Drivers::GetDriver(ServerType::MSSQL)); + ASSERT_NO_FATAL_FAILURE(dbObjects.CreateTable(TEST_TABLE, TABLE_COLUMNS)); + + ASSERT_NO_FATAL_FAILURE(odbcHandler.Connect(true)); + + for (short i = 0; i < INSERTED_VALUES.size(); i++) { + ASSERT_NO_FATAL_FAILURE(odbcHandler.ExecQuery(InsertStatement(TEST_TABLE, INSERTED_VALUES[i]))); + + } + ASSERT_NO_FATAL_FAILURE(odbcHandler.ExecQuery(SelectStatement(TEST_TABLE, { "*" }, { ORDER_BY_COLS }))); + + SQLSMALLINT sNumResults; + SQLNumResultCols(odbcHandler.GetStatementHandle(), &sNumResults); + ASSERT_EQ(sNumResults, TABLE_COLUMNS.size()); + + fetchAndCompare(odbcHandler, expectedValues); +} diff --git a/test/odbc/psqlodbc/test/geography.cpp b/test/odbc/psqlodbc/test/geography.cpp new file mode 100644 index 0000000000..79a952454b --- /dev/null +++ b/test/odbc/psqlodbc/test/geography.cpp @@ -0,0 +1,127 @@ +#include "../conversion_functions_common.h" +#include "../psqlodbc_tests_common.h" + +const string TABLE_NAME = "master.dbo.geography_table_odbc_test"; +const string COL1_NAME = "pk"; +const string COL2_NAME = "data"; +const string DATATYPE_NAME = "sys.geography"; +const string VIEW_NAME = "geography_view_odbc_test"; +const vector> TABLE_COLUMNS = { + {COL1_NAME, "INT PRIMARY KEY"}, + {COL2_NAME, DATATYPE_NAME} +}; + +class PSQL_DataTypes_Geography : public testing::Test { + void SetUp() override { + if (!Drivers::DriverExists(ServerType::MSSQL)) { + GTEST_SKIP() << "MSSQL Driver not present: skipping all tests for this fixture."; + } + + OdbcHandler test_setup(Drivers::GetDriver(ServerType::MSSQL)); + test_setup.ConnectAndExecQuery(DropObjectStatement("TABLE", TABLE_NAME)); + } + + void TearDown() override { + if (!Drivers::DriverExists(ServerType::MSSQL)) { + GTEST_SKIP() << "MSSQL Driver not present: skipping all tests for this fixture."; + } + + OdbcHandler test_teardown(Drivers::GetDriver(ServerType::MSSQL)); + test_teardown.ConnectAndExecQuery(DropObjectStatement("VIEW", VIEW_NAME)); + test_teardown.CloseStmt(); + test_teardown.ExecQuery(DropObjectStatement("TABLE", TABLE_NAME)); + } +}; + +TEST_F(PSQL_DataTypes_Geography, Table_Creation) { + const vector LENGTH_EXPECTED = {10, 0}; + const vector PRECISION_EXPECTED = {10, 0}; + const vector SCALE_EXPECTED = {0, 0}; + const vector NAME_EXPECTED = {"int", "udt"}; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testCommonColumnAttributes(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS.size(), COL1_NAME, LENGTH_EXPECTED, + PRECISION_EXPECTED, SCALE_EXPECTED, NAME_EXPECTED); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geography, Insertion_Success) { + const vector INSERTED_VALUES = { + "(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326))", + "(geography::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geography::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geography::STPointFromText('Point(1.0 2.0)', 4326))", + "(geography::Point(47.65100, -22.34900, 4326))" + }; + const vector EXPECTED_VALUES = { + "E6100000010CD34D6210585936C017D9CEF753D34740", + "E6100000010C0000000000000040000000000000F03F", + "E6100000010CD34D6210585936C017D9CEF753D34740", + "E6100000010C0000000000000040000000000000F03F", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + const int NUM_OF_INSERTS = INSERTED_VALUES.size(); + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, + INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geography, Update_Success) { + const vector INSERTED_VALUES = { + "(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326))" + }; + const vector EXPECTED_VALUES = { + "E6100000010CD34D6210585936C017D9CEF753D34740" + }; + + const vector UPDATED_VALUES = { + "(geography::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geography::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geography::STPointFromText('Point(1.0 2.0)', 4326))", + "(geography::Point(47.65100, -22.34900, 4326))" + }; + const vector EXPECTED_UPDATED_VALUES = { + "E6100000010C0000000000000040000000000000F03F", + "E6100000010CD34D6210585936C017D9CEF753D34740", + "E6100000010C0000000000000040000000000000F03F", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, + INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + testUpdateSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, COL2_NAME, + UPDATED_VALUES, EXPECTED_UPDATED_VALUES, false, true); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geography, View_creation) { + const vector INSERTED_VALUES = { + "(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326))", + "(geography::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geography::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geography::STPointFromText('Point(1.0 2.0)', 4326))", + "(geography::Point(47.65100, -22.34900, 4326))" + }; + + const vector EXPECTED_VALUES = { + "E6100000010CD34D6210585936C017D9CEF753D34740", + "E6100000010C0000000000000040000000000000F03F", + "E6100000010CD34D6210585936C017D9CEF753D34740", + "E6100000010C0000000000000040000000000000F03F", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + + const string VIEW_QUERY = "SELECT * FROM " + TABLE_NAME; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + + createView(ServerType::MSSQL, VIEW_NAME, VIEW_QUERY); + verifyValuesInObject(ServerType::MSSQL, VIEW_NAME, COL1_NAME, INSERTED_VALUES, EXPECTED_VALUES); + + dropObject(ServerType::MSSQL, "VIEW", VIEW_NAME); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} diff --git a/test/odbc/psqlodbc/test/geometry.cpp b/test/odbc/psqlodbc/test/geometry.cpp new file mode 100644 index 0000000000..0f7bf73ae0 --- /dev/null +++ b/test/odbc/psqlodbc/test/geometry.cpp @@ -0,0 +1,127 @@ +#include "../conversion_functions_common.h" +#include "../psqlodbc_tests_common.h" + +const string TABLE_NAME = "master.dbo.geometry_table_odbc_test"; +const string COL1_NAME = "pk"; +const string COL2_NAME = "data"; +const string DATATYPE_NAME = "sys.geometry"; +const string VIEW_NAME = "geometry_view_odbc_test"; +const vector> TABLE_COLUMNS = { + {COL1_NAME, "INT PRIMARY KEY"}, + {COL2_NAME, DATATYPE_NAME} +}; + +class PSQL_DataTypes_Geometry : public testing::Test { + void SetUp() override { + if (!Drivers::DriverExists(ServerType::MSSQL)) { + GTEST_SKIP() << "MSSQL Driver not present: skipping all tests for this fixture."; + } + + OdbcHandler test_setup(Drivers::GetDriver(ServerType::MSSQL)); + test_setup.ConnectAndExecQuery(DropObjectStatement("TABLE", TABLE_NAME)); + } + + void TearDown() override { + if (!Drivers::DriverExists(ServerType::MSSQL)) { + GTEST_SKIP() << "MSSQL Driver not present: skipping all tests for this fixture."; + } + + OdbcHandler test_teardown(Drivers::GetDriver(ServerType::MSSQL)); + test_teardown.ConnectAndExecQuery(DropObjectStatement("VIEW", VIEW_NAME)); + test_teardown.CloseStmt(); + test_teardown.ExecQuery(DropObjectStatement("TABLE", TABLE_NAME)); + } +}; + +TEST_F(PSQL_DataTypes_Geometry, Table_Creation) { + const vector LENGTH_EXPECTED = {10, 0}; + const vector PRECISION_EXPECTED = {10, 0}; + const vector SCALE_EXPECTED = {0, 0}; + const vector NAME_EXPECTED = {"int", "udt"}; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testCommonColumnAttributes(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS.size(), COL1_NAME, LENGTH_EXPECTED, + PRECISION_EXPECTED, SCALE_EXPECTED, NAME_EXPECTED); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geometry, Insertion_Success) { + const vector INSERTED_VALUES = { + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326))", + "(geometry::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0))", + "(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geometry::Point(47.65100, -22.34900, 4326))" + }; + const vector EXPECTED_VALUES = { + "E6100000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C000000000000F03F0000000000000040", + "00000000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + const int NUM_OF_INSERTS = INSERTED_VALUES.size(); + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, + INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geometry, Update_Success) { + const vector INSERTED_VALUES = { + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326))" + }; + const vector EXPECTED_VALUES = { + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + + const vector UPDATED_VALUES = { + "(geometry::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0))", + "(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geometry::Point(47.65100, -22.34900, 4326))" + }; + const vector EXPECTED_UPDATED_VALUES = { + "E6100000010C000000000000F03F0000000000000040", + "00000000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, + INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + testUpdateSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, COL2_NAME, + UPDATED_VALUES, EXPECTED_UPDATED_VALUES, false, true); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} + +TEST_F(PSQL_DataTypes_Geometry, View_creation) { + const vector INSERTED_VALUES = { + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 4326))", + "(geometry::STGeomFromText('Point(1.0 2.0)', 4326))", + "(geometry::STGeomFromText('Point(47.65100 -22.34900)', 0))", + "(geometry::STPointFromText('Point(47.65100 -22.34900)', 4326))", + "(geometry::Point(47.65100, -22.34900, 4326))" + }; + + const vector EXPECTED_VALUES = { + "E6100000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C000000000000F03F0000000000000040", + "00000000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0", + "E6100000010C17D9CEF753D34740D34D6210585936C0" + }; + + const string VIEW_QUERY = "SELECT * FROM " + TABLE_NAME; + + createTable(ServerType::MSSQL, TABLE_NAME, TABLE_COLUMNS); + testInsertionSuccess(ServerType::MSSQL, TABLE_NAME, COL1_NAME, INSERTED_VALUES, EXPECTED_VALUES, 0, false, true); + + createView(ServerType::MSSQL, VIEW_NAME, VIEW_QUERY); + verifyValuesInObject(ServerType::MSSQL, VIEW_NAME, COL1_NAME, INSERTED_VALUES, EXPECTED_VALUES); + + dropObject(ServerType::MSSQL, "VIEW", VIEW_NAME); + dropObject(ServerType::MSSQL, "TABLE", TABLE_NAME); +} diff --git a/test/python/expected/upgrade_validation/expected_dependency.out b/test/python/expected/upgrade_validation/expected_dependency.out index 385115fae4..e9cd5b635f 100644 --- a/test/python/expected/upgrade_validation/expected_dependency.out +++ b/test/python/expected/upgrade_validation/expected_dependency.out @@ -221,6 +221,7 @@ Function sys.bbf_binary_varbinary_cmp(sys.bbf_binary,sys.bbf_varbinary) Function sys.bbf_get_context_info() Function sys.bbf_get_current_physical_schema_name(text) Function sys.bbf_is_shared_schema(text) +Function sys.bbf_varbinary(sys.geometry) Function sys.bbf_varbinary_binary_cmp(sys.bbf_varbinary,sys.bbf_binary) Function sys.bbf_varbinary_cmp(sys.bbf_varbinary,sys.bbf_varbinary) Function sys.bbfbinary_sqlvariant(sys.bbf_binary) @@ -265,6 +266,7 @@ Function sys.bpcharrowversion(character,integer,boolean) Function sys.bpcharrowversion(sys.bpchar,integer,boolean) Function sys.bpcharvarbinary(character,integer,boolean) Function sys.bpcharvarbinary(sys.bpchar,integer,boolean) +Function sys.bytea(sys.geography) Function sys.bytea(sys.geometry) Function sys.byteavarbinary(bytea,integer,boolean) Function sys.ceiling(bigint) @@ -419,23 +421,28 @@ Function sys.ftrunci8(real) Function sys.fulltextserviceproperty(text) Function sys.geogpoint_helper(double precision,double precision,integer) Function sys.geography(bytea) +Function sys.geography(sys.bbf_varbinary) Function sys.geography(sys.geography,integer,boolean) Function sys.geography(sys.geometry) Function sys.geography__point(double precision,double precision,integer) Function sys.geography__stflipcoordinates(sys.geography) Function sys.geography__stgeomfromtext(text,integer) Function sys.geography__stpointfromtext(text,integer) +Function sys.geography_helper(bytea) Function sys.geometry(bytea) Function sys.geometry(point) +Function sys.geometry(sys.bbf_varbinary) Function sys.geometry(sys.geography) Function sys.geometry(sys.geometry,integer,boolean) Function sys.geometry(text) Function sys.geometry__point(double precision,double precision,integer) Function sys.geometry__stgeomfromtext(text,integer) Function sys.geometry__stpointfromtext(text,integer) +Function sys.geometry_helper(bytea) Function sys.geompoint_helper(double precision,double precision,integer) Function sys.get_current_full_xact_id() Function sys.get_host_os() +Function sys.get_valid_srids() Function sys.getdate() Function sys.getutcdate() Function sys.has_dbaccess(sys.sysname) @@ -620,6 +627,10 @@ Function sys.sqlvariant_tinyint(sys.sql_variant) Function sys.sqlvariant_uniqueidentifier(sys.sql_variant) Function sys.sqlvariant_varchar(sys.sql_variant) Function sys.square(double precision) +Function sys.st_geometrytype(sys.geography) +Function sys.st_geometrytype(sys.geometry) +Function sys.st_zmflag(sys.geography) +Function sys.st_zmflag(sys.geometry) Function sys.stasbinary_helper(sys.geography) Function sys.stastext_helper(sys.geography) Function sys.stdistance_helper(sys.geography,sys.geography) @@ -870,7 +881,6 @@ Operator sys.<>(smallint,sys.fixeddecimal) Operator sys.<>(sys."bit",integer) Operator sys.<>(sys."bit",sys."bit") Operator sys.<>(sys.bbf_binary,sys.bbf_binary) -Operator sys.<>(sys.bbf_varbinary,sys.bbf_varbinary) Operator sys.<>(sys.datetime,sys.datetime) Operator sys.<>(sys.datetime2,sys.datetime2) Operator sys.<>(sys.datetimeoffset,sys.datetimeoffset)