diff --git a/contrib/babelfishpg_common/sql/string_operators.sql b/contrib/babelfishpg_common/sql/string_operators.sql index 6eed4a593a..811a84a020 100644 --- a/contrib/babelfishpg_common/sql/string_operators.sql +++ b/contrib/babelfishpg_common/sql/string_operators.sql @@ -1,19 +1,9 @@ -- Wrap built-in CONCAT function to accept two text arguments. -- This is necessary because CONCAT accepts arguments of type VARIADIC "any". -- CONCAT also automatically handles NULL which || does not. -CREATE OR REPLACE FUNCTION sys.babelfish_concat_wrapper(leftarg text, rightarg text) RETURNS TEXT AS -$$ - SELECT - CASE WHEN (current_setting('babelfishpg_tsql.concat_null_yields_null') = 'on') THEN - CASE - WHEN leftarg IS NULL OR rightarg IS NULL THEN NULL - ELSE CONCAT(leftarg, rightarg) - END - ELSE - CONCAT(leftarg, rightarg) - END -$$ -LANGUAGE SQL STABLE; +CREATE OR REPLACE FUNCTION sys.babelfish_concat_wrapper(leftarg text, rightarg text) RETURNS TEXT +AS 'babelfishpg_tsql', 'babelfish_concat_wrapper' +LANGUAGE C STABLE PARALLEL SAFE; CREATE OR REPLACE FUNCTION sys.babelfish_concat_wrapper_outer(leftarg text, rightarg text) RETURNS sys.varchar(8000) AS $$ diff --git a/contrib/babelfishpg_tsql/runtime/functions.c b/contrib/babelfishpg_tsql/runtime/functions.c index 19fbb0d113..f17125e334 100644 --- a/contrib/babelfishpg_tsql/runtime/functions.c +++ b/contrib/babelfishpg_tsql/runtime/functions.c @@ -88,6 +88,7 @@ typedef enum OBJECT_TYPE_EXTENDED_STORED_PROCEDURE } ObjectPropertyType; + PG_FUNCTION_INFO_V1(trancount); PG_FUNCTION_INFO_V1(version); PG_FUNCTION_INFO_V1(error); @@ -149,6 +150,7 @@ PG_FUNCTION_INFO_V1(pg_extension_config_remove); PG_FUNCTION_INFO_V1(objectproperty_internal); PG_FUNCTION_INFO_V1(sysutcdatetime); PG_FUNCTION_INFO_V1(getutcdate); +PG_FUNCTION_INFO_V1(babelfish_concat_wrapper); void *string_to_tsql_varchar(const char *input_str); void *get_servername_internal(void); @@ -184,6 +186,58 @@ char *bbf_language = "us_english"; #define MD5_HASH_LEN 32 +Datum +babelfish_concat_wrapper(PG_FUNCTION_ARGS) +{ + text *arg1, *arg2, *new_text; + int32 arg1_size, arg2_size, new_text_size; + bool first_param = PG_ARGISNULL(0); + bool second_param = PG_ARGISNULL(1); + + if (pltsql_concat_null_yields_null) + { + if(first_param || second_param) + { + PG_RETURN_NULL(); // If any is NULL, return NULL + } + } + else + { + if (first_param && second_param) + { + PG_RETURN_NULL(); // If both are NULL, return NULL + } + else if (second_param) + { + PG_RETURN_TEXT_P(PG_GETARG_TEXT_PP(0)); // If only the second string is NULL, return the first string + } + else if (first_param) + { + PG_RETURN_TEXT_P(PG_GETARG_TEXT_PP(1)); // If only the first string is NULL, return the second string + } + } + arg1 = PG_GETARG_TEXT_PP(0); + arg2 = PG_GETARG_TEXT_PP(1); + arg1_size = VARSIZE_ANY_EXHDR(arg1); + arg2_size = VARSIZE_ANY_EXHDR(arg2); + + new_text_size = arg1_size + arg2_size + VARHDRSZ; + new_text = (text *) palloc(new_text_size); + + SET_VARSIZE(new_text, new_text_size); + + if(arg1_size>0) + { + memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size); + } + if(arg2_size>0) + { + memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size); + } + + PG_RETURN_TEXT_P(new_text); +} + Datum trancount(PG_FUNCTION_ARGS) { diff --git a/test/JDBC/expected/babel_4299.out b/test/JDBC/expected/babel_4299.out new file mode 100644 index 0000000000..585aa27688 --- /dev/null +++ b/test/JDBC/expected/babel_4299.out @@ -0,0 +1,309 @@ +select ''+'ps'; +GO +~~START~~ +varchar +ps +~~END~~ + + +select 'rs' + ''; +GO +~~START~~ +varchar +rs +~~END~~ + + +select '' + ''; +GO +~~START~~ +varchar + +~~END~~ + + +select '' + NULL; +GO +~~START~~ +varchar + +~~END~~ + + +select NULL + ''; +GO +~~START~~ +varchar + +~~END~~ + + +set quoted_identifier off +GO +select ""+'s'; +GO +~~START~~ +varchar +s +~~END~~ + + +set quoted_identifier off +GO +select 'rs' + ""; +GO +~~START~~ +varchar +rs +~~END~~ + + +set quoted_identifier off +GO +select '' + ""; +GO +~~START~~ +varchar + +~~END~~ + + +set quoted_identifier off +GO +select "" + NULL; +GO +~~START~~ +varchar + +~~END~~ + + +set quoted_identifier off +GO +select NULL + ""; +GO +~~START~~ +varchar + +~~END~~ + + +set quoted_identifier off +GO +select ""+"s"; +GO +~~START~~ +varchar +s +~~END~~ + + +set quoted_identifier off +GO +select "pr" + ""; +GO +~~START~~ +varchar +pr +~~END~~ + + +set quoted_identifier off +GO +select "" + ""; +GO +~~START~~ +varchar + +~~END~~ + + +set quoted_identifier off +GO +select "" + ""; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT 'Hello' + NULL + 'World'; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT 'Hello' + NULL + 'World'; +GO +~~START~~ +varchar +HelloWorld +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + 'World'; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + 'World'; +GO +~~START~~ +varchar +World +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + ''; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + ''; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT NULL + 'World'; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT NULL + 'World'; +GO +~~START~~ +varchar +World +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT 'Hello' + NULL; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT 'Hello' + NULL; +GO +~~START~~ +varchar +Hello +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT "" + NULL + 'World'; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT "" + NULL + 'World'; +GO +~~START~~ +varchar +World +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT "" + NULL + ""; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT "" + NULL + ""; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + "World"; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + "World"; +GO +~~START~~ +varchar +World +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + ""; +GO +~~START~~ +varchar + +~~END~~ + + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + ""; +GO +~~START~~ +varchar + +~~END~~ + diff --git a/test/JDBC/input/babel_4299.sql b/test/JDBC/input/babel_4299.sql new file mode 100644 index 0000000000..f295fde3d7 --- /dev/null +++ b/test/JDBC/input/babel_4299.sql @@ -0,0 +1,149 @@ +select ''+'ps'; +GO + +select 'rs' + ''; +GO + +select '' + ''; +GO + +select '' + NULL; +GO + +select NULL + ''; +GO + +set quoted_identifier off +GO +select ""+'s'; +GO + +set quoted_identifier off +GO +select 'rs' + ""; +GO + +set quoted_identifier off +GO +select '' + ""; +GO + +set quoted_identifier off +GO +select "" + NULL; +GO + +set quoted_identifier off +GO +select NULL + ""; +GO + +set quoted_identifier off +GO +select ""+"s"; +GO + +set quoted_identifier off +GO +select "pr" + ""; +GO + +set quoted_identifier off +GO +select "" + ""; +GO + +set quoted_identifier off +GO +select "" + ""; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT 'Hello' + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT 'Hello' + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + ''; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + ''; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT 'Hello' + NULL; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT 'Hello' + NULL; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT "" + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT "" + NULL + 'World'; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT "" + NULL + ""; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT "" + NULL + ""; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + "World"; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + "World"; +GO + +SET CONCAT_NULL_YIELDS_NULL ON; +GO +SELECT '' + NULL + ""; +GO + +SET CONCAT_NULL_YIELDS_NULL OFF; +GO +SELECT '' + NULL + ""; +GO \ No newline at end of file