Skip to content

Commit

Permalink
Implement sp_rename
Browse files Browse the repository at this point in the history
Signed-off-by: Rishabh Tanwar <[email protected]>
  • Loading branch information
ritanwar committed Jul 23, 2024
1 parent 41ff574 commit 0a6bd67
Show file tree
Hide file tree
Showing 19 changed files with 384 additions and 35 deletions.
12 changes: 6 additions & 6 deletions contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2942,7 +2942,7 @@ BEGIN
DECLARE @subname sys.nvarchar(776) = '';
DECLARE @schemaname sys.nvarchar(776) = '';
DECLARE @dbname sys.nvarchar(776) = '';
SELECT @name_count = COUNT(*) FROM STRING_SPLIT(@objname, '.');
SELECT @name_count = COUNT(*) FROM sys.babelfish_split_identifier(@objname);
IF @name_count > 3
BEGIN
THROW 33557097, N'No item by the given @objname could be found in the current database', 1;
Expand All @@ -2951,30 +2951,30 @@ BEGIN
BEGIN
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM STRING_SPLIT(@objname, '.'))
FROM sys.babelfish_split_identifier(@objname))
SELECT @dbname = value FROM myTableWithRows WHERE row = 1;
IF @dbname != sys.db_name()
BEGIN
THROW 33557097, N'No item by the given @objname could be found in the current database', 1;
END
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM STRING_SPLIT(@objname, '.'))
FROM sys.babelfish_split_identifier(@objname))
SELECT @schemaname = value FROM myTableWithRows WHERE row = 2;
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM STRING_SPLIT(@objname, '.'))
FROM sys.babelfish_split_identifier(@objname))
SELECT @subname = value FROM myTableWithRows WHERE row = 3;
END
IF @name_count = 2
BEGIN
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM STRING_SPLIT(@objname, '.'))
FROM sys.babelfish_split_identifier(@objname))
SELECT @schemaname = value FROM myTableWithRows WHERE row = 1;
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM STRING_SPLIT(@objname, '.'))
FROM sys.babelfish_split_identifier(@objname))
SELECT @subname = value FROM myTableWithRows WHERE row = 2;
END
IF @name_count = 1
Expand Down
4 changes: 4 additions & 0 deletions contrib/babelfishpg_tsql/sql/sys_function_helpers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10352,3 +10352,7 @@ CREATE OR REPLACE FUNCTION sys.bbf_is_shared_schema(IN schemaname TEXT)
RETURNS BOOL
AS 'babelfishpg_tsql', 'is_shared_schema_wrapper'
LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION sys.babelfish_split_identifier(IN identifier VARCHAR, OUT value VARCHAR)
RETURNS SETOF VARCHAR AS 'babelfishpg_tsql', 'split_identifier_internal'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,106 @@ CREATE OR REPLACE VIEW information_schema_tsql.tables AS
AND ext.dbid = sys.db_id()
AND (NOT c.relname = 'sysdatabases');

CREATE OR REPLACE FUNCTION sys.babelfish_split_identifier(IN identifier VARCHAR, OUT value VARCHAR)
RETURNS SETOF VARCHAR AS 'babelfishpg_tsql', 'split_identifier_internal'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE OR REPLACE PROCEDURE sys.sp_rename(
IN "@objname" sys.nvarchar(776),
IN "@newname" sys.SYSNAME,
IN "@objtype" sys.varchar(13) DEFAULT NULL
)
LANGUAGE 'pltsql'
AS $$
BEGIN
If @objtype IS NULL
BEGIN
THROW 33557097, N'Please provide @objtype that is supported in Babelfish', 1;
END
IF @objtype = 'COLUMN'
BEGIN
THROW 33557097, N'Feature not supported: renaming object type Column', 1;
END
IF @objtype = 'INDEX'
BEGIN
THROW 33557097, N'Feature not supported: renaming object type Index', 1;
END
IF @objtype = 'STATISTICS'
BEGIN
THROW 33557097, N'Feature not supported: renaming object type Statistics', 1;
END
IF @objtype = 'USERDATATYPE'
BEGIN
THROW 33557097, N'Feature not supported: renaming object type User-defined Data Type alias', 1;
END
IF @objtype IS NOT NULL AND (@objtype != 'OBJECT')
BEGIN
THROW 33557097, N'Provided @objtype is not currently supported in Babelfish', 1;
END
DECLARE @name_count INT;
DECLARE @subname sys.nvarchar(776) = '';
DECLARE @schemaname sys.nvarchar(776) = '';
DECLARE @dbname sys.nvarchar(776) = '';
SELECT @name_count = COUNT(*) FROM sys.babelfish_split_identifier(@objname);
IF @name_count > 3
BEGIN
THROW 33557097, N'No item by the given @objname could be found in the current database', 1;
END
IF @name_count = 3
BEGIN
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM sys.babelfish_split_identifier(@objname))
SELECT @dbname = value FROM myTableWithRows WHERE row = 1;
IF @dbname != sys.db_name()
BEGIN
THROW 33557097, N'No item by the given @objname could be found in the current database', 1;
END
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM sys.babelfish_split_identifier(@objname))
SELECT @schemaname = value FROM myTableWithRows WHERE row = 2;
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM sys.babelfish_split_identifier(@objname))
SELECT @subname = value FROM myTableWithRows WHERE row = 3;
END
IF @name_count = 2
BEGIN
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM sys.babelfish_split_identifier(@objname))
SELECT @schemaname = value FROM myTableWithRows WHERE row = 1;
WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY NULL)) as row,*
FROM sys.babelfish_split_identifier(@objname))
SELECT @subname = value FROM myTableWithRows WHERE row = 2;
END
IF @name_count = 1
BEGIN
SET @schemaname = sys.schema_name();
SET @subname = @objname;
END

DECLARE @count INT;
DECLARE @currtype char(2);
SELECT @count = COUNT(*) FROM sys.objects o1 INNER JOIN sys.schemas s1 ON o1.schema_id = s1.schema_id
WHERE s1.name = @schemaname AND o1.name = @subname;
IF @count > 1
BEGIN
THROW 33557097, N'There are multiple objects with the given @objname.', 1;
END
IF @count < 1
BEGIN
THROW 33557097, N'There is no object with the given @objname.', 1;
END
SELECT @currtype = type FROM sys.objects o1 INNER JOIN sys.schemas s1 ON o1.schema_id = s1.schema_id
WHERE s1.name = @schemaname AND o1.name = @subname;
EXEC sys.babelfish_sp_rename_internal @subname, @newname, @schemaname, @currtype;
PRINT 'Caution: Changing any part of an object name could break scripts and stored procedures.';
END;
$$;

-- Drops the temporary procedure used by the upgrade script.
-- Please have this be one of the last statements executed in this upgrade script.
DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar);
Expand Down
66 changes: 66 additions & 0 deletions contrib/babelfishpg_tsql/src/pltsql_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ bool is_tsql_nchar_or_nvarchar_datatype(Oid oid); /* sys.nchar / sys.nvarchar *
bool is_tsql_binary_or_varbinary_datatype(Oid oid); /* sys.binary / sys.varbinary */
bool is_tsql_datatype_with_max_scale_expr_allowed(Oid oid); /* sys.varchar(max), sys.nvarchar(max), sys.varbinary(max) */
bool is_tsql_text_ntext_or_image_datatype(Oid oid);
PG_FUNCTION_INFO_V1(split_identifier_internal);


/* To cache oid of sys.varchar */
Expand Down Expand Up @@ -1215,6 +1216,71 @@ split_object_name(char *name)
return res;
}

/*
* Wrapper over split_object_name function above to expose it as a SQL function.
*/
Datum
split_identifier_internal(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
char **split_parts = NULL;

if (SRF_IS_FIRSTCALL())
{
int num_parts = 0;
MemoryContext oldcontext;

funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
if (!PG_ARGISNULL(0))
{
char *input;
char **splited_object_name;
int i, j = 0;

input = text_to_cstring(PG_GETARG_TEXT_P(0));
splited_object_name = split_object_name(input);

for (i = 0; i < 4; i++)
{
if (strlen(splited_object_name[i]) > 0)
num_parts++;
}

if (num_parts > 0)
{
split_parts = (char **) palloc(num_parts * sizeof(char *));

for (i = 0; i < 4; i++)
{
if (i >= (4 - num_parts))
split_parts[j++] = splited_object_name[i];
else
pfree(splited_object_name[i]);
}
}
pfree(splited_object_name);
}

funcctx->max_calls = num_parts;
funcctx->user_fctx = split_parts;
MemoryContextSwitchTo(oldcontext);
}

funcctx = SRF_PERCALL_SETUP();
split_parts = (char **) funcctx->user_fctx;

if (funcctx->call_cntr < funcctx->max_calls)
{
VarChar *val = (*common_utility_plugin_ptr->tsql_varchar_input) (split_parts[funcctx->call_cntr],
strlen(split_parts[funcctx->call_cntr]),
-1);
SRF_RETURN_NEXT(funcctx, PointerGetDatum(val));
}
else
SRF_RETURN_DONE(funcctx);
}

/*
* is_schema_from_db
* Given schema_oid and db_id, check if schema belongs to provided database id.
Expand Down
28 changes: 27 additions & 1 deletion contrib/babelfishpg_tsql/src/procedures.c
Original file line number Diff line number Diff line change
Expand Up @@ -2764,6 +2764,8 @@ Datum sp_rename_internal(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}

extern const char *ATTOPTION_BBF_ORIGINAL_TABLE_NAME;

static List *
gen_sp_rename_subcmds(const char *objname, const char *newname, const char *schemaname, ObjectType objtype)
{
Expand All @@ -2775,6 +2777,7 @@ gen_sp_rename_subcmds(const char *objname, const char *newname, const char *sche
initStringInfo(&query);
if (objtype == OBJECT_TABLE) {
appendStringInfo(&query, "ALTER TABLE dummy RENAME TO dummy; ");
appendStringInfo(&query, "ALTER TABLE dummy SET (dummy = 'dummy'); ");
} else if (objtype == OBJECT_VIEW) {
appendStringInfo(&query, "ALTER VIEW dummy RENAME TO dummy; ");
} else if (objtype == OBJECT_PROCEDURE) {
Expand All @@ -2790,7 +2793,7 @@ gen_sp_rename_subcmds(const char *objname, const char *newname, const char *sche
}
res = raw_parser(query.data, RAW_PARSE_DEFAULT);

if (list_length(res) != 1)
if ((objtype != OBJECT_TABLE) && (list_length(res) != 1))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("Expected 1 statement but get %d statements after parsing", list_length(res))));
Expand All @@ -2807,6 +2810,29 @@ gen_sp_rename_subcmds(const char *objname, const char *newname, const char *sche
renamestmt->newname = pstrdup(lowerstr(newname));
renamestmt->relation->schemaname = pstrdup(lowerstr(schemaname));
renamestmt->relation->relname = pstrdup(lowerstr(objname));

if (objtype == OBJECT_TABLE)
{
AlterTableStmt *altertablestmt;
AlterTableCmd *cmd;
ListCell *lc = NULL;

rewrite_object_refs(stmt);
/* extra query nodes for modifying reloption */
stmt = parsetree_nth_stmt(res, 1);
altertablestmt = (AlterTableStmt *) stmt;
if (!IsA(altertablestmt, AlterTableStmt))
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("query is not a AlterTableStmt")));

altertablestmt->relation->schemaname = pstrdup(lowerstr(schemaname));
altertablestmt->relation->relname = pstrdup(lowerstr(newname));
altertablestmt->objtype = OBJECT_TABLE;
/* get data of the first node */
lc = list_head(altertablestmt->cmds);
cmd = (AlterTableCmd *) lfirst(lc);
cmd->subtype = AT_SetRelOptions;
cmd->def = (Node *) list_make1(makeDefElem(pstrdup(ATTOPTION_BBF_ORIGINAL_TABLE_NAME), (Node *) makeString(pstrdup(newname)), -1));
}
} else {
// } else if ((objtype == OBJECT_PROCEDURE) || (objtype == OBJECT_FUNCTION)) {
ObjectWithArgs *objwargs = (ObjectWithArgs *) renamestmt->object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ GO
DROP FUNCTION [BABEL-2877-vu-prepare_FUNC_Schema].[BABEL-2877-vu-prepare_FUNC];
GO

DROP FUNCTION [BABEL-2877-vu-prepare Schema . WITH .. DOTS].[BABEL-2877-vu-prepare Function . WITH .. DOTS];
DROP FUNCTION [BABEL-2877-vu-prepare Schema . WITH .. DOTS].[BABEL-2877-vu-prepare Function . WITH .. DOTS2];
GO

DROP SCHEMA [BABEL-2877-vu-prepare_FUNC_Schema];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,49 @@ master_dbo#!#babel_2877_vu_prepare_proc3#!#babel_2877_vu_prepare_proc3(integer,
~~END~~


SELECT orig_name,
CASE flag_validity & 1
WHEN 0
THEN NULL
ELSE
CASE flag_values & 1
WHEN 0
THEN 0
ELSE 1
END
END AS ansi_null,
CASE flag_validity & 2
WHEN 0
THEN NULL
ELSE
CASE flag_values & 2
WHEN 0
THEN 0
ELSE 1
END
END AS quoted_identifier
FROM sys.babelfish_function_ext WHERE funcname LIKE 'babel-2877-vu-prepare%' ORDER BY funcname;
GO
~~START~~
nvarchar#!#int#!#int
BABEL-2877-vu-prepare Schema . WITH .. DOTS#!#1#!#1
BABEL-2877-vu-prepare_FUNC_Schema#!#1#!#1
BABEL-2877-vu-prepare_FUNC_ANSI_NULLOFF_QIDOFF#!#0#!#0
BABEL-2877-vu-prepare_FUNC_ANSI_NULLOFF_QIDON#!#0#!#1
BABEL-2877-vu-prepare_FUNC_ANSI_NULLON_QIDOFF#!#1#!#0
BABEL-2877-vu-prepare_FUNC_ANSI_NULLON_QIDON#!#1#!#1
~~END~~


-- Rename the existing functions to fix the originally stored incorrect orig_name
EXEC sp_rename 'BABEL-2877-vu-prepare_FUNC_Schema.BABEL-2877-vu-prepare_FUNC', 'BABEL-2877-vu-prepare_FUNC2', 'OBJECT'
GO

EXEC sp_rename '"BABEL-2877-vu-prepare Schema . WITH .. DOTS"."BABEL-2877-vu-prepare Function . WITH .. DOTS"', 'BABEL-2877-vu-prepare Function . WITH .. DOTS2', 'OBJECT'
GO

-- create a new function with name which is prefix of schema name to verify new behavior
CREATE FUNCTION [BABEL-2877-vu-prepare_FUNC_Schema] . [BABEL-2877-vu-prepare_FUNC_S] (@a int)
CREATE FUNCTION [BABEL-2877-vu-prepare_FUNC_Schema] . [BABEL-2877-vu-prepare_FUNC] (@a int)
RETURNS INT AS BEGIN RETURN 1; END;
GO

Expand Down Expand Up @@ -228,15 +269,15 @@ FROM sys.babelfish_function_ext WHERE funcname LIKE 'babel-2877-vu-prepare%' ORD
GO
~~START~~
nvarchar#!#int#!#int
BABEL-2877-vu-prepare Schema . WITH .. DOTS#!#1#!#1
BABEL-2877-vu-prepare_FUNC_S#!#1#!#1
BABEL-2877-vu-prepare_FUNC_Schema#!#1#!#1
BABEL-2877-vu-prepare Function . WITH .. DOTS2#!#1#!#1
BABEL-2877-vu-prepare_FUNC#!#1#!#1
BABEL-2877-vu-prepare_FUNC2#!#1#!#1
BABEL-2877-vu-prepare_FUNC_ANSI_NULLOFF_QIDOFF#!#0#!#0
BABEL-2877-vu-prepare_FUNC_ANSI_NULLOFF_QIDON#!#0#!#1
BABEL-2877-vu-prepare_FUNC_ANSI_NULLON_QIDOFF#!#1#!#0
BABEL-2877-vu-prepare_FUNC_ANSI_NULLON_QIDON#!#1#!#1
~~END~~


DROP FUNCTION [BABEL-2877-vu-prepare_FUNC_Schema] . [BABEL-2877-vu-prepare_FUNC_S]
DROP FUNCTION [BABEL-2877-vu-prepare_FUNC_Schema] . [BABEL-2877-vu-prepare_FUNC2]
GO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
DROP TABLE isc_tables_sc1.t2
DROP TABLE [ISC_TABLES_TABLE_SCHEMA].[ISC_TABLES_TABLE]
DROP TABLE [ISC_TABLES SCHEMA . WITH .. DOTS].[ISC_TABLES TABLE . WITH .. DOTS]
DROP TABLE [ISC_TABLES SCHEMA . WITH .. DOTS].[ISC_TABLES TABLE . WITH .. DOTS2]
GO

DROP TYPE isc_tables_sc1.isc_table_type2
Expand Down
Loading

0 comments on commit 0a6bd67

Please sign in to comment.