diff --git a/contrib/b_sql_plugin/Makefile b/contrib/b_sql_plugin/Makefile index 98804c3e1619178d3234cb5ec4c6876f0f6d2f8d..c26cef769ac109db60a21e66ca06c89967d7abd8 100644 --- a/contrib/b_sql_plugin/Makefile +++ b/contrib/b_sql_plugin/Makefile @@ -52,14 +52,20 @@ parser: utils: make -C $(utils) + +b_sql_plugin--1.0.sql: sql_script/* + cat $^ >> $@ +DATA_built = b_sql_plugin--1.0.sql + OBJS += plugin_postgres.o plugin_postgres.o: plugin_postgres.cpp OBJS += pg_builtin_proc.o pg_builtin_proc.o: pg_builtin_proc.cpp utils EXTENSION = b_sql_plugin -DATA = b_sql_plugin--1.0.sql -REGRESS = regexp join_without_on db_b_parser1 db_b_parser2 db_b_parser3 db_b_parser4 +REGRESS:=$(shell find ./sql -maxdepth 1 -type f) +REGRESS:=$(basename $(patsubst ./sql/%,%,$(REGRESS)) .sql) + REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress -c 0 -d 1 --single_node override CPPFLAGS :=$(filter-out -fPIE, $(CPPFLAGS)) -fPIC -I$(top_builddir)/$(subdir)/include -fvisibility=hidden -I. diff --git a/contrib/b_sql_plugin/expected/test_binary.out b/contrib/b_sql_plugin/expected/test_binary.out new file mode 100644 index 0000000000000000000000000000000000000000..0aa20bc600742f7ede91ac4ec8b918664181b2a8 --- /dev/null +++ b/contrib/b_sql_plugin/expected/test_binary.out @@ -0,0 +1,96 @@ +drop database if exists test; +NOTICE: database "test" does not exist, skipping +create database test dbcompatibility 'B'; +\c test +create extension b_sql_plugin; +create table binary_templates (a bytea, b binary(5), c varbinary(5)); +-- invalid typmod +create table invalid_table (b binary(-1)); +ERROR: length for type binary must be at least 0 +create table invalid_table (b binary(256)); +ERROR: length for type binary cannot exceed 255 +create table invalid_table (b varbinary(-1)); +ERROR: length for type varbinary must be at least 0 +create table invalid_table (b varbinary(65536)); +ERROR: length for type varbinary cannot exceed 65535 +insert into binary_templates values ('aaa', 'aaa', 'aaa'); +insert into binary_templates values ('aaa', 'aaa', 'aaaaa'); +-- invalid insert +insert into binary_templates values ('aaaaaa', 'aaaaaa', 'aaa'); +ERROR: The input length:6 exceeds the maximum length:5. +CONTEXT: referenced column: b +insert into binary_templates values ('aaaaaa', 'aaa', 'aaaaaa'); +ERROR: The input length:6 exceeds the maximum length:5. +CONTEXT: referenced column: c +select * from binary_templates; + a | b | c +----------+--------------+-------------- + \x616161 | \x6161610000 | \x616161 + \x616161 | \x6161610000 | \x6161616161 +(2 rows) + +create table test_bytea (a bytea); +create table test_binary (a binary(5)); +create table test_varbinary (a varbinary(5)); +insert into test_bytea select a from binary_templates; +insert into test_bytea select b from binary_templates; +insert into test_bytea select c from binary_templates; +insert into test_binary select a from binary_templates; +insert into test_binary select b from binary_templates; +insert into test_binary select c from binary_templates; +insert into test_varbinary select a from binary_templates; +insert into test_varbinary select b from binary_templates; +insert into test_varbinary select c from binary_templates; +create table shorter_binary (a binary(3)); +create table shorter_varbinary (a varbinary(3)); +insert into shorter_binary select b from binary_templates; +ERROR: The input length:5 exceeds the maximum length:3. +CONTEXT: referenced column: a +insert into shorter_varbinary select c from binary_templates; +ERROR: The input length:5 exceeds the maximum length:3. +CONTEXT: referenced column: a +create table test_index (a binary(10), b varbinary(10)); +create index on test_index using btree (a); +create index on test_index using hash (a); +create index on test_index using gin (to_tsvector(a::text)); +create index on test_index using btree (b); +create index on test_index using hash (b); +create index on test_index using gin (to_tsvector(b::text)); +\d test_index + Table "public.test_index" + Column | Type | Modifiers +--------+---------------+----------- + a | "binary"(10) | + b | varbinary(10) | +Indexes: + "test_index_a_idx" btree (a) TABLESPACE pg_default + "test_index_a_idx1" hash (a) TABLESPACE pg_default + "test_index_b_idx" btree (b) TABLESPACE pg_default + "test_index_b_idx1" hash (b) TABLESPACE pg_default + "test_index_to_tsvector_idx" gin (to_tsvector(a::text)) TABLESPACE pg_default + "test_index_to_tsvector_idx1" gin (to_tsvector(b::text)) TABLESPACE pg_default + +create cast (text as binary) without function as implicit; +create cast (text as varbinary) without function as implicit; +create table test_text2binary (a binary(255), b varbinary(65535)); +insert into test_text2binary values(repeat('a', 256), repeat('a', 65536)); +ERROR: The input length:256 exceeds the maximum length:255. +CONTEXT: referenced column: a +insert into test_text2binary values(repeat('a', 255), repeat('a', 65535)); +select octet_length(a) as binary_length, octet_length(b) as varbinary_length from test_text2binary; + binary_length | varbinary_length +---------------+------------------ + 255 | 65535 +(1 row) + +drop cast if exists (text as binary); +drop cast if exists (text as varbinary); +drop table binary_templates; +drop table test_binary; +drop table test_varbinary; +drop table shorter_binary; +drop table shorter_varbinary; +drop table test_index; +drop table test_text2binary; +\c postgres +drop database test; diff --git a/contrib/b_sql_plugin/expected/test_blob.out b/contrib/b_sql_plugin/expected/test_blob.out new file mode 100644 index 0000000000000000000000000000000000000000..8d1baaab7349a4e07fce57cf91a685caa8661e0d --- /dev/null +++ b/contrib/b_sql_plugin/expected/test_blob.out @@ -0,0 +1,38 @@ +drop database if exists test; +NOTICE: database "test" does not exist, skipping +create database test dbcompatibility 'B'; +\c test +create extension b_sql_plugin; +create table test_template (t tinyblob, b blob, m mediumblob, l longblob); +insert into test_template values('aaaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaa'); +create table test_tiny (t tinyblob); +create table test_blob (b blob); +create table test_medium (m mediumblob); +create table test_long (l longblob); +insert into test_tiny select t from test_template; +insert into test_tiny select b from test_template; +insert into test_tiny select m from test_template; +insert into test_tiny select l from test_template; +insert into test_blob select t from test_template; +insert into test_blob select b from test_template; +insert into test_blob select m from test_template; +insert into test_blob select l from test_template; +insert into test_medium select t from test_template; +insert into test_medium select b from test_template; +insert into test_medium select m from test_template; +insert into test_medium select l from test_template; +insert into test_long select t from test_template; +insert into test_long select b from test_template; +insert into test_long select m from test_template; +insert into test_long select l from test_template; +\COPY test_template to './test_template.data'; +create table test_template2 (t tinyblob, b blob, m mediumblob, l longblob); +\COPY test_template2 from './test_template.data'; +drop table test_template; +drop table test_template2; +drop table test_tiny; +drop table test_blob; +drop table test_medium; +drop table test_long; +\c postgres +drop database test; diff --git a/contrib/b_sql_plugin/expected/test_fixed.out b/contrib/b_sql_plugin/expected/test_fixed.out new file mode 100644 index 0000000000000000000000000000000000000000..f57c54f49d00dea5358cb301b332b8ed2f9e2523 --- /dev/null +++ b/contrib/b_sql_plugin/expected/test_fixed.out @@ -0,0 +1,16 @@ +drop database if exists test; +NOTICE: database "test" does not exist, skipping +create database test dbcompatibility 'B'; +\c test +DROP TABLE IF EXISTS fixed_test; +NOTICE: table "fixed_test" does not exist, skipping +CREATE TABLE fixed_test (a fixed(10, 5)); +\d fixed_test + Table "public.fixed_test" + Column | Type | Modifiers +--------+---------------+----------- + a | numeric(10,5) | + +DROP TABLE fixed_test; +\c postgres +drop database test; diff --git a/contrib/b_sql_plugin/plugin_utils/adt/varlena.cpp b/contrib/b_sql_plugin/plugin_utils/adt/varlena.cpp index 4e600963879b32dfeb5d9d4e6584f2b62bd92706..570e98ff12b0077afb28fe443bc14eb3caa1d008 100644 --- a/contrib/b_sql_plugin/plugin_utils/adt/varlena.cpp +++ b/contrib/b_sql_plugin/plugin_utils/adt/varlena.cpp @@ -44,6 +44,14 @@ #define JUDGE_INPUT_VALID(X, Y) ((NULL == (X)) || (NULL == (Y))) #define GET_POSITIVE(X) ((X) > 0 ? (X) : ((-1) * (X))) +#define GetMaxLen(typmod) (typmod < (int32)VARHDRSZ ? 1 : typmod - (int32)VARHDRSZ) + +#define MAX_BINARY_LENGTH 255 +#define MAX_VARBINARY_LENGTH 65535 + +#define TinyBlobMaxAllocSize ((Size)255) /* 255B */ +#define MediumBlobMaxAllocSize ((Size)(16 * 1024 * 1024 - 1)) /* 16MB - 1 */ +#define LongBlobMaxAllocSize (((Size)4 * 1024 * 1024 * 1024 - 1)) /* 4GB - 1 */ static int getResultPostionReverse(text* textStr, text* textStrToSearch, int32 beginIndex, int occurTimes); static int getResultPostion(text* textStr, text* textStrToSearch, int32 beginIndex, int occurTimes); @@ -135,6 +143,51 @@ static void text_format_append_string(StringInfo buf, const char* str, int flags // adapt A db's substrb static text* get_substring_really(Datum str, int32 start, int32 length, bool length_not_specified); +static void check_blob_size(Datum blob, int64 max_size); +static int32 anybinary_typmodin(ArrayType* ta, const char* typname, uint32 max); +static char* anybinary_typmodout(int32 typmod); +static Datum copy_binary(Datum source, int typmod, bool target_is_var); +static bytea* copy_blob(bytea* source, int64 max_size); + +PG_FUNCTION_INFO_V1_PUBLIC(binary_typmodin); +extern "C" DLL_PUBLIC Datum binary_typmodin(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(varbinary_typmodin); +extern "C" DLL_PUBLIC Datum varbinary_typmodin(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(binary_typmodout); +extern "C" DLL_PUBLIC Datum binary_typmodout(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(bytea2binary); +extern "C" DLL_PUBLIC Datum bytea2binary(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(bytea2var); +extern "C" DLL_PUBLIC Datum bytea2var(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(tinyblob_rawin); +extern "C" DLL_PUBLIC Datum tinyblob_rawin(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(mediumblob_rawin); +extern "C" DLL_PUBLIC Datum mediumblob_rawin(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(longblob_rawin); +extern "C" DLL_PUBLIC Datum longblob_rawin(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(tinyblob_recv); +extern "C" DLL_PUBLIC Datum tinyblob_recv(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(mediumblob_recv); +extern "C" DLL_PUBLIC Datum mediumblob_recv(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(longblob_recv); +extern "C" DLL_PUBLIC Datum longblob_recv(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(longblob2tinyblob); +extern "C" DLL_PUBLIC Datum longblob2tinyblob(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1_PUBLIC(longblob2mediumblob); +extern "C" DLL_PUBLIC Datum longblob2mediumblob(PG_FUNCTION_ARGS); + /***************************************************************************** * CONVERSION ROUTINES EXPORTED FOR USE BY C CODE * *****************************************************************************/ @@ -6803,3 +6856,191 @@ Datum float8_text(PG_FUNCTION_ARGS) pfree_ext(tmp); PG_RETURN_DATUM(result); } + +static Datum copy_binary(Datum source, int typmod, bool target_is_var) +{ + int maxlen = GetMaxLen(typmod); + int length = VARSIZE(source) - VARHDRSZ; + + if (length > maxlen) { + ereport(ERROR, (errmsg("The input length:%d exceeds the maximum length:%d.", length, maxlen))); + } + + char* data = NULL; + struct varlena* attr = (struct varlena*)DatumGetPointer(source); + data = attr->vl_dat; + + bytea* result = NULL; + int alloc_size = (target_is_var ? length : maxlen) + VARHDRSZ; + result = (bytea*)palloc0(alloc_size); + SET_VARSIZE(result, alloc_size); + if (length == 0) { + PG_RETURN_POINTER(result); + } + char* rp = VARDATA(result); + errno_t errorno = memcpy_s(rp, length, data, length); + securec_check(errorno, "\0", "\0"); + PG_RETURN_BYTEA_P(result); +} + +static bytea* copy_blob(bytea* source, int64 max_size) +{ + int64 nbytes = VARSIZE(source); + if (nbytes - VARHDRSZ > max_size) { + ereport(ERROR, (errmsg("The length: %ld bytes is exceeded the max length: %ld bytes", + nbytes, max_size))); + } + bytea* target = (bytea*)palloc(nbytes); + SET_VARSIZE(target, nbytes); + if (nbytes == VARHDRSZ) { + return target; + } + char* rp = VARDATA(target); + char* data = source->vl_dat; + errno_t errorno = memcpy_s(rp, nbytes - VARHDRSZ, data, nbytes - VARHDRSZ); + securec_check(errorno, "\0", "\0"); + return target; +} + +static void check_blob_size(Datum blob, int64 max_size) +{ + int64 nbytes = toast_datum_size(blob) - VARHDRSZ; + if (nbytes > max_size) { + ereport(ERROR, (errmsg("The length: %ld bytes is exceeded the max length: %ld bytes", + nbytes, max_size))); + } +} + +static int32 anybinary_typmodin(ArrayType* ta, const char* typname, uint32 max) +{ + int32 typmod; + int32* tl = NULL; + int n; + + tl = ArrayGetIntegerTypmods(ta, &n); + + if (n != 1) { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid type modifier"))); + } + + if (*tl < 0){ + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("length for type %s must be at least 0", typname))); + } + + if (*((uint32*)tl) > max) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("length for type %s cannot exceed %u", typname, max))); + } + + typmod = VARHDRSZ + *tl; + + return typmod; +} + +/* common code for bpchartypmodout and varchartypmodout */ +static char* anybinary_typmodout(int32 typmod) +{ + const size_t buffer_len = 64; + + char* res = (char*)palloc(buffer_len); + errno_t ss_rc = 0; + + if (typmod > VARHDRSZ) { + ss_rc = snprintf_s(res, buffer_len, buffer_len - 1, "(%d)", (int)(typmod - VARHDRSZ)); + securec_check_ss(ss_rc, "\0", "\0"); + } else + *res = '\0'; + + return res; +} + +Datum binary_typmodin(PG_FUNCTION_ARGS) +{ + ArrayType* ta = PG_GETARG_ARRAYTYPE_P(0); + + PG_RETURN_INT32(anybinary_typmodin(ta, "binary", MAX_BINARY_LENGTH)); +} + +Datum varbinary_typmodin(PG_FUNCTION_ARGS) +{ + ArrayType* ta = PG_GETARG_ARRAYTYPE_P(0); + + PG_RETURN_INT32(anybinary_typmodin(ta, "varbinary", MAX_VARBINARY_LENGTH)); +} + +Datum binary_typmodout(PG_FUNCTION_ARGS) +{ + int32 typmod = PG_GETARG_INT32(0); + + PG_RETURN_CSTRING(anybinary_typmodout(typmod)); +} + +Datum bytea2binary(PG_FUNCTION_ARGS) +{ + bytea* source = PG_GETARG_BYTEA_P(0); + int32 maxlen = PG_GETARG_INT32(1); + return copy_binary(PointerGetDatum(source), maxlen, false); +} + +Datum bytea2var(PG_FUNCTION_ARGS) +{ + bytea* source = PG_GETARG_BYTEA_P(0); + int32 maxlen = PG_GETARG_INT32(1); + return copy_binary(PointerGetDatum(source), maxlen, true); +} + +Datum tinyblob_rawin(PG_FUNCTION_ARGS) +{ + Datum result = rawin(fcinfo); + check_blob_size(result, (int64)TinyBlobMaxAllocSize); + return result; +} + +Datum mediumblob_rawin(PG_FUNCTION_ARGS) +{ + Datum result = rawin(fcinfo); + check_blob_size(result, (int64)MediumBlobMaxAllocSize); + return result; +} + +Datum longblob_rawin(PG_FUNCTION_ARGS) +{ + Datum result = rawin(fcinfo); + check_blob_size(result, (int64)LongBlobMaxAllocSize); + return result; +} + +Datum tinyblob_recv(PG_FUNCTION_ARGS) +{ + Datum result = bytearecv(fcinfo); + check_blob_size(result, (int64)TinyBlobMaxAllocSize); + return result; +} + +Datum mediumblob_recv(PG_FUNCTION_ARGS) +{ + Datum result = bytearecv(fcinfo); + check_blob_size(result, (int64)MediumBlobMaxAllocSize); + return result; +} + +Datum longblob_recv(PG_FUNCTION_ARGS) +{ + Datum result = bytearecv(fcinfo); + check_blob_size(result, (int64)LongBlobMaxAllocSize); + return result; +} + +Datum longblob2tinyblob(PG_FUNCTION_ARGS) +{ + bytea* source = PG_GETARG_BYTEA_P(0); + PG_RETURN_BYTEA_P(copy_blob(source, (int64)TinyBlobMaxAllocSize)); +} + +Datum longblob2mediumblob(PG_FUNCTION_ARGS) +{ + bytea* source = PG_GETARG_BYTEA_P(0); + PG_RETURN_BYTEA_P(copy_blob(source, (int64)MediumBlobMaxAllocSize)); +} diff --git a/contrib/b_sql_plugin/sql/test_binary.sql b/contrib/b_sql_plugin/sql/test_binary.sql new file mode 100644 index 0000000000000000000000000000000000000000..44e81b985867af499f8d074776e3eec96d0c1eb5 --- /dev/null +++ b/contrib/b_sql_plugin/sql/test_binary.sql @@ -0,0 +1,69 @@ +drop database if exists test; +create database test dbcompatibility 'B'; +\c test +create extension b_sql_plugin; +create table binary_templates (a bytea, b binary(5), c varbinary(5)); + +-- invalid typmod +create table invalid_table (b binary(-1)); +create table invalid_table (b binary(256)); +create table invalid_table (b varbinary(-1)); +create table invalid_table (b varbinary(65536)); + +insert into binary_templates values ('aaa', 'aaa', 'aaa'); +insert into binary_templates values ('aaa', 'aaa', 'aaaaa'); + +-- invalid insert +insert into binary_templates values ('aaaaaa', 'aaaaaa', 'aaa'); +insert into binary_templates values ('aaaaaa', 'aaa', 'aaaaaa'); + +select * from binary_templates; + +create table test_bytea (a bytea); +create table test_binary (a binary(5)); +create table test_varbinary (a varbinary(5)); + +insert into test_bytea select a from binary_templates; +insert into test_bytea select b from binary_templates; +insert into test_bytea select c from binary_templates; + +insert into test_binary select a from binary_templates; +insert into test_binary select b from binary_templates; +insert into test_binary select c from binary_templates; + +insert into test_varbinary select a from binary_templates; +insert into test_varbinary select b from binary_templates; +insert into test_varbinary select c from binary_templates; + +create table shorter_binary (a binary(3)); +create table shorter_varbinary (a varbinary(3)); +insert into shorter_binary select b from binary_templates; +insert into shorter_varbinary select c from binary_templates; + +create table test_index (a binary(10), b varbinary(10)); +create index on test_index using btree (a); +create index on test_index using hash (a); +create index on test_index using gin (to_tsvector(a::text)); +create index on test_index using btree (b); +create index on test_index using hash (b); +create index on test_index using gin (to_tsvector(b::text)); +\d test_index + +create cast (text as binary) without function as implicit; +create cast (text as varbinary) without function as implicit; + +create table test_text2binary (a binary(255), b varbinary(65535)); +insert into test_text2binary values(repeat('a', 256), repeat('a', 65536)); +insert into test_text2binary values(repeat('a', 255), repeat('a', 65535)); +select octet_length(a) as binary_length, octet_length(b) as varbinary_length from test_text2binary; +drop cast if exists (text as binary); +drop cast if exists (text as varbinary); +drop table binary_templates; +drop table test_binary; +drop table test_varbinary; +drop table shorter_binary; +drop table shorter_varbinary; +drop table test_index; +drop table test_text2binary; +\c postgres +drop database test; \ No newline at end of file diff --git a/contrib/b_sql_plugin/sql/test_blob.sql b/contrib/b_sql_plugin/sql/test_blob.sql new file mode 100644 index 0000000000000000000000000000000000000000..2e53ca7e03dc63382689a0ab89baaf81d6db6ad6 --- /dev/null +++ b/contrib/b_sql_plugin/sql/test_blob.sql @@ -0,0 +1,43 @@ +drop database if exists test; +create database test dbcompatibility 'B'; +\c test +create extension b_sql_plugin; +create table test_template (t tinyblob, b blob, m mediumblob, l longblob); +insert into test_template values('aaaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaa'); +create table test_tiny (t tinyblob); +create table test_blob (b blob); +create table test_medium (m mediumblob); +create table test_long (l longblob); + +insert into test_tiny select t from test_template; +insert into test_tiny select b from test_template; +insert into test_tiny select m from test_template; +insert into test_tiny select l from test_template; + +insert into test_blob select t from test_template; +insert into test_blob select b from test_template; +insert into test_blob select m from test_template; +insert into test_blob select l from test_template; + +insert into test_medium select t from test_template; +insert into test_medium select b from test_template; +insert into test_medium select m from test_template; +insert into test_medium select l from test_template; + +insert into test_long select t from test_template; +insert into test_long select b from test_template; +insert into test_long select m from test_template; +insert into test_long select l from test_template; + +\COPY test_template to './test_template.data'; +create table test_template2 (t tinyblob, b blob, m mediumblob, l longblob); +\COPY test_template2 from './test_template.data'; + +drop table test_template; +drop table test_template2; +drop table test_tiny; +drop table test_blob; +drop table test_medium; +drop table test_long; +\c postgres +drop database test; \ No newline at end of file diff --git a/contrib/b_sql_plugin/sql/test_fixed.sql b/contrib/b_sql_plugin/sql/test_fixed.sql new file mode 100644 index 0000000000000000000000000000000000000000..2911b7207b513de5c610f0177d20f1d3e7587194 --- /dev/null +++ b/contrib/b_sql_plugin/sql/test_fixed.sql @@ -0,0 +1,9 @@ +drop database if exists test; +create database test dbcompatibility 'B'; +\c test +DROP TABLE IF EXISTS fixed_test; +CREATE TABLE fixed_test (a fixed(10, 5)); +\d fixed_test +DROP TABLE fixed_test; +\c postgres +drop database test; \ No newline at end of file diff --git a/contrib/b_sql_plugin/b_sql_plugin--1.0.sql b/contrib/b_sql_plugin/sql_script/base.sql similarity index 99% rename from contrib/b_sql_plugin/b_sql_plugin--1.0.sql rename to contrib/b_sql_plugin/sql_script/base.sql index e5b9b88092d0f29f6190e0fcc03dc7ab39cc5c99..59de578259c0d95809f8901a3159dc0852f923ea 100644 --- a/contrib/b_sql_plugin/b_sql_plugin--1.0.sql +++ b/contrib/b_sql_plugin/sql_script/base.sql @@ -208,4 +208,4 @@ begin return (select trunc(t1, num)); end; $$ -language plpgsql; \ No newline at end of file +language plpgsql; diff --git a/contrib/b_sql_plugin/sql_script/binary.sql b/contrib/b_sql_plugin/sql_script/binary.sql new file mode 100644 index 0000000000000000000000000000000000000000..00e4fac0a8cc50767de115e31530d85d3f82ad20 --- /dev/null +++ b/contrib/b_sql_plugin/sql_script/binary.sql @@ -0,0 +1,113 @@ +/* binary */ +DROP TYPE IF EXISTS pg_catalog.binary CASCADE; +DROP TYPE IF EXISTS pg_catalog._binary CASCADE; + +CREATE TYPE pg_catalog.binary; + +DROP FUNCTION IF EXISTS pg_catalog.binary_in(cstring) CASCADE; + +CREATE FUNCTION pg_catalog.binary_in ( +cstring +) RETURNS binary LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteain'; + +DROP FUNCTION IF EXISTS pg_catalog.binary_out(binary) CASCADE; + +CREATE FUNCTION pg_catalog.binary_out ( +binary +) RETURNS cstring LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteaout'; + +DROP FUNCTION IF EXISTS pg_catalog.binary_recv(internal, oid, int) CASCADE; + +CREATE FUNCTION pg_catalog.binary_recv ( +internal +) RETURNS binary LANGUAGE INTERNAL IMMUTABLE STRICT as 'bytearecv'; + +DROP FUNCTION IF EXISTS pg_catalog.binary_send(binary) CASCADE; + +CREATE FUNCTION pg_catalog.binary_send ( +binary +) RETURNS bytea LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteasend'; + +DROP FUNCTION IF EXISTS pg_catalog.binary_typmodin(_cstring) CASCADE; + +CREATE FUNCTION pg_catalog.binary_typmodin ( +_cstring +) RETURNS int LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'binary_typmodin'; + +DROP FUNCTION IF EXISTS pg_catalog.binary_typmodout(int) CASCADE; + +CREATE FUNCTION pg_catalog.binary_typmodout ( +int +) RETURNS cstring LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'binary_typmodout'; + +CREATE TYPE pg_catalog.binary (input=binary_in, output=binary_out, + typmod_in = binary_typmodin, typmod_out = binary_typmodout, + receive = binary_recv, send = binary_send, + STORAGE=EXTENDED, category='U'); + +/* varbinary */ +DROP TYPE IF EXISTS pg_catalog.varbinary CASCADE; +DROP TYPE IF EXISTS pg_catalog._varbinary CASCADE; + +CREATE TYPE pg_catalog.varbinary; + +DROP FUNCTION IF EXISTS pg_catalog.varbinary_in(cstring, oid, int) CASCADE; + +CREATE FUNCTION pg_catalog.varbinary_in ( +cstring +) RETURNS varbinary LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteain'; + +DROP FUNCTION IF EXISTS pg_catalog.varbinary_out(varbinary) CASCADE; + +CREATE FUNCTION pg_catalog.varbinary_out ( +varbinary +) RETURNS cstring LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteaout'; + +DROP FUNCTION IF EXISTS pg_catalog.varbinary_recv(internal, oid, int) CASCADE; + +CREATE FUNCTION pg_catalog.varbinary_recv ( +internal +) RETURNS varbinary LANGUAGE INTERNAL IMMUTABLE STRICT as 'bytearecv'; + +DROP FUNCTION IF EXISTS pg_catalog.varbinary_send(varbinary) CASCADE; + +CREATE FUNCTION pg_catalog.varbinary_send ( +varbinary +) RETURNS bytea LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteasend'; + +DROP FUNCTION IF EXISTS pg_catalog.varbinary_typmodin(_cstring) CASCADE; + +CREATE FUNCTION pg_catalog.varbinary_typmodin ( +_cstring +) RETURNS int LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'varbinary_typmodin'; + +CREATE TYPE pg_catalog.varbinary (input=varbinary_in, output=varbinary_out, + typmod_in = varbinary_typmodin, typmod_out = binary_typmodout, + receive = varbinary_recv, send = varbinary_send, + STORAGE=EXTENDED, category='U'); + +-- to_binary +DROP FUNCTION IF EXISTS pg_catalog.to_binary(bytea, int) CASCADE; + +CREATE FUNCTION pg_catalog.to_binary ( +bytea, +int +) RETURNS binary LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'bytea2binary'; +-- to_varbinary +DROP FUNCTION IF EXISTS pg_catalog.to_varbinary(bytea, int) CASCADE; + +CREATE FUNCTION pg_catalog.to_varbinary ( +bytea, +int +) RETURNS varbinary LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'bytea2var'; + + +CREATE CAST (binary AS bytea) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (varbinary AS bytea) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (bytea AS binary) WITH FUNCTION to_binary(bytea, int) AS IMPLICIT; +CREATE CAST (bytea AS varbinary) WITH FUNCTION to_varbinary(bytea, int) AS IMPLICIT; + +CREATE CAST (varbinary AS binary) WITH FUNCTION to_binary(bytea, int) AS IMPLICIT; +CREATE CAST (binary AS varbinary) WITH FUNCTION to_varbinary(bytea, int) AS IMPLICIT; +CREATE CAST (binary AS binary) WITH FUNCTION to_binary(bytea, int) AS IMPLICIT; +CREATE CAST (varbinary AS varbinary) WITH FUNCTION to_varbinary(bytea, int) AS IMPLICIT; diff --git a/contrib/b_sql_plugin/sql_script/blob.sql b/contrib/b_sql_plugin/sql_script/blob.sql new file mode 100644 index 0000000000000000000000000000000000000000..b91bdb9e7248027b0737b6f0c813ee59b5e1d68f --- /dev/null +++ b/contrib/b_sql_plugin/sql_script/blob.sql @@ -0,0 +1,134 @@ +-- tinyblob +DROP TYPE IF EXISTS pg_catalog.tinyblob CASCADE; +DROP TYPE IF EXISTS pg_catalog._tinyblob CASCADE; + +CREATE TYPE pg_catalog.tinyblob; + +DROP FUNCTION IF EXISTS pg_catalog.tinyblob_rawin(cstring) CASCADE; + +CREATE FUNCTION pg_catalog.tinyblob_rawin ( +cstring +) RETURNS tinyblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'tinyblob_rawin'; + +DROP FUNCTION IF EXISTS pg_catalog.tinyblob_rawout(tinyblob) CASCADE; + +CREATE FUNCTION pg_catalog.tinyblob_rawout ( +tinyblob +) RETURNS cstring LANGUAGE INTERNAL IMMUTABLE STRICT as 'rawout'; + +DROP FUNCTION IF EXISTS pg_catalog.tinyblob_recv(internal) CASCADE; + +CREATE FUNCTION pg_catalog.tinyblob_recv ( +internal +) RETURNS tinyblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'tinyblob_recv'; + +DROP FUNCTION IF EXISTS pg_catalog.tinyblob_send(tinyblob) CASCADE; + +CREATE FUNCTION pg_catalog.tinyblob_send ( +tinyblob +) RETURNS bytea LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteasend'; + +CREATE TYPE pg_catalog.tinyblob (input=tinyblob_rawin, output=tinyblob_rawout, RECEIVE = tinyblob_recv, SEND = tinyblob_send, STORAGE=EXTENDED, category='C'); + + +--mediumblob +DROP TYPE IF EXISTS pg_catalog.mediumblob CASCADE; +DROP TYPE IF EXISTS pg_catalog._mediumblob CASCADE; + +CREATE TYPE pg_catalog.mediumblob; + +DROP FUNCTION IF EXISTS pg_catalog.mediumblob_rawin(cstring) CASCADE; + +CREATE FUNCTION pg_catalog.mediumblob_rawin ( +cstring +) RETURNS mediumblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'mediumblob_rawin'; + +DROP FUNCTION IF EXISTS pg_catalog.mediumblob_rawout(mediumblob) CASCADE; + +CREATE FUNCTION pg_catalog.mediumblob_rawout ( +mediumblob +) RETURNS cstring LANGUAGE INTERNAL IMMUTABLE STRICT as 'rawout'; + +DROP FUNCTION IF EXISTS pg_catalog.mediumblob_recv(internal) CASCADE; + +CREATE FUNCTION pg_catalog.mediumblob_recv ( +internal +) RETURNS mediumblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'mediumblob_recv'; + +DROP FUNCTION IF EXISTS pg_catalog.mediumblob_send(mediumblob) CASCADE; + +CREATE FUNCTION pg_catalog.mediumblob_send ( +mediumblob +) RETURNS bytea LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteasend'; + +CREATE TYPE pg_catalog.mediumblob (input=mediumblob_rawin, output=mediumblob_rawout, RECEIVE = mediumblob_recv, SEND = mediumblob_send, STORAGE=EXTENDED, category='U'); + +-- longblob +DROP TYPE IF EXISTS pg_catalog.longblob CASCADE; +DROP TYPE IF EXISTS pg_catalog._longblob CASCADE; + +CREATE TYPE pg_catalog.longblob; + +DROP FUNCTION IF EXISTS pg_catalog.longblob_rawin(cstring) CASCADE; + +CREATE FUNCTION pg_catalog.longblob_rawin ( +cstring +) RETURNS longblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'longblob_rawin'; + +DROP FUNCTION IF EXISTS pg_catalog.longblob_rawout(longblob) CASCADE; + +CREATE FUNCTION pg_catalog.longblob_rawout ( +longblob +) RETURNS cstring LANGUAGE INTERNAL IMMUTABLE STRICT as 'rawout'; + +DROP FUNCTION IF EXISTS pg_catalog.longblob_recv(internal) CASCADE; + +CREATE FUNCTION pg_catalog.longblob_recv ( +internal +) RETURNS longblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'longblob_recv'; + +DROP FUNCTION IF EXISTS pg_catalog.longblob_send(longblob) CASCADE; + +CREATE FUNCTION pg_catalog.longblob_send ( +longblob +) RETURNS bytea LANGUAGE INTERNAL IMMUTABLE STRICT as 'byteasend'; + +CREATE TYPE pg_catalog.longblob (input=longblob_rawin, output=longblob_rawout, RECEIVE = longblob_recv, SEND = longblob_send, STORAGE=EXTENDED, category='U'); + +-- to_tinyblob +DROP FUNCTION IF EXISTS pg_catalog.to_tinyblob(longblob) CASCADE; + +CREATE FUNCTION pg_catalog.to_tinyblob ( +longblob +) RETURNS tinyblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'longblob2tinyblob'; + +-- to_mediumblob +DROP FUNCTION IF EXISTS pg_catalog.to_mediumblob(longblob) CASCADE; + +CREATE FUNCTION pg_catalog.to_mediumblob ( +longblob +) RETURNS mediumblob LANGUAGE C IMMUTABLE STRICT as '$libdir/b_sql_plugin', 'longblob2mediumblob'; + +CREATE CAST (tinyblob AS longblob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (mediumblob AS longblob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (blob AS longblob) WITHOUT FUNCTION AS IMPLICIT; + +CREATE CAST (blob AS tinyblob) WITH FUNCTION to_tinyblob(longblob) AS IMPLICIT; +CREATE CAST (mediumblob AS tinyblob) WITH FUNCTION to_tinyblob(longblob) AS IMPLICIT; +CREATE CAST (longblob AS tinyblob) WITH FUNCTION to_tinyblob(longblob) AS IMPLICIT; + +CREATE CAST (tinyblob AS blob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (mediumblob AS blob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (longblob AS blob) WITHOUT FUNCTION AS IMPLICIT; + +CREATE CAST (tinyblob AS mediumblob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (blob AS mediumblob) WITH FUNCTION to_mediumblob(longblob) AS IMPLICIT; +CREATE CAST (longblob AS mediumblob) WITH FUNCTION to_mediumblob(longblob) AS IMPLICIT; + +CREATE CAST (tinyblob AS raw) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (mediumblob AS raw) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (longblob AS raw) WITHOUT FUNCTION AS IMPLICIT; + +CREATE CAST (raw AS longblob) WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (raw AS tinyblob) WITH FUNCTION to_tinyblob(longblob) AS IMPLICIT; +CREATE CAST (raw AS mediumblob) WITH FUNCTION to_mediumblob(longblob) AS IMPLICIT;