diff --git a/.github/scripts/scan-warnings.sh b/.github/scripts/scan-warnings.sh index 611cdf607eb..342e3fdfd36 100644 --- a/.github/scripts/scan-warnings.sh +++ b/.github/scripts/scan-warnings.sh @@ -49,7 +49,7 @@ if [[ "$SNAPSHOT_ACTIVE_COUNT" -ne 44 ]]; then ERROR_FOUND=true fi -if [[ "$LEAK_COUNT" -ne 324 ]]; then +if [[ "$LEAK_COUNT" -ne 350 ]]; then echo "Error: Expected 324 leak warnings, but found $LEAK_COUNT" ERROR_FOUND=true fi diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c index a55d38342a5..17199c67bc6 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c @@ -40,6 +40,8 @@ */ #define INT32_STRLEN 12 +#define VARCHAR_MAX_LEN 0x1F40 /* 8000 */ + /* For checking the invalid length parameters */ #define CheckForInvalidLength(temp) \ do \ @@ -1182,6 +1184,15 @@ GetSetColMetadataForCharType(ParameterToken temp, StringInfo message, uint8_t td return STATUS_ERROR; memcpy(&tempLen, &message->data[offset], sizeof(tempLen)); + + /* + * Technically maxLen can be 0 but since typmod of + * 0 is not supported in PG, we will translate it + * to max supported typmod of char based datatypes. + */ + if (tempLen == 0) + tempLen = VARCHAR_MAX_LEN; + temp->maxLen = tempLen; offset += sizeof(tempLen); memcpy(&collation, &message->data[offset], sizeof(collation)); diff --git a/contrib/babelfishpg_tds/src/backend/tds/tdsutils.c b/contrib/babelfishpg_tds/src/backend/tds/tdsutils.c index 5592c793064..49fbfdceb47 100644 --- a/contrib/babelfishpg_tds/src/backend/tds/tdsutils.c +++ b/contrib/babelfishpg_tds/src/backend/tds/tdsutils.c @@ -19,6 +19,7 @@ #include "access/genam.h" #include "access/htup_details.h" #include "access/table.h" +#include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_db_role_setting.h" #include "catalog/pg_database.h" @@ -35,6 +36,7 @@ #include "utils/syscache.h" #include "miscadmin.h" #include "utils/builtins.h" +#include "utils/catcache.h" static int FindMatchingParam(List *params, const char *name); static Node *TransformParamRef(ParseState *pstate, ParamRef *pref); @@ -937,8 +939,11 @@ check_babelfish_droprole_restrictions(char *role) * This function check the underlying assumption on the membership chain instead * sysadmin <-- dbo* <--- db_owner* <--- users/roles * + * A Babelfish login is a member of babelfish created user/role i.e., dbo, guest or user created user. + * * actual dbo and db_owner name varies across different babelfish logical databases */ + static bool is_babelfish_role(const char *role) { @@ -949,13 +954,16 @@ is_babelfish_role(const char *role) Oid bbf_msdb_guest_oid; Oid securityadmin; Oid dbcreator; + CatCList *memlist; + int i; + bool is_babelfish_login = false; sysadmin_oid = get_role_oid(BABELFISH_SYSADMIN, true); /* missing OK */ role_oid = get_role_oid(role, true); /* missing OK */ securityadmin = get_role_oid(BABELFISH_SECURITYADMIN, true); /* missing OK */ dbcreator = get_role_oid(BABELFISH_DBCREATOR, true); /* missing OK */ - if (!OidIsValid(sysadmin_oid) || !OidIsValid(role_oid) + if (!OidIsValid(sysadmin_oid) || !OidIsValid(role_oid) || !OidIsValid(securityadmin) || !OidIsValid(dbcreator)) return false; @@ -965,18 +973,37 @@ is_babelfish_role(const char *role) pg_strcasecmp(role, BABELFISH_ROLE_ADMIN) == 0) /* check if it is bbf_role_admin */ return true; + /* Most of the Babelfish logins would be a member of one of these guest roles.*/ bbf_master_guest_oid = get_role_oid("master_guest", true); bbf_tempdb_guest_oid = get_role_oid("tempdb_guest", true); bbf_msdb_guest_oid = get_role_oid("msdb_guest", true); - if (OidIsValid(bbf_master_guest_oid) - && OidIsValid(bbf_tempdb_guest_oid) - && OidIsValid(bbf_msdb_guest_oid) - && (is_member_of_role(role_oid, bbf_master_guest_oid) - || is_member_of_role(role_oid, bbf_tempdb_guest_oid) - || is_member_of_role(role_oid, bbf_msdb_guest_oid))) + if ((OidIsValid(bbf_master_guest_oid) && is_member_of_role(role_oid, bbf_master_guest_oid)) + || (OidIsValid(bbf_tempdb_guest_oid) && is_member_of_role(role_oid, bbf_tempdb_guest_oid)) + || (OidIsValid(bbf_msdb_guest_oid) && is_member_of_role(role_oid, bbf_msdb_guest_oid))) return true; - return false; + /* Check if it's a Babelfish login, if it's not a member of any guest role.*/ + memlist = SearchSysCacheList1(AUTHMEMMEMROLE, + ObjectIdGetDatum(role_oid)); + for (i = 0; i < memlist->n_members; i++) + { + HeapTuple tup = &memlist->members[i]->tuple; + Form_pg_auth_members form = (Form_pg_auth_members) GETSTRUCT(tup); + Oid parent_role_oid = form->roleid; + const char *parent_role_name = GetUserNameFromId(parent_role_oid, false); + + /* Check if the parent role is a Babelfish role */ + if (is_member_of_role(sysadmin_oid, parent_role_oid) || + is_member_of_role(securityadmin, parent_role_oid) || + is_member_of_role(dbcreator, parent_role_oid) || + pg_strcasecmp(parent_role_name, BABELFISH_ROLE_ADMIN) == 0) + { + is_babelfish_login = true; + break; + } + } + ReleaseSysCacheList(memlist); + return is_babelfish_login; } /* diff --git a/contrib/babelfishpg_tsql/runtime/functions.c b/contrib/babelfishpg_tsql/runtime/functions.c index 8842187dff0..1189a498937 100644 --- a/contrib/babelfishpg_tsql/runtime/functions.c +++ b/contrib/babelfishpg_tsql/runtime/functions.c @@ -2137,6 +2137,7 @@ object_id(PG_FUNCTION_ARGS) Oid user_id = GetUserId(); Oid result = InvalidOid; bool is_temp_object; + bool search_in_sys_for_sp_procs; int i; if (PG_ARGISNULL(0)) @@ -2244,6 +2245,9 @@ object_id(PG_FUNCTION_ARGS) * user don't have lookup access */ schema_oid = get_namespace_oid(physical_schema_name, true); + /* search in sys when proc name is sp_ prefixed and schema name is empty or dbo */ + search_in_sys_for_sp_procs = (OidIsValid(sys_schema_oid) && strncmp(object_name, "sp_", 3) == 0 && + (strcmp(schema_name, "dbo") == 0 || strlen(schema_name) == 0)); /* free unnecessary pointers */ pfree(db_name); @@ -2328,6 +2332,9 @@ object_id(PG_FUNCTION_ARGS) /* search in pg_proc by name and schema oid */ result = tsql_get_proc_oid(object_name, schema_oid, user_id); + + if (!OidIsValid(result) && search_in_sys_for_sp_procs) + result = tsql_get_proc_oid(object_name, sys_schema_oid, user_id); } else if (!strcmp(object_type, "tr") || !strcmp(object_type, "ta")) { @@ -2384,6 +2391,9 @@ object_id(PG_FUNCTION_ARGS) { /* search in pg_proc by name and schema oid */ result = tsql_get_proc_oid(object_name, schema_oid, user_id); + + if (!OidIsValid(result) && search_in_sys_for_sp_procs) + result = tsql_get_proc_oid(object_name, sys_schema_oid, user_id); } if (!OidIsValid(result)) diff --git a/contrib/babelfishpg_tsql/sql/ownership.sql b/contrib/babelfishpg_tsql/sql/ownership.sql index bc2ba789a09..b97adebfd70 100644 --- a/contrib/babelfishpg_tsql/sql/ownership.sql +++ b/contrib/babelfishpg_tsql/sql/ownership.sql @@ -178,54 +178,6 @@ BEGIN GRANT SELECT ON msdb_dbo.syspolicy_configuration TO PUBLIC; ALTER VIEW msdb_dbo.syspolicy_configuration OWNER TO sysadmin; - CREATE OR REPLACE PROCEDURE master_dbo.sp_addlinkedserver( IN "@server" sys.sysname, - IN "@srvproduct" sys.nvarchar(128) DEFAULT NULL, - IN "@provider" sys.nvarchar(128) DEFAULT 'SQLNCLI', - IN "@datasrc" sys.nvarchar(4000) DEFAULT NULL, - IN "@location" sys.nvarchar(4000) DEFAULT NULL, - IN "@provstr" sys.nvarchar(4000) DEFAULT NULL, - IN "@catalog" sys.sysname DEFAULT NULL) - AS 'babelfishpg_tsql', 'sp_addlinkedserver_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_addlinkedserver OWNER TO sysadmin; - - CREATE OR REPLACE PROCEDURE master_dbo.sp_addlinkedsrvlogin( IN "@rmtsrvname" sys.sysname, - IN "@useself" sys.varchar(8) DEFAULT 'TRUE', - IN "@locallogin" sys.sysname DEFAULT NULL, - IN "@rmtuser" sys.sysname DEFAULT NULL, - IN "@rmtpassword" sys.sysname DEFAULT NULL) - AS 'babelfishpg_tsql', 'sp_addlinkedsrvlogin_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_addlinkedsrvlogin OWNER TO sysadmin; - - CREATE OR REPLACE PROCEDURE master_dbo.sp_droplinkedsrvlogin( IN "@rmtsrvname" sys.sysname, - IN "@locallogin" sys.sysname) - AS 'babelfishpg_tsql', 'sp_droplinkedsrvlogin_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_droplinkedsrvlogin OWNER TO sysadmin; - - CREATE OR REPLACE PROCEDURE master_dbo.sp_dropserver( IN "@server" sys.sysname, - IN "@droplogins" sys.bpchar(10) DEFAULT NULL) - AS 'babelfishpg_tsql', 'sp_dropserver_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_dropserver OWNER TO sysadmin; - - CREATE OR REPLACE PROCEDURE master_dbo.sp_testlinkedserver( IN "@servername" sys.sysname) - AS 'babelfishpg_tsql', 'sp_testlinkedserver_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_testlinkedserver OWNER TO sysadmin; - - CREATE OR REPLACE PROCEDURE master_dbo.sp_enum_oledb_providers() - AS 'babelfishpg_tsql', 'sp_enum_oledb_providers_internal' - LANGUAGE C; - - ALTER PROCEDURE master_dbo.sp_enum_oledb_providers OWNER TO sysadmin; - -- let sysadmin only to update babelfish_domain_mapping GRANT ALL ON TABLE sys.babelfish_domain_mapping TO sysadmin; END diff --git a/contrib/babelfishpg_tsql/sql/sys_functions.sql b/contrib/babelfishpg_tsql/sql/sys_functions.sql index abb9560f89c..13ebdde412f 100644 --- a/contrib/babelfishpg_tsql/sql/sys_functions.sql +++ b/contrib/babelfishpg_tsql/sql/sys_functions.sql @@ -2395,7 +2395,7 @@ LANGUAGE C PARALLEL SAFE IMMUTABLE; CREATE OR REPLACE FUNCTION sys.db_id() RETURNS SMALLINT AS 'babelfishpg_tsql', 'babelfish_db_id' -LANGUAGE C PARALLEL SAFE IMMUTABLE; +LANGUAGE C PARALLEL SAFE STABLE; CREATE OR REPLACE FUNCTION sys.db_name(int) RETURNS sys.nvarchar(128) AS 'babelfishpg_tsql', 'babelfish_db_name' @@ -2403,7 +2403,7 @@ LANGUAGE C PARALLEL SAFE IMMUTABLE; CREATE OR REPLACE FUNCTION sys.db_name() RETURNS sys.nvarchar(128) AS 'babelfishpg_tsql', 'babelfish_db_name' -LANGUAGE C PARALLEL SAFE IMMUTABLE; +LANGUAGE C PARALLEL SAFE STABLE; CREATE OR REPLACE FUNCTION sys.exp(IN arg DOUBLE PRECISION) RETURNS DOUBLE PRECISION @@ -4126,6 +4126,24 @@ END $BODY$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE STRICT; +CREATE OR REPLACE FUNCTION sys.loginproperty(login_name sys.sysname, property_name sys.nvarchar(128)) +RETURNS sys.nvarchar(128) +AS $$ +DECLARE +BEGIN + RETURN NULL; +END; +$$ LANGUAGE plpgsql STABLE; + +CREATE OR REPLACE FUNCTION sys.fn_varbintohexsubstring(set_prefix INT, expression sys.varbinary(128), start_offset INT, length_to_return INT) +RETURNS sys.nvarchar(128) +AS $$ +DECLARE +BEGIN + RETURN NULL; +END; +$$ LANGUAGE plpgsql STABLE; + CREATE OR REPLACE FUNCTION objectproperty( id INT, property SYS.VARCHAR diff --git a/contrib/babelfishpg_tsql/sql/sys_views.sql b/contrib/babelfishpg_tsql/sql/sys_views.sql index d4c77ab42a6..0cbe6550247 100644 --- a/contrib/babelfishpg_tsql/sql/sys_views.sql +++ b/contrib/babelfishpg_tsql/sql/sys_views.sql @@ -3299,6 +3299,56 @@ JOIN pg_trigger pt ON pt.tgrelid = pc.oid AND tr.trigger_name = pt.tgname COLLAT AND has_table_privilege(pc.oid, 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE,TRIGGER'); GRANT SELECT ON sys.events TO PUBLIC; +CREATE OR REPLACE VIEW sys.server_permissions +AS +SELECT + CAST(0 as sys.tinyint) AS class, + CAST(NULL as sys.nvarchar(60)) AS class_desc, + CAST(NULL as INT) AS major_id, + CAST(NULL as INT) AS minor_id, + CAST(NULL as INT) AS grantee_principal_id, + CAST(NULL as INT) AS grantor_principal_id, + CAST(NULL as sys.BPCHAR(4)) AS type, + CAST(NULL as sys.nvarchar(128)) AS permission_name, + CAST(NULL as sys.BPCHAR(1)) AS state, + CAST(NULL as sys.nvarchar(60)) AS state_desc +WHERE FALSE; +GRANT SELECT ON sys.server_permissions TO PUBLIC; + +CREATE OR REPLACE VIEW sys.credentials +AS +SELECT + CAST(NULL as INT) AS credential_id, + CAST(NULL as sys.sysname) AS name, + CAST(NULL as sys.nvarchar(4000)) AS credential_identity, + CAST(NULL as sys.datetime) AS create_date, + CAST(NULL as sys.datetime) AS modify_date, + CAST(NULL as sys.nvarchar(100)) AS target_type, + CAST(NULL as INT) AS target_id +WHERE FALSE; +GRANT SELECT ON sys.credentials TO PUBLIC; + +CREATE VIEW sys.sql_logins AS +SELECT + CAST(NULL as sys.sysname) AS name, + CAST(NULL as INT) AS principal_id, + CAST(NULL as sys.VARBINARY(85)) AS sid, + CAST(NULL as sys.BPCHAR(1)) AS type, + CAST(NULL as sys.nvarchar(60)) AS type_desc, + CAST(NULL as INT) AS is_disabled, + CAST(NULL as sys.DATETIME) AS create_date, + CAST(NULL as sys.DATETIME) AS modify_date, + CAST(NULL as sys.sysname) AS default_database_name, + CAST(NULL as sys.sysname) AS default_language_name, + CAST(NULL as INT) AS credential_id, + CAST(NULL as INT) AS owning_principal_id, + CAST(0 as sys.BIT) AS is_fixed_role, + CAST(0 as sys.BIT) AS is_policy_checked, + CAST(0 as sys.BIT) AS is_expiration_checked, + CAST(NULL as sys.varbinary(256)) AS password_hash +WHERE FALSE; +GRANT SELECT ON sys.sql_logins TO PUBLIC; + CREATE OR REPLACE VIEW sys.trigger_events AS SELECT diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql index ed8abb9595e..fb578636653 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql @@ -375,8 +375,151 @@ BEGIN END END; $$; +CREATE OR REPLACE FUNCTION sys.db_id() RETURNS SMALLINT +AS 'babelfishpg_tsql', 'babelfish_db_id' +LANGUAGE C PARALLEL SAFE STABLE; + +CREATE OR REPLACE FUNCTION sys.db_name() RETURNS sys.nvarchar(128) +AS 'babelfishpg_tsql', 'babelfish_db_name' +LANGUAGE C PARALLEL SAFE STABLE; + + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_addlinkedserver; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_addlinkedsrvlogin; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_droplinkedsrvlogin; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_dropserver; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_testlinkedserver; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; + +DO $$ +BEGIN + BEGIN + DROP PROCEDURE master_dbo.sp_enum_oledb_providers; + EXCEPTION + WHEN OTHERS THEN + raise NOTICE '%', SQLERRM; + END; +END; +$$; -- After upgrade, always run analyze for all babelfish catalogs. CALL sys.analyze_babelfish_catalogs(); -- Reset search_path to not affect any subsequent scripts SELECT set_config('search_path', trim(leading 'sys, ' from current_setting('search_path')), false); + +CREATE OR REPLACE FUNCTION sys.loginproperty(login_name sys.sysname, property_name sys.nvarchar(128)) +RETURNS sys.nvarchar(128) +AS $$ +DECLARE +BEGIN + RETURN NULL; +END; +$$ LANGUAGE plpgsql STABLE; + +CREATE OR REPLACE FUNCTION sys.fn_varbintohexsubstring(set_prefix INT, expression sys.varbinary(128), start_offset INT, length_to_return INT) +RETURNS sys.nvarchar(128) +AS $$ +DECLARE +BEGIN + RETURN NULL; +END; +$$ LANGUAGE plpgsql STABLE; + +CREATE OR REPLACE VIEW sys.server_permissions +AS +SELECT + CAST(0 as sys.tinyint) AS class, + CAST(NULL as sys.nvarchar(60)) AS class_desc, + CAST(NULL as INT) AS major_id, + CAST(NULL as INT) AS minor_id, + CAST(NULL as INT) AS grantee_principal_id, + CAST(NULL as INT) AS grantor_principal_id, + CAST(NULL as sys.BPCHAR(4)) AS type, + CAST(NULL as sys.nvarchar(128)) AS permission_name, + CAST(NULL as sys.BPCHAR(1)) AS state, + CAST(NULL as sys.nvarchar(60)) AS state_desc +WHERE FALSE; +GRANT SELECT ON sys.server_permissions TO PUBLIC; + +CREATE OR REPLACE VIEW sys.credentials +AS +SELECT + CAST(NULL as INT) AS credential_id, + CAST(NULL as sys.sysname) AS name, + CAST(NULL as sys.nvarchar(4000)) AS credential_identity, + CAST(NULL as sys.datetime) AS create_date, + CAST(NULL as sys.datetime) AS modify_date, + CAST(NULL as sys.nvarchar(100)) AS target_type, + CAST(NULL as INT) AS target_id +WHERE FALSE; +GRANT SELECT ON sys.credentials TO PUBLIC; + +CREATE VIEW sys.sql_logins AS +SELECT + CAST(NULL as sys.sysname) AS name, + CAST(NULL as INT) AS principal_id, + CAST(NULL as sys.VARBINARY(85)) AS sid, + CAST(NULL as sys.BPCHAR(1)) AS type, + CAST(NULL as sys.nvarchar(60)) AS type_desc, + CAST(NULL as INT) AS is_disabled, + CAST(NULL as sys.DATETIME) AS create_date, + CAST(NULL as sys.DATETIME) AS modify_date, + CAST(NULL as sys.sysname) AS default_database_name, + CAST(NULL as sys.sysname) AS default_language_name, + CAST(NULL as INT) AS credential_id, + CAST(NULL as INT) AS owning_principal_id, + CAST(0 as sys.BIT) AS is_fixed_role, + CAST(0 as sys.BIT) AS is_policy_checked, + CAST(0 as sys.BIT) AS is_expiration_checked, + CAST(NULL as sys.varbinary(256)) AS password_hash +WHERE FALSE; +GRANT SELECT ON sys.sql_logins TO PUBLIC; + diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index d4372ae9ee3..03e48a85e71 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -73,6 +73,7 @@ Oid bbf_authid_login_ext_idx_oid; *****************************************/ Oid bbf_authid_user_ext_oid; Oid bbf_authid_user_ext_idx_oid; +Oid bbf_authid_user_ext_login_dbname_idx_oid; /***************************************** * VIEW_DEF @@ -912,6 +913,16 @@ get_authid_user_ext_idx_oid(void) return bbf_authid_user_ext_idx_oid; } +Oid +get_bbf_authid_user_ext_login_dbname_idx_oid(void) +{ + if (!OidIsValid(bbf_authid_user_ext_login_dbname_idx_oid)) + bbf_authid_user_ext_login_dbname_idx_oid = get_relname_relid(BBF_AUTHID_USER_EXT_LOGIN_DB_NAME_IDX_NAME, + get_namespace_oid("sys", false)); + + return bbf_authid_user_ext_login_dbname_idx_oid; +} + /* Returns palloc'd original name given the physical name of the db principal */ char * get_authid_user_ext_original_name(const char *physical_role_name, const char *db_name, bool suppress_error) @@ -960,7 +971,7 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) { Relation bbf_authid_user_ext_rel; HeapTuple tuple_user_ext; - TableScanDesc scan; + SysScanDesc scan; char *user_name = NULL; NameData *login_name; ScanKeyData key[2]; @@ -978,13 +989,20 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) Anum_bbf_authid_user_ext_login_name, BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(login_name)); - ScanKeyInit(&key[1], - Anum_bbf_authid_user_ext_database_name, - BTEqualStrategyNumber, F_TEXTEQ, - CStringGetTextDatum(db_name)); - scan = table_beginscan_catalog(bbf_authid_user_ext_rel, 2, key); - - tuple_user_ext = heap_getnext(scan, ForwardScanDirection); + ScanKeyEntryInitialize(&key[1], + 0, + Anum_bbf_authid_user_ext_database_name, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_database_or_server_collation_oid_internal(false), + F_TEXTEQ, + CStringGetTextDatum(db_name)); + + scan = systable_beginscan(bbf_authid_user_ext_rel, + get_bbf_authid_user_ext_login_dbname_idx_oid(), + true, NULL, 2, key); + + tuple_user_ext = systable_getnext(scan); if (HeapTupleIsValid(tuple_user_ext)) { Form_authid_user_ext userform; @@ -993,7 +1011,7 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) user_name = pstrdup(NameStr(userform->rolname)); } - table_endscan(scan); + systable_endscan(scan); table_close(bbf_authid_user_ext_rel, RowExclusiveLock); return user_name; @@ -1002,47 +1020,33 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) char * get_authid_user_ext_schema_name(const char *db_name, const char *user) { - Relation bbf_authid_user_ext_rel; HeapTuple tuple_user_ext; - ScanKeyData key[2]; - TableScanDesc scan; char *schema_name = NULL; - NameData *user_name; if (!db_name || !user) return NULL; - bbf_authid_user_ext_rel = table_open(get_authid_user_ext_oid(), - RowExclusiveLock); + tuple_user_ext = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(user)); - user_name = (NameData *) palloc0(NAMEDATALEN); - snprintf(user_name->data, NAMEDATALEN, "%s", user); - ScanKeyInit(&key[0], - Anum_bbf_authid_user_ext_rolname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(user_name)); - ScanKeyInit(&key[1], - Anum_bbf_authid_user_ext_database_name, - BTEqualStrategyNumber, F_TEXTEQ, - CStringGetTextDatum(db_name)); - - scan = table_beginscan_catalog(bbf_authid_user_ext_rel, 2, key); - - tuple_user_ext = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tuple_user_ext)) { - Datum datum; - bool is_null; - - datum = heap_getattr(tuple_user_ext, - Anum_bbf_authid_user_ext_default_schema_name, - bbf_authid_user_ext_rel->rd_att, - &is_null); - schema_name = pstrdup(TextDatumGetCString(datum)); - } + Datum datum = SysCacheGetAttrNotNull(AUTHIDUSEREXTROLENAME, tuple_user_ext, + Anum_bbf_authid_user_ext_database_name); + char *db_name_cstring = TextDatumGetCString(datum); - table_endscan(scan); - table_close(bbf_authid_user_ext_rel, RowExclusiveLock); + if (strcmp(db_name_cstring, db_name) == 0) + { + Datum schema_datum = SysCacheGetAttrNotNull(AUTHIDUSEREXTROLENAME, tuple_user_ext, + Anum_bbf_authid_user_ext_default_schema_name); + char *default_schema_name = TextDatumGetCString(schema_datum); + + if (strlen(default_schema_name)) + schema_name = default_schema_name; + } + + pfree(db_name_cstring); + ReleaseSysCache(tuple_user_ext); + } return schema_name; } diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index f51b3fc0cea..2dd49e7fd35 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -139,6 +139,7 @@ extern Oid get_authid_login_ext_idx_oid(void); *****************************************/ #define BBF_AUTHID_USER_EXT_TABLE_NAME "babelfish_authid_user_ext" #define BBF_AUTHID_USER_EXT_IDX_NAME "babelfish_authid_user_ext_pkey" +#define BBF_AUTHID_USER_EXT_LOGIN_DB_NAME_IDX_NAME "babelfish_authid_user_ext_login_db_idx" #define Anum_bbf_authid_user_ext_rolname 1 #define Anum_bbf_authid_user_ext_login_name 2 #define Anum_bbf_authid_user_ext_orig_username 11 @@ -153,6 +154,7 @@ extern Oid bbf_authid_user_ext_idx_oid; const int get_db_principal_kind(Oid role_oid, const char *db_name); extern Oid get_authid_user_ext_oid(void); extern Oid get_authid_user_ext_idx_oid(void); +extern Oid get_bbf_authid_user_ext_login_dbname_idx_oid(void); extern char *get_authid_user_ext_original_name(const char *physical_role_name, const char *db_name, bool suppress_error); extern char *get_authid_user_ext_physical_name(const char *db_name, const char *login_name); extern char *get_authid_user_ext_schema_name(const char *db_name, const char *user_name); diff --git a/contrib/babelfishpg_tsql/src/collation.c b/contrib/babelfishpg_tsql/src/collation.c index 3ed0bcf7d0e..44bda8ecdf8 100644 --- a/contrib/babelfishpg_tsql/src/collation.c +++ b/contrib/babelfishpg_tsql/src/collation.c @@ -1835,7 +1835,7 @@ set_db_collation_internal(const char *db_name) Oid database_collation_oid; /* Get collation oid corresponding to collation name */ - database_collation_oid = get_collation_oid(list_make1(makeString((char*)get_collation_name_for_db(db_name))), false); + database_collation_oid = get_collation_oid(list_make2(makeString("sys"), makeString((char*)get_collation_name_for_db(db_name))), false); if (!OidIsValid(database_collation_oid)) ereport(ERROR, diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index f66a359dd5f..cf99f0ff4c2 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -99,6 +99,12 @@ typedef enum PltsqlInitPrivsOptions ERROR_INIT_PRIVS } PltsqlInitPrivsOptions; +/***************************************** + * General Hooks + *****************************************/ + +static bool is_bbf_tds_connection(void); + /***************************************** * Catalog Hooks *****************************************/ @@ -188,7 +194,6 @@ static bool pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event); static bool plsql_TriggerRecursiveCheck(ResultRelInfo *resultRelInfo); static bool bbf_check_rowcount_hook(int es_processed); -static char *get_local_schema_for_bbf_functions(Oid proc_nsp_oid); extern bool called_from_tsql_insert_exec(); extern bool called_for_tsql_itvf_func(); static void is_function_pg_stat_valid(FunctionCallInfo fcinfo, @@ -290,7 +295,6 @@ static table_variable_satisfies_update_hook_type prev_table_variable_satisfies_u static table_variable_satisfies_vacuum_hook_type prev_table_variable_satisfies_vacuum = NULL; static table_variable_satisfies_vacuum_horizon_hook_type prev_table_variable_satisfies_vacuum_horizon = NULL; static drop_relation_refcnt_hook_type prev_drop_relation_refcnt_hook = NULL; -static set_local_schema_for_func_hook_type prev_set_local_schema_for_func_hook = NULL; static bbf_get_sysadmin_oid_hook_type prev_bbf_get_sysadmin_oid_hook = NULL; static get_bbf_admin_oid_hook_type prev_get_bbf_admin_oid_hook = NULL; static transform_pivot_clause_hook_type pre_transform_pivot_clause_hook = NULL; @@ -474,9 +478,6 @@ InstallExtendedHooks(void) prev_drop_relation_refcnt_hook = drop_relation_refcnt_hook; drop_relation_refcnt_hook = pltsql_drop_relation_refcnt_hook; - prev_set_local_schema_for_func_hook = set_local_schema_for_func_hook; - set_local_schema_for_func_hook = get_local_schema_for_bbf_functions; - prev_bbf_get_sysadmin_oid_hook = bbf_get_sysadmin_oid_hook; bbf_get_sysadmin_oid_hook = get_sysadmin_oid; @@ -534,6 +535,8 @@ InstallExtendedHooks(void) is_bbf_db_ddladmin_operation_hook = is_bbf_db_ddladmin_operation; pltsql_allow_storing_init_privs_hook = allow_storing_init_privs; + + is_bbf_tds_connection_hook = is_bbf_tds_connection; } void @@ -590,7 +593,6 @@ UninstallExtendedHooks(void) IsToastRelationHook = PrevIsToastRelationHook; IsToastClassHook = PrevIsToastClassHook; drop_relation_refcnt_hook = prev_drop_relation_refcnt_hook; - set_local_schema_for_func_hook = prev_set_local_schema_for_func_hook; bbf_get_sysadmin_oid_hook = prev_bbf_get_sysadmin_oid_hook; get_bbf_admin_oid_hook = prev_get_bbf_admin_oid_hook; transform_pivot_clause_hook = pre_transform_pivot_clause_hook; @@ -613,6 +615,7 @@ UninstallExtendedHooks(void) handle_default_collation_hook = NULL; pltsql_get_object_identity_event_trigger_hook = NULL; pltsql_allow_storing_init_privs_hook = NULL; + is_bbf_tds_connection_hook = NULL; } /***************************************** @@ -5099,37 +5102,6 @@ sort_nulls_first(SortGroupClause * sortcl, bool reverse) } } - -static char * -get_local_schema_for_bbf_functions(Oid proc_nsp_oid) -{ - HeapTuple tuple; - char *func_schema_name = NULL, - *new_search_path = NULL; - char *func_dbo_schema; - const char *cur_dbname = get_cur_db_name(); - - tuple = SearchSysCache1(NAMESPACEOID, - ObjectIdGetDatum(proc_nsp_oid)); - if(HeapTupleIsValid(tuple)) - { - func_schema_name = NameStr(((Form_pg_namespace) GETSTRUCT(tuple))->nspname); - func_dbo_schema = get_dbo_schema_name(cur_dbname); - - if(strcmp(func_schema_name, func_dbo_schema) != 0 - && strcmp(func_schema_name, "sys") != 0) - new_search_path = psprintf("%s, %s, \"$user\", sys, pg_catalog", - quote_identifier(func_schema_name), - quote_identifier(func_dbo_schema)); - - ReleaseSysCache(tuple); - - pfree(func_dbo_schema); - } - - return new_search_path; -} - static ResTarget * make_restarget_from_cstr_list(List * l) { @@ -6048,4 +6020,11 @@ remove_db_name_in_schema(const char *object_name, const char *object_type) pfree(splited_object_name); return (const char *)pstrdup(object_name + prefix_len); -} \ No newline at end of file +} + +/* Check if current connection is a tds connection */ +static bool +is_bbf_tds_connection(void) +{ + return IS_TDS_CONN(); +} diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index 4329580cb55..4e78ba7f95d 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -26,6 +26,7 @@ static void restore_ctx_full(PLtsql_execstate *estate); static ErrorData *restore_ctx_partial1(PLtsql_execstate *estate); static void restore_ctx_partial2(PLtsql_execstate *estate); static void set_exec_error_data(char *procedure, int number, int severity, int state, bool rethrow); +static void set_search_path_for_pltsql_stmt(PLtsql_execstate *estate, PLtsql_stmt *stmt); static void reset_exec_error_data(PLtsql_execstate *estate); static void assert_equal_estate_err(PLtsql_estate_err *err1, PLtsql_estate_err *err2); static void read_raiserror_params(PLtsql_execstate *estate, List *params, int paramno, @@ -46,6 +47,7 @@ extern PLtsql_estate_err *pltsql_clone_estate_err(PLtsql_estate_err *err); extern void prepare_format_string(StringInfo buf, char *msg_string, int nargs, Datum *args, Oid *argtypes, bool *argisnull); + static int exec_stmt_goto(PLtsql_execstate *estate, PLtsql_stmt_goto *stmt) { @@ -645,6 +647,8 @@ dispatch_stmt(PLtsql_execstate *estate, PLtsql_stmt *stmt) /* reset number of tuple processed in previous command */ estate->eval_processed = 0; + set_search_path_for_pltsql_stmt(estate, stmt); + switch (stmt->cmd_type) { case PLTSQL_STMT_ASSIGN: @@ -2184,3 +2188,91 @@ send_env_change_token_on_txn_abort(void) if (*pltsql_protocol_plugin_ptr && (*pltsql_protocol_plugin_ptr)->send_env_change_binary) ((*pltsql_protocol_plugin_ptr)->send_env_change_binary) (ENVCHANGE_ROLLBACKTXN, NULL, 0, &txnId, sizeof(uint64_t)); } + +/* + * We will keep verifying the search path is correct + * before executing any pltsql statement + */ +static void +set_search_path_for_pltsql_stmt(PLtsql_execstate *estate, PLtsql_stmt *stmt) +{ + char *cur_dbname; + char *new_search_path = NULL; + char *pltsql_func_search_path = NULL; + const char *current_db_search_path; + + Assert(stmt != NULL); + + if (!IS_TDS_CONN() || IsInParallelMode() || stmt->cmd_type == PLTSQL_STMT_USEDB) + return; + + cur_dbname = get_cur_db_name(); + current_db_search_path = get_current_db_search_path(); + pltsql_func_search_path = estate->func->fn_search_path; + + if (stmt->cmd_type == PLTSQL_STMT_EXECSQL) + { + PLtsql_stmt_execsql *execsqlstmt = (PLtsql_stmt_execsql *)stmt; + + if (execsqlstmt->is_create_view && execsqlstmt->schema_name != NULL && strcmp(execsqlstmt->schema_name, "sys") != 0 + && strcmp(execsqlstmt->schema_name, "pg_catalog") != 0) + { + char *physical_schema = get_physical_schema_name(cur_dbname, execsqlstmt->schema_name); + char *dbo_schema = get_dbo_schema_name(cur_dbname); + + new_search_path = psprintf(PLTSQL_SEARCH_PATH_BUFFER, quote_identifier(physical_schema), quote_identifier(dbo_schema)); + + pfree(physical_schema); + pfree(dbo_schema); + } + else if (execsqlstmt->is_ddl) + { + new_search_path = pstrdup(current_db_search_path); + } + } + else if (stmt->cmd_type == PLTSQL_STMT_EXEC) + { + PLtsql_stmt_exec *execstmt = (PLtsql_stmt_exec *)stmt; + + if (strncmp(execstmt->proc_name, "sp_", 3) == 0 && + (execstmt->schema_name == NULL || strcmp(execstmt->schema_name, "dbo") == 0)) + { + /* handled in exec_stmt_exec() */ + } + else if (execstmt->db_name != NULL && strcmp(execstmt->db_name, cur_dbname) != 0 && + execstmt->schema_name != NULL && strcmp(execstmt->schema_name, "sys") == 0) + { + /* handled in exec_stmt_exec() */ + } + else + { + new_search_path = pstrdup(current_db_search_path); + } + } + + if (new_search_path == NULL) + { + if (pltsql_func_search_path) + new_search_path = pstrdup(pltsql_func_search_path); + else if (current_db_search_path) + new_search_path = pstrdup(current_db_search_path); + } + + PG_TRY(); + { + pltsql_check_search_path = false; + + if (new_search_path && strcmp(new_search_path, namespace_search_path) != 0) + { + SetConfigOption("search_path", new_search_path, + PGC_SUSET, PGC_S_SESSION); + pfree(new_search_path); + } + } + PG_FINALLY(); + { + pltsql_check_search_path = true; + pfree(cur_dbname); + } + PG_END_TRY(); +} diff --git a/contrib/babelfishpg_tsql/src/pl_comp.c b/contrib/babelfishpg_tsql/src/pl_comp.c index 7ccc2380fe0..d3491b4e82c 100644 --- a/contrib/babelfishpg_tsql/src/pl_comp.c +++ b/contrib/babelfishpg_tsql/src/pl_comp.c @@ -42,6 +42,7 @@ #include "pltsql.h" #include "pltsql-2.h" #include "analyzer.h" +#include "catalog.h" #include "codegen.h" #include "iterative_exec.h" #include "multidb.h" @@ -147,6 +148,7 @@ static void delete_function(PLtsql_function *func); extern Portal ActivePortal; extern bool pltsql_function_parse_error_transpose(const char *prosrc); +static char *get_local_schema_for_bbf_functions(Oid proc_nsp_oid, int16 dbid); /* ---------- * pltsql_compile Make an execution tree for a PL/tsql function. @@ -967,6 +969,18 @@ do_compile(FunctionCallInfo fcinfo, for (i = 0; i < function->fn_nargs; i++) function->fn_argvarnos[i] = in_arg_varnos[i]; + /* store the logical db which contains this function */ + if (IS_TDS_CONN() && procStruct->provolatile != PROVOLATILE_IMMUTABLE && procStruct->proparallel == PROPARALLEL_UNSAFE) + { + function->fn_dbid = get_dbid_from_physical_schema_name(get_namespace_name(procStruct->pronamespace), true); + function->fn_search_path = get_local_schema_for_bbf_functions(procStruct->pronamespace, function->fn_dbid); + } + else + { + function->fn_dbid = InvalidDbid; + function->fn_search_path = NULL; + } + pltsql_finish_datums(function); /* Debug dump for completed functions */ @@ -1112,6 +1126,8 @@ pltsql_compile_inline(char *proc_source, InlineCodeBlockArgs *args) function->fn_retbyval = true; function->fn_rettyplen = sizeof(int32); function->fn_tupdesc = NULL; + function->fn_dbid = InvalidDbid; + function->fn_search_path = NULL; /* * Remember if function is STABLE/IMMUTABLE. XXX would it be better to @@ -3252,3 +3268,34 @@ reset_cached_batch() delete_cached_batch(cur_handle_id--); cur_handle_id = 1; } + +static char * +get_local_schema_for_bbf_functions(Oid proc_nsp_oid, int16 dbid) +{ + HeapTuple tuple; + char *func_schema_name = NULL, + *new_search_path = NULL; + char *func_dbo_schema; + + if (!IS_TDS_CONN() || !DbidIsValid(dbid)) + return NULL; + + tuple = SearchSysCache1(NAMESPACEOID, + ObjectIdGetDatum(proc_nsp_oid)); + if(HeapTupleIsValid(tuple)) + { + func_schema_name = get_namespace_name(proc_nsp_oid); + func_dbo_schema = get_dbo_schema_name(get_db_name(dbid)); + + new_search_path = psprintf(PLTSQL_SEARCH_PATH_BUFFER, + quote_identifier(func_schema_name), + quote_identifier(func_dbo_schema)); + + ReleaseSysCache(tuple); + + pfree(func_schema_name); + pfree(func_dbo_schema); + } + + return new_search_path; +} diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 30bddbcce17..629df3ac6fc 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -30,6 +30,7 @@ #include "parser/scansup.h" #include "parser/parse_oper.h" #include "src/include/lib/qunique.h" +#include "utils/varlena.h" /* helper function to get current T-SQL estate */ PLtsql_execstate *get_current_tsql_estate(void); @@ -135,6 +136,7 @@ static Node *get_underlying_node_from_implicit_casting(Node *n, NodeTag underlyi /* Enclose a user-defined @@var or @var# name in delimiters */ static char *delimit_tsql_atatuservar(const char *src); +static void set_search_path_for_sp_procs(char *schema); /* * The pltsql_proc_return_code global variable is used to record the @@ -835,57 +837,11 @@ exec_stmt_exec(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt) volatile int rc; SimpleEcontextStackEntry *topEntry; SPIExecuteOptions options; - bool need_path_reset = false; + char *save_db_name = get_cur_db_name(); - char *cur_dbname = get_cur_db_name(); - - /* fetch current search_path */ - char *old_search_path = NULL; - char *new_search_path; - /* whether procedure was created WITH RECOMPILE */ bool created_with_recompile = false; - estate->db_name = NULL; - if (stmt->proc_name == NULL) - stmt->proc_name = ""; - - if (stmt->is_cross_db) - { - estate->db_name = stmt->db_name; - } - - /* - * "sp_describe_first_result_set" needs special handling. It is a sys - * function and satisfies the below condition and it appends "master_dbo" - * to the search path which is not required for sys functions. - */ - if (strcmp(stmt->proc_name, "sp_describe_first_result_set") != 0) - { - if (strncmp(stmt->proc_name, "sp_", 3) == 0 && strcmp(cur_dbname, "master") != 0 - && ((stmt->schema_name == NULL || stmt->schema_name[0] == (char) '\0') || strcmp(stmt->schema_name, "dbo") == 0)) - { - if (!old_search_path) - { - List *path_oids = fetch_search_path(false); - - old_search_path = flatten_search_path(path_oids); - list_free(path_oids); - } - new_search_path = psprintf("%s, master_dbo", old_search_path); - - /* Add master_dbo to the new search path */ - (void) set_config_option("search_path", new_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - need_path_reset = true; - } - } - if (stmt->schema_name != NULL && stmt->schema_name[0] != (char) '\0') - estate->schema_name = stmt->schema_name; - else - estate->schema_name = NULL; - /* * We need to disable the explain gucs incase of sp_reset_connection * execution otherwise we will get explain output for it which is @@ -913,6 +869,28 @@ exec_stmt_exec(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt) Tuplestorestate *tss; DestReceiver *dest; + if (IS_TDS_CONN()) + { + if (strncmp(stmt->proc_name, "sp_", 3) == 0 && + (stmt->schema_name == NULL || strcmp(stmt->schema_name, "dbo") == 0)) + { + + if (stmt->db_name != NULL) + set_cur_user_db_and_path(stmt->db_name, false); + + set_search_path_for_sp_procs(stmt->schema_name); + } + else if (stmt->db_name != NULL && strcmp(stmt->db_name, save_db_name) != 0 && + stmt->schema_name != NULL && strcmp(stmt->schema_name, "sys") == 0) + { + /* + * For sys pltsql routines and sp_ procs switch to + * the database specified while calling it. + */ + set_cur_user_db_and_path(stmt->db_name, false); + } + } + if (plan == NULL) plan = prepare_stmt_exec(estate, estate->func, stmt, estate->atomic); @@ -1290,20 +1268,12 @@ exec_stmt_exec(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt) dest->rDestroy(dest); } } - PG_CATCH(); + PG_FINALLY(); { - if (need_path_reset) - { - /* - * Note: there is no test case to validate restoring the search_path below. - * In fact, we don't know whether this restore is even required, since removing the - * call set_config_option("search_path") does not cause any test cases to fail. - * Nevertheless we're keeping the code out of an abundance of caution. - */ - (void) set_config_option("search_path", old_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - } + if (strcmp(get_current_pltsql_db_name(), save_db_name) != 0) + set_cur_user_db_and_path(save_db_name, false); + + pfree(save_db_name); /* * If we aren't saving the plan, unset the pointer. Note that it @@ -1316,31 +1286,9 @@ exec_stmt_exec(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt) expr->plan = NULL; SPI_freeplan(plan); } - PG_RE_THROW(); } PG_END_TRY(); - if (need_path_reset) - { - /* - * Note: there is no test case to validate restoring the search_path below. - * In fact, we don't know whether this restore is even required, since removing the - * call set_config_option("search_path") does not cause any test cases to fail. - * Nevertheless we're keeping the code out of an abundance of caution. - */ - (void) set_config_option("search_path", old_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - } - - if (expr->plan && !expr->plan->saved) - { - SPIPlanPtr plan = expr->plan; - - expr->plan = NULL; - SPI_freeplan(plan); - } - if (rc < 0) elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s", expr->query, SPI_result_code_string(rc)); @@ -1585,7 +1533,7 @@ exec_stmt_exec_batch(PLtsql_execstate *estate, PLtsql_stmt_exec_batch *stmt) cur_db_name = get_cur_db_name(); if (strcmp(cur_db_name, old_db_name) != 0) - set_session_properties(old_db_name); + set_cur_user_db_and_path(old_db_name, false); } PG_END_TRY(); @@ -3109,11 +3057,7 @@ exec_stmt_usedb(PLtsql_execstate *estate, PLtsql_stmt_usedb *stmt) "\"%s\" is probably undergoing DDL statements in another session.", stmt->db_name, stmt->db_name))); - /* - * Same as set_session_properties() but skips checks as they were done - * before locking - */ - set_cur_user_db_and_path(stmt->db_name); + set_cur_user_db_and_path(stmt->db_name, false); top_es_entry = exec_state_call_stack->next; while (top_es_entry != NULL) @@ -3186,7 +3130,7 @@ exec_stmt_usedb_explain(PLtsql_execstate *estate, PLtsql_stmt_usedb *stmt, bool /* error if new db is not valid and restore original db */ if (!DbidIsValid(new_db_id)) { - set_session_properties(initial_database_name); + set_cur_user_db_and_path(initial_database_name, true); ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", stmt->db_name))); @@ -3213,7 +3157,7 @@ exec_stmt_usedb_explain(PLtsql_execstate *estate, PLtsql_stmt_usedb *stmt, bool "\"%s\" is probably undergoing DDL statements in another session.", stmt->db_name, stmt->db_name))); - set_cur_user_db_and_path(stmt->db_name); + set_cur_user_db_and_path(stmt->db_name, false); return PLTSQL_RC_OK; } @@ -4654,3 +4598,23 @@ exec_stmt_partition_scheme(PLtsql_execstate *estate, PLtsql_stmt_partition_schem CommandCounterIncrement(); return PLTSQL_RC_OK; } + +static void +set_search_path_for_sp_procs(char *schema) +{ + char *dbo_schema = get_dbo_schema_name(get_current_pltsql_db_name()); + char *new_search_path; + + if (schema != NULL && strcmp(schema, "dbo") == 0) + new_search_path = psprintf("%s, sys, pg_catalog, %s", + quote_identifier(dbo_schema), "master_dbo"); + else + new_search_path = psprintf("%s, sys, pg_catalog, %s", + get_current_db_search_path(), "master_dbo"); + + SetConfigOption("search_path", new_search_path, + PGC_SUSET, PGC_S_SESSION); + + pfree(new_search_path); + pfree(dbo_schema); +} diff --git a/contrib/babelfishpg_tsql/src/pl_exec.c b/contrib/babelfishpg_tsql/src/pl_exec.c index f1133ce86e6..e6f83284c93 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec.c +++ b/contrib/babelfishpg_tsql/src/pl_exec.c @@ -466,7 +466,6 @@ static void pltsql_clean_table_variables(PLtsql_execstate *estate, PLtsql_functi static void pltsql_init_exec_error_data(PLtsqlErrorData *error_data); static void pltsql_copy_exec_error_data(PLtsqlErrorData *src, PLtsqlErrorData *dst, MemoryContext dstCxt); PLtsql_estate_err *pltsql_clone_estate_err(PLtsql_estate_err *err); -static bool reset_search_path(PLtsql_stmt_execsql *stmt, char **old_search_path, bool *reset_session_properties, bool inside_trigger); extern void pltsql_init_anonymous_cursors(PLtsql_execstate *estate); extern void pltsql_cleanup_local_cursors(PLtsql_execstate *estate); @@ -4625,42 +4624,22 @@ exec_stmt_execsql(PLtsql_execstate *estate, bool enable_txn_in_triggers = !pltsql_disable_txn_in_triggers; bool support_tsql_trans = pltsql_support_tsql_transactions(); StringInfoData query; - bool need_path_reset = false; char *cur_dbname = get_cur_db_name(); - bool reset_session_properties = false; - bool inside_trigger = false; - - /* fetch current search_path */ - char *old_search_path = NULL; + bool is_cross_db = stmt->is_cross_db && stmt->db_name && strcmp(cur_dbname, stmt->db_name) != 0; bool ro_func = (estate->func->fn_prokind == PROKIND_FUNCTION) && (estate->func->fn_is_trigger == PLTSQL_NOT_TRIGGER) && (strcmp(estate->func->fn_signature, "inline_code_block") != 0); original_query_string = stmt->original_query ? stmt->original_query : NULL; - if (stmt->is_cross_db) + if (is_cross_db) { - if (stmt->insert_exec) - { - estate->db_name = stmt->db_name; - } - /* * When there is cross db reference to sys or information_schema * schemas, Change the session property. */ if (stmt->schema_name != NULL && (strcmp(stmt->schema_name, "sys") == 0 || strcmp(stmt->schema_name, "information_schema") == 0)) - set_session_properties(stmt->db_name); - } - if (stmt->is_dml || stmt->is_ddl || stmt->is_create_view) - { - if (stmt->is_schema_specified) - estate->schema_name = stmt->schema_name; - else - estate->schema_name = NULL; - if (estate->trigdata) - inside_trigger = true; - need_path_reset = reset_search_path(stmt, &old_search_path, &reset_session_properties, inside_trigger); + set_cur_user_db_and_path(stmt->db_name, true); } PG_TRY(); @@ -4670,14 +4649,10 @@ exec_stmt_execsql(PLtsql_execstate *estate, { int ret = exec_stmt_insert_execute_select(estate, expr); - if (reset_session_properties) - { - set_session_properties(cur_dbname); - } - else if (stmt->is_cross_db) + if (is_cross_db) { if (stmt->schema_name != NULL && (strcmp(stmt->schema_name, "sys") == 0 || strcmp(stmt->schema_name, "information_schema") == 0)) - set_session_properties(cur_dbname); + set_cur_user_db_and_path(cur_dbname, true); } return ret; } @@ -5076,18 +5051,10 @@ exec_stmt_execsql(PLtsql_execstate *estate, { original_query_string = NULL; - if (need_path_reset) - (void) set_config_option("search_path", old_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - if (reset_session_properties) - { - set_session_properties(cur_dbname); - } - else if (stmt->is_cross_db) + if (is_cross_db) { if (stmt->schema_name != NULL && (strcmp(stmt->schema_name, "sys") == 0 || strcmp(stmt->schema_name, "information_schema") == 0)) - set_session_properties(cur_dbname); + set_cur_user_db_and_path(cur_dbname, true); } pfree(cur_dbname); @@ -10280,175 +10247,6 @@ pltsql_clone_estate_err(PLtsql_estate_err *err) return clone; } -static bool -reset_search_path(PLtsql_stmt_execsql *stmt, char **old_search_path, bool *reset_session_properties, bool inside_trigger) -{ - PLExecStateCallStack *top_es_entry; - char *cur_dbname = get_cur_db_name(); - char *new_search_path; - char *physical_schema; - char *dbo_schema = NULL; - - top_es_entry = exec_state_call_stack->next; - - while (top_es_entry != NULL) - { - /* - * Traverse through the estate stack. If the occurrence of exec in the - * call stack, update the search path accordingly. - */ - if (top_es_entry->estate && top_es_entry->estate->err_stmt && - (top_es_entry->estate->err_stmt->cmd_type == PLTSQL_STMT_EXEC || - (top_es_entry->estate->err_stmt->cmd_type == PLTSQL_STMT_EXECSQL && - ((PLtsql_stmt_execsql*)top_es_entry->estate->err_stmt)->insert_exec && - ((PLtsql_stmt_execsql*)top_es_entry->estate->err_stmt)->is_cross_db) - )) - { - if (top_es_entry->estate->schema_name != NULL && stmt->is_dml) - { - if (top_es_entry->estate->db_name == NULL) - { - /* - * Don't change the search path, if the statement inside - * the procedure is a function or schema qualified. - */ - if (stmt->func_call || stmt->is_schema_specified) - break; - else - { - physical_schema = get_physical_schema_name(cur_dbname, top_es_entry->estate->schema_name); - dbo_schema = get_dbo_schema_name(cur_dbname); - } - } - else - { - if (stmt->func_call || stmt->is_schema_specified) - { - set_session_properties(top_es_entry->estate->db_name); - *reset_session_properties = true; - break; - } - else - { - physical_schema = get_physical_schema_name((char *) top_es_entry->estate->db_name, top_es_entry->estate->schema_name); - dbo_schema = get_dbo_schema_name(top_es_entry->estate->db_name); - } - } - if (!*old_search_path) - { - List *path_oids = fetch_search_path(false); - - *old_search_path = flatten_search_path(path_oids); - list_free(path_oids); - } - new_search_path = psprintf("%s, %s, %s", quote_identifier(physical_schema), quote_identifier(dbo_schema), *old_search_path); - - pfree(physical_schema); - /* - * Add the schema where the object is referenced and dbo - * schema to the new search path - */ - (void) set_config_option("search_path", new_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - - pfree(new_search_path); - pfree(dbo_schema); - - return true; - } - else if (top_es_entry->estate->db_name != NULL && stmt->is_ddl) - { - set_session_properties(top_es_entry->estate->db_name); - *reset_session_properties = true; - break; - } - } - /* if the stmt is inside an exec_batch, return false */ - else if (top_es_entry->estate && top_es_entry->estate->err_stmt && - top_es_entry->estate->err_stmt->cmd_type == PLTSQL_STMT_EXEC_BATCH) - return false; - - /* - * Traverse through the estate stack, if the stmt is inside trigger we - * set the search path accordingly. - */ - else if (top_es_entry->estate && top_es_entry->estate->err_stmt && - top_es_entry->estate->err_stmt->cmd_type == PLTSQL_STMT_EXECSQL) - { - if (inside_trigger && top_es_entry->estate->schema_name) - { - /* - * If the object in the stmt is schema qualified or it's a ddl - * we don't need to update the searh path. - */ - if (stmt->is_schema_specified || stmt->is_ddl) - return false; - else - { - physical_schema = get_physical_schema_name(cur_dbname, top_es_entry->estate->schema_name); - dbo_schema = get_dbo_schema_name(cur_dbname); - if (!*old_search_path) - { - List *path_oids = fetch_search_path(false); - - *old_search_path = flatten_search_path(path_oids); - list_free(path_oids); - } - new_search_path = psprintf("%s, %s, %s", quote_identifier(physical_schema), quote_identifier(dbo_schema), *old_search_path); - - pfree(physical_schema); - /* - * Add the schema where the object is referenced and dbo - * schema to the new search path - */ - (void) set_config_option("search_path", new_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - pfree(new_search_path); - pfree(dbo_schema); - - return true; - } - } - } - top_es_entry = top_es_entry->next; - } - - if (stmt->is_create_view && stmt->schema_name != NULL && (strcmp(stmt->schema_name, "sys") != 0 - && strcmp(stmt->schema_name, "pg_catalog") != 0)) - { - cur_dbname = get_cur_db_name(); - physical_schema = get_physical_schema_name(cur_dbname, stmt->schema_name); - dbo_schema = get_dbo_schema_name(cur_dbname); - if (!*old_search_path) - { - List *path_oids = fetch_search_path(false); - - *old_search_path = flatten_search_path(path_oids); - list_free(path_oids); - } - new_search_path = psprintf("%s, %s, %s", quote_identifier(physical_schema), quote_identifier(dbo_schema), *old_search_path); - - pfree(physical_schema); - /* - * Add the schema where the object is referenced and dbo schema to the - * new search path - */ - (void) set_config_option("search_path", new_search_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); - pfree(new_search_path); - pfree(dbo_schema); - - return true; - } - - pfree(cur_dbname); - - return false; -} - /* * Get the original_query_string which stores the original query. */ diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index dd6ba56a012..4b1e7d0ba08 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -48,6 +48,7 @@ #include "nodes/pg_list.h" #include "parser/analyze.h" #include "parser/parser.h" +#include "parser/parsetree.h" #include "parser/parse_clause.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" @@ -3609,7 +3610,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } PG_END_TRY(); - set_session_properties(db_name); + set_cur_user_db_and_path(db_name, true); pfree(db_name); return; @@ -5515,6 +5516,8 @@ pltsql_call_handler(PG_FUNCTION_ARGS) int saved_dialect = sql_dialect; int current_spi_stack_depth; bool send_error = false; + char *saved_search_path = MemoryContextStrdup(TopMemoryContext, namespace_search_path); + int16 saved_dbid = get_cur_db_id(); create_queryEnv2(CacheMemoryContext, false); @@ -5572,6 +5575,10 @@ pltsql_call_handler(PG_FUNCTION_ARGS) { set_procid(func->fn_oid); + /* for cross db func/proc calls switch to that db */ + if (DbidIsValid(func->fn_dbid) && get_cur_db_id() != func->fn_dbid) + set_cur_user_db_and_path(get_db_name(func->fn_dbid), false); + /* * Determine if called as function or trigger and call appropriate * subhandler @@ -5606,7 +5613,7 @@ pltsql_call_handler(PG_FUNCTION_ARGS) { set_procid(prev_procid); pltsql_trigger_depth = save_pltsql_trigger_depth; - + send_error = true; } PG_END_TRY(2); @@ -5619,10 +5626,23 @@ pltsql_call_handler(PG_FUNCTION_ARGS) pltsql_remove_current_query_env(); pltsql_revert_guc(save_nestlevel); pltsql_revert_last_scope_identity(scope_level); + + /* reset db context must always be the last line in this block */ + if (get_cur_db_id() != saved_dbid) + set_cur_user_db_and_path(get_db_name((saved_dbid)), false); + if (saved_search_path != NULL && strcmp(saved_search_path, namespace_search_path) != 0 + && !IsAbortedTransactionBlockState()) + { + pltsql_check_search_path = false; + SetConfigOption("search_path", saved_search_path, + PGC_SUSET, PGC_S_SESSION); + } + pfree(saved_search_path); } PG_FINALLY(); { sql_dialect = saved_dialect; + pltsql_check_search_path = true; /* If func is NULL then we have encountered a parser error. */ if (!func) @@ -6724,15 +6744,51 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) { Query *q = (Query *)n; bool seen_identity = false; + bool ordinality_changed = false; AttrNumber current_resno = 0; Index identity_ressortgroupref = 0; List *modifiedTargetList = NIL; + bool persist_identity = true; + + /* + * In T-SQL, identity property of column in destination + * table is not persisted if the SELECT ... INTO statement + * does not contain a single base relation + */ + if (q->jointree && q->jointree->fromlist != NIL) + { + if (list_length(q->jointree->fromlist) > 1) + persist_identity = false; + else + { + Node *n_from = (Node *) linitial(q->jointree->fromlist); + + if (!IsA(n_from, RangeTblRef)) + persist_identity = false; + else + { + RangeTblRef *rtr = (RangeTblRef *) n_from; + RangeTblEntry *rte = rt_fetch(rtr->rtindex, q->rtable); + + /* Do not persist identity if not an ordinary relation */ + if (rte->rtekind != RTE_RELATION) + persist_identity = false; + } + } + } + + altstmt = makeNode(AlterTableStmt); + altstmt->relation = into->rel; + altstmt->objtype = OBJECT_TABLE; + altstmt->cmds = NIL; + foreach (elements, q->targetList) { TargetEntry *tle = (TargetEntry *)lfirst(elements); if(tle->resname != NULL && !tle->resjunk) tle->resname = downcase_identifier(tle->resname, strlen(tle->resname), false, false); + if (tle->expr && IsA(tle->expr, FuncExpr) && strcasecmp(get_func_name(((FuncExpr *)(tle->expr))->funcid), "identity_into_bigint") == 0) { FuncExpr *funcexpr; @@ -6786,18 +6842,15 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) } seen_identity = true; + ordinality_changed = true; identity_ressortgroupref = tle->ressortgroupref; /** Save this Index to modify sortClause and distinctClause*/ /** Add alter table add identity node after Select Into statement */ - altstmt = makeNode(AlterTableStmt); - altstmt->relation = into->rel; - altstmt->objtype = OBJECT_TABLE; - altstmt->cmds = NIL; - constraint = makeNode(Constraint); constraint->contype = CONSTR_IDENTITY; constraint->generated_when = ATTRIBUTE_IDENTITY_ALWAYS; constraint->options = seqoptions; + constraint->location = -1; def = makeNode(ColumnDef); def->colname = tle->resname; @@ -6812,6 +6865,61 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) lcmd->def = (Node *)def; altstmt->cmds = lappend(altstmt->cmds, lcmd); } + else if (tle->expr && IsA(tle->expr, Var) && OidIsValid(tle->resorigtbl)) + { + HeapTuple attrtup = SearchSysCacheAttNum(tle->resorigtbl, tle->resorigcol); + + if (HeapTupleIsValid(attrtup)) + { + AlterTableCmd *lcmd; + Form_pg_attribute attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup); + + if (attrStruct->attnotnull) + { + /* + * Add ALTER TABLE ... ALTER COLUMN ... SET NOT NULL + * after SELECT INTO statement + */ + lcmd = makeNode(AlterTableCmd); + lcmd->subtype = AT_SetNotNull; + lcmd->name = tle->resname; + altstmt->cmds = lappend(altstmt->cmds, lcmd); + } + + if (attrStruct->attidentity && persist_identity) + { + Constraint *constraint; + + if (seen_identity) + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Attempting to add multiple identity columns to table \"%s\" using the SELECT INTO statement.", into->rel->relname))); + + seen_identity = true; + + constraint = makeNode(Constraint); + constraint->contype = CONSTR_IDENTITY; + constraint->generated_when = attrStruct->attidentity; + constraint->options = sequence_options(get_table_identity(tle->resorigtbl)); + constraint->location = -1; + + /* + * Add ALTER TABLE ... ALTER COLUMN ... after SELECT INTO + * statement where the column is made an IDENTITY column + */ + lcmd = makeNode(AlterTableCmd); + lcmd->subtype = AT_AddIdentity; + lcmd->name = tle->resname; + lcmd->def = (Node *) constraint; + altstmt->cmds = lappend(altstmt->cmds, lcmd); + } + + current_resno += 1; + tle->resno = current_resno; + modifiedTargetList = lappend(modifiedTargetList, tle); + + ReleaseSysCache(attrtup); + } + } else { current_resno += 1; @@ -6821,7 +6929,7 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) } q->targetList = modifiedTargetList; - if (seen_identity) + if (ordinality_changed) { if (q->sortClause) { @@ -6846,7 +6954,7 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) } result = lappend(result, stmt); - if (altstmt) + if (altstmt && list_length(altstmt->cmds) > 0) result = lappend(result, altstmt); return result; diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index 08388706afa..d781c37dea1 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1166,12 +1166,9 @@ typedef struct PLtsql_stmt_execsql * SELECT @a=1) */ bool insert_exec; /* INSERT-EXEC stmt? */ bool is_cross_db; /* cross database reference */ - bool is_dml; /* DML statement? */ bool is_ddl; /* DDL statement? */ - bool func_call; /* Function call? */ char *schema_name; /* Schema specified */ char *db_name; /* db_name: only for cross db query */ - bool is_schema_specified; /* is schema name specified? */ bool is_create_view; /* CREATE VIEW? */ bool is_set_tran_isolation; /* SET TRANSACTION ISOLATION? */ char *original_query; /* Only for batch level statement. */ @@ -1306,6 +1303,8 @@ typedef struct PLtsql_function int fetch_status_varno; int new_varno; int old_varno; + int16 fn_dbid; /* logical db which contains the function */ + char *fn_search_path; TupleDesc fn_tupdesc; /* tuple descriptor for return info */ @@ -1537,8 +1536,6 @@ typedef struct PLtsql_execstate bool insert_exec; List *explain_infos; - char *schema_name; - const char *db_name; instr_time planning_start; instr_time planning_end; instr_time execution_start; @@ -2025,6 +2022,8 @@ extern bool insert_bulk_check_constraints; * Function declarations **********************************************************************/ +# define PLTSQL_SEARCH_PATH_BUFFER "%s, %s, sys, pg_catalog" + /* * Functions in pl_comp.c */ @@ -2227,7 +2226,6 @@ extern bool TryLockLogicalDatabaseForSession(int16 dbid, LOCKMODE lockmode); extern void UnlockLogicalDatabaseForSession(int16 dbid, LOCKMODE lockmode, bool force); extern char *bpchar_to_cstring(const BpChar *bpchar); extern char *varchar_to_cstring(const VarChar *varchar); -extern char *flatten_search_path(List *oid_list); extern char *get_pltsql_function_signature_internal(const char *funcname, int nargs, const Oid *argtypes); extern void report_info_or_warning(int elevel, char *message); extern void init_and_check_common_utility(void); @@ -2332,6 +2330,7 @@ extern void pltsql_nextval_identity(Oid seqid, int64 val); extern void pltsql_resetcache_identity(void); extern int64 pltsql_setval_identity(Oid seqid, int64 val, int64 last_val); extern int64 last_scope_identity_value(void); +extern Oid get_table_identity(Oid tableOid); /* * Functions in linked_servers.c diff --git a/contrib/babelfishpg_tsql/src/pltsql_identity.c b/contrib/babelfishpg_tsql/src/pltsql_identity.c index 4300d105032..2cc89567dfa 100644 --- a/contrib/babelfishpg_tsql/src/pltsql_identity.c +++ b/contrib/babelfishpg_tsql/src/pltsql_identity.c @@ -55,7 +55,7 @@ static HTAB *seqhashtabidentity = NULL; static SeqTableIdentityData *last_used_seq_identity = NULL; -static Oid get_table_identity(Oid tableOid); +Oid get_table_identity(Oid tableOid); static ScopeIdentityStack *last_used_scope_seq_identity = NULL; static int PltsqlScopeIdentityNestLevel = 0; @@ -217,7 +217,7 @@ get_identity_current(PG_FUNCTION_ARGS) /* * Get the table's identity sequence OID. */ -static Oid +Oid get_table_identity(Oid tableOid) { Relation rel; diff --git a/contrib/babelfishpg_tsql/src/pltsql_utils.c b/contrib/babelfishpg_tsql/src/pltsql_utils.c index c5ab5fe3e6e..7be620c391f 100644 --- a/contrib/babelfishpg_tsql/src/pltsql_utils.c +++ b/contrib/babelfishpg_tsql/src/pltsql_utils.c @@ -1292,29 +1292,6 @@ varchar_to_cstring(const VarChar *varchar) return result; } -/* - * Convert list of schema OIDs to schema names. - */ - -char * -flatten_search_path(List *oid_list) -{ - StringInfoData pathbuf; - ListCell *lc; - - initStringInfo(&pathbuf); - - foreach(lc, oid_list) - { - Oid schema_oid = lfirst_oid(lc); - char *schema_name = get_namespace_name(schema_oid); - - appendStringInfo(&pathbuf, " %s,", quote_identifier(schema_name)); - } - pathbuf.data[strlen(pathbuf.data) - 1] = '\0'; - return pathbuf.data; -} - char * get_pltsql_function_signature_internal(const char *funcname, int nargs, const Oid *argtypes) diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index fab72ba38e9..a6ffb65b8fd 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -1856,9 +1856,10 @@ sp_execute_postgresql(PG_FUNCTION_ARGS) PlannedStmt *wrapper; const char *saved_dialect = GetConfigOption("babelfishpg_tsql.sql_dialect", true, true); Oid current_user_id = GetUserId(); - const char *saved_path = pstrdup(GetConfigOption("search_path", true, true)); const char *new_path = "public, \"$user\", sys, pg_catalog"; + int save_nestlevel; + save_nestlevel = NewGUCNestLevel(); PG_TRY(); { set_config_option("babelfishpg_tsql.sql_dialect", "postgres", @@ -2067,12 +2068,10 @@ sp_execute_postgresql(PG_FUNCTION_ARGS) set_config_option("babelfishpg_tsql.sql_dialect", saved_dialect, GUC_CONTEXT_CONFIG, PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - set_config_option("search_path", saved_path, - PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0, false); SetCurrentRoleId(current_user_id, false); } + AtEOXact_GUC(false, save_nestlevel); PG_END_TRY(); PG_RETURN_VOID(); } diff --git a/contrib/babelfishpg_tsql/src/session.c b/contrib/babelfishpg_tsql/src/session.c index d1367275e5c..b32718d922e 100644 --- a/contrib/babelfishpg_tsql/src/session.c +++ b/contrib/babelfishpg_tsql/src/session.c @@ -29,6 +29,8 @@ static int16 current_db_id = 0; static char current_db_name[MAX_BBF_NAMEDATALEND + 1] = {'\0'}; static Oid current_user_id = InvalidOid; +/* search path for current active logical database */ +static char *current_db_search_path = NULL; static void set_search_path_for_user_schema(const char *db_name, const char *user); void reset_cached_batch(void); @@ -66,6 +68,17 @@ get_current_pltsql_db_name(void) return current_db_name; } +/* + * Get search path corresponding to current active logical database + * Only valid for TDS connections + */ +const char * +get_current_db_search_path(void) +{ + Assert(IS_TDS_CONN() && current_db_search_path != NULL); + return current_db_search_path; +} + void set_cur_db_name_for_parallel_worker(const char* logical_db_name) { @@ -118,21 +131,6 @@ bbf_set_current_user(const char *user_name) SetCurrentRoleId(userid, false); } -void -set_session_properties(const char *db_name) -{ - int16 db_id = get_db_id(db_name); - - if (!DbidIsValid(db_id)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%s\" does not exist", db_name))); - - check_session_db_access(db_name); - - set_cur_user_db_and_path(db_name); -} - /* * Raises an error if the current session does not have access to the given database * Caller responsible for checking db_name is valid @@ -156,13 +154,27 @@ check_session_db_access(const char *db_name) } } -/* Caller responsible for checking db_name is valid */ void -set_cur_user_db_and_path(const char *db_name) +set_cur_user_db_and_path(const char *db_name, bool check_db_id) { const char *user = get_user_for_database(db_name); int16 db_id = get_db_id(db_name); + if (check_db_id && !DbidIsValid(db_id)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", db_name))); + + if (!user) + { + char *login = GetUserNameFromId(GetSessionUserId(), false); + 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, db_name))); + } + /* set current DB */ set_cur_db(db_id, db_name); @@ -180,41 +192,46 @@ set_cur_user_db_and_path(const char *db_name) static void set_search_path_for_user_schema(const char *db_name, const char *user) { - const char *path; - const char *buffer = "%s, \"$user\", sys, pg_catalog"; - char *physical_schema; - char *dbo_role_name = get_dbo_role_name(db_name); - char *guest_role_name = get_guest_role_name(db_name); + char *path; + char *db_name_copy = pstrdup(db_name); + char *schema; + char *physical_schema = NULL; + char *dbo_schema_name = get_dbo_schema_name(db_name); - if ((dbo_role_name && strcmp(user, dbo_role_name) == 0)) - { - physical_schema = get_dbo_schema_name(db_name); - } - else if (guest_role_name && strcmp(user, guest_role_name) == 0) - { - const char *guest_schema = get_authid_user_ext_schema_name(db_name, "guest"); + Assert (db_name != NULL && strlen(db_name) > 0); - if (!guest_schema) - guest_schema = "guest"; - physical_schema = get_physical_schema_name(pstrdup(db_name), guest_schema); - } - else + schema = get_authid_user_ext_schema_name(db_name, user); + if (schema) { - const char *schema; - - schema = get_authid_user_ext_schema_name(db_name, user); - physical_schema = get_physical_schema_name(pstrdup(db_name), schema); + physical_schema = get_physical_schema_name(db_name_copy, schema); + pfree(schema); } - - path = psprintf(buffer, quote_identifier(physical_schema)); - SetConfigOption("search_path", - path, - PGC_SUSET, - PGC_S_DATABASE_USER); + path = psprintf(PLTSQL_SEARCH_PATH_BUFFER, + physical_schema ? quote_identifier(physical_schema) : quote_identifier(dbo_schema_name), + quote_identifier(dbo_schema_name)); + + if (current_db_search_path) + pfree(current_db_search_path); + current_db_search_path = MemoryContextStrdup(TopMemoryContext, path); + + /* set search path default so transaction rollback does not affect it */ + SetConfigOption("search_path", path, + PGC_SUSET, PGC_S_SESSION); + /* + * Incase of error inside parallel worker we could reach here before transaction + * abort. Do not try to set_config since it will fail inside a parallel worker + * This function is used in code path where error is never expected + */ + if (!IsAbortedTransactionBlockState()) + SetConfigOption("search_path", path, + PGC_SUSET, PGC_S_DATABASE_USER); - pfree(dbo_role_name); - pfree(guest_role_name); - pfree(physical_schema); + pfree(path); + pfree(dbo_schema_name); + pfree(db_name_copy); + + if (physical_schema) + pfree(physical_schema); } /* diff --git a/contrib/babelfishpg_tsql/src/session.h b/contrib/babelfishpg_tsql/src/session.h index 82f58e3bd9e..e4c88bf3652 100644 --- a/contrib/babelfishpg_tsql/src/session.h +++ b/contrib/babelfishpg_tsql/src/session.h @@ -8,10 +8,10 @@ extern int16 get_cur_db_id(void); extern void set_cur_db(int16 id, const char *name); extern char *get_cur_db_name(void); extern const char *get_current_pltsql_db_name(void); +extern const char *get_current_db_search_path(void); extern void bbf_set_current_user(const char *user_name); -extern void set_session_properties(const char *db_name); extern void check_session_db_access(const char *dn_name); -extern void set_cur_user_db_and_path(const char *db_name); +extern void set_cur_user_db_and_path(const char *db_name, bool check_db_id); extern void restore_session_properties(void); extern void reset_session_properties(void); extern void set_cur_db_name_for_parallel_worker(const char* logical_db_name); diff --git a/contrib/babelfishpg_tsql/src/tsqlIface.cpp b/contrib/babelfishpg_tsql/src/tsqlIface.cpp index 51a03fc4439..69b55ea7021 100644 --- a/contrib/babelfishpg_tsql/src/tsqlIface.cpp +++ b/contrib/babelfishpg_tsql/src/tsqlIface.cpp @@ -1420,8 +1420,6 @@ class tsqlBuilder : public tsqlCommonMutator bool is_cross_db = false; std::string schema_name; std::string db_name; - bool is_function = false; - bool is_schema_specified = false; bool in_func_body_return_select_body = false; // We keep a stack of the containers that are active during a traversal. @@ -1908,11 +1906,10 @@ class tsqlBuilder : public tsqlCommonMutator if (ctx_name->database) { db_name = stripQuoteFromId(ctx_name->database); - if (!string_matches(db_name.c_str(), get_cur_db_name())) - { - is_cross_db = true; - } + is_cross_db = true; } + if (ctx_name->schema) + schema_name = stripQuoteFromId(ctx_name->schema); } } @@ -1922,20 +1919,12 @@ class tsqlBuilder : public tsqlCommonMutator stmt->is_cross_db = true; is_cross_db = false; } - // record that the stmt is dml - stmt->is_dml = true; - // record if a function call - if (is_function) - stmt->func_call = true; if (!schema_name.empty()) stmt->schema_name = pstrdup(downcase_truncate_identifier(schema_name.c_str(), schema_name.length(), true)); // record db name for the cross db query if (!db_name.empty()) stmt->db_name = pstrdup(downcase_truncate_identifier(db_name.c_str(), db_name.length(), true)); - // record if the SQL object is schema qualified - if (is_schema_specified) - stmt->is_schema_specified = true; if (is_compiling_create_function()) { @@ -2670,10 +2659,7 @@ class tsqlBuilder : public tsqlCommonMutator if (ctx && (ctx->DOT().size() <= 2) && ctx->schema) { schema_name = stripQuoteFromId(ctx->schema); - is_schema_specified = true; } - else - is_schema_specified = false; // The flag setSysSchema is used exclusively in case of rewriting a cross-DB catalog reference // that uses 'dbo' as schema: this puts 'sys' in tsqlBuilder::schema_name, which ends up @@ -2743,7 +2729,6 @@ class tsqlBuilder : public tsqlCommonMutator void exitFunction_call(TSqlParser::Function_callContext *ctx) override { - is_function = true; if (ctx->NEXT() && ctx->full_object_name()) { TSqlParser::Full_object_nameContext *fctx = (TSqlParser::Full_object_nameContext *) ctx->full_object_name(); @@ -6814,7 +6799,6 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) std::string proc_name; std::string db_name; std::string name; - bool is_cross_db = false; int lineno = getLineNo(ctx); int return_code_dno = -1; std::string execKeywd = "EXEC"; // DO NOT CHANGE! @@ -6877,12 +6861,8 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) if (ctx_name->database) { db_name = stripQuoteFromId(ctx_name->database); - if (!string_matches(db_name.c_str(), get_cur_db_name())) - { - is_cross_db = true; - } } - + if (ctx_name->schema) { schema_name = stripQuoteFromId(ctx_name->schema); @@ -6895,32 +6875,26 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) // Note: previous code performed rewriting here for procedure names with leading dots (EXEC ..proc1) // This is now performed in exitFunc_proc_name_server_database_schema() which is called via the mutator (previously, it wasn't). - - // For sp_* procs, truncate proc name to sp_* if the schema is "dbo" or "sys" or has leading dots - // ToDo: handle 'EXEC mydb..sp_proc' where sp_proc gets executed in the context of 'mydb', even when the current DB is not 'mydb' - if ((pg_strncasecmp(name.c_str(), "..dbo.sp_", 9) == 0) || (pg_strncasecmp(name.c_str(), "..sys.sp_", 9) == 0)) - { - name.erase(name.begin() + 0, name.begin() + 6); - } - else if ((pg_strncasecmp(name.c_str(), ".dbo.sp_", 8) == 0) || (pg_strncasecmp(name.c_str(), ".sys.sp_", 8) == 0)) - { - name.erase(name.begin() + 0, name.begin() + 5); - } - else if ((pg_strncasecmp(name.c_str(), "dbo.sp_", 7) == 0) || (pg_strncasecmp(name.c_str(), "sys.sp_", 7) == 0)) - { - name.erase(name.begin() + 0, name.begin() + 4); - } - else if (pg_strncasecmp(name.c_str(), ".sp_", 4) == 0) - { - name.erase(name.begin() + 0, name.begin() + 1); - } - else if (pg_strncasecmp(name.c_str(), "..sp_", 5) == 0) + + if ((!proc_name.empty() && pg_strncasecmp(proc_name.c_str(), "sp_", 3) == 0) && + (schema_name.empty() || pg_strcasecmp(schema_name.c_str(), "dbo") == 0)) { - name.erase(name.begin() + 0, name.begin() + 2); + /* + * For sp_ prefixed procedures remove database and schema portion if schema name is empty or dbo + * We do this because db.dbo.sp_proc should be searched in sys and master.dbo schema as well + */ + name.replace(name.begin(), name.end(), proc_name); + name_length = proc_name.length(); } - else if (pg_strncasecmp(name.c_str(), "...sp_", 6) == 0) + else if (is_sp_proc(proc_name) && !schema_name.empty() && pg_strcasecmp(schema_name.c_str(), "sys") == 0) { - name.erase(name.begin() + 0, name.begin() + 3); + /* + * These sys.sp_procs do not actually exists in sys schema + * We handle them as different statement in iterative executor + * so only keep the proc name and discard everything else + */ + name.replace(name.begin(), name.end(), proc_name); + name_length = proc_name.length(); } } @@ -6958,7 +6932,6 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) result->return_code_dno = return_code_dno; result->paramno = 0; result->params = NIL; - result->is_cross_db = is_cross_db; // Record whether this is a cross-db call result->exec_with_recompile = exec_with_recompile; // Handle name parts @@ -6966,6 +6939,8 @@ makeExecuteProcedure(ParserRuleContext *ctx, std::string call_type) { result->proc_name = pstrdup(downcase_truncate_identifier(proc_name.c_str(), proc_name.length(), true)); } + else + result->proc_name = pstrdup(""); if (!schema_name.empty()) { result->schema_name = pstrdup(downcase_truncate_identifier(schema_name.c_str(), schema_name.length(), true)); diff --git a/test/JDBC/expected/BABEL-1444-vu-verify.out b/test/JDBC/expected/BABEL-1444-vu-verify.out index a46b1f87ec3..2996b49da6c 100644 --- a/test/JDBC/expected/BABEL-1444-vu-verify.out +++ b/test/JDBC/expected/BABEL-1444-vu-verify.out @@ -45,7 +45,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -77,7 +77,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -babel_1444_db1_dbo, "$user", sys, pg_catalog +babel_1444_db1_dbo, babel_1444_db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -114,7 +114,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -babel_1444_db1_dbo, "$user", sys, pg_catalog +babel_1444_db1_dbo, babel_1444_db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -147,7 +147,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -179,7 +179,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -212,7 +212,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; diff --git a/test/JDBC/expected/BABEL-1444.out b/test/JDBC/expected/BABEL-1444.out index 9821b95dbe6..d79177e59b3 100644 --- a/test/JDBC/expected/BABEL-1444.out +++ b/test/JDBC/expected/BABEL-1444.out @@ -73,7 +73,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -105,7 +105,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -142,7 +142,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -175,7 +175,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -207,7 +207,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -240,7 +240,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -278,7 +278,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -310,7 +310,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -347,7 +347,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -380,7 +380,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -412,7 +412,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -445,7 +445,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; diff --git a/test/JDBC/expected/BABEL-CROSS-DB-vu-cleanup.out b/test/JDBC/expected/BABEL-CROSS-DB-vu-cleanup.out index 867c5cdcf83..13ae31cd78f 100644 --- a/test/JDBC/expected/BABEL-CROSS-DB-vu-cleanup.out +++ b/test/JDBC/expected/BABEL-CROSS-DB-vu-cleanup.out @@ -140,3 +140,9 @@ GO DROP SCHEMA babel_cross_db_vu_prepare_myschema GO + +DROP PROCEDURE babel_5448_p02, babel_5448_p01 +GO + +DROP PROC sp_test_babel_5448_1, sp_test_babel_5448_2 +GO diff --git a/test/JDBC/expected/BABEL-CROSS-DB-vu-prepare.out b/test/JDBC/expected/BABEL-CROSS-DB-vu-prepare.out index 5a9cf7047e0..70ca3a3a2ef 100644 --- a/test/JDBC/expected/BABEL-CROSS-DB-vu-prepare.out +++ b/test/JDBC/expected/BABEL-CROSS-DB-vu-prepare.out @@ -279,3 +279,76 @@ GO GRANT SELECT ON babel_cross_db_vu_prepare_t4 TO guest; GO + +------------------ BABEL-5448 ------------------ +------------------------------------------------ +USE master; +GO + +CREATE PROCEDURE dbo.babel_5448_p01 AS +BEGIN + SELECT 'This is correct datbase dbname = master'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p02 AS +BEGIN + EXECUTE dbo.babel_5448_p01; -- schema.proc + EXECUTE master.dbo.babel_5448_p01; -- db.schema.proc + EXECUTE master..babel_5448_p01; -- db..proc + EXECUTE babel_5448_p01; -- proc +END; +GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +CREATE PROCEDURE dbo.babel_5448_p01 AS +BEGIN + SELECT 'This is the incorrect database: dbname = my_babel_cross_db_vu_prepare_db1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p03 AS +BEGIN + EXECUTE master.dbo.babel_5448_p02; +END; +GO + + +------------------------------------------------ +--------------- sp_proc cross db --------------- +------------------------------------------------ +USE master; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is correct: master.dbo.sp_test_babel_5448_1' +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_2 AS +BEGIN +EXECUTE master..sp_test_babel_5448_1; +EXECUTE sp_test_babel_5448_1; +EXECUTE dbo.sp_test_babel_5448_1; +EXECUTE master.dbo.sp_test_babel_5448_1; +END; +GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is the incorrect database: my_babel_cross_db_vu_prepare_db1.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_3 AS +BEGIN +EXECUTE master.dbo.sp_test_babel_5448_2; +END; +GO + diff --git a/test/JDBC/expected/BABEL-CROSS-DB-vu-verify.out b/test/JDBC/expected/BABEL-CROSS-DB-vu-verify.out index 93c9c832689..40188f80050 100644 --- a/test/JDBC/expected/BABEL-CROSS-DB-vu-verify.out +++ b/test/JDBC/expected/BABEL-CROSS-DB-vu-verify.out @@ -1921,3 +1921,59 @@ GO -- [TESTCASE GROUP END] Batches for testing default_database and default_schema setting USE master GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +EXECUTE dbo.babel_5448_p03; +GO +~~START~~ +varchar +This is correct datbase dbname = master +~~END~~ + +~~START~~ +varchar +This is correct datbase dbname = master +~~END~~ + +~~START~~ +varchar +This is correct datbase dbname = master +~~END~~ + +~~START~~ +varchar +This is correct datbase dbname = master +~~END~~ + + +SELECT db_name() +GO +~~START~~ +nvarchar +my_babel_cross_db_vu_prepare_db1 +~~END~~ + +EXECUTE dbo.sp_test_babel_5448_3; +GO +~~START~~ +nvarchar +This is correct: master.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: master.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: master.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: master.dbo.sp_test_babel_5448_1 +~~END~~ + diff --git a/test/JDBC/expected/BABEL-CROSS-DB.out b/test/JDBC/expected/BABEL-CROSS-DB.out index 39e9e149174..246a2659462 100644 --- a/test/JDBC/expected/BABEL-CROSS-DB.out +++ b/test/JDBC/expected/BABEL-CROSS-DB.out @@ -1003,3 +1003,136 @@ GO DROP DATABASE db2; GO + +------------------ BABEL-5448 ------------------ +------------------------------------------------ +USE master; +GO + +CREATE DATABASE babel_5448_db1; +GO +CREATE DATABASE babel_5448_db2; +GO + +USE babel_5448_db1 +GO + +CREATE PROCEDURE dbo.babel_5448_p1 AS +BEGIN + SELECT 'This is correct: babel_5448_db1.dbo.babel_5448_p1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p2 AS +BEGIN + EXECUTE dbo.babel_5448_p1; -- schema.proc + EXECUTE babel_5448_db1.dbo.babel_5448_p1; -- db.schema.proc + EXECUTE babel_5448_db1..babel_5448_p1; -- db..proc + EXECUTE babel_5448_p1; -- proc +END; +GO + +USE babel_5448_db2; +GO + +CREATE PROCEDURE dbo.babel_5448_p1 AS +BEGIN + SELECT 'This is the incorrect database: babel_5448_db2.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p3 AS +BEGIN + EXECUTE babel_5448_db1.dbo.babel_5448_p2; +END; +GO + +EXECUTE dbo.babel_5448_p3; +GO +~~START~~ +varchar +This is correct: babel_5448_db1.dbo.babel_5448_p1 +~~END~~ + +~~START~~ +varchar +This is correct: babel_5448_db1.dbo.babel_5448_p1 +~~END~~ + +~~START~~ +varchar +This is correct: babel_5448_db1.dbo.babel_5448_p1 +~~END~~ + +~~START~~ +varchar +This is correct: babel_5448_db1.dbo.babel_5448_p1 +~~END~~ + + + +------------------------------------------------ +--------------- sp_proc cross db --------------- +------------------------------------------------ +USE babel_5448_db1; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1' +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_2 AS +BEGIN +EXECUTE babel_5448_db1..sp_test_babel_5448_1; +EXECUTE sp_test_babel_5448_1; +EXECUTE dbo.sp_test_babel_5448_1; +EXECUTE babel_5448_db1.dbo.sp_test_babel_5448_1; +END; +GO + +USE babel_5448_db2; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is the incorrect database: babel_5448_db2.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_3 AS +BEGIN +EXECUTE babel_5448_db1.dbo.sp_test_babel_5448_2; +END; +GO + +EXECUTE dbo.sp_test_babel_5448_3; +GO +~~START~~ +nvarchar +This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1 +~~END~~ + +~~START~~ +nvarchar +This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1 +~~END~~ + + +USE master +GO +DROP DATABASE babel_5448_db2 +GO +DROP DATABASE babel_5448_db1 +GO diff --git a/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out b/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out index 7f3a161fe38..39eaca9ecbe 100644 --- a/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out +++ b/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out @@ -77,7 +77,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -182,7 +182,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_sch2, "$user", sys, pg_catalog +master_sch2, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/BABEL-LOGIN-vu-verify.out b/test/JDBC/expected/BABEL-LOGIN-vu-verify.out index 8c9ae546db3..2f80ebd7566 100644 --- a/test/JDBC/expected/BABEL-LOGIN-vu-verify.out +++ b/test/JDBC/expected/BABEL-LOGIN-vu-verify.out @@ -23,7 +23,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -117,7 +117,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_babel_login_vu_prepare_sch, "$user", sys, pg_catalog +master_babel_login_vu_prepare_sch, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/BABEL_4442.out b/test/JDBC/expected/BABEL_4442.out index fc63a02cade..8cc3dd47488 100644 --- a/test/JDBC/expected/BABEL_4442.out +++ b/test/JDBC/expected/BABEL_4442.out @@ -80,7 +80,7 @@ SELECT babel_4442_f(), current_setting('search_path'), babel_4442_s1.babel_4442_ GO ~~START~~ int#!#text#!#int#!#text#!#int#!#int#!#text#!#int -1#!#master_dbo, "$user", sys, pg_catalog#!#2#!#master_dbo, "$user", sys, pg_catalog#!#3#!#1#!#master_dbo, "$user", sys, pg_catalog#!#1 +1#!#master_dbo, master_dbo, sys, pg_catalog#!#2#!#master_dbo, master_dbo, sys, pg_catalog#!#3#!#1#!#master_dbo, master_dbo, sys, pg_catalog#!#1 ~~END~~ @@ -88,7 +88,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -98,7 +98,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4442_s1.babel_4442_f(), babel_4442_s2.babel_4442_f(), * FROM babel_4442_t @@ -112,7 +112,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4442_s1.babel_4442_f(), babel_4442_s2.babel_4442_f(), * FROM babel_4442_t @@ -129,7 +129,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -139,7 +139,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4442_s1.babel_4442_f(), babel_4442_s2.babel_4442_f(), * FROM babel_4442_t @@ -153,7 +153,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4442_s1.babel_4442_f(), babel_4442_s2.babel_4442_f(), * FROM babel_4442_t @@ -170,7 +170,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/BABEL_4877.out b/test/JDBC/expected/BABEL_4877.out index c9afcd5f334..dbd76a9fa50 100644 --- a/test/JDBC/expected/BABEL_4877.out +++ b/test/JDBC/expected/BABEL_4877.out @@ -101,7 +101,7 @@ EXEC babel_4877_s1.babel_4877_p1 GO ~~START~~ varchar#!#text -before search path ====> #!#master_dbo, "$user", sys, pg_catalog +before search path ====> #!#master_babel_4877_s1, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ @@ -120,7 +120,7 @@ master_babel_4877_s1, sys, pg_catalog ~~START~~ varchar#!#text -after search path ====> #!#master_babel_4877_s1, sys, pg_catalog +after search path ====> #!#master_babel_4877_s1, master_dbo, sys, pg_catalog ~~END~~ @@ -144,26 +144,26 @@ EXEC babel_4877_s1.babel_4877_p1 GO ~~START~~ varchar#!#text -before search path ====> #!#master_dbo, "$user", sys, pg_catalog +before search path ====> #!#master_babel_4877_s1, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ varchar -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog -master_babel_4877_s1, master_dbo, "$user", sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog +master_babel_4877_s1, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ varchar#!#text -after search path ====> #!#master_dbo, "$user", sys, pg_catalog +after search path ====> #!#master_babel_4877_s1, master_dbo, sys, pg_catalog ~~END~~ @@ -256,7 +256,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -273,7 +273,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -290,7 +290,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -301,7 +301,7 @@ SELECT 'before search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -before search_path ----> #!#master_dbo, "$user", sys, pg_catalog +before search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ EXEC babel_4877_s.babel_4877_p @@ -316,7 +316,7 @@ SELECT 'after error search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after error search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after error search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ COMMIT @@ -325,7 +325,7 @@ SELECT 'after tran search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after tran search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after tran search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -335,7 +335,7 @@ SELECT 'before search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -before search_path ----> #!#master_dbo, "$user", sys, pg_catalog +before search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4877_s.babel_4877_f2(); @@ -350,7 +350,7 @@ SELECT 'after error search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after error search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after error search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ COMMIT @@ -359,7 +359,7 @@ SELECT 'after tran search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after tran search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after tran search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -371,7 +371,7 @@ COMMIT GO ~~START~~ varchar#!#text -before search_path ----> #!#master_dbo, "$user", sys, pg_catalog +before search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ @@ -382,7 +382,7 @@ varchar ~~START~~ varchar#!#text -after error search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after error search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -415,7 +415,7 @@ SELECT 'before search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -before search_path ----> #!#master_dbo, "$user", sys, pg_catalog +before search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ EXEC babel_4877_s.babel_4877_p2 @@ -436,7 +436,7 @@ SELECT 'after tran search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after tran search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after tran search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -446,7 +446,7 @@ SELECT 'before search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -before search_path ----> #!#master_dbo, "$user", sys, pg_catalog +before search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT babel_4877_s.babel_4877_f3(); @@ -467,7 +467,7 @@ SELECT 'after tran search_path ----> ', current_setting('search_path'); GO ~~START~~ varchar#!#text -after tran search_path ----> #!#master_dbo, "$user", sys, pg_catalog +after tran search_path ----> #!#master_dbo, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.out b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.out new file mode 100644 index 00000000000..c22fc0b8045 --- /dev/null +++ b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.out @@ -0,0 +1,57 @@ +-- tsql +USE babel_5448_db +GO +DROP PROC dbo.babel_5448_p1, babel_5448_s1.babel_5448_p1, babel_5448_user_default_schema.babel_5448_p1 +GO +USE master +GO +DROP DATABASE babel_5448_db +GO + +DROP PROC dbo.babel_5448_p, dbo.babel_5448_p1, dbo.babel_5448_p2 +GO +DROP PROC babel_5448_user_default_schema.babel_5448_p, babel_5448_user_default_schema.babel_5448_p1, + babel_5448_user_default_schema.babel_5448_p2 +GO +DROP PROC babel_5448_s1.babel_5448_p, babel_5448_s1.babel_5448_p1, babel_5448_s1.babel_5448_p2 +GO +DROP PROC babel_5448_s1.babel_5448_p5, babel_5448_s1.babel_5448_p6, babel_5448_s1.babel_5448_p7, + babel_5448_s1.babel_5448_p8, babel_5448_s1.babel_5448_p9, babel_5448_s1.babel_5448_p10, + babel_5448_s1.babel_5448_p11, babel_5448_s1.babel_5448_p12, babel_5448_s1.babel_5448_p13, + babel_5448_s1.babel_5448_p14, babel_5448_s1.babel_5448_p15; +GO + +DROP FUNCTION dbo.babel_5448_f +GO +DROP FUNCTION babel_5448_user_default_schema.babel_5448_f +GO +DROP FUNCTION babel_5448_s1.babel_5448_f, babel_5448_s1.babel_5448_f2, + babel_5448_s1.babel_5448_f3, babel_5448_s1.babel_5448_f4, + babel_5448_s1.babel_5448_f5; +GO +DROP FUNCTION babel_5448_s2.babel_5448_f +GO + +DROP TABLE dbo.babel_5448_t +GO +DROP TABLE babel_5448_user_default_schema.babel_5448_t +GO +DROP TABLE babel_5448_s1.babel_5448_t +GO + +DROP VIEW babel_5448_s2.babel_5448_v +GO + +DROP SCHEMA babel_5448_user_default_schema +GO +DROP SCHEMA babel_5448_s1 +GO +DROP SCHEMA babel_5448_s2 +GO + +DROP LOGIN babel_5448_login +GO + +-- psql +DROP FUNCTION master_dbo.babel_5448_plpgsql_func(); +GO diff --git a/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.out b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.out new file mode 100644 index 00000000000..745d1b2f60c --- /dev/null +++ b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.out @@ -0,0 +1,659 @@ + + + + + + + + + +-- tsql +-- In this test file we will test babelfish object resolution inside procedure functions and triggers +-- At high level there are four cases to tests +-- 1. CROSS DB routine calls +-- 2. Same DB routine calls +-- 3. CROSS DB non default user schema +-- 4. Same DB non default user schema +-- Then each case will be tested against subcases like +-- 1. DMLs +-- 2. DDLs +-- 3. Cross databases objects references +-- 4. EXEC procedure call statements +-- 5. Other tsql statements +-- Easiest way to test both db_context and search path in a single query +-- is to have both schema specified and non schema specified object references in the query +-- We can skip three part names because they have very straight forward handling and not dependant +-- upon current active logical database or current search path (sp_procs are exception to this and test cases are present elsewhere) +-- Another important case to test is scope handling +-- This means that search path and current logical database value should be set and reset correctly +-- and we do not leak any of these values in any case +-- For example a search path which was set inside the procedure should not be used for queries after the procedure has ended +-- So we need tests cases like EXEC s1.p; SELECT * FROM t; and check if t is resolved correctly. +/***************************************/ +/*************** SAME DB ***************/ +/***************************************/ +/******** SETUP ********/ +-- We will work with 3 schemas "dbo" & +USE master +GO +CREATE SCHEMA babel_5448_user_default_schema +GO +CREATE SCHEMA babel_5448_s1 +GO +CREATE SCHEMA babel_5448_s2 +GO + +-- Now create objects in all three schemas +CREATE TABLE dbo.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_user_default_schema.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_s1.babel_5448_t (id NVARCHAR(max)) +GO + +INSERT INTO dbo.babel_5448_t VALUES ('master.dbo') +INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('master.babel_5448_user_default_schema') +INSERT INTO babel_5448_s1.babel_5448_t VALUES ('master.babel_5448_s1') +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +CREATE PROCEDURE dbo.babel_5448_p AS SELECT 'master.dbo' AS col1 +GO +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p AS SELECT 'master.babel_5448_user_default_schema' AS col1 +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p AS SELECT 'master.babel_5448_s1' AS col1 +GO + +CREATE FUNCTION dbo.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.dbo'; +END +GO + +CREATE FUNCTION babel_5448_user_default_schema.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.babel_5448_user_default_schema'; +END +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.babel_5448_s1'; +END +GO + +CREATE FUNCTION babel_5448_s2.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN ' |-- function in -- master.babel_5448_s2 --| '; +END +GO + +-- Test declare statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f2() RETURNS NVARCHAR(MAX) +AS +BEGIN + DECLARE @i NVARCHAR(MAX) = (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); + RETURN @i +END +GO + +-- Test return statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f3() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); +END +GO + +CREATE VIEW babel_5448_s2.babel_5448_v AS SELECT ' |-- view in -- master.babel_5448_s2 --| ' AS col1 +GO + +CREATE TRIGGER dbo.babel_5448_trigger +ON dbo.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.dbo' + SELECT dbo.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.dbo' +GO + +CREATE TRIGGER babel_5448_user_default_schema.babel_5448_trigger +ON babel_5448_user_default_schema.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema' + SELECT babel_5448_user_default_schema.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema' +GO + +CREATE TRIGGER babel_5448_s1.babel_5448_trigger +ON babel_5448_s1.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.babel_5448_s1' + SELECT babel_5448_s1.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.babel_5448_s1' +GO + +CREATE PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROC dbo.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_user_default_schema.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_s1.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + + +/***************************************/ +/************** CROSS DB ***************/ +/***************************************/ +CREATE DATABASE babel_5448_db +GO +USE babel_5448_db +GO +CREATE SCHEMA babel_5448_user_default_schema +GO +CREATE SCHEMA babel_5448_s1 +GO +CREATE SCHEMA babel_5448_s2 +GO + +-- Now create objects in all three schemas +CREATE TABLE dbo.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_user_default_schema.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_s1.babel_5448_t (id NVARCHAR(max)) +GO + +INSERT INTO dbo.babel_5448_t VALUES ('babel_5448_db.dbo') +INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('babel_5448_db.babel_5448_user_default_schema') +INSERT INTO babel_5448_s1.babel_5448_t VALUES ('babel_5448_db.babel_5448_s1') +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +CREATE PROCEDURE dbo.babel_5448_p AS SELECT 'babel_5448_db.dbo' AS col1 +GO +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p AS SELECT 'babel_5448_db.babel_5448_user_default_schema' AS col1 +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p AS SELECT 'babel_5448_db.babel_5448_s1' AS col1 +GO + +CREATE FUNCTION dbo.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.dbo'; +END +GO + +CREATE FUNCTION babel_5448_user_default_schema.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.babel_5448_user_default_schema'; +END +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.babel_5448_s1'; +END +GO + +CREATE FUNCTION babel_5448_s2.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN ' |-- function in -- babel_5448_db.babel_5448_s2 --| '; +END +GO + +-- Test declare statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f2() RETURNS NVARCHAR(MAX) +AS +BEGIN + DECLARE @i NVARCHAR(MAX) = (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); + RETURN @i +END +GO + +-- Test return statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f3() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); +END +GO + +CREATE VIEW babel_5448_s2.babel_5448_v AS SELECT ' |-- view in -- babel_5448_db.babel_5448_s2 --| ' AS col1 +GO + +CREATE TRIGGER dbo.babel_5448_trigger +ON dbo.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.dbo' + SELECT dbo.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.dbo' +GO + +CREATE TRIGGER babel_5448_user_default_schema.babel_5448_trigger +ON babel_5448_user_default_schema.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema' + SELECT babel_5448_user_default_schema.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema' +GO + +CREATE TRIGGER babel_5448_s1.babel_5448_trigger +ON babel_5448_s1.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1' + SELECT babel_5448_s1.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1' +GO + +CREATE PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROC dbo.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_user_default_schema.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_s1.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + + + + +/************************************************************************************************/ +/************************** START OF TRANSACTION AND ERROR **************************************/ +/*********************** CASES TESTING WITH OBJECT RESOLUTION ***********************************/ +/************************************************************************************************/ +-- create procedures functions which will throw different levels of error +-- and check if search path correctly updated +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p5 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p6 +AS + SELECT '========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + CREATE TABLE #temp (id INT, id1 AS id*2); + ALTER TABLE #temp ADD CONSTRAINT def DEFAULT 1 FOR id1; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p7 +AS + SELECT '========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT * FROM non_existent_table; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f4() RETURNS INT +AS + BEGIN + DECLARE @table_var TABLE(id INT); + INSERT INTO @table_var VALUES (1), (255), (256); + RETURN (SELECT CAST(max(id) AS TINYINT) FROM @table_var); + END +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p5 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p6 +AS + SELECT '========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + CREATE TABLE #temp (id INT, id1 AS id*2); + ALTER TABLE #temp ADD CONSTRAINT def DEFAULT 1 FOR id1; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p7 +AS + SELECT '========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT * FROM non_existent_table; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f4() RETURNS INT +AS + BEGIN + DECLARE @table_var TABLE(id INT); + INSERT INTO @table_var VALUES (1), (255), (256) + RETURN (SELECT CAST(max(id) AS TINYINT) FROM @table_var); + END +GO + + + +/************************************************************************************************/ +/************************** START OF TRY CATCH BLOCK TESTS **************************************/ +/************************************************************************************************/ +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p8 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ====================' + BEGIN TRY + SELECT '############ IN TRY BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + END TRY + BEGIN CATCH + SELECT '############ IN CATCH BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + END CATCH + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p8 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ====================' + BEGIN TRY + SELECT '############ IN TRY BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + END TRY + BEGIN CATCH + SELECT '############ IN CATCH BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + END CATCH + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' +GO + + +/*************************************************************************************/ +/************************** START OF DDLs TESTS **************************************/ +/*************************************************************************************/ +USE master +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p9 +AS + CREATE TABLE #temp (rolename TEXT, roleid TEXT, isapprole TEXT) + CREATE ROLE babel_5448_r1; + CREATE ROLE babel_5448_r2; + ALTER ROLE babel_5448_r1 ADD MEMBER babel_5448_r2; + INSERT INTO #temp EXEC sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC master.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC babel_5448_db.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + DROP ROLE babel_5448_r2; + DROP ROLE babel_5448_r1; + DROP TABLE #temp; +GO + +-- test nested cross database case for ddls +CREATE PROC babel_5448_s1.babel_5448_p10 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC babel_5448_db.babel_5448_s1.babel_5448_p9; +GO + + +USE babel_5448_db +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p9 +AS + CREATE TABLE #temp (rolename TEXT, roleid TEXT, isapprole TEXT) + CREATE ROLE babel_5448_r1; + CREATE ROLE babel_5448_r2; + ALTER ROLE babel_5448_r1 ADD MEMBER babel_5448_r2; + INSERT INTO #temp EXEC sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC master.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC babel_5448_db.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + DROP ROLE babel_5448_r2; + DROP ROLE babel_5448_r1; + DROP TABLE #temp; +GO + + + + +/*************************************************************************************/ +/************************** START OF DYNAMIC SQL *************************************/ +/*************************************************************************************/ +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p11 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p11 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + + + +/*************************************************************************************/ +/************************* START OF SP_EXECUTE_SQL ***********************************/ +/*************************************************************************************/ +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p12 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p12 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + + +/*************************************************************************************/ +/************************* CROSS DB TESTS WITH TEMP TABLE ****************************/ +/*************************************************************************************/ +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p13 +AS + CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); + DROP TABLE #temp_babel_5448; +GO + +-- same as previous but temp table will be created in another database and used inside this proc +CREATE PROCEDURE babel_5448_s1.babel_5448_p14 +AS + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); +GO + + +-- psql +/*************************************************************************************/ +/******************************** INTEROPERABILITY ***********************************/ +/*************************************************************************************/ +CREATE FUNCTION master_dbo.babel_5448_plpgsql_func() +RETURNS TEXT +AS +$$ BEGIN return (SELECT id FROM babel_5448_t); END; $$ +LANGUAGE plpgsql; +GO + +-- tsql +CREATE PROCEDURE babel_5448_s1.babel_5448_p15 +AS + CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); + DROP TABLE #temp_babel_5448; +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f5() RETURNS NVARCHAR(MAX) AS +BEGIN + return (SELECT babel_5448_plpgsql_func()) +END; +GO + +-- same as previous but temp table will be created in another database and used inside this proc +USE babel_5448_db +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p15 +AS + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT master.dbo.babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f5() RETURNS NVARCHAR(MAX) AS +BEGIN + return (SELECT master.dbo.babel_5448_plpgsql_func()) +END; +GO diff --git a/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.out b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.out new file mode 100644 index 00000000000..94e90256fa0 --- /dev/null +++ b/test/JDBC/expected/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.out @@ -0,0 +1,1653 @@ + +-- tsql + + +-- All tests will be triggered from babel_5448_db database +-- For cross database, we will use master database +/*********************************/ +/*********** SAME DB ************/ +/*********************************/ +USE babel_5448_db +GO + +-- All objects should resolve to babel_5448_db.dbo schema in this call +EXEC dbo.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +babel_5448_db.dbo#!#babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +~~END~~ + + +-- All objects should resolve to babel_5448_db.babel_5448_s1 schema in this call +-- except EXEC call stmt +EXEC babel_5448_s1.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +babel_5448_db.babel_5448_s1#!#babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1 +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + + + +-- Now we will run the same procedures again but this time we will references objects from other schema +-- proc in dbo will reference objects from babel_5448_user_default_schema schema +-- proc in babel_5448_s1 will reference objects from dbo schema +ALTER PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_user_default_schema.babel_5448_f(), * FROM babel_5448_user_default_schema.babel_5448_t; + EXEC babel_5448_user_default_schema.babel_5448_p; + INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_user_default_schema.babel_5448_t; +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT dbo.babel_5448_f(), * FROM dbo.babel_5448_t; + EXEC dbo.babel_5448_p; + INSERT INTO dbo.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM dbo.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM dbo.babel_5448_t; +GO + +-- All objects should resolve to babel_5448_db.babel_5448_user_default_schema schema in this call +EXEC dbo.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +babel_5448_db.babel_5448_user_default_schema#!#babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +varchar +babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_user_default_schema +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_user_default_schema +~~END~~ + + +-- All objects should resolve to babel_5448_db.dbo schema in this call +EXEC babel_5448_s1.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +babel_5448_db.dbo#!#babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +~~END~~ + + +-- testing different schemas +-- procedure and function will be on same schema but +-- table & trigger will be different schema +-- basically testing row level search path changes +ALTER PROCEDURE dbo.babel_5448_p1 +AS + INSERT INTO babel_5448_user_default_schema.babel_5448_t SELECT babel_5448_f() FROM generate_series(1,3); + -- trigger execution will tells use what the function resolved to + -- and what the objects inside triggers resolved to + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE id != 'babel_5448_db.babel_5448_user_default_schema' +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + INSERT INTO dbo.babel_5448_t SELECT babel_5448_f() FROM generate_series(1,3); + -- trigger execution will tells use what the function resolved to + -- and what the objects inside triggers resolved to + DELETE FROM dbo.babel_5448_t WHERE id != 'babel_5448_db.dbo' +GO + + +EXEC dbo.babel_5448_p1 +GO +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_user_default_schema +babel_5448_db.dbo +babel_5448_db.dbo +babel_5448_db.dbo +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema +~~END~~ + +~~ROW COUNT: 3~~ + +~~ROW COUNT: 3~~ + + +EXEC babel_5448_s1.babel_5448_p1 +GO +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.dbo +babel_5448_db.babel_5448_s1 +babel_5448_db.babel_5448_s1 +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== babel_5448_db.dbo +~~END~~ + +~~ROW COUNT: 3~~ + +~~ROW COUNT: 3~~ + + +-- Test INSERT EXEC +CREATE TABLE #temp (col1 NVARCHAR(MAX), col2 NVARCHAR(MAX), col3 NVARCHAR(MAX), col4 NVARCHAR(MAX)) +GO + +INSERT INTO #temp EXEC dbo.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#nvarchar#!#nvarchar#!#nvarchar +babel_5448_db.dbo#!# |-- function in -- babel_5448_db.babel_5448_s2 --| #!#babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +INSERT INTO #temp EXEC babel_5448_s1.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#nvarchar#!#nvarchar#!#nvarchar +babel_5448_db.babel_5448_s1#!# |-- function in -- babel_5448_db.babel_5448_s2 --| #!#babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +DROP TABLE #temp +GO + + +-- Test declare statement inside function +SELECT babel_5448_s1.babel_5448_f2(); +-- Test declare statement inside function +SELECT babel_5448_s1.babel_5448_f3(); +GO +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + + + +/*********************************/ +/*********** CROSS DB ************/ +/*********************************/ +USE babel_5448_db +GO + +-- All objects should resolve to master.dbo schema in this call +EXEC master.dbo.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +master.dbo#!#master.dbo +~~END~~ + +~~START~~ +varchar +master.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== master.dbo +~~END~~ + +~~START~~ +nvarchar +master.dbo +~~END~~ + +~~START~~ +nvarchar +master.dbo +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== master.dbo +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +master.dbo +~~END~~ + + +-- All objects should resolve to master.babel_5448_s1 schema in this call +-- except EXEC call stmt +EXEC master.babel_5448_s1.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +master.babel_5448_s1#!#master.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +master.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== master.babel_5448_s1 +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + + +-- Now we need to alter the procedure so switch to master database +-- alter the master database procedures and then execute then from +-- babel_5448_db again +USE master +GO + +ALTER PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_user_default_schema.babel_5448_f(), * FROM babel_5448_user_default_schema.babel_5448_t; + EXEC babel_5448_user_default_schema.babel_5448_p; + INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_user_default_schema.babel_5448_t; +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT dbo.babel_5448_f(), * FROM dbo.babel_5448_t; + EXEC dbo.babel_5448_p; + INSERT INTO dbo.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM dbo.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM dbo.babel_5448_t; +GO + +USE babel_5448_db +GO + +-- Now execute the altered master database procedures +-- All objects should resolve to master.babel_5448_user_default_schema schema in this call +EXEC master.dbo.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +master.babel_5448_user_default_schema#!#master.babel_5448_user_default_schema +~~END~~ + +~~START~~ +varchar +master.babel_5448_user_default_schema +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_user_default_schema +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_user_default_schema +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +master.babel_5448_user_default_schema +~~END~~ + + +-- All objects should resolve to master.dbo schema in this call +EXEC master.babel_5448_s1.babel_5448_p1 +GO +~~START~~ +nvarchar#!#nvarchar +master.dbo#!#master.dbo +~~END~~ + +~~START~~ +varchar +master.dbo +~~END~~ + +~~START~~ +varchar +=========== START OF TRIGGER EXECUTION ========== master.dbo +~~END~~ + +~~START~~ +nvarchar +master.dbo +~~END~~ + +~~START~~ +nvarchar +master.dbo +temp inserted row to check DML and trigger executiong +~~END~~ + +~~START~~ +varchar +=========== END OF TRIGGER EXECUTION ========== master.dbo +~~END~~ + +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar +master.dbo +~~END~~ + + +-- Test INSERT EXEC +CREATE TABLE #temp (col1 NVARCHAR(MAX), col2 NVARCHAR(MAX), col3 NVARCHAR(MAX), col4 NVARCHAR(MAX)) +GO + +INSERT INTO #temp EXEC master.dbo.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#nvarchar#!#nvarchar#!#nvarchar +master.dbo#!# |-- function in -- master.babel_5448_s2 --| #!#master.dbo#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +EXEC master.babel_5448_s1.babel_5448_p2 +GO +~~START~~ +nvarchar#!#nvarchar#!#nvarchar#!#varchar +master.babel_5448_s1#!# |-- function in -- master.babel_5448_s2 --| #!#master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +INSERT INTO #temp EXEC master.babel_5448_s1.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#nvarchar#!#nvarchar#!#nvarchar +master.babel_5448_s1#!# |-- function in -- master.babel_5448_s2 --| #!#master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + + + +-- Test declare statement inside function +SELECT master.babel_5448_s1.babel_5448_f2(); +-- Test declare statement inside function +SELECT master.babel_5448_s1.babel_5448_f3(); +GO +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + + +DROP TABLE #temp +GO + + + +/************************************************************************************************/ +/************************** START OF TRANSACTION AND ERROR **************************************/ +/*********************** CASES TESTING WITH OBJECT RESOLUTION ***********************************/ +/************************************************************************************************/ +/*********** SAME DB ************/ +EXEC babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 1752)~~ + +~~ERROR (Message: column "id1" of relation "#temp" is a generated column)~~ + +~~START~~ +varchar +========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "non_existent_table" does not exist)~~ + +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO +~~START~~ +varchar +========= END OF TRANSACTION ABORTING ERROR ==================== +~~END~~ + + +SELECT babel_5448_s1.babel_5448_f4(); +GO +~~START~~ +int +~~ERROR (Code: 220)~~ + +~~ERROR (Message: value for domain tinyint violates check constraint "tinyint_check")~~ + +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + + +/*********** SAME DB ************/ +/*********** BUT INSIDE TRAN ************/ +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 1752)~~ + +~~ERROR (Message: column "id1" of relation "#temp" is a generated column)~~ + +~~START~~ +varchar +========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "non_existent_table" does not exist)~~ + +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO +~~START~~ +varchar +========= END OF TRANSACTION ABORTING ERROR ==================== +~~END~~ + + +BEGIN TRAN +GO +SELECT babel_5448_s1.babel_5448_f4(); +GO +~~START~~ +int +~~ERROR (Code: 220)~~ + +~~ERROR (Message: value for domain tinyint violates check constraint "tinyint_check")~~ + +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +COMMIT +GO + +/*********** CROSS DB ************/ +EXEC master.babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC master.babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 1752)~~ + +~~ERROR (Message: column "id1" of relation "#temp" is a generated column)~~ + +~~START~~ +varchar +========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC master.babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "non_existent_table" does not exist)~~ + +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO +~~START~~ +varchar +========= END OF TRANSACTION ABORTING ERROR ==================== +~~END~~ + + +SELECT master.babel_5448_s1.babel_5448_f4() FROM generate_series(1,3); +GO +~~START~~ +int +~~ERROR (Code: 220)~~ + +~~ERROR (Message: value for domain tinyint violates check constraint "tinyint_check")~~ + +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + + +/*********** CROSS DB ************/ +/*********** BUT INSIDE TRAN ************/ +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 1752)~~ + +~~ERROR (Message: column "id1" of relation "#temp" is a generated column)~~ + +~~START~~ +varchar +========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "non_existent_table" does not exist)~~ + +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO +~~START~~ +varchar +========= END OF TRANSACTION ABORTING ERROR ==================== +~~END~~ + + +BEGIN TRAN +GO +SELECT master.babel_5448_s1.babel_5448_f4() FROM generate_series(1,3); +GO +~~START~~ +int +~~ERROR (Code: 220)~~ + +~~ERROR (Message: value for domain tinyint violates check constraint "tinyint_check")~~ + +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +COMMIT +GO + + +/************************************************************************************************/ +/************************** START OF TRY CATCH BLOCK TESTS **************************************/ +/************************************************************************************************/ +USE babel_5448_db +GO + +BEGIN TRY + EXEC babel_5448_s1.babel_5448_p8 + SELECT 1/0; +END TRY +BEGIN CATCH + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + USE msdb + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +END CATCH +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ==================== +~~END~~ + +~~START~~ +varchar +############ IN TRY BLOCK ############ +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +varchar +############ IN CATCH BLOCK ############ +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "babel_5448_t" does not exist)~~ + + +SELECT db_name() +GO +~~START~~ +nvarchar +msdb +~~END~~ + + +USE babel_5448_db +GO + +BEGIN TRY + EXEC babel_5448_s1.babel_5448_p8 + SELECT 1/0; +END TRY +BEGIN CATCH + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + USE msdb + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +END CATCH +GO +~~START~~ +varchar +========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ==================== +~~END~~ + +~~START~~ +varchar +############ IN TRY BLOCK ############ +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +varchar +############ IN CATCH BLOCK ############ +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +varchar +========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ==================== +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "babel_5448_t" does not exist)~~ + + +SELECT db_name() +GO +~~START~~ +nvarchar +msdb +~~END~~ + + +USE babel_5448_db +GO + + +/*************************************************************************************/ +/************************** START OF DDLs TESTS **************************************/ +/*************************************************************************************/ +EXEC babel_5448_s1.babel_5448_p9; +GO +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + +~~ERROR (Code: 50000)~~ + +~~ERROR (Message: babel_5448_r2 is not a role.)~~ + +~~START~~ +text +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + + +EXEC master.babel_5448_s1.babel_5448_p9; +GO +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + +~~ERROR (Code: 50000)~~ + +~~ERROR (Message: babel_5448_r2 is not a role.)~~ + +~~START~~ +text +~~END~~ + + +-- tsql database=babel_5448_db +-- run this in a new connection to avoid hitting BABEL-5604 +EXEC master.babel_5448_s1.babel_5448_p10; +GO +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + +~~ERROR (Code: 50000)~~ + +~~ERROR (Message: babel_5448_r2 is not a role.)~~ + +~~START~~ +text +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +text +babel_5448_r2 +~~END~~ + + + +/*************************************************************************************/ +/************************** START OF DYNAMIC SQL *************************************/ +/*************************************************************************************/ +EXEC babel_5448_s1.babel_5448_p11; +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC master.babel_5448_s1.babel_5448_p11; +GO +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.dbo#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + + + +/*************************************************************************************/ +/************************* START OF SP_EXECUTE_SQL ***********************************/ +/*************************************************************************************/ +EXEC babel_5448_s1.babel_5448_p12; +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + +EXEC master.babel_5448_s1.babel_5448_p12; +GO +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.dbo#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar#!#varchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + + + +/*************************************************************************************/ +/***************** VERIFY DEFAULT SCHEMA OF IN BUILT USERS ***************************/ +/*************************************************************************************/ +SELECT database_name, orig_username, default_schema_name FROM sys.babelfish_authid_user_ext +WHERE database_name IN ('master', 'tempdb', 'msdb', 'babel_5448_db') AND + orig_username IN ('dbo', 'guest') +ORDER BY database_name, orig_username; +GO +~~START~~ +nvarchar#!#nvarchar#!#nvarchar +babel_5448_db#!#dbo#!#dbo +babel_5448_db#!#guest#!#guest +master#!#dbo#!#dbo +master#!#guest#!#guest +msdb#!#dbo#!#dbo +msdb#!#guest#!#guest +tempdb#!#dbo#!#dbo +tempdb#!#guest#!#guest +~~END~~ + + +-- tsql +USE master +GO +CREATE LOGIN babel_5448_login WITH PASSWORD = '12345678' +GO +GRANT CONNECT TO guest +GO + +SELECT current_setting('search_path') +GO +~~START~~ +text +master_dbo, master_dbo, sys, pg_catalog +~~END~~ + +-- tsql user=babel_5448_login password=12345678 database=master +SELECT current_setting('search_path') +GO +~~START~~ +text +master_guest, master_dbo, sys, pg_catalog +~~END~~ + + + +-- tsql database=babel_5448_db +/*************************************************************************************/ +/************************* CROSS DB TESTS WITH TEMP TABLE ****************************/ +/*************************************************************************************/ +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +EXEC master.babel_5448_s1.babel_5448_p13 +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#varchar#!#nvarchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +varchar#!#nvarchar + |-- view in -- master.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +nvarchar#!#nvarchar +master.babel_5448_s1#!#<-------- temp table ---------> +~~END~~ + + +CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +EXEC master.babel_5448_s1.babel_5448_p14 +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#varchar#!#nvarchar +master.babel_5448_s1#!# |-- view in -- master.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +varchar#!#nvarchar + |-- view in -- master.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +nvarchar#!#nvarchar +master.babel_5448_s1#!#<-------- temp table ---------> +~~END~~ + +DROP TABLE #temp_babel_5448; +GO + + +BEGIN + IF OBJECT_ID ('tempdb..#temp') IS NOT NULL + BEGIN + DROP TABLE #temp; + END; SELECT TOP 111 * + INTO #temp + FROM ( SELECT col1 AS col1_cross_db FROM master.babel_5448_s2.babel_5448_v) + JOIN babel_5448_t ON (1=1) + JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT * FROM #temp; +END; +GO +~~START~~ +varchar#!#nvarchar#!#varchar + |-- view in -- master.babel_5448_s2 --| #!#babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + + + + +BEGIN + IF OBJECT_ID ('tempdb..#temp') IS NOT NULL + BEGIN + DROP TABLE #temp; + END; + USE master; + SELECT TOP 111 * + INTO #temp + FROM (SELECT col1 AS col1_cross_db FROM babel_5448_db.babel_5448_s2.babel_5448_v) + JOIN babel_5448_t ON (1=1) + JOIN babel_5448_s2.babel_5448_v ON (1=1); + USE babel_5448_db; + SELECT * FROM #temp; +END; +GO +~~WARNING (Code: 0)~~ + +~~WARNING (Message: Changed database context to 'master'. Server SQLState: S0001)~~~~WARNING (Message: Changed database context to 'babel_5448_db'. Server SQLState: S0001)~~ + +~~START~~ +varchar#!#nvarchar#!#varchar + |-- view in -- babel_5448_db.babel_5448_s2 --| #!#master.dbo#!# |-- view in -- master.babel_5448_s2 --| +~~END~~ + + + +-- tsql +/*************************************************************************************/ +/******************************** INTEROPERABILITY ***********************************/ +/*************************************************************************************/ +USE master +GO + +-- plpgsql function call outside any procedure or function +SELECT babel_5448_plpgsql_func(); +GO +~~START~~ +text +master.dbo +~~END~~ + + +-- tsql database=babel_5448_db +USE babel_5448_db +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +EXEC master.babel_5448_s1.babel_5448_p15 +GO +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +~~START~~ +varchar +<----------------------- start of plpgsql function -----------------------> +~~END~~ + +~~START~~ +text +master.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +<----------------------- end of plpgsql function -----------------------> +~~END~~ + +~~ROW COUNT: 1~~ + +~~START~~ +varchar +<----------------------- start of plpgsql function -----------------------> +~~END~~ + +~~START~~ +text +master.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +<----------------------- end of plpgsql function -----------------------> +~~END~~ + +~~START~~ +nvarchar#!#nvarchar +master.babel_5448_s1#!#<-------- temp table ---------> +~~END~~ + + + +SELECT master.babel_5448_s1.babel_5448_f5(); +CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +~~START~~ +nvarchar +master.babel_5448_s1 +~~END~~ + +~~START~~ +nvarchar#!#varchar +babel_5448_db.dbo#!# |-- view in -- babel_5448_db.babel_5448_s2 --| +~~END~~ + +EXEC babel_5448_s1.babel_5448_p15 +GO +~~ROW COUNT: 1~~ + +~~START~~ +nvarchar#!#varchar#!#nvarchar +babel_5448_db.babel_5448_s1#!# |-- view in -- babel_5448_db.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +varchar +<----------------------- start of plpgsql function -----------------------> +~~END~~ + +~~START~~ +text +babel_5448_db.babel_5448_s1 +~~END~~ + +~~START~~ +varchar +<----------------------- end of plpgsql function -----------------------> +~~END~~ + +~~START~~ +varchar#!#nvarchar + |-- view in -- babel_5448_db.babel_5448_s2 --| #!#<-------- temp table ---------> +~~END~~ + +~~START~~ +nvarchar#!#nvarchar +babel_5448_db.babel_5448_s1#!#<-------- temp table ---------> +~~END~~ + +DROP TABLE #temp_babel_5448; +GO + +SELECT babel_5448_s1.babel_5448_f5(); +GO +~~START~~ +nvarchar +babel_5448_db.babel_5448_s1 +~~END~~ + diff --git a/test/JDBC/expected/Test-sp_execute_postgresql.out b/test/JDBC/expected/Test-sp_execute_postgresql.out index d0d40c16f86..7aec7278650 100644 --- a/test/JDBC/expected/Test-sp_execute_postgresql.out +++ b/test/JDBC/expected/Test-sp_execute_postgresql.out @@ -61,7 +61,7 @@ select current_setting('search_path') go ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -439,7 +439,7 @@ select current_setting('search_path') go ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/Test-sp_reset_connection.out b/test/JDBC/expected/Test-sp_reset_connection.out index 8613fa30945..f12f1f01db6 100644 --- a/test/JDBC/expected/Test-sp_reset_connection.out +++ b/test/JDBC/expected/Test-sp_reset_connection.out @@ -682,7 +682,7 @@ SELECT CURRENT_SETTING('role', true) GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ @@ -716,7 +716,7 @@ SELECT CURRENT_SETTING('role', true) GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ diff --git a/test/JDBC/expected/babel_219.out b/test/JDBC/expected/babel_219.out index 57683c502e8..75313b72beb 100644 --- a/test/JDBC/expected/babel_219.out +++ b/test/JDBC/expected/babel_219.out @@ -22,7 +22,7 @@ select set_config('search_path', current_setting('search_path') + ', pg_catalog' GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog, pg_catalog +master_dbo, master_dbo, sys, pg_catalog, pg_catalog ~~END~~ -- Set tsql dialet so the fix for BABEL-219 can kick in diff --git a/test/JDBC/expected/getdate-vu-verify.out b/test/JDBC/expected/getdate-vu-verify.out index 20e1edde9f8..3cf6b98fdc7 100644 --- a/test/JDBC/expected/getdate-vu-verify.out +++ b/test/JDBC/expected/getdate-vu-verify.out @@ -429,6 +429,7 @@ int#!#int#!#int#!#int -- psql +SET search_path = master_dbo, sys, pg_catalog; SET timezone = '+05:30'; select master_dbo.checkDatetimeDiff(sys.DATEDIFF('MINUTE', sys.SYSDATETIME(), sys.SYSDATETIME() AT TIME ZONE 'UTC'), 330, 1); select master_dbo.checkDatetimeDiff(sys.DATEDIFF('MINUTE', sys.getdate(), sys.getdate() AT TIME ZONE 'UTC'), 330, 1); diff --git a/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/test_search_path.out b/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/test_search_path.out index 2d789c084a6..a61ecfb17af 100644 --- a/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/test_search_path.out +++ b/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/test_search_path.out @@ -15,7 +15,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""babel_5111.db""_dbo", "$user", sys, pg_catalog +"""babel_5111.db""_dbo", """babel_5111.db""_dbo", sys, pg_catalog ~~END~~ @@ -47,7 +47,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""龙漫远; 龍漫遠.??€?""_dbo", "$user", sys, pg_catalog +"""龙漫远; 龍漫遠.??€?""_dbo", """龙漫远; 龍漫遠.??€?""_dbo", sys, pg_catalog ~~END~~ @@ -182,7 +182,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""babel_5111.db""_dbo", "$user", sys, pg_catalog +"""babel_5111.db""_dbo", """babel_5111.db""_dbo", sys, pg_catalog ~~END~~ @@ -214,7 +214,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""???; ???.¢£€¥""_dbo", "$user", sys, pg_catalog +"""???; ???.¢£€¥""_dbo", """???; ???.¢£€¥""_dbo", sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/parallel_query/BABEL-1444.out b/test/JDBC/expected/parallel_query/BABEL-1444.out index 9821b95dbe6..d79177e59b3 100644 --- a/test/JDBC/expected/parallel_query/BABEL-1444.out +++ b/test/JDBC/expected/parallel_query/BABEL-1444.out @@ -73,7 +73,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -105,7 +105,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -142,7 +142,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -175,7 +175,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -207,7 +207,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -240,7 +240,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -278,7 +278,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -310,7 +310,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -347,7 +347,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -db1_dbo, "$user", sys, pg_catalog +db1_dbo, db1_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -380,7 +380,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -412,7 +412,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -445,7 +445,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; diff --git a/test/JDBC/expected/parallel_query/Test-sp_reset_connection.out b/test/JDBC/expected/parallel_query/Test-sp_reset_connection.out index fde23af56ad..cff02905cf7 100644 --- a/test/JDBC/expected/parallel_query/Test-sp_reset_connection.out +++ b/test/JDBC/expected/parallel_query/Test-sp_reset_connection.out @@ -658,7 +658,7 @@ Gather (cost=0.00..0.01 rows=1 width=4) ~~START~~ text -Babelfish T-SQL Batch Parsing Time: 0.085 ms +Babelfish T-SQL Batch Parsing Time: 0.125 ms ~~END~~ @@ -685,7 +685,7 @@ SELECT CURRENT_SETTING('role', true) GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ @@ -719,7 +719,7 @@ SELECT CURRENT_SETTING('role', true) GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ ~~START~~ diff --git a/test/JDBC/expected/permission_restrictions_from_pg.out b/test/JDBC/expected/permission_restrictions_from_pg.out index 52b0f568403..bdcb93248cf 100644 --- a/test/JDBC/expected/permission_restrictions_from_pg.out +++ b/test/JDBC/expected/permission_restrictions_from_pg.out @@ -8,6 +8,32 @@ go create user permission_restrictions_tsql_user1 for login permission_restrictions_tsql_login1; go +-- create user for a login in master, tempdb and msdb +create login permission_restrictions_tsql_login2 with password = '123'; +go + +create user permission_restrictions_tsql_login2; +go + +use tempdb; +go + +create user permission_restrictions_tsql_login2; +go + +use msdb; +go + +create user permission_restrictions_tsql_login2; +go + +use master +go + +-- create a login with no mapped user +create login permission_restrictions_tsql_login3 with password = '123'; +go + -- psql create user permission_restrictions_psql_user with password '123'; go @@ -76,6 +102,14 @@ go Server SQLState: 42501)~~ +grant permission_restrictions_tsql_login2 to permission_restrictions_psql_user; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be altered outside of a Babelfish session + Server SQLState: 42501)~~ + + grant master_db_datareader to master_db_datareader; go ~~ERROR (Code: 0)~~ @@ -93,6 +127,22 @@ go Server SQLState: 42501)~~ +drop user permission_restrictions_tsql_login2; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be dropped or altered outside of a Babelfish session + Server SQLState: 42501)~~ + + +drop user permission_restrictions_tsql_login3; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be dropped or altered outside of a Babelfish session + Server SQLState: 42501)~~ + + drop user master_permission_restrictions_tsql_user1; go ~~ERROR (Code: 0)~~ @@ -198,6 +248,14 @@ go Server SQLState: 42501)~~ +grant permission_restrictions_tsql_login2 to permission_restrictions_psql_user; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be altered outside of a Babelfish session + Server SQLState: 42501)~~ + + grant master_db_datareader to master_db_datareader; go ~~ERROR (Code: 0)~~ @@ -215,6 +273,22 @@ go Server SQLState: 42501)~~ +drop user permission_restrictions_tsql_login2; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be dropped or altered outside of a Babelfish session + Server SQLState: 42501)~~ + + +drop user permission_restrictions_tsql_login3; +go +~~ERROR (Code: 0)~~ + +~~ERROR (Message: ERROR: Babelfish-created logins/users/roles cannot be dropped or altered outside of a Babelfish session + Server SQLState: 42501)~~ + + drop user master_permission_restrictions_tsql_user1; go ~~ERROR (Code: 0)~~ @@ -283,6 +357,14 @@ bool ~~END~~ +SELECT pg_terminate_backend(pid) FROM pg_stat_get_activity(NULL) +WHERE sys.suser_name(usesysid) = 'permission_restrictions_tsql_login2' AND backend_type = 'client backend' AND usesysid IS NOT NULL; +GO +~~START~~ +bool +~~END~~ + + select pg_sleep(1); GO ~~START~~ @@ -295,8 +377,29 @@ void drop user permission_restrictions_tsql_user1; go +drop user permission_restrictions_tsql_login2; +go + +use tempdb +go + +drop user permission_restrictions_tsql_login2; +go + +use msdb +go + +drop user permission_restrictions_tsql_login2; +go + drop login permission_restrictions_tsql_login1; go +drop login permission_restrictions_tsql_login2; +go + drop login permission_restrictions_tsql_login go + +drop login permission_restrictions_tsql_login3; +go diff --git a/test/JDBC/expected/restricting_function_overloading-vu-verify.out b/test/JDBC/expected/restricting_function_overloading-vu-verify.out index c287ef4768e..8994ec2348a 100644 --- a/test/JDBC/expected/restricting_function_overloading-vu-verify.out +++ b/test/JDBC/expected/restricting_function_overloading-vu-verify.out @@ -310,7 +310,7 @@ SELECT CURRENT_SETTING('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/schema_resolution_trigger-vu-verify.out b/test/JDBC/expected/schema_resolution_trigger-vu-verify.out index 47a26daa2fe..283046f5e23 100644 --- a/test/JDBC/expected/schema_resolution_trigger-vu-verify.out +++ b/test/JDBC/expected/schema_resolution_trigger-vu-verify.out @@ -1,3 +1,20 @@ +-- need to and recreate trigger if it exists in the incorrect schema +BEGIN TRAN +GO +IF NOT EXISTS ( + SELECT * FROM pg_proc + WHERE proname = 'schema_resolution_trigger_tr2' AND + pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'master_schema_resolution_trigger_s1')) +BEGIN + DROP TRIGGER schema_resolution_trigger_s1.schema_resolution_trigger_tr2; +END +GO +IF NOT EXISTS (select * from sys.objects where type = 'TR' and name = 'schema_resolution_trigger_tr2') +EXEC dbo.sp_executesql @statement = N'create trigger schema_resolution_trigger_s1.schema_resolution_trigger_tr2 on schema_resolution_trigger_s1.schema_resolution_trigger_mytab for insert as +select * from schema_resolution_trigger_t1' +COMMIT +GO + -- Resolves to dbo.schema_resolution_trigger_t1 insert into dbo.schema_resolution_trigger_mytab values(1) go diff --git a/test/JDBC/expected/select_into-identity-notnull.out b/test/JDBC/expected/select_into-identity-notnull.out new file mode 100644 index 00000000000..b37ca6e4116 --- /dev/null +++ b/test/JDBC/expected/select_into-identity-notnull.out @@ -0,0 +1,420 @@ +create database db_select_into +go + +use db_select_into +go + +create schema sch_select_into +go + +create table t1_select_into ([Col1] INT IDENTITY(1, 1), [Col2] [NVarchar](20) NOT NULL) +go + +insert into t1_select_into([Col2]) values ('First') +go +~~ROW COUNT: 1~~ + + +set identity_insert t1_select_into on +go + +insert into t1_select_into([Col1], [Col2]) values (1, 'First_dup') +go +~~ROW COUNT: 1~~ + + +set identity_insert t1_select_into off +go + +create view v1_select_into as select * from t1_select_into +go + +create table sch_select_into.t1_select_into ([Col3] TINYINT IDENTITY(2, 2), [Col4] numeric(4,3) NOT NULL) +go + +insert into sch_select_into.t1_select_into([Col4]) values (2.222) +go +~~ROW COUNT: 1~~ + + +use master +go + +create schema sch_select_into_master +go + +create table sch_select_into_master.t1_select_into_master ([Col5] SMALLINT IDENTITY(3, 3), [Col6] [Nvarchar](20) NOT NULL) +go + +insert into sch_select_into_master.t1_select_into_master([Col6]) values ('Third') +go +~~ROW COUNT: 1~~ + + +create table t1_select_into_master ([Col7] float NOT NULL, [Col8] BIGINT IDENTITY(4, 4)) +go + +insert into t1_select_into_master([Col7]) values (4.4) +go +~~ROW COUNT: 1~~ + + +create table t1_select_into_master_dec ([Col9] DECIMAL(10,0) IDENTITY(5, 5) PRIMARY KEY, [Col10] real NOT NULL) +go + +insert into t1_select_into_master_dec([Col10]) values (5.567) +go +~~ROW COUNT: 1~~ + + +use db_select_into +go + +select * into dest_table_1 from t1_select_into order by [Col1] +go + +select * into dest_table_2 from sch_select_into.t1_select_into group by [Col3], [Col4] +go + +select * into dest_table_3 from master.sch_select_into_master.t1_select_into_master +go + +select * into dest_table_4 from master..t1_select_into_master +go + +select * into dest_table_5 from master.dbo.t1_select_into_master_dec +go + +exec sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_identity_function', 'ignore'; +go + +-- Should throw error because there are 2 identity columns +select identity(int, 1, 1) as identity_col, * into dest_table_error from t1_select_into +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Attempting to add multiple identity columns to table "dest_table_error" using the SELECT INTO statement.)~~ + + +exec sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_identity_function', 'strict'; +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_1 ([Col2]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col2" of relation "dest_table_1" violates not-null constraint)~~ + + +insert into dest_table_1 ([Col2]) values ('Second') +go +~~ROW COUNT: 1~~ + + +-- Identity column should be populated by default +select * from dest_table_1 order by [Col1] +go +~~START~~ +int#!#nvarchar +1#!#First +1#!#First_dup +2#!#Second +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_2 ([Col4]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col4" of relation "dest_table_2" violates not-null constraint)~~ + + +insert into dest_table_2 ([Col4]) values (3.333) +go +~~ROW COUNT: 1~~ + + +-- Identity column should be populated by default +select * from dest_table_2 order by [Col3] +go +~~START~~ +smallint#!#numeric +2#!#2.222 +4#!#3.333 +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_3 ([Col6]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col6" of relation "dest_table_3" violates not-null constraint)~~ + + +insert into dest_table_3 ([Col6]) values ('Fourth') +go +~~ROW COUNT: 1~~ + + +-- Identity column should be populated by default +select * from dest_table_3 order by [Col5] +go +~~START~~ +smallint#!#nvarchar +3#!#Third +6#!#Fourth +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_4 ([Col7]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col7" of relation "dest_table_4" violates not-null constraint)~~ + + +insert into dest_table_4 ([Col7]) values (5.5) +go +~~ROW COUNT: 1~~ + + +-- Identity column should be populated by default +select * from dest_table_4 order by [Col8] +go +~~START~~ +float#!#bigint +4.4#!#4 +5.5#!#8 +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_5 ([Col10]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col10" of relation "dest_table_5" violates not-null constraint)~~ + + +insert into dest_table_5 ([Col10]) values (6.789) +go +~~ROW COUNT: 1~~ + + +-- Identity column should be populated by default +select * from dest_table_5 order by [Col9] +go +~~START~~ +bigint#!#real +5#!#5.567 +10#!#6.789 +~~END~~ + + +-- FROM clause contains joins from multiple tables +-- Should not fail as identity should not be persisted but nullability should +select * +into dest_table_join +from dest_table_1 t1 +inner join dest_table_2 t2 +on t1.[Col1] * 2 = t2.[Col3] +go + +select * from dest_table_join order by [Col1], [Col2] +go +~~START~~ +int#!#nvarchar#!#smallint#!#numeric +1#!#First#!#2#!#2.222 +1#!#First_dup#!#2#!#2.222 +2#!#Second#!#4#!#3.333 +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_join ([Col2]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col1" of relation "dest_table_join" violates not-null constraint)~~ + + +-- Should fail. Violate NOT NULL constraint on other column +insert into dest_table_join ([Col2]) values ('Join') +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col1" of relation "dest_table_join" violates not-null constraint)~~ + + +insert into dest_table_join ([Col1], [Col2], [Col3], [Col4]) values (99, 'Join', 88, 9.867) +go +~~ROW COUNT: 1~~ + + +select * from dest_table_join order by [Col1], [Col2] +go +~~START~~ +int#!#nvarchar#!#smallint#!#numeric +1#!#First#!#2#!#2.222 +1#!#First_dup#!#2#!#2.222 +2#!#Second#!#4#!#3.333 +99#!#Join#!#88#!#9.867 +~~END~~ + + +-- FROM clause contains subquery +select * +into dest_table_union +from +( + select * from dest_table_1 + union all + select * from dest_table_3 +) as combined_tables +go + +select * from dest_table_union order by [Col1] +go +~~START~~ +int#!#nvarchar +1#!#First +1#!#First_dup +2#!#Second +3#!#Third +6#!#Fourth +~~END~~ + + +-- Ideally should fail as it violates NOT NULL constraint +-- Currently NOT NULL constraint won't get carried over +-- to destination table in case of subquery +insert into dest_table_union ([Col2]) values (NULL) +go +~~ROW COUNT: 1~~ + + +insert into dest_table_union ([Col2]) values ('Union') +go +~~ROW COUNT: 1~~ + + +select * from dest_table_union order by [Col1] +go +~~START~~ +int#!#nvarchar +#!# +#!#Union +1#!#First_dup +1#!#First +2#!#Second +3#!#Third +6#!#Fourth +~~END~~ + + +select * +into dest_table_sub_join +from +( + select * from dest_table_1 t1 + inner join dest_table_2 t2 + on t1.[Col1] * 2 = t2.[Col3] +) as combined_tables +go + +select * from dest_table_sub_join order by [Col1], [Col2] +go +~~START~~ +int#!#nvarchar#!#smallint#!#numeric +1#!#First#!#2#!#2.222 +1#!#First_dup#!#2#!#2.222 +2#!#Second#!#4#!#3.333 +~~END~~ + + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_sub_join ([Col1]) values (NULL) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col1" of relation "dest_table_sub_join" violates not-null constraint)~~ + + +-- Should fail. Violate NOT NULL constraint on other column +insert into dest_table_sub_join ([Col1]) values (200) +go +~~ERROR (Code: 515)~~ + +~~ERROR (Message: null value in column "col2" of relation "dest_table_sub_join" violates not-null constraint)~~ + + +insert into dest_table_sub_join ([Col1], [Col2], [Col3], [Col4]) values (209, 'Sub-Join', 78, 8.567) +go +~~ROW COUNT: 1~~ + + +select * from dest_table_sub_join order by [Col1], [Col2] +go +~~START~~ +int#!#nvarchar#!#smallint#!#numeric +1#!#First#!#2#!#2.222 +1#!#First_dup#!#2#!#2.222 +2#!#Second#!#4#!#3.333 +209#!#Sub-Join#!#78#!#8.567 +~~END~~ + + +select * into dest_table_view from v1_select_into +go + +select * from dest_table_view order by [Col1], [Col2] +go +~~START~~ +int#!#nvarchar +1#!#First +1#!#First_dup +~~END~~ + + +drop table dest_table_1 +drop table dest_table_2 +drop table dest_table_3 +drop table dest_table_4 +drop table dest_table_5 +drop table dest_table_join +drop table dest_table_union +drop table dest_table_sub_join +drop view v1_select_into +drop table dest_table_view +go + +drop table t1_select_into +go + +drop table sch_select_into.t1_select_into +go + +drop schema sch_select_into +go + +use master +go + +drop database db_select_into +go + +drop table t1_select_into_master +go + +drop table t1_select_into_master_dec +go + +drop table sch_select_into_master.t1_select_into_master +go + +drop schema sch_select_into_master +go diff --git a/test/JDBC/expected/single_db/BABEL-1444.out b/test/JDBC/expected/single_db/BABEL-1444.out index b2226130073..490f36027b7 100644 --- a/test/JDBC/expected/single_db/BABEL-1444.out +++ b/test/JDBC/expected/single_db/BABEL-1444.out @@ -73,7 +73,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -105,7 +105,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -142,7 +142,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -175,7 +175,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -207,7 +207,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -240,7 +240,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -278,7 +278,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -310,7 +310,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -347,7 +347,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -380,7 +380,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -412,7 +412,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -445,7 +445,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; diff --git a/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out b/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out index bd9742cef7d..e38212212cb 100644 --- a/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out +++ b/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out @@ -77,7 +77,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ @@ -182,7 +182,7 @@ SELECT current_setting('search_path'); go ~~START~~ text -master_sch2, "$user", sys, pg_catalog +master_sch2, master_dbo, sys, pg_catalog ~~END~~ diff --git a/test/JDBC/expected/singledb__verification_cleanup__BABEL-1444-vu-verify.out b/test/JDBC/expected/singledb__verification_cleanup__BABEL-1444-vu-verify.out index 8a7d41223d6..2b9a3759121 100644 --- a/test/JDBC/expected/singledb__verification_cleanup__BABEL-1444-vu-verify.out +++ b/test/JDBC/expected/singledb__verification_cleanup__BABEL-1444-vu-verify.out @@ -45,7 +45,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -77,7 +77,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -114,7 +114,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -dbo, "$user", sys, pg_catalog +dbo, dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -147,7 +147,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -179,7 +179,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; @@ -212,7 +212,7 @@ SELECT current_setting('search_path'); GO ~~START~~ text -master_dbo, "$user", sys, pg_catalog +master_dbo, master_dbo, sys, pg_catalog ~~END~~ SELECT session_user, current_user, user; diff --git a/test/JDBC/expected/sp_proc.out b/test/JDBC/expected/sp_proc.out index 0bf6a4157c6..f8d03adbe6c 100644 --- a/test/JDBC/expected/sp_proc.out +++ b/test/JDBC/expected/sp_proc.out @@ -1,3 +1,4 @@ +-- tsql create proc sp_hello as select 1 go @@ -213,9 +214,96 @@ go ~~ERROR (Message: procedure @a() does not exist)~~ +use master +go +create table sometableinmaster(somecolumn INT) +go +use db1 +go +create schema s1 +go + +-- should resolve to db1.dbo.sp_hello +exec db1.dbo.sp_hello +go +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + +exec db1..sp_hello +go +~~ERROR (Code: 8134)~~ + +~~ERROR (Message: division by zero)~~ + + +-- should throw an error +exec db1.sys.sp_hello +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: procedure sys.sp_hello() does not exist)~~ + + +-- should thorw an error +exec db1.s1.sp_hello +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: procedure s1.sp_hello() does not exist)~~ + + drop proc sp_hello; go +-- should resolve to master.dbo.sp_hello since proc does not exists in db1 +-- special behaviour for sp_ procs +exec db1.dbo.sp_hello +go +~~START~~ +int +1 +~~END~~ + +exec db1..sp_hello +go +~~START~~ +int +1 +~~END~~ + + +-- should resolve to sys sp_tables +exec db1.dbo.sp_tables +go +~~START~~ +varchar#!#varchar#!#varchar#!#varchar#!#varchar +db1#!#dbo#!#sysdatabases#!#VIEW#!# +~~END~~ + +exec db1..sp_tables +go +~~START~~ +varchar#!#varchar#!#varchar#!#varchar#!#varchar +db1#!#dbo#!#sysdatabases#!#VIEW#!# +~~END~~ + +-- procedure should be executed as if current db was master +exec master..sp_tables @table_name = N'sometableinmaster' +go +~~START~~ +varchar#!#varchar#!#varchar#!#varchar#!#varchar +master#!#dbo#!#sometableinmaster#!#TABLE#!# +~~END~~ + +exec master.dbo.sp_tables @table_name = N'sometableinmaster' +go +~~START~~ +varchar#!#varchar#!#varchar#!#varchar#!#varchar +master#!#dbo#!#sometableinmaster#!#TABLE#!# +~~END~~ + + use master go @@ -409,8 +497,70 @@ go use master go +drop table sometableinmaster +go drop proc sp_hello go +use db1 +go +create schema s1 +go + create login non_default_schema_login with password = '12345678' +go +create user non_default_schema_login +go +alter user non_default_schema_login with default_schema = s1 +go +create proc s1.sp_user_proc as select '--- S1 ---'; +go +create proc dbo.sp_user_proc as select '--- DBO ---'; +go +alter role db_owner add member non_default_schema_login +go + +-- tsql user=non_default_schema_login password=12345678 database=db1 +select schema_name(), db_name() +go +~~START~~ +varchar#!#nvarchar +s1#!#db1 +~~END~~ + +-- should resolve to s1.sp_user_proc +exec sp_user_proc +exec db1..sp_user_proc +go +~~START~~ +varchar +--- S1 --- +~~END~~ + +~~START~~ +varchar +--- S1 --- +~~END~~ + +-- should resolve to dbo.sp_user_proc +exec dbo.sp_user_proc +exec db1.dbo.sp_user_proc +go +~~START~~ +varchar +--- DBO --- +~~END~~ + +~~START~~ +varchar +--- DBO --- +~~END~~ + +-- terminate-tsql-conn user=non_default_schema_login password=12345678 database=db1 + +-- tsql +use master +go +drop login non_default_schema_login +go drop database db1 go diff --git a/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-cleanup.out b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-cleanup.out new file mode 100644 index 00000000000..9b8eba77ad0 --- /dev/null +++ b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-cleanup.out @@ -0,0 +1,8 @@ +DROP VIEW fn_varbintohexsubstring_vu_prepare_view +GO + +DROP PROC fn_varbintohexsubstring_vu_prepare_proc +GO + +DROP FUNCTION fn_varbintohexsubstring_vu_prepare_func +GO diff --git a/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-prepare.out b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-prepare.out new file mode 100644 index 00000000000..0e411299c93 --- /dev/null +++ b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-prepare.out @@ -0,0 +1,16 @@ +-- Create dependant objects +CREATE VIEW fn_varbintohexsubstring_vu_prepare_view AS +SELECT sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +GO + +CREATE PROC fn_varbintohexsubstring_vu_prepare_proc AS +SELECT sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +GO + +CREATE FUNCTION fn_varbintohexsubstring_vu_prepare_func() +RETURNS nvarchar(128) +AS +BEGIN +RETURN sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +END +GO diff --git a/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-verify.out b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-verify.out new file mode 100644 index 00000000000..c538d5cb67c --- /dev/null +++ b/test/JDBC/expected/sys-fn-varbintohexsubstring-vu-verify.out @@ -0,0 +1,23 @@ +SELECT * FROM fn_varbintohexsubstring_vu_prepare_view +GO +~~START~~ +nvarchar + +~~END~~ + + +EXEC fn_varbintohexsubstring_vu_prepare_proc +GO +~~START~~ +nvarchar + +~~END~~ + + +SELECT * FROM fn_varbintohexsubstring_vu_prepare_func() +GO +~~START~~ +nvarchar + +~~END~~ + diff --git a/test/JDBC/expected/sys-login-property-vu-cleanup.out b/test/JDBC/expected/sys-login-property-vu-cleanup.out new file mode 100644 index 00000000000..32d0923752f --- /dev/null +++ b/test/JDBC/expected/sys-login-property-vu-cleanup.out @@ -0,0 +1,8 @@ +DROP VIEW loginproperty_vu_prepare_view +GO + +DROP PROC loginproperty_vu_prepare_proc +GO + +DROP FUNCTION loginproperty_vu_prepare_func +GO diff --git a/test/JDBC/expected/sys-login-property-vu-prepare.out b/test/JDBC/expected/sys-login-property-vu-prepare.out new file mode 100644 index 00000000000..99a973bbc5c --- /dev/null +++ b/test/JDBC/expected/sys-login-property-vu-prepare.out @@ -0,0 +1,16 @@ +-- Create dependant objects +CREATE VIEW loginproperty_vu_prepare_view AS +SELECT sys.loginproperty('test_login', 'PasswordHash') +GO + +CREATE PROC loginproperty_vu_prepare_proc AS +SELECT sys.loginproperty('test_login', 'PasswordHash') +GO + +CREATE FUNCTION loginproperty_vu_prepare_func() +RETURNS nvarchar(128) +AS +BEGIN +RETURN sys.loginproperty('test_login', 'PasswordHash') +END +GO diff --git a/test/JDBC/expected/sys-login-property-vu-verify.out b/test/JDBC/expected/sys-login-property-vu-verify.out new file mode 100644 index 00000000000..aa755f362f4 --- /dev/null +++ b/test/JDBC/expected/sys-login-property-vu-verify.out @@ -0,0 +1,23 @@ +SELECT * FROM loginproperty_vu_prepare_view +GO +~~START~~ +nvarchar + +~~END~~ + + +EXEC loginproperty_vu_prepare_proc +GO +~~START~~ +nvarchar + +~~END~~ + + +SELECT * FROM loginproperty_vu_prepare_func() +GO +~~START~~ +nvarchar + +~~END~~ + diff --git a/test/JDBC/expected/sys_credentials-vu-cleanup.out b/test/JDBC/expected/sys_credentials-vu-cleanup.out new file mode 100644 index 00000000000..ab627b85248 --- /dev/null +++ b/test/JDBC/expected/sys_credentials-vu-cleanup.out @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_credentials_vu_prepare_view +GO + +DROP PROC sys_credentials_vu_prepare_proc +GO + +DROP FUNCTION sys_credentials_vu_prepare_func +GO diff --git a/test/JDBC/expected/sys_credentials-vu-prepare.out b/test/JDBC/expected/sys_credentials-vu-prepare.out new file mode 100644 index 00000000000..2cebaee4b07 --- /dev/null +++ b/test/JDBC/expected/sys_credentials-vu-prepare.out @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_credentials_vu_prepare_view AS +SELECT * FROM sys.credentials +GO + +CREATE PROC sys_credentials_vu_prepare_proc AS +SELECT * FROM sys.credentials +GO + +CREATE FUNCTION sys_credentials_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.credentials) +END +GO diff --git a/test/JDBC/expected/sys_credentials-vu-verify.out b/test/JDBC/expected/sys_credentials-vu-verify.out new file mode 100644 index 00000000000..d0bc4e9a38b --- /dev/null +++ b/test/JDBC/expected/sys_credentials-vu-verify.out @@ -0,0 +1,31 @@ +USE master +GO + +SELECT * FROM sys.credentials +GO +~~START~~ +int#!#varchar#!#nvarchar#!#datetime#!#datetime#!#nvarchar#!#int +~~END~~ + + +SELECT * FROM sys_credentials_vu_prepare_view +GO +~~START~~ +int#!#varchar#!#nvarchar#!#datetime#!#datetime#!#nvarchar#!#int +~~END~~ + + +EXEC sys_credentials_vu_prepare_proc +GO +~~START~~ +int#!#varchar#!#nvarchar#!#datetime#!#datetime#!#nvarchar#!#int +~~END~~ + + +SELECT sys_credentials_vu_prepare_func() +GO +~~START~~ +int +0 +~~END~~ + diff --git a/test/JDBC/expected/sys_server_permissions-vu-cleanup.out b/test/JDBC/expected/sys_server_permissions-vu-cleanup.out new file mode 100644 index 00000000000..22b2a175a40 --- /dev/null +++ b/test/JDBC/expected/sys_server_permissions-vu-cleanup.out @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_server_permissions_vu_prepare_view +GO + +DROP PROC sys_server_permissions_vu_prepare_proc +GO + +DROP FUNCTION sys_server_permissions_vu_prepare_func +GO diff --git a/test/JDBC/expected/sys_server_permissions-vu-prepare.out b/test/JDBC/expected/sys_server_permissions-vu-prepare.out new file mode 100644 index 00000000000..df4a09229c3 --- /dev/null +++ b/test/JDBC/expected/sys_server_permissions-vu-prepare.out @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_server_permissions_vu_prepare_view AS +SELECT * FROM sys.server_permissions +GO + +CREATE PROC sys_server_permissions_vu_prepare_proc AS +SELECT * FROM sys.server_permissions +GO + +CREATE FUNCTION sys_server_permissions_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.server_permissions) +END +GO diff --git a/test/JDBC/expected/sys_server_permissions-vu-verify.out b/test/JDBC/expected/sys_server_permissions-vu-verify.out new file mode 100644 index 00000000000..f49b5e7a126 --- /dev/null +++ b/test/JDBC/expected/sys_server_permissions-vu-verify.out @@ -0,0 +1,31 @@ +USE master +GO + +SELECT * FROM sys.server_permissions +GO +~~START~~ +tinyint#!#nvarchar#!#int#!#int#!#int#!#int#!#char#!#nvarchar#!#char#!#nvarchar +~~END~~ + + +SELECT * FROM sys_server_permissions_vu_prepare_view +GO +~~START~~ +tinyint#!#nvarchar#!#int#!#int#!#int#!#int#!#char#!#nvarchar#!#char#!#nvarchar +~~END~~ + + +EXEC sys_server_permissions_vu_prepare_proc +GO +~~START~~ +tinyint#!#nvarchar#!#int#!#int#!#int#!#int#!#char#!#nvarchar#!#char#!#nvarchar +~~END~~ + + +SELECT sys_server_permissions_vu_prepare_func() +GO +~~START~~ +int +0 +~~END~~ + diff --git a/test/JDBC/expected/sys_sql_logins-vu-cleanup.out b/test/JDBC/expected/sys_sql_logins-vu-cleanup.out new file mode 100644 index 00000000000..fba67f46e2a --- /dev/null +++ b/test/JDBC/expected/sys_sql_logins-vu-cleanup.out @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_sql_logins_vu_prepare_view +GO + +DROP PROC sys_sql_logins_vu_prepare_proc +GO + +DROP FUNCTION sys_sql_logins_vu_prepare_func +GO diff --git a/test/JDBC/expected/sys_sql_logins-vu-prepare.out b/test/JDBC/expected/sys_sql_logins-vu-prepare.out new file mode 100644 index 00000000000..93ca245df0c --- /dev/null +++ b/test/JDBC/expected/sys_sql_logins-vu-prepare.out @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_sql_logins_vu_prepare_view AS +SELECT * FROM sys.sql_logins +GO + +CREATE PROC sys_sql_logins_vu_prepare_proc AS +SELECT * FROM sys.sql_logins +GO + +CREATE FUNCTION sys_sql_logins_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.sql_logins) +END +GO diff --git a/test/JDBC/expected/sys_sql_logins-vu-verify.out b/test/JDBC/expected/sys_sql_logins-vu-verify.out new file mode 100644 index 00000000000..c658f478051 --- /dev/null +++ b/test/JDBC/expected/sys_sql_logins-vu-verify.out @@ -0,0 +1,31 @@ +USE master +GO + +SELECT * FROM sys.sql_logins +GO +~~START~~ +varchar#!#int#!#varbinary#!#char#!#nvarchar#!#int#!#datetime#!#datetime#!#varchar#!#varchar#!#int#!#int#!#bit#!#bit#!#bit#!#varbinary +~~END~~ + + +SELECT * FROM sys_sql_logins_vu_prepare_view +GO +~~START~~ +varchar#!#int#!#varbinary#!#char#!#nvarchar#!#int#!#datetime#!#datetime#!#varchar#!#varchar#!#int#!#int#!#bit#!#bit#!#bit#!#varbinary +~~END~~ + + +EXEC sys_sql_logins_vu_prepare_proc +GO +~~START~~ +varchar#!#int#!#varbinary#!#char#!#nvarchar#!#int#!#datetime#!#datetime#!#varchar#!#varchar#!#int#!#int#!#bit#!#bit#!#bit#!#varbinary +~~END~~ + + +SELECT sys_sql_logins_vu_prepare_func() +GO +~~START~~ +int +0 +~~END~~ + diff --git a/test/JDBC/expected/test_search_path.out b/test/JDBC/expected/test_search_path.out index 28790694cfd..4511fa80793 100644 --- a/test/JDBC/expected/test_search_path.out +++ b/test/JDBC/expected/test_search_path.out @@ -15,7 +15,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""babel_5111.db""_dbo", "$user", sys, pg_catalog +"""babel_5111.db""_dbo", """babel_5111.db""_dbo", sys, pg_catalog ~~END~~ @@ -47,7 +47,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""???; ???.¢£€¥""_dbo", "$user", sys, pg_catalog +"""???; ???.¢£€¥""_dbo", """???; ???.¢£€¥""_dbo", sys, pg_catalog ~~END~~ @@ -182,7 +182,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""babel_5111.db""_dbo", "$user", sys, pg_catalog +"""babel_5111.db""_dbo", """babel_5111.db""_dbo", sys, pg_catalog ~~END~~ @@ -214,7 +214,7 @@ SELECT current_setting('search_path') GO ~~START~~ text -"""???; ???.¢£€¥""_dbo", "$user", sys, pg_catalog +"""???; ???.¢£€¥""_dbo", """???; ???.¢£€¥""_dbo", sys, pg_catalog ~~END~~ diff --git a/test/JDBC/input/BABEL-CROSS-DB.mix b/test/JDBC/input/BABEL-CROSS-DB.mix index 05ebc64454e..1e09ff5462f 100644 --- a/test/JDBC/input/BABEL-CROSS-DB.mix +++ b/test/JDBC/input/BABEL-CROSS-DB.mix @@ -632,3 +632,98 @@ GO DROP DATABASE db2; GO + +------------------ BABEL-5448 ------------------ +------------------------------------------------ +USE master; +GO + +CREATE DATABASE babel_5448_db1; +GO +CREATE DATABASE babel_5448_db2; +GO + +USE babel_5448_db1 +GO + +CREATE PROCEDURE dbo.babel_5448_p1 AS +BEGIN + SELECT 'This is correct: babel_5448_db1.dbo.babel_5448_p1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p2 AS +BEGIN + EXECUTE dbo.babel_5448_p1; -- schema.proc + EXECUTE babel_5448_db1.dbo.babel_5448_p1; -- db.schema.proc + EXECUTE babel_5448_db1..babel_5448_p1; -- db..proc + EXECUTE babel_5448_p1; -- proc +END; +GO + +USE babel_5448_db2; +GO + +CREATE PROCEDURE dbo.babel_5448_p1 AS +BEGIN + SELECT 'This is the incorrect database: babel_5448_db2.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p3 AS +BEGIN + EXECUTE babel_5448_db1.dbo.babel_5448_p2; +END; +GO + +EXECUTE dbo.babel_5448_p3; +GO + +------------------------------------------------ +--------------- sp_proc cross db --------------- +------------------------------------------------ + +USE babel_5448_db1; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is correct: babel_5448_db1.dbo.sp_test_babel_5448_1' +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_2 AS +BEGIN +EXECUTE babel_5448_db1..sp_test_babel_5448_1; +EXECUTE sp_test_babel_5448_1; +EXECUTE dbo.sp_test_babel_5448_1; +EXECUTE babel_5448_db1.dbo.sp_test_babel_5448_1; +END; +GO + +USE babel_5448_db2; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is the incorrect database: babel_5448_db2.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_3 AS +BEGIN +EXECUTE babel_5448_db1.dbo.sp_test_babel_5448_2; +END; +GO + +EXECUTE dbo.sp_test_babel_5448_3; +GO + +USE master +GO +DROP DATABASE babel_5448_db2 +GO +DROP DATABASE babel_5448_db1 +GO +----------- END OF BABEL-5448 ------------------ +------------------------------------------------ diff --git a/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-cleanup.sql b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-cleanup.sql new file mode 100644 index 00000000000..9b8eba77ad0 --- /dev/null +++ b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-cleanup.sql @@ -0,0 +1,8 @@ +DROP VIEW fn_varbintohexsubstring_vu_prepare_view +GO + +DROP PROC fn_varbintohexsubstring_vu_prepare_proc +GO + +DROP FUNCTION fn_varbintohexsubstring_vu_prepare_func +GO diff --git a/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-prepare.sql b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-prepare.sql new file mode 100644 index 00000000000..0e411299c93 --- /dev/null +++ b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-prepare.sql @@ -0,0 +1,16 @@ +-- Create dependant objects +CREATE VIEW fn_varbintohexsubstring_vu_prepare_view AS +SELECT sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +GO + +CREATE PROC fn_varbintohexsubstring_vu_prepare_proc AS +SELECT sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +GO + +CREATE FUNCTION fn_varbintohexsubstring_vu_prepare_func() +RETURNS nvarchar(128) +AS +BEGIN +RETURN sys.fn_varbintohexsubstring(1, CAST('0x1234' AS varbinary(128)), 1, 4) +END +GO diff --git a/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-verify.sql b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-verify.sql new file mode 100644 index 00000000000..920a65394f8 --- /dev/null +++ b/test/JDBC/input/functions/sys-fn-varbintohexsubstring-vu-verify.sql @@ -0,0 +1,8 @@ +SELECT * FROM fn_varbintohexsubstring_vu_prepare_view +GO + +EXEC fn_varbintohexsubstring_vu_prepare_proc +GO + +SELECT * FROM fn_varbintohexsubstring_vu_prepare_func() +GO diff --git a/test/JDBC/input/functions/sys-login-property-vu-cleanup.sql b/test/JDBC/input/functions/sys-login-property-vu-cleanup.sql new file mode 100644 index 00000000000..32d0923752f --- /dev/null +++ b/test/JDBC/input/functions/sys-login-property-vu-cleanup.sql @@ -0,0 +1,8 @@ +DROP VIEW loginproperty_vu_prepare_view +GO + +DROP PROC loginproperty_vu_prepare_proc +GO + +DROP FUNCTION loginproperty_vu_prepare_func +GO diff --git a/test/JDBC/input/functions/sys-login-property-vu-prepare.sql b/test/JDBC/input/functions/sys-login-property-vu-prepare.sql new file mode 100644 index 00000000000..99a973bbc5c --- /dev/null +++ b/test/JDBC/input/functions/sys-login-property-vu-prepare.sql @@ -0,0 +1,16 @@ +-- Create dependant objects +CREATE VIEW loginproperty_vu_prepare_view AS +SELECT sys.loginproperty('test_login', 'PasswordHash') +GO + +CREATE PROC loginproperty_vu_prepare_proc AS +SELECT sys.loginproperty('test_login', 'PasswordHash') +GO + +CREATE FUNCTION loginproperty_vu_prepare_func() +RETURNS nvarchar(128) +AS +BEGIN +RETURN sys.loginproperty('test_login', 'PasswordHash') +END +GO diff --git a/test/JDBC/input/functions/sys-login-property-vu-verify.sql b/test/JDBC/input/functions/sys-login-property-vu-verify.sql new file mode 100644 index 00000000000..ca757dcbe46 --- /dev/null +++ b/test/JDBC/input/functions/sys-login-property-vu-verify.sql @@ -0,0 +1,8 @@ +SELECT * FROM loginproperty_vu_prepare_view +GO + +EXEC loginproperty_vu_prepare_proc +GO + +SELECT * FROM loginproperty_vu_prepare_func() +GO diff --git a/test/JDBC/input/getdate-vu-verify.mix b/test/JDBC/input/getdate-vu-verify.mix index 9fa3af9a190..e366bbd196b 100644 --- a/test/JDBC/input/getdate-vu-verify.mix +++ b/test/JDBC/input/getdate-vu-verify.mix @@ -155,6 +155,7 @@ SELECT * from trgdatetimediffTestTab; go -- psql +SET search_path = master_dbo, sys, pg_catalog; SET timezone = '+05:30'; select master_dbo.checkDatetimeDiff(sys.DATEDIFF('MINUTE', sys.SYSDATETIME(), sys.SYSDATETIME() AT TIME ZONE 'UTC'), 330, 1); select master_dbo.checkDatetimeDiff(sys.DATEDIFF('MINUTE', sys.getdate(), sys.getdate() AT TIME ZONE 'UTC'), 330, 1); diff --git a/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.mix b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.mix new file mode 100644 index 00000000000..c22fc0b8045 --- /dev/null +++ b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-cleanup.mix @@ -0,0 +1,57 @@ +-- tsql +USE babel_5448_db +GO +DROP PROC dbo.babel_5448_p1, babel_5448_s1.babel_5448_p1, babel_5448_user_default_schema.babel_5448_p1 +GO +USE master +GO +DROP DATABASE babel_5448_db +GO + +DROP PROC dbo.babel_5448_p, dbo.babel_5448_p1, dbo.babel_5448_p2 +GO +DROP PROC babel_5448_user_default_schema.babel_5448_p, babel_5448_user_default_schema.babel_5448_p1, + babel_5448_user_default_schema.babel_5448_p2 +GO +DROP PROC babel_5448_s1.babel_5448_p, babel_5448_s1.babel_5448_p1, babel_5448_s1.babel_5448_p2 +GO +DROP PROC babel_5448_s1.babel_5448_p5, babel_5448_s1.babel_5448_p6, babel_5448_s1.babel_5448_p7, + babel_5448_s1.babel_5448_p8, babel_5448_s1.babel_5448_p9, babel_5448_s1.babel_5448_p10, + babel_5448_s1.babel_5448_p11, babel_5448_s1.babel_5448_p12, babel_5448_s1.babel_5448_p13, + babel_5448_s1.babel_5448_p14, babel_5448_s1.babel_5448_p15; +GO + +DROP FUNCTION dbo.babel_5448_f +GO +DROP FUNCTION babel_5448_user_default_schema.babel_5448_f +GO +DROP FUNCTION babel_5448_s1.babel_5448_f, babel_5448_s1.babel_5448_f2, + babel_5448_s1.babel_5448_f3, babel_5448_s1.babel_5448_f4, + babel_5448_s1.babel_5448_f5; +GO +DROP FUNCTION babel_5448_s2.babel_5448_f +GO + +DROP TABLE dbo.babel_5448_t +GO +DROP TABLE babel_5448_user_default_schema.babel_5448_t +GO +DROP TABLE babel_5448_s1.babel_5448_t +GO + +DROP VIEW babel_5448_s2.babel_5448_v +GO + +DROP SCHEMA babel_5448_user_default_schema +GO +DROP SCHEMA babel_5448_s1 +GO +DROP SCHEMA babel_5448_s2 +GO + +DROP LOGIN babel_5448_login +GO + +-- psql +DROP FUNCTION master_dbo.babel_5448_plpgsql_func(); +GO diff --git a/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.mix b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.mix new file mode 100644 index 00000000000..9325b7360af --- /dev/null +++ b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-prepare.mix @@ -0,0 +1,647 @@ +-- In this test file we will test babelfish object resolution inside procedure functions and triggers + +-- At high level there are four cases to tests +-- 1. CROSS DB routine calls +-- 2. Same DB routine calls +-- 3. CROSS DB non default user schema +-- 4. Same DB non default user schema + +-- Then each case will be tested against subcases like +-- 1. DMLs +-- 2. DDLs +-- 3. Cross databases objects references +-- 4. EXEC procedure call statements +-- 5. Other tsql statements + +-- Easiest way to test both db_context and search path in a single query +-- is to have both schema specified and non schema specified object references in the query +-- We can skip three part names because they have very straight forward handling and not dependant +-- upon current active logical database or current search path (sp_procs are exception to this and test cases are present elsewhere) + +-- Another important case to test is scope handling +-- This means that search path and current logical database value should be set and reset correctly +-- and we do not leak any of these values in any case +-- For example a search path which was set inside the procedure should not be used for queries after the procedure has ended +-- So we need tests cases like EXEC s1.p; SELECT * FROM t; and check if t is resolved correctly. + + +/***************************************/ +/*************** SAME DB ***************/ +/***************************************/ + +/******** SETUP ********/ + +-- We will work with 3 schemas "dbo" & + +-- tsql +USE master +GO +CREATE SCHEMA babel_5448_user_default_schema +GO +CREATE SCHEMA babel_5448_s1 +GO +CREATE SCHEMA babel_5448_s2 +GO + +-- Now create objects in all three schemas +CREATE TABLE dbo.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_user_default_schema.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_s1.babel_5448_t (id NVARCHAR(max)) +GO + +INSERT INTO dbo.babel_5448_t VALUES ('master.dbo') +INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('master.babel_5448_user_default_schema') +INSERT INTO babel_5448_s1.babel_5448_t VALUES ('master.babel_5448_s1') +GO + +CREATE PROCEDURE dbo.babel_5448_p AS SELECT 'master.dbo' AS col1 +GO +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p AS SELECT 'master.babel_5448_user_default_schema' AS col1 +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p AS SELECT 'master.babel_5448_s1' AS col1 +GO + +CREATE FUNCTION dbo.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.dbo'; +END +GO + +CREATE FUNCTION babel_5448_user_default_schema.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.babel_5448_user_default_schema'; +END +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'master.babel_5448_s1'; +END +GO + +CREATE FUNCTION babel_5448_s2.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN ' |-- function in -- master.babel_5448_s2 --| '; +END +GO + +-- Test declare statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f2() RETURNS NVARCHAR(MAX) +AS +BEGIN + DECLARE @i NVARCHAR(MAX) = (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); + RETURN @i +END +GO + +-- Test return statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f3() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); +END +GO + +CREATE VIEW babel_5448_s2.babel_5448_v AS SELECT ' |-- view in -- master.babel_5448_s2 --| ' AS col1 +GO + +CREATE TRIGGER dbo.babel_5448_trigger +ON dbo.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.dbo' + SELECT dbo.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.dbo' +GO + +CREATE TRIGGER babel_5448_user_default_schema.babel_5448_trigger +ON babel_5448_user_default_schema.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema' + SELECT babel_5448_user_default_schema.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.babel_5448_user_default_schema' +GO + +CREATE TRIGGER babel_5448_s1.babel_5448_trigger +ON babel_5448_s1.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== master.babel_5448_s1' + SELECT babel_5448_s1.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== master.babel_5448_s1' +GO + +CREATE PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROC dbo.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_user_default_schema.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_s1.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +/***************************************/ +/************** CROSS DB ***************/ +/***************************************/ + +CREATE DATABASE babel_5448_db +GO +USE babel_5448_db +GO +CREATE SCHEMA babel_5448_user_default_schema +GO +CREATE SCHEMA babel_5448_s1 +GO +CREATE SCHEMA babel_5448_s2 +GO + +-- Now create objects in all three schemas +CREATE TABLE dbo.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_user_default_schema.babel_5448_t (id NVARCHAR(max)) +GO +CREATE TABLE babel_5448_s1.babel_5448_t (id NVARCHAR(max)) +GO + +INSERT INTO dbo.babel_5448_t VALUES ('babel_5448_db.dbo') +INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('babel_5448_db.babel_5448_user_default_schema') +INSERT INTO babel_5448_s1.babel_5448_t VALUES ('babel_5448_db.babel_5448_s1') +GO + +CREATE PROCEDURE dbo.babel_5448_p AS SELECT 'babel_5448_db.dbo' AS col1 +GO +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p AS SELECT 'babel_5448_db.babel_5448_user_default_schema' AS col1 +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p AS SELECT 'babel_5448_db.babel_5448_s1' AS col1 +GO + +CREATE FUNCTION dbo.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.dbo'; +END +GO + +CREATE FUNCTION babel_5448_user_default_schema.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.babel_5448_user_default_schema'; +END +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN 'babel_5448_db.babel_5448_s1'; +END +GO + +CREATE FUNCTION babel_5448_s2.babel_5448_f() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN ' |-- function in -- babel_5448_db.babel_5448_s2 --| '; +END +GO + +-- Test declare statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f2() RETURNS NVARCHAR(MAX) +AS +BEGIN + DECLARE @i NVARCHAR(MAX) = (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); + RETURN @i +END +GO + +-- Test return statement inside function +CREATE FUNCTION babel_5448_s1.babel_5448_f3() RETURNS NVARCHAR(MAX) +AS +BEGIN + RETURN (SELECT id FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1)); +END +GO + +CREATE VIEW babel_5448_s2.babel_5448_v AS SELECT ' |-- view in -- babel_5448_db.babel_5448_s2 --| ' AS col1 +GO + +CREATE TRIGGER dbo.babel_5448_trigger +ON dbo.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.dbo' + SELECT dbo.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.dbo' +GO + +CREATE TRIGGER babel_5448_user_default_schema.babel_5448_trigger +ON babel_5448_user_default_schema.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema' + SELECT babel_5448_user_default_schema.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_user_default_schema' +GO + +CREATE TRIGGER babel_5448_s1.babel_5448_trigger +ON babel_5448_s1.babel_5448_t +AFTER INSERT AS + SELECT '=========== START OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1' + SELECT babel_5448_s1.babel_5448_f(); + SELECT * FROM babel_5448_t; + SELECT '=========== END OF TRIGGER EXECUTION ========== babel_5448_db.babel_5448_s1' +GO + +CREATE PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_user_default_schema.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT babel_5448_f(), * FROM babel_5448_t; + -- EXEC call should still resolve to dbo.babel_5448_p + EXEC babel_5448_p; + INSERT INTO babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_t; +GO + +CREATE PROC dbo.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_user_default_schema.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE PROC babel_5448_s1.babel_5448_p2 AS + SELECT babel_5448_f(), babel_5448_s2.babel_5448_f(), * FROM + babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + + + +/************************************************************************************************/ +/************************** START OF TRANSACTION AND ERROR **************************************/ +/*********************** CASES TESTING WITH OBJECT RESOLUTION ***********************************/ +/************************************************************************************************/ + +-- create procedures functions which will throw different levels of error +-- and check if search path correctly updated +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p5 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p6 +AS + SELECT '========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + CREATE TABLE #temp (id INT, id1 AS id*2); + ALTER TABLE #temp ADD CONSTRAINT def DEFAULT 1 FOR id1; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p7 +AS + SELECT '========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT * FROM non_existent_table; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f4() RETURNS INT +AS + BEGIN + DECLARE @table_var TABLE(id INT); + INSERT INTO @table_var VALUES (1), (255), (256); + RETURN (SELECT CAST(max(id) AS TINYINT) FROM @table_var); + END +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p5 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p6 +AS + SELECT '========= START OF PROC WHICH WILL THROW BATCH TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + CREATE TABLE #temp (id INT, id1 AS id*2); + ALTER TABLE #temp ADD CONSTRAINT def DEFAULT 1 FOR id1; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p7 +AS + SELECT '========= START OF PROC WHICH WILL THROW TRANSACTION TERMINATING ERROR ====================' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT * FROM non_existent_table; + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f4() RETURNS INT +AS + BEGIN + DECLARE @table_var TABLE(id INT); + INSERT INTO @table_var VALUES (1), (255), (256) + RETURN (SELECT CAST(max(id) AS TINYINT) FROM @table_var); + END +GO + + +/************************************************************************************************/ +/************************** START OF TRY CATCH BLOCK TESTS **************************************/ +/************************************************************************************************/ + +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p8 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ====================' + BEGIN TRY + SELECT '############ IN TRY BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + END TRY + BEGIN CATCH + SELECT '############ IN CATCH BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + END CATCH + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p8 +AS + SELECT '========= START OF PROC WHICH WILL THROW STATEMENT TERMINATING ERROR WITH TRY CATCH ====================' + BEGIN TRY + SELECT '############ IN TRY BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + SELECT 1/0; + END TRY + BEGIN CATCH + SELECT '############ IN CATCH BLOCK ############' + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + END CATCH + SELECT '========= STATEMENT TERMINATING ERROR SO STILL IN EXECUTION AFTER ERROR ====================' +GO + +/*************************************************************************************/ +/************************** START OF DDLs TESTS **************************************/ +/*************************************************************************************/ + +USE master +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p9 +AS + CREATE TABLE #temp (rolename TEXT, roleid TEXT, isapprole TEXT) + CREATE ROLE babel_5448_r1; + CREATE ROLE babel_5448_r2; + ALTER ROLE babel_5448_r1 ADD MEMBER babel_5448_r2; + INSERT INTO #temp EXEC sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC master.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC babel_5448_db.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + DROP ROLE babel_5448_r2; + DROP ROLE babel_5448_r1; + DROP TABLE #temp; +GO + +-- test nested cross database case for ddls +CREATE PROC babel_5448_s1.babel_5448_p10 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC babel_5448_db.babel_5448_s1.babel_5448_p9; +GO + + +USE babel_5448_db +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p9 +AS + CREATE TABLE #temp (rolename TEXT, roleid TEXT, isapprole TEXT) + CREATE ROLE babel_5448_r1; + CREATE ROLE babel_5448_r2; + ALTER ROLE babel_5448_r1 ADD MEMBER babel_5448_r2; + INSERT INTO #temp EXEC sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC master.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + INSERT INTO #temp EXEC babel_5448_db.sys.sp_helprole 'babel_5448_r2'; + SELECT rolename FROM #temp; TRUNCATE TABLE #temp; + DROP ROLE babel_5448_r2; + DROP ROLE babel_5448_r1; + DROP TABLE #temp; +GO + + +/*************************************************************************************/ +/************************** START OF DYNAMIC SQL *************************************/ +/*************************************************************************************/ + + +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p11 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p11 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +/*************************************************************************************/ +/************************* START OF SP_EXECUTE_SQL ***********************************/ +/*************************************************************************************/ + + +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p12 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +USE babel_5448_db +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p12 +AS + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + EXEC('SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); SELECT babel_5448_s1.babel_5448_f2();') + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +/*************************************************************************************/ +/************************* CROSS DB TESTS WITH TEMP TABLE ****************************/ +/*************************************************************************************/ + +USE master +GO + +CREATE PROCEDURE babel_5448_s1.babel_5448_p13 +AS + CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); + DROP TABLE #temp_babel_5448; +GO + +-- same as previous but temp table will be created in another database and used inside this proc +CREATE PROCEDURE babel_5448_s1.babel_5448_p14 +AS + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); +GO + +/*************************************************************************************/ +/******************************** INTEROPERABILITY ***********************************/ +/*************************************************************************************/ + +-- psql +CREATE FUNCTION master_dbo.babel_5448_plpgsql_func() +RETURNS TEXT +AS +$$ BEGIN return (SELECT id FROM babel_5448_t); END; $$ +LANGUAGE plpgsql; +GO + +-- tsql +CREATE PROCEDURE babel_5448_s1.babel_5448_p15 +AS + CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); + DROP TABLE #temp_babel_5448; +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f5() RETURNS NVARCHAR(MAX) AS +BEGIN + return (SELECT babel_5448_plpgsql_func()) +END; +GO + +-- same as previous but temp table will be created in another database and used inside this proc +USE babel_5448_db +GO +CREATE PROCEDURE babel_5448_s1.babel_5448_p15 +AS + INSERT INTO #temp_babel_5448 VALUES ('<-------- temp table --------->'); + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1) JOIN #temp_babel_5448 ON (1=1); + SELECT '<----------------------- start of plpgsql function ----------------------->' + SELECT master.dbo.babel_5448_plpgsql_func(); + SELECT '<----------------------- end of plpgsql function ----------------------->' + SELECT * FROM babel_5448_s2.babel_5448_v JOIN #temp_babel_5448 ON (1=1); + SELECT * FROM babel_5448_t JOIN #temp_babel_5448 ON (1=1); +GO + +CREATE FUNCTION babel_5448_s1.babel_5448_f5() RETURNS NVARCHAR(MAX) AS +BEGIN + return (SELECT master.dbo.babel_5448_plpgsql_func()) +END; +GO diff --git a/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.mix b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.mix new file mode 100644 index 00000000000..73903889179 --- /dev/null +++ b/test/JDBC/input/object_resolution/BABEL_OBJECT_RESOLUTION_IN_ROUTINES-vu-verify.mix @@ -0,0 +1,481 @@ +-- All tests will be triggered from babel_5448_db database +-- For cross database, we will use master database + +-- tsql + +/*********************************/ +/*********** SAME DB ************/ +/*********************************/ + +USE babel_5448_db +GO + +-- All objects should resolve to babel_5448_db.dbo schema in this call +EXEC dbo.babel_5448_p1 +GO + +-- All objects should resolve to babel_5448_db.babel_5448_s1 schema in this call +-- except EXEC call stmt +EXEC babel_5448_s1.babel_5448_p1 +GO + +-- Now we will run the same procedures again but this time we will references objects from other schema +-- proc in dbo will reference objects from babel_5448_user_default_schema schema +-- proc in babel_5448_s1 will reference objects from dbo schema + +ALTER PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_user_default_schema.babel_5448_f(), * FROM babel_5448_user_default_schema.babel_5448_t; + EXEC babel_5448_user_default_schema.babel_5448_p; + INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_user_default_schema.babel_5448_t; +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT dbo.babel_5448_f(), * FROM dbo.babel_5448_t; + EXEC dbo.babel_5448_p; + INSERT INTO dbo.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM dbo.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM dbo.babel_5448_t; +GO + +-- All objects should resolve to babel_5448_db.babel_5448_user_default_schema schema in this call +EXEC dbo.babel_5448_p1 +GO + +-- All objects should resolve to babel_5448_db.dbo schema in this call +EXEC babel_5448_s1.babel_5448_p1 +GO + +-- testing different schemas +-- procedure and function will be on same schema but +-- table & trigger will be different schema +-- basically testing row level search path changes +ALTER PROCEDURE dbo.babel_5448_p1 +AS + INSERT INTO babel_5448_user_default_schema.babel_5448_t SELECT babel_5448_f() FROM generate_series(1,3); + -- trigger execution will tells use what the function resolved to + -- and what the objects inside triggers resolved to + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE id != 'babel_5448_db.babel_5448_user_default_schema' +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + INSERT INTO dbo.babel_5448_t SELECT babel_5448_f() FROM generate_series(1,3); + -- trigger execution will tells use what the function resolved to + -- and what the objects inside triggers resolved to + DELETE FROM dbo.babel_5448_t WHERE id != 'babel_5448_db.dbo' +GO + + +EXEC dbo.babel_5448_p1 +GO + +EXEC babel_5448_s1.babel_5448_p1 +GO + +-- Test INSERT EXEC +CREATE TABLE #temp (col1 NVARCHAR(MAX), col2 NVARCHAR(MAX), col3 NVARCHAR(MAX), col4 NVARCHAR(MAX)) +GO + +INSERT INTO #temp EXEC dbo.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO + +INSERT INTO #temp EXEC babel_5448_s1.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO + +DROP TABLE #temp +GO + +-- Test declare statement inside function +SELECT babel_5448_s1.babel_5448_f2(); + +-- Test declare statement inside function +SELECT babel_5448_s1.babel_5448_f3(); +GO + +/*********************************/ +/*********** CROSS DB ************/ +/*********************************/ + +USE babel_5448_db +GO + +-- All objects should resolve to master.dbo schema in this call +EXEC master.dbo.babel_5448_p1 +GO + +-- All objects should resolve to master.babel_5448_s1 schema in this call +-- except EXEC call stmt +EXEC master.babel_5448_s1.babel_5448_p1 +GO + +-- Now we need to alter the procedure so switch to master database +-- alter the master database procedures and then execute then from +-- babel_5448_db again +USE master +GO + +ALTER PROCEDURE dbo.babel_5448_p1 +AS + SELECT babel_5448_user_default_schema.babel_5448_f(), * FROM babel_5448_user_default_schema.babel_5448_t; + EXEC babel_5448_user_default_schema.babel_5448_p; + INSERT INTO babel_5448_user_default_schema.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM babel_5448_user_default_schema.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM babel_5448_user_default_schema.babel_5448_t; +GO + +ALTER PROCEDURE babel_5448_s1.babel_5448_p1 +AS + SELECT dbo.babel_5448_f(), * FROM dbo.babel_5448_t; + EXEC dbo.babel_5448_p; + INSERT INTO dbo.babel_5448_t VALUES ('temp inserted row to check DML and trigger executiong'); + DELETE FROM dbo.babel_5448_t WHERE length(id) > 50; + -- CHECK IF ROW WAS DELETED FROM THE RIGHT TABLE + SELECT * FROM dbo.babel_5448_t; +GO + +USE babel_5448_db +GO + +-- Now execute the altered master database procedures +-- All objects should resolve to master.babel_5448_user_default_schema schema in this call +EXEC master.dbo.babel_5448_p1 +GO + +-- All objects should resolve to master.dbo schema in this call +EXEC master.babel_5448_s1.babel_5448_p1 +GO + +-- Test INSERT EXEC +CREATE TABLE #temp (col1 NVARCHAR(MAX), col2 NVARCHAR(MAX), col3 NVARCHAR(MAX), col4 NVARCHAR(MAX)) +GO + +INSERT INTO #temp EXEC master.dbo.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO +EXEC master.babel_5448_s1.babel_5448_p2 +GO +INSERT INTO #temp EXEC master.babel_5448_s1.babel_5448_p2 +SELECT * FROM #temp +TRUNCATE TABLE #temp +GO + +-- Test declare statement inside function +SELECT master.babel_5448_s1.babel_5448_f2(); + +-- Test declare statement inside function +SELECT master.babel_5448_s1.babel_5448_f3(); +GO + +DROP TABLE #temp +GO + + +/************************************************************************************************/ +/************************** START OF TRANSACTION AND ERROR **************************************/ +/*********************** CASES TESTING WITH OBJECT RESOLUTION ***********************************/ +/************************************************************************************************/ + +/*********** SAME DB ************/ +EXEC babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +EXEC babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +EXEC babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO + +SELECT babel_5448_s1.babel_5448_f4(); +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +/*********** SAME DB ************/ +/*********** BUT INSIDE TRAN ************/ + +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO + +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO + +BEGIN TRAN +GO +EXEC babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO + +BEGIN TRAN +GO +SELECT babel_5448_s1.babel_5448_f4(); +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +COMMIT +GO + +/*********** CROSS DB ************/ +EXEC master.babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +EXEC master.babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +EXEC master.babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO + +SELECT master.babel_5448_s1.babel_5448_f4() FROM generate_series(1,3); +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO + +/*********** CROSS DB ************/ +/*********** BUT INSIDE TRAN ************/ + +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p5 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO + +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p6 +SELECT '========= CURRENT BATCH TERMINATING ERROR ONLY SO STILL IN EXECUTION OUTSIDE ERROR BATCH ====================' +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +COMMIT +GO + +BEGIN TRAN +GO +EXEC master.babel_5448_s1.babel_5448_p7 +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +SELECT '========= END OF TRANSACTION ABORTING ERROR ====================' +GO + +BEGIN TRAN +GO +SELECT master.babel_5448_s1.babel_5448_f4() FROM generate_series(1,3); +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +COMMIT +GO + +/************************************************************************************************/ +/************************** START OF TRY CATCH BLOCK TESTS **************************************/ +/************************************************************************************************/ + +USE babel_5448_db +GO + +BEGIN TRY + EXEC babel_5448_s1.babel_5448_p8 + SELECT 1/0; +END TRY +BEGIN CATCH + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + USE msdb + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +END CATCH +GO + +SELECT db_name() +GO + +USE babel_5448_db +GO + +BEGIN TRY + EXEC babel_5448_s1.babel_5448_p8 + SELECT 1/0; +END TRY +BEGIN CATCH + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); + USE msdb + SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +END CATCH +GO + +SELECT db_name() +GO + +USE babel_5448_db +GO + +/*************************************************************************************/ +/************************** START OF DDLs TESTS **************************************/ +/*************************************************************************************/ + +EXEC babel_5448_s1.babel_5448_p9; +GO + +EXEC master.babel_5448_s1.babel_5448_p9; +GO + +-- run this in a new connection to avoid hitting BABEL-5604 +-- tsql database=babel_5448_db +EXEC master.babel_5448_s1.babel_5448_p10; +GO + +/*************************************************************************************/ +/************************** START OF DYNAMIC SQL *************************************/ +/*************************************************************************************/ + +EXEC babel_5448_s1.babel_5448_p11; +GO + +EXEC master.babel_5448_s1.babel_5448_p11; +GO + +/*************************************************************************************/ +/************************* START OF SP_EXECUTE_SQL ***********************************/ +/*************************************************************************************/ + +EXEC babel_5448_s1.babel_5448_p12; +GO + +EXEC master.babel_5448_s1.babel_5448_p12; +GO + +/*************************************************************************************/ +/***************** VERIFY DEFAULT SCHEMA OF IN BUILT USERS ***************************/ +/*************************************************************************************/ + +SELECT database_name, orig_username, default_schema_name FROM sys.babelfish_authid_user_ext +WHERE database_name IN ('master', 'tempdb', 'msdb', 'babel_5448_db') AND + orig_username IN ('dbo', 'guest') +ORDER BY database_name, orig_username; +GO + +-- tsql +USE master +GO +CREATE LOGIN babel_5448_login WITH PASSWORD = '12345678' +GO +GRANT CONNECT TO guest +GO + +SELECT current_setting('search_path') +GO +-- tsql user=babel_5448_login password=12345678 database=master +SELECT current_setting('search_path') +GO + +/*************************************************************************************/ +/************************* CROSS DB TESTS WITH TEMP TABLE ****************************/ +/*************************************************************************************/ + +-- tsql database=babel_5448_db +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +EXEC master.babel_5448_s1.babel_5448_p13 +GO + +CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +EXEC master.babel_5448_s1.babel_5448_p14 +GO +DROP TABLE #temp_babel_5448; +GO + +BEGIN + IF OBJECT_ID ('tempdb..#temp') IS NOT NULL + BEGIN + DROP TABLE #temp; + END; SELECT TOP 111 * + INTO #temp + FROM ( SELECT col1 AS col1_cross_db FROM master.babel_5448_s2.babel_5448_v) + JOIN babel_5448_t ON (1=1) + JOIN babel_5448_s2.babel_5448_v ON (1=1); + + SELECT * FROM #temp; +END; +GO + +BEGIN + IF OBJECT_ID ('tempdb..#temp') IS NOT NULL + BEGIN + DROP TABLE #temp; + END; + USE master; + SELECT TOP 111 * + INTO #temp + FROM (SELECT col1 AS col1_cross_db FROM babel_5448_db.babel_5448_s2.babel_5448_v) + JOIN babel_5448_t ON (1=1) + JOIN babel_5448_s2.babel_5448_v ON (1=1); + + USE babel_5448_db; + + SELECT * FROM #temp; +END; +GO + +/*************************************************************************************/ +/******************************** INTEROPERABILITY ***********************************/ +/*************************************************************************************/ + +-- tsql +USE master +GO + +-- plpgsql function call outside any procedure or function +SELECT babel_5448_plpgsql_func(); +GO + +-- tsql database=babel_5448_db +USE babel_5448_db +GO +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +EXEC master.babel_5448_s1.babel_5448_p15 +GO + +SELECT master.babel_5448_s1.babel_5448_f5(); + +CREATE TABLE #temp_babel_5448 (id NVARCHAR(MAX)); +SELECT * FROM babel_5448_t JOIN babel_5448_s2.babel_5448_v ON (1=1); +GO +EXEC babel_5448_s1.babel_5448_p15 +GO +DROP TABLE #temp_babel_5448; +GO + +SELECT babel_5448_s1.babel_5448_f5(); +GO diff --git a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-cleanup.mix b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-cleanup.mix index 867c5cdcf83..13ae31cd78f 100644 --- a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-cleanup.mix +++ b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-cleanup.mix @@ -140,3 +140,9 @@ GO DROP SCHEMA babel_cross_db_vu_prepare_myschema GO + +DROP PROCEDURE babel_5448_p02, babel_5448_p01 +GO + +DROP PROC sp_test_babel_5448_1, sp_test_babel_5448_2 +GO diff --git a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-prepare.mix b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-prepare.mix index 425e73d24f6..b5aae9d09b1 100644 --- a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-prepare.mix +++ b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-prepare.mix @@ -275,3 +275,78 @@ GO GRANT SELECT ON babel_cross_db_vu_prepare_t4 TO guest; GO + +------------------ BABEL-5448 ------------------ +------------------------------------------------ +USE master; +GO + +CREATE PROCEDURE dbo.babel_5448_p01 AS +BEGIN + SELECT 'This is correct datbase dbname = master'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p02 AS +BEGIN + EXECUTE dbo.babel_5448_p01; -- schema.proc + EXECUTE master.dbo.babel_5448_p01; -- db.schema.proc + EXECUTE master..babel_5448_p01; -- db..proc + EXECUTE babel_5448_p01; -- proc +END; +GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +CREATE PROCEDURE dbo.babel_5448_p01 AS +BEGIN + SELECT 'This is the incorrect database: dbname = my_babel_cross_db_vu_prepare_db1'; +END; +GO + +CREATE PROCEDURE dbo.babel_5448_p03 AS +BEGIN + EXECUTE master.dbo.babel_5448_p02; +END; +GO + +------------------------------------------------ +--------------- sp_proc cross db --------------- +------------------------------------------------ + +USE master; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is correct: master.dbo.sp_test_babel_5448_1' +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_2 AS +BEGIN +EXECUTE master..sp_test_babel_5448_1; +EXECUTE sp_test_babel_5448_1; +EXECUTE dbo.sp_test_babel_5448_1; +EXECUTE master.dbo.sp_test_babel_5448_1; +END; +GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_1 AS +BEGIN +SELECT N'This is the incorrect database: my_babel_cross_db_vu_prepare_db1.dbo.sp_test_babel_5448_1'; +END; +GO + +CREATE PROCEDURE dbo.sp_test_babel_5448_3 AS +BEGIN +EXECUTE master.dbo.sp_test_babel_5448_2; +END; +GO + +----------- END OF BABEL-5448 ------------------ +------------------------------------------------ diff --git a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-verify.mix b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-verify.mix index 4a20c1731fc..890a875d356 100644 --- a/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-verify.mix +++ b/test/JDBC/input/ownership/BABEL-CROSS-DB-vu-verify.mix @@ -926,3 +926,14 @@ GO -- tsql USE master GO + +USE my_babel_cross_db_vu_prepare_db1; +GO + +EXECUTE dbo.babel_5448_p03; +GO + +SELECT db_name() +GO +EXECUTE dbo.sp_test_babel_5448_3; +GO diff --git a/test/JDBC/input/ownership/schema_resolution_trigger-vu-verify.sql b/test/JDBC/input/ownership/schema_resolution_trigger-vu-verify.sql index 0816b8c186c..0e7637c04d6 100644 --- a/test/JDBC/input/ownership/schema_resolution_trigger-vu-verify.sql +++ b/test/JDBC/input/ownership/schema_resolution_trigger-vu-verify.sql @@ -1,3 +1,20 @@ +-- need to and recreate trigger if it exists in the incorrect schema +BEGIN TRAN +GO +IF NOT EXISTS ( + SELECT * FROM pg_proc + WHERE proname = 'schema_resolution_trigger_tr2' AND + pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'master_schema_resolution_trigger_s1')) +BEGIN + DROP TRIGGER schema_resolution_trigger_s1.schema_resolution_trigger_tr2; +END +GO +IF NOT EXISTS (select * from sys.objects where type = 'TR' and name = 'schema_resolution_trigger_tr2') +EXEC dbo.sp_executesql @statement = N'create trigger schema_resolution_trigger_s1.schema_resolution_trigger_tr2 on schema_resolution_trigger_s1.schema_resolution_trigger_mytab for insert as +select * from schema_resolution_trigger_t1' +COMMIT +GO + -- Resolves to dbo.schema_resolution_trigger_t1 insert into dbo.schema_resolution_trigger_mytab values(1) go diff --git a/test/JDBC/input/permission_restrictions_from_pg.mix b/test/JDBC/input/permission_restrictions_from_pg.mix index a5c5770f0ab..04e3b3ef4f3 100644 --- a/test/JDBC/input/permission_restrictions_from_pg.mix +++ b/test/JDBC/input/permission_restrictions_from_pg.mix @@ -8,6 +8,32 @@ go create user permission_restrictions_tsql_user1 for login permission_restrictions_tsql_login1; go +-- create user for a login in master, tempdb and msdb +create login permission_restrictions_tsql_login2 with password = '123'; +go + +create user permission_restrictions_tsql_login2; +go + +use tempdb; +go + +create user permission_restrictions_tsql_login2; +go + +use msdb; +go + +create user permission_restrictions_tsql_login2; +go + +use master +go + +-- create a login with no mapped user +create login permission_restrictions_tsql_login3 with password = '123'; +go + -- psql create user permission_restrictions_psql_user with password '123'; go @@ -39,6 +65,9 @@ go grant permission_restrictions_tsql_login1 to permission_restrictions_psql_user; go +grant permission_restrictions_tsql_login2 to permission_restrictions_psql_user; +go + grant master_db_datareader to master_db_datareader; go @@ -46,6 +75,12 @@ go drop user permission_restrictions_tsql_login1; go +drop user permission_restrictions_tsql_login2; +go + +drop user permission_restrictions_tsql_login3; +go + drop user master_permission_restrictions_tsql_user1; go @@ -97,6 +132,9 @@ go grant permission_restrictions_tsql_login1 to permission_restrictions_psql_user; go +grant permission_restrictions_tsql_login2 to permission_restrictions_psql_user; +go + grant master_db_datareader to master_db_datareader; go @@ -104,6 +142,12 @@ go drop user permission_restrictions_tsql_login1; go +drop user permission_restrictions_tsql_login2; +go + +drop user permission_restrictions_tsql_login3; +go + drop user master_permission_restrictions_tsql_user1; go @@ -147,6 +191,10 @@ SELECT pg_terminate_backend(pid) FROM pg_stat_get_activity(NULL) WHERE sys.suser_name(usesysid) = 'permission_restrictions_tsql_login1' AND backend_type = 'client backend' AND usesysid IS NOT NULL; GO +SELECT pg_terminate_backend(pid) FROM pg_stat_get_activity(NULL) +WHERE sys.suser_name(usesysid) = 'permission_restrictions_tsql_login2' AND backend_type = 'client backend' AND usesysid IS NOT NULL; +GO + select pg_sleep(1); GO @@ -154,8 +202,29 @@ GO drop user permission_restrictions_tsql_user1; go +drop user permission_restrictions_tsql_login2; +go + +use tempdb +go + +drop user permission_restrictions_tsql_login2; +go + +use msdb +go + +drop user permission_restrictions_tsql_login2; +go + drop login permission_restrictions_tsql_login1; go +drop login permission_restrictions_tsql_login2; +go + drop login permission_restrictions_tsql_login go + +drop login permission_restrictions_tsql_login3; +go diff --git a/test/JDBC/input/select_into-identity-notnull.sql b/test/JDBC/input/select_into-identity-notnull.sql new file mode 100644 index 00000000000..e9c88836a95 --- /dev/null +++ b/test/JDBC/input/select_into-identity-notnull.sql @@ -0,0 +1,263 @@ +create database db_select_into +go + +use db_select_into +go + +create schema sch_select_into +go + +create table t1_select_into ([Col1] INT IDENTITY(1, 1), [Col2] [NVarchar](20) NOT NULL) +go + +insert into t1_select_into([Col2]) values ('First') +go + +set identity_insert t1_select_into on +go + +insert into t1_select_into([Col1], [Col2]) values (1, 'First_dup') +go + +set identity_insert t1_select_into off +go + +create view v1_select_into as select * from t1_select_into +go + +create table sch_select_into.t1_select_into ([Col3] TINYINT IDENTITY(2, 2), [Col4] numeric(4,3) NOT NULL) +go + +insert into sch_select_into.t1_select_into([Col4]) values (2.222) +go + +use master +go + +create schema sch_select_into_master +go + +create table sch_select_into_master.t1_select_into_master ([Col5] SMALLINT IDENTITY(3, 3), [Col6] [Nvarchar](20) NOT NULL) +go + +insert into sch_select_into_master.t1_select_into_master([Col6]) values ('Third') +go + +create table t1_select_into_master ([Col7] float NOT NULL, [Col8] BIGINT IDENTITY(4, 4)) +go + +insert into t1_select_into_master([Col7]) values (4.4) +go + +create table t1_select_into_master_dec ([Col9] DECIMAL(10,0) IDENTITY(5, 5) PRIMARY KEY, [Col10] real NOT NULL) +go + +insert into t1_select_into_master_dec([Col10]) values (5.567) +go + +use db_select_into +go + +select * into dest_table_1 from t1_select_into order by [Col1] +go + +select * into dest_table_2 from sch_select_into.t1_select_into group by [Col3], [Col4] +go + +select * into dest_table_3 from master.sch_select_into_master.t1_select_into_master +go + +select * into dest_table_4 from master..t1_select_into_master +go + +select * into dest_table_5 from master.dbo.t1_select_into_master_dec +go + +exec sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_identity_function', 'ignore'; +go + +-- Should throw error because there are 2 identity columns +select identity(int, 1, 1) as identity_col, * into dest_table_error from t1_select_into +go + +exec sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_identity_function', 'strict'; +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_1 ([Col2]) values (NULL) +go + +insert into dest_table_1 ([Col2]) values ('Second') +go + +-- Identity column should be populated by default +select * from dest_table_1 order by [Col1] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_2 ([Col4]) values (NULL) +go + +insert into dest_table_2 ([Col4]) values (3.333) +go + +-- Identity column should be populated by default +select * from dest_table_2 order by [Col3] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_3 ([Col6]) values (NULL) +go + +insert into dest_table_3 ([Col6]) values ('Fourth') +go + +-- Identity column should be populated by default +select * from dest_table_3 order by [Col5] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_4 ([Col7]) values (NULL) +go + +insert into dest_table_4 ([Col7]) values (5.5) +go + +-- Identity column should be populated by default +select * from dest_table_4 order by [Col8] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_5 ([Col10]) values (NULL) +go + +insert into dest_table_5 ([Col10]) values (6.789) +go + +-- Identity column should be populated by default +select * from dest_table_5 order by [Col9] +go + +-- FROM clause contains joins from multiple tables +-- Should not fail as identity should not be persisted but nullability should +select * +into dest_table_join +from dest_table_1 t1 +inner join dest_table_2 t2 +on t1.[Col1] * 2 = t2.[Col3] +go + +select * from dest_table_join order by [Col1], [Col2] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_join ([Col2]) values (NULL) +go + +-- Should fail. Violate NOT NULL constraint on other column +insert into dest_table_join ([Col2]) values ('Join') +go + +insert into dest_table_join ([Col1], [Col2], [Col3], [Col4]) values (99, 'Join', 88, 9.867) +go + +select * from dest_table_join order by [Col1], [Col2] +go + +-- FROM clause contains subquery +select * +into dest_table_union +from +( + select * from dest_table_1 + union all + select * from dest_table_3 +) as combined_tables +go + +select * from dest_table_union order by [Col1] +go + +-- Ideally should fail as it violates NOT NULL constraint +-- Currently NOT NULL constraint won't get carried over +-- to destination table in case of subquery +insert into dest_table_union ([Col2]) values (NULL) +go + +insert into dest_table_union ([Col2]) values ('Union') +go + +select * from dest_table_union order by [Col1] +go + +select * +into dest_table_sub_join +from +( + select * from dest_table_1 t1 + inner join dest_table_2 t2 + on t1.[Col1] * 2 = t2.[Col3] +) as combined_tables +go + +select * from dest_table_sub_join order by [Col1], [Col2] +go + +-- Should fail. Violate NOT NULL constraint +insert into dest_table_sub_join ([Col1]) values (NULL) +go + +-- Should fail. Violate NOT NULL constraint on other column +insert into dest_table_sub_join ([Col1]) values (200) +go + +insert into dest_table_sub_join ([Col1], [Col2], [Col3], [Col4]) values (209, 'Sub-Join', 78, 8.567) +go + +select * from dest_table_sub_join order by [Col1], [Col2] +go + +select * into dest_table_view from v1_select_into +go + +select * from dest_table_view order by [Col1], [Col2] +go + +drop table dest_table_1 +drop table dest_table_2 +drop table dest_table_3 +drop table dest_table_4 +drop table dest_table_5 +drop table dest_table_join +drop table dest_table_union +drop table dest_table_sub_join +drop view v1_select_into +drop table dest_table_view +go + +drop table t1_select_into +go + +drop table sch_select_into.t1_select_into +go + +drop schema sch_select_into +go + +use master +go + +drop database db_select_into +go + +drop table t1_select_into_master +go + +drop table t1_select_into_master_dec +go + +drop table sch_select_into_master.t1_select_into_master +go + +drop schema sch_select_into_master +go diff --git a/test/JDBC/input/sp_proc.sql b/test/JDBC/input/sp_proc.mix similarity index 51% rename from test/JDBC/input/sp_proc.sql rename to test/JDBC/input/sp_proc.mix index 9831db05d73..f95c152b0de 100644 --- a/test/JDBC/input/sp_proc.sql +++ b/test/JDBC/input/sp_proc.mix @@ -1,3 +1,4 @@ +-- tsql create proc sp_hello as select 1 go @@ -95,9 +96,50 @@ go exec @a; go +use master +go +create table sometableinmaster(somecolumn INT) +go +use db1 +go +create schema s1 +go + +-- should resolve to db1.dbo.sp_hello +exec db1.dbo.sp_hello +go +exec db1..sp_hello +go + +-- should throw an error +exec db1.sys.sp_hello +go + +-- should thorw an error +exec db1.s1.sp_hello +go + drop proc sp_hello; go +-- should resolve to master.dbo.sp_hello since proc does not exists in db1 +-- special behaviour for sp_ procs +exec db1.dbo.sp_hello +go +exec db1..sp_hello +go + +-- should resolve to sys sp_tables +exec db1.dbo.sp_tables +go +exec db1..sp_tables +go +-- procedure should be executed as if current db was master +exec master..sp_tables @table_name = N'sometableinmaster' +go +exec master.dbo.sp_tables @table_name = N'sometableinmaster' +go + use master go @@ -193,8 +235,45 @@ go use master go +drop table sometableinmaster +go drop proc sp_hello go +use db1 +go +create schema s1 +go + create login non_default_schema_login with password = '12345678' +go +create user non_default_schema_login +go +alter user non_default_schema_login with default_schema = s1 +go +create proc s1.sp_user_proc as select '--- S1 ---'; +go +create proc dbo.sp_user_proc as select '--- DBO ---'; +go +alter role db_owner add member non_default_schema_login +go + +-- tsql user=non_default_schema_login password=12345678 database=db1 +select schema_name(), db_name() +go +-- should resolve to s1.sp_user_proc +exec sp_user_proc +exec db1..sp_user_proc +go +-- should resolve to dbo.sp_user_proc +exec dbo.sp_user_proc +exec db1.dbo.sp_user_proc +go +-- terminate-tsql-conn user=non_default_schema_login password=12345678 database=db1 + +-- tsql +use master +go +drop login non_default_schema_login +go drop database db1 go diff --git a/test/JDBC/input/views/sys_credentials-vu-cleanup.sql b/test/JDBC/input/views/sys_credentials-vu-cleanup.sql new file mode 100644 index 00000000000..7ad520d2d0b --- /dev/null +++ b/test/JDBC/input/views/sys_credentials-vu-cleanup.sql @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_credentials_vu_prepare_view +GO + +DROP PROC sys_credentials_vu_prepare_proc +GO + +DROP FUNCTION sys_credentials_vu_prepare_func +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_credentials-vu-prepare.sql b/test/JDBC/input/views/sys_credentials-vu-prepare.sql new file mode 100644 index 00000000000..b33cb55bbaa --- /dev/null +++ b/test/JDBC/input/views/sys_credentials-vu-prepare.sql @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_credentials_vu_prepare_view AS +SELECT * FROM sys.credentials +GO + +CREATE PROC sys_credentials_vu_prepare_proc AS +SELECT * FROM sys.credentials +GO + +CREATE FUNCTION sys_credentials_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.credentials) +END +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_credentials-vu-verify.sql b/test/JDBC/input/views/sys_credentials-vu-verify.sql new file mode 100644 index 00000000000..2772f0e2e39 --- /dev/null +++ b/test/JDBC/input/views/sys_credentials-vu-verify.sql @@ -0,0 +1,14 @@ +USE master +GO + +SELECT * FROM sys.credentials +GO + +SELECT * FROM sys_credentials_vu_prepare_view +GO + +EXEC sys_credentials_vu_prepare_proc +GO + +SELECT sys_credentials_vu_prepare_func() +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_server_permissions-vu-cleanup.sql b/test/JDBC/input/views/sys_server_permissions-vu-cleanup.sql new file mode 100644 index 00000000000..4416361024b --- /dev/null +++ b/test/JDBC/input/views/sys_server_permissions-vu-cleanup.sql @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_server_permissions_vu_prepare_view +GO + +DROP PROC sys_server_permissions_vu_prepare_proc +GO + +DROP FUNCTION sys_server_permissions_vu_prepare_func +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_server_permissions-vu-prepare.sql b/test/JDBC/input/views/sys_server_permissions-vu-prepare.sql new file mode 100644 index 00000000000..1fa5474b850 --- /dev/null +++ b/test/JDBC/input/views/sys_server_permissions-vu-prepare.sql @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_server_permissions_vu_prepare_view AS +SELECT * FROM sys.server_permissions +GO + +CREATE PROC sys_server_permissions_vu_prepare_proc AS +SELECT * FROM sys.server_permissions +GO + +CREATE FUNCTION sys_server_permissions_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.server_permissions) +END +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_server_permissions-vu-verify.sql b/test/JDBC/input/views/sys_server_permissions-vu-verify.sql new file mode 100644 index 00000000000..ef66ad47d42 --- /dev/null +++ b/test/JDBC/input/views/sys_server_permissions-vu-verify.sql @@ -0,0 +1,14 @@ +USE master +GO + +SELECT * FROM sys.server_permissions +GO + +SELECT * FROM sys_server_permissions_vu_prepare_view +GO + +EXEC sys_server_permissions_vu_prepare_proc +GO + +SELECT sys_server_permissions_vu_prepare_func() +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_sql_logins-vu-cleanup.sql b/test/JDBC/input/views/sys_sql_logins-vu-cleanup.sql new file mode 100644 index 00000000000..a7c907d2989 --- /dev/null +++ b/test/JDBC/input/views/sys_sql_logins-vu-cleanup.sql @@ -0,0 +1,11 @@ +USE master +GO + +DROP VIEW sys_sql_logins_vu_prepare_view +GO + +DROP PROC sys_sql_logins_vu_prepare_proc +GO + +DROP FUNCTION sys_sql_logins_vu_prepare_func +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_sql_logins-vu-prepare.sql b/test/JDBC/input/views/sys_sql_logins-vu-prepare.sql new file mode 100644 index 00000000000..5ca6023fc06 --- /dev/null +++ b/test/JDBC/input/views/sys_sql_logins-vu-prepare.sql @@ -0,0 +1,18 @@ +USE master +GO + +CREATE VIEW sys_sql_logins_vu_prepare_view AS +SELECT * FROM sys.sql_logins +GO + +CREATE PROC sys_sql_logins_vu_prepare_proc AS +SELECT * FROM sys.sql_logins +GO + +CREATE FUNCTION sys_sql_logins_vu_prepare_func() +RETURNS INT +AS +BEGIN + RETURN (SELECT COUNT(*) FROM sys.sql_logins) +END +GO \ No newline at end of file diff --git a/test/JDBC/input/views/sys_sql_logins-vu-verify.sql b/test/JDBC/input/views/sys_sql_logins-vu-verify.sql new file mode 100644 index 00000000000..4d4cd8d73a6 --- /dev/null +++ b/test/JDBC/input/views/sys_sql_logins-vu-verify.sql @@ -0,0 +1,14 @@ +USE master +GO + +SELECT * FROM sys.sql_logins +GO + +SELECT * FROM sys_sql_logins_vu_prepare_view +GO + +EXEC sys_sql_logins_vu_prepare_proc +GO + +SELECT sys_sql_logins_vu_prepare_func() +GO \ No newline at end of file diff --git a/test/JDBC/upgrade/14_15/schedule b/test/JDBC/upgrade/14_15/schedule index a898cf64b70..5d93916303a 100644 --- a/test/JDBC/upgrade/14_15/schedule +++ b/test/JDBC/upgrade/14_15/schedule @@ -479,3 +479,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/14_18/schedule b/test/JDBC/upgrade/14_18/schedule index ceb83c59e5e..6e6e2d5cfa5 100644 --- a/test/JDBC/upgrade/14_18/schedule +++ b/test/JDBC/upgrade/14_18/schedule @@ -479,3 +479,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/15_10/schedule b/test/JDBC/upgrade/15_10/schedule index dc9055a6680..4cdcaaf1bab 100644 --- a/test/JDBC/upgrade/15_10/schedule +++ b/test/JDBC/upgrade/15_10/schedule @@ -570,3 +570,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/15_13/schedule b/test/JDBC/upgrade/15_13/schedule index ad64955d61f..53888e3e061 100644 --- a/test/JDBC/upgrade/15_13/schedule +++ b/test/JDBC/upgrade/15_13/schedule @@ -570,3 +570,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/15_7/schedule b/test/JDBC/upgrade/15_7/schedule index 23c094957cd..251b0cf84a4 100644 --- a/test/JDBC/upgrade/15_7/schedule +++ b/test/JDBC/upgrade/15_7/schedule @@ -578,3 +578,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/15_8/schedule b/test/JDBC/upgrade/15_8/schedule index 3524054c893..19d8acbc02b 100644 --- a/test/JDBC/upgrade/15_8/schedule +++ b/test/JDBC/upgrade/15_8/schedule @@ -570,3 +570,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/16_4/schedule b/test/JDBC/upgrade/16_4/schedule index a32c610ef64..55e911ee494 100644 --- a/test/JDBC/upgrade/16_4/schedule +++ b/test/JDBC/upgrade/16_4/schedule @@ -596,3 +596,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/16_6/schedule b/test/JDBC/upgrade/16_6/schedule index 40a980e60a6..013a82d6189 100644 --- a/test/JDBC/upgrade/16_6/schedule +++ b/test/JDBC/upgrade/16_6/schedule @@ -599,3 +599,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char_before_17_4 +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/16_9/schedule b/test/JDBC/upgrade/16_9/schedule index d0461923eda..6b2953d4ae0 100644 --- a/test/JDBC/upgrade/16_9/schedule +++ b/test/JDBC/upgrade/16_9/schedule @@ -605,3 +605,4 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index bc60a049b83..70fb91ef323 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -602,3 +602,9 @@ test_conv_money_to_varchar fixeddecimal_modulo BABEL-NUMERIC_EXPR test_conv_float_to_varchar_char +sys_credentials +sys_server_permissions +sys_sql_logins +sys-login-property +sys-fn-varbintohexsubstring +BABEL_OBJECT_RESOLUTION_IN_ROUTINES diff --git a/test/dotnet/ExpectedOutput/ddl_logins.out b/test/dotnet/ExpectedOutput/ddl_logins.out new file mode 100644 index 00000000000..b505ac2f5a0 --- /dev/null +++ b/test/dotnet/ExpectedOutput/ddl_logins.out @@ -0,0 +1,33 @@ +#Q#CREATE LOGIN login_1 + WITH PASSWORD = '891$RtQ73nJ#k8'; + ALTER SERVER ROLE [sysadmin] ADD MEMBER [login_1] + +#Q# +CREATE LOGIN login_2 + WITH PASSWORD = '673$WpM45hB#j4', + default_database = tempdb; + +#Q#CREATE LOGIN [ad\Aduser] from windows with default_database=[tempdb]; + +CREATE LOGIN [ad\Aduser] FROM WINDOWS WITH DEFAULT_DATABASE=[tempdb], DEFAULT_LANGUAGE=[English] +GO + +CREATE LOGIN [login_1] WITH PASSWORD='********************************************', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF +GO +ALTER LOGIN [login_1] DISABLE +GO +ALTER SERVER ROLE [sysadmin] ADD MEMBER [login_1] +GO + +CREATE LOGIN [login_2] WITH PASSWORD='********************************************', DEFAULT_DATABASE=[tempdb], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF +GO +ALTER LOGIN [login_2] DISABLE +GO +#Q#DROP LOGIN login_1 + +#Q#DROP LOGIN login_2 + +#Q#DROP LOGIN [ad\Aduser] + +#Q# + diff --git a/test/dotnet/ExpectedOutput/ddl_users.out b/test/dotnet/ExpectedOutput/ddl_users.out index dc49642a038..7743ee4887e 100644 --- a/test/dotnet/ExpectedOutput/ddl_users.out +++ b/test/dotnet/ExpectedOutput/ddl_users.out @@ -1,23 +1,23 @@ -#Q#DROP USER IF EXISTS test_usr1 +#Q#DROP USER IF EXISTS test_usr1 -#Q#DROP USER IF EXISTS test_usr2 +#Q#DROP USER IF EXISTS test_usr2 -#Q#DROP USER IF EXISTS test_usr3 +#Q#DROP USER IF EXISTS test_usr3 -#Q#CREATE LOGIN test_pwd1 - WITH PASSWORD = '340$Uuxwp7Mcxo7Khy'; +#Q#CREATE LOGIN test_pwd1 + WITH PASSWORD = '340$Uuxwp7Mcxo7Khy'; -#Q#CREATE LOGIN test_pwd2 - WITH PASSWORD = '340$UuxwpMcxo7Khy'; +#Q#CREATE LOGIN test_pwd2 + WITH PASSWORD = '340$UuxwpMcxo7Khy'; -#Q#CREATE LOGIN test_pwd3 - WITH PASSWORD = '340$Uuxwp7Mco7Khy'; +#Q#CREATE LOGIN test_pwd3 + WITH PASSWORD = '340$Uuxwp7Mco7Khy'; -#Q#CREATE USER test_usr1 FOR LOGIN test_pwd1; +#Q#CREATE USER test_usr1 FOR LOGIN test_pwd1; -#Q#CREATE USER test_usr2 FOR LOGIN test_pwd2; +#Q#CREATE USER test_usr2 FOR LOGIN test_pwd2; -#Q#CREATE USER test_usr3 FOR LOGIN test_pwd3; +#Q#CREATE USER test_usr3 FOR LOGIN test_pwd3; CREATE USER [test_usr1] FOR LOGIN [test_pwd1] WITH DEFAULT_SCHEMA=[dbo] GO @@ -25,15 +25,30 @@ CREATE USER [test_usr2] FOR LOGIN [test_pwd2] WITH DEFAULT_SCHEMA=[dbo] GO CREATE USER [test_usr3] FOR LOGIN [test_pwd3] WITH DEFAULT_SCHEMA=[dbo] GO -#Q#DROP LOGIN test_pwd1 -#Q#DROP LOGIN test_pwd2 +CREATE LOGIN [test_pwd1] WITH PASSWORD='********************************************', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF +GO +ALTER LOGIN [test_pwd1] DISABLE +GO + +CREATE LOGIN [test_pwd2] WITH PASSWORD='********************************************', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF +GO +ALTER LOGIN [test_pwd2] DISABLE +GO + +CREATE LOGIN [test_pwd3] WITH PASSWORD='********************************************', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF +GO +ALTER LOGIN [test_pwd3] DISABLE +GO +#Q#DROP LOGIN test_pwd1 + +#Q#DROP LOGIN test_pwd2 -#Q#DROP LOGIN test_pwd3 +#Q#DROP LOGIN test_pwd3 -#Q#DROP USER IF EXISTS test_usr1 +#Q#DROP USER IF EXISTS test_usr1 -#Q#DROP USER IF EXISTS test_usr2 +#Q#DROP USER IF EXISTS test_usr2 -#Q#DROP USER IF EXISTS test_usr3 +#Q#DROP USER IF EXISTS test_usr3 diff --git a/test/dotnet/input/DDLExport/ddl_logins.sql b/test/dotnet/input/DDLExport/ddl_logins.sql new file mode 100644 index 00000000000..57f8fd960ec --- /dev/null +++ b/test/dotnet/input/DDLExport/ddl_logins.sql @@ -0,0 +1,20 @@ +CREATE LOGIN login_1 + WITH PASSWORD = '891$RtQ73nJ#k8'; + ALTER SERVER ROLE [sysadmin] ADD MEMBER [login_1] +GO + +CREATE LOGIN login_2 + WITH PASSWORD = '673$WpM45hB#j4', + default_database = tempdb; +GO +CREATE LOGIN [ad\Aduser] from windows with default_database=[tempdb]; +GO +ddlexport#!#0 +GO +DROP LOGIN login_1 +GO +DROP LOGIN login_2 +GO +DROP LOGIN [ad\Aduser] +GO + diff --git a/test/dotnet/src/BatchRun.cs b/test/dotnet/src/BatchRun.cs index 1461857172b..ee88ce16ea6 100644 --- a/test/dotnet/src/BatchRun.cs +++ b/test/dotnet/src/BatchRun.cs @@ -288,7 +288,8 @@ bool BatchRunner(DbConnection bblCnn, string queryFilePath, Serilog.Core.Logger testUtils.PrintToLogsOrConsole("######################################################################", logger, "information"); testUtils.PrintToLogsOrConsole("############################# DDLEXPORT ##############################", logger, "information"); testUtils.PrintToLogsOrConsole("######################################################################\n", logger, "information"); - DatabaseScripter.ScriptDatabase(strLine, testName, testUtils, logger); + LoginDatabaseScripter.ScriptDatabase(strLine, testName, testUtils, logger); + LoginDatabaseScripter.ScriptLogins(testName, testUtils, logger); } else { diff --git a/test/dotnet/src/ScriptDatabase.cs b/test/dotnet/src/ScriptDatabase.cs index e18d7a8bdb4..226ed73c288 100644 --- a/test/dotnet/src/ScriptDatabase.cs +++ b/test/dotnet/src/ScriptDatabase.cs @@ -4,11 +4,38 @@ using Microsoft.SqlServer.Management.Common; using System.Collections.Specialized; using Microsoft.SqlServer.Management.Sdk.Sfc; +using System.Text.RegularExpressions; namespace BabelfishDotnetFramework { -public class DatabaseScripter +public class LoginDatabaseScripter { + public static ServerConnection serverConnection; + public static Server server; + public static Scripter scripter; + + public static void ConnectionInitialisation() + { + // Initialize ServerConnection + serverConnection = new ServerConnection(ConfigSetup.BblUrl); + serverConnection.LoginSecure = false; + serverConnection.Login = ConfigSetup.BblUser; + serverConnection.Password = ConfigSetup.BblPasswd; + + // Initialize Server + server = new Server(serverConnection); + + // Initialize Scripter with options + scripter = new Scripter(server) + { + Options = { + DriAll = true, + ScriptSchema = true, + ScriptData = false, + NoCollation = true + } + }; + } public static void ScriptDatabase(string strLine, string testName, TestUtils testUtils, Serilog.Core.Logger logger) { string[] result = strLine.Split("#!#", StringSplitOptions.RemoveEmptyEntries); @@ -18,13 +45,8 @@ public static void ScriptDatabase(string strLine, string testName, TestUtils tes try { - ServerConnection serverConnection = new ServerConnection(ConfigSetup.BblUrl); - serverConnection.LoginSecure = false; - serverConnection.Login = ConfigSetup.BblUser; - serverConnection.Password = ConfigSetup.BblPasswd; + ConnectionInitialisation(); - // Create a Server object - Server server = new Server(serverConnection); Database database = server.Databases[ConfigSetup.BblDb]; if (database == null) { @@ -34,24 +56,89 @@ public static void ScriptDatabase(string strLine, string testName, TestUtils tes testUtils.PrintToLogsOrConsole($"\nScripting database: {ConfigSetup.BblDb}", logger, "information"); - Scripter scripter = new Scripter(server) - { - Options = { - DriAll = true, - ScriptSchema = true, - ScriptData = false, - NoCollation = true - } - }; - ScriptDatabaseObjects(database, scripter, flag, testName, testUtils, logger); } catch (Exception ex) { testUtils.PrintToLogsOrConsole("An error occurred: " + ex.Message, logger, "information"); } + finally + { + if (server?.ConnectionContext != null) + { + server.ConnectionContext.Disconnect(); + } + if (serverConnection != null) + { + serverConnection.Disconnect(); + } + } } + public static void ScriptLogins(string testName, TestUtils testUtils, Serilog.Core.Logger logger) + { + try + { + ConnectionInitialisation(); + + string currentUser = server.ConnectionContext.TrueLogin; + var logins = server.Logins.Cast() + .Where(l => !l.IsSystemObject && l.Name != currentUser) + .ToList(); + + if (!logins.Any()) + { + testUtils.PrintToLogsOrConsole("No user-defined logins found.", logger, "information"); + return; + } + + // Precompile regex patterns + Regex passwordRegex = new Regex(@"N?'(.*?)'", RegexOptions.Compiled); + Regex commentBlockRegex = new Regex(@"(?m)^\s*/\*.*?\*/\s*$", RegexOptions.Compiled); + Regex singleLineCommentRegex = new Regex(@"(?m)^\s*--.*$", RegexOptions.Compiled); + Regex sidRegex = new Regex(@",\s*SID=0x[0-9A-F]+", RegexOptions.Compiled); + + foreach (Login login in logins) + { + try + { + testUtils.PrintToLogsOrConsole($"\nScripting Login: {login.Name}", logger, "information"); + StringCollection loginScripts = scripter.Script(new Urn[] { login.Urn }); + + for (int i = 0; i < loginScripts.Count; i++) + { + // replace password with equal length * + loginScripts[i] = passwordRegex.Replace(loginScripts[i], match => "'" + new string('*', match.Groups[1].Value.Length) + "'"); + // remove comments + loginScripts[i] = commentBlockRegex.Replace(loginScripts[i], ""); + loginScripts[i] = singleLineCommentRegex.Replace(loginScripts[i], ""); + loginScripts[i] = sidRegex.Replace(loginScripts[i], ""); + } + testUtils.ResultSetWriter(loginScripts, testName); + } + catch (Exception ex) + { + testUtils.PrintToLogsOrConsole($"Could not script login {login.Name}: {ex.Message}", logger, "warning"); + } + } + } + catch (Exception ex) + { + testUtils.PrintToLogsOrConsole($"Error in ScriptLogins: {ex.Message}", logger, "error"); + } + finally + { + if (server?.ConnectionContext != null) + { + server.ConnectionContext.Disconnect(); + } + if (serverConnection != null) + { + serverConnection.Disconnect(); + } + } + } + private static void ScriptDatabaseObjects(Database database, Scripter scripter, string flag, string testName, TestUtils testUtils, Serilog.Core.Logger logger) { const string sys_schema = "sys";