Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
027e0dc
fix for char and nchar function correct handling
pranavJ23 Jun 19, 2025
11ac3a8
Merge remote-tracking branch 'upstream/BABEL_5_X_DEV' into babel-4810
pranavJ23 Jun 20, 2025
8fa8985
Merge remote-tracking branch 'upstream/BABEL_5_X_DEV' into babel-4810
pranavJ23 Jun 20, 2025
295dddc
fixing expected files
pranavJ23 Jun 20, 2025
f04f307
fixing the test collation output
pranavJ23 Jun 20, 2025
00dbe04
Merge branch 'BABEL_5_X_DEV' into babel-4810
pranavJ23 Jun 20, 2025
2c9ae0b
Merge remote-tracking branch 'upstream/BABEL_5_X_DEV' into babel-4810
pranavJ23 Jun 20, 2025
b14d538
Merge remote-tracking branch 'origin/babel-4810' into babel-4810
pranavJ23 Jun 22, 2025
4b1b6b5
updating upgrade files
pranavJ23 Jun 22, 2025
f28916d
minor changes
pranavJ23 Jun 22, 2025
b6793b7
fix for nchar when input is coercible to int type
pranavJ23 Jun 25, 2025
3f8c48d
minor fixes
pranavJ23 Jun 25, 2025
d190bc7
minor fixes
pranavJ23 Jun 25, 2025
f290dae
Merge branch 'babelfish-for-postgresql:BABEL_5_X_DEV' into babel-4810
pranavJ23 Jun 26, 2025
ed7b626
fixing datetime changes
pranavJ23 Jun 26, 2025
57a2436
addressing comments
pranavJ23 Jun 27, 2025
e6a5113
minor upgrade fixes
pranavJ23 Jun 27, 2025
339c8a9
expected_drop change
pranavJ23 Jun 27, 2025
e1e35eb
fixing edge case, adding test with quoted identifier, simplifying the…
pranavJ23 Jun 29, 2025
25b99f8
fixing expected test files
pranavJ23 Jun 29, 2025
58183b8
fixing test
pranavJ23 Jun 29, 2025
cb7533b
adding helper function and more tests
pranavJ23 Jun 30, 2025
e249f6f
fixing test updates collation
pranavJ23 Jun 30, 2025
0cd0a3d
Merge branch 'babelfish-for-postgresql:BABEL_5_X_DEV' into babel-4810
pranavJ23 Jul 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 11 additions & 18 deletions contrib/babelfishpg_common/sql/string_operators.sql
Original file line number Diff line number Diff line change
Expand Up @@ -97,28 +97,34 @@ CREATE OPERATOR sys.+ (
FUNCTION = sys.babelfish_concat_wrapper
);

create or replace function sys.CHAR(x in int)returns char
create or replace function sys.cht_(x in int) returns sys.varchar
AS
$body$
BEGIN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if input is 0? (Same for other functions as well)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this edge case need to be handled since pg function 'chr' expects the input b/w 1-255 where as the tsql expects input b/w 0-255. Thanks

/***************************************************************
EXTENSION PACK function CHAR(x)
***************************************************************/
if x = 0 then
return ('\x00'::bytea)::sys.varbinary;
end if;
if x between 1 and 255 then
return chr(x);
else
return null;
end if;
END;
$body$
language plpgsql STABLE;
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mark all the functions as STABLE since the underlying helper function depends on encoding settings

Copy link
Copy Markdown
Contributor Author

@pranavJ23 pranavJ23 Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with stable we are not able to use the CHAR function in computed column, where as in tsql the char can be used in computed column.
Since the encoding in babelfish_db can' t be changed once the db is formed, hence we can mark the function as immutable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we verified that it is really PARALLEL SAFE?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the test case is passing in the JDBC parallel query mode, so we can say that it's parallel safe ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the pg_proc catalog too, we have verified that chr() function is parallel safe and since we are using chr() underlying sys.char(), so we can say it's parallel safe


CREATE OR REPLACE FUNCTION sys.nchar(IN x INTEGER) RETURNS sys.nvarchar
CREATE OR REPLACE FUNCTION sys.ncht_(x in int) RETURNS sys.nvarchar
AS
$body$
BEGIN
--- 1114111 is 0x10FFFF - max value permitted as specified by documentation
if x between 1 and 1114111 then
if x = 0 then
return ('\x00'::bytea)::sys.varbinary;
end if;
--- 65535 is 0x0000FFFF - max value permitted as specified by documentation without SC collation
if x between 1 and 65535 then
return(select chr(x))::sys.nvarchar;
else
return null;
Expand All @@ -127,16 +133,3 @@ END;
$body$
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

CREATE OR REPLACE FUNCTION sys.nchar(IN x varbinary) RETURNS sys.nvarchar
AS
$body$
BEGIN
--- 1114111 is 0x10FFFF - max value permitted as specified by documentation
if x::integer between 1 and 1114111 then
return(select chr(x::integer))::sys.nvarchar;
else
return null;
end if;
END;
$body$
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,36 @@

SELECT set_config('search_path', 'sys, '||current_setting('search_path'), false);

-- Drops an object if it does not have any dependent objects.
-- Is a temporary procedure for use by the upgrade script. Will be dropped at the end of the upgrade.
-- Please have this be one of the first statements executed in this upgrade script.
CREATE OR REPLACE PROCEDURE babelfish_drop_deprecated_object(object_type varchar, schema_name varchar, object_name varchar) AS
$$
DECLARE
error_msg text;
query1 text;
query2 text;
BEGIN

query1 := pg_catalog.format('alter extension babelfishpg_common drop %s %s.%s', object_type, schema_name, object_name);
query2 := pg_catalog.format('drop %s %s.%s', object_type, schema_name, object_name);

execute query1;
execute query2;
EXCEPTION
when object_not_in_prerequisite_state then --if 'alter extension' statement fails
GET STACKED DIAGNOSTICS error_msg = MESSAGE_TEXT;
raise warning '%', error_msg;
when dependent_objects_still_exist then --if 'drop view' statement fails
GET STACKED DIAGNOSTICS error_msg = MESSAGE_TEXT;
raise warning '%', error_msg;
when undefined_function then --if 'Deprecated function does not exist'
GET STACKED DIAGNOSTICS error_msg = MESSAGE_TEXT;
raise warning '%', error_msg;
end
$$
LANGUAGE plpgsql;

-- casting from bytea to binary
CREATE OR REPLACE FUNCTION sys.byteabinary(pg_catalog.BYTEA, integer, boolean)
RETURNS sys.BBF_BINARY
Expand Down Expand Up @@ -145,6 +175,87 @@ BEGIN
END IF;
END $$;

DO $$
DECLARE
exception_message text;
BEGIN
ALTER FUNCTION sys.char(x in int) RENAME TO chr_deprecated_5_3_0;

EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
exception_message = MESSAGE_TEXT;
RAISE WARNING '%', exception_message;
END;
$$;

CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'chr_deprecated_5_3_0');

DO $$
DECLARE
exception_message text;
BEGIN
ALTER FUNCTION sys.nchar(In x INTEGER) RENAME TO nchar_int_deprecated_5_3_0;

EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
exception_message = MESSAGE_TEXT;
RAISE WARNING '%', exception_message;
END;
$$;

CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'nchar_int_deprecated_5_3_0');

DO $$
DECLARE
exception_message text;
BEGIN
ALTER FUNCTION sys.nchar(In x varbinary) RENAME TO nchar_varbinary_deprecated_5_3_0;

EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
exception_message = MESSAGE_TEXT;
RAISE WARNING '%', exception_message;
END;
$$;

CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'nchar_varbinary_deprecated_5_3_0');

create or replace function sys.cht_(x in int) returns sys.varchar
AS
$body$
BEGIN
/***************************************************************
EXTENSION PACK function CHAR(x)
***************************************************************/
if x = 0 then
return ('\x00'::bytea)::sys.varbinary;
end if;
if x between 1 and 255 then
return chr(x);
else
return null;
end if;
END;
$body$
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

CREATE OR REPLACE FUNCTION sys.ncht_(x in int) RETURNS sys.nvarchar
AS
$body$
BEGIN
if x = 0 then
return ('\x00'::bytea)::sys.varbinary;
end if;
--- 65535 is 0x0000FFFF - max value permitted as specified by documentation without SC collation
if x between 1 and 65535 then
return(select chr(x))::sys.nvarchar;
else
return null;
end if;
END;
$body$
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

-- arithmetic functions where one of the
-- operand is smallmoney

Expand Down Expand Up @@ -669,5 +780,9 @@ BEGIN
END IF;
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);

-- Reset search_path to not affect any subsequent scripts
SELECT set_config('search_path', trim(leading 'sys, ' from current_setting('search_path')), false);
49 changes: 33 additions & 16 deletions contrib/babelfishpg_tsql/src/tsqlIface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3004,6 +3004,33 @@ class tsqlMutator : public TSqlParserBaseListener
{
}

private:
void handleCharNcharTypeRename(const std::string &procNameStr, TSqlParser::IdContext *proc,
TSqlParser::IdContext *schema)
{

int startIndex = proc->start->getStartIndex();
std::string alias;
std::string formattedName;

if (pg_strcasecmp(procNameStr.c_str(), "char") == 0)
alias = "cht_";
else if (pg_strcasecmp(procNameStr.c_str(), "nchar") == 0)
alias = "ncht_";

if(schema && pg_strcasecmp(stripQuoteFromId(schema).c_str(), "sys") != 0)
return;

if (proc->DOUBLE_QUOTE_ID())
formattedName = "\"" + alias + "\"";
else if (proc->SQUARE_BRACKET_ID())
formattedName = "[" + alias + "]";
else
formattedName = alias;

stream.setText(startIndex, formattedName.c_str());
}

public:
void enterFunc_proc_name_schema(TSqlParser::Func_proc_name_schemaContext *ctx) override
{
Expand All @@ -3014,6 +3041,7 @@ class tsqlMutator : public TSqlParserBaseListener
// "char" is a data type name in PostgreSQL

TSqlParser::IdContext *proc = ctx->procedure;
TSqlParser::IdContext *schema = ctx->schema;

// According to the grammar, an id can be any of the following:
//
Expand All @@ -3032,17 +3060,11 @@ class tsqlMutator : public TSqlParserBaseListener
if (proc->keyword() || proc->colon_colon())
return;

// FIXME: handle the schema here too
std::string procNameStr = getIDName(proc->DOUBLE_QUOTE_ID(), proc->SQUARE_BRACKET_ID(), proc->ID());

if (pg_strcasecmp(procNameStr.c_str(), "char") == 0)
if (pg_strcasecmp(procNameStr.c_str(), "char") == 0 || pg_strcasecmp(procNameStr.c_str(), "nchar") == 0)
{
if (proc->DOUBLE_QUOTE_ID())
stream.setText(ctx->start->getStartIndex(), "\"chr\" ");
else if (proc->SQUARE_BRACKET_ID())
stream.setText(ctx->start->getStartIndex(), "[chr] ");
else
stream.setText(ctx->start->getStartIndex(), " chr");
handleCharNcharTypeRename(procNameStr, proc, schema);
}
}

Expand Down Expand Up @@ -3140,6 +3162,7 @@ class tsqlMutator : public TSqlParserBaseListener
// "char" is a data type name in PostgreSQL

TSqlParser::IdContext *proc = ctx->procedure;
TSqlParser::IdContext *schema = ctx->schema;

#ifdef ENABLE_SPATIAL_TYPES
if(!ctx->id().empty() && ctx->id()[0]->id().size() == 2)
Expand Down Expand Up @@ -3176,17 +3199,11 @@ class tsqlMutator : public TSqlParserBaseListener
if (proc->keyword() || proc->colon_colon())
return;

// FIXME: handle the schema here too
std::string procNameStr = getIDName(proc->DOUBLE_QUOTE_ID(), proc->SQUARE_BRACKET_ID(), proc->ID());

if (pg_strcasecmp(procNameStr.c_str(), "char") == 0)
if (pg_strcasecmp(procNameStr.c_str(), "char") == 0 || pg_strcasecmp(procNameStr.c_str(), "nchar") == 0)
{
if (proc->DOUBLE_QUOTE_ID())
stream.setText(ctx->start->getStartIndex(), "\"chr\" ");
else if (proc->SQUARE_BRACKET_ID())
stream.setText(ctx->start->getStartIndex(), "[chr] ");
else
stream.setText(ctx->start->getStartIndex(), " chr");
handleCharNcharTypeRename(procNameStr, proc, schema);
}
}

Expand Down
13 changes: 7 additions & 6 deletions test/JDBC/expected/ascii.out
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ int#!#int#!#int#!#int
-- following throws error in babelfish
SELECT ASCII(CHAR(0)) AS NullChar
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: null character not permitted)~~
~~START~~
int
0
~~END~~


-- 4. Tests with Different Data Types
Expand Down Expand Up @@ -238,7 +239,7 @@ SELECT
GO
~~START~~
int#!#int
256#!#12121
<NULL>#!#<NULL>
~~END~~


Expand All @@ -262,7 +263,7 @@ SELECT
FROM Numbers;
GO
~~START~~
int#!#text#!#int#!#varchar
int#!#varchar#!#int#!#varchar
1#!##!#1#!#Pass
2#!##!#2#!#Pass
3#!##!#3#!#Pass
Expand Down Expand Up @@ -712,7 +713,7 @@ EXEC ascii_sp_analyzestring 'Test String';
EXEC ascii_sp_validateascii 'A', 65;
GO
~~START~~
varchar#!#int#!#text#!#varchar
varchar#!#int#!#varchar#!#varchar
Test String#!#84#!#T#!#Uppercase
~~END~~

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int
select coalesce(NULL, CHAR(9))
go
~~START~~
text
varchar

~~END~~

Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/babel_726-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int
select coalesce(NULL, CHAR(9))
go
~~START~~
text
varchar

~~END~~

Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/expected/babel_726.out
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int
select coalesce(NULL, CHAR(9))
go
~~START~~
text
varchar

~~END~~

Expand Down
23 changes: 21 additions & 2 deletions test/JDBC/expected/babel_char-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ select nchar(0x10FFFF);
GO
~~START~~
nvarchar
􏿿
<NULL>
~~END~~

~~START~~
nvarchar
􏿿
<NULL>
~~END~~


Expand All @@ -61,6 +61,25 @@ nvarchar
<NULL>
~~END~~

~~START~~
nvarchar

~~END~~

~~START~~
nvarchar
<NULL>
~~END~~

select sys.nchar(65535)
select sys.nchar(65536)
select sys.nchar(-1)
GO
~~START~~
nvarchar
￿
~~END~~

~~START~~
nvarchar
<NULL>
Expand Down
Loading
Loading