diff --git a/contrib/age/regress/expected/cypher_match.out b/contrib/age/regress/expected/cypher_match.out index 7e2066da57e06f13ee05335a99be3fd899652988..e502c2b9f9e5010fe7224cf21c00a34fd55a339c 100644 --- a/contrib/age/regress/expected/cypher_match.out +++ b/contrib/age/regress/expected/cypher_match.out @@ -1068,7 +1068,7 @@ drop cascades to table cypher_match.e2 drop cascades to table cypher_match.v3 drop cascades to table cypher_match.e3 drop cascades to table cypher_match.loop -drop cascades to table cypher_match.self +drop cascades to table cypher_match."self" drop cascades to table cypher_match.duplicate drop cascades to table cypher_match.dup_edge drop cascades to table cypher_match.other_v diff --git a/contrib/datavec/CHANGELOG.md b/contrib/datavec/CHANGELOG.md index 042199daba35bba588fc579916e67f8861fa4397..13412c1caf45728d455414d6dbb9ebbb72dcec99 100644 --- a/contrib/datavec/CHANGELOG.md +++ b/contrib/datavec/CHANGELOG.md @@ -1,198 +1,3 @@ -## 0.7.2 (2024-06-11) +## 1.0 (2024-09-30) -- Fixed initialization fork for indexes on unlogged tables - -## 0.7.1 (2024-06-03) - -- Improved performance of on-disk HNSW index builds -- Fixed `undefined symbol` error with GCC 8 -- Fixed compilation error with universal binaries on Mac -- Fixed compilation warning with Clang < 14 - -## 0.7.0 (2024-04-29) - -- Added `halfvec` type -- Added `sparsevec` type -- Added support for indexing `bit` type -- Added support for indexing L1 distance with HNSW -- Added `binary_quantize` function -- Added `hamming_distance` function -- Added `jaccard_distance` function -- Added `l2_normalize` function -- Added `subvector` function -- Added concatenate operator for vectors -- Added CPU dispatching for distance functions on Linux x86-64 -- Updated comparison operators to support vectors with different dimensions - -## 0.6.2 (2024-03-18) - -- Reduced lock contention with parallel HNSW index builds - -## 0.6.1 (2024-03-04) - -- Fixed error with `ANALYZE` and vectors with different dimensions -- Fixed segmentation fault with `shared_preload_libraries` -- Fixed vector subtraction being marked as commutative - -## 0.6.0 (2024-01-29) - -- Added support for parallel index builds for HNSW -- Added validation for GUC parameters -- Changed storage for vector from `extended` to `external` -- Improved performance of HNSW -- Reduced memory usage for HNSW index builds -- Reduced WAL generation for HNSW index builds -- Fixed error with logical replication -- Fixed `invalid memory alloc request size` error with HNSW index builds -- Moved Docker image to `datavec` org -- Added Docker tags for each supported version of Postgres -- Dropped support for Postgres 11 - -## 0.5.1 (2023-10-10) - -- Improved performance of HNSW index builds -- Added check for MVCC-compliant snapshot for index scans - -## 0.5.0 (2023-08-28) - -- Added HNSW index type -- Added support for parallel index builds for IVFFlat -- Added `l1_distance` function -- Added element-wise multiplication for vectors -- Added `sum` aggregate -- Improved performance of distance functions -- Fixed out of range results for cosine distance -- Fixed results for NULL and NaN distances for IVFFlat - -## 0.4.4 (2023-06-12) - -- Improved error message for malformed vector literal -- Fixed segmentation fault with text input -- Fixed consecutive delimiters with text input - -## 0.4.3 (2023-06-10) - -- Improved cost estimation -- Improved support for spaces with text input -- Fixed infinite and NaN values with binary input -- Fixed infinite values with vector addition and subtraction -- Fixed infinite values with list centers -- Fixed compilation error when `float8` is pass by reference -- Fixed compilation error on PowerPC -- Fixed segmentation fault with index creation on i386 - -## 0.4.2 (2023-05-13) - -- Added notice when index created with little data -- Fixed dimensions check for some direct function calls -- Fixed installation error with Postgres 12.0-12.2 - -## 0.4.1 (2023-03-21) - -- Improved performance of cosine distance -- Fixed index scan count - -## 0.4.0 (2023-01-11) - -If upgrading with Postgres < 13, see [this note](https://github.com/datavec/datavec#040). - -- Changed text representation for vector elements to match `real` -- Changed storage for vector from `plain` to `extended` -- Increased max dimensions for vector from 1024 to 16000 -- Increased max dimensions for index from 1024 to 2000 -- Improved accuracy of text parsing for certain inputs -- Added `avg` aggregate for vector -- Added experimental support for Windows -- Dropped support for Postgres 10 - -## 0.3.2 (2022-11-22) - -- Fixed `invalid memory alloc request size` error - -## 0.3.1 (2022-11-02) - -If upgrading from 0.2.7 or 0.3.0, [recreate](https://github.com/datavec/datavec#031) all `ivfflat` indexes after upgrading to ensure all data is indexed. - -- Fixed issue with inserts silently corrupting `ivfflat` indexes (introduced in 0.2.7) -- Fixed segmentation fault with index creation when lists > 6500 - -## 0.3.0 (2022-10-15) - -- Added support for Postgres 15 -- Dropped support for Postgres 9.6 - -## 0.2.7 (2022-07-31) - -- Fixed `unexpected data beyond EOF` error - -## 0.2.6 (2022-05-22) - -- Improved performance of index creation for Postgres < 12 - -## 0.2.5 (2022-02-11) - -- Reduced memory usage during index creation -- Fixed index creation exceeding `maintenance_work_mem` -- Fixed error with index creation when lists > 1600 - -## 0.2.4 (2022-02-06) - -- Added support for parallel vacuum -- Fixed issue with index not reusing space - -## 0.2.3 (2022-01-30) - -- Added indexing progress for Postgres 12+ -- Improved interrupt handling during index creation - -## 0.2.2 (2022-01-15) - -- Fixed compilation error on Mac ARM - -## 0.2.1 (2022-01-02) - -- Fixed `operator is not unique` error - -## 0.2.0 (2021-10-03) - -- Added support for Postgres 14 - -## 0.1.8 (2021-09-07) - -- Added cast for `vector` to `real[]` - -## 0.1.7 (2021-06-13) - -- Added cast for `numeric[]` to `vector` - -## 0.1.6 (2021-06-09) - -- Fixed segmentation fault with `COUNT` - -## 0.1.5 (2021-05-25) - -- Reduced memory usage during index creation - -## 0.1.4 (2021-05-09) - -- Fixed kmeans for inner product -- Fixed multiple definition error with GCC 10 - -## 0.1.3 (2021-05-06) - -- Added Dockerfile -- Fixed version - -## 0.1.2 (2021-04-26) - -- Vectorized distance calculations -- Improved cost estimation - -## 0.1.1 (2021-04-25) - -- Added binary representation for `COPY` -- Marked functions as `PARALLEL SAFE` - -## 0.1.0 (2021-04-20) - -- First release +- First release, support vector data type and ivfflat and hnsw access methods. diff --git a/contrib/datavec/CMakeLists.txt b/contrib/datavec/CMakeLists.txt index ecba00c56911af0b4a2ef4985d88c440edf378dd..45108abeb79af36ab79a86e02afbaf91fee6774f 100644 --- a/contrib/datavec/CMakeLists.txt +++ b/contrib/datavec/CMakeLists.txt @@ -1,5 +1,5 @@ set(EXTENSION "datavec") -set(EXTVERSION "0.7.2") +set(EXTVERSION "1.0") file(GLOB_RECURSE TGT_datavec_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp @@ -10,8 +10,16 @@ SET(TGT_datavec_INC ${CMAKE_CURRENT_SOURCE_DIR}/src ) +if ((APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm") OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64*") + set(datavec_OPTFLAGS "") +else () + set(datavec_OPTFLAGS "-march=native") +endif () + +set(datavec_OPTFLAGS ${datavec_OPTFLAGS} -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math) + set(datavec_DEF_OPTIONS ${MACRO_OPTIONS}) -set(datavec_COMPILE_OPTIONS ${OPTIMIZE_OPTIONS} ${OS_OPTIONS} ${PROTECT_OPTIONS} ${WARNING_OPTIONS} ${LIB_SECURE_OPTIONS} ${CHECK_OPTIONS}) +set(datavec_COMPILE_OPTIONS ${OPTIMIZE_OPTIONS} ${datavec_OPTFLAGS} ${OS_OPTIONS} ${PROTECT_OPTIONS} ${WARNING_OPTIONS} ${LIB_SECURE_OPTIONS} ${CHECK_OPTIONS}) set(datavec_LINK_OPTIONS ${LIB_LINK_OPTIONS}) add_shared_libtarget(datavec TGT_datavec_SRC TGT_datavec_INC "${datavec_DEF_OPTIONS}" "${datavec_COMPILE_OPTIONS}" "${datavec_LINK_OPTIONS}") diff --git a/contrib/datavec/Makefile b/contrib/datavec/Makefile index 4ece8e71a553a9a6b343c922396bfe5591925a0f..8193dd944b463fa3c0c844485705b8f6293cda07 100644 --- a/contrib/datavec/Makefile +++ b/contrib/datavec/Makefile @@ -1,9 +1,9 @@ EXTENSION = datavec -EXTVERSION = 0.7.2 +EXTVERSION = 1.0 MODULE_big = datavec DATA = sql/$(EXTENSION)--$(EXTVERSION).sql -OBJS = src/bitutils.o src/bitvec.o src/f2s.o src/halfutils.o src/halfvec.o src/hnsw.o src/hnswbuild.o src/hnswinsert.o src/hnswscan.o src/hnswutils.o src/hnswvacuum.o src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/sparsevec.o src/vector.o +OBJS = src/bitutils.o src/bitvec.o src/f2s.o src/halfutils.o src/halfvec.o src/hnsw.o src/hnswbuild.o src/hnswdelete.o src/hnswinsert.o src/hnswscan.o src/hnswutils.o src/hnswvacuum.o src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/sparsevec.o src/vecindex.o src/vector.o HEADERS = src/halfvec.h src/sparsevec.h src/vector.h TESTS = $(wildcard test/sql/*.sql) @@ -55,8 +55,8 @@ include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif -override CXXFLAGS :=$(filter-out -fstack-protector, $(CFLAGS)) -fstack-protector-all -Wl,-z,relro,-z,now -fPIC -override CPPFLAGS +=$(filter-out -fstack-protector, $(CFLAGS)) -fstack-protector-all -Wl,-z,relro,-z,now -fPIC +override CXXFLAGS :=$(filter-out -fstack-protector, $(CFLAGS)) -fstack-protector-all -Wl,-z,relro,-z,now -fPIC $(PG_CFLAGS) +override CPPFLAGS +=$(filter-out -fstack-protector, $(CFLAGS)) -fstack-protector-all -Wl,-z,relro,-z,now -fPIC $(PG_CFLAGS) # for Mac ifeq ($(PROVE),) diff --git a/contrib/datavec/Makefile.win b/contrib/datavec/Makefile.win index 9d28f4b963f8b3f1fb1e0e7a4ba5ac61bfbacb69..2886af06a6dcb081f5efd44dd7ac0ba556c13515 100644 --- a/contrib/datavec/Makefile.win +++ b/contrib/datavec/Makefile.win @@ -1,5 +1,5 @@ EXTENSION = datavec -EXTVERSION = 0.7.2 +EXTVERSION = 1.0 OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj HEADERS = src\halfvec.h src\sparsevec.h src\vector.h diff --git a/contrib/datavec/datavec.control b/contrib/datavec/datavec.control index d5a1d299d2fbd267baa5725e583915bd58fbd54d..447960fbe9f713c3098d2316efaa9df0509e2cee 100644 --- a/contrib/datavec/datavec.control +++ b/contrib/datavec/datavec.control @@ -1,4 +1,4 @@ comment = 'vector data type and ivfflat and hnsw access methods' -default_version = '0.7.2' +default_version = '1.0' module_pathname = '$libdir/datavec' relocatable = true diff --git a/contrib/datavec/sql/datavec--0.1.0--0.1.1.sql b/contrib/datavec/sql/datavec--0.1.0--0.1.1.sql deleted file mode 100644 index 4387251a536bd831ef9e174d87127512cc02f52c..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.0--0.1.1.sql +++ /dev/null @@ -1,39 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.1'" to load this file. \quit - -CREATE FUNCTION vector_recv(internal, oid, integer) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION vector_send(vector) RETURNS bytea - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER TYPE vector SET ( RECEIVE = vector_recv, SEND = vector_send ); - --- functions - -ALTER FUNCTION vector_in(cstring, oid, integer) ; -ALTER FUNCTION vector_out(vector) ; -ALTER FUNCTION vector_typmod_in(cstring[]) ; -ALTER FUNCTION vector_recv(internal, oid, integer) ; -ALTER FUNCTION vector_send(vector) ; -ALTER FUNCTION l2_distance(vector, vector) ; -ALTER FUNCTION inner_product(vector, vector) ; -ALTER FUNCTION cosine_distance(vector, vector) ; -ALTER FUNCTION vector_dims(vector) ; -ALTER FUNCTION vector_norm(vector) ; -ALTER FUNCTION vector_add(vector, vector) ; -ALTER FUNCTION vector_sub(vector, vector) ; -ALTER FUNCTION vector_lt(vector, vector) ; -ALTER FUNCTION vector_le(vector, vector) ; -ALTER FUNCTION vector_eq(vector, vector) ; -ALTER FUNCTION vector_ne(vector, vector) ; -ALTER FUNCTION vector_ge(vector, vector) ; -ALTER FUNCTION vector_gt(vector, vector) ; -ALTER FUNCTION vector_cmp(vector, vector) ; -ALTER FUNCTION vector_l2_squared_distance(vector, vector) ; -ALTER FUNCTION vector_negative_inner_product(vector, vector) ; -ALTER FUNCTION vector_spherical_distance(vector, vector) ; -ALTER FUNCTION vector(vector, integer, boolean) ; -ALTER FUNCTION array_to_vector(integer[], integer, boolean) ; -ALTER FUNCTION array_to_vector(real[], integer, boolean) ; -ALTER FUNCTION array_to_vector(double precision[], integer, boolean) ; diff --git a/contrib/datavec/sql/datavec--0.1.1--0.1.3.sql b/contrib/datavec/sql/datavec--0.1.1--0.1.3.sql deleted file mode 100644 index 9db8b31d461d3f1b60c10bfd4938d36eb1096ed9..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.1--0.1.3.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.3'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.1.3--0.1.4.sql b/contrib/datavec/sql/datavec--0.1.3--0.1.4.sql deleted file mode 100644 index de133ed2ce21b1b265588d0fd338af55562879f0..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.3--0.1.4.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.4'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.1.4--0.1.5.sql b/contrib/datavec/sql/datavec--0.1.4--0.1.5.sql deleted file mode 100644 index 1d0ebd6f980cb6569e8eea804562af4c33f5fa77..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.4--0.1.5.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.5'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.1.5--0.1.6.sql b/contrib/datavec/sql/datavec--0.1.5--0.1.6.sql deleted file mode 100644 index b1006347478012769a39da338af7d17b483c7993..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.5--0.1.6.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.6'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.1.6--0.1.7.sql b/contrib/datavec/sql/datavec--0.1.6--0.1.7.sql deleted file mode 100644 index 52c514882bd9c0476c4bec367ee9edf0751808bf..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.6--0.1.7.sql +++ /dev/null @@ -1,8 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.7'" to load this file. \quit - -CREATE FUNCTION array_to_vector(numeric[], integer, boolean) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE CAST (numeric[] AS vector) - WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS IMPLICIT; diff --git a/contrib/datavec/sql/datavec--0.1.7--0.1.8.sql b/contrib/datavec/sql/datavec--0.1.7--0.1.8.sql deleted file mode 100644 index 5f198b9ae25692aa98a03106e21b3e5b6f0fa07c..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.7--0.1.8.sql +++ /dev/null @@ -1,8 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.1.8'" to load this file. \quit - -CREATE FUNCTION vector_to_float4(vector, integer, boolean) RETURNS real[] - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE CAST (vector AS real[]) - WITH FUNCTION vector_to_float4(vector, integer, boolean) AS IMPLICIT; diff --git a/contrib/datavec/sql/datavec--0.1.8--0.2.0.sql b/contrib/datavec/sql/datavec--0.1.8--0.2.0.sql deleted file mode 100644 index 529155d209ada60d204673101344de5841ecc058..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.1.8--0.2.0.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.0'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.0--0.2.1.sql b/contrib/datavec/sql/datavec--0.2.0--0.2.1.sql deleted file mode 100644 index 18320fc09123a95230709390461d109448cc5039..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.0--0.2.1.sql +++ /dev/null @@ -1,19 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.1'" to load this file. \quit - -DROP CAST (integer[] AS vector); -DROP CAST (real[] AS vector); -DROP CAST (double precision[] AS vector); -DROP CAST (numeric[] AS vector); - -CREATE CAST (integer[] AS vector) - WITH FUNCTION array_to_vector(integer[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (real[] AS vector) - WITH FUNCTION array_to_vector(real[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (double precision[] AS vector) - WITH FUNCTION array_to_vector(double precision[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (numeric[] AS vector) - WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS ASSIGNMENT; diff --git a/contrib/datavec/sql/datavec--0.2.1--0.2.2.sql b/contrib/datavec/sql/datavec--0.2.1--0.2.2.sql deleted file mode 100644 index 92b35521c5ebd5bd94acfe221cd46feb084c0f95..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.1--0.2.2.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.2'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.2--0.2.3.sql b/contrib/datavec/sql/datavec--0.2.2--0.2.3.sql deleted file mode 100644 index b1ffbe9738c8778ecb1522336971df46f66c04af..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.2--0.2.3.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.3'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.3--0.2.4.sql b/contrib/datavec/sql/datavec--0.2.3--0.2.4.sql deleted file mode 100644 index 8dd5b231cbaa45e23e91f2da44892e3d595e42cd..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.3--0.2.4.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.4'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.4--0.2.5.sql b/contrib/datavec/sql/datavec--0.2.4--0.2.5.sql deleted file mode 100644 index 4ba491c4d84e3c2d2cce7136eb96535b0df1333d..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.4--0.2.5.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.5'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.5--0.2.6.sql b/contrib/datavec/sql/datavec--0.2.5--0.2.6.sql deleted file mode 100644 index 6403ea096e06042235a234fa943dbf6920e78a6c..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.5--0.2.6.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.6'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.6--0.2.7.sql b/contrib/datavec/sql/datavec--0.2.6--0.2.7.sql deleted file mode 100644 index 7b7e6cff3d87f010b5d6fec9cd2c908497cc4f83..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.6--0.2.7.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.2.7'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.2.7--0.3.0.sql b/contrib/datavec/sql/datavec--0.2.7--0.3.0.sql deleted file mode 100644 index 257cfb5a4ef10729001ba7ff6c13396fa71d8b3d..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.2.7--0.3.0.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.3.0'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.3.0--0.3.1.sql b/contrib/datavec/sql/datavec--0.3.0--0.3.1.sql deleted file mode 100644 index 40bf35645d5ca932358bd2633d93d7a973f5066c..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.3.0--0.3.1.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.3.1'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.3.1--0.3.2.sql b/contrib/datavec/sql/datavec--0.3.1--0.3.2.sql deleted file mode 100644 index d3434ed1a23eab4aa2161f007cfb225be5fc4e3d..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.3.1--0.3.2.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.3.2'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.3.2--0.4.0.sql b/contrib/datavec/sql/datavec--0.3.2--0.4.0.sql deleted file mode 100644 index 39218eb075f740920d4910dfa997c514e667aff7..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.3.2--0.4.0.sql +++ /dev/null @@ -1,23 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.4.0'" to load this file. \quit - --- remove this single line for Postgres < 13 -ALTER TYPE vector SET (STORAGE = extended); - -CREATE FUNCTION vector_accum(double precision[], vector) RETURNS double precision[] - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_avg(double precision[]) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_combine(double precision[], double precision[]) RETURNS double precision[] - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE AGGREGATE avg(vector) ( - SFUNC = vector_accum, - STYPE = double precision[], - FINALFUNC = vector_avg, - COMBINEFUNC = vector_combine, - INITCOND = '{0}', - PARALLEL = SAFE -); diff --git a/contrib/datavec/sql/datavec--0.4.0--0.4.1.sql b/contrib/datavec/sql/datavec--0.4.0--0.4.1.sql deleted file mode 100644 index 811aebe52daa1a3039b170ea9bf7ca8ad66aec2f..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.4.0--0.4.1.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.4.1'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.4.1--0.4.2.sql b/contrib/datavec/sql/datavec--0.4.1--0.4.2.sql deleted file mode 100644 index d09bfcd5a7008d9bcae8c737f1d1ff788993625c..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.4.1--0.4.2.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.4.2'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.4.2--0.4.3.sql b/contrib/datavec/sql/datavec--0.4.2--0.4.3.sql deleted file mode 100644 index e7ac269a3e75143fff7aea921edd2b151073fd5d..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.4.2--0.4.3.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.4.3'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.4.3--0.4.4.sql b/contrib/datavec/sql/datavec--0.4.3--0.4.4.sql deleted file mode 100644 index 890d3cdb0b1675f4116b77de16240d02273ead8f..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.4.3--0.4.4.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.4.4'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.4.4--0.5.0.sql b/contrib/datavec/sql/datavec--0.4.4--0.5.0.sql deleted file mode 100644 index 827435b37a2f41ef6c8f2cc41a1f788720695b97..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.4.4--0.5.0.sql +++ /dev/null @@ -1,43 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.5.0'" to load this file. \quit - -CREATE FUNCTION l1_distance(vector, vector) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_mul(vector, vector) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE OPERATOR * ( - LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_mul, - COMMUTATOR = * -); - -CREATE AGGREGATE sum(vector) ( - SFUNC = vector_add, - STYPE = vector, - COMBINEFUNC = vector_add, - PARALLEL = SAFE -); - -CREATE FUNCTION hnswhandler(internal) RETURNS index_am_handler - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE ACCESS METHOD hnsw TYPE INDEX HANDLER hnswhandler; - -COMMENT ON ACCESS METHOD hnsw IS 'hnsw index access method'; - -CREATE OPERATOR CLASS vector_l2_ops - FOR TYPE vector USING hnsw AS - OPERATOR 1 <-> (vector, vector) FOR ORDER BY float_ops, - FUNCTION 1 vector_l2_squared_distance(vector, vector); - -CREATE OPERATOR CLASS vector_ip_ops - FOR TYPE vector USING hnsw AS - OPERATOR 1 <#> (vector, vector) FOR ORDER BY float_ops, - FUNCTION 1 vector_negative_inner_product(vector, vector); - -CREATE OPERATOR CLASS vector_cosine_ops - FOR TYPE vector USING hnsw AS - OPERATOR 1 <=> (vector, vector) FOR ORDER BY float_ops, - FUNCTION 1 vector_negative_inner_product(vector, vector), - FUNCTION 2 vector_norm(vector); diff --git a/contrib/datavec/sql/datavec--0.5.0--0.5.1.sql b/contrib/datavec/sql/datavec--0.5.0--0.5.1.sql deleted file mode 100644 index 0bfb8bb4997944b2be2729201be217a516c7dbf1..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.5.0--0.5.1.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.5.1'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.5.1--0.6.0.sql b/contrib/datavec/sql/datavec--0.5.1--0.6.0.sql deleted file mode 100644 index 241282d9d9829f2041c34b881c58b2276396e209..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.5.1--0.6.0.sql +++ /dev/null @@ -1,5 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.6.0'" to load this file. \quit - --- remove this single line for Postgres < 13 -ALTER TYPE datavec SET (STORAGE = external); diff --git a/contrib/datavec/sql/datavec--0.6.0--0.6.1.sql b/contrib/datavec/sql/datavec--0.6.0--0.6.1.sql deleted file mode 100644 index 4e70de251fa94b4b7786c79551baac175f9c008a..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.6.0--0.6.1.sql +++ /dev/null @@ -1,16 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.6.1'" to load this file. \quit - -DROP OPERATOR - (vector, vector); - -CREATE OPERATOR - ( - LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_sub -); - -ALTER OPERATOR <= (vector, vector) SET ( - RESTRICT = scalarlesel, JOIN = scalarlejoinsel -); - -ALTER OPERATOR >= (vector, vector) SET ( - RESTRICT = scalargesel, JOIN = scalargejoinsel -); diff --git a/contrib/datavec/sql/datavec--0.6.1--0.6.2.sql b/contrib/datavec/sql/datavec--0.6.1--0.6.2.sql deleted file mode 100644 index 8dcff8b7d995b263f0c62f45ad9e41f2945ae358..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.6.1--0.6.2.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.6.2'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.6.2--0.7.0.sql b/contrib/datavec/sql/datavec--0.6.2--0.7.0.sql deleted file mode 100644 index 61a0b5265e9672343933f71bad6636cd02efe0ac..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.6.2--0.7.0.sql +++ /dev/null @@ -1,569 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.7.0'" to load this file. \quit - -CREATE FUNCTION l2_normalize(vector) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION binary_quantize(vector) RETURNS bit - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION subvector(vector, int, int) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_concat(vector, vector) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE OPERATOR <+> ( - LEFTARG = vector, RIGHTARG = vector, PROCEDURE = l1_distance, - COMMUTATOR = '<+>' -); - -CREATE OPERATOR || ( - LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_concat -); - -CREATE FUNCTION ivfflat_halfvec_support(internal) RETURNS internal - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION ivfflat_bit_support(internal) RETURNS internal - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION hnsw_halfvec_support(internal) RETURNS internal - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION hnsw_bit_support(internal) RETURNS internal - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION hnsw_sparsevec_support(internal) RETURNS internal - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE OPERATOR CLASS vector_l1_ops - FOR TYPE vector USING hnsw AS - OPERATOR 1 <+> (vector, vector) FOR ORDER BY float_ops, - FUNCTION 1 l1_distance(vector, vector); - -CREATE TYPE halfvec; - -CREATE FUNCTION halfvec_in(cstring, oid, integer) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_out(halfvec) RETURNS cstring - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_typmod_in(cstring[]) RETURNS integer - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_recv(internal, oid, integer) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_send(halfvec) RETURNS bytea - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE TYPE halfvec ( - INPUT = halfvec_in, - OUTPUT = halfvec_out, - TYPMOD_IN = halfvec_typmod_in, - RECEIVE = halfvec_recv, - SEND = halfvec_send, - STORAGE = external -); - -CREATE FUNCTION l2_distance(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME', 'halfvec_l2_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION inner_product(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME', 'halfvec_inner_product' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION cosine_distance(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME', 'halfvec_cosine_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l1_distance(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME', 'halfvec_l1_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_dims(halfvec) RETURNS integer - AS 'MODULE_PATHNAME', 'halfvec_vector_dims' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l2_norm(halfvec) RETURNS float8 - AS 'MODULE_PATHNAME', 'halfvec_l2_norm' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l2_normalize(halfvec) RETURNS halfvec - AS 'MODULE_PATHNAME', 'halfvec_l2_normalize' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION binary_quantize(halfvec) RETURNS bit - AS 'MODULE_PATHNAME', 'halfvec_binary_quantize' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION subvector(halfvec, int, int) RETURNS halfvec - AS 'MODULE_PATHNAME', 'halfvec_subvector' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_add(halfvec, halfvec) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_sub(halfvec, halfvec) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_mul(halfvec, halfvec) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_concat(halfvec, halfvec) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_lt(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_le(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_eq(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_ne(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_ge(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_gt(halfvec, halfvec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_cmp(halfvec, halfvec) RETURNS int4 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_l2_squared_distance(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_negative_inner_product(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_spherical_distance(halfvec, halfvec) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_accum(double precision[], halfvec) RETURNS double precision[] - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_avg(double precision[]) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_combine(double precision[], double precision[]) RETURNS double precision[] - AS 'MODULE_PATHNAME', 'vector_combine' LANGUAGE C IMMUTABLE STRICT ; - -CREATE AGGREGATE avg(halfvec) ( - SFUNC = halfvec_accum, - STYPE = double precision[], - FINALFUNC = halfvec_avg, - COMBINEFUNC = halfvec_combine, - INITCOND = '{0}', - PARALLEL = SAFE -); - -CREATE AGGREGATE sum(halfvec) ( - SFUNC = halfvec_add, - STYPE = halfvec, - COMBINEFUNC = halfvec_add, - PARALLEL = SAFE -); - -CREATE FUNCTION halfvec(halfvec, integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_to_vector(halfvec, integer, boolean) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_to_halfvec(vector, integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION array_to_halfvec(integer[], integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION array_to_halfvec(real[], integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION array_to_halfvec(double precision[], integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION array_to_halfvec(numeric[], integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_to_float4(halfvec, integer, boolean) RETURNS real[] - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE CAST (halfvec AS halfvec) - WITH FUNCTION halfvec(halfvec, integer, boolean) AS IMPLICIT; - -CREATE CAST (halfvec AS vector) - WITH FUNCTION halfvec_to_vector(halfvec, integer, boolean) AS ASSIGNMENT; - -CREATE CAST (vector AS halfvec) - WITH FUNCTION vector_to_halfvec(vector, integer, boolean) AS IMPLICIT; - -CREATE CAST (halfvec AS real[]) - WITH FUNCTION halfvec_to_float4(halfvec, integer, boolean) AS ASSIGNMENT; - -CREATE CAST (integer[] AS halfvec) - WITH FUNCTION array_to_halfvec(integer[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (real[] AS halfvec) - WITH FUNCTION array_to_halfvec(real[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (double precision[] AS halfvec) - WITH FUNCTION array_to_halfvec(double precision[], integer, boolean) AS ASSIGNMENT; - -CREATE CAST (numeric[] AS halfvec) - WITH FUNCTION array_to_halfvec(numeric[], integer, boolean) AS ASSIGNMENT; - -CREATE OPERATOR <-> ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = l2_distance, - COMMUTATOR = '<->' -); - -CREATE OPERATOR <#> ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_negative_inner_product, - COMMUTATOR = '<#>' -); - -CREATE OPERATOR <=> ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = cosine_distance, - COMMUTATOR = '<=>' -); - -CREATE OPERATOR <+> ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = l1_distance, - COMMUTATOR = '<+>' -); - -CREATE OPERATOR + ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_add, - COMMUTATOR = + -); - -CREATE OPERATOR - ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_sub -); - -CREATE OPERATOR * ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_mul, - COMMUTATOR = * -); - -CREATE OPERATOR || ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_concat -); - -CREATE OPERATOR < ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_lt, - COMMUTATOR = > , NEGATOR = >= , - RESTRICT = scalarltsel, JOIN = scalarltjoinsel -); - -CREATE OPERATOR <= ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_le, - COMMUTATOR = >= , NEGATOR = > , - RESTRICT = scalarlesel, JOIN = scalarlejoinsel -); - -CREATE OPERATOR = ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_eq, - COMMUTATOR = = , NEGATOR = <> , - RESTRICT = eqsel, JOIN = eqjoinsel -); - -CREATE OPERATOR <> ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_ne, - COMMUTATOR = <> , NEGATOR = = , - RESTRICT = eqsel, JOIN = eqjoinsel -); - -CREATE OPERATOR >= ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_ge, - COMMUTATOR = <= , NEGATOR = < , - RESTRICT = scalargesel, JOIN = scalargejoinsel -); - -CREATE OPERATOR > ( - LEFTARG = halfvec, RIGHTARG = halfvec, PROCEDURE = halfvec_gt, - COMMUTATOR = < , NEGATOR = <= , - RESTRICT = scalargtsel, JOIN = scalargtjoinsel -); - -CREATE OPERATOR CLASS halfvec_ops - DEFAULT FOR TYPE halfvec USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 halfvec_cmp(halfvec, halfvec); - -CREATE OPERATOR CLASS halfvec_l2_ops - FOR TYPE halfvec USING ivfflat AS - OPERATOR 1 <-> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_l2_squared_distance(halfvec, halfvec), - FUNCTION 3 l2_distance(halfvec, halfvec), - FUNCTION 5 ivfflat_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_ip_ops - FOR TYPE halfvec USING ivfflat AS - OPERATOR 1 <#> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_negative_inner_product(halfvec, halfvec), - FUNCTION 3 halfvec_spherical_distance(halfvec, halfvec), - FUNCTION 4 l2_norm(halfvec), - FUNCTION 5 ivfflat_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_cosine_ops - FOR TYPE halfvec USING ivfflat AS - OPERATOR 1 <=> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_negative_inner_product(halfvec, halfvec), - FUNCTION 2 l2_norm(halfvec), - FUNCTION 3 halfvec_spherical_distance(halfvec, halfvec), - FUNCTION 4 l2_norm(halfvec), - FUNCTION 5 ivfflat_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_l2_ops - FOR TYPE halfvec USING hnsw AS - OPERATOR 1 <-> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_l2_squared_distance(halfvec, halfvec), - FUNCTION 3 hnsw_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_ip_ops - FOR TYPE halfvec USING hnsw AS - OPERATOR 1 <#> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_negative_inner_product(halfvec, halfvec), - FUNCTION 3 hnsw_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_cosine_ops - FOR TYPE halfvec USING hnsw AS - OPERATOR 1 <=> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 halfvec_negative_inner_product(halfvec, halfvec), - FUNCTION 2 l2_norm(halfvec), - FUNCTION 3 hnsw_halfvec_support(internal); - -CREATE OPERATOR CLASS halfvec_l1_ops - FOR TYPE halfvec USING hnsw AS - OPERATOR 1 <+> (halfvec, halfvec) FOR ORDER BY float_ops, - FUNCTION 1 l1_distance(halfvec, halfvec), - FUNCTION 3 hnsw_halfvec_support(internal); - -CREATE FUNCTION hamming_distance(bit, bit) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION jaccard_distance(bit, bit) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE OPERATOR <~> ( - LEFTARG = bit, RIGHTARG = bit, PROCEDURE = hamming_distance, - COMMUTATOR = '<~>' -); - -CREATE OPERATOR <%> ( - LEFTARG = bit, RIGHTARG = bit, PROCEDURE = jaccard_distance, - COMMUTATOR = '<%>' -); - -CREATE OPERATOR CLASS bit_hamming_ops - FOR TYPE bit USING ivfflat AS - OPERATOR 1 <~> (bit, bit) FOR ORDER BY float_ops, - FUNCTION 1 hamming_distance(bit, bit), - FUNCTION 3 hamming_distance(bit, bit), - FUNCTION 5 ivfflat_bit_support(internal); - -CREATE OPERATOR CLASS bit_hamming_ops - FOR TYPE bit USING hnsw AS - OPERATOR 1 <~> (bit, bit) FOR ORDER BY float_ops, - FUNCTION 1 hamming_distance(bit, bit), - FUNCTION 3 hnsw_bit_support(internal); - -CREATE OPERATOR CLASS bit_jaccard_ops - FOR TYPE bit USING hnsw AS - OPERATOR 1 <%> (bit, bit) FOR ORDER BY float_ops, - FUNCTION 1 jaccard_distance(bit, bit), - FUNCTION 3 hnsw_bit_support(internal); - -CREATE TYPE sparsevec; - -CREATE FUNCTION sparsevec_in(cstring, oid, integer) RETURNS sparsevec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_out(sparsevec) RETURNS cstring - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_typmod_in(cstring[]) RETURNS integer - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_recv(internal, oid, integer) RETURNS sparsevec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_send(sparsevec) RETURNS bytea - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE TYPE sparsevec ( - INPUT = sparsevec_in, - OUTPUT = sparsevec_out, - TYPMOD_IN = sparsevec_typmod_in, - RECEIVE = sparsevec_recv, - SEND = sparsevec_send, - STORAGE = external -); - -CREATE FUNCTION l2_distance(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME', 'sparsevec_l2_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION inner_product(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME', 'sparsevec_inner_product' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION cosine_distance(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME', 'sparsevec_cosine_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l1_distance(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME', 'sparsevec_l1_distance' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l2_norm(sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME', 'sparsevec_l2_norm' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION l2_normalize(sparsevec) RETURNS sparsevec - AS 'MODULE_PATHNAME', 'sparsevec_l2_normalize' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_lt(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_le(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_eq(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_ne(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_ge(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_gt(sparsevec, sparsevec) RETURNS bool - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_cmp(sparsevec, sparsevec) RETURNS int4 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_l2_squared_distance(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_negative_inner_product(sparsevec, sparsevec) RETURNS float8 - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec(sparsevec, integer, boolean) RETURNS sparsevec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION vector_to_sparsevec(vector, integer, boolean) RETURNS sparsevec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_to_vector(sparsevec, integer, boolean) RETURNS vector - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION halfvec_to_sparsevec(halfvec, integer, boolean) RETURNS sparsevec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE FUNCTION sparsevec_to_halfvec(sparsevec, integer, boolean) RETURNS halfvec - AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT ; - -CREATE CAST (sparsevec AS sparsevec) - WITH FUNCTION sparsevec(sparsevec, integer, boolean) AS IMPLICIT; - -CREATE CAST (sparsevec AS vector) - WITH FUNCTION sparsevec_to_vector(sparsevec, integer, boolean) AS ASSIGNMENT; - -CREATE CAST (vector AS sparsevec) - WITH FUNCTION vector_to_sparsevec(vector, integer, boolean) AS IMPLICIT; - -CREATE CAST (sparsevec AS halfvec) - WITH FUNCTION sparsevec_to_halfvec(sparsevec, integer, boolean) AS ASSIGNMENT; - -CREATE CAST (halfvec AS sparsevec) - WITH FUNCTION halfvec_to_sparsevec(halfvec, integer, boolean) AS IMPLICIT; - -CREATE OPERATOR <-> ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = l2_distance, - COMMUTATOR = '<->' -); - -CREATE OPERATOR <#> ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_negative_inner_product, - COMMUTATOR = '<#>' -); - -CREATE OPERATOR <=> ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = cosine_distance, - COMMUTATOR = '<=>' -); - -CREATE OPERATOR <+> ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = l1_distance, - COMMUTATOR = '<+>' -); - -CREATE OPERATOR < ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_lt, - COMMUTATOR = > , NEGATOR = >= , - RESTRICT = scalarltsel, JOIN = scalarltjoinsel -); - -CREATE OPERATOR <= ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_le, - COMMUTATOR = >= , NEGATOR = > , - RESTRICT = scalarlesel, JOIN = scalarlejoinsel -); - -CREATE OPERATOR = ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_eq, - COMMUTATOR = = , NEGATOR = <> , - RESTRICT = eqsel, JOIN = eqjoinsel -); - -CREATE OPERATOR <> ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_ne, - COMMUTATOR = <> , NEGATOR = = , - RESTRICT = eqsel, JOIN = eqjoinsel -); - -CREATE OPERATOR >= ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_ge, - COMMUTATOR = <= , NEGATOR = < , - RESTRICT = scalargesel, JOIN = scalargejoinsel -); - -CREATE OPERATOR > ( - LEFTARG = sparsevec, RIGHTARG = sparsevec, PROCEDURE = sparsevec_gt, - COMMUTATOR = < , NEGATOR = <= , - RESTRICT = scalargtsel, JOIN = scalargtjoinsel -); - -CREATE OPERATOR CLASS sparsevec_ops - DEFAULT FOR TYPE sparsevec USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 sparsevec_cmp(sparsevec, sparsevec); - -CREATE OPERATOR CLASS sparsevec_l2_ops - FOR TYPE sparsevec USING hnsw AS - OPERATOR 1 <-> (sparsevec, sparsevec) FOR ORDER BY float_ops, - FUNCTION 1 sparsevec_l2_squared_distance(sparsevec, sparsevec), - FUNCTION 3 hnsw_sparsevec_support(internal); - -CREATE OPERATOR CLASS sparsevec_ip_ops - FOR TYPE sparsevec USING hnsw AS - OPERATOR 1 <#> (sparsevec, sparsevec) FOR ORDER BY float_ops, - FUNCTION 1 sparsevec_negative_inner_product(sparsevec, sparsevec), - FUNCTION 3 hnsw_sparsevec_support(internal); - -CREATE OPERATOR CLASS sparsevec_cosine_ops - FOR TYPE sparsevec USING hnsw AS - OPERATOR 1 <=> (sparsevec, sparsevec) FOR ORDER BY float_ops, - FUNCTION 1 sparsevec_negative_inner_product(sparsevec, sparsevec), - FUNCTION 2 l2_norm(sparsevec), - FUNCTION 3 hnsw_sparsevec_support(internal); - -CREATE OPERATOR CLASS sparsevec_l1_ops - FOR TYPE sparsevec USING hnsw AS - OPERATOR 1 <+> (sparsevec, sparsevec) FOR ORDER BY float_ops, - FUNCTION 1 l1_distance(sparsevec, sparsevec), - FUNCTION 3 hnsw_sparsevec_support(internal); diff --git a/contrib/datavec/sql/datavec--0.7.0--0.7.1.sql b/contrib/datavec/sql/datavec--0.7.0--0.7.1.sql deleted file mode 100644 index 3baf960de53e1f6d664387d4ed369b39dee38f17..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.7.0--0.7.1.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.7.1'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec--0.7.1--0.7.2.sql b/contrib/datavec/sql/datavec--0.7.1--0.7.2.sql deleted file mode 100644 index d48be842a7fc18929638e241f6f405d81d335d8b..0000000000000000000000000000000000000000 --- a/contrib/datavec/sql/datavec--0.7.1--0.7.2.sql +++ /dev/null @@ -1,2 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "ALTER EXTENSION datavec UPDATE TO '0.7.2'" to load this file. \quit diff --git a/contrib/datavec/sql/datavec.sql b/contrib/datavec/sql/datavec.sql index 900e26b55e71196afdf672d6f6c6af6c4a530ec4..e079528dec224a17573fe2e49cd3d06c99534090 100644 --- a/contrib/datavec/sql/datavec.sql +++ b/contrib/datavec/sql/datavec.sql @@ -324,6 +324,9 @@ CREATE FUNCTION hnswgettuple(internal, internal) RETURNS boolean CREATE FUNCTION hnswendscan(internal) RETURNS void AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION hnswdelete(internal, internal, internal, internal, internal) RETURNS boolean + AS 'MODULE_PATHNAME' LANGUAGE C; + CREATE FUNCTION hnswhandler(internal) RETURNS index_am_handler AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/contrib/datavec/src/hnsw.cpp b/contrib/datavec/src/hnsw.cpp index e2875647bf0e8ba160168eb63a3494a604199bae..ce90ba0d3cd6f2620d7078aa5f86b638476e8dae 100644 --- a/contrib/datavec/src/hnsw.cpp +++ b/contrib/datavec/src/hnsw.cpp @@ -11,11 +11,6 @@ #include "utils/guc.h" #include "utils/selfuncs.h" -#if PG_VERSION_NUM < 150000 -#define MarkGUCPrefixReserved(x) EmitWarningsOnPlaceholders(x) -#endif - -int hnsw_ef_search; int hnsw_lock_tranche_id; static relopt_kind hnsw_relopt_kind; @@ -25,7 +20,7 @@ static relopt_kind hnsw_relopt_kind; void HnswInit(void) { - hnsw_relopt_kind = add_reloption_kind(); + hnsw_relopt_kind = RELOPT_KIND_DATAVEC; add_int_reloption(hnsw_relopt_kind, "m", "Max number of connections", HNSW_DEFAULT_M, HNSW_MIN_M, HNSW_MAX_M); add_int_reloption(hnsw_relopt_kind, "ef_construction", "Size of the dynamic candidate list for construction", @@ -35,12 +30,6 @@ HnswInit(void) add_int_reloption(hnsw_relopt_kind, "pq_ksub", "Number of centroids for each PQ subquantizer", HNSW_DEFAULT_PQ_KSUB, HNSW_MIN_PQ_KSUB, HNSW_MAX_PQ_KSUB); add_bool_reloption(hnsw_relopt_kind, "enable_pq", "Whether to enable PQ", HNSW_DEFAULT_ENABLE_PQ); - - DefineCustomIntVariable("hnsw.ef_search", "Sets the size of the dynamic candidate list for search", - "Valid range is 1..1000.", &hnsw_ef_search, HNSW_DEFAULT_EF_SEARCH, - HNSW_MIN_EF_SEARCH, HNSW_MAX_EF_SEARCH, PGC_USERSET, 0, NULL, NULL, NULL); - - MarkGUCPrefixReserved("hnsw"); } /* @@ -101,7 +90,8 @@ hnswoptions_internal(Datum reloptions, bool validate) {"enable_pq", RELOPT_TYPE_BOOL, offsetof(HnswOptions, enablePQ)}, {"pq_m", RELOPT_TYPE_INT, offsetof(HnswOptions, pqM)}, {"pq_ksub", RELOPT_TYPE_INT, offsetof(HnswOptions, pqKsub)}, - {"parallel_workers", RELOPT_TYPE_INT, offsetof(StdRdOptions, parallel_workers)} + {"parallel_workers", RELOPT_TYPE_INT, offsetof(StdRdOptions, parallel_workers)}, + {"storage_type", RELOPT_TYPE_STRING, offsetof(HnswOptions, storage_type)} }; #if PG_VERSION_NUM >= 130000 @@ -114,6 +104,9 @@ hnswoptions_internal(Datum reloptions, bool validate) int numoptions; HnswOptions *rdopts; + if (needInitialization) { + InitRelOptions(); + } options = parseRelOptions(reloptions, validate, hnsw_relopt_kind, &numoptions); rdopts = (HnswOptions *)allocateReloptStruct(sizeof(HnswOptions), options, numoptions); fillRelOptions((void *) rdopts, sizeof(HnswOptions), options, numoptions, @@ -141,60 +134,62 @@ PGDLLEXPORT PG_FUNCTION_INFO_V1(hnswhandler); Datum hnswhandler(PG_FUNCTION_ARGS) { - IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); + IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); - amroutine->amstrategies = 0; - amroutine->amsupport = 3; + amroutine->amstrategies = 0; + amroutine->amsupport = 3; #if PG_VERSION_NUM >= 130000 - amroutine->amoptsprocnum = 0; + amroutine->amoptsprocnum = 0; #endif - amroutine->amcanorder = false; - amroutine->amcanorderbyop = true; - amroutine->amcanbackward = false; /* can change direction mid-scan */ - amroutine->amcanunique = false; - amroutine->amcanmulticol = false; - amroutine->amoptionalkey = true; - amroutine->amsearcharray = false; - amroutine->amsearchnulls = false; - amroutine->amstorage = false; - amroutine->amclusterable = false; - amroutine->ampredlocks = false; - amroutine->amcanparallel = false; - amroutine->amcaninclude = false; + amroutine->amcanorder = false; + amroutine->amcanorderbyop = true; + amroutine->amcanbackward = false; /* can change direction mid-scan */ + amroutine->amcanunique = false; + amroutine->amcanmulticol = false; + amroutine->amoptionalkey = true; + amroutine->amsearcharray = false; + amroutine->amsearchnulls = false; + amroutine->amstorage = false; + amroutine->amclusterable = false; + amroutine->ampredlocks = false; + amroutine->amcanparallel = false; + amroutine->amcaninclude = false; #if PG_VERSION_NUM >= 130000 - amroutine->amusemaintenanceworkmem = false; /* not used during VACUUM */ - amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL; + amroutine->amusemaintenanceworkmem = false; /* not used during VACUUM */ + amroutine->amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL; #endif - amroutine->amkeytype = InvalidOid; - - /* Interface functions */ - errno_t rc; - rc = strcpy_s(amroutine->ambuildfuncname, NAMEDATALEN, "hnswbuild"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->ambuildemptyfuncname, NAMEDATALEN, "hnswbuildempty"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->aminsertfuncname, NAMEDATALEN, "hnswinsert"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->ambulkdeletefuncname, NAMEDATALEN, "hnswbulkdelete"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amvacuumcleanupfuncname, NAMEDATALEN, "hnswvacuumcleanup"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amcostestimatefuncname, NAMEDATALEN, "hnswcostestimate"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amoptionsfuncname, NAMEDATALEN, "hnswoptions"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amvalidatefuncname, NAMEDATALEN, "hnswvalidate"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->ambeginscanfuncname, NAMEDATALEN, "hnswbeginscan"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amrescanfuncname, NAMEDATALEN, "hnswrescan"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amgettuplefuncname, NAMEDATALEN, "hnswgettuple"); - securec_check(rc, "\0", "\0"); - rc = strcpy_s(amroutine->amendscanfuncname, NAMEDATALEN, "hnswendscan"); - securec_check(rc, "\0", "\0"); - - PG_RETURN_POINTER(amroutine); + amroutine->amkeytype = InvalidOid; + + /* Interface functions */ + errno_t rc = 0; + rc = strcpy_s(amroutine->ambuildfuncname, NAMEDATALEN, "hnswbuild"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->ambuildemptyfuncname, NAMEDATALEN, "hnswbuildempty"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->aminsertfuncname, NAMEDATALEN, "hnswinsert"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->ambulkdeletefuncname, NAMEDATALEN, "hnswbulkdelete"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amvacuumcleanupfuncname, NAMEDATALEN, "hnswvacuumcleanup"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amcostestimatefuncname, NAMEDATALEN, "hnswcostestimate"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amoptionsfuncname, NAMEDATALEN, "hnswoptions"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amvalidatefuncname, NAMEDATALEN, "hnswvalidate"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->ambeginscanfuncname, NAMEDATALEN, "hnswbeginscan"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amrescanfuncname, NAMEDATALEN, "hnswrescan"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amgettuplefuncname, NAMEDATALEN, "hnswgettuple"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amendscanfuncname, NAMEDATALEN, "hnswendscan"); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(amroutine->amdeletefuncname, NAMEDATALEN, "hnswdelete"); + securec_check(rc, "\0", "\0"); + + PG_RETURN_POINTER(amroutine); } PGDLLEXPORT PG_FUNCTION_INFO_V1(hnswbuild); @@ -348,3 +343,18 @@ hnswendscan(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } + +PGDLLEXPORT PG_FUNCTION_INFO_V1(hnswdelete); +Datum +hnswdelete(PG_FUNCTION_ARGS) +{ + Relation rel = (Relation)PG_GETARG_POINTER(0); + Datum *values = (Datum *)PG_GETARG_POINTER(1); + const bool* isnull = (const bool*)PG_GETARG_POINTER(2); + ItemPointer heapTCtid = (ItemPointer)PG_GETARG_POINTER(3); + bool isRollbackIndex = (bool)PG_GETARG_POINTER(4); + + bool result = hnswdelete_internal(rel, values, isnull, heapTCtid, isRollbackIndex); + + PG_RETURN_BOOL(result); +} \ No newline at end of file diff --git a/contrib/datavec/src/hnsw.h b/contrib/datavec/src/hnsw.h index 910b76e03630c93b51013ec7ad5e23ccbba18867..5b70fb07f5c5c82f22c4ee5c023df3d234071a98 100644 --- a/contrib/datavec/src/hnsw.h +++ b/contrib/datavec/src/hnsw.h @@ -8,6 +8,7 @@ #include "nodes/execnodes.h" #include "port.h" /* for random() */ #include "vector.h" +#include "vecindex.h" #define HNSW_MAX_DIM 2000 #define HNSW_MAX_NNZ 1000 @@ -58,8 +59,11 @@ #define HNSW_NEIGHBOR_TUPLE_TYPE 2 /* page types */ +#define HNSW_DEFAULT_PAGE_TYPE 0 #define HNSW_ELEMENT_PAGE_TYPE 1 #define HNSW_NEIGHBOR_PAGE_TYPE 2 +#define HNSW_USTORE_PAGE_TYPE 3 +#define HNSW_APPEND_META_PAGE_TYPE 4 /* Make graph robust against non-HOT updates */ #define HNSW_HEAPTIDS 10 @@ -83,6 +87,13 @@ #define HnswPageGetMeta(page) ((HnswMetaPageData *) PageGetContents(page)) #define HnswPageGetAppendMeta(page) ((HnswAppendMetaPageData *) PageGetContents(page)) +#define HnswDefaultMaxItemSize \ + MAXALIGN_DOWN((BLCKSZ - \ + MAXALIGN(SizeOfPageHeaderData + \ + sizeof(ItemIdData) + \ + sizeof(ItemPointerData)) - \ + MAXALIGN(sizeof(HnswPageOpaqueData)))) + #if PG_VERSION_NUM >= 150000 #define RandomDouble() pg_prng_double(&pg_global_prng_state) #define SeedRandom(seed) pg_prng_seed(&pg_global_prng_state, seed) @@ -115,13 +126,13 @@ new_list = (List *) palloc(sizeof(List)); \ new_list->type = list->type; \ new_list->length = len; \ - new_list->head = list_arr[0]; \ - new_list->tail = list_arr[len - 1]; \ + new_list->head = list_arr[len - 1]; \ + new_list->tail = list_arr[0]; \ \ - for (i = 0; i < len - 1; i++) \ - list_arr[i]->next = list_arr[i + 1]; \ + for (i = len - 1; i > 0; i--) \ + list_arr[i]->next = list_arr[i - 1]; \ \ - list_arr[len - 1]->next = NULL; \ + list_arr[0]->next = NULL; \ pfree(list_arr); \ list = new_list; \ } while (0) @@ -156,7 +167,6 @@ #define HnswPtrOffset(hp) relptr_offset((hp).relptr) /* Variables */ -extern int hnsw_ef_search; extern int hnsw_lock_tranche_id; typedef struct HnswElementData HnswElementData; @@ -277,6 +287,7 @@ typedef struct HnswOptions bool enablePQ; int pqM; /* number of subquantizer */ int pqKsub; /* number of centroids for each subquantizer */ + char* storage_type; /* table access method kind */ } HnswOptions; typedef struct HnswGraph @@ -478,6 +489,9 @@ typedef struct HnswScanOpaqueData FmgrInfo *procinfo; FmgrInfo *normprocinfo; Oid collation; + + /* used in ustore only */ + VectorScanData vs; } HnswScanOpaqueData; typedef HnswScanOpaqueData * HnswScanOpaque; @@ -518,28 +532,34 @@ FmgrInfo *HnswOptionalProcInfo(Relation index, uint16 procnum); Datum HnswNormValue(const HnswTypeInfo * typeInfo, Oid collation, Datum value); bool HnswCheckNorm(FmgrInfo *procinfo, Oid collation, Datum value); Buffer HnswNewBuffer(Relation index, ForkNumber forkNum); -void HnswInitPage(Buffer buf, Page page); +void HnswInitPage(Buffer buf, Page page, uint8 pageType); void HnswInit(void); -List *HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinfo, Oid collation, int m, bool inserting, HnswElement skipElement); +List *HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinfo, + Oid collation, int m, bool inserting, HnswElement skipElement, IndexScanDesc scan = NULL); HnswElement HnswGetEntryPoint(Relation index); void HnswGetMetaPageInfo(Relation index, int *m, HnswElement * entryPoint); void *HnswAlloc(HnswAllocator * allocator, Size size); HnswElement HnswInitElement(char *base, ItemPointer tid, int m, double ml, int maxLevel, HnswAllocator * alloc); HnswElement HnswInitElementFromBlock(BlockNumber blkno, OffsetNumber offno); void HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint, Relation index, FmgrInfo *procinfo, Oid collation, int m, int efConstruction, bool existing); -HnswCandidate *HnswEntryCandidate(char *base, HnswElement em, Datum q, Relation rel, FmgrInfo *procinfo, Oid collation, bool loadVec); +HnswCandidate *HnswEntryCandidate(char *base, HnswElement em, Datum q, Relation rel, FmgrInfo *procinfo, + Oid collation, bool loadVec, IndexScanDesc scan = NULL); void HnswUpdateMetaPage(Relation index, int updateEntry, HnswElement entryPoint, BlockNumber insertPage, ForkNumber forkNum, bool building); +void HnswUpdateAppendMetaPage(Relation index, int updateEntry, HnswElement entryPoint, BlockNumber eleInsertPage, + BlockNumber neiInsertPage, ForkNumber forkNum, bool building); void HnswSetNeighborTuple(char *base, HnswNeighborTuple ntup, HnswElement e, int m); void HnswAddHeapTid(HnswElement element, ItemPointer heaptid); void HnswInitNeighbors(char *base, HnswElement element, int m, HnswAllocator * alloc); bool HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, const bool *isnull, ItemPointer heap_tid, bool building); void HnswUpdateNeighborsOnDisk(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting, bool building); void HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHeaptids, bool loadVec); -void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance); +bool HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, + Oid collation, bool loadVec, float *maxDistance, IndexScanDesc scan = NULL); void HnswSetElementTuple(char *base, HnswElementTuple etup, HnswElement element); void HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation); void HnswLoadNeighbors(HnswElement element, Relation index, int m); const HnswTypeInfo *HnswGetTypeInfo(Relation index); +bool HnswDelete(Relation index, Datum* values, const bool* isnull, ItemPointer heapTCtid, bool isRollbackIndex); extern "C" { Datum hnswhandler(PG_FUNCTION_ARGS); @@ -555,6 +575,7 @@ extern "C" { Datum hnswrescan(PG_FUNCTION_ARGS); Datum hnswgettuple(PG_FUNCTION_ARGS); Datum hnswendscan(PG_FUNCTION_ARGS); + Datum hnswdelete(PG_FUNCTION_ARGS); Datum hnsw_halfvec_support(PG_FUNCTION_ARGS); Datum hnsw_bit_support(PG_FUNCTION_ARGS); Datum hnsw_sparsevec_support(PG_FUNCTION_ARGS); @@ -570,6 +591,8 @@ IndexScanDesc hnswbeginscan_internal(Relation index, int nkeys, int norderbys); void hnswrescan_internal(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys); bool hnswgettuple_internal(IndexScanDesc scan, ScanDirection dir); void hnswendscan_internal(IndexScanDesc scan); +bool hnswdelete_internal(Relation index, Datum* values, const bool* isnull, ItemPointer heapTCtid, + bool isRollbackIndex); static inline HnswNeighborArray * HnswGetNeighbors(char *base, HnswElement element, int lc) diff --git a/contrib/datavec/src/hnswbuild.cpp b/contrib/datavec/src/hnswbuild.cpp index d8fb9faac47d038d5f9498a16bccf7574532513d..e9530c57f81de5f10135c09019577df6837f98c4 100644 --- a/contrib/datavec/src/hnswbuild.cpp +++ b/contrib/datavec/src/hnswbuild.cpp @@ -82,32 +82,32 @@ static void CreateMetaPage(HnswBuildState * buildstate) { - Relation index = buildstate->index; - ForkNumber forkNum = buildstate->forkNum; - Buffer buf; - Page page; - HnswMetaPage metap; - - buf = HnswNewBuffer(index, forkNum); - page = BufferGetPage(buf); - HnswInitPage(buf, page); - - /* Set metapage data */ - metap = HnswPageGetMeta(page); - metap->magicNumber = HNSW_MAGIC_NUMBER; - metap->version = HNSW_VERSION; - metap->dimensions = buildstate->dimensions; - metap->m = buildstate->m; - metap->efConstruction = buildstate->efConstruction; - metap->entryBlkno = InvalidBlockNumber; - metap->entryOffno = InvalidOffsetNumber; - metap->entryLevel = -1; - metap->insertPage = InvalidBlockNumber; - ((PageHeader) page)->pd_lower = - ((char *) metap + sizeof(HnswMetaPageData)) - (char *) page; - - MarkBufferDirty(buf); - UnlockReleaseBuffer(buf); + Relation index = buildstate->index; + ForkNumber forkNum = buildstate->forkNum; + Buffer buf; + Page page; + HnswMetaPage metap; + + buf = HnswNewBuffer(index, forkNum); + page = BufferGetPage(buf); + HnswInitPage(buf, page, HNSW_USTORE_PAGE_TYPE); + + /* Set metapage data */ + metap = HnswPageGetMeta(page); + metap->magicNumber = HNSW_MAGIC_NUMBER; + metap->version = HNSW_VERSION; + metap->dimensions = buildstate->dimensions; + metap->m = buildstate->m; + metap->efConstruction = buildstate->efConstruction; + metap->entryBlkno = InvalidBlockNumber; + metap->entryOffno = InvalidOffsetNumber; + metap->entryLevel = -1; + metap->insertPage = InvalidBlockNumber; + ((PageHeader) page)->pd_lower = + ((char *) metap + sizeof(HnswMetaPageData)) - (char *) page; + + MarkBufferDirty(buf); + UnlockReleaseBuffer(buf); } /* @@ -125,7 +125,7 @@ CreateAppendMetaPage(HnswBuildState *buildstate) buf = HnswNewBuffer(index, forkNum); page = BufferGetPage(buf); - HnswInitPage(buf, page); + HnswInitPage(buf, page, HNSW_APPEND_META_PAGE_TYPE); /* Set append metapage data */ appMetap = HnswPageGetAppendMeta(page); @@ -175,26 +175,29 @@ CreateAppendMetaPage(HnswBuildState *buildstate) static void HnswBuildAppendPage(Relation index, Buffer *buf, Page *page, ForkNumber forkNum) { - /* Add a new page */ - Buffer newbuf = HnswNewBuffer(index, forkNum); - - /* Update previous page */ - HnswPageGetOpaque(*page)->nextblkno = BufferGetBlockNumber(newbuf); - - /* Commit */ - MarkBufferDirty(*buf); - UnlockReleaseBuffer(*buf); - - /* Can take a while, so ensure we can interrupt */ - /* Needs to be called when no buffer locks are held */ - LockBuffer(newbuf, BUFFER_LOCK_UNLOCK); - CHECK_FOR_INTERRUPTS(); - LockBuffer(newbuf, BUFFER_LOCK_EXCLUSIVE); - - /* Prepare new page */ - *buf = newbuf; - *page = BufferGetPage(*buf); - HnswInitPage(*buf, *page); + /* Add a new page */ + Buffer newbuf = HnswNewBuffer(index, forkNum); + + /* Update previous page */ + HnswPageGetOpaque(*page)->nextblkno = BufferGetBlockNumber(newbuf); + + /* Store page type */ + uint8 pageType = HnswPageGetOpaque(page)->pageType; + + /* Commit */ + MarkBufferDirty(*buf); + UnlockReleaseBuffer(*buf); + + /* Can take a while, so ensure we can interrupt */ + /* Needs to be called when no buffer locks are held */ + LockBuffer(newbuf, BUFFER_LOCK_UNLOCK); + CHECK_FOR_INTERRUPTS(); + LockBuffer(newbuf, BUFFER_LOCK_EXCLUSIVE); + + /* Prepare new page */ + *buf = newbuf; + *page = BufferGetPage(*buf); + HnswInitPage(*buf, *page, pageType); } /* @@ -203,99 +206,210 @@ HnswBuildAppendPage(Relation index, Buffer *buf, Page *page, ForkNumber forkNum) static void CreateGraphPages(HnswBuildState * buildstate) { - Relation index = buildstate->index; - ForkNumber forkNum = buildstate->forkNum; - Size maxSize; - HnswElementTuple etup; - HnswNeighborTuple ntup; - BlockNumber insertPage; - HnswElement entryPoint; - Buffer buf; - Page page; - HnswElementPtr iter = buildstate->graph->head; - char *base = buildstate->hnswarea; + Relation index = buildstate->index; + ForkNumber forkNum = buildstate->forkNum; + Size maxSize; + HnswElementTuple etup; + HnswNeighborTuple ntup; + BlockNumber insertPage; + HnswElement entryPoint; + Buffer buf; + Page page; + HnswElementPtr iter = buildstate->graph->head; + char *base = buildstate->hnswarea; + IndexTransInfo *idxXid; - /* Calculate sizes */ - maxSize = HNSW_MAX_SIZE; + /* Calculate sizes */ + maxSize = HNSW_MAX_SIZE; - /* Allocate once */ - etup = (HnswElementTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); - ntup = (HnswNeighborTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); + /* Allocate once */ + etup = (HnswElementTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); + ntup = (HnswNeighborTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); - /* Prepare first page */ - buf = HnswNewBuffer(index, forkNum); - page = BufferGetPage(buf); - HnswInitPage(buf, page); + /* Prepare first page */ + buf = HnswNewBuffer(index, forkNum); + page = BufferGetPage(buf); + HnswInitPage(buf, page, HNSW_USTORE_PAGE_TYPE); + + while (!HnswPtrIsNull(base, iter)) { + HnswElement element = (HnswElement)HnswPtrAccess(base, iter); + Size etupSize; + Size ntupSize; + Size combinedSize; + Pointer valuePtr = (Pointer)HnswPtrAccess(base, element->value); + + /* Update iterator */ + iter = element->next; + + /* Zero memory for each element */ + MemSet(etup, 0, HNSW_TUPLE_ALLOC_SIZE); + + /* Calculate sizes */ + etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(valuePtr)); + ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(element->level, buildstate->m); + combinedSize = etupSize + ntupSize + sizeof(ItemIdData); + + if (buildstate->isUStore) { + combinedSize += sizeof(IndexTransInfo); + } + + /* Initial size check */ + if (etupSize > HNSW_TUPLE_ALLOC_SIZE) { + elog(ERROR, "index tuple too large"); + } + + HnswSetElementTuple(base, etup, element); + + /* Keep element and neighbors on the same page if possible */ + if (PageGetFreeSpace(page) < etupSize || (combinedSize <= maxSize && PageGetFreeSpace(page) < combinedSize)) { + HnswBuildAppendPage(index, &buf, &page, forkNum); + } + + /* Calculate offsets */ + element->blkno = BufferGetBlockNumber(buf); + element->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); + if (combinedSize <= maxSize) { + element->neighborPage = element->blkno; + element->neighborOffno = OffsetNumberNext(element->offno); + } else { + element->neighborPage = element->blkno + 1; + element->neighborOffno = FirstOffsetNumber; + } + + ItemPointerSet(&etup->neighbortid, element->neighborPage, element->neighborOffno); + + if (buildstate->isUStore) { + ((PageHeader)page)->pd_upper -= sizeof(IndexTransInfo); + idxXid = (IndexTransInfo *)(((char *)page) + ((PageHeader)page)->pd_upper); + idxXid->xmin = FrozenTransactionId; + idxXid->xmax = InvalidTransactionId; + } + + /* Add element */ + if (PageAddItem(page, (Item)etup, etupSize, InvalidOffsetNumber, false, false) != element->offno) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + + /* Add new page if needed */ + if (PageGetFreeSpace(page) < ntupSize) { + HnswBuildAppendPage(index, &buf, &page, forkNum); + } + /* Add placeholder for neighbors */ + if (PageAddItem(page, (Item)ntup, ntupSize, InvalidOffsetNumber, false, false) != element->neighborOffno) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + } - while (!HnswPtrIsNull(base, iter)) - { - HnswElement element = (HnswElement)HnswPtrAccess(base, iter); - Size etupSize; - Size ntupSize; - Size combinedSize; - Pointer valuePtr = (Pointer)HnswPtrAccess(base, element->value); + insertPage = BufferGetBlockNumber(buf); - /* Update iterator */ - iter = element->next; + /* Commit */ + MarkBufferDirty(buf); + UnlockReleaseBuffer(buf); - /* Zero memory for each element */ - MemSet(etup, 0, HNSW_TUPLE_ALLOC_SIZE); + entryPoint = (HnswElement)HnswPtrAccess(base, buildstate->graph->entryPoint); + HnswUpdateMetaPage(index, HNSW_UPDATE_ENTRY_ALWAYS, entryPoint, insertPage, forkNum, true); - /* Calculate sizes */ - etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(valuePtr)); - ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(element->level, buildstate->m); - combinedSize = etupSize + ntupSize + sizeof(ItemIdData); + pfree(etup); + pfree(ntup); +} - /* Initial size check */ - if (etupSize > HNSW_TUPLE_ALLOC_SIZE) - elog(ERROR, "index tuple too large"); +/* + * Create element & neighbor pages + */ +static void +CreateElementNeighborPages(HnswBuildState * buildstate) +{ + Relation index = buildstate->index; + ForkNumber forkNum = buildstate->forkNum; + HnswElementTuple etup; + HnswNeighborTuple ntup; + BlockNumber elementInsertSlot; + BlockNumber neighborInsertSlot; + HnswElement entryPoint; + Buffer buf; + Page page; + Buffer nbuf; + Page npage; - HnswSetElementTuple(base, etup, element); + HnswElementPtr iter = buildstate->graph->head; + char *base = buildstate->hnswarea; - /* Keep element and neighbors on the same page if possible */ - if (PageGetFreeSpace(page) < etupSize || (combinedSize <= maxSize && PageGetFreeSpace(page) < combinedSize)) - HnswBuildAppendPage(index, &buf, &page, forkNum); + /* Allocate once */ + etup = (HnswElementTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); + ntup = (HnswNeighborTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); - /* Calculate offsets */ - element->blkno = BufferGetBlockNumber(buf); - element->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); - if (combinedSize <= maxSize) - { - element->neighborPage = element->blkno; - element->neighborOffno = OffsetNumberNext(element->offno); - } - else - { - element->neighborPage = element->blkno + 1; - element->neighborOffno = FirstOffsetNumber; - } + /* Prepare first page */ + buf = HnswNewBuffer(index, forkNum); + page = BufferGetPage(buf); + HnswInitPage(buf, page, HNSW_ELEMENT_PAGE_TYPE); - ItemPointerSet(&etup->neighbortid, element->neighborPage, element->neighborOffno); + nbuf = HnswNewBuffer(index, forkNum); + npage = BufferGetPage(nbuf); + HnswInitPage(nbuf, npage, HNSW_NEIGHBOR_PAGE_TYPE); - /* Add element */ - if (PageAddItem(page, (Item) etup, etupSize, InvalidOffsetNumber, false, false) != element->offno) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + while (!HnswPtrIsNull(base, iter)) { + HnswElement element = (HnswElement)HnswPtrAccess(base, iter); + Size etupSize; + Size ntupSize; + Pointer valuePtr = (Pointer)HnswPtrAccess(base, element->value); - /* Add new page if needed */ - if (PageGetFreeSpace(page) < ntupSize) - HnswBuildAppendPage(index, &buf, &page, forkNum); + /* Update iterator */ + iter = element->next; - /* Add placeholder for neighbors */ - if (PageAddItem(page, (Item) ntup, ntupSize, InvalidOffsetNumber, false, false) != element->neighborOffno) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); - } + /* Zero memory for each element */ + MemSet(etup, 0, HNSW_TUPLE_ALLOC_SIZE); - insertPage = BufferGetBlockNumber(buf); + /* Calculate sizes */ + etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(valuePtr)); + ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(element->level, buildstate->m); - /* Commit */ - MarkBufferDirty(buf); - UnlockReleaseBuffer(buf); + /* Initial size check */ + if (etupSize > HNSW_TUPLE_ALLOC_SIZE) + elog(ERROR, "index element tuple too large"); - entryPoint = (HnswElement)HnswPtrAccess(base, buildstate->graph->entryPoint); - HnswUpdateMetaPage(index, HNSW_UPDATE_ENTRY_ALWAYS, entryPoint, insertPage, forkNum, true); + HnswSetElementTuple(base, etup, element); - pfree(etup); - pfree(ntup); + /* Add new page if needed */ + if (PageGetFreeSpace(page) < etupSize) + HnswBuildAppendPage(index, &buf, &page, forkNum); + + if (PageGetFreeSpace(npage) < ntupSize) { + HnswBuildAppendPage(index, &nbuf, &npage, forkNum); + } + + /* Calculate offsets */ + element->blkno = BufferGetBlockNumber(buf); + element->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); + element->neighborPage = BufferGetBlockNumber(nbuf); + element->neighborOffno = OffsetNumberNext(PageGetMaxOffsetNumber(npage)); + + ItemPointerSet(&etup->neighbortid, element->neighborPage, element->neighborOffno); + + /* Add element */ + if (PageAddItem(page, (Item)etup, etupSize, InvalidOffsetNumber, false, false) != element->offno) + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + + /* Add neighbors */ + if (PageAddItem(npage, (Item)ntup, ntupSize, InvalidOffsetNumber, false, false) != element->neighborOffno) + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + + elementInsertSlot = BufferGetBlockNumber(buf); + neighborInsertSlot = BufferGetBlockNumber(nbuf); + + /* Commit */ + MarkBufferDirty(buf); + UnlockReleaseBuffer(buf); + + MarkBufferDirty(nbuf); + UnlockReleaseBuffer(nbuf); + + entryPoint = (HnswElement)HnswPtrAccess(base, buildstate->graph->entryPoint); + HnswUpdateAppendMetaPage(index, HNSW_UPDATE_ENTRY_ALWAYS, entryPoint, elementInsertSlot, neighborInsertSlot, + forkNum, true); + + pfree(etup); + pfree(ntup); } /* @@ -355,15 +469,20 @@ static void FlushPages(HnswBuildState * buildstate) { #ifdef HNSW_MEMORY - elog(INFO, "memory: %zu MB", buildstate->graph->memoryUsed / (1024 * 1024)); + elog(INFO, "memory: %zu MB", buildstate->graph->memoryUsed / (1024 * 1024)); #endif - CreateMetaPage(buildstate); - CreateGraphPages(buildstate); - WriteNeighborTuples(buildstate); + if (buildstate->isUStore) { + CreateMetaPage(buildstate); + CreateGraphPages(buildstate); + } else { + CreateAppendMetaPage(buildstate); + CreateElementNeighborPages(buildstate); + } + WriteNeighborTuples(buildstate); - buildstate->graph->flushed = true; - MemoryContextReset(buildstate->graphCtx); + buildstate->graph->flushed = true; + MemoryContextReset(buildstate->graphCtx); } /* @@ -793,7 +912,7 @@ InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, Index buildstate->centerTable = NULL; buildstate->pqcodeSize = 0; - buildstate->isUStore = RelationIsUstoreFormat(buildstate->heap); + buildstate->isUStore = buildstate->heap ? RelationIsUstoreFormat(buildstate->heap) : false; } /* @@ -970,42 +1089,45 @@ HnswBeginParallel(HnswBuildState * buildstate, int request) static void BuildGraph(HnswBuildState * buildstate, ForkNumber forkNum) { - int parallel_workers = 0; + int parallel_workers = 0; - /* Calculate parallel workers */ - if (buildstate->heap != NULL) - parallel_workers = PlanCreateIndexWorkers(buildstate->heap, buildstate->indexInfo); + /* Calculate parallel workers */ + if (buildstate->heap != NULL) { + parallel_workers = PlanCreateIndexWorkers(buildstate->heap, buildstate->indexInfo); + } - /* Attempt to launch parallel worker scan when required */ - if (parallel_workers > 0) - HnswBeginParallel(buildstate, parallel_workers); + /* Attempt to launch parallel worker scan when required */ + if (parallel_workers > 0) { + HnswBeginParallel(buildstate, parallel_workers); + } - /* Add tuples to graph */ - if (buildstate->heap != NULL) - { - if (!buildstate->hnswleader) { + /* Add tuples to graph */ + if (buildstate->heap != NULL) { + if (!buildstate->hnswleader) { serial_build: - buildstate->reltuples = IndexBuildHeapScan(buildstate->heap, buildstate->index, buildstate->indexInfo, - true, BuildCallback, (void *) buildstate, NULL); - } else { - int nruns; - buildstate->reltuples = ParallelHeapScan(buildstate, &nruns); - if (nruns == 0) { - /* failed to startup any bgworker, retry to do serial build */ - goto serial_build; - } - } - - buildstate->indtuples = buildstate->graph->indtuples; - } + buildstate->reltuples = tableam_index_build_scan(buildstate->heap, buildstate->index, buildstate->indexInfo, + true, BuildCallback, (void *) buildstate, NULL); + } else { + int nruns; + buildstate->reltuples = ParallelHeapScan(buildstate, &nruns); + if (nruns == 0) { + /* failed to startup any bgworker, retry to do serial build */ + goto serial_build; + } + } + + buildstate->indtuples = buildstate->graph->indtuples; + } - /* Flush pages */ - if (!buildstate->graph->flushed) - FlushPages(buildstate); + /* Flush pages */ + if (!buildstate->graph->flushed) { + FlushPages(buildstate); + } - /* End parallel build */ - if (buildstate->hnswleader) - HnswEndParallel(); + /* End parallel build */ + if (buildstate->hnswleader) { + HnswEndParallel(); + } } /* diff --git a/contrib/datavec/src/hnswdelete.cpp b/contrib/datavec/src/hnswdelete.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cc0bb43c7e766d533744ea378c4b021c78711b5 --- /dev/null +++ b/contrib/datavec/src/hnswdelete.cpp @@ -0,0 +1,199 @@ +#include "access/ubtree.h" +#include "hnsw.h" +#include "vecindex.h" + +bool HnswIsTIDEquals(ItemPointer p1, ItemPointer p2) +{ + int id; + bool equal = true; + for (id = 0; id < HNSW_HEAPTIDS; id++) { + if (ItemPointerIsValid(&p1[id]) && ItemPointerIsValid(&p2[id])) { + equal = ItemPointerEquals(&p1[id], &p2[id]); + } else if (!ItemPointerIsValid(&p1[id]) && !ItemPointerIsValid(&p2[id])) { + continue; + } else { + equal = false; + } + + if (!equal) { + break; + } + } + + return equal; +} + +bool HnswIsETUPEqual(HnswElementTuple etup1, HnswElementTuple etup2) +{ + if (etup1 == NULL || etup2 == NULL) { + return false; + } + Size len1 = MAXALIGN(VARSIZE_ANY(&etup1->data)); + Size len2 = MAXALIGN(VARSIZE_ANY(&etup2->data)); + if (len1 == 0 || len2 == 0 || len1 != len2) { + return false; + } + return memcmp(&etup1->data, &etup2->data, len1) == 0; +} + +OffsetNumber HnswFindDeleteLocation(Relation index, Buffer buf, HnswElementTuple etup) +{ + OffsetNumber off; + OffsetNumber maxOff; + Page page; + TransactionId xmin; + TransactionId xmax; + + page = BufferGetPage(buf); + maxOff = PageGetMaxOffsetNumber(page); + + if (RelationIsGlobalIndex(index)) { + elog(ERROR, "the GLOBAL partitioned index is not supported.\n"); + } + + for (off = FirstOffsetNumber; off < maxOff; off++) { + ItemId iid; + HnswElementTuple tup; + + iid = PageGetItemId(page, off); + if (!ItemIdIsDead(iid)) { + tup = (HnswElementTuple)PageGetItem(page, iid); + if (!HnswIsTIDEquals(etup->heaptids, tup->heaptids)) { + continue; + } + + if (!HnswIsETUPEqual(etup, tup)) { + continue; + } + + bool xminCommitted = false; + bool xmaxCommitted = false; + bool isDead = VecItupGetXminXmax(page, off, InvalidTransactionId, &xmin, &xmax, &xminCommitted, + &xmaxCommitted, RelationGetNamespace(index) == PG_TOAST_NAMESPACE); + if (!isDead && !TransactionIdIsValid(xmax)) { + return off; + } + } + } + return InvalidOffsetNumber; +} + +void HnswDeleteOnPage(Relation index, Buffer buf, OffsetNumber offset) +{ + ItemId iid; + IndexTransInfo* idxXid; + Page page; + HnswElementTuple etup; + + page = BufferGetPage(buf); + iid = PageGetItemId(page, offset); + etup = (HnswElementTuple)PageGetItem(page, iid); + idxXid = (IndexTransInfo*)VecIndexTupleGetXid(etup); + + idxXid->xmax = GetCurrentTransactionId(); + + MarkBufferDirty(buf); +} + +bool IsHnswEntryPoint(Relation index, BlockNumber blkno, OffsetNumber offno) +{ + Buffer buf; + Page page; + HnswMetaPage metap; + bool res = false; + + buf = ReadBuffer(index, HNSW_METAPAGE_BLKNO); + LockBuffer(buf, BUFFER_LOCK_SHARE); + page = BufferGetPage(buf); + metap = HnswPageGetMeta(page); + if (blkno == metap->entryBlkno && offno == metap->entryOffno) { + res = true; + } + UnlockReleaseBuffer(buf); + return res; +} + +bool HnswDeleteIndex(Relation index, HnswElementTuple etup) +{ + bool found = false; + BlockNumber blkno; + Buffer buf; + char *base = NULL; + Datum q; + List *ep; + List *w; + ListCell *cell; + int m; + HnswElement entryPoint; + FmgrInfo *procinfo; + Oid collation; + OffsetNumber offset; + Page page; + + blkno = InvalidBlockNumber; + procinfo = index_getprocinfo(index, 1, 1); + collation = index->rd_indcollation[0]; + q = (Datum)(&etup->data); + HnswGetMetaPageInfo(index, &m, &entryPoint); + ep = list_make1(HnswEntryCandidate(base, entryPoint, q, index, procinfo, collation, false, NULL)); + + for (int lc = entryPoint->level; lc >= 0; lc--) { + w = HnswSearchLayer(base, q, ep, 1, lc, index, procinfo, collation, m, false, NULL); + ep = w; + } + + foreach(cell, ep) { + HnswCandidate *hc = (HnswCandidate *) lfirst(cell); + HnswElement element = (HnswElement)HnswPtrAccess(base, hc->element); + blkno = element->blkno; + } + + while (BlockNumberIsValid(blkno)) { + buf = ReadBuffer(index, blkno); + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + offset = HnswFindDeleteLocation(index, buf, etup); + if (offset != InvalidOffsetNumber && ! IsHnswEntryPoint(index, blkno, offset)) { + HnswDeleteOnPage(index, buf, offset); + UnlockReleaseBuffer(buf); + found = true; + break; + } + + page = BufferGetPage(buf); + blkno = HnswPageGetOpaque(page)->nextblkno; + UnlockReleaseBuffer(buf); + } + return found; +} + +HnswElementTuple IndexFormHnswElementTuple(TupleDesc tupleDesc, Datum* values, const bool* isnull, + ItemPointer heapTCtid) +{ + Datum value; + HnswElementTuple etup; + Size etupSize; + + value = PointerGetDatum(PG_DETOAST_DATUM(values[0])); + + etup = (HnswElementTuple)palloc0(HNSW_TUPLE_ALLOC_SIZE); + etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(DatumGetPointer(value))); + + etup->heaptids[0] = *heapTCtid; + for (int i = 1; i < HNSW_HEAPTIDS; i++) { + ItemPointerSetInvalid(&etup->heaptids[i]); + } + + memcpy(&etup->data, DatumGetPointer(value), VARSIZE_ANY(DatumGetPointer(value))); + return etup; +} + +bool hnswdelete_internal(Relation index, Datum* values, const bool* isnull, ItemPointer heapTCtid, bool isRollbackIndex) +{ + bool found; + HnswElementTuple etup; + + etup = IndexFormHnswElementTuple(RelationGetDescr(index), values, isnull, heapTCtid); + found = HnswDeleteIndex(index, etup); + + return found; +} diff --git a/contrib/datavec/src/hnswinsert.cpp b/contrib/datavec/src/hnswinsert.cpp index e699bec2ac02eb9d6750ab8246ac37700be8f571..4e0ca2c0c9ed457301d458202e93cbb247c9504b 100644 --- a/contrib/datavec/src/hnswinsert.cpp +++ b/contrib/datavec/src/hnswinsert.cpp @@ -3,6 +3,7 @@ #include #include "access/generic_xlog.h" +#include "access/xact.h" #include "hnsw.h" #include "storage/buf/bufmgr.h" #include "storage/lmgr.h" @@ -32,6 +33,34 @@ GetInsertPage(Relation index) return insertPage; } +/* + * Get the insert append page + */ +static BlockNumber +GetInsertAppendPage(Relation index, uint8 pageType) +{ + Buffer buf; + Page page; + HnswAppendMetaPage metap; + BlockNumber insertPage; + + buf = ReadBuffer(index, HNSW_METAPAGE_BLKNO); + LockBuffer(buf, BUFFER_LOCK_SHARE); + page = BufferGetPage(buf); + metap = HnswPageGetAppendMeta(page); + + if (pageType == HNSW_ELEMENT_PAGE_TYPE) + insertPage = metap->elementInsertSlot; + else if (pageType == HNSW_NEIGHBOR_PAGE_TYPE) + insertPage = metap->neighborInsertSlot; + else + elog(ERROR, "failed to insert [%d] type page to \"%s\"", pageType, RelationGetRelationName(index)); + + UnlockReleaseBuffer(buf); + + return insertPage; +} + /* * Check for a free offset */ @@ -96,21 +125,21 @@ HnswFreeOffset(Relation index, Buffer buf, Page page, HnswElement element, Size static void HnswInsertAppendPage(Relation index, Buffer *nbuf, Page *npage, GenericXLogState *state, Page page, bool building) { - /* Add a new page */ - LockRelationForExtension(index, ExclusiveLock); - *nbuf = HnswNewBuffer(index, MAIN_FORKNUM); - UnlockRelationForExtension(index, ExclusiveLock); + /* Add a new page */ + LockRelationForExtension(index, ExclusiveLock); + *nbuf = HnswNewBuffer(index, MAIN_FORKNUM); + UnlockRelationForExtension(index, ExclusiveLock); - /* Init new page */ - if (building) - *npage = BufferGetPage(*nbuf); - else - *npage = GenericXLogRegisterBuffer(state, *nbuf, GENERIC_XLOG_FULL_IMAGE); + /* Init new page */ + if (building) + *npage = BufferGetPage(*nbuf); + else + *npage = GenericXLogRegisterBuffer(state, *nbuf, GENERIC_XLOG_FULL_IMAGE); - HnswInitPage(*nbuf, *npage); + HnswInitPage(*nbuf, *npage, HnswPageGetOpaque(page)->pageType); - /* Update previous buffer */ - HnswPageGetOpaque(page)->nextblkno = BufferGetBlockNumber(*nbuf); + /* Update previous buffer */ + HnswPageGetOpaque(page)->nextblkno = BufferGetBlockNumber(*nbuf); } /* @@ -119,201 +148,418 @@ HnswInsertAppendPage(Relation index, Buffer *nbuf, Page *npage, GenericXLogState static void AddElementOnDisk(Relation index, HnswElement e, int m, BlockNumber insertPage, BlockNumber *updatedInsertPage, bool building) { - Buffer buf; - Page page; - GenericXLogState *state; - Size etupSize; - Size ntupSize; - Size combinedSize; - Size maxSize; - Size minCombinedSize; - HnswElementTuple etup; - BlockNumber currentPage = insertPage; - HnswNeighborTuple ntup; - Buffer nbuf; - Page npage; - OffsetNumber freeOffno = InvalidOffsetNumber; - OffsetNumber freeNeighborOffno = InvalidOffsetNumber; - BlockNumber newInsertPage = InvalidBlockNumber; - char *base = NULL; - - /* Calculate sizes */ - etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(HnswPtrAccess(base, e->value))); - ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(e->level, m); - combinedSize = etupSize + ntupSize + sizeof(ItemIdData); - maxSize = HNSW_MAX_SIZE; - minCombinedSize = etupSize + HNSW_NEIGHBOR_TUPLE_SIZE(0, m) + sizeof(ItemIdData); - - /* Prepare element tuple */ - etup = (HnswElementTuple)palloc0(etupSize); - HnswSetElementTuple(base, etup, e); - - /* Prepare neighbor tuple */ - ntup = (HnswNeighborTuple)palloc0(ntupSize); - HnswSetNeighborTuple(base, ntup, e, m); - - /* Find a page (or two if needed) to insert the tuples */ - for (;;) - { - buf = ReadBuffer(index, currentPage); - LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); - - if (building) - { - state = NULL; - page = BufferGetPage(buf); - } - else - { - state = GenericXLogStart(index); - page = GenericXLogRegisterBuffer(state, buf, 0); - } - - /* Keep track of first page where element at level 0 can fit */ - if (!BlockNumberIsValid(newInsertPage) && PageGetFreeSpace(page) >= minCombinedSize) - newInsertPage = currentPage; - - /* First, try the fastest path */ - /* Space for both tuples on the current page */ - /* This can split existing tuples in rare cases */ - if (PageGetFreeSpace(page) >= combinedSize) - { - nbuf = buf; - npage = page; - break; - } - - /* Next, try space from a deleted element */ - if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, &newInsertPage)) - { - if (nbuf != buf) - { - if (building) - npage = BufferGetPage(nbuf); - else - npage = GenericXLogRegisterBuffer(state, nbuf, 0); - } - - break; - } - - /* Finally, try space for element only if last page */ - /* Skip if both tuples can fit on the same page */ - if (combinedSize > maxSize && PageGetFreeSpace(page) >= etupSize && !BlockNumberIsValid(HnswPageGetOpaque(page)->nextblkno)) - { - HnswInsertAppendPage(index, &nbuf, &npage, state, page, building); - break; - } - - currentPage = HnswPageGetOpaque(page)->nextblkno; - - if (BlockNumberIsValid(currentPage)) - { - /* Move to next page */ - if (!building) - GenericXLogAbort(state); - UnlockReleaseBuffer(buf); - } - else - { - Buffer newbuf; - Page newpage; - - HnswInsertAppendPage(index, &newbuf, &newpage, state, page, building); - - /* Commit */ - if (building) - MarkBufferDirty(buf); - else - GenericXLogFinish(state); - - /* Unlock previous buffer */ - UnlockReleaseBuffer(buf); - - /* Prepare new buffer */ - buf = newbuf; - if (building) - { - state = NULL; - page = BufferGetPage(buf); - } - else - { - state = GenericXLogStart(index); - page = GenericXLogRegisterBuffer(state, buf, 0); - } - - /* Create new page for neighbors if needed */ - if (PageGetFreeSpace(page) < combinedSize) - HnswInsertAppendPage(index, &nbuf, &npage, state, page, building); - else - { - nbuf = buf; - npage = page; - } - - break; - } - } - - e->blkno = BufferGetBlockNumber(buf); - e->neighborPage = BufferGetBlockNumber(nbuf); - - /* Added tuple to new page if newInsertPage is not set */ - /* So can set to neighbor page instead of element page */ - if (!BlockNumberIsValid(newInsertPage)) - newInsertPage = e->neighborPage; - - if (OffsetNumberIsValid(freeOffno)) - { - e->offno = freeOffno; - e->neighborOffno = freeNeighborOffno; - } - else - { - e->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); - if (nbuf == buf) - e->neighborOffno = OffsetNumberNext(e->offno); - else - e->neighborOffno = FirstOffsetNumber; - } - - ItemPointerSet(&etup->neighbortid, e->neighborPage, e->neighborOffno); - - /* Add element and neighbors */ - if (OffsetNumberIsValid(freeOffno)) - { - if (!page_index_tuple_overwrite(page, e->offno, (Item) etup, etupSize)) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); - - if (!page_index_tuple_overwrite(npage, e->neighborOffno, (Item) ntup, ntupSize)) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); - } - else - { - if (PageAddItem(page, (Item) etup, etupSize, InvalidOffsetNumber, false, false) != e->offno) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); - - if (PageAddItem(npage, (Item) ntup, ntupSize, InvalidOffsetNumber, false, false) != e->neighborOffno) - elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); - } - - /* Commit */ - if (building) - { - MarkBufferDirty(buf); - if (nbuf != buf) - MarkBufferDirty(nbuf); - } - else - GenericXLogFinish(state); - UnlockReleaseBuffer(buf); - if (nbuf != buf) - UnlockReleaseBuffer(nbuf); + Buffer buf; + Page page; + GenericXLogState *state; + Size etupSize; + Size ntupSize; + Size combinedSize; + Size maxSize; + Size minCombinedSize; + HnswElementTuple etup; + BlockNumber currentPage = insertPage; + HnswNeighborTuple ntup; + Buffer nbuf; + Page npage; + OffsetNumber freeOffno = InvalidOffsetNumber; + OffsetNumber freeNeighborOffno = InvalidOffsetNumber; + BlockNumber newInsertPage = InvalidBlockNumber; + char *base = NULL; + bool isUStore; + IndexTransInfo* idxXid; + + /* Calculate sizes */ + etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(HnswPtrAccess(base, e->value))); + ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(e->level, m); + combinedSize = etupSize + ntupSize + sizeof(ItemIdData); + maxSize = HNSW_MAX_SIZE; + minCombinedSize = etupSize + HNSW_NEIGHBOR_TUPLE_SIZE(0, m) + sizeof(ItemIdData); + + /* Prepare element tuple */ + etup = (HnswElementTuple)palloc0(etupSize); + HnswSetElementTuple(base, etup, e); + + /* Prepare neighbor tuple */ + ntup = (HnswNeighborTuple)palloc0(ntupSize); + HnswSetNeighborTuple(base, ntup, e, m); + + /* Find a page (or two if needed) to insert the tuples */ + for (;;) { + buf = ReadBuffer(index, currentPage); + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + + if (building) { + state = NULL; + page = BufferGetPage(buf); + } else { + state = GenericXLogStart(index); + page = GenericXLogRegisterBuffer(state, buf, 0); + } + + isUStore = HnswPageGetOpaque(page)->pageType == HNSW_USTORE_PAGE_TYPE; + /* Keep track of first page where element at level 0 can fit */ + if (!BlockNumberIsValid(newInsertPage) && PageGetFreeSpace(page) >= minCombinedSize) { + newInsertPage = currentPage; + } + + /* First, try the fastest path */ + /* Space for both tuples on the current page */ + /* This can split existing tuples in rare cases */ + if (PageGetFreeSpace(page) >= combinedSize) { + nbuf = buf; + npage = page; + break; + } + + /* Next, try space from a deleted element */ + if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, + &freeNeighborOffno, &newInsertPage)) { + if (nbuf != buf) { + if (building) { + npage = BufferGetPage(nbuf); + } else { + npage = GenericXLogRegisterBuffer(state, nbuf, 0); + } + } + + break; + } + + /* Finally, try space for element only if last page */ + /* Skip if both tuples can fit on the same page */ + if (combinedSize > maxSize && PageGetFreeSpace(page) >= etupSize && + !BlockNumberIsValid(HnswPageGetOpaque(page)->nextblkno)) { + HnswInsertAppendPage(index, &nbuf, &npage, state, page, building); + break; + } + + currentPage = HnswPageGetOpaque(page)->nextblkno; + + if (BlockNumberIsValid(currentPage)) { + /* Move to next page */ + if (!building) + GenericXLogAbort(state); + UnlockReleaseBuffer(buf); + } else { + Buffer newbuf; + Page newpage; + + HnswInsertAppendPage(index, &newbuf, &newpage, state, page, building); + + /* Commit */ + if (building) { + MarkBufferDirty(buf); + } else { + GenericXLogFinish(state); + } + + /* Unlock previous buffer */ + UnlockReleaseBuffer(buf); + + /* Prepare new buffer */ + buf = newbuf; + if (building) { + state = NULL; + page = BufferGetPage(buf); + } else { + state = GenericXLogStart(index); + page = GenericXLogRegisterBuffer(state, buf, 0); + } + + /* Create new page for neighbors if needed */ + if (PageGetFreeSpace(page) < combinedSize) { + HnswInsertAppendPage(index, &nbuf, &npage, state, page, building); + } else { + nbuf = buf; + npage = page; + } + + break; + } + } + + e->blkno = BufferGetBlockNumber(buf); + e->neighborPage = BufferGetBlockNumber(nbuf); + + /* Added tuple to new page if newInsertPage is not set */ + /* So can set to neighbor page instead of element page */ + if (!BlockNumberIsValid(newInsertPage)) { + newInsertPage = e->neighborPage; + } + + if (OffsetNumberIsValid(freeOffno)) { + e->offno = freeOffno; + e->neighborOffno = freeNeighborOffno; + } else { + e->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); + if (nbuf == buf) { + e->neighborOffno = OffsetNumberNext(e->offno); + } else { + e->neighborOffno = FirstOffsetNumber; + } + } + + ItemPointerSet(&etup->neighbortid, e->neighborPage, e->neighborOffno); + + /* Add element and neighbors */ + if (OffsetNumberIsValid(freeOffno)) { + if (isUStore) { + ItemId item_id = PageGetItemId(page, e->offno); + Size aligned_size = MAXALIGN(ItemIdGetLength(item_id)); + unsigned offset = ItemIdGetOffset(item_id); + idxXid = (IndexTransInfo*)((char*)page + offset + aligned_size); + idxXid->xmin = GetCurrentTransactionId(); + idxXid->xmax = InvalidTransactionId; + } + if (!page_index_tuple_overwrite(page, e->offno, (Item) etup, etupSize)) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + + if (!page_index_tuple_overwrite(npage, e->neighborOffno, (Item) ntup, ntupSize)) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + } else { + if (isUStore) { + ((PageHeader)page)->pd_upper -= sizeof(IndexTransInfo); + idxXid = (IndexTransInfo*)(((char*)page) + ((PageHeader)page)->pd_upper); + idxXid->xmin = GetCurrentTransactionId(); + idxXid->xmax = InvalidTransactionId; + } + if (PageAddItem(page, (Item) etup, etupSize, InvalidOffsetNumber, false, false) != e->offno) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + + if (PageAddItem(npage, (Item) ntup, ntupSize, InvalidOffsetNumber, false, false) != e->neighborOffno) { + elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index)); + } + } + + /* Commit */ + if (building) { + MarkBufferDirty(buf); + if (nbuf != buf) + MarkBufferDirty(nbuf); + } else { + GenericXLogFinish(state); + } + UnlockReleaseBuffer(buf); + if (nbuf != buf) + UnlockReleaseBuffer(nbuf); + + /* Update the insert page */ + if (BlockNumberIsValid(newInsertPage) && newInsertPage != insertPage) + *updatedInsertPage = newInsertPage; +} - /* Update the insert page */ - if (BlockNumberIsValid(newInsertPage) && newInsertPage != insertPage) - *updatedInsertPage = newInsertPage; +static void +AddAppendElementOnDisk(Relation index, HnswElement e, int m, BlockNumber insertElementPage, + BlockNumber insertNeighborPage, BlockNumber *updatedInsertElementPage, + BlockNumber *updatedInsertNeighborPage, bool building) +{ + Buffer buf; + Page page; + GenericXLogState *state; + Size etupSize; + Size ntupSize; + HnswElementTuple etup; + BlockNumber currentElementPage = insertElementPage; + HnswNeighborTuple ntup; + BlockNumber currentNeighborPage = insertNeighborPage; + Buffer nbuf; + Page npage; + + OffsetNumber freeOffno = InvalidOffsetNumber; + OffsetNumber freeNeighborOffno = InvalidOffsetNumber; + BlockNumber newInsertElementPage = InvalidBlockNumber; + BlockNumber newInsertNeighborPage = InvalidBlockNumber; + char *base = NULL; + + /* Calculate sizes */ + etupSize = HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(HnswPtrAccess(base, e->value))); + ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(e->level, m); + + /* Prepare element tuple */ + etup = (HnswElementTuple)palloc0(etupSize); + HnswSetElementTuple(base, etup, e); + + /* Prepare neighbor tuple */ + ntup = (HnswNeighborTuple)palloc0(ntupSize); + HnswSetNeighborTuple(base, ntup, e, m); + + /* Find a page to insert the element tuple */ + for (;;) { + buf = ReadBuffer(index, currentElementPage); + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + + if (building) { + state = NULL; + page = BufferGetPage(buf); + } else { + state = GenericXLogStart(index); + page = GenericXLogRegisterBuffer(state, buf, 0); + } + + if (!BlockNumberIsValid(newInsertElementPage) && PageGetFreeSpace(page) >= etupSize) + newInsertElementPage = currentElementPage; + + /* First, try the fastest path */ + /* Space for element tuple on the current page */ + if (PageGetFreeSpace(page) >= etupSize) { + break; + } + + /* Next, try space from a deleted element */ + if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, + &newInsertElementPage)) { + if (building) + npage = BufferGetPage(nbuf); + else + npage = GenericXLogRegisterBuffer(state, nbuf, 0); + + break; + } + + currentElementPage = HnswPageGetOpaque(page)->nextblkno; + if (BlockNumberIsValid(currentElementPage)) { + /* Move to next page */ + if (!building) + GenericXLogAbort(state); + UnlockReleaseBuffer(buf); + } else { + Buffer newbuf; + Page newpage; + + HnswInsertAppendPage(index, &newbuf, &newpage, state, page, building); + + /* Commit */ + if (building) + MarkBufferDirty(buf); + else + GenericXLogFinish(state); + + /* Unlock previous buffer */ + UnlockReleaseBuffer(buf); + + /* Prepare new buffer */ + buf = newbuf; + if (building) { + state = NULL; + page = BufferGetPage(buf); + } else { + state = GenericXLogStart(index); + page = GenericXLogRegisterBuffer(state, buf, 0); + } + + break; + } + } + + /* find a page to insert the neighbor tuple */ + for (;;) { + /* found offetno to overwrite deleted neighbor tuple */ + if (OffsetNumberIsValid(freeOffno)) { + break; + } + + nbuf = ReadBuffer(index, currentNeighborPage); + LockBuffer(nbuf, BUFFER_LOCK_EXCLUSIVE); + + if (building) { + state = NULL; + npage = BufferGetPage(nbuf); + } else { + npage = GenericXLogRegisterBuffer(state, nbuf, 0); + } + + /* Keep track of first page where element at level 0 can fit */ + if (!BlockNumberIsValid(newInsertNeighborPage) && PageGetFreeSpace(npage) >= ntupSize) + newInsertNeighborPage = currentNeighborPage; + + /* First, try the fastest path */ + /* Space for neighbor tuple on the current page */ + if (PageGetFreeSpace(npage) >= ntupSize) { + break; + } + + currentNeighborPage = HnswPageGetOpaque(npage)->nextblkno; + if (BlockNumberIsValid(currentNeighborPage)) { + /* Move to next page */ + if (!building) + GenericXLogAbort(state); + UnlockReleaseBuffer(nbuf); + } else { + Buffer newbuf; + Page newpage; + + HnswInsertAppendPage(index, &newbuf, &newpage, state, npage, building); + + /* Commit */ + if (building) + MarkBufferDirty(nbuf); + else + GenericXLogFinish(state); + + /* Unlock previous buffer */ + UnlockReleaseBuffer(nbuf); + + /* Prepare new buffer */ + nbuf = newbuf; + if (building) { + state = NULL; + npage = BufferGetPage(nbuf); + } else { + state = GenericXLogStart(index); + npage = GenericXLogRegisterBuffer(state, nbuf, 0); + } + break; + } + } + + e->blkno = BufferGetBlockNumber(buf); + e->neighborPage = BufferGetBlockNumber(nbuf); + + if (OffsetNumberIsValid(freeOffno)) { + e->offno = freeOffno; + e->neighborOffno = freeNeighborOffno; + } else { + e->offno = OffsetNumberNext(PageGetMaxOffsetNumber(page)); + e->neighborOffno = OffsetNumberNext(PageGetMaxOffsetNumber(npage)); + } + + ItemPointerSet(&etup->neighbortid, e->neighborPage, e->neighborOffno); + + /* Add element and neighbors */ + if (OffsetNumberIsValid(freeOffno)) { + if (!page_index_tuple_overwrite(page, e->offno, (Item)etup, etupSize)) + elog(ERROR, "failed to add element index item to \"%s\"", RelationGetRelationName(index)); + + if (!page_index_tuple_overwrite(npage, e->neighborOffno, (Item)ntup, ntupSize)) + elog(ERROR, "failed to add neighbor index item to \"%s\"", RelationGetRelationName(index)); + } else { + if (PageAddItem(page, (Item)etup, etupSize, InvalidOffsetNumber, false, false) != e->offno) + elog(ERROR, "failed to add element index item to \"%s\"", RelationGetRelationName(index)); + + if (PageAddItem(npage, (Item)ntup, ntupSize, InvalidOffsetNumber, false, false) != e->neighborOffno) + elog(ERROR, "failed to add neighbor index item to \"%s\"", RelationGetRelationName(index)); + } + + /* Commit */ + if (building) { + MarkBufferDirty(buf); + MarkBufferDirty(nbuf); + } else { + GenericXLogFinish(state); + } + + UnlockReleaseBuffer(buf); + UnlockReleaseBuffer(nbuf); + + /* Update the insert page */ + if (BlockNumberIsValid(newInsertElementPage) && newInsertElementPage != insertElementPage) + *updatedInsertElementPage = newInsertElementPage; + + if (BlockNumberIsValid(newInsertNeighborPage) && newInsertNeighborPage != insertNeighborPage) + *updatedInsertNeighborPage = newInsertNeighborPage; } /* @@ -529,25 +775,58 @@ FindDuplicateOnDisk(Relation index, HnswElement element, bool building) static void UpdateGraphOnDisk(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement element, int m, int efConstruction, HnswElement entryPoint, bool building) { - BlockNumber newInsertPage = InvalidBlockNumber; - - /* Look for duplicate */ - if (FindDuplicateOnDisk(index, element, building)) - return; - - /* Add element */ - AddElementOnDisk(index, element, m, GetInsertPage(index), &newInsertPage, building); - - /* Update insert page if needed */ - if (BlockNumberIsValid(newInsertPage)) - HnswUpdateMetaPage(index, 0, NULL, newInsertPage, MAIN_FORKNUM, building); - - /* Update neighbors */ - HnswUpdateNeighborsOnDisk(index, procinfo, collation, element, m, false, building); - - /* Update entry point if needed */ - if (entryPoint == NULL || element->level > entryPoint->level) - HnswUpdateMetaPage(index, HNSW_UPDATE_ENTRY_GREATER, element, InvalidBlockNumber, MAIN_FORKNUM, building); + BlockNumber newInsertPage = InvalidBlockNumber; + BlockNumber newInsertNeighborPage = InvalidBlockNumber; + + /* Look for duplicate */ + if (FindDuplicateOnDisk(index, element, building)) { + return; + } + + Buffer buf; + Page page; + buf = ReadBuffer(index, HNSW_METAPAGE_BLKNO); + LockBuffer(buf, BUFFER_LOCK_SHARE); + page = BufferGetPage(buf); + uint8 pageType = HnswPageGetOpaque(page)->pageType; + UnlockReleaseBuffer(buf); + + /* Add element */ + if (pageType == HNSW_USTORE_PAGE_TYPE) { + AddElementOnDisk(index, element, m, GetInsertPage(index), &newInsertPage, building); + + /* Update insert page if needed */ + if (BlockNumberIsValid(newInsertPage)) + HnswUpdateMetaPage(index, 0, NULL, newInsertPage, MAIN_FORKNUM, building); + + /* Update neighbors */ + HnswUpdateNeighborsOnDisk(index, procinfo, collation, element, m, false, building); + + /* Update entry point if needed */ + if (entryPoint == NULL || element->level > entryPoint->level) + HnswUpdateMetaPage(index, HNSW_UPDATE_ENTRY_GREATER, element, InvalidBlockNumber, MAIN_FORKNUM, building); + } else if (pageType == HNSW_APPEND_META_PAGE_TYPE) { + AddAppendElementOnDisk(index, element, m, GetInsertAppendPage(index, HNSW_ELEMENT_PAGE_TYPE), + GetInsertAppendPage(index, HNSW_NEIGHBOR_PAGE_TYPE), &newInsertPage, + &newInsertNeighborPage, building); + + if (BlockNumberIsValid(newInsertPage)) + HnswUpdateAppendMetaPage(index, 0, NULL, newInsertPage, InvalidBlockNumber, MAIN_FORKNUM, building); + + if (BlockNumberIsValid(newInsertNeighborPage)) + HnswUpdateAppendMetaPage(index, 0, NULL, InvalidBlockNumber, newInsertNeighborPage, MAIN_FORKNUM, building); + + /* Update neighbors */ + HnswUpdateNeighborsOnDisk(index, procinfo, collation, element, m, false, building); + + /* Update entry point if needed */ + if (entryPoint == NULL || element->level > entryPoint->level) { + HnswUpdateAppendMetaPage(index, HNSW_UPDATE_ENTRY_GREATER, element, InvalidBlockNumber, InvalidBlockNumber, + MAIN_FORKNUM, building); + } + } else { + elog(ERROR, "failed to insert [%d] type meta page to \"%s\"", pageType, RelationGetRelationName(index)); + } } /* diff --git a/contrib/datavec/src/hnswscan.cpp b/contrib/datavec/src/hnswscan.cpp index 992f56aba12e0bc307eb7e008c320f0dadf84057..c05b6f2a6fadfc8f4a481724d5c477b86dee304a 100644 --- a/contrib/datavec/src/hnswscan.cpp +++ b/contrib/datavec/src/hnswscan.cpp @@ -13,31 +13,31 @@ static List * GetScanItems(IndexScanDesc scan, Datum q) { - HnswScanOpaque so = (HnswScanOpaque) scan->opaque; - Relation index = scan->indexRelation; - FmgrInfo *procinfo = so->procinfo; - Oid collation = so->collation; - List *ep; - List *w; - int m; - HnswElement entryPoint; - char *base = NULL; - - /* Get m and entry point */ - HnswGetMetaPageInfo(index, &m, &entryPoint); - - if (entryPoint == NULL) - return NIL; - - ep = list_make1(HnswEntryCandidate(base, entryPoint, q, index, procinfo, collation, false)); - - for (int lc = entryPoint->level; lc >= 1; lc--) - { - w = HnswSearchLayer(base, q, ep, 1, lc, index, procinfo, collation, m, false, NULL); - ep = w; - } - - return HnswSearchLayer(base, q, ep, hnsw_ef_search, 0, index, procinfo, collation, m, false, NULL); + HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + Relation index = scan->indexRelation; + FmgrInfo *procinfo = so->procinfo; + Oid collation = so->collation; + List *ep; + List *w; + int m; + HnswElement entryPoint; + char *base = NULL; + + /* Get m and entry point */ + HnswGetMetaPageInfo(index, &m, &entryPoint); + + if (entryPoint == NULL) + return NIL; + + ep = list_make1(HnswEntryCandidate(base, entryPoint, q, index, procinfo, collation, false, scan)); + + for (int lc = entryPoint->level; lc >= 1; lc--) { + w = HnswSearchLayer(base, q, ep, 1, lc, index, procinfo, collation, m, false, NULL, scan); + ep = w; + } + + int hnsw_ef_search = get_session_context()->hnsw_ef_search; + return HnswSearchLayer(base, q, ep, hnsw_ef_search, 0, index, procinfo, collation, m, false, NULL, scan); } /* @@ -73,26 +73,30 @@ GetScanValue(IndexScanDesc scan) IndexScanDesc hnswbeginscan_internal(Relation index, int nkeys, int norderbys) { - IndexScanDesc scan; - HnswScanOpaque so; + IndexScanDesc scan; + HnswScanOpaque so; + + scan = RelationGetIndexScan(index, nkeys, norderbys); - scan = RelationGetIndexScan(index, nkeys, norderbys); + so = (HnswScanOpaque) palloc(sizeof(HnswScanOpaqueData)); + so->typeInfo = HnswGetTypeInfo(index); + so->first = true; + so->tmpCtx = AllocSetContextCreate(CurrentMemoryContext, + "Hnsw scan temporary context", + ALLOCSET_DEFAULT_SIZES); - so = (HnswScanOpaque) palloc(sizeof(HnswScanOpaqueData)); - so->typeInfo = HnswGetTypeInfo(index); - so->first = true; - so->tmpCtx = AllocSetContextCreate(CurrentMemoryContext, - "Hnsw scan temporary context", - ALLOCSET_DEFAULT_SIZES); + so->vs.buf = InvalidBuffer; + so->vs.lastSelfModifiedItup = NULL; + so->vs.lastSelfModifiedItupBufferSize = 0; - /* Set support functions */ - so->procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC); - so->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC); - so->collation = index->rd_indcollation[0]; + /* Set support functions */ + so->procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC); + so->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC); + so->collation = index->rd_indcollation[0]; - scan->opaque = so; + scan->opaque = so; - return scan; + return scan; } /* @@ -101,16 +105,20 @@ hnswbeginscan_internal(Relation index, int nkeys, int norderbys) void hnswrescan_internal(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys) { - HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + + if (so->vs.lastSelfModifiedItup) { + IndexTupleSetSize(((IndexTuple)(so->vs.lastSelfModifiedItup)), 0); /* clear */ + } - so->first = true; - MemoryContextReset(so->tmpCtx); + so->first = true; + MemoryContextReset(so->tmpCtx); - if (keys && scan->numberOfKeys > 0) - memmove(scan->keyData, keys, scan->numberOfKeys * sizeof(ScanKeyData)); + if (keys && scan->numberOfKeys > 0) + memmove(scan->keyData, keys, scan->numberOfKeys * sizeof(ScanKeyData)); - if (orderbys && scan->numberOfOrderBys > 0) - memmove(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData)); + if (orderbys && scan->numberOfOrderBys > 0) + memmove(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData)); } /* @@ -119,77 +127,74 @@ hnswrescan_internal(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderby bool hnswgettuple_internal(IndexScanDesc scan, ScanDirection dir) { - HnswScanOpaque so = (HnswScanOpaque) scan->opaque; - MemoryContext oldCtx = MemoryContextSwitchTo(so->tmpCtx); + HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + MemoryContext oldCtx = MemoryContextSwitchTo(so->tmpCtx); - /* - * Index can be used to scan backward, but Postgres doesn't support - * backward scan on operators - */ - Assert(ScanDirectionIsForward(dir)); + /* + * Index can be used to scan backward, but Postgres doesn't support + * backward scan on operators + */ + Assert(ScanDirectionIsForward(dir)); - if (so->first) - { - Datum value; + if (so->first) { + Datum value; - /* Count index scan for stats */ - pgstat_count_index_scan(scan->indexRelation); + /* Count index scan for stats */ + pgstat_count_index_scan(scan->indexRelation); - /* Safety check */ - if (scan->orderByData == NULL) - elog(ERROR, "cannot scan hnsw index without order"); + /* Safety check */ + if (scan->orderByData == NULL) + elog(ERROR, "cannot scan hnsw index without order"); - /* Requires MVCC-compliant snapshot as not able to maintain a pin */ - /* https://www.postgresql.org/docs/current/index-locking.html */ - if (!IsMVCCSnapshot(scan->xs_snapshot)) - elog(ERROR, "non-MVCC snapshots are not supported with hnsw"); + /* Requires MVCC-compliant snapshot as not able to maintain a pin */ + /* https://www.postgresql.org/docs/current/index-locking.html */ + if (!IsMVCCSnapshot(scan->xs_snapshot)) + elog(ERROR, "non-MVCC snapshots are not supported with hnsw"); - /* Get scan value */ - value = GetScanValue(scan); + /* Get scan value */ + value = GetScanValue(scan); - /* - * Get a shared lock. This allows vacuum to ensure no in-flight scans - * before marking tuples as deleted. - */ - LockPage(scan->indexRelation, HNSW_SCAN_LOCK, ShareLock); + /* + * Get a shared lock. This allows vacuum to ensure no in-flight scans + * before marking tuples as deleted. + */ + LockPage(scan->indexRelation, HNSW_SCAN_LOCK, ShareLock); - so->w = GetScanItems(scan, value); + so->w = GetScanItems(scan, value); - /* Release shared lock */ - UnlockPage(scan->indexRelation, HNSW_SCAN_LOCK, ShareLock); + /* Release shared lock */ + UnlockPage(scan->indexRelation, HNSW_SCAN_LOCK, ShareLock); - so->first = false; + so->first = false; #if defined(HNSW_MEMORY) && PG_VERSION_NUM >= 130000 - elog(INFO, "memory: %zu MB", MemoryContextMemAllocated(so->tmpCtx, false) / (1024 * 1024)); + elog(INFO, "memory: %zu MB", MemoryContextMemAllocated(so->tmpCtx, false) / MEM_INFO_NUM); #endif - } + } - while (list_length(so->w) > 0) - { - char *base = NULL; - HnswCandidate *hc = (HnswCandidate *)llast(so->w); - HnswElement element = (HnswElement)HnswPtrAccess(base, hc->element); - ItemPointer heaptid; + while (list_length(so->w) > 0) { + char *base = NULL; + HnswCandidate *hc = (HnswCandidate *)linitial(so->w); + HnswElement element = (HnswElement)HnswPtrAccess(base, hc->element); + ItemPointer heaptid; - /* Move to next element if no valid heap TIDs */ - if (element->heaptidsLength == 0) - { - so->w = list_delete_last(so->w); - continue; - } + /* Move to next element if no valid heap TIDs */ + if (element->heaptidsLength == 0) { + so->w = list_delete_first(so->w); + continue; + } - heaptid = &element->heaptids[--element->heaptidsLength]; + heaptid = &element->heaptids[--element->heaptidsLength]; - MemoryContextSwitchTo(oldCtx); + MemoryContextSwitchTo(oldCtx); - scan->xs_ctup.t_self = *heaptid; - scan->xs_recheck = false; - return true; - } + scan->xs_ctup.t_self = *heaptid; + scan->xs_recheck = false; + return true; + } - MemoryContextSwitchTo(oldCtx); - return false; + MemoryContextSwitchTo(oldCtx); + return false; } /* @@ -198,10 +203,12 @@ hnswgettuple_internal(IndexScanDesc scan, ScanDirection dir) void hnswendscan_internal(IndexScanDesc scan) { - HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + HnswScanOpaque so = (HnswScanOpaque) scan->opaque; + + FREE_POINTER(so->vs.lastSelfModifiedItup); - MemoryContextDelete(so->tmpCtx); + MemoryContextDelete(so->tmpCtx); - pfree(so); - scan->opaque = NULL; + pfree(so); + scan->opaque = NULL; } diff --git a/contrib/datavec/src/hnswutils.cpp b/contrib/datavec/src/hnswutils.cpp index 9e01d1d419fbcd09e5e63e6feb9790f8f1202ca2..d5d2b4b03f99b29ffdd5e9f487bcf5bad88de83c 100644 --- a/contrib/datavec/src/hnswutils.cpp +++ b/contrib/datavec/src/hnswutils.cpp @@ -232,11 +232,12 @@ HnswNewBuffer(Relation index, ForkNumber forkNum) * Init page */ void -HnswInitPage(Buffer buf, Page page) +HnswInitPage(Buffer buf, Page page, uint8 pageType) { - PageInit(page, BufferGetPageSize(buf), sizeof(HnswPageOpaqueData)); - HnswPageGetOpaque(page)->nextblkno = InvalidBlockNumber; - HnswPageGetOpaque(page)->page_id = HNSW_PAGE_ID; + PageInit(page, BufferGetPageSize(buf), sizeof(HnswPageOpaqueData)); + HnswPageGetOpaque(page)->nextblkno = InvalidBlockNumber; + HnswPageGetOpaque(page)->page_id = HNSW_PAGE_ID; + HnswPageGetOpaque(page)->pageType = pageType; } /* @@ -654,36 +655,47 @@ HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHe /* * Load an element and optionally get its distance from q */ -void -HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance) +bool +HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, + Oid collation, bool loadVec, float *maxDistance, IndexScanDesc scan) { - Buffer buf; - Page page; - HnswElementTuple etup; - - /* Read vector */ - buf = ReadBuffer(index, element->blkno); - LockBuffer(buf, BUFFER_LOCK_SHARE); - page = BufferGetPage(buf); + Buffer buf; + Page page; + HnswElementTuple etup; + bool needRecheck = false; + bool isVisible = true; + + /* Read vector */ + buf = ReadBuffer(index, element->blkno); + LockBuffer(buf, BUFFER_LOCK_SHARE); + page = BufferGetPage(buf); + if (scan != NULL && HnswPageGetOpaque(page)->pageType == HNSW_USTORE_PAGE_TYPE) { + HnswScanOpaque so = (HnswScanOpaque)scan->opaque; + so->vs.buf = buf; + isVisible = VecVisibilityCheck(scan, page, element->offno, &needRecheck); + } - etup = (HnswElementTuple) PageGetItem(page, PageGetItemId(page, element->offno)); + etup = (HnswElementTuple) PageGetItem(page, PageGetItemId(page, element->offno)); - Assert(HnswIsElementTuple(etup)); + Assert(HnswIsElementTuple(etup)); - /* Calculate distance */ - if (distance != NULL) - { - if (DatumGetPointer(*q) == NULL) - *distance = 0; - else - *distance = (float) DatumGetFloat8(FunctionCall2Coll(procinfo, collation, *q, PointerGetDatum(&etup->data))); - } + /* Calculate distance */ + if (distance != NULL) { + if (DatumGetPointer(*q) == NULL) { + *distance = 0; + } else { + *distance = (float) DatumGetFloat8(FunctionCall2Coll(procinfo, collation, *q, + PointerGetDatum(&etup->data))); + } + } - /* Load element */ - if (distance == NULL || maxDistance == NULL || *distance < *maxDistance) - HnswLoadElementFromTuple(element, etup, true, loadVec); + /* Load element */ + if (distance == NULL || maxDistance == NULL || *distance < *maxDistance) { + HnswLoadElementFromTuple(element, etup, true, loadVec); + } - UnlockReleaseBuffer(buf); + UnlockReleaseBuffer(buf); + return isVisible; } /* @@ -702,16 +714,22 @@ GetCandidateDistance(char *base, HnswCandidate * hc, Datum q, FmgrInfo *procinfo * Create a candidate for the entry point */ HnswCandidate * -HnswEntryCandidate(char *base, HnswElement entryPoint, Datum q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec) +HnswEntryCandidate(char *base, HnswElement entryPoint, Datum q, Relation index, FmgrInfo *procinfo, + Oid collation, bool loadVec, IndexScanDesc scan) { - HnswCandidate *hc = (HnswCandidate *)palloc(sizeof(HnswCandidate)); + HnswCandidate *hc = (HnswCandidate *)palloc(sizeof(HnswCandidate)); - HnswPtrStore(base, hc->element, entryPoint); - if (index == NULL) - hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation); - else - HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec, NULL); - return hc; + HnswPtrStore(base, hc->element, entryPoint); + if (index == NULL) { + hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation); + } else { + bool isVisible = HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, + collation, loadVec, NULL, scan); + if (!isVisible) { + elog(ERROR, "hnsw entryPoint is invisible\n"); + } + } + return hc; } /* @@ -828,138 +846,136 @@ CountElement(char *base, HnswElement skipElement, HnswCandidate * hc) * Algorithm 2 from paper */ List * -HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinfo, Oid collation, int m, bool inserting, HnswElement skipElement) +HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinfo, + Oid collation, int m, bool inserting, HnswElement skipElement, IndexScanDesc scan) { - List *w = NIL; - pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL); - pairingheap *W = pairingheap_allocate(CompareFurthestCandidates, NULL); - int wlen = 0; - visited_hash v; - ListCell *lc2; - HnswNeighborArray *neighborhoodData = NULL; - Size neighborhoodSize; - - InitVisited(base, &v, index, ef, m); - - /* Create local memory for neighborhood if needed */ - if (index == NULL) - { - neighborhoodSize = HNSW_NEIGHBOR_ARRAY_SIZE(HnswGetLayerM(m, lc)); - neighborhoodData = (HnswNeighborArray *)palloc(neighborhoodSize); - } - - /* Add entry points to v, C, and W */ - foreach(lc2, ep) - { - HnswCandidate *hc = (HnswCandidate *) lfirst(lc2); - bool found; - - AddToVisited(base, &v, hc, index, &found); - - pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node)); - pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node)); - - /* - * Do not count elements being deleted towards ef when vacuuming. It - * would be ideal to do this for inserts as well, but this could - * affect insert performance. - */ - if (CountElement(base, skipElement, hc)) - wlen++; - } + List *w = NIL; + pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL); + pairingheap *W = pairingheap_allocate(CompareFurthestCandidates, NULL); + int wlen = 0; + visited_hash v; + ListCell *lc2; + HnswNeighborArray *neighborhoodData = NULL; + Size neighborhoodSize; + bool isVisible = true; + + InitVisited(base, &v, index, ef, m); + + /* Create local memory for neighborhood if needed */ + if (index == NULL) { + neighborhoodSize = HNSW_NEIGHBOR_ARRAY_SIZE(HnswGetLayerM(m, lc)); + neighborhoodData = (HnswNeighborArray *)palloc(neighborhoodSize); + } - while (!pairingheap_is_empty(C)) - { - HnswNeighborArray *neighborhood; - HnswCandidate *c = ((HnswPairingHeapNode *) pairingheap_remove_first(C))->inner; - HnswCandidate *f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner; - HnswElement cElement; + /* Add entry points to v, C, and W */ + foreach(lc2, ep) { + HnswCandidate *hc = (HnswCandidate *) lfirst(lc2); + bool found; - if (c->distance > f->distance) - break; + AddToVisited(base, &v, hc, index, &found); - cElement = (HnswElement)HnswPtrAccess(base, c->element); + pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node)); + pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node)); - if (HnswPtrIsNull(base, cElement->neighbors)) - HnswLoadNeighbors(cElement, index, m); + /* + * Do not count elements being deleted towards ef when vacuuming. It + * would be ideal to do this for inserts as well, but this could + * affect insert performance. + */ + if (CountElement(base, skipElement, hc)) + wlen++; + } - /* Get the neighborhood at layer lc */ - neighborhood = HnswGetNeighbors(base, cElement, lc); + while (!pairingheap_is_empty(C)) { + HnswNeighborArray *neighborhood; + HnswCandidate *c = ((HnswPairingHeapNode *) pairingheap_remove_first(C))->inner; + HnswCandidate *f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner; + HnswElement cElement; - /* Copy neighborhood to local memory if needed */ - if (index == NULL) - { - LWLockAcquire(&cElement->lock, LW_SHARED); - memcpy(neighborhoodData, neighborhood, neighborhoodSize); - LWLockRelease(&cElement->lock); - neighborhood = neighborhoodData; - } + if (c->distance > f->distance) + break; - for (int i = 0; i < neighborhood->length; i++) - { - HnswCandidate *e = &neighborhood->items[i]; - bool visited; + cElement = (HnswElement)HnswPtrAccess(base, c->element); - AddToVisited(base, &v, e, index, &visited); + if (HnswPtrIsNull(base, cElement->neighbors)) + HnswLoadNeighbors(cElement, index, m); - if (!visited) - { - float eDistance; - HnswElement eElement = (HnswElement)HnswPtrAccess(base, e->element); - bool alwaysAdd = wlen < ef; + /* Get the neighborhood at layer lc */ + neighborhood = HnswGetNeighbors(base, cElement, lc); - f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner; - - if (index == NULL) - eDistance = GetCandidateDistance(base, e, q, procinfo, collation); - else - HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting, alwaysAdd ? NULL : &f->distance); + /* Copy neighborhood to local memory if needed */ + if (index == NULL) { + LWLockAcquire(&cElement->lock, LW_SHARED); + memcpy(neighborhoodData, neighborhood, neighborhoodSize); + LWLockRelease(&cElement->lock); + neighborhood = neighborhoodData; + } - if (eDistance < f->distance || alwaysAdd) - { - HnswCandidate *ec; - - Assert(!eElement->deleted); - - /* Make robust to issues */ - if (eElement->level < lc) - continue; - - /* Copy e */ - ec = (HnswCandidate *)palloc(sizeof(HnswCandidate)); - HnswPtrStore(base, ec->element, eElement); - ec->distance = eDistance; - - pairingheap_add(C, &(CreatePairingHeapNode(ec)->ph_node)); - pairingheap_add(W, &(CreatePairingHeapNode(ec)->ph_node)); - - /* - * Do not count elements being deleted towards ef when - * vacuuming. It would be ideal to do this for inserts as - * well, but this could affect insert performance. - */ - if (CountElement(base, skipElement, e)) - { - wlen++; - - /* No need to decrement wlen */ - if (wlen > ef) - pairingheap_remove_first(W); - } - } - } - } - } + for (int i = 0; i < neighborhood->length; i++) { + HnswCandidate *e = &neighborhood->items[i]; + bool visited; + + AddToVisited(base, &v, e, index, &visited); + + if (!visited) { + float eDistance; + HnswElement eElement = (HnswElement)HnswPtrAccess(base, e->element); + bool alwaysAdd = wlen < ef; + + f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner; + + if (index == NULL) { + eDistance = GetCandidateDistance(base, e, q, procinfo, collation); + } else { + isVisible = HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting, + alwaysAdd ? NULL : &f->distance, scan); + } + if (!isVisible) { + continue; + } + + if (eDistance < f->distance || alwaysAdd) { + HnswCandidate *ec; + + Assert(!eElement->deleted); + + /* Make robust to issues */ + if (eElement->level < lc) + continue; + + /* Copy e */ + ec = (HnswCandidate *)palloc(sizeof(HnswCandidate)); + HnswPtrStore(base, ec->element, eElement); + ec->distance = eDistance; + + pairingheap_add(C, &(CreatePairingHeapNode(ec)->ph_node)); + pairingheap_add(W, &(CreatePairingHeapNode(ec)->ph_node)); + + /* + * Do not count elements being deleted towards ef when + * vacuuming. It would be ideal to do this for inserts as + * well, but this could affect insert performance. + */ + if (CountElement(base, skipElement, e)) { + wlen++; + + /* No need to decrement wlen */ + if (wlen > ef) + pairingheap_remove_first(W); + } + } + } + } + } - /* Add each element of W to w */ - while (!pairingheap_is_empty(W)) - { - HnswCandidate *hc = ((HnswPairingHeapNode *) pairingheap_remove_first(W))->inner; + /* Add each element of W to w */ + while (!pairingheap_is_empty(W)) { + HnswCandidate *hc = ((HnswPairingHeapNode *) pairingheap_remove_first(W))->inner; - w = lappend(w, hc); - } + w = lcons(hc, w); + } - return w; + return w; } /* @@ -1064,105 +1080,112 @@ CheckElementCloser(char *base, HnswCandidate * e, List *r, FmgrInfo *procinfo, O static List * SelectNeighbors(char *base, List *c, int lm, int lc, FmgrInfo *procinfo, Oid collation, HnswElement e2, HnswCandidate * newCandidate, HnswCandidate * *pruned, bool sortCandidates) { - List *r = NIL; - List *w = list_copy(c); - HnswCandidate **wd; - int wdlen = 0; - int wdoff = 0; - HnswNeighborArray *neighbors = HnswGetNeighbors(base, e2, lc); - bool mustCalculate = !neighbors->closerSet; - List *added = NIL; - bool removedAny = false; - - if (list_length(w) <= lm) - return w; - - wd = (HnswCandidate **)palloc(sizeof(HnswCandidate *) * list_length(w)); - - /* Ensure order of candidates is deterministic for closer caching */ - if (sortCandidates) - { - if (base == NULL) - list_sort(w, CompareCandidateDistances); - else - list_sort(w, CompareCandidateDistancesOffset); - } - - while (list_length(w) > 0 && list_length(r) < lm) - { - /* Assumes w is already ordered desc */ - HnswCandidate *e = (HnswCandidate *)llast(w); + List *r = NIL; + List *w = list_copy(c); + HnswCandidate **wd; + int wdlen = 0; + int wdoff = 0; + HnswNeighborArray *neighbors = HnswGetNeighbors(base, e2, lc); + bool mustCalculate = !neighbors->closerSet; + List *added = NIL; + bool removedAny = false; + + if (list_length(w) <= lm) + return w; + + wd = (HnswCandidate **)palloc(sizeof(HnswCandidate *) * list_length(w)); + + /* Ensure order of candidates is deterministic for closer caching */ + if (sortCandidates) + { + if (base == NULL) { + list_sort(w, CompareCandidateDistances); + } + else { + list_sort(w, CompareCandidateDistancesOffset); + } + } - w = list_delete_last(w); + while (list_length(w) > 0 && list_length(r) < lm) { + /* Assumes w is already ordered desc */ + HnswCandidate *e = (HnswCandidate *)linitial(w); - /* Use previous state of r and wd to skip work when possible */ - if (mustCalculate) - e->closer = CheckElementCloser(base, e, r, procinfo, collation); - else if (list_length(added) > 0) - { - /* Keep Valgrind happy for in-memory, parallel builds */ - if (base != NULL) - VALGRIND_MAKE_MEM_DEFINED(&e->closer, 1); - - /* - * If the current candidate was closer, we only need to compare it - * with the other candidates that we have added. - */ - if (e->closer) - { - e->closer = CheckElementCloser(base, e, added, procinfo, collation); + w = list_delete_first(w); - if (!e->closer) - removedAny = true; - } - else - { - /* - * If we have removed any candidates from closer, a candidate - * that was not closer earlier might now be. - */ - if (removedAny) - { - e->closer = CheckElementCloser(base, e, r, procinfo, collation); - if (e->closer) - added = lappend(added, e); - } - } - } - else if (e == newCandidate) - { - e->closer = CheckElementCloser(base, e, r, procinfo, collation); - if (e->closer) - added = lappend(added, e); - } + /* Use previous state of r and wd to skip work when possible */ + if (mustCalculate) { + e->closer = CheckElementCloser(base, e, r, procinfo, collation); + } + else if (list_length(added) > 0) { + /* Keep Valgrind happy for in-memory, parallel builds */ + if (base != NULL) { + VALGRIND_MAKE_MEM_DEFINED(&e->closer, 1); + } + + /* + * If the current candidate was closer, we only need to compare it + * with the other candidates that we have added. + */ + if (e->closer) { + e->closer = CheckElementCloser(base, e, added, procinfo, collation); + + if (!e->closer) { + removedAny = true; + } + } + else { + /* + * If we have removed any candidates from closer, a candidate + * that was not closer earlier might now be. + */ + if (removedAny) { + e->closer = CheckElementCloser(base, e, r, procinfo, collation); + if (e->closer) { + added = lappend(added, e); + } + } + } + } + else if (e == newCandidate) + { + e->closer = CheckElementCloser(base, e, r, procinfo, collation); + if (e->closer) { + added = lappend(added, e); + } + } - /* Keep Valgrind happy for in-memory, parallel builds */ - if (base != NULL) - VALGRIND_MAKE_MEM_DEFINED(&e->closer, 1); + /* Keep Valgrind happy for in-memory, parallel builds */ + if (base != NULL) { + VALGRIND_MAKE_MEM_DEFINED(&e->closer, 1); + } - if (e->closer) - r = lappend(r, e); - else - wd[wdlen++] = e; - } + if (e->closer) { + r = lappend(r, e); + } + else { + wd[wdlen++] = e; + } + } - /* Cached value can only be used in future if sorted deterministically */ - neighbors->closerSet = sortCandidates; + /* Cached value can only be used in future if sorted deterministically */ + neighbors->closerSet = sortCandidates; - /* Keep pruned connections */ - while (wdoff < wdlen && list_length(r) < lm) - r = lappend(r, wd[wdoff++]); + /* Keep pruned connections */ + while (wdoff < wdlen && list_length(r) < lm) { + r = lappend(r, wd[wdoff++]); + } - /* Return pruned for update connections */ - if (pruned != NULL) - { - if (wdoff < wdlen) - *pruned = wd[wdoff]; - else - *pruned = (HnswCandidate *)linitial(w); - } + /* Return pruned for update connections */ + if (pruned != NULL) { + if (wdoff < wdlen) { + *pruned = wd[wdoff]; + } + else { + *pruned = (HnswCandidate *)linitial(w); + } + } - return r; + return r; } /* diff --git a/contrib/datavec/src/ivfbuild.cpp b/contrib/datavec/src/ivfbuild.cpp index af84c22bb69de213eebcfa8e98d9c02bc3ddc70f..be4b30d427776c7bfd049a3949fdc998e159d4f2 100644 --- a/contrib/datavec/src/ivfbuild.cpp +++ b/contrib/datavec/src/ivfbuild.cpp @@ -14,6 +14,7 @@ #include "utils/memutils.h" #include "vector.h" #include "postmaster/bgworker.h" +#include "commands/vacuum.h" #if PG_VERSION_NUM >= 140000 #include "utils/backend_progress.h" @@ -37,6 +38,96 @@ #define PARALLEL_KEY_IVFFLAT_CENTERS UINT64CONST(0xA000000000000003) #define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000004) +/* + * Add sample + */ +static void +AddSample(Datum *values, IvfflatBuildState *buildstate) +{ + VectorArray samples = buildstate->samples; + int targsamples = samples->maxlen; + + /* Detoast once for all calls */ + Datum value = PointerGetDatum(PG_DETOAST_DATUM(values[0])); + + /* + * Normalize with KMEANS_NORM_PROC since spherical distance function + * expects unit vectors + */ + if (buildstate->kmeansnormprocinfo != NULL) { + if (!IvfflatCheckNorm(buildstate->kmeansnormprocinfo, buildstate->collation, value)) { + return; + } + + value = IvfflatNormValue(buildstate->typeInfo, buildstate->collation, value); + } + + if (samples->length < targsamples) { + VectorArraySet(samples, samples->length, DatumGetPointer(value)); + samples->length++; + } else { + if (buildstate->rowstoskip < 0) { + buildstate->rowstoskip = anl_get_next_S(samples->length, targsamples, &buildstate->rstate); + } + + if (buildstate->rowstoskip <= 0) { + int k = (int) (targsamples * anl_random_fract()); + Assert(k >= 0 && k < targsamples); + VectorArraySet(samples, k, DatumGetPointer(value)); + } + + buildstate->rowstoskip -= 1; + } +} + +/* + * Callback for sampling + */ +static void +SampleCallback(Relation index, CALLBACK_ITEM_POINTER, Datum *values, + const bool *isnull, bool tupleIsAlive, void *state) +{ + IvfflatBuildState *buildstate = (IvfflatBuildState *) state; + MemoryContext oldCtx; + + /* Skip nulls */ + if (isnull[0]) { + return; + } + + /* Use memory context since detoast can allocate */ + oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx); + + /* Add sample */ + AddSample(values, buildstate); + + /* Reset memory context */ + MemoryContextSwitchTo(oldCtx); + MemoryContextReset(buildstate->tmpCtx); +} + +/* + * Sample rows with same logic as ANALYZE + */ +static void +SampleRows(IvfflatBuildState *buildstate) +{ + int targsamples = buildstate->samples->maxlen; + BlockNumber totalblocks = RelationGetNumberOfBlocks(buildstate->heap); + + buildstate->rowstoskip = -1; + + BlockSampler_Init(&buildstate->bs, totalblocks, targsamples); + + buildstate->rstate = anl_init_selection_state(targsamples); + while (BlockSampler_HasMore(&buildstate->bs)) { + BlockNumber targblock = BlockSampler_Next(&buildstate->bs); + + tableam_index_build_scan(buildstate->heap, buildstate->index, buildstate->indexInfo, + false, SampleCallback, (void *) buildstate, NULL, targblock, 1); + } +} + /* * Add tuple to sort */ @@ -294,39 +385,41 @@ FreeBuildState(IvfflatBuildState * buildstate) * Compute centers */ static void -ComputeCenters(IvfflatBuildState * buildstate) +ComputeCenters(IvfflatBuildState *buildstate) { - int numSamples; - - /* Target 50 samples per list, with at least 10000 samples */ - /* The number of samples has a large effect on index build time */ - numSamples = buildstate->lists * 50; - if (numSamples < 10000) - numSamples = 10000; - - /* Skip samples for unlogged table */ - if (buildstate->heap == NULL) - numSamples = 1; - - /* Sample rows */ - /* TODO Ensure within maintenance_work_mem */ - buildstate->samples = VectorArrayInit(numSamples, buildstate->dimensions, buildstate->centers->itemsize); - if (buildstate->heap != NULL) - { - if (buildstate->samples->length < buildstate->lists) - { - ereport(NOTICE, - (errmsg("ivfflat index created with little data"), - errdetail("This will cause low recall."), - errhint("Drop the index until the table has more data."))); - } - } - - /* Calculate centers */ - IvfflatBench("k-means", IvfflatKmeans(buildstate->index, buildstate->samples, buildstate->centers, buildstate->typeInfo)); - - /* Free samples before we allocate more memory */ - VectorArrayFree(buildstate->samples); + int numSamples; + + /* Target 50 samples per list, with at least 10000 samples */ + /* The number of samples has a large effect on index build time */ + numSamples = buildstate->lists * 50; + if (numSamples < 10000) { + numSamples = 10000; + } + + /* Skip samples for unlogged table */ + if (buildstate->heap == NULL) { + numSamples = 1; + } + + /* Sample rows */ + /* TODO Ensure within maintenance_work_mem */ + buildstate->samples = VectorArrayInit(numSamples, buildstate->dimensions, buildstate->centers->itemsize); + if (buildstate->heap != NULL) { + SampleRows(buildstate); + if (buildstate->samples->length < buildstate->lists) { + ereport(NOTICE, + (errmsg("ivfflat index created with little data"), + errdetail("This will cause low recall."), + errhint("Drop the index until the table has more data."))); + } + } + + /* Calculate centers */ + IvfflatBench("k-means", IvfflatKmeans(buildstate->index, buildstate->samples, + buildstate->centers, buildstate->typeInfo)); + + /* Free samples before we allocate more memory */ + VectorArrayFree(buildstate->samples); } /* diff --git a/contrib/datavec/src/ivfflat.cpp b/contrib/datavec/src/ivfflat.cpp index 753fb6a2ef30e41ae363d70f1b1d32efe6ea5d9d..27ee98945c15b54f8eb6e1962d0ae821ae74ddd3 100644 --- a/contrib/datavec/src/ivfflat.cpp +++ b/contrib/datavec/src/ivfflat.cpp @@ -10,11 +10,6 @@ #include "utils/selfuncs.h" #include "utils/spccache.h" -#if PG_VERSION_NUM < 150000 -#define MarkGUCPrefixReserved(x) EmitWarningsOnPlaceholders(x) -#endif - -int ivfflat_probes; static relopt_kind ivfflat_relopt_kind; /* @@ -30,12 +25,6 @@ IvfflatInit(void) ,AccessExclusiveLock #endif ); - - DefineCustomIntVariable("ivfflat.probes", "Sets the number of probes", - "Valid range is 1..lists.", &ivfflat_probes, - IVFFLAT_DEFAULT_PROBES, IVFFLAT_MIN_LISTS, IVFFLAT_MAX_LISTS, PGC_USERSET, 0, NULL, NULL, NULL); - - MarkGUCPrefixReserved("ivfflat"); } /* @@ -43,75 +32,74 @@ IvfflatInit(void) */ static void ivfflatcostestimate_internal(PlannerInfo *root, IndexPath *path, double loop_count, - Cost *indexStartupCost, Cost *indexTotalCost, - Selectivity *indexSelectivity, double *indexCorrelation) + Cost *indexStartupCost, Cost *indexTotalCost, + Selectivity *indexSelectivity, double *indexCorrelation) { - GenericCosts costs; - int lists; - double ratio; - double spc_seq_page_cost; - Relation index; - - /* Never use index without order */ - if (path->indexorderbys == NULL) - { - *indexStartupCost = DBL_MAX; - *indexTotalCost = DBL_MAX; - *indexSelectivity = 0; - *indexCorrelation = 0; - return; - } - - MemSet(&costs, 0, sizeof(costs)); - - index = index_open(path->indexinfo->indexoid, NoLock); - IvfflatGetMetaPageInfo(index, &lists, NULL); - index_close(index, NoLock); - - /* Get the ratio of lists that we need to visit */ - ratio = ((double) ivfflat_probes) / lists; - if (ratio > 1.0) - ratio = 1.0; - - /* - * This gives us the subset of tuples to visit. This value is passed into - * the generic cost estimator to determine the number of pages to visit - * during the index scan. - */ - costs.numIndexTuples = path->indexinfo->tuples * ratio; - - genericcostestimate(root, path, loop_count, costs.numIndexTuples, &costs.indexStartupCost, - &costs.indexTotalCost, &costs.indexSelectivity, &costs.indexCorrelation); - - get_tablespace_page_costs(path->indexinfo->reltablespace, NULL, &spc_seq_page_cost); - - /* Adjust cost if needed since TOAST not included in seq scan cost */ - if (costs.numIndexPages > path->indexinfo->rel->pages && ratio < 0.5) - { - /* Change all page cost from random to sequential */ - costs.indexTotalCost -= costs.numIndexPages * (costs.spc_random_page_cost - spc_seq_page_cost); - - /* Remove cost of extra pages */ - costs.indexTotalCost -= (costs.numIndexPages - path->indexinfo->rel->pages) * spc_seq_page_cost; - } - else - { - /* Change some page cost from random to sequential */ - costs.indexTotalCost -= 0.5 * costs.numIndexPages * (costs.spc_random_page_cost - spc_seq_page_cost); - } - - /* - * If the list selectivity is lower than what is returned from the generic - * cost estimator, use that. - */ - if (ratio < costs.indexSelectivity) - costs.indexSelectivity = ratio; - - /* Use total cost since most work happens before first tuple is returned */ - *indexStartupCost = costs.indexTotalCost; - *indexTotalCost = costs.indexTotalCost; - *indexSelectivity = costs.indexSelectivity; - *indexCorrelation = costs.indexCorrelation; + GenericCosts costs; + int lists; + double ratio; + double spc_seq_page_cost; + Relation index; + double half = 0.5; + + /* Never use index without order */ + if (path->indexorderbys == NULL) { + *indexStartupCost = DBL_MAX; + *indexTotalCost = DBL_MAX; + *indexSelectivity = 0; + *indexCorrelation = 0; + return; + } + + MemSet(&costs, 0, sizeof(costs)); + + index = index_open(path->indexinfo->indexoid, NoLock); + IvfflatGetMetaPageInfo(index, &lists, NULL); + index_close(index, NoLock); + + /* Get the ratio of lists that we need to visit */ + ratio = ((double) get_session_context()->ivfflat_probes) / lists; + if (ratio > 1.0) { + ratio = 1.0; + } + + /* + * This gives us the subset of tuples to visit. This value is passed into + * the generic cost estimator to determine the number of pages to visit + * during the index scan. + */ + costs.numIndexTuples = path->indexinfo->tuples * ratio; + + genericcostestimate(root, path, loop_count, costs.numIndexTuples, &costs.indexStartupCost, + &costs.indexTotalCost, &costs.indexSelectivity, &costs.indexCorrelation); + + get_tablespace_page_costs(path->indexinfo->reltablespace, NULL, &spc_seq_page_cost); + + /* Adjust cost if needed since TOAST not included in seq scan cost */ + if (costs.numIndexPages > path->indexinfo->rel->pages && ratio < half) { + /* Change all page cost from random to sequential */ + costs.indexTotalCost -= costs.numIndexPages * (costs.spc_random_page_cost - spc_seq_page_cost); + + /* Remove cost of extra pages */ + costs.indexTotalCost -= (costs.numIndexPages - path->indexinfo->rel->pages) * spc_seq_page_cost; + } else { + /* Change some page cost from random to sequential */ + costs.indexTotalCost -= half * costs.numIndexPages * (costs.spc_random_page_cost - spc_seq_page_cost); + } + + /* + * If the list selectivity is lower than what is returned from the generic + * cost estimator, use that. + */ + if (ratio < costs.indexSelectivity) { + costs.indexSelectivity = ratio; + } + + /* Use total cost since most work happens before first tuple is returned */ + *indexStartupCost = costs.indexTotalCost; + *indexTotalCost = costs.indexTotalCost; + *indexSelectivity = costs.indexSelectivity; + *indexCorrelation = costs.indexCorrelation; } /* @@ -120,27 +108,30 @@ ivfflatcostestimate_internal(PlannerInfo *root, IndexPath *path, double loop_cou static bytea * ivfflatoptions_internal(Datum reloptions, bool validate) { - static const relopt_parse_elt tab[] = { - {"lists", RELOPT_TYPE_INT, offsetof(IvfflatOptions, lists)}, - {"parallel_workers", RELOPT_TYPE_INT, offsetof(StdRdOptions, parallel_workers)} - }; + static const relopt_parse_elt tab[] = { + {"lists", RELOPT_TYPE_INT, offsetof(IvfflatOptions, lists)}, + {"parallel_workers", RELOPT_TYPE_INT, offsetof(StdRdOptions, parallel_workers)} + }; #if PG_VERSION_NUM >= 130000 - return (bytea *) build_reloptions(reloptions, validate, - ivfflat_relopt_kind, - sizeof(IvfflatOptions), - tab, lengthof(tab)); + return (bytea *) build_reloptions(reloptions, validate, + ivfflat_relopt_kind, + sizeof(IvfflatOptions), + tab, lengthof(tab)); #else - relopt_value *options; - int numoptions; - IvfflatOptions *rdopts; - - options = parseRelOptions(reloptions, validate, ivfflat_relopt_kind, &numoptions); - rdopts = (IvfflatOptions *)allocateReloptStruct(sizeof(IvfflatOptions), options, numoptions); - fillRelOptions((void *) rdopts, sizeof(IvfflatOptions), options, numoptions, - validate, tab, lengthof(tab)); - - return (bytea *) rdopts; + relopt_value *options; + int numoptions; + IvfflatOptions *rdopts; + + if (needInitialization) { + InitRelOptions(); + } + options = parseRelOptions(reloptions, validate, ivfflat_relopt_kind, &numoptions); + rdopts = (IvfflatOptions *)allocateReloptStruct(sizeof(IvfflatOptions), options, numoptions); + fillRelOptions((void *) rdopts, sizeof(IvfflatOptions), options, numoptions, + validate, tab, lengthof(tab)); + + return (bytea *) rdopts; #endif } diff --git a/contrib/datavec/src/ivfflat.h b/contrib/datavec/src/ivfflat.h index 3989230c939d7e6e71772e66235621f9591e254e..d18d896f9aa164dbf37cef2e6b06f838b60e6d2c 100644 --- a/contrib/datavec/src/ivfflat.h +++ b/contrib/datavec/src/ivfflat.h @@ -79,9 +79,6 @@ #define RandomInt() random() #endif -/* Variables */ -extern int ivfflat_probes; - typedef struct VectorArrayData { int length; @@ -191,7 +188,7 @@ typedef struct IvfflatBuildState /* Sampling */ BlockSamplerData bs; - ReservoirStateData rstate; + double rstate; int rowstoskip; /* Sorting */ diff --git a/contrib/datavec/src/ivfkmeans.cpp b/contrib/datavec/src/ivfkmeans.cpp index 3ca043381769031fb93fe0f5d1e4fb77a72a7481..fcdcd9d285c974e59b37ac91831db31324cbd503 100644 --- a/contrib/datavec/src/ivfkmeans.cpp +++ b/contrib/datavec/src/ivfkmeans.cpp @@ -316,7 +316,7 @@ ElkanKmeans(Relation index, VectorArray samples, VectorArray centers, const Ivff agg = (float *)palloc(aggSize); centerCounts = (int *)palloc(centerCountsSize); closestCenters = (int *)palloc(closestCentersSize); - lowerBound = (float *)palloc_extended(lowerBoundSize, MCXT_ALLOC_HUGE); + lowerBound = (float *)MemoryContextAllocExtended(CurrentMemoryContext, lowerBoundSize, MCXT_ALLOC_HUGE); upperBound = (float *)palloc(upperBoundSize); s = (float *)palloc(sSize); halfcdist = (float *)palloc_extended(halfcdistSize, MCXT_ALLOC_HUGE); diff --git a/contrib/datavec/src/ivfscan.cpp b/contrib/datavec/src/ivfscan.cpp index 6fe411f6a2252519329cd05e31a9cbf16e955c63..acd0e1ef48340154bd73a104b06d6f05a8753248 100644 --- a/contrib/datavec/src/ivfscan.cpp +++ b/contrib/datavec/src/ivfscan.cpp @@ -221,50 +221,55 @@ GetScanValue(IndexScanDesc scan) IndexScanDesc ivfflatbeginscan_internal(Relation index, int nkeys, int norderbys) { - IndexScanDesc scan; - IvfflatScanOpaque so; - int lists; - int dimensions; - AttrNumber attNums[] = {1}; - Oid sortOperators[] = {FLOAT8LTOID}; - Oid sortCollations[] = {InvalidOid}; - bool nullsFirstFlags[] = {false}; - int probes = ivfflat_probes; - - scan = RelationGetIndexScan(index, nkeys, norderbys); - - /* Get lists and dimensions from metapage */ - IvfflatGetMetaPageInfo(index, &lists, &dimensions); - - if (probes > lists) - probes = lists; - - so = (IvfflatScanOpaque) palloc(offsetof(IvfflatScanOpaqueData, lists) + probes * sizeof(IvfflatScanList)); - so->typeInfo = IvfflatGetTypeInfo(index); - so->first = true; - so->probes = probes; - so->dimensions = dimensions; - - /* Set support functions */ - so->procinfo = index_getprocinfo(index, 1, IVFFLAT_DISTANCE_PROC); - so->normprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_NORM_PROC); - so->collation = index->rd_indcollation[0]; - - /* Create tuple description for sorting */ - so->tupdesc = CreateTemplateTupleDesc(2, false); - TupleDescInitEntry(so->tupdesc, (AttrNumber) 1, "distance", FLOAT8OID, -1, 0); - TupleDescInitEntry(so->tupdesc, (AttrNumber) 2, "heaptid", TIDOID, -1, 0); - - /* Prep sort */ - so->sortstate = tuplesort_begin_heap(so->tupdesc, 1, attNums, sortOperators, sortCollations, nullsFirstFlags, u_sess->attr.attr_memory.work_mem, NULL, false); - - so->slot = MakeSingleTupleTableSlot(so->tupdesc); - - so->listQueue = pairingheap_allocate(CompareLists, scan); - - scan->opaque = so; - - return scan; + IndexScanDesc scan; + IvfflatScanOpaque so; + int lists; + int dimensions; + AttrNumber attNums[] = {1}; + Oid sortOperators[] = {FLOAT8LTOID}; + Oid sortCollations[] = {InvalidOid}; + bool nullsFirstFlags[] = {false}; + int probes = get_session_context()->ivfflat_probes; + int natts = 2; + int attDistance = 1; + int attHeaptid = 2; + + scan = RelationGetIndexScan(index, nkeys, norderbys); + + /* Get lists and dimensions from metapage */ + IvfflatGetMetaPageInfo(index, &lists, &dimensions); + + if (probes > lists) { + probes = lists; + } + + so = (IvfflatScanOpaque) palloc(offsetof(IvfflatScanOpaqueData, lists) + probes * sizeof(IvfflatScanList)); + so->typeInfo = IvfflatGetTypeInfo(index); + so->first = true; + so->probes = probes; + so->dimensions = dimensions; + + /* Set support functions */ + so->procinfo = index_getprocinfo(index, 1, IVFFLAT_DISTANCE_PROC); + so->normprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_NORM_PROC); + so->collation = index->rd_indcollation[0]; + + /* Create tuple description for sorting */ + so->tupdesc = CreateTemplateTupleDesc(natts, false); + TupleDescInitEntry(so->tupdesc, (AttrNumber) attDistance, "distance", FLOAT8OID, -1, 0); + TupleDescInitEntry(so->tupdesc, (AttrNumber) attHeaptid, "heaptid", TIDOID, -1, 0); + + /* Prep sort */ + so->sortstate = tuplesort_begin_heap(so->tupdesc, 1, attNums, sortOperators, sortCollations, nullsFirstFlags, + u_sess->attr.attr_memory.work_mem, NULL, false); + + so->slot = MakeSingleTupleTableSlot(so->tupdesc); + + so->listQueue = pairingheap_allocate(CompareLists, scan); + + scan->opaque = so; + + return scan; } /* diff --git a/contrib/datavec/src/vecindex.cpp b/contrib/datavec/src/vecindex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1c15e243fbe0de1cb7db24677379c92dcb581cf --- /dev/null +++ b/contrib/datavec/src/vecindex.cpp @@ -0,0 +1,293 @@ +#include "access/transam.h" +#include "hnsw.h" +#include "storage/procarray.h" +#include "vecindex.h" + +VectorScanData *VecGetScanData(IndexScanDesc scan) +{ + switch (scan->indexRelation->rd_rel->relam) { + case HNSW_AM_OID: + return &((HnswScanOpaque)scan->opaque)->vs; + default: + break; + } + return NULL; +} + +size_t VecDefaultMaxItemSize(IndexScanDesc scan) +{ + switch (scan->indexRelation->rd_rel->relam) { + case HNSW_AM_OID: + return HnswDefaultMaxItemSize; + default: + break; + } + return (size_t)-1; +} + +TransactionIdStatus HnswCheckXid(TransactionId xid) +{ + TransactionIdStatus ts = TransactionIdGetStatus(xid); + /* Please refer to HeapTupleSatisfiesVaccum */ + if (ts == XID_INPROGRESS) { + if (TransactionIdIsInProgress(xid)) { + /* Inprogress */ + } else if (TransactionIdDidCommit(xid)) { + ts = XID_COMMITTED; + } else { + ts = XID_ABORTED; + } + } + return ts; +} + +bool VecItupGetXminXmax(Page page, OffsetNumber offnum, TransactionId oldest_xmin, TransactionId *xmin, + TransactionId *xmax, bool *xminCommitted, bool *xmaxCommitted, bool isToast) +{ + ItemId iid = PageGetItemId(page, offnum); + HnswElementTuple itup = (HnswElementTuple)PageGetItem(page, iid); + IndexTransInfo* idxXid = (IndexTransInfo*)VecIndexTupleGetXid(itup); + bool isDead = false; + bool needCheckXmin = true; + + *xminCommitted = *xmaxCommitted = false; + + if (ItemIdIsDead(iid)) { + *xmin = InvalidTransactionId; + *xmax = InvalidTransactionId; + return true; + } + + *xmin = idxXid->xmin; + *xmax = idxXid->xmax; + + /* examine xmax */ + if (TransactionIdIsValid(*xmax)) { + TransactionIdStatus ts = HnswCheckXid(*xmax); + switch (ts) { + case XID_INPROGRESS: + if (TransactionIdEquals(*xmin, *xmax)) { + needCheckXmin = false; + } + break; + case XID_COMMITTED: + *xminCommitted = *xmaxCommitted = true; + needCheckXmin = false; + break; + case XID_ABORTED: + idxXid->xmax = InvalidTransactionId; + *xmax = InvalidTransactionId; + if (TransactionIdEquals(*xmin, *xmax)) { + /* xmin xmax aborted */ + idxXid->xmin = InvalidTransactionId; + *xmin = InvalidTransactionId; + needCheckXmin = false; + } + break; + } + } + + /* examine xmin */ + if (needCheckXmin) { + if (IndexItemIdIsFrozen(iid)) { + *xminCommitted = true; + } else if (TransactionIdIsValid(*xmin)) { + TransactionIdStatus ts = HnswCheckXid(*xmin); + switch (ts) { + case XID_INPROGRESS: + break; + case XID_COMMITTED: + *xminCommitted = true; + break; + case XID_ABORTED: + idxXid->xmin = InvalidTransactionId; + *xmin = InvalidTransactionId; + break; + } + } + } + + /* if there is no passed oldest_xmin, we will ues the current oldest_xmin */ + if (!TransactionIdIsValid(oldest_xmin)) { + if (isToast) { + GetOldestXminForUndo(&oldest_xmin); + } else { + oldest_xmin = u_sess->utils_cxt.RecentGlobalDataXmin; + } + } + /* we can't do bypass in hotstandby read mode, or there will be different between index scan and seq scan */ + if (RecoveryInProgress()) { + oldest_xmin = InvalidTransactionId; + } + + if (!TransactionIdIsValid(*xmin)) { + isDead = true; + } + /* before we mark the tuple as DEAD because of xmax, must comfirm that xmax has committed */ + if (*xmaxCommitted && TransactionIdPrecedes(*xmax, oldest_xmin)) { + isDead = true; + } + + /* before we mark the tuple as FROZEN, must comfirm that xmin has committed */ + if (IndexItemIdIsFrozen(iid)) { + *xmin = FrozenTransactionId; + } else if (*xminCommitted && TransactionIdPrecedes(*xmin, oldest_xmin)) { + IndexItemIdSetFrozen(iid); + *xmin = FrozenTransactionId; + } + + if (isDead) { + ItemIdMarkDead(iid); + *xmin = InvalidTransactionId; + *xmax = InvalidTransactionId; + *xminCommitted = *xmaxCommitted = false; + } + + return isDead; +} + +static bool VecItupEquals(IndexTuple itup1, IndexTuple itup2) +{ + if (itup1 == NULL || itup2 == NULL) { + return false; + } + if (IndexTupleSize(itup1) == 0 || IndexTupleSize(itup2) == 0) { + return false; + } + /* + * compare the binary directly. If these index tuples are formed from the + * same uheap tuple, they should be exactly the same. + */ + return memcmp(itup1, itup2, IndexTupleSize(itup1)) == 0; +} + +static bool VecVisibilityCheckCid(IndexScanDesc scan, IndexTuple itup, bool *needRecheck) +{ + VectorScanData *vs = VecGetScanData(scan); + Assert(vs != NULL); + + if (VecItupEquals((IndexTuple)vs->lastSelfModifiedItup, itup)) { + *needRecheck = false; + return false; /* tuples with same key and TID will only returned once */ + } + + /* save this index tuple as lastSelfModifiedItup */ + /* Step1: Check that the buffer space is large enough. */ + size_t maxItemSize = VecDefaultMaxItemSize(scan); + uint newSize = 0; + int multiSize = 2; + if (vs->lastSelfModifiedItup == NULL) { + newSize = IndexTupleSize(itup); + } else if (vs->lastSelfModifiedItupBufferSize < IndexTupleSize(itup)) { + newSize = MAX(vs->lastSelfModifiedItupBufferSize * multiSize, IndexTupleSize(itup)); + newSize = MIN(newSize, maxItemSize); + pfree(vs->lastSelfModifiedItup); + } + /* Step2: Extend when necessary. */ + if (newSize != 0) { + vs->lastSelfModifiedItup = (char*)palloc(newSize); + vs->lastSelfModifiedItupBufferSize = newSize; + } + /* Step3: Save the current IndexTuple. */ + errno_t rc = 0; + rc = memcpy_s(vs->lastSelfModifiedItup, maxItemSize, itup, IndexTupleSize(itup)); + securec_check(rc, "\0", "\0"); + + *needRecheck = true; + return true; /* treat as visible, but need recheck */ +} + +static bool VecXidSatisfiesMVCC(TransactionId xid, bool committed, Snapshot snapshot, Buffer buffer) +{ + TransactionIdStatus ignore; + + if (!TransactionIdIsValid(xid)) { + return false; /* invisible */ + } + if (xid == FrozenTransactionId) { + return true; /* frozen */ + } + + /* + * We can use snapshot's xmin/xmax as fast bypass after they become valid again. + * Currently, snapshot's csn and xmin/xmax may be inconsistent. The reavsn is + * that there is a problem with the cooperation of committing and subtransaction. + */ + + /* we can't tell visibility by snapshot's xmin/xmax alone, check snapshot */ + return XidVisibleInSnapshot(xid, snapshot, &ignore, (RecoveryInProgress() ? buffer : InvalidBuffer), NULL); +} + +static bool VecVisibilityCheckXid(TransactionId xmin, TransactionId xmax, bool xminCommitted, bool xmaxCommitted, + Snapshot snapshot, Buffer buffer, bool isUpsert) +{ + if (snapshot->satisfies == SNAPSHOT_DIRTY && isUpsert) { + bool xmaxVisible = xmaxCommitted || TransactionIdIsCurrentTransactionId(xmax); + if (xmaxVisible) { + return false; + } + return true; + } + + /* only support MVCC and NOW, ereport used to locate bug */ + if (snapshot->satisfies != SNAPSHOT_VERSION_MVCC && + snapshot->satisfies != SNAPSHOT_MVCC && snapshot->satisfies != SNAPSHOT_NOW) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported snapshot type %u for UBTree index.", snapshot->satisfies), + errhint("This kind of operation may not supported."))); + } + + /* handle snapshot MVCC */ + if (snapshot->satisfies == SNAPSHOT_VERSION_MVCC || snapshot->satisfies == SNAPSHOT_MVCC) { + if (VecXidSatisfiesMVCC(xmax, xmaxCommitted, snapshot, buffer)) { + return false; /* already deleted */ + } + if (!VecXidSatisfiesMVCC(xmin, xminCommitted, snapshot, buffer)) { + return false; /* have not inserted yet */ + } + } + + /* handle snapshot NOW */ + if (snapshot->satisfies == SNAPSHOT_NOW) { + return xminCommitted && !xmaxCommitted; + } + + return true; +} + +bool VecVisibilityCheck(IndexScanDesc scan, Page page, OffsetNumber offnum, bool *needRecheck) +{ + bool needVisibilityCheck = scan->xs_snapshot->satisfies != SNAPSHOT_ANY && + scan->xs_snapshot->satisfies != SNAPSHOT_TOAST; + TransactionId xmin, xmax; + bool xminCommitted = false; + bool xmaxCommitted = false; + bool isDead = VecItupGetXminXmax(page, offnum, InvalidTransactionId, + &xmin, &xmax, &xminCommitted, &xmaxCommitted, + RelationGetNamespace(scan->indexRelation) == PG_TOAST_NAMESPACE); + + if (needRecheck == NULL) { + *needRecheck = false; + } + + bool isVisible = !isDead; + if (needVisibilityCheck && !isDead) { + /* + * If this IndexTuple is not visible to the current Snapshot, try to get the next one. + * We're not going to tell heap to skip visibility check, because it doesn't cost a lot and we need heap + * to check the visibility with CID when snapshot's xid equals to xmin or xmax. + */ + if (scan->xs_snapshot->satisfies == SNAPSHOT_MVCC && + (TransactionIdIsCurrentTransactionId(xmin) || TransactionIdIsCurrentTransactionId(xmax))) { + ItemId iid = PageGetItemId(page, offnum); + IndexTuple tuple = (IndexTuple)PageGetItem(page, iid); + isVisible = VecVisibilityCheckCid(scan, tuple, needRecheck); /* need check cid */ + } else { + VectorScanData *vs = VecGetScanData(scan); + isVisible = VecVisibilityCheckXid(xmin, xmax, xminCommitted, xmaxCommitted, + scan->xs_snapshot, vs->buf, scan->isUpsert); + } + } + + return isVisible; +} diff --git a/contrib/datavec/src/vecindex.h b/contrib/datavec/src/vecindex.h new file mode 100644 index 0000000000000000000000000000000000000000..410d1d4878187f7e127113f19012308b3e224478 --- /dev/null +++ b/contrib/datavec/src/vecindex.h @@ -0,0 +1,23 @@ +#ifndef VECINDEX_H +#define VECINDEX_H + +#define MIN(A, B) ((B) < (A) ? (B) : (A)) +#define MAX(A, B) ((B) > (A) ? (B) : (A)) + +#define VecIndexTupleGetXid(itup) (((char*)(itup)) + HNSW_ELEMENT_TUPLE_SIZE(VARSIZE_ANY(&(itup)->data))) + +struct VectorScanData { + /* + * used in ustore only, indicate the last returned index tuple which is modified + * by current transaction. see VecVisibilityCheckCid() for more information. + */ + char *lastSelfModifiedItup; + uint16 lastSelfModifiedItupBufferSize; + Buffer buf; +}; + +bool VecItupGetXminXmax(Page page, OffsetNumber offnum, TransactionId oldest_xmin, TransactionId *xmin, + TransactionId *xmax, bool *xminCommitted, bool *xmaxCommitted, bool isToast); +bool VecVisibilityCheck(IndexScanDesc scan, Page page, OffsetNumber offnum, bool *needRecheck); + +#endif //VECINDEX_H diff --git a/contrib/datavec/src/vector.cpp b/contrib/datavec/src/vector.cpp index 4cb6b62f9c744c9bb4808515707426177c1bf021..66adc2e3c4ee4b7272d6537f8ccb895a76733680 100644 --- a/contrib/datavec/src/vector.cpp +++ b/contrib/datavec/src/vector.cpp @@ -19,6 +19,8 @@ #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/numeric.h" +#include "commands/extension.h" +#include "knl/knl_session.h" #include "vector.h" #if PG_VERSION_NUM >= 160000 @@ -39,8 +41,60 @@ #define VECTOR_TARGET_CLONES #endif +#if PG_VERSION_NUM < 150000 +#define MarkGUCPrefixReserved(x) EmitWarningsOnPlaceholders(x) +#endif + PG_MODULE_MAGIC; +uint32 datavec_index; +THR_LOCAL bool needInitialization = true; + +void set_extension_index(uint32 index) +{ + datavec_index = index; +} + +datavec_session_context* get_session_context() +{ + if (u_sess->attr.attr_common.extension_session_vars_array[datavec_index] == NULL) { + init_session_vars(); + } + return (datavec_session_context*)u_sess->attr.attr_common.extension_session_vars_array[datavec_index]; +} + +void init_session_vars(void) +{ + RepallocSessionVarsArrayIfNecessary(); + datavec_session_context* ctx = (datavec_session_context*)MemoryContextAllocZero(u_sess->self_mem_cxt, + sizeof(datavec_session_context)); + u_sess->attr.attr_common.extension_session_vars_array[datavec_index] = ctx; + + ctx->hnsw_ef_search = 0; + ctx->ivfflat_probes = 0; + + DefineCustomIntVariable("hnsw.ef_search", "Sets the size of the dynamic candidate list for search", + "Valid range is 1..1000.", &(get_session_context()->hnsw_ef_search), + HNSW_DEFAULT_EF_SEARCH, HNSW_MIN_EF_SEARCH, HNSW_MAX_EF_SEARCH, + PGC_USERSET, 0, NULL, NULL, NULL); + + MarkGUCPrefixReserved("hnsw"); + + DefineCustomIntVariable("ivfflat.probes", "Sets the number of probes", + "Valid range is 1..lists.", &(get_session_context()->ivfflat_probes), + IVFFLAT_DEFAULT_PROBES, IVFFLAT_MIN_LISTS, IVFFLAT_MAX_LISTS, + PGC_USERSET, 0, NULL, NULL, NULL); + + MarkGUCPrefixReserved("ivfflat"); +} + +void InitRelOptions() +{ + HnswInit(); + IvfflatInit(); + needInitialization = false; +} + /* * Initialize index options and variables */ @@ -48,10 +102,11 @@ PGDLLEXPORT void _PG_init(void); void _PG_init(void) { - BitvecInit(); - HalfvecInit(); - HnswInit(); - IvfflatInit(); + BitvecInit(); + HalfvecInit(); + if (needInitialization) { + InitRelOptions(); + } } /* diff --git a/contrib/datavec/src/vector.h b/contrib/datavec/src/vector.h index 1d7c60b4c22955e0f028a3f7f6d4aad367d45060..87f7a38197b3be984205d2f112d8ae4c882e8940 100644 --- a/contrib/datavec/src/vector.h +++ b/contrib/datavec/src/vector.h @@ -2,6 +2,7 @@ #define VECTOR_H #define VECTOR_MAX_DIM 16000 +#define MEM_INFO_NUM (1024 * 1024) #define VECTOR_SIZE(_dim) (offsetof(Vector, x) + sizeof(float)*(_dim)) #define DatumGetVector(x) ((Vector *) PG_DETOAST_DATUM(x)) @@ -22,6 +23,7 @@ void PrintVector(char *msg, Vector * vector); int vector_cmp_internal(Vector * a, Vector * b); void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std); int PlanCreateIndexWorkers(Relation heapRelation, IndexInfo *indexInfo); +void InitRelOptions(); extern "C" { PGDLLEXPORT Datum vector_in(PG_FUNCTION_ARGS); @@ -60,6 +62,17 @@ extern "C" { PGDLLEXPORT Datum vector_concat(PG_FUNCTION_ARGS); PGDLLEXPORT Datum halfvec_l2_normalize(PG_FUNCTION_ARGS); PGDLLEXPORT Datum sparsevec_l2_normalize(PG_FUNCTION_ARGS); + PGDLLEXPORT void set_extension_index(uint32 index); + PGDLLEXPORT void init_session_vars(void); } +typedef struct datavec_session_context { + int hnsw_ef_search; + int ivfflat_probes; +} datavec_session_context; + +extern uint32 datavec_index; +extern datavec_session_context* get_session_context(); +extern THR_LOCAL bool needInitialization; + #endif diff --git a/contrib/dolphin/expected/alter_function_test/alter_function.out b/contrib/dolphin/expected/alter_function_test/alter_function.out index 3a256079cd588a8935da2f050aa48635aee1d5a3..40d777b28e785b9612d704585cc5687f3cda86d2 100644 --- a/contrib/dolphin/expected/alter_function_test/alter_function.out +++ b/contrib/dolphin/expected/alter_function_test/alter_function.out @@ -74,6 +74,7 @@ end; $$ LANGUAGE PLPGSQL; alter FUNCTION f5 no sql; ERROR: more than one function named "f5" +alter FUNCTION f5() set query_dop = 2; create table t1 (a int); select f5(1); f5 diff --git a/contrib/dolphin/expected/ansi_quotes_test.out b/contrib/dolphin/expected/ansi_quotes_test.out index 45943b57ee4a00e11a6b7419f6fcfac17e8008bc..4fb15046b905ea85c68e8f637b3af0e24dedd23a 100644 --- a/contrib/dolphin/expected/ansi_quotes_test.out +++ b/contrib/dolphin/expected/ansi_quotes_test.out @@ -58,6 +58,7 @@ ERROR: syntax error at or near ""test_quotes_2"" LINE 1: CREATE TABLE "test_quotes_2" (a text); ^ CREATE TABLE test_quotes_2 (a text) compression = "pglz"; -- success +WARNING: The compressed relation you are using is an unofficial supported extended feature. -- test desc desc test_quotes_2; Field | Type | Null | Key | Default | Extra diff --git a/contrib/dolphin/expected/b_rowtype.out b/contrib/dolphin/expected/b_rowtype.out new file mode 100644 index 0000000000000000000000000000000000000000..d1db17ccdc2c47fefae4070afd2dbd20617ade39 --- /dev/null +++ b/contrib/dolphin/expected/b_rowtype.out @@ -0,0 +1,22 @@ +create schema b_rowtype; +create table t_Compare_Case0017(first_name varchar(100), last_name varchar(100)); +set behavior_compat_options='allow_procedure_compile_check'; +create table t_CurRowtype_PLObject_Case0017(first_name varchar(100), last_name varchar(100)); +insert into t_CurRowtype_PLObject_Case0017 values('Jason','Statham'); +create trigger tri_CurRowtype_PLObject_Case0017 before insert on t_CurRowtype_PLObject_Case0017 for each row +declare + cursor cur_1 is select * from t_CurRowtype_PLObject_Case0017; + source cur_1%rowtype; +begin + source.first_name:=new.first_name; + source.last_name:=new.last_name; + insert into t_Compare_Case0017 values (source.first_name,source.last_name); + return new; +end; +/ +insert into t_CurRowtype_PLObject_Case0017 values('Jason_New','Statham_New'); +reset behavior_compat_options; +drop trigger tri_CurRowtype_PLObject_Case0017; +drop table t_Compare_Case0017; +drop table t_CurRowtype_PLObject_Case0017; +drop schema b_rowtype cascade; diff --git a/contrib/dolphin/expected/builtin_funcs/b_compatibility_substr_func.out b/contrib/dolphin/expected/builtin_funcs/b_compatibility_substr_func.out index 8c3cf790f7a1fa2a7cc1105cd83b1a6d95b2bb0c..60b2cdef73dc2e7f3f5beaf76689ba859883d177 100644 --- a/contrib/dolphin/expected/builtin_funcs/b_compatibility_substr_func.out +++ b/contrib/dolphin/expected/builtin_funcs/b_compatibility_substr_func.out @@ -390,6 +390,113 @@ select c1, mid(`bit1`, 2, 2), mid(`bit8`, 2, 2), mid(`bit15`, 2, 2), mid(`bit64` 3 | | | \000 | om (3 rows) +-- test mid pos、length is bit type +select c1, mid(`int1`, b'11'), mid(`uint1`, b'11'), mid(`int2`, b'11'), mid(`uint2`, b'11'), mid(`int4`, b'11'), mid(`uint4`, b'11'), mid(`int8`, b'11'), mid(`uint8`, b'11'), mid(`float4`, b'11'), mid(`float8`, b'11'), mid(`boolean`, b'11') from t_number order by c1; + c1 | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid +----+-----+-----+------+-----+-----------+----------+--------------------+--------------------+--------+-----------------+----- + 1 | | | | | | | | | | | + 2 | 7 | 5 | 767 | 535 | 47483647 | 94967295 | 23372036854775807 | 446744073709551615 | 40282 | 79769313486231 | + 3 | 27 | | 2768 | | 147483648 | | 223372036854775808 | | 234.57 | 002345.78456892 | +(3 rows) + +select c1, mid(`int1`, b'11', 2), mid(`uint1`, b'11', 2), mid(`int2`, b'11', 2), mid(`uint2`, b'11', 2), mid(`int4`, b'11', 2), mid(`uint4`, b'11', 2), mid(`int8`, b'11', 2), mid(`uint8`, b'11', 2), mid(`float4`, b'11', 2), mid(`float8`, b'11', 2), mid(`boolean`, b'11', 2) from t_number order by c1; + c1 | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + 1 | | | | | | | | | | | + 2 | 7 | 5 | 76 | 53 | 47 | 94 | 23 | 44 | 40 | 79 | + 3 | 27 | | 27 | | 14 | | 22 | | 23 | 00 | +(3 rows) + +select c1, mid(`int1`, 2, b'11'), mid(`uint1`, 2, b'11'), mid(`int2`, 2, b'11'), mid(`uint2`, 2, b'11'), mid(`int4`, 2, b'11'), mid(`uint4`, 2, b'11'), mid(`int8`, 2, b'11'), mid(`uint8`, 2, b'11'), mid(`float4`, 2, b'11'), mid(`float8`, 2, b'11'), mid(`boolean`, 2, b'11') from t_number order by c1; + c1 | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + 1 | | | | | | | | | | | + 2 | 27 | 55 | 276 | 553 | 147 | 294 | 223 | 844 | .40 | .79 | + 3 | 127 | | 327 | | 214 | | 922 | | 123 | 100 | +(3 rows) + +select c1, mid(`int1`, b'11', b'11'), mid(`uint1`, b'11', b'11'), mid(`int2`, b'11', b'11'), mid(`uint2`, b'11', b'11'), mid(`int4`, b'11', b'11'), mid(`uint4`, b'11', b'11'), mid(`int8`, b'11', b'11'), mid(`uint8`, b'11', b'11'), mid(`float4`, b'11', b'11'), mid(`float8`, b'11', b'11'), mid(`boolean`, b'11', b'11') from t_number order by c1; + c1 | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid | mid +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + 1 | | | | | | | | | | | + 2 | 7 | 5 | 767 | 535 | 474 | 949 | 233 | 446 | 402 | 797 | + 3 | 27 | | 276 | | 147 | | 223 | | 234 | 002 | +(3 rows) + +set dolphin.sql_mode = 'sql_mode_strict,sql_mode_full_group,pipes_as_concat,ansi_quotes,no_zero_date,pad_char_to_full_length,auto_recompile_function,error_for_division_by_zero'; -- with pad_char_to_full_length +select c1, mid(`char`, b'11'), mid(`varchar`, b'11'), mid(`binary`, b'11'), mid(`varbinary`, b'11'), mid(`text`, b'11') from t_str order by c1; + c1 | mid | mid | mid | mid | mid +----+---------------------------------------------------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+---------------------- + 1 | .345*67-89 | .345*67-89 | .345*67-89\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | .345*67-89 | .345*67-89 + 2 | day is a good day. | day is a good day. | day is a good day. \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | day is a good day. | day is a good day. + 3 | 桃红桃映脸 | 桃红桃映脸 | \270\346\230\240\346\241\203\347\272\242\346\241\203\346\230\240\350\204\270\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | \270\346\230\240\346\241\203\347\272\242\346\241\203\346\230\240\350\204\270 | 桃红桃映脸 +(3 rows) + +set dolphin.sql_mode = 'sql_mode_strict,sql_mode_full_group,pipes_as_concat,ansi_quotes,no_zero_date,auto_recompile_function,error_for_division_by_zero'; -- without pad_char_to_full_length +select c1, mid(`char`, b'11'), mid(`varchar`, b'11'), mid(`binary`, b'11'), mid(`varbinary`, b'11'), mid(`text`, b'11') from t_str order by c1; + c1 | mid | mid | mid | mid | mid +----+--------------------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+---------------------- + 1 | .345*67-89 | .345*67-89 | .345*67-89\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | .345*67-89 | .345*67-89 + 2 | day is a good day. | day is a good day. | day is a good day. \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | day is a good day. | day is a good day. + 3 | 桃红桃映脸 | 桃红桃映脸 | \270\346\230\240\346\241\203\347\272\242\346\241\203\346\230\240\350\204\270\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 | \270\346\230\240\346\241\203\347\272\242\346\241\203\346\230\240\350\204\270 | 桃红桃映脸 +(3 rows) + +select c1, mid(`char`, b'11', 4), mid(`varchar`, b'11', 4), mid(`binary`, b'11', 4), mid(`varbinary`, b'11', 4), mid(`text`, b'11', 4) from t_str order by c1; + c1 | mid | mid | mid | mid | mid +----+----------+----------+------------------+------------------+---------- + 1 | .345 | .345 | .345 | .345 | .345 + 2 | day | day | day | day | day + 3 | 桃红桃映 | 桃红桃映 | \270\346\230\240 | \270\346\230\240 | 桃红桃映 +(3 rows) + +select c1, mid(`char`, 3, b'100'), mid(`varchar`, 3, b'100'), mid(`binary`, 3, b'100'), mid(`varbinary`, 3, b'100'), mid(`text`, 3, b'100') from t_str order by c1; + c1 | mid | mid | mid | mid | mid +----+----------+----------+------------------+------------------+---------- + 1 | .345 | .345 | .345 | .345 | .345 + 2 | day | day | day | day | day + 3 | 桃红桃映 | 桃红桃映 | \270\346\230\240 | \270\346\230\240 | 桃红桃映 +(3 rows) + +select c1, mid(`char`, b'11', b'100'), mid(`varchar`, b'11', b'100'), mid(`binary`, b'11', b'100'), mid(`varbinary`, b'11', b'100'), mid(`text`, b'11', b'100') from t_str order by c1; + c1 | mid | mid | mid | mid | mid +----+----------+----------+------------------+------------------+---------- + 1 | .345 | .345 | .345 | .345 | .345 + 2 | day | day | day | day | day + 3 | 桃红桃映 | 桃红桃映 | \270\346\230\240 | \270\346\230\240 | 桃红桃映 +(3 rows) + +select c1, mid(`bit1`, b'10'), mid(`bit8`, b'10'), mid(`bit15`, b'10'), mid(`bit64`, b'10') from t_bit order by c1; + c1 | mid | mid | mid | mid +----+-----+-----+------+------------ + 1 | | | E | ome\000one + 2 | | | W | Someone + 3 | | | \000 | omeone\000 +(3 rows) + +select c1, mid(`bit1`, b'10', 3), mid(`bit8`, b'10', 3), mid(`bit15`, b'10', 3), mid(`bit64`, b'10', 3) from t_bit order by c1; + c1 | mid | mid | mid | mid +----+-----+-----+------+----- + 1 | | | E | ome + 2 | | | W | Som + 3 | | | \000 | ome +(3 rows) + +select c1, mid(`bit1`, 2, b'11'), mid(`bit8`, 2, b'11'), mid(`bit15`, 2, b'11'), mid(`bit64`, 2, b'11') from t_bit order by c1; + c1 | mid | mid | mid | mid +----+-----+-----+------+----- + 1 | | | E | ome + 2 | | | W | Som + 3 | | | \000 | ome +(3 rows) + +select c1, mid(`bit1`, b'10', b'11'), mid(`bit8`, b'10', b'11'), mid(`bit15`, b'10', b'11'), mid(`bit64`, b'10', b'11') from t_bit order by c1; + c1 | mid | mid | mid | mid +----+-----+-----+------+----- + 1 | | | E | ome + 2 | | | W | Som + 3 | | | \000 | ome +(3 rows) + drop table t_number; drop table t_bit; drop table t_str; diff --git a/contrib/dolphin/expected/builtin_funcs/db_b_format.out b/contrib/dolphin/expected/builtin_funcs/db_b_format.out index d25e9a68d88f4827ea5d9cf74da10f8ec794b20d..32d281adb8ed2b556df332128d2ed499ca081809 100644 --- a/contrib/dolphin/expected/builtin_funcs/db_b_format.out +++ b/contrib/dolphin/expected/builtin_funcs/db_b_format.out @@ -478,6 +478,79 @@ select format(null, null, null); (1 row) +-- test overflow +select format(123123.456,100000000000); + format +------------------------------------------ + 123,123.45600000000000000000000000000000 +(1 row) + +select format(123123.456,1000000000000); + format +--------- + 123,123 +(1 row) + +select format(123123.456,10000000000000); + format +------------------------------------------ + 123,123.45600000000000000000000000000000 +(1 row) + +select format(123123.456,545634633746483465436546345635436587463); +WARNING: bigint out of range +CONTEXT: referenced column: format + format +--------- + 123,123 +(1 row) + +select format(123123.456,'513513413546587468514351345435413'); +WARNING: value "513513413546587468514351345435413" is out of range for type bigint +LINE 1: select format(123123.456,'513513413546587468514351345435413'... + ^ +CONTEXT: referenced column: format + format +--------- + 123,123 +(1 row) + +select format(123123.456,100000000000,'de_DE'); + format +------------------------------------------ + 123.123,45600000000000000000000000000000 +(1 row) + +select format(123123.456,1000000000000,'de_DE'); + format +--------- + 123.123 +(1 row) + +select format(123123.456,10000000000000,'de_DE'); + format +------------------------------------------ + 123.123,45600000000000000000000000000000 +(1 row) + +select format(123123.456,545634633746483465436546345635436587463,'de_DE'); +WARNING: bigint out of range +CONTEXT: referenced column: format + format +--------- + 123.123 +(1 row) + +select format(123123.456,'513513413546587468514351345435413','de_DE'); +WARNING: value "513513413546587468514351345435413" is out of range for type bigint +LINE 1: select format(123123.456,'513513413546587468514351345435413'... + ^ +CONTEXT: referenced column: format + format +--------- + 123.123 +(1 row) + -- test for setting b_compatibility_mode back to false set dolphin.b_compatibility_mode = 0; select format(1234.456, 2); diff --git a/contrib/dolphin/expected/case_sensitive_test/cluster.out b/contrib/dolphin/expected/case_sensitive_test/cluster.out index 9486faced0be288e73a7fdace96c8a39df43483e..bda6fdd0e3d372579f743358ce5593545368b126 100644 --- a/contrib/dolphin/expected/case_sensitive_test/cluster.out +++ b/contrib/dolphin/expected/case_sensitive_test/cluster.out @@ -60,7 +60,7 @@ INSERT INTO Clstr_tst (b, c) VALUES (8, 'ocho'); INSERT INTO Clstr_tst (b, c, d) VALUES (6, 'seis', repeat('xyzzy', 100000)); CLUSTER Clstr_tst_c ON Clstr_tst; SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | @@ -97,7 +97,7 @@ SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; (32 rows) SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | @@ -134,7 +134,7 @@ SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a; (32 rows) SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY b; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 20 | 1 | uno | | 11 | 2 | dos | | @@ -171,7 +171,7 @@ SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY b; (32 rows) SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY c; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 10 | 14 | catorce | | 18 | 5 | cinco | | @@ -210,7 +210,7 @@ SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY c; -- Verify that inheritance link still works -- INSERT INTO Clstr_tst_inh VALUES (0, 100, 'in child table'); SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | diff --git a/contrib/dolphin/expected/case_sensitive_test/schema_test.out b/contrib/dolphin/expected/case_sensitive_test/schema_test.out index 335d0f7343dad07f84924c857788c54af75a9f7e..d14c956438a13e918e535265def0d2cfd7ca4521 100644 --- a/contrib/dolphin/expected/case_sensitive_test/schema_test.out +++ b/contrib/dolphin/expected/case_sensitive_test/schema_test.out @@ -46,7 +46,8 @@ WARNING: TEST is not a valid encoding name. default value set --? test_2 | .* --? test_3 | .* --? test_temp | .* -(25 rows) +--? xmltype | .* +(26 rows) ALTER SCHEMA test_1 WITHOUT BLOCKCHAIN; ALTER SCHEMA Test_1 WITHOUT BLOCKCHAIN; @@ -91,7 +92,8 @@ ALTER SCHEMA Test_1_BAK OWNER TO Test_Schema_User; --? test_2 | .* --? test_3 | .* --? test_temp | .* -(25 rows) +--? xmltype | .* +(26 rows) SET SEARCH_PATH TO test_1, Test1; SHOW SEARCH_PATH; @@ -143,7 +145,8 @@ DROP SCHEMA test_1_bak, Test_1_BAK; --? test_2 | .* --? test_3 | .* --? test_temp | .* -(23 rows) +--? xmltype | .* +(24 rows) -- dolphin_any_name DROP SCHEMA IF EXISTS Test_Schema_User CASCADE; @@ -175,7 +178,8 @@ CREATE SCHEMA AUTHORIZATION Test_Schema_User; --? test_2 | .* --? test_3 | .* --? test_temp | .* -(23 rows) +--? xmltype | .* +(24 rows) -- dolphin_qualified_name CREATE TABLE test_1_table (a int); diff --git a/contrib/dolphin/expected/case_sensitive_test/trigger.out b/contrib/dolphin/expected/case_sensitive_test/trigger.out new file mode 100644 index 0000000000000000000000000000000000000000..9e23729948296d48dc93acba4d0847aaf4604172 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/trigger.out @@ -0,0 +1,43 @@ +\c table_name_test_db; +set dolphin.lower_case_table_names to 0; +create table t1(c1 int); +create table t2(c1 int); +create trigger tg_case_1 before insert on t1 for each row update t2 set c1 = c1 + 1; +create trigger TG_CASE_1 before insert on t1 for each row update t2 set c1 = c1 + 1; +create schema s1; +create schema S1; +create table s1.t1(c1 int); +create table s1.t2(c1 int); +create table S1.t1(c1 int); +create table S1.t2(c1 int); +create trigger s1.tg_case_2 before insert on s1.t1 for each row update s1.t2 set c1 = c1 + 1; +create trigger s1.TG_CASE_2 before insert on s1.t1 for each row update s1.t2 set c1 = c1 + 1; +create trigger S1.tg_case_3 before insert on S1.t1 for each row update S1.t2 set c1 = c1 + 1; +create trigger S1.TG_CASE_3 before insert on S1.t1 for each row update S1.t2 set c1 = c1 + 1; +select tgname from pg_trigger where lower(tgname) like 'tg_case_%' order by tgname asc; + tgname +----------- + TG_CASE_1 + TG_CASE_2 + TG_CASE_3 + tg_case_1 + tg_case_2 + tg_case_3 +(6 rows) + +drop trigger tg_case_1; +drop trigger TG_CASE_1; +drop trigger s1.tg_case_2; +drop trigger s1.TG_CASE_2; +drop trigger S1.tg_case_3; +drop trigger S1.TG_CASE_3; +drop table t1; +drop table t2; +drop schema s1 cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table s1.t1 +drop cascades to table s1.t2 +drop schema S1 cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table "S1".t1 +drop cascades to table "S1".t2 diff --git a/contrib/dolphin/expected/case_sensitive_test_backquote/cluster.out b/contrib/dolphin/expected/case_sensitive_test_backquote/cluster.out index 7c8f4fff7b8d4a4163da3e140b99a11f3364e235..6d77d64364fdb7ad155150885f134ee232b0383d 100644 --- a/contrib/dolphin/expected/case_sensitive_test_backquote/cluster.out +++ b/contrib/dolphin/expected/case_sensitive_test_backquote/cluster.out @@ -60,7 +60,7 @@ INSERT INTO `Clstr_tst` (`b`, `c`) VALUES (8, 'ocho'); INSERT INTO `Clstr_tst` (`b`, `c`, `d`) VALUES (6, 'seis', repeat('xyzzy', 100000)); CLUSTER Clstr_tst_c ON `Clstr_tst`; SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY `a`, `b`, `c`; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | @@ -97,7 +97,7 @@ SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY (32 rows) SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY `a`; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | @@ -134,7 +134,7 @@ SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY (32 rows) SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY `b`; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 20 | 1 | uno | | 11 | 2 | dos | | @@ -171,7 +171,7 @@ SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY (32 rows) SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY `c`; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 10 | 14 | catorce | | 18 | 5 | cinco | | @@ -210,7 +210,7 @@ SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY -- Verify that inheritance link still works -- INSERT INTO Clstr_tst_inh VALUES (0, 100, 'in child table'); SELECT `a`,`b`,`c`,substring(`d` for 30), length(`d`) from `Clstr_tst` ORDER BY `a`, `b`, `c`; - a | b | c | substring | length + a | b | c | substr | length ----+----+---------------+--------------------------------+-------- 1 | 11 | once | | 2 | 10 | diez | | diff --git a/contrib/dolphin/expected/create_function_test/b_compat_create_func.out b/contrib/dolphin/expected/create_function_test/b_compat_create_func.out index 6a933372dee84851ef610579495031f023ebadc9..7e9d337b5a15ba0e7e766f51d1c71492f058be5d 100644 --- a/contrib/dolphin/expected/create_function_test/b_compat_create_func.out +++ b/contrib/dolphin/expected/create_function_test/b_compat_create_func.out @@ -726,6 +726,46 @@ select test_function_030('aaa') is null; drop table if exists test_table_030; drop function if exists test_function_030; +CREATE PROCEDURE p_log_job_info_bak() +AS DECLARE +begin + raise notice '1'; + commit; +END; +/ +create procedure p_gen_rpt_init_self_recovery() +AS +DECLARE + temp_wtg_id BIGINT; + CURSOR crs_ar FOR (SELECT wtg_id + FROM temp_init_sr_previous + ORDER BY 1); +BEGIN + CREATE TEMPORARY TABLE temp_init_sr_previous(wtg_id BIGINT); + OPEN crs_ar; +ar_loop:LOOP + FETCH crs_ar INTO temp_wtg_id; + IF NOT FOUND THEN + leave ar_loop; + END IF; + END LOOP; + CLOSE crs_ar; + DROP TEMPORARY TABLE temp_init_sr_previous; + + CALL p_log_job_info_bak(); +END; +/ +call p_gen_rpt_init_self_recovery(); +NOTICE: 1 +CONTEXT: SQL statement "CALL p_log_job_info_bak()" +PL/pgSQL function p_gen_rpt_init_self_recovery() line 18 at PERFORM + p_gen_rpt_init_self_recovery +------------------------------ + +(1 row) + +drop procedure p_log_job_info_bak; +DROP PROCEDURE p_gen_rpt_init_self_recovery; -- expect error: there is no parameter $1, other error is wrong!!! select :lable; ERROR: there is no parameter $1 diff --git a/contrib/dolphin/expected/create_function_test/m_type_create_proc.out b/contrib/dolphin/expected/create_function_test/m_type_create_proc.out index ffbbd71eb7a81b3e33a9efe062b62004a98825b5..9c0804a59117e0d7b2b711d2f145cc64241c8162 100644 --- a/contrib/dolphin/expected/create_function_test/m_type_create_proc.out +++ b/contrib/dolphin/expected/create_function_test/m_type_create_proc.out @@ -500,6 +500,9 @@ set @x2=0; set @x3=0; set @x4=0; call proc_continue_sqlexception(); +WARNING: The compressed relation you are using is an unofficial supported extended feature. +CONTEXT: SQL statement "create table t_rowcompress_pglz_compresslevel(id int) with (compresstype=1,compress_level=2)" +PL/pgSQL function proc_continue_sqlexception() line 6 at SQL statement proc_continue_sqlexception ---------------------------- diff --git a/contrib/dolphin/expected/db_b_new_gram_test.out b/contrib/dolphin/expected/db_b_new_gram_test.out index 22aadd3e84b4f56da1f0b4321510226921229bcb..da09cc6fca601b589ba5375cb12cde85a290ee09 100644 --- a/contrib/dolphin/expected/db_b_new_gram_test.out +++ b/contrib/dolphin/expected/db_b_new_gram_test.out @@ -18,6 +18,7 @@ CREATE TABLE IF NOT EXISTS test_engine_type_table2_1 OF test_engine_type2_1 engi CREATE TABLE test_engine_as engine = InnoDB as select a from test_engine_1; -- CREATE TABLE COMPRESSION test CREATE TABLE test_compression_1_pglz (a int) COMPRESSION = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_1_pglz Table "db_b_new_gram_test.test_compression_1_pglz" Column | Type | Modifiers | Storage | Stats target | Description @@ -27,6 +28,7 @@ Has OIDs: no Options: orientation=row, compresstype=1 CREATE TABLE IF NOT EXISTS test_compression_create_2_pglz (a int) COMPRESSION = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_create_2_pglz Table "db_b_new_gram_test.test_compression_create_2_pglz" Column | Type | Modifiers | Storage | Stats target | Description @@ -36,6 +38,7 @@ Has OIDs: no Options: orientation=row, compresstype=1 CREATE TABLE test_compression_type_table_1_pglz OF test_engine_type1 COMPRESSION = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_type_table_1_pglz Table "db_b_new_gram_test.test_compression_type_table_1_pglz" Column | Type | Modifiers | Storage | Stats target | Description @@ -47,6 +50,7 @@ Has OIDs: no Options: orientation=row, compresstype=1 CREATE TABLE IF NOT EXISTS test_compression_create_type_table_2_pglz OF test_engine_type2 COMPRESSION = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_create_type_table_2_pglz Table "db_b_new_gram_test.test_compression_create_type_table_2_pglz" Column | Type | Modifiers | Storage | Stats target | Description @@ -58,6 +62,7 @@ Has OIDs: no Options: orientation=row, compresstype=1 CREATE TABLE test_compression_as_pglz COMPRESSION = pglz as select a from test_compression_1_pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_as_pglz Table "db_b_new_gram_test.test_compression_as_pglz" Column | Type | Modifiers | Storage | Stats target | Description @@ -67,6 +72,7 @@ Has OIDs: no Options: orientation=row, compresstype=1 CREATE TABLE test_compression_1_zstd (a int) COMPRESSION = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_1_zstd Table "db_b_new_gram_test.test_compression_1_zstd" Column | Type | Modifiers | Storage | Stats target | Description @@ -76,6 +82,7 @@ Has OIDs: no Options: orientation=row, compresstype=2 CREATE TABLE IF NOT EXISTS test_compression_create_2_zstd (a int) COMPRESSION = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_create_2_zstd Table "db_b_new_gram_test.test_compression_create_2_zstd" Column | Type | Modifiers | Storage | Stats target | Description @@ -85,6 +92,7 @@ Has OIDs: no Options: orientation=row, compresstype=2 CREATE TABLE test_compression_type_table_1_zstd OF test_engine_type1 COMPRESSION = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_type_table_1_zstd Table "db_b_new_gram_test.test_compression_type_table_1_zstd" Column | Type | Modifiers | Storage | Stats target | Description @@ -96,6 +104,7 @@ Has OIDs: no Options: orientation=row, compresstype=2 CREATE TABLE IF NOT EXISTS test_compression_create_type_table_2_zstd OF test_engine_type2 COMPRESSION = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_create_type_table_2_zstd Table "db_b_new_gram_test.test_compression_create_type_table_2_zstd" Column | Type | Modifiers | Storage | Stats target | Description @@ -107,6 +116,7 @@ Has OIDs: no Options: orientation=row, compresstype=2 CREATE TABLE test_compression_as_zstd COMPRESSION = zstd as select a from test_compression_1_zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. \d+ test_compression_as_zstd Table "db_b_new_gram_test.test_compression_as_zstd" Column | Type | Modifiers | Storage | Stats target | Description @@ -1404,4 +1414,45 @@ explain (costs off) select count(a) from t1 ignore index(bmu); explain (costs off) select count(a) from t1 ignore index(bm); ERROR: index not exists in relation t1 -drop table t1; \ No newline at end of file +-- with rollup +create table table_json_a(SITE_NAME_I18N json); +insert into table_json_a values('{"i18nValue": {"en_US": "测试字符串-en", "es_ES": "测试字符串01-es", "ja_JP": "PDC测试字符串01-jp", "zh_CN": "PDC测试字符串01-zh"}, "defaultValue": "PDC测试字符串01"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001-大熊猫-EN", "es_ES": "", "ja_JP": "", "zh_CN": ""}, "defaultValue": "WF001-大熊猫"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001-10-us", "es_ES": "WF001-10-es", "ja_JP": "WF001-10-jp", "zh_CN": "WF001-10-cn"}, "defaultValue": "WF001-10"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001一期-en", "es_ES": "WF001一期-ES", "ja_JP": "WF001一期-JP", "zh_CN": "WF001一期-zh"}, "defaultValue": "WF001一期"}'); +CREATE TABLE table_json_b (name_i18n json); +insert into table_json_b values('{"i18nValue": {"en_US": "测试字符串-en", "es_ES": "测试字符串01-es", "ja_JP": "PDC测试字符串01-jp", "zh_CN": "PDC测试字符串01-zh"}, "defaultValue": "PDC测试字符串01"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001-大熊猫-EN", "es_ES": "", "ja_JP": "", "zh_CN": ""}, "defaultValue": "WF001-大熊猫"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001-10-us", "es_ES": "WF001-10-es", "ja_JP": "WF001-10-jp", "zh_CN": "WF001-10-cn"}, "defaultValue": "WF001-10"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001一期-en", "es_ES": "WF001一期-ES", "ja_JP": "WF001一期-JP", "zh_CN": "WF001一期-zh"}, "defaultValue": "WF001一期"}'); +select count(*) from table_json_a,table_json_b group by + coalesce(table_json_b.NAME_I18N->>'$.i18nValue.zh_CN', table_json_b.NAME_I18N->>'$.defaultValue'), + coalesce(table_json_a.SITE_NAME_I18N->>'$.i18nValue.zh_CN', table_json_a.SITE_NAME_I18N->>'$.defaultValue') with rollup; + count +------- + 1 + 1 + 1 + 1 + 4 + 1 + 1 + 1 + 1 + 4 + 1 + 1 + 1 + 1 + 4 + 1 + 1 + 1 + 1 + 4 + 16 +(21 rows) + +drop table table_json_a; +drop table table_json_b; +drop table t1; diff --git a/contrib/dolphin/expected/db_b_plpgsql_test.out b/contrib/dolphin/expected/db_b_plpgsql_test.out index b27a859bb9fe0b817ce5b95592aa6a41601ad2cc..18d6b6b2f33e3aa7ecec50221f74fc479dd808bb 100644 --- a/contrib/dolphin/expected/db_b_plpgsql_test.out +++ b/contrib/dolphin/expected/db_b_plpgsql_test.out @@ -171,6 +171,24 @@ call proc_abort_050_02(); ERROR: only support commit/rollback transaction statements. HINT: Use a BEGIN block with an EXCEPTION clause instead of begin/end transaction. CONTEXT: PL/pgSQL function proc_abort_050_02() line 3 at SQL statement +delimiter // +create or replace procedure test_set(out res int) +begin +declare a int; +declare b int; +declare c int; +set a=1, b=2, c=3; +set res=a+b+c; +end; +// +delimiter ; +call test_set(@res); + res +----- + 6 +(1 row) + +drop procedure test_set; drop schema db_b_plpgsql_test cascade; NOTICE: drop cascades to 9 other objects DETAIL: drop cascades to table tb_b_grammar_0038 diff --git a/contrib/dolphin/expected/foreign_key_checks_test.out b/contrib/dolphin/expected/foreign_key_checks_test.out new file mode 100644 index 0000000000000000000000000000000000000000..46fa3e9b5fa6014b87743f189ceb838e59ab6a0b --- /dev/null +++ b/contrib/dolphin/expected/foreign_key_checks_test.out @@ -0,0 +1,57 @@ +create schema foreign_key_checks_test; +set current_schema to 'foreign_key_checks_test'; +-- test FOREIGN_KEY_CHECKS +create table parent_table(id INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "parent_table_pkey" for table "parent_table" +CREATE TABLE child_table( +id INT PRIMARY KEY, +parent_id INT, +FOREIGN KEY (parent_id) REFERENCES parent_table(id) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "child_table_pkey" for table "child_table" +insert into parent_table values (1),(2),(3); +insert into child_table values (11, 1); +insert into child_table values (15, 5); -- error expectly +ERROR: insert or update on table "child_table" violates foreign key constraint "child_table_parent_id_fkey" +DETAIL: Key (parent_id)=(5) is not present in table "parent_table". +SET FOREIGN_KEY_CHECKS=0; +insert into child_table values (15, 5); -- success expectly +SET FOREIGN_KEY_CHECKS=1; +update child_table set parent_id = 6 where parent_id = 1; -- error expectly +ERROR: insert or update on table "child_table" violates foreign key constraint "child_table_parent_id_fkey" +DETAIL: Key (parent_id)=(6) is not present in table "parent_table". +SET FOREIGN_KEY_CHECKS=0; +update child_table set parent_id = 6 where parent_id = 1; -- success expectly +drop table child_table; +drop table parent_table; +SET FOREIGN_KEY_CHECKS=1; +create table parent_table(id INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "parent_table_pkey" for table "parent_table" +CREATE TABLE child_table( +id INT PRIMARY KEY, +parent_id INT, +FOREIGN KEY (parent_id) REFERENCES parent_table(id) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "child_table_pkey" for table "child_table" +insert into parent_table values (1),(2),(3); +insert into child_table values (11, 1); +delete from parent_table where id = 1; --error expectly +ERROR: update or delete on table "parent_table" violates foreign key constraint "child_table_parent_id_fkey" on table "child_table" +DETAIL: Key (id)=(1) is still referenced from table "child_table". +SET FOREIGN_KEY_CHECKS=0; +delete from parent_table where id = 1; --success expectly +SET FOREIGN_KEY_CHECKS=1; +alter table parent_table drop column id; --error expectly +ERROR: must have at least one column +SET FOREIGN_KEY_CHECKS=0; +alter table parent_table drop column id; --error expectly +ERROR: must have at least one column +SET FOREIGN_KEY_CHECKS=1; +drop table parent_table; -- error expectly +ERROR: cannot drop table parent_table because other objects depend on it +DETAIL: constraint child_table_parent_id_fkey on table child_table depends on table parent_table +HINT: Use DROP ... CASCADE to drop the dependent objects too. +drop table child_table; +drop table parent_table; -- success expectly +drop schema foreign_key_checks_test cascade; +reset current_schema; diff --git a/contrib/dolphin/expected/function_type_test.out b/contrib/dolphin/expected/function_type_test.out index f134a3b3d1ccd0e3c86f5469341b564b3a2fdf39..1b7719c9d4eb29180f13b3d2238fee74e10bb34e 100644 --- a/contrib/dolphin/expected/function_type_test.out +++ b/contrib/dolphin/expected/function_type_test.out @@ -198,7 +198,7 @@ CONTEXT: referenced column: uint8and SQL function "uint8and" statement 1 bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and | bit_and ---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+------------------------------------------------------------------+---------+----------+---------+---------+----------------+----------------+----------------+----------------+---------+---------+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------+--------------+--------------+--------------+--------------+---------+---------+---------+--------- - 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000000000000000000000000000000000000000000000000000111 | 1 | 20230205 | 191050 | 191050 | 20230205191050 | 20230205191050 | 20230205191050 | 20230205191050 | 2023 | 1 | 1 | \x312e3233610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | \x312e323361 | \x312e323361 | \x312e323361 | \x312e323361 | \x312e323361 | 1 | 1 | 5 | 0 + 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000000000000000000000000000000000000000000000000000111 | 1 | 20230205 | 191050 | 191050 | 20230205191050 | 20230205191050 | 20230205191050 | 20230205191050 | 2023 | 1 | 1 | \x312e3233610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | \x312e323361 | \x312e323361 | \x312e323361 | \x312e323361 | \x312e323361 | 1 | 1 | 5 | 0 (1 row) create table test_bit_and_1(c uint8); diff --git a/contrib/dolphin/expected/ignore_keyword_list.out b/contrib/dolphin/expected/ignore_keyword_list.out index 8e06defea33bc124ff8056f9ddd0874dd68329d9..d1c304b2269837a9e51d2e3dc2eb5488b5094fa0 100644 --- a/contrib/dolphin/expected/ignore_keyword_list.out +++ b/contrib/dolphin/expected/ignore_keyword_list.out @@ -1,7 +1,7 @@ create schema ignore_keyword_list; set current_schema to 'ignore_keyword_list'; select 1 interval; --error -ERROR: syntax error at or near "interval" +ERROR: syntax error at or near "interval;" LINE 1: select 1 interval; ^ set disable_keyword_options = 'interval'; @@ -22,7 +22,22 @@ select 1 interval; --ok reset disable_keyword_options; select 1 interval; --error -ERROR: syntax error at or near "interval" +ERROR: syntax error at or near "interval;" LINE 1: select 1 interval; ^ +create table t1 (binary int); +ERROR: syntax error at or near "binary" +LINE 1: create table t1 (binary int); + ^ +create table t2 (prior int); +ERROR: syntax error at or near "prior" +LINE 1: create table t2 (prior int); + ^ +set disable_keyword_options ='prior,binary'; +create table t1 (binary int); +create table t2 (prior int); +reset current_schema; drop schema ignore_keyword_list cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table ignore_keyword_list.t1 +drop cascades to table ignore_keyword_list.t2 diff --git a/contrib/dolphin/expected/interval_expr_unit.out b/contrib/dolphin/expected/interval_expr_unit.out index ef6ba7a77c3914519dcc21f7d1192699ef6f2032..c75709b6f4bbf2d99e5589ace6ba9d6f299c3376 100644 --- a/contrib/dolphin/expected/interval_expr_unit.out +++ b/contrib/dolphin/expected/interval_expr_unit.out @@ -101,7 +101,7 @@ desc res_view; float4 + interval 1 day | text | YES | | NULL | float8 + interval 1 day | text | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) + interval 1 day | text | YES | | NULL | datetime + interval 1 day | timestamp without time zone | YES | | NULL | @@ -180,7 +180,7 @@ desc res_view; interval 1 day + float4 | text | YES | | NULL | interval 1 day + float8 | text | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | interval 1 day + time | text | YES | | NULL | interval 1 day + time(4) | text | YES | | NULL | interval 1 day + datetime | timestamp without time zone | YES | | NULL | @@ -259,7 +259,7 @@ desc res_view; float4 - interval 1 day | text | YES | | NULL | float8 - interval 1 day | text | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) - interval 1 day | text | YES | | NULL | datetime - interval 1 day | timestamp without time zone | YES | | NULL | @@ -281,11 +281,11 @@ create table test_def_interval_pl( c datetime default ('2020-01-01 00:00:00' - interval 1 day) ); desc test_def_interval_pl; - Field | Type | Null | Key | Default | Extra --------+--------------------------------+------+-----+----------------------------------------------------+------- - a | timestamp(0) without time zone | YES | | ('2020-01-01 00:00:00'::text + any2interval(1, 8)) | - b | timestamp(0) without time zone | YES | | (any2interval(1, 8) + '2020-01-01 00:00:00'::text) | - c | timestamp(0) without time zone | YES | | ('2020-01-01 00:00:00'::text - any2interval(1, 8)) | + Field | Type | Null | Key | Default | Extra +-------+--------------------------------+------+-----+--------------------------------------------------------------------------------------------------+------- + a | timestamp(0) without time zone | YES | | (('2020-01-01 00:00:00' COLLATE "default")::timestamp(6) without time zone + any2interval(1, 8)) | + b | timestamp(0) without time zone | YES | | (any2interval(1, 8) + ('2020-01-01 00:00:00' COLLATE "default")::timestamp(6) without time zone) | + c | timestamp(0) without time zone | YES | | (('2020-01-01 00:00:00' COLLATE "default")::timestamp(6) without time zone - any2interval(1, 8)) | (3 rows) insert into test_def_interval_pl values(default, default, default); @@ -411,7 +411,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -534,7 +534,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -657,7 +657,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -727,10 +727,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: float8 + interval 1 day WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: numeric + interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: date + interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date + interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime + interval 1 day WARNING: date/time field overflow @@ -820,7 +818,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -890,10 +888,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: interval 1 day + float8 WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: interval 1 day + numeric -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: interval 1 day + date +WARNING: date/time field value out of range +CONTEXT: referenced column: interval 1 day + date WARNING: date/time field overflow CONTEXT: referenced column: interval 1 day + datetime WARNING: date/time field overflow @@ -983,7 +979,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1053,10 +1049,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: float8 - interval 1 day WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: numeric - interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_sub -SQL function "date_sub" statement 1 -referenced column: date - interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date - interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime - interval 1 day WARNING: date/time field overflow @@ -1123,10 +1117,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: float8 + interval 1 day WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: numeric + interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: date + interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date + interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime + interval 1 day WARNING: date/time field overflow @@ -1216,7 +1208,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1286,10 +1278,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: interval 1 day + float8 WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: interval 1 day + numeric -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: interval 1 day + date +WARNING: date/time field value out of range +CONTEXT: referenced column: interval 1 day + date WARNING: date/time field overflow CONTEXT: referenced column: interval 1 day + datetime WARNING: date/time field overflow @@ -1379,7 +1369,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1449,10 +1439,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: float8 - interval 1 day WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: numeric - interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_sub -SQL function "date_sub" statement 1 -referenced column: date - interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date - interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime - interval 1 day WARNING: date/time field overflow @@ -1542,7 +1530,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1668,7 +1656,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1791,7 +1779,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -1914,7 +1902,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2256,7 +2244,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2379,7 +2367,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2502,7 +2490,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2572,10 +2560,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: float8 + interval 1 day WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: numeric + interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: date + interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date + interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime + interval 1 day WARNING: date/time field overflow @@ -2665,7 +2651,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2735,10 +2721,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: interval 1 day + float8 WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: interval 1 day + numeric -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: interval 1 day + date +WARNING: date/time field value out of range +CONTEXT: referenced column: interval 1 day + date WARNING: date/time field overflow CONTEXT: referenced column: interval 1 day + datetime WARNING: date/time field overflow @@ -2828,7 +2812,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -2898,10 +2882,8 @@ WARNING: Incorrect datetime value: "0" CONTEXT: referenced column: float8 - interval 1 day WARNING: Incorrect datetime value: "0.000000" CONTEXT: referenced column: numeric - interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_sub -SQL function "date_sub" statement 1 -referenced column: date - interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date - interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime - interval 1 day WARNING: date/time field overflow @@ -2968,10 +2950,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: float8 + interval 1 day WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: numeric + interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: date + interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date + interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime + interval 1 day WARNING: date/time field overflow @@ -3061,7 +3041,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric + interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date + interval 1 day | text | YES | | NULL | + date + interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time + interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -3131,10 +3111,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: interval 1 day + float8 WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: interval 1 day + numeric -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_add -SQL function "date_add" statement 1 -referenced column: interval 1 day + date +WARNING: date/time field value out of range +CONTEXT: referenced column: interval 1 day + date WARNING: date/time field overflow CONTEXT: referenced column: interval 1 day + datetime WARNING: date/time field overflow @@ -3224,7 +3202,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | interval 1 day + numeric | text | YES | | NULL | date | date | YES | | NULL | - interval 1 day + date | text | YES | | NULL | + interval 1 day + date | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | interval 1 day + time | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | @@ -3294,10 +3272,8 @@ WARNING: Incorrect datetime value: "-1" CONTEXT: referenced column: float8 - interval 1 day WARNING: Incorrect datetime value: "-1.000000" CONTEXT: referenced column: numeric - interval 1 day -WARNING: Incorrect datetime value: "0000-00-00" -CONTEXT: referenced column: date_sub -SQL function "date_sub" statement 1 -referenced column: date - interval 1 day +WARNING: date/time field value out of range +CONTEXT: referenced column: date - interval 1 day WARNING: date/time field overflow CONTEXT: referenced column: datetime - interval 1 day WARNING: date/time field overflow @@ -3387,7 +3363,7 @@ desc res_tab; numeric | numeric(20,6) | YES | | NULL | numeric - interval 1 day | text | YES | | NULL | date | date | YES | | NULL | - date - interval 1 day | text | YES | | NULL | + date - interval 1 day | date | YES | | NULL | time | time(0) without time zone | YES | | NULL | time - interval 1 day | text | YES | | NULL | time(4) | time(4) without time zone | YES | | NULL | diff --git a/contrib/dolphin/expected/json_insert.out b/contrib/dolphin/expected/json_insert.out index aaa64c18aac9a7bc6c6be9ffa2e51caa526d6b33..5faf56cd9f75a2215d2a59df47676b0372c3a93c 100644 --- a/contrib/dolphin/expected/json_insert.out +++ b/contrib/dolphin/expected/json_insert.out @@ -210,5 +210,59 @@ select * from test; {"a": 43, "b": [{"c": true}, "Test"]} (5 rows) +create table t_json(c1 json); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::text); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::varchar); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::char(30)); +insert into t_json values ('{"k1":"v1","k2"}'::text); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +insert into t_json values ('{"k1":"v1","k2"}'::varchar); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +insert into t_json values ('{"k1":"v1","k2"}'::char(30)); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +select * from t_json; + c1 +----------------------- + {"k1":"v1","k2":"v2"} + {"k1":"v1","k2":"v2"} + {"k1":"v1","k2":"v2"} +(3 rows) + +update t_json set c1 = '{"k1":"v1","k3":"v3"}'::text; +update t_json set c1 = '{"k1":"v1","k4":"v4"}'::varchar; +update t_json set c1 = '{"k1":"v1","k4":"v4"}'::char(30); +select * from t_json; + c1 +----------------------- + {"k1":"v1","k4":"v4"} + {"k1":"v1","k4":"v4"} + {"k1":"v1","k4":"v4"} +(3 rows) + +insert ignore into t_json values ('{"k1":"v1","k2"}'::text); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +insert ignore into t_json values ('{"k1":"v1","k2"}'::varchar); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +insert ignore into t_json values ('{"k1":"v1","k2"}'::char(30)); +ERROR: invalid input syntax for type json +DETAIL: Expected ":", but found "}". +CONTEXT: JSON data, line 1: {"k1":"v1","k2"} +referenced column: c1 +drop table t_json; drop schema test_json_insert cascade; reset current_schema; diff --git a/contrib/dolphin/expected/operator_compatibility_test/time_operator_test.out b/contrib/dolphin/expected/operator_compatibility_test/time_operator_test.out index 2b7db3d1d4d2192c924be62d92403bbedeba8253..82ca28b97c605aa948719382bbe78efdeeae57b6 100644 --- a/contrib/dolphin/expected/operator_compatibility_test/time_operator_test.out +++ b/contrib/dolphin/expected/operator_compatibility_test/time_operator_test.out @@ -3460,7 +3460,7 @@ select CURRENT_DATE = time'00:00:00'; select (CURRENT_DATE::date + interval'11 hour 11 min 11 sec') = time'11:11:11'; ?column? ---------- - t + f (1 row) select (CURRENT_DATE::datetime + interval'11 hour 11 min 11 sec') = time'11:11:11'; @@ -3482,10 +3482,6 @@ select CURRENT_DATE <> time'00:00:00'; (1 row) select (CURRENT_DATE::date + interval'11 hour 11 min 11 sec') <> time'11:11:11'; -WARNING: invalid input syntax for type double precision: "11:11:11" -CONTEXT: SQL function "uint2_time_ne" during inlining ---? WARNING: invalid input syntax for type int16: ".* 11:11:11" -DETAIL: text contain invalid character ?column? ---------- t @@ -3512,7 +3508,7 @@ select CURRENT_DATE < time'00:00:00'; select (CURRENT_DATE::date + interval'11 hour 11 min 11 sec') < time'11:11:11'; ?column? ---------- - f + t (1 row) select (CURRENT_DATE::datetime + interval'11 hour 11 min 11 sec') < time'11:11:11'; @@ -3584,7 +3580,7 @@ select CURRENT_DATE >= time'00:00:00'; select (CURRENT_DATE::date + interval'11 hour 11 min 11 sec') >= time'11:11:11'; ?column? ---------- - t + f (1 row) select (CURRENT_DATE::datetime + interval'11 hour 11 min 11 sec') >= time'11:11:11'; diff --git a/contrib/dolphin/expected/option.out b/contrib/dolphin/expected/option.out index b5ddc965b7c37c63086d927d464a7f905487d961..47d169e73bf667b93aa533ead36ca27f94aa4fc8 100644 --- a/contrib/dolphin/expected/option.out +++ b/contrib/dolphin/expected/option.out @@ -4,7 +4,9 @@ create global temp table test1(a int primary key, b text) on commit delete rows NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test1_pkey" for table "test1" create global temp table test2(id int,vname varchar(48),remark text) engine = InnoDB on commit PRESERVE rows ; create table test3(a int) FOR MATERIALIZED VIEW nocompress compression = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. create table test4(a int) FOR MATERIALIZED VIEW nocompress compression = pglz FOR MATERIALIZED VIEW compression = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. create table test5 nocompress with(orientation = column) as select * from test4; create table test6 with(orientation = column) nocompress with(orientation = row) as table test5; ERROR: can't use "option" with more than once diff --git a/contrib/dolphin/expected/partition_test1.out b/contrib/dolphin/expected/partition_test1.out index 1298d2056595436d8d366e0eaf14c235360d33f3..7e6f6f81c485d047a6f2b16d6047f2173472f5c0 100644 --- a/contrib/dolphin/expected/partition_test1.out +++ b/contrib/dolphin/expected/partition_test1.out @@ -1555,6 +1555,41 @@ partition by range(store_id)( insert into RangePartionLevel1_IntegerTypes values (1,2); insert into RangePartionLevel1_IntegerTypes values (1,65535); drop table RangePartionLevel1_IntegerTypes; +create table t_select_0019(col01 int,col02 varchar(255)) +partition by list(col01) ( +partition p1 values in (1000), +partition p2 values in (2000), +partition p3 values in (3000), +partition p4 values in (4000), +partition p5 values in (5000), +partition p6 values in (6000) +); +select * into t_select_0019_p1 from t_select_0019 partition (p1, p3, p5, p6); +select * from t_select_0019_p1; + col01 | col02 +-------+------- +(0 rows) + +drop table t_select_0019; +drop table t_select_0019_p1; +-- extract +create table t_partition_range_0181_1( id int not null, ename varchar(30), hired date not null default '1970-01-01', separated date not null default '9999-12-31', job varchar(30) not null, store_id int not null ) partition by range(extract(year from separated))( partition p0 values less than (1995), partition p1 values less than (2000), partition p2 values less than (2005)); +create table t_partition_range_0181_2( id int, purchased date ) partition by range(year(purchased)) subpartition by hash(id)( partition p0 values less than (1990) ( subpartition s0, subpartition s1), partition p1 values less than (2000) ( subpartition s2, subpartition s3), partition p2 values less than (maxvalue) ( subpartition s4, subpartition s5)); +select relname, parttype, partstrategy, boundaries,reltablespace,intervaltablespace,`interval`,transit from pg_partition where parentid in (select oid from pg_class where relname like 't_partition_range_0181%'); + relname | parttype | partstrategy | boundaries | reltablespace | intervaltablespace | interval | transit +--------------------------+----------+--------------+------------+---------------+--------------------+----------+--------- +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +(8 rows) + +drop table t_partition_range_0181_1; +drop table t_partition_range_0181_2; drop schema partition_test1 cascade; NOTICE: drop cascades to 6 other objects DETAIL: drop cascades to table test_part_list diff --git a/contrib/dolphin/expected/string_func_test/db_b_left_right_test.out b/contrib/dolphin/expected/string_func_test/db_b_left_right_test.out index cbc2e45b298f822d3fd3357d2d1be340b5329bde..491e1724aa4ce94b0c0d9c78aa7753fdc83a7d61 100644 --- a/contrib/dolphin/expected/string_func_test/db_b_left_right_test.out +++ b/contrib/dolphin/expected/string_func_test/db_b_left_right_test.out @@ -310,5 +310,6186 @@ select right('abc',5/2); abc (1 row) +select left('dont!', b'10010'); + left +------- + dont! +(1 row) + +select right('dont!', b'10010'); + right +------- + dont! +(1 row) + +select left('dont!', X'FF'); + left +------- + dont! +(1 row) + +select right('dont!', X'FF'); + right +------- + dont! +(1 row) + +select left('dont!', '9223372036854775807'); + left +------- + dont! +(1 row) + +select right('dont!', '9223372036854775807'); + right +------- + dont! +(1 row) + +select right('dont!', 9223372036854775807); + right +------- + dont! +(1 row) + +select right('dont!', 9223372036854775808); + right +------- + +(1 row) + +\x +CREATE TABLE test_type_table +( + `int1` tinyint, + `uint1` tinyint unsigned, + `int2` smallint, + `uint2` smallint unsigned, + `int4` integer, + `uint4` integer unsigned, + `int8` bigint, + `uint8` bigint unsigned, + `float4` float4, + `float8` float8, + `numeric` decimal(20, 6), + `bit1` bit(1), + `bit64` bit(64), + `boolean` boolean, + `date` date, + `time` time, + `time(4)` time(4), + `datetime` datetime, + `datetime(4)` datetime(4) default '2022-11-11 11:11:11', + `timestamp` timestamp, + `timestamp(4)` timestamp(4) default '2022-11-11 11:11:11', + `year` year, + `char` char(100), + `varchar` varchar(100), + `binary` binary(100), + `varbinary` varbinary(100), + `tinyblob` tinyblob, + `blob` blob, + `mediumblob` mediumblob, + `longblob` longblob, + `text` text, + `enum_t` enum('a', 'b', 'c'), + `set_t` set('a', 'b', 'c'), + `json` json +); +NOTICE: CREATE TABLE will create implicit set "test_type_table_set_t_set" for column "test_type_table.set_t" +insert into test_type_table values(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,b'1', b'111', true,'2023-02-05', '19:10:50', '19:10:50.3456', '2023-02-05 19:10:50', '2023-02-05 19:10:50.456', '2023-02-05 19:10:50', '2023-02-05 19:10:50.456', '2023','1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a','a', 'a,c',json_object('a', 1, 'b', 2)); +select +right(`int1`,`int1`), +right(`int1`,`uint1`), +right(`int1`,`int2`), +right(`int1`,`uint2`), +right(`int1`,`int4`), +right(`int1`,`uint4`), +right(`int1`,`int8`), +right(`int1`,`uint8`), +right(`int1`,`float4`), +right(`int1`,`float8`), +right(`int1`,`numeric`), +right(`int1`,`bit1`), +right(`int1`,`bit64`), +right(`int1`,`boolean`), +right(`int1`,`date`), +right(`int1`,`time`), +right(`int1`,`time(4)`), +right(`int1`,`datetime`), +right(`int1`,`datetime(4)`), +right(`int1`,`timestamp`), +right(`int1`,`timestamp(4)`), +right(`int1`,`year`), +right(`int1`,`char`), +right(`int1`,`varchar`), +right(`int1`,`binary`), +right(`int1`,`varbinary`), +right(`int1`,`tinyblob`), +right(`int1`,`blob`), +right(`int1`,`mediumblob`), +right(`int1`,`longblob`), +right(`int1`,`text`), +right(`int1`,`enum_t`), +right(`int1`,`set_t`), +right(`int1`,`json`), +right(`uint1`,`int1`), +right(`uint1`,`uint1`), +right(`uint1`,`int2`), +right(`uint1`,`uint2`), +right(`uint1`,`int4`), +right(`uint1`,`uint4`), +right(`uint1`,`int8`), +right(`uint1`,`uint8`), +right(`uint1`,`float4`), +right(`uint1`,`float8`), +right(`uint1`,`numeric`), +right(`uint1`,`bit1`), +right(`uint1`,`bit64`), +right(`uint1`,`boolean`), +right(`uint1`,`date`), +right(`uint1`,`time`), +right(`uint1`,`time(4)`), +right(`uint1`,`datetime`), +right(`uint1`,`datetime(4)`), +right(`uint1`,`timestamp`), +right(`uint1`,`timestamp(4)`), +right(`uint1`,`year`), +right(`uint1`,`char`), +right(`uint1`,`varchar`), +right(`uint1`,`binary`), +right(`uint1`,`varbinary`), +right(`uint1`,`tinyblob`), +right(`uint1`,`blob`), +right(`uint1`,`mediumblob`), +right(`uint1`,`longblob`), +right(`uint1`,`text`), +right(`uint1`,`enum_t`), +right(`uint1`,`set_t`), +right(`uint1`,`json`), +right(`int2`,`int1`), +right(`int2`,`uint1`), +right(`int2`,`int2`), +right(`int2`,`uint2`), +right(`int2`,`int4`), +right(`int2`,`uint4`), +right(`int2`,`int8`), +right(`int2`,`uint8`), +right(`int2`,`float4`), +right(`int2`,`float8`), +right(`int2`,`numeric`), +right(`int2`,`bit1`), +right(`int2`,`bit64`), +right(`int2`,`boolean`), +right(`int2`,`date`), +right(`int2`,`time`), +right(`int2`,`time(4)`), +right(`int2`,`datetime`), +right(`int2`,`datetime(4)`), +right(`int2`,`timestamp`), +right(`int2`,`timestamp(4)`), +right(`int2`,`year`), +right(`int2`,`char`), +right(`int2`,`varchar`), +right(`int2`,`binary`), +right(`int2`,`varbinary`), +right(`int2`,`tinyblob`), +right(`int2`,`blob`), +right(`int2`,`mediumblob`), +right(`int2`,`longblob`), +right(`int2`,`text`), +right(`int2`,`enum_t`), +right(`int2`,`set_t`), +right(`int2`,`json`), +right(`uint2`,`int1`), +right(`uint2`,`uint1`), +right(`uint2`,`int2`), +right(`uint2`,`uint2`), +right(`uint2`,`int4`), +right(`uint2`,`uint4`), +right(`uint2`,`int8`), +right(`uint2`,`uint8`), +right(`uint2`,`float4`), +right(`uint2`,`float8`), +right(`uint2`,`numeric`), +right(`uint2`,`bit1`), +right(`uint2`,`bit64`), +right(`uint2`,`boolean`), +right(`uint2`,`date`), +right(`uint2`,`time`), +right(`uint2`,`time(4)`), +right(`uint2`,`datetime`), +right(`uint2`,`datetime(4)`), +right(`uint2`,`timestamp`), +right(`uint2`,`timestamp(4)`), +right(`uint2`,`year`), +right(`uint2`,`char`), +right(`uint2`,`varchar`), +right(`uint2`,`binary`), +right(`uint2`,`varbinary`), +right(`uint2`,`tinyblob`), +right(`uint2`,`blob`), +right(`uint2`,`mediumblob`), +right(`uint2`,`longblob`), +right(`uint2`,`text`), +right(`uint2`,`enum_t`), +right(`uint2`,`set_t`), +right(`uint2`,`json`), +right(`int4`,`int1`), +right(`int4`,`uint1`), +right(`int4`,`int2`), +right(`int4`,`uint2`), +right(`int4`,`int4`), +right(`int4`,`uint4`), +right(`int4`,`int8`), +right(`int4`,`uint8`), +right(`int4`,`float4`), +right(`int4`,`float8`), +right(`int4`,`numeric`), +right(`int4`,`bit1`), +right(`int4`,`bit64`), +right(`int4`,`boolean`), +right(`int4`,`date`), +right(`int4`,`time`), +right(`int4`,`time(4)`), +right(`int4`,`datetime`), +right(`int4`,`datetime(4)`), +right(`int4`,`timestamp`), +right(`int4`,`timestamp(4)`), +right(`int4`,`year`), +right(`int4`,`char`), +right(`int4`,`varchar`), +right(`int4`,`binary`), +right(`int4`,`varbinary`), +right(`int4`,`tinyblob`), +right(`int4`,`blob`), +right(`int4`,`mediumblob`), +right(`int4`,`longblob`), +right(`int4`,`text`), +right(`int4`,`enum_t`), +right(`int4`,`set_t`), +right(`int4`,`json`), +right(`uint4`,`int1`), +right(`uint4`,`uint1`), +right(`uint4`,`int2`), +right(`uint4`,`uint2`), +right(`uint4`,`int4`), +right(`uint4`,`uint4`), +right(`uint4`,`int8`), +right(`uint4`,`uint8`), +right(`uint4`,`float4`), +right(`uint4`,`float8`), +right(`uint4`,`numeric`), +right(`uint4`,`bit1`), +right(`uint4`,`bit64`), +right(`uint4`,`boolean`), +right(`uint4`,`date`), +right(`uint4`,`time`), +right(`uint4`,`time(4)`), +right(`uint4`,`datetime`), +right(`uint4`,`datetime(4)`), +right(`uint4`,`timestamp`), +right(`uint4`,`timestamp(4)`), +right(`uint4`,`year`), +right(`uint4`,`char`), +right(`uint4`,`varchar`), +right(`uint4`,`binary`), +right(`uint4`,`varbinary`), +right(`uint4`,`tinyblob`), +right(`uint4`,`blob`), +right(`uint4`,`mediumblob`), +right(`uint4`,`longblob`), +right(`uint4`,`text`), +right(`uint4`,`enum_t`), +right(`uint4`,`set_t`), +right(`uint4`,`json`), +right(`int8`,`int1`), +right(`int8`,`uint1`), +right(`int8`,`int2`), +right(`int8`,`uint2`), +right(`int8`,`int4`), +right(`int8`,`uint4`), +right(`int8`,`int8`), +right(`int8`,`uint8`), +right(`int8`,`float4`), +right(`int8`,`float8`), +right(`int8`,`numeric`), +right(`int8`,`bit1`), +right(`int8`,`bit64`), +right(`int8`,`boolean`), +right(`int8`,`date`), +right(`int8`,`time`), +right(`int8`,`time(4)`), +right(`int8`,`datetime`), +right(`int8`,`datetime(4)`), +right(`int8`,`timestamp`), +right(`int8`,`timestamp(4)`), +right(`int8`,`year`), +right(`int8`,`char`), +right(`int8`,`varchar`), +right(`int8`,`binary`), +right(`int8`,`varbinary`), +right(`int8`,`tinyblob`), +right(`int8`,`blob`), +right(`int8`,`mediumblob`), +right(`int8`,`longblob`), +right(`int8`,`text`), +right(`int8`,`enum_t`), +right(`int8`,`set_t`), +right(`int8`,`json`), +right(`uint8`,`int1`), +right(`uint8`,`uint1`), +right(`uint8`,`int2`), +right(`uint8`,`uint2`), +right(`uint8`,`int4`), +right(`uint8`,`uint4`), +right(`uint8`,`int8`), +right(`uint8`,`uint8`), +right(`uint8`,`float4`), +right(`uint8`,`float8`), +right(`uint8`,`numeric`), +right(`uint8`,`bit1`), +right(`uint8`,`bit64`), +right(`uint8`,`boolean`), +right(`uint8`,`date`), +right(`uint8`,`time`), +right(`uint8`,`time(4)`), +right(`uint8`,`datetime`), +right(`uint8`,`datetime(4)`), +right(`uint8`,`timestamp`), +right(`uint8`,`timestamp(4)`), +right(`uint8`,`year`), +right(`uint8`,`char`), +right(`uint8`,`varchar`), +right(`uint8`,`binary`), +right(`uint8`,`varbinary`), +right(`uint8`,`tinyblob`), +right(`uint8`,`blob`), +right(`uint8`,`mediumblob`), +right(`uint8`,`longblob`), +right(`uint8`,`text`), +right(`uint8`,`enum_t`), +right(`uint8`,`set_t`), +right(`uint8`,`json`), +right(`float4`,`int1`), +right(`float4`,`uint1`), +right(`float4`,`int2`), +right(`float4`,`uint2`), +right(`float4`,`int4`), +right(`float4`,`uint4`), +right(`float4`,`int8`), +right(`float4`,`uint8`), +right(`float4`,`float4`), +right(`float4`,`float8`), +right(`float4`,`numeric`), +right(`float4`,`bit1`), +right(`float4`,`bit64`), +right(`float4`,`boolean`), +right(`float4`,`date`), +right(`float4`,`time`), +right(`float4`,`time(4)`), +right(`float4`,`datetime`), +right(`float4`,`datetime(4)`), +right(`float4`,`timestamp`), +right(`float4`,`timestamp(4)`), +right(`float4`,`year`), +right(`float4`,`char`), +right(`float4`,`varchar`), +right(`float4`,`binary`), +right(`float4`,`varbinary`), +right(`float4`,`tinyblob`), +right(`float4`,`blob`), +right(`float4`,`mediumblob`), +right(`float4`,`longblob`), +right(`float4`,`text`), +right(`float4`,`enum_t`), +right(`float4`,`set_t`), +right(`float4`,`json`), +right(`float8`,`int1`), +right(`float8`,`uint1`), +right(`float8`,`int2`), +right(`float8`,`uint2`), +right(`float8`,`int4`), +right(`float8`,`uint4`), +right(`float8`,`int8`), +right(`float8`,`uint8`), +right(`float8`,`float4`), +right(`float8`,`float8`), +right(`float8`,`numeric`), +right(`float8`,`bit1`), +right(`float8`,`bit64`), +right(`float8`,`boolean`), +right(`float8`,`date`), +right(`float8`,`time`), +right(`float8`,`time(4)`), +right(`float8`,`datetime`), +right(`float8`,`datetime(4)`), +right(`float8`,`timestamp`), +right(`float8`,`timestamp(4)`), +right(`float8`,`year`), +right(`float8`,`char`), +right(`float8`,`varchar`), +right(`float8`,`binary`), +right(`float8`,`varbinary`), +right(`float8`,`tinyblob`), +right(`float8`,`blob`), +right(`float8`,`mediumblob`), +right(`float8`,`longblob`), +right(`float8`,`text`), +right(`float8`,`enum_t`), +right(`float8`,`set_t`), +right(`float8`,`json`), +right(`numeric`,`int1`), +right(`numeric`,`uint1`), +right(`numeric`,`int2`), +right(`numeric`,`uint2`), +right(`numeric`,`int4`), +right(`numeric`,`uint4`), +right(`numeric`,`int8`), +right(`numeric`,`uint8`), +right(`numeric`,`float4`), +right(`numeric`,`float8`), +right(`numeric`,`numeric`), +right(`numeric`,`bit1`), +right(`numeric`,`bit64`), +right(`numeric`,`boolean`), +right(`numeric`,`date`), +right(`numeric`,`time`), +right(`numeric`,`time(4)`), +right(`numeric`,`datetime`), +right(`numeric`,`datetime(4)`), +right(`numeric`,`timestamp`), +right(`numeric`,`timestamp(4)`), +right(`numeric`,`year`), +right(`numeric`,`char`), +right(`numeric`,`varchar`), +right(`numeric`,`binary`), +right(`numeric`,`varbinary`), +right(`numeric`,`tinyblob`), +right(`numeric`,`blob`), +right(`numeric`,`mediumblob`), +right(`numeric`,`longblob`), +right(`numeric`,`text`), +right(`numeric`,`enum_t`), +right(`numeric`,`set_t`), +right(`numeric`,`json`), +right(`bit1`,`int1`), +right(`bit1`,`uint1`), +right(`bit1`,`int2`), +right(`bit1`,`uint2`), +right(`bit1`,`int4`), +right(`bit1`,`uint4`), +right(`bit1`,`int8`), +right(`bit1`,`uint8`), +right(`bit1`,`float4`), +right(`bit1`,`float8`), +right(`bit1`,`numeric`), +right(`bit1`,`bit1`), +right(`bit1`,`bit64`), +right(`bit1`,`boolean`), +right(`bit1`,`date`), +right(`bit1`,`time`), +right(`bit1`,`time(4)`), +right(`bit1`,`datetime`), +right(`bit1`,`datetime(4)`), +right(`bit1`,`timestamp`), +right(`bit1`,`timestamp(4)`), +right(`bit1`,`year`), +right(`bit1`,`char`), +right(`bit1`,`varchar`), +right(`bit1`,`binary`), +right(`bit1`,`varbinary`), +right(`bit1`,`tinyblob`), +right(`bit1`,`blob`), +right(`bit1`,`mediumblob`), +right(`bit1`,`longblob`), +right(`bit1`,`text`), +right(`bit1`,`enum_t`), +right(`bit1`,`set_t`), +right(`bit1`,`json`), +right(`bit64`,`int1`), +right(`bit64`,`uint1`), +right(`bit64`,`int2`), +right(`bit64`,`uint2`), +right(`bit64`,`int4`), +right(`bit64`,`uint4`), +right(`bit64`,`int8`), +right(`bit64`,`uint8`), +right(`bit64`,`float4`), +right(`bit64`,`float8`), +right(`bit64`,`numeric`), +right(`bit64`,`bit1`), +right(`bit64`,`bit64`), +right(`bit64`,`boolean`), +right(`bit64`,`date`), +right(`bit64`,`time`), +right(`bit64`,`time(4)`), +right(`bit64`,`datetime`), +right(`bit64`,`datetime(4)`), +right(`bit64`,`timestamp`), +right(`bit64`,`timestamp(4)`), +right(`bit64`,`year`), +right(`bit64`,`char`), +right(`bit64`,`varchar`), +right(`bit64`,`binary`), +right(`bit64`,`varbinary`), +right(`bit64`,`tinyblob`), +right(`bit64`,`blob`), +right(`bit64`,`mediumblob`), +right(`bit64`,`longblob`), +right(`bit64`,`text`), +right(`bit64`,`enum_t`), +right(`bit64`,`set_t`), +right(`bit64`,`json`), +right(`boolean`,`int1`), +right(`boolean`,`uint1`), +right(`boolean`,`int2`), +right(`boolean`,`uint2`), +right(`boolean`,`int4`), +right(`boolean`,`uint4`), +right(`boolean`,`int8`), +right(`boolean`,`uint8`), +right(`boolean`,`float4`), +right(`boolean`,`float8`), +right(`boolean`,`numeric`), +right(`boolean`,`bit1`), +right(`boolean`,`bit64`), +right(`boolean`,`boolean`), +right(`boolean`,`date`), +right(`boolean`,`time`), +right(`boolean`,`time(4)`), +right(`boolean`,`datetime`), +right(`boolean`,`datetime(4)`), +right(`boolean`,`timestamp`), +right(`boolean`,`timestamp(4)`), +right(`boolean`,`year`), +right(`boolean`,`char`), +right(`boolean`,`varchar`), +right(`boolean`,`binary`), +right(`boolean`,`varbinary`), +right(`boolean`,`tinyblob`), +right(`boolean`,`blob`), +right(`boolean`,`mediumblob`), +right(`boolean`,`longblob`), +right(`boolean`,`text`), +right(`boolean`,`enum_t`), +right(`boolean`,`set_t`), +right(`boolean`,`json`), +right(`date`,`int1`), +right(`date`,`uint1`), +right(`date`,`int2`), +right(`date`,`uint2`), +right(`date`,`int4`), +right(`date`,`uint4`), +right(`date`,`int8`), +right(`date`,`uint8`), +right(`date`,`float4`), +right(`date`,`float8`), +right(`date`,`numeric`), +right(`date`,`bit1`), +right(`date`,`bit64`), +right(`date`,`boolean`), +right(`date`,`date`), +right(`date`,`time`), +right(`date`,`time(4)`), +right(`date`,`datetime`), +right(`date`,`datetime(4)`), +right(`date`,`timestamp`), +right(`date`,`timestamp(4)`), +right(`date`,`year`), +right(`date`,`char`), +right(`date`,`varchar`), +right(`date`,`binary`), +right(`date`,`varbinary`), +right(`date`,`tinyblob`), +right(`date`,`blob`), +right(`date`,`mediumblob`), +right(`date`,`longblob`), +right(`date`,`text`), +right(`date`,`enum_t`), +right(`date`,`set_t`), +right(`date`,`json`), +right(`time`,`int1`), +right(`time`,`uint1`), +right(`time`,`int2`), +right(`time`,`uint2`), +right(`time`,`int4`), +right(`time`,`uint4`), +right(`time`,`int8`), +right(`time`,`uint8`), +right(`time`,`float4`), +right(`time`,`float8`), +right(`time`,`numeric`), +right(`time`,`bit1`), +right(`time`,`bit64`), +right(`time`,`boolean`), +right(`time`,`date`), +right(`time`,`time`), +right(`time`,`time(4)`), +right(`time`,`datetime`), +right(`time`,`datetime(4)`), +right(`time`,`timestamp`), +right(`time`,`timestamp(4)`), +right(`time`,`year`), +right(`time`,`char`), +right(`time`,`varchar`), +right(`time`,`binary`), +right(`time`,`varbinary`), +right(`time`,`tinyblob`), +right(`time`,`blob`), +right(`time`,`mediumblob`), +right(`time`,`longblob`), +right(`time`,`text`), +right(`time`,`enum_t`), +right(`time`,`set_t`), +right(`time`,`json`), +right(`time(4)`,`int1`), +right(`time(4)`,`uint1`), +right(`time(4)`,`int2`), +right(`time(4)`,`uint2`), +right(`time(4)`,`int4`), +right(`time(4)`,`uint4`), +right(`time(4)`,`int8`), +right(`time(4)`,`uint8`), +right(`time(4)`,`float4`), +right(`time(4)`,`float8`), +right(`time(4)`,`numeric`), +right(`time(4)`,`bit1`), +right(`time(4)`,`bit64`), +right(`time(4)`,`boolean`), +right(`time(4)`,`date`), +right(`time(4)`,`time`), +right(`time(4)`,`time(4)`), +right(`time(4)`,`datetime`), +right(`time(4)`,`datetime(4)`), +right(`time(4)`,`timestamp`), +right(`time(4)`,`timestamp(4)`), +right(`time(4)`,`year`), +right(`time(4)`,`char`), +right(`time(4)`,`varchar`), +right(`time(4)`,`binary`), +right(`time(4)`,`varbinary`), +right(`time(4)`,`tinyblob`), +right(`time(4)`,`blob`), +right(`time(4)`,`mediumblob`), +right(`time(4)`,`longblob`), +right(`time(4)`,`text`), +right(`time(4)`,`enum_t`), +right(`time(4)`,`set_t`), +right(`time(4)`,`json`), +right(`datetime`,`int1`), +right(`datetime`,`uint1`), +right(`datetime`,`int2`), +right(`datetime`,`uint2`), +right(`datetime`,`int4`), +right(`datetime`,`uint4`), +right(`datetime`,`int8`), +right(`datetime`,`uint8`), +right(`datetime`,`float4`), +right(`datetime`,`float8`), +right(`datetime`,`numeric`), +right(`datetime`,`bit1`), +right(`datetime`,`bit64`), +right(`datetime`,`boolean`), +right(`datetime`,`date`), +right(`datetime`,`time`), +right(`datetime`,`time(4)`), +right(`datetime`,`datetime`), +right(`datetime`,`datetime(4)`), +right(`datetime`,`timestamp`), +right(`datetime`,`timestamp(4)`), +right(`datetime`,`year`), +right(`datetime`,`char`), +right(`datetime`,`varchar`), +right(`datetime`,`binary`), +right(`datetime`,`varbinary`), +right(`datetime`,`tinyblob`), +right(`datetime`,`blob`), +right(`datetime`,`mediumblob`), +right(`datetime`,`longblob`), +right(`datetime`,`text`), +right(`datetime`,`enum_t`), +right(`datetime`,`set_t`), +right(`datetime`,`json`), +right(`datetime(4)`,`int1`), +right(`datetime(4)`,`uint1`), +right(`datetime(4)`,`int2`), +right(`datetime(4)`,`uint2`), +right(`datetime(4)`,`int4`), +right(`datetime(4)`,`uint4`), +right(`datetime(4)`,`int8`), +right(`datetime(4)`,`uint8`), +right(`datetime(4)`,`float4`), +right(`datetime(4)`,`float8`), +right(`datetime(4)`,`numeric`), +right(`datetime(4)`,`bit1`), +right(`datetime(4)`,`bit64`), +right(`datetime(4)`,`boolean`), +right(`datetime(4)`,`date`), +right(`datetime(4)`,`time`), +right(`datetime(4)`,`time(4)`), +right(`datetime(4)`,`datetime`), +right(`datetime(4)`,`datetime(4)`), +right(`datetime(4)`,`timestamp`), +right(`datetime(4)`,`timestamp(4)`), +right(`datetime(4)`,`year`), +right(`datetime(4)`,`char`), +right(`datetime(4)`,`varchar`), +right(`datetime(4)`,`binary`), +right(`datetime(4)`,`varbinary`), +right(`datetime(4)`,`tinyblob`), +right(`datetime(4)`,`blob`), +right(`datetime(4)`,`mediumblob`), +right(`datetime(4)`,`longblob`), +right(`datetime(4)`,`text`), +right(`datetime(4)`,`enum_t`), +right(`datetime(4)`,`set_t`), +right(`datetime(4)`,`json`), +right(`timestamp`,`int1`), +right(`timestamp`,`uint1`), +right(`timestamp`,`int2`), +right(`timestamp`,`uint2`), +right(`timestamp`,`int4`), +right(`timestamp`,`uint4`), +right(`timestamp`,`int8`), +right(`timestamp`,`uint8`), +right(`timestamp`,`float4`), +right(`timestamp`,`float8`), +right(`timestamp`,`numeric`), +right(`timestamp`,`bit1`), +right(`timestamp`,`bit64`), +right(`timestamp`,`boolean`), +right(`timestamp`,`date`), +right(`timestamp`,`time`), +right(`timestamp`,`time(4)`), +right(`timestamp`,`datetime`), +right(`timestamp`,`datetime(4)`), +right(`timestamp`,`timestamp`), +right(`timestamp`,`timestamp(4)`), +right(`timestamp`,`year`), +right(`timestamp`,`char`), +right(`timestamp`,`varchar`), +right(`timestamp`,`binary`), +right(`timestamp`,`varbinary`), +right(`timestamp`,`tinyblob`), +right(`timestamp`,`blob`), +right(`timestamp`,`mediumblob`), +right(`timestamp`,`longblob`), +right(`timestamp`,`text`), +right(`timestamp`,`enum_t`), +right(`timestamp`,`set_t`), +right(`timestamp`,`json`), +right(`timestamp(4)`,`int1`), +right(`timestamp(4)`,`uint1`), +right(`timestamp(4)`,`int2`), +right(`timestamp(4)`,`uint2`), +right(`timestamp(4)`,`int4`), +right(`timestamp(4)`,`uint4`), +right(`timestamp(4)`,`int8`), +right(`timestamp(4)`,`uint8`), +right(`timestamp(4)`,`float4`), +right(`timestamp(4)`,`float8`), +right(`timestamp(4)`,`numeric`), +right(`timestamp(4)`,`bit1`), +right(`timestamp(4)`,`bit64`), +right(`timestamp(4)`,`boolean`), +right(`timestamp(4)`,`date`), +right(`timestamp(4)`,`time`), +right(`timestamp(4)`,`time(4)`), +right(`timestamp(4)`,`datetime`), +right(`timestamp(4)`,`datetime(4)`), +right(`timestamp(4)`,`timestamp`), +right(`timestamp(4)`,`timestamp(4)`), +right(`timestamp(4)`,`year`), +right(`timestamp(4)`,`char`), +right(`timestamp(4)`,`varchar`), +right(`timestamp(4)`,`binary`), +right(`timestamp(4)`,`varbinary`), +right(`timestamp(4)`,`tinyblob`), +right(`timestamp(4)`,`blob`), +right(`timestamp(4)`,`mediumblob`), +right(`timestamp(4)`,`longblob`), +right(`timestamp(4)`,`text`), +right(`timestamp(4)`,`enum_t`), +right(`timestamp(4)`,`set_t`), +right(`timestamp(4)`,`json`), +right(`year`,`int1`), +right(`year`,`uint1`), +right(`year`,`int2`), +right(`year`,`uint2`), +right(`year`,`int4`), +right(`year`,`uint4`), +right(`year`,`int8`), +right(`year`,`uint8`), +right(`year`,`float4`), +right(`year`,`float8`), +right(`year`,`numeric`), +right(`year`,`bit1`), +right(`year`,`bit64`), +right(`year`,`boolean`), +right(`year`,`date`), +right(`year`,`time`), +right(`year`,`time(4)`), +right(`year`,`datetime`), +right(`year`,`datetime(4)`), +right(`year`,`timestamp`), +right(`year`,`timestamp(4)`), +right(`year`,`year`), +right(`year`,`char`), +right(`year`,`varchar`), +right(`year`,`binary`), +right(`year`,`varbinary`), +right(`year`,`tinyblob`), +right(`year`,`blob`), +right(`year`,`mediumblob`), +right(`year`,`longblob`), +right(`year`,`text`), +right(`year`,`enum_t`), +right(`year`,`set_t`), +right(`year`,`json`), +right(`char`,`int1`), +right(`char`,`uint1`), +right(`char`,`int2`), +right(`char`,`uint2`), +right(`char`,`int4`), +right(`char`,`uint4`), +right(`char`,`int8`), +right(`char`,`uint8`), +right(`char`,`float4`), +right(`char`,`float8`), +right(`char`,`numeric`), +right(`char`,`bit1`), +right(`char`,`bit64`), +right(`char`,`boolean`), +right(`char`,`date`), +right(`char`,`time`), +right(`char`,`time(4)`), +right(`char`,`datetime`), +right(`char`,`datetime(4)`), +right(`char`,`timestamp`), +right(`char`,`timestamp(4)`), +right(`char`,`year`), +right(`char`,`char`), +right(`char`,`varchar`), +right(`char`,`binary`), +right(`char`,`varbinary`), +right(`char`,`tinyblob`), +right(`char`,`blob`), +right(`char`,`mediumblob`), +right(`char`,`longblob`), +right(`char`,`text`), +right(`char`,`enum_t`), +right(`char`,`set_t`), +right(`char`,`json`), +right(`varchar`,`int1`), +right(`varchar`,`uint1`), +right(`varchar`,`int2`), +right(`varchar`,`uint2`), +right(`varchar`,`int4`), +right(`varchar`,`uint4`), +right(`varchar`,`int8`), +right(`varchar`,`uint8`), +right(`varchar`,`float4`), +right(`varchar`,`float8`), +right(`varchar`,`numeric`), +right(`varchar`,`bit1`), +right(`varchar`,`bit64`), +right(`varchar`,`boolean`), +right(`varchar`,`date`), +right(`varchar`,`time`), +right(`varchar`,`time(4)`), +right(`varchar`,`datetime`), +right(`varchar`,`datetime(4)`), +right(`varchar`,`timestamp`), +right(`varchar`,`timestamp(4)`), +right(`varchar`,`year`), +right(`varchar`,`char`), +right(`varchar`,`varchar`), +right(`varchar`,`binary`), +right(`varchar`,`varbinary`), +right(`varchar`,`tinyblob`), +right(`varchar`,`blob`), +right(`varchar`,`mediumblob`), +right(`varchar`,`longblob`), +right(`varchar`,`text`), +right(`varchar`,`enum_t`), +right(`varchar`,`set_t`), +right(`varchar`,`json`), +right(`binary`,`int1`), +right(`binary`,`uint1`), +right(`binary`,`int2`), +right(`binary`,`uint2`), +right(`binary`,`int4`), +right(`binary`,`uint4`), +right(`binary`,`int8`), +right(`binary`,`uint8`), +right(`binary`,`float4`), +right(`binary`,`float8`), +right(`binary`,`numeric`), +right(`binary`,`bit1`), +right(`binary`,`bit64`), +right(`binary`,`boolean`), +right(`binary`,`date`), +right(`binary`,`time`), +right(`binary`,`time(4)`), +right(`binary`,`datetime`), +right(`binary`,`datetime(4)`), +right(`binary`,`timestamp`), +right(`binary`,`timestamp(4)`), +right(`binary`,`year`), +right(`binary`,`char`), +right(`binary`,`varchar`), +right(`binary`,`binary`), +right(`binary`,`varbinary`), +right(`binary`,`tinyblob`), +right(`binary`,`blob`), +right(`binary`,`mediumblob`), +right(`binary`,`longblob`), +right(`binary`,`text`), +right(`binary`,`enum_t`), +right(`binary`,`set_t`), +right(`binary`,`json`), +right(`varbinary`,`int1`), +right(`varbinary`,`uint1`), +right(`varbinary`,`int2`), +right(`varbinary`,`uint2`), +right(`varbinary`,`int4`), +right(`varbinary`,`uint4`), +right(`varbinary`,`int8`), +right(`varbinary`,`uint8`), +right(`varbinary`,`float4`), +right(`varbinary`,`float8`), +right(`varbinary`,`numeric`), +right(`varbinary`,`bit1`), +right(`varbinary`,`bit64`), +right(`varbinary`,`boolean`), +right(`varbinary`,`date`), +right(`varbinary`,`time`), +right(`varbinary`,`time(4)`), +right(`varbinary`,`datetime`), +right(`varbinary`,`datetime(4)`), +right(`varbinary`,`timestamp`), +right(`varbinary`,`timestamp(4)`), +right(`varbinary`,`year`), +right(`varbinary`,`char`), +right(`varbinary`,`varchar`), +right(`varbinary`,`binary`), +right(`varbinary`,`varbinary`), +right(`varbinary`,`tinyblob`), +right(`varbinary`,`blob`), +right(`varbinary`,`mediumblob`), +right(`varbinary`,`longblob`), +right(`varbinary`,`text`), +right(`varbinary`,`enum_t`), +right(`varbinary`,`set_t`), +right(`varbinary`,`json`), +right(`tinyblob`,`int1`), +right(`tinyblob`,`uint1`), +right(`tinyblob`,`int2`), +right(`tinyblob`,`uint2`), +right(`tinyblob`,`int4`), +right(`tinyblob`,`uint4`), +right(`tinyblob`,`int8`), +right(`tinyblob`,`uint8`), +right(`tinyblob`,`float4`), +right(`tinyblob`,`float8`), +right(`tinyblob`,`numeric`), +right(`tinyblob`,`bit1`), +right(`tinyblob`,`bit64`), +right(`tinyblob`,`boolean`), +right(`tinyblob`,`date`), +right(`tinyblob`,`time`), +right(`tinyblob`,`time(4)`), +right(`tinyblob`,`datetime`), +right(`tinyblob`,`datetime(4)`), +right(`tinyblob`,`timestamp`), +right(`tinyblob`,`timestamp(4)`), +right(`tinyblob`,`year`), +right(`tinyblob`,`char`), +right(`tinyblob`,`varchar`), +right(`tinyblob`,`binary`), +right(`tinyblob`,`varbinary`), +right(`tinyblob`,`tinyblob`), +right(`tinyblob`,`blob`), +right(`tinyblob`,`mediumblob`), +right(`tinyblob`,`longblob`), +right(`tinyblob`,`text`), +right(`tinyblob`,`enum_t`), +right(`tinyblob`,`set_t`), +right(`tinyblob`,`json`), +right(`blob`,`int1`), +right(`blob`,`uint1`), +right(`blob`,`int2`), +right(`blob`,`uint2`), +right(`blob`,`int4`), +right(`blob`,`uint4`), +right(`blob`,`int8`), +right(`blob`,`uint8`), +right(`blob`,`float4`), +right(`blob`,`float8`), +right(`blob`,`numeric`), +right(`blob`,`bit1`), +right(`blob`,`bit64`), +right(`blob`,`boolean`), +right(`blob`,`date`), +right(`blob`,`time`), +right(`blob`,`time(4)`), +right(`blob`,`datetime`), +right(`blob`,`datetime(4)`), +right(`blob`,`timestamp`), +right(`blob`,`timestamp(4)`), +right(`blob`,`year`), +right(`blob`,`char`), +right(`blob`,`varchar`), +right(`blob`,`binary`), +right(`blob`,`varbinary`), +right(`blob`,`tinyblob`), +right(`blob`,`blob`), +right(`blob`,`mediumblob`), +right(`blob`,`longblob`), +right(`blob`,`text`), +right(`blob`,`enum_t`), +right(`blob`,`set_t`), +right(`blob`,`json`), +right(`mediumblob`,`int1`), +right(`mediumblob`,`uint1`), +right(`mediumblob`,`int2`), +right(`mediumblob`,`uint2`), +right(`mediumblob`,`int4`), +right(`mediumblob`,`uint4`), +right(`mediumblob`,`int8`), +right(`mediumblob`,`uint8`), +right(`mediumblob`,`float4`), +right(`mediumblob`,`float8`), +right(`mediumblob`,`numeric`), +right(`mediumblob`,`bit1`), +right(`mediumblob`,`bit64`), +right(`mediumblob`,`boolean`), +right(`mediumblob`,`date`), +right(`mediumblob`,`time`), +right(`mediumblob`,`time(4)`), +right(`mediumblob`,`datetime`), +right(`mediumblob`,`datetime(4)`), +right(`mediumblob`,`timestamp`), +right(`mediumblob`,`timestamp(4)`), +right(`mediumblob`,`year`), +right(`mediumblob`,`char`), +right(`mediumblob`,`varchar`), +right(`mediumblob`,`binary`), +right(`mediumblob`,`varbinary`), +right(`mediumblob`,`tinyblob`), +right(`mediumblob`,`blob`), +right(`mediumblob`,`mediumblob`), +right(`mediumblob`,`longblob`), +right(`mediumblob`,`text`), +right(`mediumblob`,`enum_t`), +right(`mediumblob`,`set_t`), +right(`mediumblob`,`json`), +right(`longblob`,`int1`), +right(`longblob`,`uint1`), +right(`longblob`,`int2`), +right(`longblob`,`uint2`), +right(`longblob`,`int4`), +right(`longblob`,`uint4`), +right(`longblob`,`int8`), +right(`longblob`,`uint8`), +right(`longblob`,`float4`), +right(`longblob`,`float8`), +right(`longblob`,`numeric`), +right(`longblob`,`bit1`), +right(`longblob`,`bit64`), +right(`longblob`,`boolean`), +right(`longblob`,`date`), +right(`longblob`,`time`), +right(`longblob`,`time(4)`), +right(`longblob`,`datetime`), +right(`longblob`,`datetime(4)`), +right(`longblob`,`timestamp`), +right(`longblob`,`timestamp(4)`), +right(`longblob`,`year`), +right(`longblob`,`char`), +right(`longblob`,`varchar`), +right(`longblob`,`binary`), +right(`longblob`,`varbinary`), +right(`longblob`,`tinyblob`), +right(`longblob`,`blob`), +right(`longblob`,`mediumblob`), +right(`longblob`,`longblob`), +right(`longblob`,`text`), +right(`longblob`,`enum_t`), +right(`longblob`,`set_t`), +right(`longblob`,`json`), +right(`text`,`int1`), +right(`text`,`uint1`), +right(`text`,`int2`), +right(`text`,`uint2`), +right(`text`,`int4`), +right(`text`,`uint4`), +right(`text`,`int8`), +right(`text`,`uint8`), +right(`text`,`float4`), +right(`text`,`float8`), +right(`text`,`numeric`), +right(`text`,`bit1`), +right(`text`,`bit64`), +right(`text`,`boolean`), +right(`text`,`date`), +right(`text`,`time`), +right(`text`,`time(4)`), +right(`text`,`datetime`), +right(`text`,`datetime(4)`), +right(`text`,`timestamp`), +right(`text`,`timestamp(4)`), +right(`text`,`year`), +right(`text`,`char`), +right(`text`,`varchar`), +right(`text`,`binary`), +right(`text`,`varbinary`), +right(`text`,`tinyblob`), +right(`text`,`blob`), +right(`text`,`mediumblob`), +right(`text`,`longblob`), +right(`text`,`text`), +right(`text`,`enum_t`), +right(`text`,`set_t`), +right(`text`,`json`), +right(`enum_t`,`int1`), +right(`enum_t`,`uint1`), +right(`enum_t`,`int2`), +right(`enum_t`,`uint2`), +right(`enum_t`,`int4`), +right(`enum_t`,`uint4`), +right(`enum_t`,`int8`), +right(`enum_t`,`uint8`), +right(`enum_t`,`float4`), +right(`enum_t`,`float8`), +right(`enum_t`,`numeric`), +right(`enum_t`,`bit1`), +right(`enum_t`,`bit64`), +right(`enum_t`,`boolean`), +right(`enum_t`,`date`), +right(`enum_t`,`time`), +right(`enum_t`,`time(4)`), +right(`enum_t`,`datetime`), +right(`enum_t`,`datetime(4)`), +right(`enum_t`,`timestamp`), +right(`enum_t`,`timestamp(4)`), +right(`enum_t`,`year`), +right(`enum_t`,`char`), +right(`enum_t`,`varchar`), +right(`enum_t`,`binary`), +right(`enum_t`,`varbinary`), +right(`enum_t`,`tinyblob`), +right(`enum_t`,`blob`), +right(`enum_t`,`mediumblob`), +right(`enum_t`,`longblob`), +right(`enum_t`,`text`), +right(`enum_t`,`enum_t`), +right(`enum_t`,`set_t`), +right(`enum_t`,`json`), +right(`set_t`,`int1`), +right(`set_t`,`uint1`), +right(`set_t`,`int2`), +right(`set_t`,`uint2`), +right(`set_t`,`int4`), +right(`set_t`,`uint4`), +right(`set_t`,`int8`), +right(`set_t`,`uint8`), +right(`set_t`,`float4`), +right(`set_t`,`float8`), +right(`set_t`,`numeric`), +right(`set_t`,`bit1`), +right(`set_t`,`bit64`), +right(`set_t`,`boolean`), +right(`set_t`,`date`), +right(`set_t`,`time`), +right(`set_t`,`time(4)`), +right(`set_t`,`datetime`), +right(`set_t`,`datetime(4)`), +right(`set_t`,`timestamp`), +right(`set_t`,`timestamp(4)`), +right(`set_t`,`year`), +right(`set_t`,`char`), +right(`set_t`,`varchar`), +right(`set_t`,`binary`), +right(`set_t`,`varbinary`), +right(`set_t`,`tinyblob`), +right(`set_t`,`blob`), +right(`set_t`,`mediumblob`), +right(`set_t`,`longblob`), +right(`set_t`,`text`), +right(`set_t`,`enum_t`), +right(`set_t`,`set_t`), +right(`set_t`,`json`), +right(`json`,`int1`), +right(`json`,`uint1`), +right(`json`,`int2`), +right(`json`,`uint2`), +right(`json`,`int4`), +right(`json`,`uint4`), +right(`json`,`int8`), +right(`json`,`uint8`), +right(`json`,`float4`), +right(`json`,`float8`), +right(`json`,`numeric`), +right(`json`,`bit1`), +right(`json`,`bit64`), +right(`json`,`boolean`), +right(`json`,`date`), +right(`json`,`time`), +right(`json`,`time(4)`), +right(`json`,`datetime`), +right(`json`,`datetime(4)`), +right(`json`,`timestamp`), +right(`json`,`timestamp(4)`), +right(`json`,`year`), +right(`json`,`char`), +right(`json`,`varchar`), +right(`json`,`binary`), +right(`json`,`varbinary`), +right(`json`,`tinyblob`), +right(`json`,`blob`), +right(`json`,`mediumblob`), +right(`json`,`longblob`), +right(`json`,`text`), +right(`json`,`enum_t`), +right(`json`,`set_t`), +right(`json`,`json`) +from test_type_table; +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: right +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: right +-[ RECORD 1 ]----------------------------------------------------------------------------------------------- +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | .000000 +right | 0 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 1.000000 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 00000 +right | +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | \001 +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | 1 +right | +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 3-02-05 +right | 5 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 2023-02-05 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 5 +right | 02-05 +right | +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 9:10:50 +right | 0 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 19:10:50 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 10:50 +right | +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 50.3456 +right | 6 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 19:10:50.3456 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | .3456 +right | +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 9:10:50 +right | 0 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 2023-02-05 19:10:50 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 0 +right | 10:50 +right | +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | :50.456 +right | 6 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 2023-02-05 19:10:50.456 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 6 +right | 0.456 +right | +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 0:50-08 +right | 8 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 2023-02-05 19:10:50-08 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 50-08 +right | +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | .456-08 +right | 8 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 2023-02-05 19:10:50.456-08 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 8 +right | 56-08 +right | +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 2023 +right | 3 +right | 2023 +right | 2023 +right | 2023 +right | 2023 +right | 2023 +right | 2023 +right | 2023 +right | 2023 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 3 +right | 2023 +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | 1.23a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | 1.23a +right | +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | a +right | +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | a,c +right | c +right | a,c +right | a,c +right | a,c +right | a,c +right | a,c +right | a,c +right | a,c +right | a,c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | c +right | a,c +right | +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | "b": 2} +right | } +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | {"a": 1, "b": 2} +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | } +right | ": 2} +right | + +select +left(`int1`,`int1`), +left(`int1`,`uint1`), +left(`int1`,`int2`), +left(`int1`,`uint2`), +left(`int1`,`int4`), +left(`int1`,`uint4`), +left(`int1`,`int8`), +left(`int1`,`uint8`), +left(`int1`,`float4`), +left(`int1`,`float8`), +left(`int1`,`numeric`), +left(`int1`,`bit1`), +left(`int1`,`bit64`), +left(`int1`,`boolean`), +left(`int1`,`date`), +left(`int1`,`time`), +left(`int1`,`time(4)`), +left(`int1`,`datetime`), +left(`int1`,`datetime(4)`), +left(`int1`,`timestamp`), +left(`int1`,`timestamp(4)`), +left(`int1`,`year`), +left(`int1`,`char`), +left(`int1`,`varchar`), +left(`int1`,`binary`), +left(`int1`,`varbinary`), +left(`int1`,`tinyblob`), +left(`int1`,`blob`), +left(`int1`,`mediumblob`), +left(`int1`,`longblob`), +left(`int1`,`text`), +left(`int1`,`enum_t`), +left(`int1`,`set_t`), +left(`int1`,`json`), +left(`uint1`,`int1`), +left(`uint1`,`uint1`), +left(`uint1`,`int2`), +left(`uint1`,`uint2`), +left(`uint1`,`int4`), +left(`uint1`,`uint4`), +left(`uint1`,`int8`), +left(`uint1`,`uint8`), +left(`uint1`,`float4`), +left(`uint1`,`float8`), +left(`uint1`,`numeric`), +left(`uint1`,`bit1`), +left(`uint1`,`bit64`), +left(`uint1`,`boolean`), +left(`uint1`,`date`), +left(`uint1`,`time`), +left(`uint1`,`time(4)`), +left(`uint1`,`datetime`), +left(`uint1`,`datetime(4)`), +left(`uint1`,`timestamp`), +left(`uint1`,`timestamp(4)`), +left(`uint1`,`year`), +left(`uint1`,`char`), +left(`uint1`,`varchar`), +left(`uint1`,`binary`), +left(`uint1`,`varbinary`), +left(`uint1`,`tinyblob`), +left(`uint1`,`blob`), +left(`uint1`,`mediumblob`), +left(`uint1`,`longblob`), +left(`uint1`,`text`), +left(`uint1`,`enum_t`), +left(`uint1`,`set_t`), +left(`uint1`,`json`), +left(`int2`,`int1`), +left(`int2`,`uint1`), +left(`int2`,`int2`), +left(`int2`,`uint2`), +left(`int2`,`int4`), +left(`int2`,`uint4`), +left(`int2`,`int8`), +left(`int2`,`uint8`), +left(`int2`,`float4`), +left(`int2`,`float8`), +left(`int2`,`numeric`), +left(`int2`,`bit1`), +left(`int2`,`bit64`), +left(`int2`,`boolean`), +left(`int2`,`date`), +left(`int2`,`time`), +left(`int2`,`time(4)`), +left(`int2`,`datetime`), +left(`int2`,`datetime(4)`), +left(`int2`,`timestamp`), +left(`int2`,`timestamp(4)`), +left(`int2`,`year`), +left(`int2`,`char`), +left(`int2`,`varchar`), +left(`int2`,`binary`), +left(`int2`,`varbinary`), +left(`int2`,`tinyblob`), +left(`int2`,`blob`), +left(`int2`,`mediumblob`), +left(`int2`,`longblob`), +left(`int2`,`text`), +left(`int2`,`enum_t`), +left(`int2`,`set_t`), +left(`int2`,`json`), +left(`uint2`,`int1`), +left(`uint2`,`uint1`), +left(`uint2`,`int2`), +left(`uint2`,`uint2`), +left(`uint2`,`int4`), +left(`uint2`,`uint4`), +left(`uint2`,`int8`), +left(`uint2`,`uint8`), +left(`uint2`,`float4`), +left(`uint2`,`float8`), +left(`uint2`,`numeric`), +left(`uint2`,`bit1`), +left(`uint2`,`bit64`), +left(`uint2`,`boolean`), +left(`uint2`,`date`), +left(`uint2`,`time`), +left(`uint2`,`time(4)`), +left(`uint2`,`datetime`), +left(`uint2`,`datetime(4)`), +left(`uint2`,`timestamp`), +left(`uint2`,`timestamp(4)`), +left(`uint2`,`year`), +left(`uint2`,`char`), +left(`uint2`,`varchar`), +left(`uint2`,`binary`), +left(`uint2`,`varbinary`), +left(`uint2`,`tinyblob`), +left(`uint2`,`blob`), +left(`uint2`,`mediumblob`), +left(`uint2`,`longblob`), +left(`uint2`,`text`), +left(`uint2`,`enum_t`), +left(`uint2`,`set_t`), +left(`uint2`,`json`), +left(`int4`,`int1`), +left(`int4`,`uint1`), +left(`int4`,`int2`), +left(`int4`,`uint2`), +left(`int4`,`int4`), +left(`int4`,`uint4`), +left(`int4`,`int8`), +left(`int4`,`uint8`), +left(`int4`,`float4`), +left(`int4`,`float8`), +left(`int4`,`numeric`), +left(`int4`,`bit1`), +left(`int4`,`bit64`), +left(`int4`,`boolean`), +left(`int4`,`date`), +left(`int4`,`time`), +left(`int4`,`time(4)`), +left(`int4`,`datetime`), +left(`int4`,`datetime(4)`), +left(`int4`,`timestamp`), +left(`int4`,`timestamp(4)`), +left(`int4`,`year`), +left(`int4`,`char`), +left(`int4`,`varchar`), +left(`int4`,`binary`), +left(`int4`,`varbinary`), +left(`int4`,`tinyblob`), +left(`int4`,`blob`), +left(`int4`,`mediumblob`), +left(`int4`,`longblob`), +left(`int4`,`text`), +left(`int4`,`enum_t`), +left(`int4`,`set_t`), +left(`int4`,`json`), +left(`uint4`,`int1`), +left(`uint4`,`uint1`), +left(`uint4`,`int2`), +left(`uint4`,`uint2`), +left(`uint4`,`int4`), +left(`uint4`,`uint4`), +left(`uint4`,`int8`), +left(`uint4`,`uint8`), +left(`uint4`,`float4`), +left(`uint4`,`float8`), +left(`uint4`,`numeric`), +left(`uint4`,`bit1`), +left(`uint4`,`bit64`), +left(`uint4`,`boolean`), +left(`uint4`,`date`), +left(`uint4`,`time`), +left(`uint4`,`time(4)`), +left(`uint4`,`datetime`), +left(`uint4`,`datetime(4)`), +left(`uint4`,`timestamp`), +left(`uint4`,`timestamp(4)`), +left(`uint4`,`year`), +left(`uint4`,`char`), +left(`uint4`,`varchar`), +left(`uint4`,`binary`), +left(`uint4`,`varbinary`), +left(`uint4`,`tinyblob`), +left(`uint4`,`blob`), +left(`uint4`,`mediumblob`), +left(`uint4`,`longblob`), +left(`uint4`,`text`), +left(`uint4`,`enum_t`), +left(`uint4`,`set_t`), +left(`uint4`,`json`), +left(`int8`,`int1`), +left(`int8`,`uint1`), +left(`int8`,`int2`), +left(`int8`,`uint2`), +left(`int8`,`int4`), +left(`int8`,`uint4`), +left(`int8`,`int8`), +left(`int8`,`uint8`), +left(`int8`,`float4`), +left(`int8`,`float8`), +left(`int8`,`numeric`), +left(`int8`,`bit1`), +left(`int8`,`bit64`), +left(`int8`,`boolean`), +left(`int8`,`date`), +left(`int8`,`time`), +left(`int8`,`time(4)`), +left(`int8`,`datetime`), +left(`int8`,`datetime(4)`), +left(`int8`,`timestamp`), +left(`int8`,`timestamp(4)`), +left(`int8`,`year`), +left(`int8`,`char`), +left(`int8`,`varchar`), +left(`int8`,`binary`), +left(`int8`,`varbinary`), +left(`int8`,`tinyblob`), +left(`int8`,`blob`), +left(`int8`,`mediumblob`), +left(`int8`,`longblob`), +left(`int8`,`text`), +left(`int8`,`enum_t`), +left(`int8`,`set_t`), +left(`int8`,`json`), +left(`uint8`,`int1`), +left(`uint8`,`uint1`), +left(`uint8`,`int2`), +left(`uint8`,`uint2`), +left(`uint8`,`int4`), +left(`uint8`,`uint4`), +left(`uint8`,`int8`), +left(`uint8`,`uint8`), +left(`uint8`,`float4`), +left(`uint8`,`float8`), +left(`uint8`,`numeric`), +left(`uint8`,`bit1`), +left(`uint8`,`bit64`), +left(`uint8`,`boolean`), +left(`uint8`,`date`), +left(`uint8`,`time`), +left(`uint8`,`time(4)`), +left(`uint8`,`datetime`), +left(`uint8`,`datetime(4)`), +left(`uint8`,`timestamp`), +left(`uint8`,`timestamp(4)`), +left(`uint8`,`year`), +left(`uint8`,`char`), +left(`uint8`,`varchar`), +left(`uint8`,`binary`), +left(`uint8`,`varbinary`), +left(`uint8`,`tinyblob`), +left(`uint8`,`blob`), +left(`uint8`,`mediumblob`), +left(`uint8`,`longblob`), +left(`uint8`,`text`), +left(`uint8`,`enum_t`), +left(`uint8`,`set_t`), +left(`uint8`,`json`), +left(`float4`,`int1`), +left(`float4`,`uint1`), +left(`float4`,`int2`), +left(`float4`,`uint2`), +left(`float4`,`int4`), +left(`float4`,`uint4`), +left(`float4`,`int8`), +left(`float4`,`uint8`), +left(`float4`,`float4`), +left(`float4`,`float8`), +left(`float4`,`numeric`), +left(`float4`,`bit1`), +left(`float4`,`bit64`), +left(`float4`,`boolean`), +left(`float4`,`date`), +left(`float4`,`time`), +left(`float4`,`time(4)`), +left(`float4`,`datetime`), +left(`float4`,`datetime(4)`), +left(`float4`,`timestamp`), +left(`float4`,`timestamp(4)`), +left(`float4`,`year`), +left(`float4`,`char`), +left(`float4`,`varchar`), +left(`float4`,`binary`), +left(`float4`,`varbinary`), +left(`float4`,`tinyblob`), +left(`float4`,`blob`), +left(`float4`,`mediumblob`), +left(`float4`,`longblob`), +left(`float4`,`text`), +left(`float4`,`enum_t`), +left(`float4`,`set_t`), +left(`float4`,`json`), +left(`float8`,`int1`), +left(`float8`,`uint1`), +left(`float8`,`int2`), +left(`float8`,`uint2`), +left(`float8`,`int4`), +left(`float8`,`uint4`), +left(`float8`,`int8`), +left(`float8`,`uint8`), +left(`float8`,`float4`), +left(`float8`,`float8`), +left(`float8`,`numeric`), +left(`float8`,`bit1`), +left(`float8`,`bit64`), +left(`float8`,`boolean`), +left(`float8`,`date`), +left(`float8`,`time`), +left(`float8`,`time(4)`), +left(`float8`,`datetime`), +left(`float8`,`datetime(4)`), +left(`float8`,`timestamp`), +left(`float8`,`timestamp(4)`), +left(`float8`,`year`), +left(`float8`,`char`), +left(`float8`,`varchar`), +left(`float8`,`binary`), +left(`float8`,`varbinary`), +left(`float8`,`tinyblob`), +left(`float8`,`blob`), +left(`float8`,`mediumblob`), +left(`float8`,`longblob`), +left(`float8`,`text`), +left(`float8`,`enum_t`), +left(`float8`,`set_t`), +left(`float8`,`json`), +left(`numeric`,`int1`), +left(`numeric`,`uint1`), +left(`numeric`,`int2`), +left(`numeric`,`uint2`), +left(`numeric`,`int4`), +left(`numeric`,`uint4`), +left(`numeric`,`int8`), +left(`numeric`,`uint8`), +left(`numeric`,`float4`), +left(`numeric`,`float8`), +left(`numeric`,`numeric`), +left(`numeric`,`bit1`), +left(`numeric`,`bit64`), +left(`numeric`,`boolean`), +left(`numeric`,`date`), +left(`numeric`,`time`), +left(`numeric`,`time(4)`), +left(`numeric`,`datetime`), +left(`numeric`,`datetime(4)`), +left(`numeric`,`timestamp`), +left(`numeric`,`timestamp(4)`), +left(`numeric`,`year`), +left(`numeric`,`char`), +left(`numeric`,`varchar`), +left(`numeric`,`binary`), +left(`numeric`,`varbinary`), +left(`numeric`,`tinyblob`), +left(`numeric`,`blob`), +left(`numeric`,`mediumblob`), +left(`numeric`,`longblob`), +left(`numeric`,`text`), +left(`numeric`,`enum_t`), +left(`numeric`,`set_t`), +left(`numeric`,`json`), +left(`bit1`,`int1`), +left(`bit1`,`uint1`), +left(`bit1`,`int2`), +left(`bit1`,`uint2`), +left(`bit1`,`int4`), +left(`bit1`,`uint4`), +left(`bit1`,`int8`), +left(`bit1`,`uint8`), +left(`bit1`,`float4`), +left(`bit1`,`float8`), +left(`bit1`,`numeric`), +left(`bit1`,`bit1`), +left(`bit1`,`bit64`), +left(`bit1`,`boolean`), +left(`bit1`,`date`), +left(`bit1`,`time`), +left(`bit1`,`time(4)`), +left(`bit1`,`datetime`), +left(`bit1`,`datetime(4)`), +left(`bit1`,`timestamp`), +left(`bit1`,`timestamp(4)`), +left(`bit1`,`year`), +left(`bit1`,`char`), +left(`bit1`,`varchar`), +left(`bit1`,`binary`), +left(`bit1`,`varbinary`), +left(`bit1`,`tinyblob`), +left(`bit1`,`blob`), +left(`bit1`,`mediumblob`), +left(`bit1`,`longblob`), +left(`bit1`,`text`), +left(`bit1`,`enum_t`), +left(`bit1`,`set_t`), +left(`bit1`,`json`), +left(`bit64`,`int1`), +left(`bit64`,`uint1`), +left(`bit64`,`int2`), +left(`bit64`,`uint2`), +left(`bit64`,`int4`), +left(`bit64`,`uint4`), +left(`bit64`,`int8`), +left(`bit64`,`uint8`), +left(`bit64`,`float4`), +left(`bit64`,`float8`), +left(`bit64`,`numeric`), +left(`bit64`,`bit1`), +left(`bit64`,`bit64`), +left(`bit64`,`boolean`), +left(`bit64`,`date`), +left(`bit64`,`time`), +left(`bit64`,`time(4)`), +left(`bit64`,`datetime`), +left(`bit64`,`datetime(4)`), +left(`bit64`,`timestamp`), +left(`bit64`,`timestamp(4)`), +left(`bit64`,`year`), +left(`bit64`,`char`), +left(`bit64`,`varchar`), +left(`bit64`,`binary`), +left(`bit64`,`varbinary`), +left(`bit64`,`tinyblob`), +left(`bit64`,`blob`), +left(`bit64`,`mediumblob`), +left(`bit64`,`longblob`), +left(`bit64`,`text`), +left(`bit64`,`enum_t`), +left(`bit64`,`set_t`), +left(`bit64`,`json`), +left(`boolean`,`int1`), +left(`boolean`,`uint1`), +left(`boolean`,`int2`), +left(`boolean`,`uint2`), +left(`boolean`,`int4`), +left(`boolean`,`uint4`), +left(`boolean`,`int8`), +left(`boolean`,`uint8`), +left(`boolean`,`float4`), +left(`boolean`,`float8`), +left(`boolean`,`numeric`), +left(`boolean`,`bit1`), +left(`boolean`,`bit64`), +left(`boolean`,`boolean`), +left(`boolean`,`date`), +left(`boolean`,`time`), +left(`boolean`,`time(4)`), +left(`boolean`,`datetime`), +left(`boolean`,`datetime(4)`), +left(`boolean`,`timestamp`), +left(`boolean`,`timestamp(4)`), +left(`boolean`,`year`), +left(`boolean`,`char`), +left(`boolean`,`varchar`), +left(`boolean`,`binary`), +left(`boolean`,`varbinary`), +left(`boolean`,`tinyblob`), +left(`boolean`,`blob`), +left(`boolean`,`mediumblob`), +left(`boolean`,`longblob`), +left(`boolean`,`text`), +left(`boolean`,`enum_t`), +left(`boolean`,`set_t`), +left(`boolean`,`json`), +left(`date`,`int1`), +left(`date`,`uint1`), +left(`date`,`int2`), +left(`date`,`uint2`), +left(`date`,`int4`), +left(`date`,`uint4`), +left(`date`,`int8`), +left(`date`,`uint8`), +left(`date`,`float4`), +left(`date`,`float8`), +left(`date`,`numeric`), +left(`date`,`bit1`), +left(`date`,`bit64`), +left(`date`,`boolean`), +left(`date`,`date`), +left(`date`,`time`), +left(`date`,`time(4)`), +left(`date`,`datetime`), +left(`date`,`datetime(4)`), +left(`date`,`timestamp`), +left(`date`,`timestamp(4)`), +left(`date`,`year`), +left(`date`,`char`), +left(`date`,`varchar`), +left(`date`,`binary`), +left(`date`,`varbinary`), +left(`date`,`tinyblob`), +left(`date`,`blob`), +left(`date`,`mediumblob`), +left(`date`,`longblob`), +left(`date`,`text`), +left(`date`,`enum_t`), +left(`date`,`set_t`), +left(`date`,`json`), +left(`time`,`int1`), +left(`time`,`uint1`), +left(`time`,`int2`), +left(`time`,`uint2`), +left(`time`,`int4`), +left(`time`,`uint4`), +left(`time`,`int8`), +left(`time`,`uint8`), +left(`time`,`float4`), +left(`time`,`float8`), +left(`time`,`numeric`), +left(`time`,`bit1`), +left(`time`,`bit64`), +left(`time`,`boolean`), +left(`time`,`date`), +left(`time`,`time`), +left(`time`,`time(4)`), +left(`time`,`datetime`), +left(`time`,`datetime(4)`), +left(`time`,`timestamp`), +left(`time`,`timestamp(4)`), +left(`time`,`year`), +left(`time`,`char`), +left(`time`,`varchar`), +left(`time`,`binary`), +left(`time`,`varbinary`), +left(`time`,`tinyblob`), +left(`time`,`blob`), +left(`time`,`mediumblob`), +left(`time`,`longblob`), +left(`time`,`text`), +left(`time`,`enum_t`), +left(`time`,`set_t`), +left(`time`,`json`), +left(`time(4)`,`int1`), +left(`time(4)`,`uint1`), +left(`time(4)`,`int2`), +left(`time(4)`,`uint2`), +left(`time(4)`,`int4`), +left(`time(4)`,`uint4`), +left(`time(4)`,`int8`), +left(`time(4)`,`uint8`), +left(`time(4)`,`float4`), +left(`time(4)`,`float8`), +left(`time(4)`,`numeric`), +left(`time(4)`,`bit1`), +left(`time(4)`,`bit64`), +left(`time(4)`,`boolean`), +left(`time(4)`,`date`), +left(`time(4)`,`time`), +left(`time(4)`,`time(4)`), +left(`time(4)`,`datetime`), +left(`time(4)`,`datetime(4)`), +left(`time(4)`,`timestamp`), +left(`time(4)`,`timestamp(4)`), +left(`time(4)`,`year`), +left(`time(4)`,`char`), +left(`time(4)`,`varchar`), +left(`time(4)`,`binary`), +left(`time(4)`,`varbinary`), +left(`time(4)`,`tinyblob`), +left(`time(4)`,`blob`), +left(`time(4)`,`mediumblob`), +left(`time(4)`,`longblob`), +left(`time(4)`,`text`), +left(`time(4)`,`enum_t`), +left(`time(4)`,`set_t`), +left(`time(4)`,`json`), +left(`datetime`,`int1`), +left(`datetime`,`uint1`), +left(`datetime`,`int2`), +left(`datetime`,`uint2`), +left(`datetime`,`int4`), +left(`datetime`,`uint4`), +left(`datetime`,`int8`), +left(`datetime`,`uint8`), +left(`datetime`,`float4`), +left(`datetime`,`float8`), +left(`datetime`,`numeric`), +left(`datetime`,`bit1`), +left(`datetime`,`bit64`), +left(`datetime`,`boolean`), +left(`datetime`,`date`), +left(`datetime`,`time`), +left(`datetime`,`time(4)`), +left(`datetime`,`datetime`), +left(`datetime`,`datetime(4)`), +left(`datetime`,`timestamp`), +left(`datetime`,`timestamp(4)`), +left(`datetime`,`year`), +left(`datetime`,`char`), +left(`datetime`,`varchar`), +left(`datetime`,`binary`), +left(`datetime`,`varbinary`), +left(`datetime`,`tinyblob`), +left(`datetime`,`blob`), +left(`datetime`,`mediumblob`), +left(`datetime`,`longblob`), +left(`datetime`,`text`), +left(`datetime`,`enum_t`), +left(`datetime`,`set_t`), +left(`datetime`,`json`), +left(`datetime(4)`,`int1`), +left(`datetime(4)`,`uint1`), +left(`datetime(4)`,`int2`), +left(`datetime(4)`,`uint2`), +left(`datetime(4)`,`int4`), +left(`datetime(4)`,`uint4`), +left(`datetime(4)`,`int8`), +left(`datetime(4)`,`uint8`), +left(`datetime(4)`,`float4`), +left(`datetime(4)`,`float8`), +left(`datetime(4)`,`numeric`), +left(`datetime(4)`,`bit1`), +left(`datetime(4)`,`bit64`), +left(`datetime(4)`,`boolean`), +left(`datetime(4)`,`date`), +left(`datetime(4)`,`time`), +left(`datetime(4)`,`time(4)`), +left(`datetime(4)`,`datetime`), +left(`datetime(4)`,`datetime(4)`), +left(`datetime(4)`,`timestamp`), +left(`datetime(4)`,`timestamp(4)`), +left(`datetime(4)`,`year`), +left(`datetime(4)`,`char`), +left(`datetime(4)`,`varchar`), +left(`datetime(4)`,`binary`), +left(`datetime(4)`,`varbinary`), +left(`datetime(4)`,`tinyblob`), +left(`datetime(4)`,`blob`), +left(`datetime(4)`,`mediumblob`), +left(`datetime(4)`,`longblob`), +left(`datetime(4)`,`text`), +left(`datetime(4)`,`enum_t`), +left(`datetime(4)`,`set_t`), +left(`datetime(4)`,`json`), +left(`timestamp`,`int1`), +left(`timestamp`,`uint1`), +left(`timestamp`,`int2`), +left(`timestamp`,`uint2`), +left(`timestamp`,`int4`), +left(`timestamp`,`uint4`), +left(`timestamp`,`int8`), +left(`timestamp`,`uint8`), +left(`timestamp`,`float4`), +left(`timestamp`,`float8`), +left(`timestamp`,`numeric`), +left(`timestamp`,`bit1`), +left(`timestamp`,`bit64`), +left(`timestamp`,`boolean`), +left(`timestamp`,`date`), +left(`timestamp`,`time`), +left(`timestamp`,`time(4)`), +left(`timestamp`,`datetime`), +left(`timestamp`,`datetime(4)`), +left(`timestamp`,`timestamp`), +left(`timestamp`,`timestamp(4)`), +left(`timestamp`,`year`), +left(`timestamp`,`char`), +left(`timestamp`,`varchar`), +left(`timestamp`,`binary`), +left(`timestamp`,`varbinary`), +left(`timestamp`,`tinyblob`), +left(`timestamp`,`blob`), +left(`timestamp`,`mediumblob`), +left(`timestamp`,`longblob`), +left(`timestamp`,`text`), +left(`timestamp`,`enum_t`), +left(`timestamp`,`set_t`), +left(`timestamp`,`json`), +left(`timestamp(4)`,`int1`), +left(`timestamp(4)`,`uint1`), +left(`timestamp(4)`,`int2`), +left(`timestamp(4)`,`uint2`), +left(`timestamp(4)`,`int4`), +left(`timestamp(4)`,`uint4`), +left(`timestamp(4)`,`int8`), +left(`timestamp(4)`,`uint8`), +left(`timestamp(4)`,`float4`), +left(`timestamp(4)`,`float8`), +left(`timestamp(4)`,`numeric`), +left(`timestamp(4)`,`bit1`), +left(`timestamp(4)`,`bit64`), +left(`timestamp(4)`,`boolean`), +left(`timestamp(4)`,`date`), +left(`timestamp(4)`,`time`), +left(`timestamp(4)`,`time(4)`), +left(`timestamp(4)`,`datetime`), +left(`timestamp(4)`,`datetime(4)`), +left(`timestamp(4)`,`timestamp`), +left(`timestamp(4)`,`timestamp(4)`), +left(`timestamp(4)`,`year`), +left(`timestamp(4)`,`char`), +left(`timestamp(4)`,`varchar`), +left(`timestamp(4)`,`binary`), +left(`timestamp(4)`,`varbinary`), +left(`timestamp(4)`,`tinyblob`), +left(`timestamp(4)`,`blob`), +left(`timestamp(4)`,`mediumblob`), +left(`timestamp(4)`,`longblob`), +left(`timestamp(4)`,`text`), +left(`timestamp(4)`,`enum_t`), +left(`timestamp(4)`,`set_t`), +left(`timestamp(4)`,`json`), +left(`year`,`int1`), +left(`year`,`uint1`), +left(`year`,`int2`), +left(`year`,`uint2`), +left(`year`,`int4`), +left(`year`,`uint4`), +left(`year`,`int8`), +left(`year`,`uint8`), +left(`year`,`float4`), +left(`year`,`float8`), +left(`year`,`numeric`), +left(`year`,`bit1`), +left(`year`,`bit64`), +left(`year`,`boolean`), +left(`year`,`date`), +left(`year`,`time`), +left(`year`,`time(4)`), +left(`year`,`datetime`), +left(`year`,`datetime(4)`), +left(`year`,`timestamp`), +left(`year`,`timestamp(4)`), +left(`year`,`year`), +left(`year`,`char`), +left(`year`,`varchar`), +left(`year`,`binary`), +left(`year`,`varbinary`), +left(`year`,`tinyblob`), +left(`year`,`blob`), +left(`year`,`mediumblob`), +left(`year`,`longblob`), +left(`year`,`text`), +left(`year`,`enum_t`), +left(`year`,`set_t`), +left(`year`,`json`), +left(`char`,`int1`), +left(`char`,`uint1`), +left(`char`,`int2`), +left(`char`,`uint2`), +left(`char`,`int4`), +left(`char`,`uint4`), +left(`char`,`int8`), +left(`char`,`uint8`), +left(`char`,`float4`), +left(`char`,`float8`), +left(`char`,`numeric`), +left(`char`,`bit1`), +left(`char`,`bit64`), +left(`char`,`boolean`), +left(`char`,`date`), +left(`char`,`time`), +left(`char`,`time(4)`), +left(`char`,`datetime`), +left(`char`,`datetime(4)`), +left(`char`,`timestamp`), +left(`char`,`timestamp(4)`), +left(`char`,`year`), +left(`char`,`char`), +left(`char`,`varchar`), +left(`char`,`binary`), +left(`char`,`varbinary`), +left(`char`,`tinyblob`), +left(`char`,`blob`), +left(`char`,`mediumblob`), +left(`char`,`longblob`), +left(`char`,`text`), +left(`char`,`enum_t`), +left(`char`,`set_t`), +left(`char`,`json`), +left(`varchar`,`int1`), +left(`varchar`,`uint1`), +left(`varchar`,`int2`), +left(`varchar`,`uint2`), +left(`varchar`,`int4`), +left(`varchar`,`uint4`), +left(`varchar`,`int8`), +left(`varchar`,`uint8`), +left(`varchar`,`float4`), +left(`varchar`,`float8`), +left(`varchar`,`numeric`), +left(`varchar`,`bit1`), +left(`varchar`,`bit64`), +left(`varchar`,`boolean`), +left(`varchar`,`date`), +left(`varchar`,`time`), +left(`varchar`,`time(4)`), +left(`varchar`,`datetime`), +left(`varchar`,`datetime(4)`), +left(`varchar`,`timestamp`), +left(`varchar`,`timestamp(4)`), +left(`varchar`,`year`), +left(`varchar`,`char`), +left(`varchar`,`varchar`), +left(`varchar`,`binary`), +left(`varchar`,`varbinary`), +left(`varchar`,`tinyblob`), +left(`varchar`,`blob`), +left(`varchar`,`mediumblob`), +left(`varchar`,`longblob`), +left(`varchar`,`text`), +left(`varchar`,`enum_t`), +left(`varchar`,`set_t`), +left(`varchar`,`json`), +left(`binary`,`int1`), +left(`binary`,`uint1`), +left(`binary`,`int2`), +left(`binary`,`uint2`), +left(`binary`,`int4`), +left(`binary`,`uint4`), +left(`binary`,`int8`), +left(`binary`,`uint8`), +left(`binary`,`float4`), +left(`binary`,`float8`), +left(`binary`,`numeric`), +left(`binary`,`bit1`), +left(`binary`,`bit64`), +left(`binary`,`boolean`), +left(`binary`,`date`), +left(`binary`,`time`), +left(`binary`,`time(4)`), +left(`binary`,`datetime`), +left(`binary`,`datetime(4)`), +left(`binary`,`timestamp`), +left(`binary`,`timestamp(4)`), +left(`binary`,`year`), +left(`binary`,`char`), +left(`binary`,`varchar`), +left(`binary`,`binary`), +left(`binary`,`varbinary`), +left(`binary`,`tinyblob`), +left(`binary`,`blob`), +left(`binary`,`mediumblob`), +left(`binary`,`longblob`), +left(`binary`,`text`), +left(`binary`,`enum_t`), +left(`binary`,`set_t`), +left(`binary`,`json`), +left(`varbinary`,`int1`), +left(`varbinary`,`uint1`), +left(`varbinary`,`int2`), +left(`varbinary`,`uint2`), +left(`varbinary`,`int4`), +left(`varbinary`,`uint4`), +left(`varbinary`,`int8`), +left(`varbinary`,`uint8`), +left(`varbinary`,`float4`), +left(`varbinary`,`float8`), +left(`varbinary`,`numeric`), +left(`varbinary`,`bit1`), +left(`varbinary`,`bit64`), +left(`varbinary`,`boolean`), +left(`varbinary`,`date`), +left(`varbinary`,`time`), +left(`varbinary`,`time(4)`), +left(`varbinary`,`datetime`), +left(`varbinary`,`datetime(4)`), +left(`varbinary`,`timestamp`), +left(`varbinary`,`timestamp(4)`), +left(`varbinary`,`year`), +left(`varbinary`,`char`), +left(`varbinary`,`varchar`), +left(`varbinary`,`binary`), +left(`varbinary`,`varbinary`), +left(`varbinary`,`tinyblob`), +left(`varbinary`,`blob`), +left(`varbinary`,`mediumblob`), +left(`varbinary`,`longblob`), +left(`varbinary`,`text`), +left(`varbinary`,`enum_t`), +left(`varbinary`,`set_t`), +left(`varbinary`,`json`), +left(`tinyblob`,`int1`), +left(`tinyblob`,`uint1`), +left(`tinyblob`,`int2`), +left(`tinyblob`,`uint2`), +left(`tinyblob`,`int4`), +left(`tinyblob`,`uint4`), +left(`tinyblob`,`int8`), +left(`tinyblob`,`uint8`), +left(`tinyblob`,`float4`), +left(`tinyblob`,`float8`), +left(`tinyblob`,`numeric`), +left(`tinyblob`,`bit1`), +left(`tinyblob`,`bit64`), +left(`tinyblob`,`boolean`), +left(`tinyblob`,`date`), +left(`tinyblob`,`time`), +left(`tinyblob`,`time(4)`), +left(`tinyblob`,`datetime`), +left(`tinyblob`,`datetime(4)`), +left(`tinyblob`,`timestamp`), +left(`tinyblob`,`timestamp(4)`), +left(`tinyblob`,`year`), +left(`tinyblob`,`char`), +left(`tinyblob`,`varchar`), +left(`tinyblob`,`binary`), +left(`tinyblob`,`varbinary`), +left(`tinyblob`,`tinyblob`), +left(`tinyblob`,`blob`), +left(`tinyblob`,`mediumblob`), +left(`tinyblob`,`longblob`), +left(`tinyblob`,`text`), +left(`tinyblob`,`enum_t`), +left(`tinyblob`,`set_t`), +left(`tinyblob`,`json`), +left(`blob`,`int1`), +left(`blob`,`uint1`), +left(`blob`,`int2`), +left(`blob`,`uint2`), +left(`blob`,`int4`), +left(`blob`,`uint4`), +left(`blob`,`int8`), +left(`blob`,`uint8`), +left(`blob`,`float4`), +left(`blob`,`float8`), +left(`blob`,`numeric`), +left(`blob`,`bit1`), +left(`blob`,`bit64`), +left(`blob`,`boolean`), +left(`blob`,`date`), +left(`blob`,`time`), +left(`blob`,`time(4)`), +left(`blob`,`datetime`), +left(`blob`,`datetime(4)`), +left(`blob`,`timestamp`), +left(`blob`,`timestamp(4)`), +left(`blob`,`year`), +left(`blob`,`char`), +left(`blob`,`varchar`), +left(`blob`,`binary`), +left(`blob`,`varbinary`), +left(`blob`,`tinyblob`), +left(`blob`,`blob`), +left(`blob`,`mediumblob`), +left(`blob`,`longblob`), +left(`blob`,`text`), +left(`blob`,`enum_t`), +left(`blob`,`set_t`), +left(`blob`,`json`), +left(`mediumblob`,`int1`), +left(`mediumblob`,`uint1`), +left(`mediumblob`,`int2`), +left(`mediumblob`,`uint2`), +left(`mediumblob`,`int4`), +left(`mediumblob`,`uint4`), +left(`mediumblob`,`int8`), +left(`mediumblob`,`uint8`), +left(`mediumblob`,`float4`), +left(`mediumblob`,`float8`), +left(`mediumblob`,`numeric`), +left(`mediumblob`,`bit1`), +left(`mediumblob`,`bit64`), +left(`mediumblob`,`boolean`), +left(`mediumblob`,`date`), +left(`mediumblob`,`time`), +left(`mediumblob`,`time(4)`), +left(`mediumblob`,`datetime`), +left(`mediumblob`,`datetime(4)`), +left(`mediumblob`,`timestamp`), +left(`mediumblob`,`timestamp(4)`), +left(`mediumblob`,`year`), +left(`mediumblob`,`char`), +left(`mediumblob`,`varchar`), +left(`mediumblob`,`binary`), +left(`mediumblob`,`varbinary`), +left(`mediumblob`,`tinyblob`), +left(`mediumblob`,`blob`), +left(`mediumblob`,`mediumblob`), +left(`mediumblob`,`longblob`), +left(`mediumblob`,`text`), +left(`mediumblob`,`enum_t`), +left(`mediumblob`,`set_t`), +left(`mediumblob`,`json`), +left(`longblob`,`int1`), +left(`longblob`,`uint1`), +left(`longblob`,`int2`), +left(`longblob`,`uint2`), +left(`longblob`,`int4`), +left(`longblob`,`uint4`), +left(`longblob`,`int8`), +left(`longblob`,`uint8`), +left(`longblob`,`float4`), +left(`longblob`,`float8`), +left(`longblob`,`numeric`), +left(`longblob`,`bit1`), +left(`longblob`,`bit64`), +left(`longblob`,`boolean`), +left(`longblob`,`date`), +left(`longblob`,`time`), +left(`longblob`,`time(4)`), +left(`longblob`,`datetime`), +left(`longblob`,`datetime(4)`), +left(`longblob`,`timestamp`), +left(`longblob`,`timestamp(4)`), +left(`longblob`,`year`), +left(`longblob`,`char`), +left(`longblob`,`varchar`), +left(`longblob`,`binary`), +left(`longblob`,`varbinary`), +left(`longblob`,`tinyblob`), +left(`longblob`,`blob`), +left(`longblob`,`mediumblob`), +left(`longblob`,`longblob`), +left(`longblob`,`text`), +left(`longblob`,`enum_t`), +left(`longblob`,`set_t`), +left(`longblob`,`json`), +left(`text`,`int1`), +left(`text`,`uint1`), +left(`text`,`int2`), +left(`text`,`uint2`), +left(`text`,`int4`), +left(`text`,`uint4`), +left(`text`,`int8`), +left(`text`,`uint8`), +left(`text`,`float4`), +left(`text`,`float8`), +left(`text`,`numeric`), +left(`text`,`bit1`), +left(`text`,`bit64`), +left(`text`,`boolean`), +left(`text`,`date`), +left(`text`,`time`), +left(`text`,`time(4)`), +left(`text`,`datetime`), +left(`text`,`datetime(4)`), +left(`text`,`timestamp`), +left(`text`,`timestamp(4)`), +left(`text`,`year`), +left(`text`,`char`), +left(`text`,`varchar`), +left(`text`,`binary`), +left(`text`,`varbinary`), +left(`text`,`tinyblob`), +left(`text`,`blob`), +left(`text`,`mediumblob`), +left(`text`,`longblob`), +left(`text`,`text`), +left(`text`,`enum_t`), +left(`text`,`set_t`), +left(`text`,`json`), +left(`enum_t`,`int1`), +left(`enum_t`,`uint1`), +left(`enum_t`,`int2`), +left(`enum_t`,`uint2`), +left(`enum_t`,`int4`), +left(`enum_t`,`uint4`), +left(`enum_t`,`int8`), +left(`enum_t`,`uint8`), +left(`enum_t`,`float4`), +left(`enum_t`,`float8`), +left(`enum_t`,`numeric`), +left(`enum_t`,`bit1`), +left(`enum_t`,`bit64`), +left(`enum_t`,`boolean`), +left(`enum_t`,`date`), +left(`enum_t`,`time`), +left(`enum_t`,`time(4)`), +left(`enum_t`,`datetime`), +left(`enum_t`,`datetime(4)`), +left(`enum_t`,`timestamp`), +left(`enum_t`,`timestamp(4)`), +left(`enum_t`,`year`), +left(`enum_t`,`char`), +left(`enum_t`,`varchar`), +left(`enum_t`,`binary`), +left(`enum_t`,`varbinary`), +left(`enum_t`,`tinyblob`), +left(`enum_t`,`blob`), +left(`enum_t`,`mediumblob`), +left(`enum_t`,`longblob`), +left(`enum_t`,`text`), +left(`enum_t`,`enum_t`), +left(`enum_t`,`set_t`), +left(`enum_t`,`json`), +left(`set_t`,`int1`), +left(`set_t`,`uint1`), +left(`set_t`,`int2`), +left(`set_t`,`uint2`), +left(`set_t`,`int4`), +left(`set_t`,`uint4`), +left(`set_t`,`int8`), +left(`set_t`,`uint8`), +left(`set_t`,`float4`), +left(`set_t`,`float8`), +left(`set_t`,`numeric`), +left(`set_t`,`bit1`), +left(`set_t`,`bit64`), +left(`set_t`,`boolean`), +left(`set_t`,`date`), +left(`set_t`,`time`), +left(`set_t`,`time(4)`), +left(`set_t`,`datetime`), +left(`set_t`,`datetime(4)`), +left(`set_t`,`timestamp`), +left(`set_t`,`timestamp(4)`), +left(`set_t`,`year`), +left(`set_t`,`char`), +left(`set_t`,`varchar`), +left(`set_t`,`binary`), +left(`set_t`,`varbinary`), +left(`set_t`,`tinyblob`), +left(`set_t`,`blob`), +left(`set_t`,`mediumblob`), +left(`set_t`,`longblob`), +left(`set_t`,`text`), +left(`set_t`,`enum_t`), +left(`set_t`,`set_t`), +left(`set_t`,`json`), +left(`json`,`int1`), +left(`json`,`uint1`), +left(`json`,`int2`), +left(`json`,`uint2`), +left(`json`,`int4`), +left(`json`,`uint4`), +left(`json`,`int8`), +left(`json`,`uint8`), +left(`json`,`float4`), +left(`json`,`float8`), +left(`json`,`numeric`), +left(`json`,`bit1`), +left(`json`,`bit64`), +left(`json`,`boolean`), +left(`json`,`date`), +left(`json`,`time`), +left(`json`,`time(4)`), +left(`json`,`datetime`), +left(`json`,`datetime(4)`), +left(`json`,`timestamp`), +left(`json`,`timestamp(4)`), +left(`json`,`year`), +left(`json`,`char`), +left(`json`,`varchar`), +left(`json`,`binary`), +left(`json`,`varbinary`), +left(`json`,`tinyblob`), +left(`json`,`blob`), +left(`json`,`mediumblob`), +left(`json`,`longblob`), +left(`json`,`text`), +left(`json`,`enum_t`), +left(`json`,`set_t`), +left(`json`,`json`) +from test_type_table; +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +SQL function "left" statement 1 +referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a " +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "1.23a" +CONTEXT: referenced column: left +WARNING: invalid input syntax for type numeric: "{"a": 1, "b": 2}" +CONTEXT: referenced column: left +-[ RECORD 1 ]---------------------------------------------------------------------------------------------- +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.00000 +left | 1 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1.000000 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.000 +left | +left | \200 +left | \200 +left | \200 +left | \200 +left | \001 +left | \200 +left | \200 +left | \200 +left | \200 +left | \200 +left | \200 +left | \001 +left | \001 +left | \200 +left | \001 +left | \200 +left | \200 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \001 +left | \200 +left | \200 +left | +left | +left | +left | +left | +left | \000 +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023-02 +left | 2 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2023-02-05 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023- +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 19:10:5 +left | 1 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 19:10:50 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 19:10 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 19:10:5 +left | 1 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 19:10:50.3456 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 19:10 +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023-02 +left | 2 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2023-02-05 19:10:50 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023- +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023-02 +left | 2 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2023-02-05 19:10:50.456 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023- +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023-02 +left | 2 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2023-02-05 19:10:50-08 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023- +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023-02 +left | 2 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2023-02-05 19:10:50.456-08 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023- +left | +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023 +left | 2 +left | 2023 +left | 2023 +left | 2023 +left | 2023 +left | 2023 +left | 2023 +left | 2023 +left | 2023 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2 +left | 2023 +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | 1 +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1.23a +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1 +left | 1.23a +left | +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a,c +left | a +left | a,c +left | a,c +left | a,c +left | a,c +left | a,c +left | a,c +left | a,c +left | a,c +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a +left | a,c +left | +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | {"a": 1 +left | { +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | {"a": 1, "b": 2} +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | { +left | {"a": +left | + +drop table test_type_table; +select right('2022-12-12',b'1010'); +-[ RECORD 1 ]----- +right | 2022-12-12 + +select right(b'1001010','2022-12-12'); +WARNING: invalid input syntax for type numeric: "2022-12-12" +CONTEXT: referenced column: right +SQL function "right" statement 1 +referenced column: right +-[ RECORD 1 ] +right | J + +select right(false,2); +-[ RECORD 1 ] +right | 0 + +select left('2022-12-12',b'1010'); +-[ RECORD 1 ]---- +left | 2022-12-12 + drop schema db_b_left_right_test cascade; reset current_schema; diff --git a/contrib/dolphin/expected/string_func_test/db_b_substr_test.out b/contrib/dolphin/expected/string_func_test/db_b_substr_test.out index 25b1a11393f583dd0a65834a43f2160e4e323b55..368c5cf35cf51878f1e5cf9dbfe8ebae74c3df59 100644 --- a/contrib/dolphin/expected/string_func_test/db_b_substr_test.out +++ b/contrib/dolphin/expected/string_func_test/db_b_substr_test.out @@ -241,74 +241,74 @@ SELECT SUBSTR(b FOR -1) FROM template_string; (1 row) SELECT SUBSTRING(a FROM 1) FROM template_string; - substring + substr ---------------------------- abcdefghijklmnopqrstuvwxyz (1 row) SELECT SUBSTRING(a FROM 0) FROM template_string; - substring ------------ + substr +-------- (1 row) SELECT SUBSTRING(a FROM -1) FROM template_string; - substring ------------ + substr +-------- z (1 row) SELECT SUBSTRING(a FOR 1) FROM template_string; - substring ------------ + substr +-------- a (1 row) SELECT SUBSTRING(a FOR 0) FROM template_string; - substring ------------ + substr +-------- (1 row) SELECT SUBSTRING(a FOR -1) FROM template_string; - substring ------------ + substr +-------- (1 row) SELECT SUBSTRING(b FROM 1) FROM template_string; - substring + substr ---------------------------- abcdefghijklmnopqrstuvwxyz (1 row) SELECT SUBSTRING(b FROM 0) FROM template_string; - substring ------------ + substr +-------- (1 row) SELECT SUBSTRING(b FROM -1) FROM template_string; - substring ------------ + substr +-------- z (1 row) SELECT SUBSTRING(b FOR 1) FROM template_string; - substring ------------ + substr +-------- a (1 row) SELECT SUBSTRING(b FOR 0) FROM template_string; - substring ------------ + substr +-------- (1 row) SELECT SUBSTRING(b FOR -1) FROM template_string; - substring ------------ + substr +-------- (1 row) @@ -398,38 +398,38 @@ SELECT MID(b FOR -1) FROM template_string; -- The input is in hexadecimal format. Two hexadecimal digits are one byte. The substring is obtained by byte. select substring(E'\\xDEADBEEF'::bytea,2); - substring + substr -------------- \255\276\357 (1 row) select substring(E'\\xDEADBEEF'::bytea,2,2); - substring ------------ + substr +---------- \255\276 (1 row) select substring(E'\\xDEADBEEF'::bytea,2,8); - substring + substr -------------- \255\276\357 (1 row) select substring(E'\\xDEADBEEF'::bytea,2,10); - substring + substr -------------- \255\276\357 (1 row) select substring(E'\\xDEADBEEF'::bytea,2,0); - substring ------------ + substr +-------- (1 row) select substring(E'\\xDEADBEEF'::bytea,2,-1); - substring ------------ + substr +-------- (1 row) @@ -511,32 +511,32 @@ create table test_row (c1 text, c2 int); insert into test_column values('abcdefg', 2), ('abcdefg', 0), ('abcdefg', -2); insert into test_row(c1, c2) select c1, c2 from test_column; select c1, c2, substring(c1 from c2) from test_column order by c1; - c1 | c2 | substring ----------+----+----------- + c1 | c2 | substr +---------+----+-------- abcdefg | 2 | bcdefg abcdefg | 0 | abcdefg | -2 | fg (3 rows) select c1, c2, substring(c1 from c2) from test_row order by c1; - c1 | c2 | substring ----------+----+----------- + c1 | c2 | substr +---------+----+-------- abcdefg | 2 | bcdefg abcdefg | 0 | abcdefg | -2 | fg (3 rows) select c1, c2, substring(c1 for c2) from test_column order by c1; - c1 | c2 | substring ----------+----+----------- + c1 | c2 | substr +---------+----+-------- abcdefg | 2 | ab abcdefg | 0 | abcdefg | -2 | (3 rows) select c1, c2, substring(c1 for c2) from test_row order by c1; - c1 | c2 | substring ----------+----+----------- + c1 | c2 | substr +---------+----+-------- abcdefg | 2 | ab abcdefg | 0 | abcdefg | -2 | @@ -575,77 +575,98 @@ select c1, c2, substr(c1 for c2) from test_row order by c1; (3 rows) select substring(b'11' from b'10010'); - substring ------------ + substr +-------- (1 row) select substring(b'10010' from b'11'); - substring ------------ + substr +-------- 010 (1 row) select substring('11'::bytea from b'10010'); - substring ------------ + substr +-------- (1 row) select substring('10010'::bytea from b'11'); - substring ------------ + substr +-------- 010 (1 row) select substring('11'::text from b'10010'); - substring ------------ + substr +-------- (1 row) select substring('10010'::text from b'11'); - substring ------------ + substr +-------- 010 (1 row) select substring(b'11', b'10010'); - substring ------------ + substr +-------- (1 row) select substring(b'10010', b'11'); - substring ------------ + substr +-------- 010 (1 row) select substring('11'::bytea, b'10010'); - substring ------------ + substr +-------- (1 row) select substring('10010'::bytea, b'11'); - substring ------------ + substr +-------- 010 (1 row) select substring('11'::text, b'10010'); - substring ------------ + substr +-------- (1 row) select substring('10010'::text, b'11'); - substring ------------ + substr +-------- 010 (1 row) +select substr('abcd', '2', '3'); + substr +-------- + bcd +(1 row) + +drop table if exists t_substring_0033; +NOTICE: table "t_substring_0033" does not exist, skipping +create table t_substring_0033 (c1 text ,c2 varchar(20),c3 text); +insert t_substring_0033 value('0/8',b'010','22cc'); +select substring(c1,c2,c3) from t_substring_0033; +--?WARNING: invalid input syntax for type bigint.* +CONTEXT: referenced column: substr +WARNING: invalid input syntax for type bigint: "22cc" +CONTEXT: referenced column: substr + substr +-------- + +(1 row) + +drop table t_substring_0033; drop schema db_b_substr_test cascade; NOTICE: drop cascades to 3 other objects DETAIL: drop cascades to table template_string diff --git a/contrib/dolphin/expected/test_alter_table.out b/contrib/dolphin/expected/test_alter_table.out index 9822c7a730f9173f6670fd0a9a2b7e70e8464adc..59b2074130f6d42a3ca88e0d07bbeef0d8fda2d6 100644 --- a/contrib/dolphin/expected/test_alter_table.out +++ b/contrib/dolphin/expected/test_alter_table.out @@ -565,8 +565,19 @@ and locktype = 'relation' and relnamespace != (select oid from pg_namespace where nspname = 'pg_catalog') and c.relname != 'my_locks' group by c.relname; +-- test column table with alter table drop index +drop table if exists t_grammar0029; +NOTICE: table "t_grammar0029" does not exist, skipping +create table t_grammar0029(id int unique, sex text) +with(orientation=column); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_grammar0029_id_key" for table "t_grammar0029" +drop index if exists id_grammar0029; +NOTICE: index "id_grammar0029" does not exist, skipping +create index id_grammar0029 on t_grammar0029 using psort(id) tablespace pg_default; +alter table t_grammar0029 drop key id_grammar0029; drop schema db_alter_table cascade; -NOTICE: drop cascades to 2 other objects +NOTICE: drop cascades to 3 other objects DETAIL: drop cascades to type lockmodes drop cascades to view my_locks +drop cascades to table t_grammar0029 reset current_schema; diff --git a/contrib/dolphin/expected/test_charset_collate.out b/contrib/dolphin/expected/test_charset_collate.out index 8f7644203de3914f63e9fa963b0b143cd49e927b..58d56243a0f497c013461ebc9436cc985d078e66 100644 --- a/contrib/dolphin/expected/test_charset_collate.out +++ b/contrib/dolphin/expected/test_charset_collate.out @@ -146,6 +146,17 @@ WARNING: Invalid collation for column c1 detected. default value set create table test_collate5(c1 text collate 'aaa', c2 text collate 'utf8mb4_bin', c3 text)collate 'aaa'; WARNING: Invalid collation for column c1 detected. default value set WARNING: Invalid collation detected. default value set +-- different charset +show b_format_behavior_compat_options; + b_format_behavior_compat_options +---------------------------------- + +(1 row) + +create table test_collate6(a text) charset gbk; +ERROR: difference between the charset and the database encoding has not supported +create table test_collate6(a text) collate gbk_bin; +ERROR: difference between the charset and the database encoding has not supported -- invalid schema collate create schema test1 charset 'aaa'; WARNING: aaa is not a valid encoding name. default value set diff --git a/contrib/dolphin/expected/test_datatype.out b/contrib/dolphin/expected/test_datatype.out index d1cb913919b57bb90fe9e8141116976b55bf9b27..dfeb4f5c0d7a66a27d3780668e9d12bdc8fa858c 100644 --- a/contrib/dolphin/expected/test_datatype.out +++ b/contrib/dolphin/expected/test_datatype.out @@ -509,5 +509,60 @@ select * from t_bit; drop table test_bit64; drop table t_bit; +-- test treat_float_with_precision_as_float_type +create table test_double(c1 double, c2 double(10, 0), c3 double(15, 3), c4 float, c5 float4, c6 float4(10, 0), c7 float4(7, 5), c8 float(10, 0), c9 float(7, 5), c10 float4(5)); +\d+ test_double; + Table "b_datatype_test.test_double" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------------------+-----------+---------+--------------+------------- + c1 | double precision | | plain | | + c2 | real | | plain | | + c3 | numeric(15,3) | | main | | + c4 | real | | plain | | + c5 | real | | plain | | + c6 | numeric(10,0) | | main | | + c7 | numeric(7,5) | | main | | + c8 | real | | plain | | + c9 | numeric(7,5) | | main | | + c10 | real | | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +drop table test_double; +set dolphin.treat_float_with_precision_as_float_type = true; +create table test_double(c1 double, c2 double(10, 0), c3 double(15, 3), c4 float, c5 float4, c6 float4(10, 0), c7 float4(7, 5), c8 float(10, 0), c9 float(7, 5), c10 float4(5)); +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +NOTICE: it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on. +\d+ test_double; + Table "b_datatype_test.test_double" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------------------+-----------+---------+--------------+------------- + c1 | double precision | | plain | | + c2 | double precision | | plain | | + c3 | double precision | | plain | | + c4 | real | | plain | | + c5 | real | | plain | | + c6 | real | | plain | | + c7 | real | | plain | | + c8 | real | | plain | | + c9 | real | | plain | | + c10 | real | | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +insert into test_double values (12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456); +select * from test_double; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 +---------+---------+---------+---------+---------+---------+---------+---------+---------+--------- + 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 | 12.3456 +(1 row) + +drop table test_double; +reset dolphin.treat_float_with_precision_as_float_type; drop schema b_datatype_test cascade; reset current_schema; diff --git a/contrib/dolphin/expected/test_geometric_operator.out b/contrib/dolphin/expected/test_geometric_operator.out new file mode 100644 index 0000000000000000000000000000000000000000..e5c1ec61fc0fca058958199e763e86c7e762f065 --- /dev/null +++ b/contrib/dolphin/expected/test_geometric_operator.out @@ -0,0 +1,186 @@ +create schema test_geometric_operator; +set current_schema to 'test_geometric_operator'; +set dolphin.b_compatibility_mode to off; +SELECT box '((0,0),(1,1))' + point '(2.0,0)' AS RESULT; + RESULT +------------- + (3,1),(2,0) +(1 row) + +SELECT box '((0,0),(1,1))' - point '(2.0,0)' AS RESULT; + RESULT +--------------- + (-1,1),(-2,0) +(1 row) + +SELECT box '((0,0),(1,1))' * point '(2.0,0)' AS RESULT; + RESULT +------------- + (2,2),(0,0) +(1 row) + +SELECT box '((0,0),(2,2))' / point '(2.0,0)' AS RESULT; + RESULT +------------- + (1,1),(0,0) +(1 row) + +SELECT box '((1,-1),(-1,1))' # box '((1,1),(-2,-2))' AS RESULT; + RESULT +--------------- + (1,1),(-1,-1) +(1 row) + +SELECT # path'((1,0),(0,1),(-1,0))' AS RESULT; + RESULT +-------- + 3 +(1 row) + +SELECT @-@ path '((0,0),(1,0))' AS RESULT; + RESULT +-------- + 2 +(1 row) + +SELECT @@ circle '((0,0),10)' AS RESULT; + RESULT +-------- + (0,0) +(1 row) + +SELECT circle '((0,0),1)' <-> circle '((5,0),1)' AS RESULT; + RESULT +-------- + 3 +(1 row) + +SELECT box '((0,0),(1,1))' && box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT circle '((0,0),1)' << circle '((5,0),1)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT circle '((5,0),1)' >> circle '((0,0),1)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(1,1))' &< box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(3,3))' &> box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(3,3))' <<| box '((3,4),(5,5))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((3,4),(5,5))' |>> box '((0,0),(3,3))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(1,1))' &<| box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(3,3))' |&> box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(-3,-3))' <^ box '((0,0),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT box '((0,0),(2,2))' >^ box '((0,0),(-3,-3))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT ?- lseg '((-1,0),(1,0))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT point '(1,0)' ?- point '(0,0)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT ?| lseg '((-1,0),(1,0))' AS RESULT; + RESULT +-------- + f +(1 row) + +SELECT point '(0,1)' ?| point '(0,0)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT circle '((0,0),2)' @> point '(1,1)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT point '(1,1)' <@ circle '((0,0),2)' AS RESULT; + RESULT +-------- + t +(1 row) + +SELECT polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))' AS RESULT; + RESULT +-------- + t +(1 row) + +reset dolphin.b_compatibility_mode; +drop schema test_geometric_operator cascade; +reset current_schema; diff --git a/contrib/dolphin/expected/test_interval_expr.out b/contrib/dolphin/expected/test_interval_expr.out index 0ddbc970b94cc58dcb5545043e29900220c09612..279fccb614562c34874317533c517f46048bd665 100644 --- a/contrib/dolphin/expected/test_interval_expr.out +++ b/contrib/dolphin/expected/test_interval_expr.out @@ -292,6 +292,132 @@ select interval '1 2' second_microsecond; select interval '1 2' second to microsecond; ERROR: interval second to microsecond is not supported +select interval 1 year year; + year +---------- + @ 1 year +(1 row) + +select interval 1 month month; + month +--------- + @ 1 mon +(1 row) + +select interval 1 day day; + day +--------- + @ 1 day +(1 row) + +select interval 1 hour hour; + hour +---------- + @ 1 hour +(1 row) + +select interval 1 minute minute; + minute +--------- + @ 1 min +(1 row) + +select interval 1 second second; + second +--------- + @ 1 sec +(1 row) + +select date'20020304' + interval 1 hour; + ?column? +--------------------- + 2002-03-04 01:00:00 +(1 row) + +select interval 1 hour + date'20020304'; + ?column? +--------------------- + 2002-03-04 01:00:00 +(1 row) + +select date'20020304' - interval 1 hour; + ?column? +--------------------- + 2002-03-03 23:00:00 +(1 row) + +select date'20020304' + interval 1 minute; + ?column? +--------------------- + 2002-03-04 00:01:00 +(1 row) + +select interval 1 minute + date'20020304'; + ?column? +--------------------- + 2002-03-04 00:01:00 +(1 row) + +select date'20020304' - interval 1 minute; + ?column? +--------------------- + 2002-03-03 23:59:00 +(1 row) + +select date'20020304' + interval 1 second; + ?column? +--------------------- + 2002-03-04 00:00:01 +(1 row) + +select interval 1 second + date'20020304'; + ?column? +--------------------- + 2002-03-04 00:00:01 +(1 row) + +select date'20020304' - interval 1 second; + ?column? +--------------------- + 2002-03-03 23:59:59 +(1 row) + +select date'20020304' * interval 1 hour; + ?column? +----------------------- + @ 834179 days 8 hours +(1 row) + +select date'20020304' / interval 1 hour; + ?column? +------------------- + 480487295999999.6 +(1 row) + +select date'20020304' * interval 1 minute; + ?column? +------------------------------- + @ 13902 days 23 hours 44 mins +(1 row) + +select date'20020304' / interval 1 minute; + ?column? +----------------------- + 2.882923776000002e+16 +(1 row) + +select date'20020304' * interval 1 second; + ?column? +------------------------------------- + @ 231 days 17 hours 11 mins 44 secs +(1 row) + +select date'20020304' / interval 1 second; + ?column? +----------------------- + 1.729754265599996e+18 +(1 row) + create table k_1(a json,b blob,c longblob,d mediumblob,e tinyblob,f binary(20)); insert k_1 values('"2024-01-11 11:49:25"','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25'); select `a`+ interval 1 day,`b`+ interval 1 day,`c`+ interval 1 day,`d`+ interval 1 day,`e`+ interval 1 day,`f`+ interval 1 day from k_1; @@ -965,6 +1091,487 @@ CONTEXT: referenced column: date_sub (1 row) set dolphin.cmpt_version=5.7; +select date_add('2022-06-10 15:15:15', -10::interval year ) as updated_date; + updated_date +--------------------- + 2012-06-10 15:15:15 +(1 row) + +select date_sub('2022-06-10 15:15:15', -10::interval year ) as updated_date; + updated_date +--------------------- + 2032-06-10 15:15:15 +(1 row) + +select date_add('2022-06-10 15:15:15', -10::interval hour ) as updated_date; + updated_date +--------------------- + 2022-06-10 05:15:15 +(1 row) + +select date_sub('2022-06-10 15:15:15', -10::interval hour ) as updated_date; + updated_date +--------------------- + 2022-06-11 01:15:15 +(1 row) + +select date_add('2022-06-10 15:15:15', 10::interval year ) as updated_date; + updated_date +--------------------- + 2032-06-10 15:15:15 +(1 row) + +select date_sub('2022-06-10 15:15:15', 10::interval year ) as updated_date; + updated_date +--------------------- + 2012-06-10 15:15:15 +(1 row) + +select date_add('2022-06-10 15:15:15', 10::interval hour ) as updated_date; + updated_date +--------------------- + 2022-06-11 01:15:15 +(1 row) + +select date_sub('2022-06-10 15:15:15', 10::interval hour ) as updated_date; + updated_date +--------------------- + 2022-06-10 05:15:15 +(1 row) + +-- 运算 +select '2024-07-05 14:25:59' + interval 1 minute + 1; + ?column? +---------------- + 20240705142660 +(1 row) + +select '2024-07-05' + interval 1 minute + 1; + ?column? +---------------- + 20240705000101 +(1 row) + +select '2024-07-05 14:25:59' + interval 1 year + 1; + ?column? +---------------- + 20250705142560 +(1 row) + +select '2024-07-05' + interval 1 year + 1; + ?column? +---------- + 20250706 +(1 row) + +select '2024-07-05 14:25:59' + interval 1 day + 1; + ?column? +---------------- + 20240706142560 +(1 row) + +select '2024-07-05' + interval 1 day + 1; + ?column? +---------- + 20240707 +(1 row) + +select '2024-07-05 14:25:59' + interval 1 year_month + 1; + ?column? +---------------- + 20240805142560 +(1 row) + +select '2024-07-05' + interval 1 year_month + 1; + ?column? +---------- + 20240806 +(1 row) + +select '2024-07-05 14:25:59' + interval 1 day_hour + 1; + ?column? +---------------- + 20240705152560 +(1 row) + +select '2024-07-05' + interval 1 day_hour + 1; + ?column? +---------------- + 20240705010001 +(1 row) + +select interval 1 minute + '2024-07-05 14:25:59' + 1; + ?column? +---------------- + 20240705142660 +(1 row) + +select interval 1 minute + '2024-07-05' + 1; + ?column? +---------------- + 20240705000101 +(1 row) + +select interval 1 year +'2024-07-05 14:25:59' + 1; + ?column? +---------------- + 20250705142560 +(1 row) + +select interval 1 year + '2024-07-05' + 1; + ?column? +---------- + 20250706 +(1 row) + +select interval 1 day + '2024-07-05 14:25:59' + 1; + ?column? +---------------- + 20240706142560 +(1 row) + +select interval 1 day + '2024-07-05' + 1; + ?column? +---------- + 20240707 +(1 row) + +select interval 1 year_month + '2024-07-05 14:25:59' + 1; + ?column? +---------------- + 20240805142560 +(1 row) + +select interval 1 year_month + '2024-07-05' + interval 1 year_month + 1; + ?column? +---------- + 20240906 +(1 row) + +select interval 1 day_hour + '2024-07-05 14:25:59' + 1; + ?column? +---------------- + 20240705152560 +(1 row) + +select interval 1 day_hour + '2024-07-05' + 1; + ?column? +---------------- + 20240705010001 +(1 row) + +select '2024-07-05 14:25:59' - interval 1 minute + 1; + ?column? +---------------- + 20240705142460 +(1 row) + +select '2024-07-05' - interval 1 minute + 1; + ?column? +---------------- + 20240704235901 +(1 row) + +select '2024-07-05 14:25:59' - interval 1 year + 1; + ?column? +---------------- + 20230705142560 +(1 row) + +select '2024-07-05' - interval 1 year + 1; + ?column? +---------- + 20230706 +(1 row) + +select '2024-07-05 14:25:59' - interval 1 day + 1; + ?column? +---------------- + 20240704142560 +(1 row) + +select '2024-07-05' - interval 1 day + 1; + ?column? +---------- + 20240705 +(1 row) + +select '2024-07-05 14:25:59' - interval 1 year_month + 1; + ?column? +---------------- + 20240605142560 +(1 row) + +select '2024-07-05' - interval 1 year_month + 1; + ?column? +---------- + 20240606 +(1 row) + +select '2024-07-05 14:25:59' - interval 1 day_hour + 1; + ?column? +---------------- + 20240705132560 +(1 row) + +select '2024-07-05' - interval 1 day_hour + 1; + ?column? +---------------- + 20240704230001 +(1 row) + +select '20230205231050.968789' + interval 1 minute; + ?column? +---------------------------- + 2023-02-05 23:11:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 hour; + ?column? +---------------------------- + 2023-02-06 00:10:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 year; + ?column? +---------------------------- + 2024-02-05 23:10:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 day; + ?column? +---------------------------- + 2023-02-06 23:10:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 year_month; + ?column? +---------------------------- + 2023-03-05 23:10:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 day_hour; + ?column? +---------------------------- + 2023-02-06 00:10:50.968789 +(1 row) + +select '20230205231050.968789' + interval 1 day_microsecond; + ?column? +---------------------------- + 2023-02-05 23:10:51.068789 +(1 row) + +select interval 1 minute + '20230205231050.968789'; + ?column? +---------------------------- + 2023-02-05 23:11:50.968789 +(1 row) + +select interval 1 hour + '20230205231050.968789'; + ?column? +---------------------------- + 2023-02-06 00:10:50.968789 +(1 row) + +select interval 1 year + '20230205231050.968789'; + ?column? +---------------------------- + 2024-02-05 23:10:50.968789 +(1 row) + +select interval 1 day + '20230205231050.968789'; + ?column? +---------------------------- + 2023-02-06 23:10:50.968789 +(1 row) + +select interval 1 year_month + '20230205231050.968789'; + ?column? +---------------------------- + 2023-03-05 23:10:50.968789 +(1 row) + +select interval 1 day_hour + '20230205231050.968789'; + ?column? +---------------------------- + 2023-02-06 00:10:50.968789 +(1 row) + +select interval 1 day_microsecond + '20230205231050.968789'; + ?column? +---------------------------- + 2023-02-05 23:10:51.068789 +(1 row) + +select '20230205231050.968789' - interval 1 minute; + ?column? +---------------------------- + 2023-02-05 23:09:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 hour; + ?column? +---------------------------- + 2023-02-05 22:10:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 year; + ?column? +---------------------------- + 2022-02-05 23:10:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 day; + ?column? +---------------------------- + 2023-02-04 23:10:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 year_month; + ?column? +---------------------------- + 2023-01-05 23:10:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 day_hour; + ?column? +---------------------------- + 2023-02-05 22:10:50.968789 +(1 row) + +select '20230205231050.968789' - interval 1 day_microsecond; + ?column? +---------------------------- + 2023-02-05 23:10:50.868789 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 day_microsecond; + ?column? +---------------------------- + 2023-02-28 14:26:00.099999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 year; + ?column? +---------------------------- + 2024-02-28 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 month; + ?column? +---------------------------- + 2023-03-28 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 day; + ?column? +---------------------------- + 2023-03-01 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 hour; + ?column? +---------------------------- + 2023-02-28 15:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 minute; + ?column? +---------------------------- + 2023-02-28 14:26:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' + interval 1 second; + ?column? +---------------------------- + 2023-02-28 14:26:00.999999 +(1 row) + +select interval 1 day_microsecond + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-02-28 14:26:00.099999 +(1 row) + +select interval 1 year + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2024-02-28 14:25:59.999999 +(1 row) + +select interval 1 month + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-03-28 14:25:59.999999 +(1 row) + +select interval 1 day + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-03-01 14:25:59.999999 +(1 row) + +select interval 1 hour + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-02-28 15:25:59.999999 +(1 row) + +select interval 1 minute + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-02-28 14:26:59.999999 +(1 row) + +select interval 1 second + '2023-02-28 14:25:59.999999'; + ?column? +---------------------------- + 2023-02-28 14:26:00.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 day_microsecond; + ?column? +---------------------------- + 2023-02-28 14:25:59.899999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 year; + ?column? +---------------------------- + 2022-02-28 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 month; + ?column? +---------------------------- + 2023-01-28 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 day; + ?column? +---------------------------- + 2023-02-27 14:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 hour; + ?column? +---------------------------- + 2023-02-28 13:25:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 minute; + ?column? +---------------------------- + 2023-02-28 14:24:59.999999 +(1 row) + +select '2023-02-28 14:25:59.999999' - interval 1 second; + ?column? +---------------------------- + 2023-02-28 14:25:58.999999 +(1 row) + -- 全类型兼容 create table all_types_table ( `int1` tinyint, @@ -6342,6 +6949,66 @@ WARNING: date/time field overflow (1 row) +select '2003-11-11 00:00:50'::blob + interval '2' second; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select interval '2' second + '2003-11-11 00:00:50'::blob; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select '2003-11-11 00:00:50'::longblob + interval '2' second; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select interval '2' second + '2003-11-11 00:00:50'::longblob; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select '2003-11-11 00:00:50'::mediumblob + interval '2' second; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select interval '2' second + '2003-11-11 00:00:50'::mediumblob; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select '2003-11-11 00:00:50'::tinyblob + interval '2' second; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select interval '2' second + '2003-11-11 00:00:50'::tinyblob; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select '20031111000050'::json + interval '2' second; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + +select interval '2' second + '20031111000050'::json; + ?column? +--------------------- + 2003-11-11 00:00:52 +(1 row) + drop table all_types_table cascade; drop schema test_interval_expr cascade; NOTICE: drop cascades to 5 other objects diff --git a/contrib/dolphin/expected/test_mysql_enum.out b/contrib/dolphin/expected/test_mysql_enum.out index 2b69446c6284a5554fe0e52db602b0576f802694..8b135d43b89a862a541d9c570215bb8dfdbab0db 100644 --- a/contrib/dolphin/expected/test_mysql_enum.out +++ b/contrib/dolphin/expected/test_mysql_enum.out @@ -799,3 +799,70 @@ ERROR: duplicate key value violates unique constraint "pg_enum_typid_label_inde --expect success CREATE TYPE typenum AS ENUM ( 'a', ' a'); DROP TYPE typenum; +create table enum_test_table1(a enum('2024-07-05', '2024-07-05 14:59:58', '14:59:59')); +insert enum_test_table1 values('2024-07-05'), ('2024-07-05 14:59:58'), ('14:59:59'); +select a + interval 1 day as 'a + interval 1 day' from enum_test_table1; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: a + interval 1 day + a + interval 1 day +--------------------- + 2024-07-06 + 2024-07-06 14:59:58 + +(3 rows) + +select interval 1 day + a as 'interval 1 day + a' from enum_test_table1; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: interval 1 day + a + interval 1 day + a +--------------------- + 2024-07-06 + 2024-07-06 14:59:58 + +(3 rows) + +select a - interval 1 day as 'a - interval 1 day' from enum_test_table1; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: a - interval 1 day + a - interval 1 day +--------------------- + 2024-07-04 + 2024-07-04 14:59:58 + +(3 rows) + +drop table enum_test_table1; +create table set_t(a set('2024-07-05', '2024-07-05 14:59:58', '14:59:59')); +NOTICE: CREATE TABLE will create implicit set "set_t_a_set" for column "set_t.a" +insert set_t values('2024-07-05'), ('2024-07-05 14:59:58'), ('14:59:59'); +select a + interval 1 day as 'a + interval 1 day' from set_t; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: a + interval 1 day + a + interval 1 day +--------------------- + 2024-07-06 + 2024-07-06 14:59:58 + +(3 rows) + +select interval 1 day + a as 'interval 1 day + a' from set_t; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: interval 1 day + a + interval 1 day + a +--------------------- + 2024-07-06 + 2024-07-06 14:59:58 + +(3 rows) + +select a - interval 1 day as 'a - interval 1 day' from set_t; +WARNING: Incorrect datetime value: "14:59:59" +CONTEXT: referenced column: a - interval 1 day + a - interval 1 day +--------------------- + 2024-07-04 + 2024-07-04 14:59:58 + +(3 rows) + +drop table set_t; diff --git a/contrib/dolphin/expected/test_proxy.out b/contrib/dolphin/expected/test_proxy.out index 7c6e29d9214740ad904b05af285675c00df60a43..8d5103433edc90b39aa7271e91e7f96bb530fbee 100644 --- a/contrib/dolphin/expected/test_proxy.out +++ b/contrib/dolphin/expected/test_proxy.out @@ -116,6 +116,16 @@ reset b_compatibility_user_host_auth; drop role test_proxy_u1; drop role test_proxy_u2; drop role test_proxy_u3; +-- test PROXY as colname +create table t1 (proxy int); +insert into t1 values (1); +select proxy from t1; + proxy +------- + 1 +(1 row) + +drop table t1; drop schema db_proxy cascade; drop schema tst_schema1 cascade; NOTICE: drop cascades to table tst_t1 diff --git a/contrib/dolphin/expected/test_shows_3.out b/contrib/dolphin/expected/test_shows_3.out index 959f3ec57ff806a878037a760a77f18701f9f861..85fa6d079e368705e66e46663ac2305f3e2d646c 100644 --- a/contrib/dolphin/expected/test_shows_3.out +++ b/contrib/dolphin/expected/test_shows_3.out @@ -22,7 +22,8 @@ show databases; sc snapshot sqladvisor -(19 rows) + xmltype +(20 rows) create schema aa1; create schema aa2; @@ -77,7 +78,8 @@ show databases; public sqladvisor u1 -(11 rows) + xmltype +(12 rows) set role u2 password 'abc@1234'; show databases; @@ -94,7 +96,8 @@ show databases; public sqladvisor u2 -(11 rows) + xmltype +(12 rows) \c contrib_regression drop user u1; diff --git a/contrib/dolphin/expected/test_uuid_short.out b/contrib/dolphin/expected/test_uuid_short.out index 78a601747c2540589a02fc9aace348e0c71fe6fe..7c8d33c34df3f6227975daf41d3458b1bf00d0cc 100644 --- a/contrib/dolphin/expected/test_uuid_short.out +++ b/contrib/dolphin/expected/test_uuid_short.out @@ -12,5 +12,17 @@ select uuid_short(); --? (1 row) +select uuid(null); +ERROR: function uuid(unknown) does not exist +LINE 1: select uuid(null); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: uuid +select uuid(1); +ERROR: function uuid(integer) does not exist +LINE 1: select uuid(1); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CONTEXT: referenced column: uuid drop schema test_uuid_short cascade; reset current_schema; diff --git a/contrib/dolphin/expected/tinyint_agg.out b/contrib/dolphin/expected/tinyint_agg.out index f660c57a92a82c1655bb1aba28af1417b5dd154a..9e79256bf9458ab9ae5a58cf40feef6b1eec3e40 100644 --- a/contrib/dolphin/expected/tinyint_agg.out +++ b/contrib/dolphin/expected/tinyint_agg.out @@ -11,7 +11,7 @@ select avg(a), avg(b) from u1; select bit_and(a), bit_and(b) from u1; bit_and | bit_and ---------+--------- - 0 | 0 + 0 | 0 (1 row) select bit_or(a), bit_or(b) from u1; @@ -177,11 +177,11 @@ explain(costs off, verbose) select bit_and(a) from smp_test; QUERY PLAN ---------------------------------------------------- Aggregate - Output: bit_and((bit_and(a))) + Output: bit_and((pg_catalog.bit_and(a))) -> Streaming(type: LOCAL GATHER dop: 1/2) - Output: (bit_and(a)) + Output: (pg_catalog.bit_and(a)) -> Aggregate - Output: bit_and(a) + Output: pg_catalog.bit_and(a) -> Seq Scan on tinyint_agg.smp_test Output: a (8 rows) diff --git a/contrib/dolphin/expected/uint_agg.out b/contrib/dolphin/expected/uint_agg.out index 196047fcbc85d4b45da20de10740812050a8a684..ec37eee1bd88bda04e11baf3302dc5d1ff92d256 100644 --- a/contrib/dolphin/expected/uint_agg.out +++ b/contrib/dolphin/expected/uint_agg.out @@ -12,7 +12,7 @@ select avg(a), avg(b) from u1; select bit_and(a), bit_and(b) from u1; bit_and | bit_and ---------+--------- - 0 | 0 + 0 | 0 (1 row) select bit_or(a), bit_or(b) from u1; @@ -111,7 +111,7 @@ select avg(a), avg(b) from u2; select bit_and(a), bit_and(b) from u2; bit_and | bit_and ---------+--------- - 0 | 0 + 0 | 0 (1 row) select bit_or(a), bit_or(b) from u2; @@ -210,7 +210,7 @@ select avg(a), avg(b) from u4; select bit_and(a), bit_and(b) from u4; bit_and | bit_and ---------+--------- - 0 | 0 + 0 | 0 (1 row) select bit_or(a), bit_or(b) from u4; @@ -399,6 +399,74 @@ select listagg(a, ',') within group(order by a) from u8; create table smp_test(a uint4, b uint8); insert into smp_test select generate_series(1, 100000), generate_series(2, 100001); insert into smp_test select a + 100000, b from smp_test; +-- varbinary test +set dolphin.sql_mode = ''; +drop table if exists t; +NOTICE: table "t" does not exist, skipping +CREATE TABLE t(i INT, li BIGINT, b VARBINARY(8), lb VARBINARY(24), d DOUBLE GENERATED ALWAYS AS (i*1.0)); +INSERT INTO t(i, li, b, lb) VALUES +(NULL, NULL, NULL, NULL), +(0, 0, X'0000000000000000', +X'000000000000000000000000000000000000000000000000'), +(0, 0, X'0000000000000000', +X'000000000000000000000000000000000000000000000000'), +(1, 1, X'0000000000000001', +X'000000000000000000000000000000000000000000000001'), +(1, 1, X'0000000000000001', +X'000000000000000000000000000000000000000000000001'), +(2, 2, X'0000000000000002', +X'000000000000000000000000000000000000000000000002'), +(2, 2, X'0000000000000002', +X'000000000000000000000000000000000000000000000002'), +(3, 3, X'0000000000000003', +X'000000000000000000000000000000000000000000000003'), +(3, 3, X'0000000000000003', +X'000000000000000000000000000000000000000000000003'), +(4, 4, X'0000000000000004', +X'000000000000000000000000000000000000000000000004'), +(4, 4, X'0000000000000004', +X'000000000000000000000000000000000000000000000004'), +(5, 5, X'0000000000000005', +X'000000000000000000000000000000000000000000000005'), +(6, 6, X'0000000000000006', +X'000000000000000000000000000000000000000000000006'), +(X'01234567', X'0123456789ABCDEF', X'0123456789ABCDEF', +X'000000000000000000000000000000000123456789ABCDEF'), +(X'01200567', X'0120056789ABCDEF', X'0120056789ABCDEF', +X'0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF'), +(X'01200567', X'0120056789ABCDEF', X'0120056789ABCDEF', +X'0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF'), +(X'01200117', X'0120011789ABCDEF', X'0120011789ABCDEF', +X'0120011789ABCDEF0120011789ABCDEF0120011789ABCDEF'); +SELECT HEX(i), HEX(li), HEX(b), HEX(lb), +HEX(BIT_AND(i) OVER w), HEX(BIT_AND(li) OVER w), +HEX(BIT_AND(b) OVER w), HEX(BIT_AND(lb) OVER w), +SUM(d) OVER w AS dsum +FROM t +WINDOW w AS (ORDER BY i ROWS 2 PRECEDING); + hex | hex | hex | hex | hex | hex | hex | hex | dsum +---------+-----------------+------------------+--------------------------------------------------+------------------+------------------+------------------+--------------------------------------------------+---------- + | | | | FFFFFFFFFFFFFFFF | FFFFFFFFFFFFFFFF | FFFFFFFFFFFFFFFF | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF | + 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 0 + 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 0 + 1 | 1 | 0000000000000001 | 000000000000000000000000000000000000000000000001 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 1 + 1 | 1 | 0000000000000001 | 000000000000000000000000000000000000000000000001 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 2 + 2 | 2 | 0000000000000002 | 000000000000000000000000000000000000000000000002 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 4 + 2 | 2 | 0000000000000002 | 000000000000000000000000000000000000000000000002 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 5 + 3 | 3 | 0000000000000003 | 000000000000000000000000000000000000000000000003 | 2 | 2 | 0000000000000002 | 000000000000000000000000000000000000000000000002 | 7 + 3 | 3 | 0000000000000003 | 000000000000000000000000000000000000000000000003 | 2 | 2 | 0000000000000002 | 000000000000000000000000000000000000000000000002 | 8 + 4 | 4 | 0000000000000004 | 000000000000000000000000000000000000000000000004 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 10 + 4 | 4 | 0000000000000004 | 000000000000000000000000000000000000000000000004 | 0 | 0 | 0000000000000000 | 000000000000000000000000000000000000000000000000 | 11 + 5 | 5 | 0000000000000005 | 000000000000000000000000000000000000000000000005 | 4 | 4 | 0000000000000004 | 000000000000000000000000000000000000000000000004 | 13 + 6 | 6 | 0000000000000006 | 000000000000000000000000000000000000000000000006 | 4 | 4 | 0000000000000004 | 000000000000000000000000000000000000000000000004 | 15 + 1200117 | 120011789ABCDEF | 0120011789ABCDEF | 0120011789ABCDEF0120011789ABCDEF0120011789ABCDEF | 4 | 4 | 0000000000000004 | 000000000000000000000000000000000000000000000004 | 18874658 + 1200567 | 120056789ABCDEF | 0120056789ABCDEF | 0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF | 6 | 6 | 0000000000000006 | 000000000000000000000000000000000000000000000006 | 37750404 + 1200567 | 120056789ABCDEF | 0120056789ABCDEF | 0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF | 1200107 | 120010789ABCDEF | 0120010789ABCDEF | 0120010789ABCDEF0120010789ABCDEF0120010789ABCDEF | 56626149 + 1234567 | 123456789ABCDEF | 0123456789ABCDEF | 000000000000000000000000000000000123456789ABCDEF | 1200567 | 120056789ABCDEF | 0120056789ABCDEF | 000000000000000000000000000000000120056789ABCDEF | 56840245 +(17 rows) + +drop table t; +reset dolphin.sql_mode; set query_dop = 2; explain(costs off, verbose) select avg(a), avg(b) from smp_test; QUERY PLAN @@ -414,14 +482,14 @@ explain(costs off, verbose) select avg(a), avg(b) from smp_test; (8 rows) explain(costs off, verbose) select bit_and(a), bit_and(b) from smp_test; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------- Aggregate - Output: bit_and((bit_and(a))), bit_and((bit_and(b))) + Output: bit_and((pg_catalog.bit_and(a))), bit_and((bit_and(b))) -> Streaming(type: LOCAL GATHER dop: 1/2) - Output: (bit_and(a)), (bit_and(b)) + Output: (pg_catalog.bit_and(a)), (bit_and(b)) -> Aggregate - Output: bit_and(a), bit_and(b) + Output: pg_catalog.bit_and(a), bit_and(b) -> Seq Scan on uint_agg.smp_test Output: a, b (8 rows) diff --git a/contrib/dolphin/expected/uint_join.out b/contrib/dolphin/expected/uint_join.out index 440681b9dc6706fb13ccced9ce744dffef2ab69e..478e3ee535d793a67459970d1f67f7c7e84c9405 100644 --- a/contrib/dolphin/expected/uint_join.out +++ b/contrib/dolphin/expected/uint_join.out @@ -149,3 +149,268 @@ NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to table scott.dept drop cascades to table scott.emp reset current_schema; +-- test merge join +set enable_hashjoin to off; +set enable_nestloop to off; +set enable_mergejoin to on; +drop table if exists business_order; +NOTICE: table "business_order" does not exist, skipping +drop table if exists statement; +NOTICE: table "statement" does not exist, skipping +drop table if exists user_invoice_account; +NOTICE: table "user_invoice_account" does not exist, skipping +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT1); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: bo.id NULLS FIRST, s.business_order_id NULLS FIRST, s.user_invoice_account_id NULLS FIRST, uia.id NULLS FIRST + -> Merge Right Join + Merge Cond: (uia.id = s.user_invoice_account_id) + -> Sort + Sort Key: uia.id + -> Seq Scan on user_invoice_account uia + -> Sort + Sort Key: s.user_invoice_account_id + -> Merge Right Join + Merge Cond: (s.business_order_id = bo.id) + -> Sort + Sort Key: s.business_order_id + -> Seq Scan on statement s + -> Sort + Sort Key: bo.id + -> Seq Scan on business_order bo +(17 rows) + +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + id | business_order_id | user_invoice_account_id | id +----+-------------------+-------------------------+---- + -2 | | | + -1 | -1 | 2 | 2 + -1 | -1 | 3 | 3 + -1 | -1 | 4 | 4 + -1 | -1 | 5 | + 0 | 0 | 2 | 2 + 0 | 0 | 3 | 3 + 0 | 0 | 4 | 4 + 0 | 0 | 5 | + 1 | 1 | 2 | 2 + 1 | 1 | 3 | 3 + 1 | 1 | 4 | 4 + 1 | 1 | 5 | + 2 | 2 | 2 | 2 + 2 | 2 | 3 | 3 + 2 | 2 | 4 | 4 + 2 | 2 | 5 | + 3 | 3 | 2 | 2 + 3 | 3 | 3 | 3 + 3 | 3 | 4 | 4 + 3 | 3 | 5 | +(21 rows) + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id uint2); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: bo.id NULLS FIRST, s.business_order_id NULLS FIRST, s.user_invoice_account_id NULLS FIRST, uia.id NULLS FIRST + -> Merge Right Join + Merge Cond: (uia.id = s.user_invoice_account_id) + -> Sort + Sort Key: uia.id + -> Seq Scan on user_invoice_account uia + -> Sort + Sort Key: s.user_invoice_account_id + -> Merge Right Join + Merge Cond: (s.business_order_id = bo.id) + -> Sort + Sort Key: s.business_order_id + -> Seq Scan on statement s + -> Sort + Sort Key: bo.id + -> Seq Scan on business_order bo +(17 rows) + +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + id | business_order_id | user_invoice_account_id | id +----+-------------------+-------------------------+---- + -2 | | | + -1 | -1 | 2 | 2 + -1 | -1 | 3 | 3 + -1 | -1 | 4 | 4 + -1 | -1 | 5 | + 0 | 0 | 2 | 2 + 0 | 0 | 3 | 3 + 0 | 0 | 4 | 4 + 0 | 0 | 5 | + 1 | 1 | 2 | 2 + 1 | 1 | 3 | 3 + 1 | 1 | 4 | 4 + 1 | 1 | 5 | + 2 | 2 | 2 | 2 + 2 | 2 | 3 | 3 + 2 | 2 | 4 | 4 + 2 | 2 | 5 | + 3 | 3 | 2 | 2 + 3 | 3 | 3 | 3 + 3 | 3 | 4 | 4 + 3 | 3 | 5 | +(21 rows) + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT4); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: bo.id NULLS FIRST, s.business_order_id NULLS FIRST, s.user_invoice_account_id NULLS FIRST, uia.id NULLS FIRST + -> Merge Right Join + Merge Cond: (uia.id = s.user_invoice_account_id) + -> Sort + Sort Key: uia.id + -> Seq Scan on user_invoice_account uia + -> Sort + Sort Key: s.user_invoice_account_id + -> Merge Right Join + Merge Cond: (s.business_order_id = bo.id) + -> Sort + Sort Key: s.business_order_id + -> Seq Scan on statement s + -> Sort + Sort Key: bo.id + -> Seq Scan on business_order bo +(17 rows) + +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + id | business_order_id | user_invoice_account_id | id +----+-------------------+-------------------------+---- + -2 | | | + -1 | -1 | 2 | 2 + -1 | -1 | 3 | 3 + -1 | -1 | 4 | 4 + -1 | -1 | 5 | + 0 | 0 | 2 | 2 + 0 | 0 | 3 | 3 + 0 | 0 | 4 | 4 + 0 | 0 | 5 | + 1 | 1 | 2 | 2 + 1 | 1 | 3 | 3 + 1 | 1 | 4 | 4 + 1 | 1 | 5 | + 2 | 2 | 2 | 2 + 2 | 2 | 3 | 3 + 2 | 2 | 4 | 4 + 2 | 2 | 5 | + 3 | 3 | 2 | 2 + 3 | 3 | 3 | 3 + 3 | 3 | 4 | 4 + 3 | 3 | 5 | +(21 rows) + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT8); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: bo.id NULLS FIRST, s.business_order_id NULLS FIRST, s.user_invoice_account_id NULLS FIRST, uia.id NULLS FIRST + -> Merge Right Join + Merge Cond: (uia.id = s.user_invoice_account_id) + -> Sort + Sort Key: uia.id + -> Seq Scan on user_invoice_account uia + -> Sort + Sort Key: s.user_invoice_account_id + -> Merge Right Join + Merge Cond: (s.business_order_id = bo.id) + -> Sort + Sort Key: s.business_order_id + -> Seq Scan on statement s + -> Sort + Sort Key: bo.id + -> Seq Scan on business_order bo +(17 rows) + +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + id | business_order_id | user_invoice_account_id | id +----+-------------------+-------------------------+---- + -2 | | | + -1 | -1 | 2 | 2 + -1 | -1 | 3 | 3 + -1 | -1 | 4 | 4 + -1 | -1 | 5 | + 0 | 0 | 2 | 2 + 0 | 0 | 3 | 3 + 0 | 0 | 4 | 4 + 0 | 0 | 5 | + 1 | 1 | 2 | 2 + 1 | 1 | 3 | 3 + 1 | 1 | 4 | 4 + 1 | 1 | 5 | + 2 | 2 | 2 | 2 + 2 | 2 | 3 | 3 + 2 | 2 | 4 | 4 + 2 | 2 | 5 | + 3 | 3 | 2 | 2 + 3 | 3 | 3 | 3 + 3 | 3 | 4 | 4 + 3 | 3 | 5 | +(21 rows) + +reset enable_hashjoin; +reset enable_nestloop; +reset enable_mergejoin; +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; diff --git a/contrib/dolphin/expected/ustore_test.out b/contrib/dolphin/expected/ustore_test.out new file mode 100644 index 0000000000000000000000000000000000000000..4eeeb1b0a9347ea500a54bfe47ac0ace23fda694 --- /dev/null +++ b/contrib/dolphin/expected/ustore_test.out @@ -0,0 +1,13 @@ +create schema ustore_test; +set current_schema to 'ustore_test'; +set enable_default_ustore_table = true; +create table t_year_0005(ts1 year primary key, ts2 year(2)check(ts2 > 1998), ts3 year(4) default 2012); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_year_0005_pkey" for table "t_year_0005" +create table t_year_0005_01(ts1 year primary key, ts2 year(2)check(ts2 > 1998), ts3 year(4) default 2012); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_year_0005_01_pkey" for table "t_year_0005_01" +-- clear +drop table if exists t_year_0005 cascade; +drop table if exists t_year_0005_01 cascade; +reset enable_default_ustore_table; +drop schema ustore_test cascade; +reset current_schema; diff --git a/contrib/dolphin/expected/vec_engine.out b/contrib/dolphin/expected/vec_engine.out index c4e235e9c8e6d09b1e2065a4bc4f8bcb1922dc67..e6423e725eebe4af902909215c0c8afb193adf64 100644 --- a/contrib/dolphin/expected/vec_engine.out +++ b/contrib/dolphin/expected/vec_engine.out @@ -101,8 +101,8 @@ explain (costs off) select n_name order by revenue desc; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Row Adapter -> Vector Sort Sort Key: (sum((lineitem.l_extendedprice OPERATOR(dolphin_catalog.*) (1::numeric - lineitem.l_discount)))) DESC NULLS LAST @@ -111,7 +111,7 @@ explain (costs off) select -> Vector Sonic Hash Join Hash Cond: ((orders.o_custkey = customer.c_custkey) AND (orders.o_orderkey = lineitem.l_orderkey)) -> CStore Scan on orders - Filter: ((o_orderdate >= ('1994-01-01' COLLATE "default")::date) AND (o_orderdate < (date_add(('1994-01-01' COLLATE "default")::date, '@ 1 year'::interval))::timestamp without time zone)) + Filter: ((o_orderdate >= ('1994-01-01' COLLATE "default")::date) AND (o_orderdate < date_add_interval(('1994-01-01' COLLATE "default")::date, '@ 1 year'::interval))) -> Vector Sonic Hash Join Hash Cond: (lineitem.l_suppkey = supplier.s_suppkey) -> CStore Scan on lineitem diff --git a/contrib/dolphin/include/builtin_funcs.ini b/contrib/dolphin/include/builtin_funcs.ini index 480addbb3ee638db3ea903884068794100ba11e7..ca433d1c9ccc5f3a582134de01e6347ca13181e0 100755 --- a/contrib/dolphin/include/builtin_funcs.ini +++ b/contrib/dolphin/include/builtin_funcs.ini @@ -197,6 +197,13 @@ "anytextcat", 1, AddBuiltinFunc(_0(ANYTEXTCATFUNCOID), _1("anytextcat"), _2(2), _3(true), _4(false), _5(NULL), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 2776, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select $1::pg_catalog.text || $2"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "appendchildxml", 4, + AddBuiltinFunc(_0(8800), _1("appendchildxml"), _2(4), _3(false), _4(false), _5(xmltype_appendchildxml), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 142, 25, 25, 1009), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_appendchildxml"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8801), _1("appendchildxml"), _2(4), _3(false), _4(false), _5(xmltype_appendchildxml), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 142, 25, 142, 1009), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_appendchildxml"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8802), _1("appendchildxml"), _2(3), _3(false), _4(false), _5(NULL), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 142, 25, 142), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.appendchildxml($1, $2, $3, '{}'::pg_catalog.text[])"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8803), _1("appendchildxml"), _2(3), _3(false), _4(false), _5(NULL), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 142, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.appendchildxml($1, $2, $3, '{}'::pg_catalog.text[])"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "area", 3, AddBuiltinFunc(_0(975), _1("area"), _2(1), _3(true), _4(false), _5(box_area), _6(701), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 603), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("box_area"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("box area"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), @@ -2502,7 +2509,7 @@ ), AddFuncGroup( "ondemand_recovery_status", 1, - AddBuiltinFunc(_0(6991), _1("ondemand_recovery_status"), _2(0), _3(false), _4(false), _5(get_ondemand_recovery_status), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(0), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(0), _21(10, TEXTOID, TEXTOID, OIDOID, OIDOID, OIDOID, OIDOID, BOOLOID, TEXTOID, TEXTOID, TEXTOID), _22(10, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(10, "primary_checkpoint_redo_lsn", "realtime_build_replayed_lsn", "hashmap_used_blocks", "hashmap_total_blocks", "trxn_queue_blocks", "seg_queue_blocks", "in_ondemand_recovery", "ondemand_recovery_status", "realtime_build_status", "recovery_pause_status"), _24(NULL), _25("get_ondemand_recovery_status"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(6991), _1("ondemand_recovery_status"), _2(0), _3(false), _4(false), _5(get_ondemand_recovery_status), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(0), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(0), _21(12, TEXTOID, TEXTOID, OIDOID, OIDOID, OIDOID, OIDOID, BOOLOID, TEXTOID, TEXTOID, TEXTOID, OIDOID, OIDOID), _22(12, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(12, "primary_checkpoint_redo_lsn", "realtime_build_replayed_lsn", "hashmap_used_blocks", "hashmap_total_blocks", "trxn_queue_blocks", "seg_queue_blocks", "in_ondemand_recovery", "ondemand_recovery_status", "realtime_build_status", "recovery_pause_status", "record_item_num", "record_item_mbytes"), _24(NULL), _25("get_ondemand_recovery_status"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "dss_io_stat", 1, @@ -2645,11 +2652,25 @@ "exec_on_extension", 1, AddBuiltinFunc(_0(ECEXTENSIONFUNCOID), _1("exec_on_extension"), _2(2), _3(false), _4(true), _5(exec_on_extension), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(1000), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(2, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("exec_on_extension"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "existsnode", 1, + AddBuiltinFunc(_0(8052), _1("existsnode"), _2(2), _3(true), _4(false), _5(xmltype_existsnode), _6(5545), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 142, 1043), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_existsnode"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "exp", 2, AddBuiltinFunc(_0(1347), _1("exp"), _2(1), _3(true), _4(false), _5(dexp), _6(701), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("dexp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("natural exponential (e^x)"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), AddBuiltinFunc(_0(1732), _1("exp"), _2(1), _3(true), _4(false), _5(numeric_exp), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 1700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_exp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("natural exponential (e^x)"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "extract_internal", 2, + AddBuiltinFunc(_0(8580), _1("extract_internal"), _2(3), _3(false), _4(false), _5(xmltype_extract), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 142, 1043, 1009), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_extract"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("evaluate XPath expression, with namespace"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8581), _1("extract_internal"), _2(2), _3(false), _4(false), _5(NULL), _6(142), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 142, 1043), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.extract_internal($1, $2, '{}'::pg_catalog.text[])"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("evaluate XPath expression, without namespace"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), + AddFuncGroup( + "extractvalue", 2, + AddBuiltinFunc(_0(8051), _1("extractvalue"), _2(3), _3(true), _4(false), _5(xmltype_extractvalue), _6(1043), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 142, 1043, 1009), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_extractvalue"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8053), _1("extractvalue"), _2(2), _3(true), _4(false), _5(NULL), _6(1043), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 142, 1043), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.extractvalue($1, $2, '{}'::pg_catalog.text[])"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("evaluate XPath expression, without namespace"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "f4toi1", 1, AddBuiltinFunc(_0(5530), _1("f4toi1"), _2(1), _3(true), _4(false), _5(f4toi1), _6(5545), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 700), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("f4toi1"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -2936,7 +2957,7 @@ ), AddFuncGroup( "float8_to_interval", 1, - AddBuiltinFunc(_0(4230), _1("float8_to_interval"), _2(2), _3(true), _4(false), _5(float8_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 701, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("float8_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(4230), _1("float8_to_interval"), _2(2), _3(true), _4(false), _5(float8_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 701, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("float8_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "float8_list_agg_noarg2_transfn", 1, @@ -3291,6 +3312,11 @@ "getpgusername", 1, AddBuiltinFunc(_0(GETPGUSERNAMEFUNCOID), _1("getpgusername"), _2(0), _3(true), _4(false), _5(current_user), _6(19), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("current_user"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "getstringval", 2, + AddBuiltinFunc(_0(8583), _1("getstringval"), _2(1), _3(true), _4(false), _5(xmltype_getstringval), _6(1043), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 142), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_getstringval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8584), _1("getstringval"), _2(1), _3(true), _4(false), _5(xmltype_getstringval_array), _6(1043), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 143), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_getstringval_array"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "gin_clean_pending_list", 1, AddBuiltinFunc(_0(3989), _1("gin_clean_pending_list"), _2(1), _3(true), _4(false), _5(gin_clean_pending_list), _6(20), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(1, 2205), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("gin_clean_pending_list"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("clean up GIN pending list"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -3693,7 +3719,7 @@ ), AddFuncGroup( "gs_xlog_keepers", 1, - AddBuiltinFunc(_0(9040), _1("gs_xlog_keepers"), _2(0), _3(true), _4(false), _5(gs_xlog_keepers), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(3, 25, 25, 25), _22(3, 'o', 'o', 'o'), _23(3, "keeptype", "keepsegment", "describe"), _24(NULL), _25("gs_xlog_keepers"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f')) + AddBuiltinFunc(_0(9040), _1("gs_xlog_keepers"), _2(0), _3(true), _4(true), _5(gs_xlog_keepers), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(1000), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(0), _21(3, 25, 25, 25), _22(3, 'o', 'o', 'o'), _23(3, "keeptype", "keepsegment", "describe"), _24(NULL), _25("gs_xlog_keepers"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f')) ), AddFuncGroup( "gs_get_next_xid_csn", 1, @@ -7596,10 +7622,10 @@ ), AddFuncGroup( "num_to_interval", 4, - AddBuiltinFunc(_0(4223), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int1_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 5545, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int1_to_interval"), _26("-"), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), - AddBuiltinFunc(_0(4224), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int2_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 21, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int2_to_interval"), _26("-"), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), - AddBuiltinFunc(_0(4225), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int4_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 23, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int4_to_interval"), _26("-"), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), - AddBuiltinFunc(_0(4226), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(numeric_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1700, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_interval"), _26("-"), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(4223), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int1_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 5545, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int1_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(4224), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int2_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 21, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int2_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(4225), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(int4_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 23, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("int4_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(4226), _1("num_to_interval"), _2(2), _3(true), _4(false), _5(numeric_to_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 1700, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "nvarchar2", 1, @@ -8037,7 +8063,7 @@ ), AddFuncGroup( "pg_buffercache_pages", 1, - AddBuiltinFunc(_0(4130), _1("pg_buffercache_pages"), _2(0), _3(false), _4(true), _5(pg_buffercache_pages), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(100), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(12, 23, 26, 23, 20, 26, 26, 23, 26, 16, 16, 21, 23), _22(12, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(12, "bufferid", "relfilenode", "bucketid", "storage_type", "reltablespace", "reldatabase", "relforknumber", "relblocknumber", "isdirty", "isvalid", "usage_count", "pinning_backends"), _24(NULL), _25("pg_buffercache_pages"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(4130), _1("pg_buffercache_pages"), _2(0), _3(false), _4(true), _5(pg_buffercache_pages), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(100), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(15, 23, 26, 23, 20, 26, 26, 23, 26, 16, 16, 21, 23, 23, 26, 16), _22(15, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(15, "bufferid", "relfilenode", "bucketid", "storage_type", "reltablespace", "reldatabase", "relforknumber", "relblocknumber", "isdirty", "isvalid", "usage_count", "pinning_backends", "segfileno", "segblockno", "aio_in_process"), _24(NULL), _25("pg_buffercache_pages"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "pg_cancel_backend", 1, @@ -11190,6 +11216,14 @@ AddFuncGroup( AddBuiltinFunc(_0(SUBSTRINNFUNCOID), _1("substring_inner"), _2(3), _3(true), _4(false), _5(text_substr), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 25, 23, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("text_substr"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("extract portion of string"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), AddBuiltinFunc(_0(SUBSTRINNNOLENFUNCOID), _1("substring_inner"), _2(2), _3(true), _4(false), _5(text_substr_no_len), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 25, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("text_substr_no_len"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("extract portion of string"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "subtype_in", 1, + AddBuiltinFunc(_0(9462), _1("subtype_in"), _2(3), _3(false), _4(false), _5(subtype_in), _6(2276), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(3, 2275, 26, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("subtype_in"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0), _41(NULL)) + ), + AddFuncGroup( + "subtype_recv", 1, + AddBuiltinFunc(_0(9463), _1("subtype_recv"), _2(3), _3(false), _4(false), _5(subtype_recv), _6(2276), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(3, 2281, 26, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("subtype_recv"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0), _41(NULL)) + ), AddFuncGroup( "sum", 8, AddBuiltinFunc(_0(2107), _1("sum"), _2(1), _3(false), _4(false), _5(aggregate_dummy), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(true), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 20), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("aggregate_dummy"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("the average (arithmetic mean) as numeric of all bigint values"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), @@ -11309,7 +11343,7 @@ AddFuncGroup( ), AddFuncGroup( "text_interval", 1, - AddBuiltinFunc(_0(4211), _1("text_interval"), _2(2), _3(true), _4(false), _5(text_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("text_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(4211), _1("text_interval"), _2(2), _3(true), _4(false), _5(text_interval), _6(1186), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 25, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("text_interval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "text_larger", 1, @@ -12655,6 +12689,10 @@ AddFuncGroup( "uuid_send", 1, AddBuiltinFunc(_0(2962), _1("uuid_send"), _2(1), _3(true), _4(false), _5(uuid_send), _6(17), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2950), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("uuid_send"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "value", 1, + AddBuiltinFunc(_0(7816), _1("value"), _2(1), _3(false), _4(false), _5(object_table_value), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2249), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("object_table_value"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "value_of_percentile", 1, AddBuiltinFunc(_0(9986), _1("value_of_percentile"), _2(3), _3(false), _4(false), _5(aggregate_dummy), _6(701), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(true), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(3, 701, 701, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("aggregate_dummy"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -12954,6 +12992,11 @@ AddFuncGroup( "xmlexists", 1, AddBuiltinFunc(_0(2614), _1("xmlexists"), _2(2), _3(true), _4(false), _5(xmlexists), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 25, 142), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmlexists"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), + AddFuncGroup( + "xmlsequence", 2, + AddBuiltinFunc(_0(8586), _1("xmlsequence"), _2(1), _3(false), _4(false), _5(xmltype_xmlsequence), _6(143), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 142), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_xmlsequence"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)), + AddBuiltinFunc(_0(8587), _1("xmlsequence"), _2(1), _3(true), _4(false), _5(xmltype_xmlsequence_array), _6(143), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 143), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmltype_xmlsequence_array"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + ), AddFuncGroup( "xmlvalidate", 1, AddBuiltinFunc(_0(2897), _1("xmlvalidate"), _2(2), _3(true), _4(false), _5(xmlvalidate), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 142, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("xmlvalidate"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) @@ -13044,7 +13087,7 @@ AddFuncGroup( ), AddFuncGroup( "gs_get_recv_locations", 1, - AddBuiltinFunc(_0(2872), _1("gs_get_recv_locations"), _2(0), _3(false), _4(true), _5(gs_get_recv_locations), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(0), _21(4, 25, 25, 25, 25), _22(4, 'o', 'o', 'o', 'o'), _23(4, "received_lsn", "write_lsn", "flush_lsn", "replay_lsn"), _24(NULL), _25("gs_get_recv_locations"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("statistics: information about WAL locations"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) + AddBuiltinFunc(_0(2872), _1("gs_get_recv_locations"), _2(0), _3(false), _4(true), _5(gs_get_recv_locations), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(0), _21(4, 25, 25, 25, 25), _22(4, 'o', 'o', 'o', 'o'), _23(4, "received_lsn", "write_lsn", "flush_lsn", "replay_lsn"), _24(NULL), _25("gs_get_recv_locations"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33("statistics: information about currently wal locations"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)) ), AddFuncGroup( "gs_get_hba_conf", 1, diff --git a/contrib/dolphin/include/plugin_commands/defrem.h b/contrib/dolphin/include/plugin_commands/defrem.h index ed0e1099fca780e985349fe3249f24f8f59ce656..e40cf7bfdee6c0f05d90907057f3cf09e56c459c 100644 --- a/contrib/dolphin/include/plugin_commands/defrem.h +++ b/contrib/dolphin/include/plugin_commands/defrem.h @@ -51,8 +51,10 @@ extern bool PrepareCFunctionLibrary(HeapTuple tup); extern void InsertIntoPendingLibraryDelete(const char* filename, bool atCommit); extern void libraryDoPendingDeletes(bool isCommit); extern void ResetPendingLibraryDelete(); -extern ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_oid = InvalidOid); -extern ObjectAddress CreateFunction_extend(CreateFunctionStmt* stmt, const char* queryString, void* getHeaderInfoCtx, void** pHeapTuple, bool isPackageFunc = false); +extern ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, + Oid pkg_oid = InvalidOid, Oid type_oid = InvalidOid); +extern ObjectAddress CreateFunction_extend(CreateFunctionStmt* stmt, const char* queryString, + void* getHeaderInfoCtx, void** pHeapTuple, bool isPackageFunc = false, Oid type_oid = InvalidOid); extern ObjectAddress RenameFunction(List* name, List* argtypes, const char* newname); extern void RemoveFunctionById(Oid funcOid); extern void remove_encrypted_proc_by_id(Oid funcOid); @@ -213,6 +215,10 @@ extern ObjectAddress AlterDataSourceOwner(const char* name, Oid newOwnerId); extern void RemoveDataSourceById(Oid src_Id); extern Oid GetFunctionNodeGroup(CreateFunctionStmt* stmt, bool* multi_group); +extern List* compute_attributes_sql_style(const List* options, List** as, char** language, + bool* windowfunc_p, char* volatility_p, bool* strict_p, bool* security_definer, bool* leakproof_p, + ArrayType** proconfig, float* procost, float4* prorows, bool* fenced, + bool* shippable, bool* package, bool* is_pipelined, FunctionPartitionInfo** partInfo); extern Oid GetFunctionNodeGroupByFuncid(Oid funcid); extern Oid GetFunctionNodeGroup(AlterFunctionStmt* stmt); diff --git a/contrib/dolphin/include/plugin_nodes/parsenodes.h b/contrib/dolphin/include/plugin_nodes/parsenodes.h index 936617a91e0b79dba96eead240ab5f51837be74e..de4f3ab62ff6f3a9fe48a02470d3e0ba087053db 100755 --- a/contrib/dolphin/include/plugin_nodes/parsenodes.h +++ b/contrib/dolphin/include/plugin_nodes/parsenodes.h @@ -1523,11 +1523,27 @@ typedef struct UnlistenStmt { */ typedef struct CompositeTypeStmt { NodeTag type; - bool replace; + bool replace; /* replace if already exists */ RangeVar* typevar; /* the composite type to be created */ List* coldeflist; /* list of ColumnDef nodes */ + List* methodlist; /* list of method declaration */ + uint8 typekind; /* what kind of compisite type */ + bool final; /* final means not allow to create subtype */ + bool issubtype; /* is subtype or not */ + RangeVar* supertype; /* super type */ + char* typespec; + char* typebody; } CompositeTypeStmt; - +/* ---------------------- + * Create Type Statement, composite types + * ---------------------- + */ +typedef struct CompositeTypeBodyStmt { + NodeTag type; + RangeVar* typevar; /* the composite type to be created */ + List* methodlist; /* method declaration list */ + bool replace; /* replace if already exists */ +} CompositeTypeBodyStmt; /* ---------------------- * Create Type Statement, table of types * ---------------------- @@ -1537,6 +1553,8 @@ typedef struct TableOfTypeStmt { bool replace; List* typname; /* the table of type to be quoted */ TypeName* reftypname; /* the name of the type being referenced */ + char typtype; /* distinct table of type and varray of type */ + char typecategory; /* distinct table of type and varray of type */ } TableOfTypeStmt; /* ---------------------- @@ -2190,6 +2208,26 @@ typedef struct RefreshMatViewStmt RangeVar *relation; /* relation to insert into */ } RefreshMatViewStmt; +/* ---------------------- + * CREATE MATERIALIZED VIEW LOG Statement + * ---------------------- + */ +typedef struct CreateMatViewLogStmt +{ + NodeTag type; + RangeVar* relation; /* relation to create matview log for */ +} CreateMatViewLogStmt; + +/* ---------------------- + * DROP MATERIALIZED VIEW LOG Statement + * ---------------------- + */ +typedef struct DropMatViewLogStmt +{ + NodeTag type; + RangeVar* relation; /* relation to drop matview log from */ +} DropMatViewLogStmt; + /* ---------------------- * Checkpoint Statement * ---------------------- diff --git a/contrib/dolphin/include/plugin_nodes/parsenodes_common.h b/contrib/dolphin/include/plugin_nodes/parsenodes_common.h index d541287ccda3e088c25182f5e271a92d7ede7665..d2b2b941c7598aa3a945a0a741328c1442a08fee 100644 --- a/contrib/dolphin/include/plugin_nodes/parsenodes_common.h +++ b/contrib/dolphin/include/plugin_nodes/parsenodes_common.h @@ -2386,6 +2386,8 @@ typedef struct CreateFunctionStmt { int startLineNumber; int firstLineNumber; char *definer; + char typfunckind = 'n'; + bool isfinal = false; } CreateFunctionStmt; typedef struct FunctionSources { diff --git a/contrib/dolphin/include/plugin_parser/kwlist.h b/contrib/dolphin/include/plugin_parser/kwlist.h index 92f7afb5bb4e37010a9062a7cabfa94ffe23be20..c877f02146f3f23b5fb193e72cb527ecaabcada0 100644 --- a/contrib/dolphin/include/plugin_parser/kwlist.h +++ b/contrib/dolphin/include/plugin_parser/kwlist.h @@ -110,6 +110,7 @@ PG_KEYWORD("box", DB_B_BOX, UNRESERVED_KEYWORD) #endif PG_KEYWORD("bucketcnt", BUCKETCNT, COL_NAME_KEYWORD) /* PG_KEYWORD("buckets", BUCKETS, RESERVED_KEYWORD) */ +PG_KEYWORD("build", BUILD, UNRESERVED_KEYWORD) PG_KEYWORD("by", BY, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("bytea", DB_B_BYTEA, UNRESERVED_KEYWORD) @@ -191,6 +192,7 @@ PG_KEYWORD("constraint_catalog", CONSTRAINT_CATALOG, UNRESERVED_KEYWORD) PG_KEYWORD("constraint_name", CONSTRAINT_NAME, UNRESERVED_KEYWORD) PG_KEYWORD("constraint_schema", CONSTRAINT_SCHEMA, UNRESERVED_KEYWORD) PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD) +PG_KEYWORD("constructor", CONSTRUCTOR, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("contains", CONTAINS, UNRESERVED_KEYWORD) #endif @@ -372,6 +374,7 @@ PG_KEYWORD("fileheader", FILEHEADER_P, UNRESERVED_KEYWORD) PG_KEYWORD("fill_missing_fields", FILL_MISSING_FIELDS, UNRESERVED_KEYWORD) PG_KEYWORD("filler", FILLER, UNRESERVED_KEYWORD) PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD) +PG_KEYWORD("final", FINAL, UNRESERVED_KEYWORD) PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("fixed", FIXED_P, COL_NAME_KEYWORD) // origin: UNRESERVED_KEYWORD @@ -544,7 +547,10 @@ PG_KEYWORD("longtext", TEXT_P, UNRESERVED_KEYWORD) PG_KEYWORD("loop", LOOP, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("low_priority", LOW_PRIORITY, RESERVED_KEYWORD) +PG_KEYWORD("lseg", DB_B_LSEG, UNRESERVED_KEYWORD) #endif + +PG_KEYWORD("map", MAP, UNRESERVED_KEYWORD) PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD) PG_KEYWORD("masking", MASKING, UNRESERVED_KEYWORD) PG_KEYWORD("master", MASTER, UNRESERVED_KEYWORD) @@ -561,6 +567,9 @@ PG_KEYWORD("maxvalue", MAXVALUE, RESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("mediumint", MEDIUMINT, COL_NAME_KEYWORD) PG_KEYWORD("mediumtext", TEXT_P, UNRESERVED_KEYWORD) +#endif +PG_KEYWORD("member", MEMBER, UNRESERVED_KEYWORD) +#ifdef DOLPHIN PG_KEYWORD("memory", MEMORY, UNRESERVED_KEYWORD) #endif PG_KEYWORD("merge", MERGE, UNRESERVED_KEYWORD) @@ -681,6 +690,9 @@ PG_KEYWORD("partitioning", PARTITIONING, UNRESERVED_KEYWORD) PG_KEYWORD("partitions", PARTITIONS, UNRESERVED_KEYWORD) PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD) PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD) +#ifdef DOLPHIN +PG_KEYWORD("path", DB_B_PATH, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("pctfree", PCTFREE, UNRESERVED_KEYWORD) PG_KEYWORD("per", PER_P, UNRESERVED_KEYWORD) PG_KEYWORD("percent", PERCENT, UNRESERVED_KEYWORD) @@ -790,6 +802,7 @@ PG_KEYWORD("resize", RESIZE, UNRESERVED_KEYWORD) PG_KEYWORD("resource", RESOURCE, UNRESERVED_KEYWORD) PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD) PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD) +PG_KEYWORD("result", RESULT, UNRESERVED_KEYWORD) PG_KEYWORD("return", RETURN, UNRESERVED_KEYWORD) PG_KEYWORD("returned_sqlstate", RETURNED_SQLSTATE, UNRESERVED_KEYWORD) PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD) @@ -842,6 +855,7 @@ PG_KEYWORD("secondary_engine_attribute", SECONDARY_ENGINE_ATTRIBUTE, UNRESERVED_ #endif PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD) PG_KEYWORD("select", SELECT, RESERVED_KEYWORD) +PG_KEYWORD("self", SELF, RESERVED_KEYWORD) PG_KEYWORD("separator", SEPARATOR_P, UNRESERVED_KEYWORD) PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD) PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD) @@ -895,6 +909,7 @@ PG_KEYWORD("starting", STARTING, UNRESERVED_KEYWORD) PG_KEYWORD("starts", STARTS, UNRESERVED_KEYWORD) PG_KEYWORD("statement", STATEMENT, UNRESERVED_KEYWORD) PG_KEYWORD("statement_id", STATEMENT_ID, UNRESERVED_KEYWORD) +PG_KEYWORD("static", STATIC_P, UNRESERVED_KEYWORD) PG_KEYWORD("statistics", STATISTICS, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("stats_auto_recalc", STATS_AUTO_RECALC, UNRESERVED_KEYWORD) @@ -988,6 +1003,7 @@ PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD) #ifdef DOLPHIN PG_KEYWORD("undefined", UNDEFINED, UNRESERVED_KEYWORD) #endif +PG_KEYWORD("under", UNDER, UNRESERVED_KEYWORD) PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD) PG_KEYWORD("union", UNION, RESERVED_KEYWORD) PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD) @@ -1029,6 +1045,7 @@ PG_KEYWORD("varchar", VARCHAR, COL_NAME_KEYWORD) PG_KEYWORD("varchar2", VARCHAR2, COL_NAME_KEYWORD) PG_KEYWORD("variables", VARIABLES, UNRESERVED_KEYWORD) PG_KEYWORD("variadic", VARIADIC, RESERVED_KEYWORD) +PG_KEYWORD("varray", VARRAY, UNRESERVED_KEYWORD) PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD) PG_KEYWORD("vcgroup", VCGROUP, UNRESERVED_KEYWORD) #ifdef DOLPHIN diff --git a/contrib/dolphin/include/plugin_parser/parse_type.h b/contrib/dolphin/include/plugin_parser/parse_type.h index ab5adef31a25a41d9c5615bece44f7332a1dae46..3b389c1513f7295df5a2d956d5ffb4d951d1db83 100644 --- a/contrib/dolphin/include/plugin_parser/parse_type.h +++ b/contrib/dolphin/include/plugin_parser/parse_type.h @@ -31,6 +31,7 @@ extern Type LookupTypeNameExtended(ParseState* pstate, const TypeName* typname, bool print_notice = true, TypeDependExtend* dependExtend = NULL); extern Oid LookupPctTypeInPackage(RangeVar* rel, Oid pkgOid, const char* field); extern Oid LookupTypeInPackage(List* typeNames, const char* typeName, Oid pkgOid = InvalidOid, Oid namespaceId = InvalidOid); +extern Oid LookupTypeInFunc(const char* typeName); extern Type typenameType(ParseState* pstate, const TypeName* typname, int32* typmod_p, TypeDependExtend* dependExtend = NULL); extern Oid typenameTypeId(ParseState* pstate, const TypeName* typname); extern void typenameTypeIdAndMod(ParseState* pstate, const TypeName* typname, Oid* typeid_p, int32* typmod_p, diff --git a/contrib/dolphin/include/plugin_postgres.h b/contrib/dolphin/include/plugin_postgres.h index 3b17cfad2800837f8174762c79ef41934873f1b1..133d0a1fd1cf4f809c08524b2bd0af7d7dbe9144 100644 --- a/contrib/dolphin/include/plugin_postgres.h +++ b/contrib/dolphin/include/plugin_postgres.h @@ -196,6 +196,8 @@ typedef struct BSqlPluginContext { conn_mysql_infoP_t Conn_Mysql_Info; bool use_const_value_as_colname; bool support_interval_to; + bool treat_float_with_precision_as_float_type; + bool is_set_stmt; #endif } bSqlPluginContext; diff --git a/contrib/dolphin/include/plugin_protocol/bytestream.h b/contrib/dolphin/include/plugin_protocol/bytestream.h index a001986d38613b63b83a59b7b79750907f9b343a..acd102997e2c7567b8ca7c0aaf2fdd03b2118fe3 100644 --- a/contrib/dolphin/include/plugin_protocol/bytestream.h +++ b/contrib/dolphin/include/plugin_protocol/bytestream.h @@ -24,6 +24,7 @@ #include "postgres.h" #include "lib/stringinfo.h" +#include "libpq/libpq-be.h" #define MAX_LEN_ENCODE_BYTE 251 #define MAX_LEN_ENCODE_2_BYTE 65536 @@ -39,6 +40,7 @@ #define PROTO_PACKET_HEADER_LEN 4 #define PROTO_PAYLOAD_LEN 3 #define PROTO_SEQUENCE_LEN 1 +#define PROTO_RECV_BUFFER_SIZE 8192 #define SHIFT_BYTE_STEP 8 #define MAX_LEFT_SHIFT_BIT 32 @@ -46,6 +48,7 @@ extern int dq_putmessage(const char* packet, size_t len); extern int dq_getmessage(StringInfo s, uint32 maxlen); +extern int dq_special_getmessage(StringInfo buf, Port* port); static inline void dq_append_int_len(StringInfo buf, uint64 num, int len) { diff --git a/contrib/dolphin/include/plugin_utils/fmgr.h b/contrib/dolphin/include/plugin_utils/fmgr.h index f023b66dbb3206899ffd3a95f35a0c2766150f3e..ed23ecba9775ac507fdc41d2819edf275c715232 100644 --- a/contrib/dolphin/include/plugin_utils/fmgr.h +++ b/contrib/dolphin/include/plugin_utils/fmgr.h @@ -170,6 +170,7 @@ typedef struct FunctionCallInfoData { UDFInfoType udfInfo; StartWithFuncEvalInfo swinfo; CoercionContext ccontext; + bool is_plpgsql_language_function_with_outparam; FunctionCallInfoData() { @@ -185,6 +186,7 @@ typedef struct FunctionCallInfoData { isnull = false; can_ignore = false; ccontext = COERCION_UNKNOWN; + is_plpgsql_language_function_with_outparam = false; } } FunctionCallInfoData; diff --git a/contrib/dolphin/include/plugin_utils/plpgsql.h b/contrib/dolphin/include/plugin_utils/plpgsql.h index ecc3f3ac6733bed4cfe6e0884ce5fd43a5f09a15..d55e72a7a5090fe5602137e4d45f4c9a991dc143 100644 --- a/contrib/dolphin/include/plugin_utils/plpgsql.h +++ b/contrib/dolphin/include/plugin_utils/plpgsql.h @@ -73,7 +73,8 @@ enum { PLPGSQL_NSTYPE_UNKNOWN, PLPGSQL_NSTYPE_COMPOSITE, PLPGSQL_NSTYPE_GOTO_LABEL, - PLPGSQL_NSTYPE_CURSORROW + PLPGSQL_NSTYPE_CURSORROW, + PLPGSQL_NSTYPE_SUBTYPE }; /* ---------- @@ -95,7 +96,8 @@ enum { PLPGSQL_DTYPE_ASSIGNLIST, PLPGSQL_DTYPE_COMPOSITE, /* composite type */ PLPGSQL_DTYPE_RECORD_TYPE, /* record type */ - PLPGSQL_DTYPE_CURSORROW + PLPGSQL_DTYPE_CURSORROW, + PLPGSQL_DTYPE_SUBTYPE }; /* ---------- @@ -137,7 +139,8 @@ enum { PLPGSQL_TOK_TABLE, PLPGSQL_TOK_TABLE_VAR, PLPGSQL_TOK_RECORD, - PLPGSQL_TOK_PACKAGE_VARIABLE + PLPGSQL_TOK_PACKAGE_VARIABLE, + PLPGSQL_TOK_OBJECT_TYPE_VAR_METHOD }; /* ---------- @@ -449,6 +452,16 @@ typedef struct PLpgSQL_expr { /* SQpL Query to plan and execute */ uint64 unique_sql_id; } PLpgSQL_expr; +/* To save subtype range constraints */ +typedef struct SubTypeRange { + bool valid; + Oid SubTypeOid; + Oid functionOid; + Oid packageOid; + PLpgSQL_expr* lowValue; + PLpgSQL_expr* highValue; +} SubTypeRange; + typedef struct { /* openGauss data type */ int dtype; int dno; @@ -476,6 +489,7 @@ typedef struct { /* openGauss data type */ TypeDependExtend* dependExtend; PLpgSQL_expr* cursorExpr; int cursorDno; + char typtyp; } PLpgSQL_type; typedef struct { @@ -527,7 +541,7 @@ typedef struct { /* Row variable */ bool isImplicit; bool addNamespace; char* varname; - + PLpgSQL_type* datatype; TupleDesc rowtupdesc; /* @@ -551,6 +565,7 @@ typedef struct { /* Row variable */ PLpgSQL_expr* default_val = NULL; Oid recordVarTypOid; /* package record var's composite type oid */ bool hasExceptionInit; + bool atomically_null_object; } PLpgSQL_row; typedef struct { @@ -597,6 +612,7 @@ typedef struct { /* Record variable (non-fixed structure) */ bool freetup; bool freetupdesc; List* pkg_name = NULL; + List* field_need_check = NULL; PLpgSQL_package* pkg = NULL; PLpgSQL_expr* default_val = NULL; PLpgSQL_expr* expr = NULL; @@ -1814,6 +1830,7 @@ PLpgSQL_variable* plpgsql_build_varrayType(const char* refname, int lineno, PLpg PLpgSQL_variable* plpgsql_build_tableType(const char* refname, int lineno, PLpgSQL_type* dtype, bool add2namespace); extern PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List* list, bool add2namespace); extern PLpgSQL_rec* plpgsql_build_record(const char* refname, int lineno, bool add2namespace, TupleDesc tupleDesc); +extern void plpgsql_build_synonym(char* typname, char* basetypname); extern int plpgsql_recognize_err_condition(const char* condname, bool allow_sqlstate); extern PLpgSQL_condition* plpgsql_parse_err_condition(char* condname); PLpgSQL_condition* plpgsql_parse_err_condition_b_signal(const char* condname); @@ -2123,6 +2140,7 @@ extern TupleDesc getCursorTupleDesc(PLpgSQL_expr* expr, bool isOnlySelect, bool extern int CompileStatusSwtichTo(int newCompileStatus); extern void checkCompileMemoryContext(MemoryContext cxt); extern int getCompileStatus(); +extern void getPkgFuncTypeName(char* typname, char** functypname, char** pkgtypname); extern void pushCompileContext(); extern PLpgSQL_compile_context* popCompileContext(); void popToOldCompileContext(PLpgSQL_compile_context* save); diff --git a/contrib/dolphin/input/b_auto_increment.source b/contrib/dolphin/input/b_auto_increment.source index 7a135cecfeb094c8aca929aa6388ed3f52b616c2..d28e0d4ad52c6d80104cf0f7fc4c5c78ad1377ca 100644 --- a/contrib/dolphin/input/b_auto_increment.source +++ b/contrib/dolphin/input/b_auto_increment.source @@ -233,6 +233,9 @@ alter table txxx modify `ABcD` int auto_increment; alter table txxx modify `abcd` int auto_increment; alter table txxx modify ABcD int auto_increment; +create table test (a int, b int AUTO_INCREMENT,KEY `b`(`b`)); +alter table test add primary key(a); + \c postgres drop database if exists dolphin_autoinc; drop database if exists dolphin_autoinc_restore; \ No newline at end of file diff --git a/contrib/dolphin/input/b_caching_auth_change_noinited.source b/contrib/dolphin/input/b_caching_auth_change_noinited.source new file mode 100644 index 0000000000000000000000000000000000000000..40b210bfca7495ba7cfff034059d4a138c3b9585 --- /dev/null +++ b/contrib/dolphin/input/b_caching_auth_change_noinited.source @@ -0,0 +1,30 @@ +-- bug #IAN93O test,change password without initializing plugin +--begin:close enable_dolphin_proto +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/datanode1/ -c "enable_dolphin_proto=off" > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! sleep 5 +--end + +\! @abs_bindir@/gsql -d postgres -p @portstring@ -r -c "create database dbmysql with dbcompatibility 'B'"; +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "DROP USER IF EXISTS caching_user"; +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "CREATE USER caching_user WITH PASSWORD 'Gauss@123'"; +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "GRANT ALL PRIVILEGES TO caching_user"; +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "GRANT ALL ON SCHEMA dbe_perf TO caching_user"; +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "SET ROLE caching_user PASSWORD 'Gauss@123'"; + +-- set password for caching_sha2_password authentication first +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@123', ''),E'\n','X')"; + +-- change password for caching_sha2_password authentication +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@admin', 'Gauss@123'),E'\n','X')"; + +-- change password for caching_sha2_password authentication +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@123', 'Gauss@admin'),E'\n','X')"; + +--begin:open enable_dolphin_proto +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/datanode1/ -c "enable_dolphin_proto=on" > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! sleep 5 +--end \ No newline at end of file diff --git a/contrib/dolphin/input/dump_dumpall_test.source b/contrib/dolphin/input/dump_dumpall_test.source index b64ddeec5af1963112c698b1a3b613d80152d0f1..1be6b9a01860249a41c4fc099233e70cb4310868 100644 --- a/contrib/dolphin/input/dump_dumpall_test.source +++ b/contrib/dolphin/input/dump_dumpall_test.source @@ -145,6 +145,27 @@ update ignore test_ignore_unique set c1 = 1 where c1 =2; drop table if exists test_ignore_normal; create table test_ignore_normal(c1 int, c2 text); insert ignore into test_ignore_normal values(1, 'a'); + +-- test for keywords +reset dolphin.sql_mode; +CREATE TABLE allshortestpath_splitprovince ( +enprov varchar(50) NOT NULL, +exprov varchar(50) NOT NULL, +"version" varchar(50) NOT NULL, +"index" varchar(50) NOT NULL, +"now" varchar(50) NULL, +count int4 NULL, +"group" text NULL, +m int8 NOT NULL, +mver varchar(50) NULL, +pver varchar(50) NULL, +CONSTRAINT pk_allshortestpath_splitprovince PRIMARY KEY (enprov, exprov, version, "index") +) +WITH ( +orientation=row, +compression=no +); + drop table if exists test_ignore_invalid_input; create table test_ignore_invalid_input(c1 int, c2 char(5), c3 timestamp, c4 bit(5), c5 boolean, c6 point, c7 uuid, c8 json, c9 jsonb, c10 xml); @@ -271,6 +292,9 @@ select * from test_ignore_not_null; select * from test_ignore_unique; select * from test_ignore_normal; +-- test for keywords +select * from allshortestpath_splitprovince; + /* * test for restore by gsql */ @@ -390,6 +414,9 @@ select * from test_ignore_not_null; select * from test_ignore_unique; select * from test_ignore_normal; +-- test for keywords +select * from allshortestpath_splitprovince; + /* * test for restore by gs_dumpall */ @@ -510,5 +537,130 @@ select * from test_ignore_not_null; select * from test_ignore_unique; select * from test_ignore_normal; +-- test for keywords +select * from allshortestpath_splitprovince; + +/* + * test for quote-all-identifiers + */ +drop database if exists table_test_gsql; +create database table_test_gsql dbcompatibility 'B'; +\! @abs_bindir@/gs_dump table_test --quote-all-identifiers -p @portstring@ -f @abs_bindir@/gsql_table_test.sql >/dev/null 2>&1; echo $? +\! @abs_bindir@/gsql -d table_test_gsql -p @portstring@ -f @abs_bindir@/gsql_table_test.sql >/dev/null 2>&1; echo $? +\c table_test_gsql + +-- test for table created by like +select * from table_like_test_2; + +-- test for table created with index +\d table_created_with_index_test +select count(*) from pg_indexes where indexname = 'create_table_idx_1' and tablename = 'table_created_with_index_test'; + +-- test for create table with compression option +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_pglz'; +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_zstd'; +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_none'; + +-- test for create list partition table with VALUES IN +select * from table_list_partition_values_in; +\d+ table_list_partition_values_in + +-- test for create table timestamp column with on update current_timestamp +\d+ table_timestamp_on_update + +-- test for view created with definer +SELECT c.relname as view_name, u.usename as rolname FROM pg_class c, pg_user u WHERE u.usesysid = c.relowner AND relname like '%view_created_with_definer_test%' ORDER BY rolname; + +-- test for functionality of select distinctrow on +select distinctrow on (c1 % 2) * from normal_test_table; +select distinctrow on (c1, c2) * from normal_test_table; + +-- test for functionality of functions +select log(10); +select log(10, 100); +select log10(100); +select log2(16); +select mod(16, 7); +select mod(0.0::float8, 0.0::numeric); +select sqrt(64::numeric); +select sqrt(b'10000'); +select ascii('你'); +select instr(null,'bc'); +select instr('abcd12abc',null); +select instr('abcd12abc','bc'); +select instr('abcd12abc','bc', 2); +select instr('abcd12abc','bc', 2, 2); +select left('abcdefg', 3); +select left('abcdefg', -3); +select right('abcdefg', 3); +select right('abcdefg', -3); +select locate('test','testgood'); +select locate('','testgood'); +select locate(NULL,'testgood'); +select locate(true,'testgood'); +select locate(false,'testgood'); +select ltrim('') is null; +select ltrim('ab', 'ab') is null; +select mid(E'\\xDEADBEEF'::bytea,2,10); +select mid(E'\\xDEADBEEF'::bytea,2,0); +select mid(E'\\xDEADBEEF'::bytea,2,-1); +select quote('O\hello'); +SELECT right('abcdefg', 3); +SELECT right('abcdefg', -3); +select rtrim('ab '); +select rtrim('ab', 'ab') is null; +select rtrim('') is null; +select substr(E'\\xDEADBEEF'::bytea,2,-1); +select substr(E'\\xDEADBEEF'::bytea,2,2); +select hex(-1); +select hex(9223372036854775807); +set dolphin.b_compatibility_mode = 1; +select format(1234.456, 2); +set dolphin.b_compatibility_mode = 0; +select format('%1s %1s!', 'Hello', 'world'); +select uuid(); +select if(true,'A','B'); +select max(c) as max_ip_addr from table_inet; +select min(c) as min_ip_addr from table_inet; +select max(c) as max_ip_addr from table_inet; +select min(c) as min_ip_addr from table_inet; +select max(c) as max_ip_addr from table_cidr; +select min(c) as min_ip_addr from table_cidr; + +-- test for comments +select description +from pg_description +where objoid in (select relfilenode + from pg_class + where relnamespace in (select oid from pg_catalog.pg_namespace where nspname = 'test_b_comments')) +order by description; +select obj_description(oid, 'pg_proc') AS comment from pg_proc where proname = 'comment_test_procedure'; +select obj_description(oid, 'pg_proc') AS comment from pg_proc where proname = 'comment_test_function'; + +-- test for drop index .. on table +\d test_drop_index_on_table + +-- test for insert statement with no INTO +select * from test_insert_no_into; + +-- test for insert statement with VALUE +select * from test_insert_value; + +-- test for insert with empty value list +select * from test_insert_empty_value_with_not_null; +select * from test_insert_empty_value_with_unique; +select * from test_insert_value_with_no_constraint; +select * from test_insert_empty_value_types_1; +select * from test_insert_empty_value_types_2; +select * from test_insert_empty_value_types_3; + +-- test for IGNORE +select * from test_ignore_not_null; +select * from test_ignore_unique; +select * from test_ignore_normal; + +-- test for keywords +select * from allshortestpath_splitprovince; + \c postgres drop database if exists table_test; \ No newline at end of file diff --git a/contrib/dolphin/output/b_auto_increment.source b/contrib/dolphin/output/b_auto_increment.source index 4d9ec3711cf67f09d594edda905a06ad84f48a25..763d083889af7e87c18b0ff70505989652d83097 100644 --- a/contrib/dolphin/output/b_auto_increment.source +++ b/contrib/dolphin/output/b_auto_increment.source @@ -608,6 +608,10 @@ alter table txxx modify `abcd` int auto_increment; NOTICE: ALTER TABLE will create implicit sequence "txxx_abcd_seq" for serial column "txxx.abcd" alter table txxx modify ABcD int auto_increment; NOTICE: ALTER TABLE will create implicit sequence "txxx_ABcD_seq" for serial column "txxx.ABcD" +create table test (a int, b int AUTO_INCREMENT,KEY `b`(`b`)); +NOTICE: CREATE TABLE will create implicit sequence "test_b_seq" for serial column "test.b" +alter table test add primary key(a); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "test_pkey" for table "test" \c postgres drop database if exists dolphin_autoinc; drop database if exists dolphin_autoinc_restore; diff --git a/contrib/dolphin/output/b_caching_auth_change_noinited.source b/contrib/dolphin/output/b_caching_auth_change_noinited.source new file mode 100644 index 0000000000000000000000000000000000000000..0ce68db92139559322c32601aee9df1e15dcc6c2 --- /dev/null +++ b/contrib/dolphin/output/b_caching_auth_change_noinited.source @@ -0,0 +1,48 @@ +-- bug #IAN93O test,change password without initializing plugin +--begin:close enable_dolphin_proto +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/datanode1/ -c "enable_dolphin_proto=off" > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! sleep 5 +--end +\! @abs_bindir@/gsql -d postgres -p @portstring@ -r -c "create database dbmysql with dbcompatibility 'B'"; +CREATE DATABASE +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "DROP USER IF EXISTS caching_user"; +NOTICE: role "caching_user" does not exist, skipping +DROP ROLE +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "CREATE USER caching_user WITH PASSWORD 'Gauss@123'"; +NOTICE: The iteration value of password is not recommended.Setting the iteration value too small reduces the security of the password, and setting it too large results in performance degradation. +CREATE ROLE +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "GRANT ALL PRIVILEGES TO caching_user"; +ALTER ROLE +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "GRANT ALL ON SCHEMA dbe_perf TO caching_user"; +GRANT +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "SET ROLE caching_user PASSWORD 'Gauss@123'"; +SET +-- set password for caching_sha2_password authentication first +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@123', ''),E'\n','X')"; +--?.* +--?.* +--?.* +(1 row) + +-- change password for caching_sha2_password authentication +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@admin', 'Gauss@123'),E'\n','X')"; +--?.* +--?.* +--?.* +(1 row) + +-- change password for caching_sha2_password authentication +\! @abs_bindir@/gsql -d dbmysql -p @portstring@ -r -c "select replace(set_caching_sha2_password('caching_user', 'Gauss@123', 'Gauss@admin'),E'\n','X')"; +--?.* +--?.* +--?.* +(1 row) + +--begin:open enable_dolphin_proto +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/datanode1/ -c "enable_dolphin_proto=on" > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/datanode1 > /dev/null 2>&1 +\! sleep 5 +--end \ No newline at end of file diff --git a/contrib/dolphin/output/b_format_drop_database.source b/contrib/dolphin/output/b_format_drop_database.source index 2e72cf0680b40605bd04317f4bacea7122a4801b..ac499b70ea8cc44e747bf0c8c42bcbca2dfe5b8a 100644 --- a/contrib/dolphin/output/b_format_drop_database.source +++ b/contrib/dolphin/output/b_format_drop_database.source @@ -40,7 +40,8 @@ show databases; pg_catalog public sqladvisor -(12 rows) + xmltype +(13 rows) drop database db1; NOTICE: DROP DATABASE will change to DROP SCHEMA when dolphin.b_compatibility_mode is on. @@ -74,5 +75,6 @@ show databases; public snapshot sqladvisor -(17 rows) + xmltype +(18 rows) diff --git a/contrib/dolphin/output/b_proto_jdbc.source b/contrib/dolphin/output/b_proto_jdbc.source index e6513ea1ef628465c1174c0d01d372968140d6f0..ec8c9c07d79d6989dc052feb11b76e2e7f1e654b 100644 --- a/contrib/dolphin/output/b_proto_jdbc.source +++ b/contrib/dolphin/output/b_proto_jdbc.source @@ -104,6 +104,16 @@ mysql dolphin-server 3 postgres +Exception in thread "main" java.sql.SQLException: non-procedure CURSOR is not supported by mysql protocol. +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* select * from t3 order by id; id | name ----+---------------- @@ -343,14 +353,14 @@ proargtypesext:CHAR:null prodefaultargposext:CHAR:null allargtypes:CHAR:23 25 23 25 26 allargtypesext:CHAR:null -oid:INT UNSIGNED:13343 +oid:INT UNSIGNED:13349 relname:CHAR:replication_slots relnamespace:INT UNSIGNED:4988 -reltype:INT UNSIGNED:13344 +reltype:INT UNSIGNED:13350 reloftype:INT UNSIGNED:0 relowner:INT UNSIGNED:10 relam:INT UNSIGNED:0 -relfilenode:INT UNSIGNED:13343 +relfilenode:INT UNSIGNED:13349 reltablespace:INT UNSIGNED:0 relpages:DOUBLE:0.0 reltuples:DOUBLE:0.0 diff --git a/contrib/dolphin/output/b_proto_jdbc_8_0_28.source b/contrib/dolphin/output/b_proto_jdbc_8_0_28.source index df20809f7d7498f433fedf35a50886a6be372fe7..19f0f4ad85ccf0d8aa8fe4a87b6055fe7e307940 100644 --- a/contrib/dolphin/output/b_proto_jdbc_8_0_28.source +++ b/contrib/dolphin/output/b_proto_jdbc_8_0_28.source @@ -104,6 +104,13 @@ mysql dolphin-server 3 postgres +Exception in thread "main" java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets. +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* select * from t3 order by id; id | name ----+---------------- @@ -197,6 +204,13 @@ mysql dolphin-server 3 postgres +Exception in thread "main" java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets. +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* select * from t3 order by id; id | name ----+---------------- @@ -289,6 +303,13 @@ mysql dolphin-server 3 postgres +Exception in thread "main" java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets. +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* select * from t3 order by id; id | name ----+---------------- @@ -381,6 +402,13 @@ mysql dolphin-server 3 postgres +Exception in thread "main" java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets. +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* select * from t3 order by id; id | name ----+---------------- diff --git a/contrib/dolphin/output/dump_dumpall_test.source b/contrib/dolphin/output/dump_dumpall_test.source index ebb9f94ce33f6ff2ff943311d0cfc0b38b7c8b51..faf8304e8c84a2d79620b3b6c8b0bd9ba4863ec2 100644 --- a/contrib/dolphin/output/dump_dumpall_test.source +++ b/contrib/dolphin/output/dump_dumpall_test.source @@ -28,7 +28,9 @@ NOTICE: table "table_created_with_compression_option_zstd" does not exist, skip drop table if exists table_created_with_compression_option_none; NOTICE: table "table_created_with_compression_option_none" does not exist, skipping create table table_created_with_compression_option_pglz(c1 int, c2 text) compression = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. create table table_created_with_compression_option_zstd(c1 int, c2 text) compression = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. create table table_created_with_compression_option_none(c1 int, c2 text) compression = none; select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_pglz'; relname | reloptions @@ -228,6 +230,26 @@ drop table if exists test_ignore_normal; NOTICE: table "test_ignore_normal" does not exist, skipping create table test_ignore_normal(c1 int, c2 text); insert ignore into test_ignore_normal values(1, 'a'); +-- test for keywords +reset dolphin.sql_mode; +CREATE TABLE allshortestpath_splitprovince ( +enprov varchar(50) NOT NULL, +exprov varchar(50) NOT NULL, +"version" varchar(50) NOT NULL, +"index" varchar(50) NOT NULL, +"now" varchar(50) NULL, +count int4 NULL, +"group" text NULL, +m int8 NOT NULL, +mver varchar(50) NULL, +pver varchar(50) NULL, +CONSTRAINT pk_allshortestpath_splitprovince PRIMARY KEY (enprov, exprov, version, "index") +) +WITH ( +orientation=row, +compression=no +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pk_allshortestpath_splitprovince" for table "allshortestpath_splitprovince" drop table if exists test_ignore_invalid_input; NOTICE: table "test_ignore_invalid_input" does not exist, skipping create table test_ignore_invalid_input(c1 int, c2 char(5), c3 timestamp, c4 bit(5), c5 boolean, c6 point, c7 uuid, @@ -772,6 +794,12 @@ select * from test_ignore_normal; 1 | a (1 row) +-- test for keywords +select * from allshortestpath_splitprovince; + enprov | exprov | version | index | now | count | group | m | mver | pver +--------+--------+---------+-------+-----+-------+-------+---+------+------ +(0 rows) + /* * test for restore by gsql */ @@ -1281,6 +1309,12 @@ select * from test_ignore_normal; 1 | a (1 row) +-- test for keywords +select * from allshortestpath_splitprovince; + enprov | exprov | version | index | now | count | group | m | mver | pver +--------+--------+---------+-------+-----+-------+-------+---+------+------ +(0 rows) + /* * test for restore by gs_dumpall */ @@ -1791,5 +1825,525 @@ select * from test_ignore_normal; 1 | a (1 row) +-- test for keywords +select * from allshortestpath_splitprovince; + enprov | exprov | version | index | now | count | group | m | mver | pver +--------+--------+---------+-------+-----+-------+-------+---+------+------ +(0 rows) + +/* + * test for quote-all-identifiers + */ +drop database if exists table_test_gsql; +create database table_test_gsql dbcompatibility 'B'; +\! @abs_bindir@/gs_dump table_test --quote-all-identifiers -p @portstring@ -f @abs_bindir@/gsql_table_test.sql >/dev/null 2>&1; echo $? +0 +\! @abs_bindir@/gsql -d table_test_gsql -p @portstring@ -f @abs_bindir@/gsql_table_test.sql >/dev/null 2>&1; echo $? +0 +\c table_test_gsql +-- test for table created by like +select * from table_like_test_2; + a | b +---+--- +(0 rows) + +-- test for table created with index +\d table_created_with_index_test +Table "public.table_created_with_index_test" + Column | Type | Modifiers +--------+---------+----------- + c1 | integer | + c2 | integer | + c3 | integer | +Indexes: + "create_table_idx_1" btree (c1 DESC, c2) TABLESPACE pg_default + +select count(*) from pg_indexes where indexname = 'create_table_idx_1' and tablename = 'table_created_with_index_test'; + count +------- + 1 +(1 row) + +-- test for create table with compression option +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_pglz'; + relname | reloptions +--------------------------------------------+---------------------------------- + table_created_with_compression_option_pglz | {orientation=row,compresstype=1} +(1 row) + +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_zstd'; + relname | reloptions +--------------------------------------------+---------------------------------- + table_created_with_compression_option_zstd | {orientation=row,compresstype=2} +(1 row) + +select relname, reloptions from pg_class where relname = 'table_created_with_compression_option_none'; + relname | reloptions +--------------------------------------------+------------------------------------------------- + table_created_with_compression_option_none | {orientation=row,compresstype=0,compression=no} +(1 row) + +-- test for create list partition table with VALUES IN +select * from table_list_partition_values_in; + col1 | col2 +------+------ + 2000 | +(1 row) + +\d+ table_list_partition_values_in + Table "public.table_list_partition_values_in" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + col1 | integer | | plain | | + col2 | integer | | plain | | +Partition By LIST(col1) +Number of partitions: 4 (View pg_partition to check each partition range.) +Has OIDs: no +Options: orientation=row, compression=no + +-- test for create table timestamp column with on update current_timestamp +\d+ table_timestamp_on_update + Table "public.table_timestamp_on_update" + Column | Type | Modifiers | Storage | Stats target | Description +--------+-----------------------------+---------------------------------------------+---------+--------------+------------- + c1 | integer | | plain | | + c2 | timestamp(0) with time zone | on update b_db_statement_start_timestamp(0) | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +-- test for view created with definer +SELECT c.relname as view_name, u.usename as rolname FROM pg_class c, pg_user u WHERE u.usesysid = c.relowner AND relname like '%view_created_with_definer_test%' ORDER BY rolname; + view_name | rolname +--------------------------------+----------- + view_created_with_definer_test | Test_User +(1 row) + +-- test for functionality of select distinctrow on +select distinctrow on (c1 % 2) * from normal_test_table; + c1 | c2 +----+---- + 2 | 1 + 1 | 3 +(2 rows) + +select distinctrow on (c1, c2) * from normal_test_table; + c1 | c2 +----+---- + 1 | 3 + 2 | 1 + 3 | 1 + 3 | 2 +(4 rows) + +-- test for functionality of functions +select log(10); + log +------------------- + 2.302585092994046 +(1 row) + +select log(10, 100); + log +-------------------- + 2.0000000000000000 +(1 row) + +select log10(100); + log10 +------- + 2 +(1 row) + +select log2(16); + log2 +------ + 4 +(1 row) + +select mod(16, 7); + mod +----- + 2 +(1 row) + +select mod(0.0::float8, 0.0::numeric); + mod +----- + +(1 row) + +select sqrt(64::numeric); + sqrt +------------------- + 8.000000000000000 +(1 row) + +select sqrt(b'10000'); + sqrt +------------------- + 4.000000000000000 +(1 row) + +select ascii('你'); + ascii +------- + 228 +(1 row) + +select instr(null,'bc'); + instr +------- + +(1 row) + +select instr('abcd12abc',null); + instr +------- + +(1 row) + +select instr('abcd12abc','bc'); + instr +------- + 2 +(1 row) + +select instr('abcd12abc','bc', 2); + instr +------- + 2 +(1 row) + +select instr('abcd12abc','bc', 2, 2); + instr +------- + 8 +(1 row) + +select left('abcdefg', 3); + left +------ + abc +(1 row) + +select left('abcdefg', -3); + left +------ + +(1 row) + +select right('abcdefg', 3); + right +------- + efg +(1 row) + +select right('abcdefg', -3); + right +------- + +(1 row) + +select locate('test','testgood'); + locate +-------- + 1 +(1 row) + +select locate('','testgood'); + locate +-------- + 1 +(1 row) + +select locate(NULL,'testgood'); + locate +-------- + +(1 row) + +select locate(true,'testgood'); + locate +-------- + 0 +(1 row) + +select locate(false,'testgood'); + locate +-------- + 0 +(1 row) + +select ltrim('') is null; + ?column? +---------- + f +(1 row) + +select ltrim('ab', 'ab') is null; + ?column? +---------- + f +(1 row) + +select mid(E'\\xDEADBEEF'::bytea,2,10); + mid +---------- + \xadbeef +(1 row) + +select mid(E'\\xDEADBEEF'::bytea,2,0); + mid +----- + \x +(1 row) + +select mid(E'\\xDEADBEEF'::bytea,2,-1); + mid +----- + \x +(1 row) + +select quote('O\hello'); + quote +------------- + E'O\\hello' +(1 row) + +SELECT right('abcdefg', 3); + right +------- + efg +(1 row) + +SELECT right('abcdefg', -3); + right +------- + +(1 row) + +select rtrim('ab '); + rtrim +------- + ab +(1 row) + +select rtrim('ab', 'ab') is null; + ?column? +---------- + f +(1 row) + +select rtrim('') is null; + ?column? +---------- + f +(1 row) + +select substr(E'\\xDEADBEEF'::bytea,2,-1); + substr +-------- + \x +(1 row) + +select substr(E'\\xDEADBEEF'::bytea,2,2); + substr +-------- + \xadbe +(1 row) + +select hex(-1); + hex +------------------ + FFFFFFFFFFFFFFFF +(1 row) + +select hex(9223372036854775807); + hex +------------------ + 7FFFFFFFFFFFFFFF +(1 row) + +set dolphin.b_compatibility_mode = 1; +select format(1234.456, 2); + format +---------- + 1,234.46 +(1 row) + +set dolphin.b_compatibility_mode = 0; +select format('%1s %1s!', 'Hello', 'world'); + format +-------------- + Hello world! +(1 row) + +select uuid(); + uuid +-------------------------------------- +--?.* +(1 row) + +select if(true,'A','B'); + case +------ + A +(1 row) + +select max(c) as max_ip_addr from table_inet; + max_ip_addr +------------- + 192.168.1.2 +(1 row) + +select min(c) as min_ip_addr from table_inet; + min_ip_addr +------------- + 192.168.1.0 +(1 row) + +select max(c) as max_ip_addr from table_inet; + max_ip_addr +------------- + 192.168.1.2 +(1 row) + +select min(c) as min_ip_addr from table_inet; + min_ip_addr +------------- + 192.168.1.0 +(1 row) + +select max(c) as max_ip_addr from table_cidr; + max_ip_addr +------------- + 192.168.1.0 +(1 row) + +select min(c) as min_ip_addr from table_cidr; + min_ip_addr +---------------- + 192.168.1.0/30 +(1 row) + +-- test for comments +select description +from pg_description +where objoid in (select relfilenode + from pg_class + where relnamespace in (select oid from pg_catalog.pg_namespace where nspname = 'test_b_comments')) +order by description; + description +------------------------ + comment_test_column + comment_test_column.a + comment_test_column.b + comment_test_row + comment_test_row.a + comment_test_row.b + comment_test_row_index +(7 rows) + +select obj_description(oid, 'pg_proc') AS comment from pg_proc where proname = 'comment_test_procedure'; + comment +------------------------ + comment_test_procedure +(1 row) + +select obj_description(oid, 'pg_proc') AS comment from pg_proc where proname = 'comment_test_function'; + comment +----------------------- + comment_test_function +(1 row) + +-- test for drop index .. on table +\d test_drop_index_on_table +Table "public.test_drop_index_on_table" + Column | Type | Modifiers +--------+---------+----------- + a | integer | + +-- test for insert statement with no INTO +select * from test_insert_no_into; + c1 | c2 +----+----- + 1 | one + 2 | two +(2 rows) + +-- test for insert statement with VALUE +select * from test_insert_value; + c1 | c2 +----+----- + 1 | one + 2 | two +(2 rows) + +-- test for insert with empty value list +select * from test_insert_empty_value_with_not_null; + c1 | c2 +----+------------ + 0 | 1970-01-01 +(1 row) + +select * from test_insert_empty_value_with_unique; + c1 | c2 +----+---- + | + | +(2 rows) + +select * from test_insert_value_with_no_constraint; + c1 | c2 +----+---- + | + | + | +(3 rows) + +select * from test_insert_empty_value_types_1; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | c16 | c17 | c18 | c19 | c20 | c21 | c22 | c23 | c24 | c25 +----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + | | | | | | | | | | | | | | | | | | | | | | | | +(1 row) + +select * from test_insert_empty_value_types_2; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | c16 | c17 | c18 | c19 | c20 | c21 | c22 | c23 | c24 +----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + 1 | 1 | 1 | | | | | | | | | | | | | | | | | | | | | +(1 row) + +select * from test_insert_empty_value_types_3; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 | c11 | c12 | c13 +----+----+----+----+----+----+----+----+----+-----+-----+-----+----- + | | | | | | | | | | | | +(1 row) + +-- test for IGNORE +select * from test_ignore_not_null; + c1 +---- + 0 +(1 row) + +select * from test_ignore_unique; + c1 +---- + 1 + 2 +(2 rows) + +select * from test_ignore_normal; + c1 | c2 +----+---- + 1 | a +(1 row) + +-- test for keywords +select * from allshortestpath_splitprovince; + enprov | exprov | version | index | now | count | group | m | mver | pver +--------+--------+---------+-------+-----+-------+-------+---+------+------ +(0 rows) + \c postgres drop database if exists table_test; diff --git a/contrib/dolphin/output/test_table_ddl_import_and_export.source b/contrib/dolphin/output/test_table_ddl_import_and_export.source index 5c709fab4918b02537355f153f17b0df3f79b161..f051b8e94930d9f3b41c570510cad0f00f7cf8dd 100644 --- a/contrib/dolphin/output/test_table_ddl_import_and_export.source +++ b/contrib/dolphin/output/test_table_ddl_import_and_export.source @@ -11,6 +11,7 @@ create database restore_table_db with dbcompatibility = 'B'; create table t_create_table_001(c int) engine = InnoDB; --指定compression设置压缩参数 create table t_create_table_002(c int) compression = pglz; +WARNING: The compressed relation you are using is an unofficial supported extended feature. --row_format支持default create table t_create_table_003(c int) row_format = default; WARNING: ROW_FORMAT for TABLE is not supported for current version. skipped @@ -34,6 +35,7 @@ create table if not exists t_create_table_015 like t_create_table_011; create table t_create_table_016(c int) charset utf8 engine = InnoDB; create table t_create_table_017(c int) engine = InnoDB charset utf8; create table t_create_table_018(c int) for materialized view nocompress compression = pglz for materialized view compression = zstd; +WARNING: The compressed relation you are using is an unofficial supported extended feature. --指定timestamp类型为on update current_timestamp create table t_create_table_019(c int, t timestamp on update current_timestamp); --支持create table创建索引 diff --git a/contrib/dolphin/output/view_definer_test.source b/contrib/dolphin/output/view_definer_test.source index a6f014e6c6b849575ed2f1d7c5bed73638fe2532..796afcf2a3311e03b2f8148a1e8c6625905811cb 100644 --- a/contrib/dolphin/output/view_definer_test.source +++ b/contrib/dolphin/output/view_definer_test.source @@ -67,9 +67,9 @@ SELECT c.relname as view_name, u.usename as rolname FROM pg_class c, pg_user u W CREATE SCHEMA "Test_User"; ALTER SCHEMA "Test_User" OWNER TO "Test_User"; -CREATE SCHEMA test_user2; -ALTER SCHEMA test_user2 OWNER TO test_user2; -CREATE DEFINER = "Root_Test" PROCEDURE pro_1107262(n int) NOT SHIPPABLE +CREATE SCHEMA "test_user2"; +ALTER SCHEMA "test_user2" OWNER TO "test_user2"; +CREATE DEFINER = "Root_Test" PROCEDURE "pro_1107262"(n int) NOT SHIPPABLE AS DECLARE begin repeat insert into tab_1107262 values(n,n*2); @@ -77,23 +77,23 @@ n:=n+1; until n>10 end repeat; end; / -ALTER PROCEDURE public.pro_1107262(n integer) OWNER TO "Root_Test"; -CREATE VIEW definer_test_view1(log) AS - SELECT log((10)::number, (1000)::number) AS log; -ALTER VIEW public.definer_test_view1 OWNER TO "Root_Test"; -CREATE VIEW definer_test_view2(log) AS - SELECT log((10)::number, (100)::number) AS log; -ALTER VIEW public.definer_test_view2 OWNER TO test_user2; -CREATE VIEW definer_test_view3(log) AS - SELECT log((10)::number, (100)::number) AS log; -ALTER VIEW public.definer_test_view3 OWNER TO "Test_User"; -CREATE TABLE tab_1107262 ( - id integer, - c1 integer +ALTER PROCEDURE "public"."pro_1107262"("n" integer) OWNER TO "Root_Test"; +CREATE VIEW "definer_test_view1"("log") AS + SELECT "log"((10)::number, (1000)::number) AS "log"; +ALTER VIEW "public"."definer_test_view1" OWNER TO "Root_Test"; +CREATE VIEW "definer_test_view2"("log") AS + SELECT "log"((10)::number, (100)::number) AS "log"; +ALTER VIEW "public"."definer_test_view2" OWNER TO "test_user2"; +CREATE VIEW "definer_test_view3"("log") AS + SELECT "log"((10)::number, (100)::number) AS "log"; +ALTER VIEW "public"."definer_test_view3" OWNER TO "Test_User"; +CREATE TABLE "tab_1107262" ( + "id" integer, + "c1" integer ) WITH (orientation=row, compression=no); -ALTER TABLE public.tab_1107262 OWNER TO "Root_Test"; -COPY public.tab_1107262 (id, c1) FROM stdin; +ALTER TABLE "public"."tab_1107262" OWNER TO "Root_Test"; +COPY public."tab_1107262" ("id", "c1") FROM stdin; \. ; \! @abs_bindir@/gs_dump test_db -p @portstring@ -F c -f @abs_bindir@/definer_view_dump.dmp --disable-progress @@ -163,6 +163,8 @@ SET SET SET SET +SET +SET CREATE TABLE ALTER TABLE CREATE VIEW diff --git a/contrib/dolphin/parallel_schedule_dolphin b/contrib/dolphin/parallel_schedule_dolphin index 16cbd3e5b9acad951e569344c10b0c50ef1db563..853206044e2945566335441a6a62a4b4c830ef20 100644 --- a/contrib/dolphin/parallel_schedule_dolphin +++ b/contrib/dolphin/parallel_schedule_dolphin @@ -9,7 +9,7 @@ test: db_b_parser1 db_b_parser2 db_b_parser3 db_b_parser4 second_microsecond tes test: db_b_plpgsql_test default_guc describe explain_desc kill set_password network test_dayofweek test_timestampn kwlist empty_enum_value -test: empty_value_list empty_value_lists empty_value_support_value create_index test_guc_select_and_set test_copy_year2 test_default convert_truncated_warning assignment_conversion_to_year +test: empty_value_list empty_value_lists empty_value_support_value create_index test_guc_select_and_set test_copy_year2 test_default convert_truncated_warning assignment_conversion_to_year ustore_test test: greatest_least join_without_on mysqlmode_fullgroup mysqlmode_strict mysqlmode_strict2 none_strict_warning test_alter_table test_dolphin_catalog inet_ntoa_nvarchar2 @@ -85,9 +85,9 @@ test: builtin_funcs/b_compatibility_time_funcs builtin_funcs/b_compatibility_tim # case sensitive test, do not insert test case */ test: case_sensitive_test/create_env -test: case_sensitive_test/create_table case_sensitive_test/create_table_like case_sensitive_test/create_foreign_table case_sensitive_test/cluster case_sensitive_test/temp case_sensitive_test/rowlevelsecurity case_sensitive_test/rules column_name +test: case_sensitive_test/create_table case_sensitive_test/create_table_like case_sensitive_test/create_foreign_table case_sensitive_test/cluster case_sensitive_test/temp case_sensitive_test/rowlevelsecurity case_sensitive_test/rules column_name foreign_key_checks_test -test: case_sensitive_test/single_node_foreign_key case_sensitive_test/create_index case_sensitive_test/insert case_sensitive_test/update case_sensitive_test/delete case_sensitive_test/vacuum case_sensitive_test/analyze_commands case_sensitive_test/single_node_triggers +test: case_sensitive_test/single_node_foreign_key case_sensitive_test/create_index case_sensitive_test/insert case_sensitive_test/update case_sensitive_test/delete case_sensitive_test/vacuum case_sensitive_test/analyze_commands case_sensitive_test/single_node_triggers case_sensitive_test/trigger test: case_sensitive_test/alter_table case_sensitive_test/reindex_internal case_sensitive_test/spi_test case_sensitive_test/quoted case_sensitive_test/merge case_sensitive_test/case_sensitive_bug_test @@ -125,7 +125,7 @@ test: test_mysql_operator test_op_xor_unsignedint test_op_blob test_op_xor_boola test: json_array json_object json_quote json_contains json_contains_path json_extract json_unquote json_keys json_search json_array_append -test: show b_comments ansi_quotes_start b_system_view test_proxy test_to_days b_format_drop_database subquery +test: show b_comments ansi_quotes_start b_system_view b_rowtype test_proxy test_to_days b_format_drop_database subquery test: pl_debugger_server pl_debugger_client load load2 flush ansi_quotes_test partition_engine @@ -175,6 +175,8 @@ test: test_show_slave_status recursive test: test_show_open_tables test: test_show_open_tables_lock_waiting_1 test_show_open_tables_lock_waiting_2 test: test_show_open_tables_cleanup -test: column_quote_alias sconst_sconst sqlmode_strict test_view_table_depend +test: column_quote_alias sconst_sconst sqlmode_strict test_view_table_depend test_geometric_operator test: test_row_in test_std test_var_pop b_database_subquery test_lag_lead builtin_funcs/max_min escape_char delimiter + +test: ignore_keyword_list diff --git a/contrib/dolphin/plugin_catalog/heap.cpp b/contrib/dolphin/plugin_catalog/heap.cpp index 6d61291a009de8afa72f63e802badd1ee481a25b..c1b2523e7395ca1241b90225cef4666d8bc125cf 100644 --- a/contrib/dolphin/plugin_catalog/heap.cpp +++ b/contrib/dolphin/plugin_catalog/heap.cpp @@ -868,7 +868,7 @@ void CheckAttributeType( * If it's a domain, recurse to check its base type. */ CheckAttributeType(attname, getBaseType(atttypid), attcollation, containing_rowtypes, allow_system_table_mods); - } else if (att_typtype == TYPTYPE_COMPOSITE) { + } else if (att_typtype == TYPTYPE_COMPOSITE || att_typtype == TYPTYPE_ABSTRACT_OBJECT) { /* * For a composite type, recurse into its attributes. */ diff --git a/contrib/dolphin/plugin_executor/execQual.cpp b/contrib/dolphin/plugin_executor/execQual.cpp index ebca4888bed6dbc4a7a5e63ff1aa14e9d2e1c39c..743c988cd29577ccc7559167492e0130042fa64c 100644 --- a/contrib/dolphin/plugin_executor/execQual.cpp +++ b/contrib/dolphin/plugin_executor/execQual.cpp @@ -1438,7 +1438,7 @@ static Datum ExecEvalParamExtern(ExprState* exprstate, ExprContext* econtext, bo *isNull = prm->isnull; if (prm->tabInfo && prm->tabInfo->isnestedtable && plpgsql_estate) { - plpgsql_estate->curr_nested_table_type = prm->ptype; + plpgsql_estate->curr_nested_table_type = prm->tabInfo->tableOfIndexType; plpgsql_estate->curr_nested_table_layers = prm->tabInfo->tableOfLayers; } /* copy cursor option from param to econtext */ @@ -2207,14 +2207,8 @@ static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc) } } -void set_result_for_plpgsql_language_function_with_outparam(FuncExprState *fcache, Datum *result, bool *isNull) +void set_result_for_plpgsql_language_function_with_outparam(Datum *result, bool *isNull) { - if (!IsA(fcache->xprstate.expr, FuncExpr)) { - return; - } - if (!fcache->is_plpgsql_func_with_outparam) { - return; - } HeapTupleHeader td = DatumGetHeapTupleHeader(*result); TupleDesc tupdesc; PG_TRY(); @@ -2245,6 +2239,18 @@ void set_result_for_plpgsql_language_function_with_outparam(FuncExprState *fcach pfree(nulls); } +void set_result_for_plpgsql_language_function_with_outparam(FuncExprState *fcache, Datum *result, bool *isNull) +{ + if (!IsA(fcache->xprstate.expr, FuncExpr)) { + return; + } + if (!fcache->is_plpgsql_func_with_outparam) { + return; + } + return set_result_for_plpgsql_language_function_with_outparam(result, isNull); +} + + bool ExecSetArgIsByValue(FunctionCallInfo fcinfo) { for (int i = 0; i < fcinfo->nargs; i++) { diff --git a/contrib/dolphin/plugin_executor/functions.cpp b/contrib/dolphin/plugin_executor/functions.cpp index cd6c250678dbb4545691f82d2621d849a3747643..c902dfe78a5564c54c11030c7d3628f411d59128 100644 --- a/contrib/dolphin/plugin_executor/functions.cpp +++ b/contrib/dolphin/plugin_executor/functions.cpp @@ -799,6 +799,8 @@ static void postquel_start(execution_state* es, SQLFunctionCachePtr fcache) es->qd = CreateUtilityQueryDesc(es->stmt, fcache->src, GetActiveSnapshot(), dest, fcache->paramLI); } + es->qd->for_simplify_func = true; + /* Utility commands don't need Executor. */ if (es->qd->utilitystmt == NULL) { /* @@ -1775,7 +1777,7 @@ bool check_sql_fn_retval(Oid func_id, Oid ret_type, List* query_tree_list, bool* /* Set up junk filter if needed */ if (junk_filter != NULL) *junk_filter = ExecInitJunkFilter(tlist, false, NULL, TableAmHeap); - } else if (fn_type == TYPTYPE_COMPOSITE || ret_type == RECORDOID) { + } else if (fn_type == TYPTYPE_COMPOSITE || fn_type == TYPTYPE_ABSTRACT_OBJECT || ret_type == RECORDOID) { /* Returns a rowtype */ TupleDesc tup_desc; int tup_natts; /* physical number of columns in tuple */ diff --git a/contrib/dolphin/plugin_optimizer/commands/functioncmds.cpp b/contrib/dolphin/plugin_optimizer/commands/functioncmds.cpp index e82d33baaf50084f4c4e9a354ea026db2b24a940..94669257813190bc6fbc707ca3e8b2db4894d603 100755 --- a/contrib/dolphin/plugin_optimizer/commands/functioncmds.cpp +++ b/contrib/dolphin/plugin_optimizer/commands/functioncmds.cpp @@ -744,7 +744,7 @@ static bool compute_b_attribute(DefElem* defel) * Dissect the list of options assembled in gram.y into function * attributes. */ -static List* compute_attributes_sql_style(const List* options, List** as, char** language, bool* windowfunc_p, +List* compute_attributes_sql_style(const List* options, List** as, char** language, bool* windowfunc_p, char* volatility_p, bool* strict_p, bool* security_definer, bool* leakproof_p, ArrayType** proconfig, float4* procost, float4* prorows, bool* fenced, bool* shippable, bool* package, bool* is_pipelined, FunctionPartitionInfo** partInfo) @@ -1070,7 +1070,7 @@ extern HeapTuple SearchUserHostName(const char* userName, Oid* oid); * CreateFunction * Execute a CREATE FUNCTION utility statement. */ -ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_oid) +ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_oid, Oid type_oid) { char* probin_str = NULL; char* prosrc_str = NULL; @@ -1146,9 +1146,9 @@ ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, */ bool isalter = false; /* Convert list of names to a name and namespace */ - if (!OidIsValid(pkg_oid)) { + if (!OidIsValid(pkg_oid) && !OidIsValid(type_oid)) { namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname, &funcname); - } else { + } else if (OidIsValid(pkg_oid)) { char *schemaname = NULL; DeconstructQualifiedName(stmt->funcname, &schemaname, &funcname); HeapTuple tuple = SearchSysCache1(PACKAGEOID, ObjectIdGetDatum(pkg_oid)); @@ -1166,6 +1166,17 @@ ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PACKAGE), errmsg("package not found"))); } ReleaseSysCache(tuple); + } else { + char *schemaname = NULL; + DeconstructQualifiedName(stmt->funcname, &schemaname, &funcname); + HeapTuple tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid)); + if (HeapTupleIsValid(tuple)) { + Form_pg_type typform = (Form_pg_type)GETSTRUCT(tuple); + namespaceId = typform->typnamespace; + } else { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PACKAGE), errmsg("object type not found"))); + } + ReleaseSysCache(tuple); } CheckCreateFunctionPrivilege(namespaceId, funcname); @@ -1439,7 +1450,10 @@ ObjectAddress CreateFunction(CreateFunctionStmt* stmt, const char* queryString, ret_type_depend_ext, stmt, isPipelined, - partInfo); + partInfo, + type_oid, + stmt->typfunckind, + stmt->isfinal); CreateFunctionComment(address.objectId, functionOptions); pfree_ext(param_type_depend_ext); @@ -3115,6 +3129,10 @@ ObjectAddress CreateCast(CreateCastStmt* stmt) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("composite data types are not binary-compatible"))); + if (sourcetyptype == TYPTYPE_ABSTRACT_OBJECT || targettyptype == TYPTYPE_ABSTRACT_OBJECT) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("composite data types are not binary-compatible"))); + if (sourcetyptype == TYPTYPE_ENUM || targettyptype == TYPTYPE_ENUM) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("enum data types are not binary-compatible"))); diff --git a/contrib/dolphin/plugin_optimizer/commands/schemacmds.cpp b/contrib/dolphin/plugin_optimizer/commands/schemacmds.cpp index 66d22d43e5f5a4a649332ffd2a2f5b51d400023f..c3929d5878f0d591f52e112adec009e114f4bce9 100644 --- a/contrib/dolphin/plugin_optimizer/commands/schemacmds.cpp +++ b/contrib/dolphin/plugin_optimizer/commands/schemacmds.cpp @@ -235,6 +235,9 @@ Oid CreateSchemaCommand(CreateSchemaStmt* stmt, const char* queryString) /* OK to skip */ ereport(NOTICE, (errmsg("schema \"%s\" already exists,skipping", schemaName))); + + /* Reset current user and security context. */ + SetUserIdAndSecContext(saved_uid, save_sec_context); return InvalidOid; } } @@ -386,6 +389,7 @@ void AlterSchemaCommand(AlterSchemaStmt* stmt) AclResult aclresult; const int STR_SCHEMA_NAME_LENGTH = 9; const int STR_SNAPSHOT_LENGTH = 8; + ObjectAddress address; if (withBlockchain && ((strncmp(nspName, "dbe_perf", STR_SCHEMA_NAME_LENGTH) == 0) || (strncmp(nspName, "snapshot", STR_SNAPSHOT_LENGTH) == 0))) { @@ -420,6 +424,9 @@ void AlterSchemaCommand(AlterSchemaStmt* stmt) (errcode(ERRCODE_RESERVED_NAME), errmsg("The system schema \"%s\" doesn't allow to alter to blockchain schema", nspName))); + ObjectAddressSet(address, NamespaceNameIndexId, HeapTupleGetOid(tup)); + EventTriggerCollectSimpleCommand(address, InvalidObjectAddress, (Node*)stmt); + Datum new_record[Natts_pg_namespace] = {0}; bool new_record_nulls[Natts_pg_namespace] = {false}; bool new_record_repl[Natts_pg_namespace] = {false}; diff --git a/contrib/dolphin/plugin_optimizer/commands/typecmds.cpp b/contrib/dolphin/plugin_optimizer/commands/typecmds.cpp index 10b47ba645b793178b33a26461bcbd9f6f8f6517..e3dadb5e917382632691cec83e4c8b5c3f881389 100644 --- a/contrib/dolphin/plugin_optimizer/commands/typecmds.cpp +++ b/contrib/dolphin/plugin_optimizer/commands/typecmds.cpp @@ -37,6 +37,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/tableam.h" +#include "access/transam.h" #include "access/xact.h" #include "catalog/catalog.h" #include "catalog/dependency.h" @@ -59,6 +60,7 @@ #include "catalog/pg_type_fn.h" #include "catalog/gs_db_privilege.h" #include "plugin_commands/defrem.h" +#include "commands/dbcommands.h" #include "commands/tablecmds.h" #include "commands/typecmds.h" #include "executor/executor.h" @@ -86,6 +88,9 @@ #include "utils/typcache.h" #include "catalog/gs_dependencies_fn.h" #include "catalog/pg_object.h" +#include "catalog/pg_object_type.h" +#include "funcapi.h" +#include "utils/typcache.h" /* result structure for get_rels_with_domain() */ typedef struct { @@ -115,6 +120,35 @@ static void CheckFuncParamType(Oid foid, Oid toid, bool isin); static void CheckTypeMatch(Oid funcOid, bool isInputFunc, int16 typlen, bool typbyval); static Oid GetBuiltinFuncTypeOid(Oid custumTypeFunc, bool isInputFunc); +/* object type methods */ +static Oid SubTypeInheritBaseType(CompositeTypeStmt* stmt); +static List* object_type_get_function_arguments(HeapTuple proctup); +static List* MergeObjectTypeMethod(CompositeTypeStmt* stmt, Oid typeoid); +static bool isSameTypeMethodArgList(List* argList1, List* argList2, List* funcname); +static List* MergeObjectTypeAttributes(List* schema, Oid supertypeid, int32 typmod); +static void GetSuperTypeAttribute(CompositeTypeStmt* stmt, Oid supertypeoid); +static bool is_same_function(HeapTuple proctup, TupleDesc tupdesc, CreateFunctionStmt* method); +static void DealTypeMethodSelfParam(CompositeTypeStmt* stmt, Oid typeoid, List* methodList); +static void UpdateObjectTypeTypeAttribute(Oid typid); +static void GetObjectTypeMapOrderMethod(Oid typeoid, char* mapOrder, Oid* mapid, Oid* orderid); +static void MakeDefaultArrayConstructMethod(List* typname, Oid elemtypoid, Oid typoid); +static List* ConstructQualifiedName(char* catalogname, char* schemaname, char* relname); +static Node *makeAArrayExpr(List *elements, int location) +{ + A_ArrayExpr *n = makeNode(A_ArrayExpr); + + n->elements = elements; + n->location = location; + return (Node *) n; +} +static Node *makeTypeCast(Node *arg, TypeName *typname, int location) +{ + TypeCast *n = makeNode(TypeCast); + n->arg = arg; + n->typname = typname; + n->location = location; + return (Node *) n; +} /* * DefineType * Registers a new base type. @@ -663,12 +697,27 @@ void RemoveTypeById(Oid typeOid) #endif Relation relation; HeapTuple tup; + Relation objectrel = NULL; + HeapTuple objecttuple; + char typtype = 0; relation = heap_open(TypeRelationId, RowExclusiveLock); - tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for type %u", typeOid))); + typtype = ((Form_pg_type)GETSTRUCT(tup))->typtype; + /* Delete related methods while deleting object type */ + if (typtype == TYPTYPE_ABSTRACT_OBJECT) { + /* Delete data in pg_object_type */ + objectrel = heap_open(ObjectTypeRelationId, RowExclusiveLock); + objecttuple = SearchSysCache1(OBJECTTYPE, ObjectIdGetDatum(typeOid)); + if (!HeapTupleIsValid(objecttuple)) + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for object type %u", typeOid))); + CatalogTupleDelete(objectrel, &objecttuple->t_self); + heap_close(objectrel, RowExclusiveLock); + ReleaseSysCache(objecttuple); + } simple_heap_delete(relation, &tup->t_self); @@ -2232,26 +2281,31 @@ ObjectAddress DefineTableOfType(const TableOfTypeStmt* stmt) errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for type %u, type Oid is invalid", typeOid))); } + Form_pg_type typform = (Form_pg_type)GETSTRUCT(type_tup); - if (((Form_pg_type)GETSTRUCT(type_tup))->typtype == TYPTYPE_TABLEOF) { + if (typform->typtype == TYPTYPE_TABLEOF) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("table type does not support nested table."))); } - Oid refTypeOid = ((Form_pg_type)GETSTRUCT(type_tup))->typarray; + Oid refTypeOid = typform->typarray; if (!OidIsValid(refTypeOid)) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("type %s doesn't support table type.", (((Form_pg_type)GETSTRUCT(type_tup))->typname).data))); + errmsg("type %s doesn't support table type.", (typform->typname).data))); } ReleaseSysCache(type_tup); if (OidIsValid(typoid) && get_typisdefined(typoid)) { - return ReplaceTableOfType(typoid, refTypeOid); + /* Remove and rebuild Array construct method */ + RemoveTypeMethod(typoid); + ObjectAddress address = ReplaceTableOfType(typoid, refTypeOid); + MakeDefaultArrayConstructMethod(stmt->typname, typeOid, address.objectId); + return address; } else { /* Create the pg_type entry */ - return TypeCreate(InvalidOid, /* no predetermined type OID */ + ObjectAddress address = TypeCreate(InvalidOid, /* no predetermined type OID */ typname, /* type name */ typeNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ @@ -2282,8 +2336,58 @@ ObjectAddress DefineTableOfType(const TableOfTypeStmt* stmt) 0, /* Array dimensions of typbasetype */ false, /* Type NOT NULL */ InvalidOid); /* type's collation (ranges never have one) */ + CommandCounterIncrement(); + + MakeDefaultArrayConstructMethod(stmt->typname, typeOid, address.objectId); + + return address; } - +} + +static void MakeDefaultArrayConstructMethod(List* typname, Oid elemtypoid, Oid typoid) +{ + Form_pg_type type = NULL; + HeapTuple tuple = NULL; + List* paramlist = NULL; + List* option = NULL; + FunctionParameter *self = makeNode(FunctionParameter); + StringInfoData defassign; + Oid arraytypeoid = get_array_type(elemtypoid); + initStringInfo(&defassign); + appendStringInfo(&defassign, "begin return self; \nend"); + + tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arraytypeoid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("array type with OID %u does not exist", arraytypeoid))); + type = (Form_pg_type)GETSTRUCT(tuple); + self->name = pstrdup("self"); + self->argType = makeTypeNameFromNameList(list_make2( + makeString(get_namespace_name(type->typnamespace)), makeString(NameStr(type->typname)))); + self->mode = FUNC_PARAM_VARIADIC; + self->defexpr = (Node*)makeNullAConst(-1); + paramlist = lappend(paramlist, self); + + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = list_copy(typname); + + n->parameters = paramlist; + n->returnType = makeTypeNameFromNameList(typname); + n->typfunckind = TABLE_VARRAY_CONSTRUCTOR_PROC; + n->isfinal = true; + option = list_make1(makeDefElem("as", (Node*)list_make1(makeString(defassign.data)))); + option = lappend(option, makeDefElem("language", (Node*)makeString("plpgsql"))); + option = lappend(option, makeDefElem("strict", (Node*)makeInteger(TRUE))); + n->options = option; + n->withClause = NULL; + n->isProcedure = false; + + CreateFunction(n, NULL, InvalidOid, typoid); + ReleaseSysCache(tuple); } /* ------------------------------------------------------------------- @@ -2300,12 +2404,14 @@ ObjectAddress DefineTableOfType(const TableOfTypeStmt* stmt) * an implicit composite type during function creation * ------------------------------------------------------------------- */ -ObjectAddress DefineCompositeType(RangeVar* typevar, List* coldeflist) +ObjectAddress DefineCompositeType(RangeVar* typevar, List* coldeflist, bool replace, + ObjectAddress* reladdress, bool is_object_type) { CreateStmt* createStmt = makeNode(CreateStmt); Oid old_type_oid; Oid typeNamespace; ObjectAddress address; + Oid pkgOid = InvalidOid; /* * now set the parameters for keys/inheritance etc. All of these are * uninteresting for composite types... @@ -2331,20 +2437,1312 @@ ObjectAddress DefineCompositeType(RangeVar* typevar, List* coldeflist) old_type_oid = GetSysCacheOid2(TYPENAMENSP, CStringGetDatum(createStmt->relation->relname), ObjectIdGetDatum(typeNamespace)); if (OidIsValid(old_type_oid)) { + /* replace will drop the ojbect type. */ + if (replace) { + DropStmt* n = makeNode(DropStmt); + n->removeType = OBJECT_TYPE; + n->missing_ok = true; + n->objects = list_make1(list_make1(makeTypeNameFromNameList( + ConstructQualifiedName(typevar->catalogname, typevar->schemaname, typevar->relname)))); + n->arguments = NIL; + n->behavior = DROP_CASCADE; + n->concurrent = false; + n->purge = false; + RemoveObjects(n, true, has_createrole_privilege(GetUserId())); + } if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", createStmt->relation->relname))); } + /* Check object type related package exists since object type is hard to distinguish package and object type */ + if (is_object_type) { + pkgOid = PackageNameGetOid(createStmt->relation->relname, typeNamespace); + if (OidIsValid(pkgOid)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("type \"%s\" already exists same package object", createStmt->relation->relname))); + } + /* * Finally create the relation. This also creates the type. */ - DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address); + ObjectAddress relation_address = DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address); + if (reladdress) + *reladdress = relation_address; return address; } +void RemoveTypeMethod(Oid typeoid) +{ + Relation desc; + ScanKeyData skey[1]; + SysScanDesc sysscan; + HeapTuple tuple; + + ScanKeyInit(&skey[0], Anum_pg_proc_packageid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(typeoid)); + desc = heap_open(ProcedureRelationId, AccessShareLock); + sysscan = systable_beginscan(desc, ProcedureNameArgsNspNewIndexId, true, NULL, 1, skey); + + /* Get all method according to type_oid */ + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + Oid result = InvalidOid; + result = HeapTupleGetOid(tuple); + if (OidIsValid(result)) { + (void)deleteDependencyRecordsFor(ProcedureRelationId, result, true); + (void)deleteSharedDependencyRecordsFor(ProcedureRelationId, result, 0); + /* delete this method */ + DeleteTypesDenpendOnPackage(ProcedureRelationId, result); + RemoveFunctionById(result); + } + } + + systable_endscan(sysscan); + heap_close(desc, AccessShareLock); +} + +static void GetObjectTypeMapOrderMethod(Oid typeoid, char *mapOrder, Oid* mapid, Oid* orderid) +{ + Relation desc; + ScanKeyData skey[2]; + SysScanDesc sysscan; + HeapTuple tuple; + + ScanKeyInit(&skey[0], Anum_pg_proc_proname, BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(mapOrder)); + ScanKeyInit(&skey[1], Anum_pg_proc_packageid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(typeoid)); + desc = heap_open(ProcedureRelationId, AccessShareLock); + sysscan = systable_beginscan(desc, ProcedureNameArgsNspNewIndexId, true, NULL, 2, skey); + + /* Get all method according to type_oid */ + while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { + Oid result = InvalidOid; + result = HeapTupleGetOid(tuple); + bool isNull = false; + char methodtype = OBJECTTYPE_NULL_PROC; + if (!OidIsValid(result)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("map or order method \"%s\" is not exist.", mapOrder))); + } + /* Find method type from pg_object */ + Assert(result >= FirstBootstrapObjectId); + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(result), CharGetDatum(OBJECT_TYPE_PROC)); + if (!HeapTupleIsValid(objTuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("map or order method \"%s\" is not exist.", mapOrder))); + } + methodtype = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isNull)); + ReleaseSysCache(objTuple); + if ((methodtype != OBJECTTYPE_MAP_PROC) && (methodtype != OBJECTTYPE_ORDER_PROC)) + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("map or order method \"%s\" type error.", mapOrder))); + if (methodtype == OBJECTTYPE_MAP_PROC) + *mapid = result; + else + *orderid = result; + } + + systable_endscan(sysscan); + heap_close(desc, AccessShareLock); +} + +static void MakeDefaultParamConstructMethod(CompositeTypeStmt* stmt, Oid typoid) +{ + Relation relation; + TupleDesc tupledesc; + AttrNumber parent_attno; + Form_pg_type type = NULL; + HeapTuple tuple = NULL; + List* paramlist = NIL; + List* option = NIL; + List* typ = list_make1(makeString(stmt->typevar->relname)); + StringInfoData defassign; + + initStringInfo(&defassign); + appendStringInfo(&defassign, "begin \n self := ROW("); + + if (stmt->typevar->schemaname) + typ = lcons(makeString(stmt->typevar->schemaname), typ); + + FunctionParameter *self = makeNode(FunctionParameter); + self->name = pstrdup("self"); + self->argType = makeTypeNameFromNameList(typ); + self->mode = FUNC_PARAM_OUT; + paramlist = lappend(paramlist, self); + tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid)); + if (!HeapTupleIsValid(tuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("Ojbect type with Oid %u does not exist", typoid))); + } + type = (Form_pg_type)GETSTRUCT(tuple); + + relation = relation_open(type->typrelid, AccessShareLock); + tupledesc = RelationGetDescr(relation); + + for (parent_attno = 1; parent_attno <= tupledesc->natts; parent_attno++) { + Form_pg_attribute attribute = &tupledesc->attrs[parent_attno - 1]; + char* attributeName = NameStr(attribute->attname); + FunctionParameter *param = NULL; + + /* Ignore dropped columns in parent. */ + if (attribute->attisdropped) { + continue; /* leave newattno entry as zero */ + } + param = makeNode(FunctionParameter); + + param->argType = makeTypeNameFromNameList(get_typename_with_schema(attribute->atttypid)); + param->name = pstrdup(attributeName); + param->mode = FUNC_PARAM_IN; + param->defexpr = NULL; + paramlist = lappend(paramlist, param); + /* + * Use row method to build for default, add quote to make sure we can use origin value of columns + */ + if (parent_attno == tupledesc->natts) + appendStringInfo(&defassign, "%s", quote_identifier(attributeName)); + else + appendStringInfo(&defassign, "%s, ", quote_identifier(attributeName)); + } + + appendStringInfoString(&defassign, "); \nend"); + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = list_make1(makeString(stmt->typevar->relname)); + if (stmt->typevar->schemaname) + n->funcname = lcons(makeString(stmt->typevar->schemaname), n->funcname); + n->parameters = paramlist; + n->typfunckind = OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC; + n->isfinal = true; + option = list_make1(makeDefElem("as", (Node*)list_make1(makeString(defassign.data)))); + option = lappend(option, makeDefElem("language", (Node*)makeString("plpgsql"))); + n->options = option; + n->withClause = NULL; + n->isProcedure = false; + + stmt->methodlist = lcons(n, stmt->methodlist); + relation_close(relation, AccessShareLock); + ReleaseSysCache(tuple); +} + +/* + * Check names and typoid, make sure it is the same type + * names cane be any of formates: + * database.schema.type + * schema.type + * type + * + */ +static bool check_type_with_oid(List* names, Oid typoid) +{ + bool typeUnmatch = true; + if (list_length(names) == 1 + && get_typeoid(SchemaNameGetSchemaOid(NULL, true), strVal(linitial(names))) == typoid) { + typeUnmatch = false; + } else if (list_length(names) == 2 + && get_typeoid(SchemaNameGetSchemaOid(strVal(linitial(names)), true), strVal(llast(names))) == typoid) { + typeUnmatch = false; + } else if (list_length(names) == 3 + && strcmp(get_and_check_db_name(u_sess->proc_cxt.MyDatabaseId, true), strVal(linitial(names))) == 0 + && get_typeoid(SchemaNameGetSchemaOid(strVal(lsecond(names)), true), strVal(llast(names))) == typoid) { + typeUnmatch = false; + } + + return typeUnmatch; +} + +void DefineObjectTypeMethodSpec(CompositeTypeStmt* stmt, Oid typoid, char** mapOrder) +{ + ListCell* func = NULL; + bool ordermap = false; + bool issubtype = true; + List* typ = list_make1(makeString(stmt->typevar->relname)); + + if (stmt->typevar->schemaname) + typ = lcons(makeString(stmt->typevar->schemaname), typ); + + /* 1. Find methods of super type. Constructor method cannot be inheritate */ + if (NULL != stmt->supertype) { + /* Get Oid of super type */ + Oid supertypeoid = InvalidOid; + List* inhmethod = NULL; + Oid typeNamespace = RangeVarGetAndCheckCreationNamespace(stmt->supertype, NoLock, NULL, RELKIND_COMPOSITE_TYPE); + RangeVarAdjustRelationPersistence(stmt->supertype, typeNamespace); + supertypeoid = + GetSysCacheOid2(TYPENAMENSP, CStringGetDatum(stmt->supertype->relname), ObjectIdGetDatum(typeNamespace)); + if (!OidIsValid(supertypeoid)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("super type \"%s\" does not exist", stmt->supertype->relname))); + } + MergeObjectTypeMethod(stmt, supertypeoid); + inhmethod = list_concat(inhmethod, stmt->methodlist); + stmt->methodlist = inhmethod; + } else { + issubtype = false; + } + + /* 2. Build default constructor function with args */ + MakeDefaultParamConstructMethod(stmt, typoid); + + /* 3. build method recursively */ + foreach(func, stmt->methodlist) { + CreateFunctionStmt* submethod = (CreateFunctionStmt*)lfirst(func); + char* funcname = NULL; + FunctionParameter *firstparam = NULL; + FunctionParameter *self = makeNode(FunctionParameter); + self->name = pstrdup("self"); + self->argType = makeTypeNameFromNameList(typ); + self->mode = FUNC_PARAM_INOUT; + + submethod->replace = stmt->replace; + QualifiedNameGetCreationNamespace(submethod->funcname, &funcname); + + if (submethod->parameters != NULL) { + firstparam = (FunctionParameter *) linitial(submethod->parameters); + /* check self param type */ + if ((submethod->typfunckind != OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC) + && ((NULL != firstparam->name) && (strcmp(firstparam->name, "self") == 0)) + && check_type_with_oid(firstparam->argType->names, typoid)) + ereport(ERROR, (errmodule(MOD_COMMAND), errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("The self parameter type is not object type"))); + } + /* The first parameter of constructor function is self and check */ + if (submethod->typfunckind == OBJECTTYPE_CONSTRUCTOR_PROC) { + /* IF TYPE HAVE SCHEMA, constructor function SHOULD ALSO HAVE IT */ + if ((list_length(submethod->funcname) != 1) || strcmp(funcname, stmt->typevar->relname) != 0) + ereport(ERROR, (errmodule(MOD_COMMAND), errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("Constructor function Name %s Fault, " + "construct function name must be same with type", funcname))); + submethod->returnType = makeTypeNameFromOid(typoid, -1); + + if (firstparam == NULL || ((firstparam != NULL) + && ((NULL == firstparam->name) || (strcmp(firstparam->name, "self") != 0)))) { + self->mode = FUNC_PARAM_OUT; + submethod->parameters = lcons(self, submethod->parameters); + } else { + firstparam->mode = FUNC_PARAM_OUT; + } + if (stmt->typevar->schemaname) + submethod->funcname = lcons(makeString(stmt->typevar->schemaname), submethod->funcname); + } + + /* member first param is self */ + if (submethod->typfunckind == OBJECTTYPE_MEMBER_PROC) { + if ((firstparam == NULL) || ((firstparam != NULL) + && ((NULL == firstparam->name) || (strcmp(firstparam->name, "self") != 0)))) { + self->mode = FUNC_PARAM_INOUT; + submethod->parameters = lcons(self, submethod->parameters); + if (submethod->isProcedure) { + submethod->returnType = NULL; + } + } + } + /* static method do not have self param */ + if ((submethod->typfunckind == OBJECTTYPE_STATIC_PROC) && (firstparam != NULL) + && (NULL != firstparam->name) && (strcmp(firstparam->name, "self") == 0)) { + ereport(ERROR, (errmodule(MOD_COMMAND), errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("a static method cannot declare a parameter name SELF."))); + } + /* report error if already have map method */ + if ((submethod->typfunckind == OBJECTTYPE_ORDER_PROC + || submethod->typfunckind == OBJECTTYPE_MAP_PROC) && ordermap) { + ereport(ERROR, (errmodule(MOD_COMMAND), errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("An object type may have only 1 MAP or 1 ORDER method."))); + } + + /* Make sure the first parameter of map is self. Allow it to only have one parameter */ + if (submethod->typfunckind == OBJECTTYPE_MAP_PROC) { + if (firstparam == NULL) { + self->mode = FUNC_PARAM_IN; + submethod->parameters = lcons(self, submethod->parameters); + } else if (((NULL == firstparam->name) || (strcmp(firstparam->name, "self") != 0)) + || list_length(submethod->parameters) >1) { + ereport(ERROR, + (errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("MAP methods must be declared without any parameters other than (optional) SELF"))); + } + ordermap = true; + *mapOrder = funcname; + } + + if (submethod->typfunckind == OBJECTTYPE_ORDER_PROC) { + if (firstparam == NULL) + ereport(ERROR, + (errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("ORDER methods must be declared without any parameters other than (optional) SELF"))); + + if ((((NULL != firstparam->name) && (strcmp(firstparam->name, "self") == 0)) + && (list_length(submethod->parameters) !=2)) || + (((NULL == firstparam->name) || (strcmp(firstparam->name, "self") != 0)) + && (list_length(submethod->parameters) !=1))) + ereport(ERROR, + (errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("ORDER methods must be declared with 1 parameters in addition to (optional)SELF."))); + /* order parameter check, exclude self, parameter type must be object type */ + if ((NULL == firstparam->name) || (strcmp(firstparam->name, "self") != 0)) { + if (check_type_with_oid(firstparam->argType->names, typoid)) + ereport(ERROR, + (errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("The parameter type in an ORDER method must be the containing object type."))); + } else { + FunctionParameter *secondparam = (FunctionParameter *)lsecond(submethod->parameters); + if (check_type_with_oid(secondparam->argType->names, typoid)) + ereport(ERROR, + (errcode(ERRCODE_MAP_METHOD_PARAMETER), + errmsg("The parameter type in an ORDER method must be the containing object type."))); + } + + /* order method return type check, can only be number like types */ + if (submethod->returnType != NULL) { + Oid returntypeid = InvalidOid; + Type typtup = LookupTypeName(NULL, submethod->returnType, NULL); + if (!HeapTupleIsValid(typtup)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("ORDER methods must return an INTEGER."))); + returntypeid = typeTypeId(typtup); + if (returntypeid != INT2OID && returntypeid != INT4OID + && returntypeid != INT8OID && returntypeid != INT1OID) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("ORDER methods must return an INTEGER."))); + ReleaseSysCache(typtup); + } else { + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("ORDER methods must return an INTEGER."))); + } + + /* Order function with self parameter */ + if ((NULL != firstparam->name) && (strcmp(firstparam->name, "self") != 0)) { + self->mode = FUNC_PARAM_IN; + submethod->parameters = lcons(self, submethod->parameters); + } + ordermap = true; + *mapOrder = funcname; + } + + submethod->replace = true; + CreateFunction(submethod, NULL, InvalidOid, typoid); + } +} + +ObjectAddress DefineObjectTypeSpec(CompositeTypeStmt* stmt) +{ + Oid relid = InvalidOid; + Oid supertypeoid = InvalidOid; + Relation objectrel = NULL; + TupleDesc tupdesc = NULL; + Datum values[Natts_pg_object_type]; + bool isnull[Natts_pg_object_type]; + errno_t rc = EOK; + HeapTuple tup = NULL; + Oid typoid = InvalidOid; + Form_pg_class pgclasstuple = NULL; + HeapTuple classtuple = NULL; + HeapTuple oldobjecttuple = NULL; + char* mapOrder = NULL; + Oid mapid = InvalidOid; + Oid orderid = InvalidOid; + ObjectAddress reladdress; + + /* Check if system type with the same name already exists */ + typoid = GetSysCacheOid2(TYPENAMENSP, CStringGetDatum(stmt->typevar->relname), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE)); + if (OidIsValid(typoid)) { + ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type %s already exists", stmt->typevar->relname))); + } + + /* 1. Inherite super type's method */ + supertypeoid = SubTypeInheritBaseType(stmt); + /* 2. Build composite type */ + ObjectAddress address = DefineCompositeType(stmt->typevar, stmt->coldeflist, stmt->replace, &reladdress, true); + relid = reladdress.objectId; + + /* 3. Get Oid of composite type */ + classtuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(classtuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for relation %u", relid))); + } + pgclasstuple = (Form_pg_class)GETSTRUCT(classtuple); + typoid = pgclasstuple->reltype; + ReleaseSysCache(classtuple); + + /* 4. Create function declaration */ + DefineObjectTypeMethodSpec(stmt, typoid, &mapOrder); + + /* 5. Build dependencies for supertype and subtype */ + if (OidIsValid(supertypeoid)) { + ObjectAddress myself, referenced; + myself.classId = TypeRelationId; + myself.objectId = typoid; + myself.objectSubId = 0; + + /* dependency on namespace */ + referenced.classId = TypeRelationId; + referenced.objectId = supertypeoid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* 6. get object's map/order method */ + if (mapOrder != NULL) { + GetObjectTypeMapOrderMethod(typoid, mapOrder, &mapid, &orderid); + } + + /* 7. insert record to pg_object_type */ + oldobjecttuple = SearchSysCache1(OBJECTTYPE, ObjectIdGetDatum(typoid)); + objectrel = heap_open(ObjectTypeRelationId, RowExclusiveLock); + tupdesc = RelationGetDescr(objectrel); + + rc = memset_s(values, sizeof(values), 0, sizeof(values)); + securec_check(rc, "\0", "\0"); + rc = memset_s(isnull, sizeof(isnull), 0, sizeof(isnull)); + securec_check(rc, "\0", "\0"); + + values[Anum_pg_object_type_typoid-1] = ObjectIdGetDatum(typoid); + values[Anum_pg_object_type_supertypeoid-1] = ObjectIdGetDatum(supertypeoid); + values[Anum_pg_object_type_isfinal-1] = BoolGetDatum(false); + values[Anum_pg_object_type_isinstantiable-1] = BoolGetDatum(true); + values[Anum_pg_object_type_ispersistable-1] = BoolGetDatum(true); + values[Anum_pg_object_type_isbodydefined-1] = BoolGetDatum(false); + values[Anum_pg_object_type_mapmethod-1] = ObjectIdGetDatum(false); + values[Anum_pg_object_type_ordermethod-1] = ObjectIdGetDatum(false); + values[Anum_pg_object_type_objectoptions-1] = Int32GetDatum(0); + values[Anum_pg_object_type_typespecsrc-1] = CStringGetTextDatum(stmt->typespec); + isnull[Anum_pg_object_type_typebodydeclsrc-1] = true; + isnull[Anum_pg_object_type_objectextensions-1] = true; + + /* replace will delete type firstly, report an error if other object depend it */ + if (stmt->replace && HeapTupleIsValid(oldobjecttuple)) { + bool replaces[Natts_pg_object_type]; + replaces[Anum_pg_object_type_typoid-1] = true; + replaces[Anum_pg_object_type_supertypeoid-1] = true; + replaces[Anum_pg_object_type_isfinal-1] = true; + replaces[Anum_pg_object_type_isbodydefined-1] = true; + replaces[Anum_pg_object_type_mapmethod-1] = true; + replaces[Anum_pg_object_type_ordermethod-1] = true; + replaces[Anum_pg_object_type_typespecsrc-1] = true; + + tup = heap_modify_tuple(oldobjecttuple, tupdesc, values, isnull, replaces); + CatalogTupleUpdate(objectrel, &tup->t_self, tup); + ReleaseSysCache(oldobjecttuple); + } else { + tup = heap_form_tuple(tupdesc, values, isnull); + CatalogTupleInsert(objectrel, tup); + } + /* 8.update typetyptype of pg_type */ + UpdateObjectTypeTypeAttribute(typoid); + + heap_freetuple_ext(tup); + heap_close(objectrel, RowExclusiveLock); + return address; +} + +static void UpdateObjectTypeTypeAttribute(Oid typid) +{ + HeapTuple typetuple = NULL; + Relation typrel = NULL; + TupleDesc typtupdesc = NULL; + Datum values[Natts_pg_type]; + bool isnulls[Natts_pg_type]; + bool replace[Natts_pg_type]; + HeapTuple tup = NULL; + errno_t rc = EOK; + + typetuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid)); + if (!HeapTupleIsValid(typetuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type with OID %u does not exist.", typid))); + rc = memset_s(values, sizeof(values), 0, sizeof(values)); + securec_check(rc, "\0", "\0"); + rc = memset_s(isnulls, sizeof(isnulls), 0, sizeof(isnulls)); + securec_check(rc, "\0", "\0"); + rc = memset_s(replace, sizeof(replace), 0, sizeof(replace)); + securec_check(rc, "\0", "\0"); + typrel = heap_open(TypeRelationId, RowExclusiveLock); + typtupdesc = RelationGetDescr(typrel); + values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_ABSTRACT_OBJECT); + isnulls[Anum_pg_type_typtype - 1] = false; + replace[Anum_pg_type_typtype - 1] = true; + + tup = heap_modify_tuple(typetuple, typtupdesc, values, isnulls, replace); + CatalogTupleUpdate(typrel, &tup->t_self, tup); + ReleaseSysCache(typetuple); + heap_close(typrel, RowExclusiveLock); + heap_freetuple_ext(tup); +} + +void DefineObjectTypeBody(CompositeTypeStmt* stmt) +{ + Relation objectrel = NULL; + TupleDesc objectypetupdesc = NULL; + HeapTuple objecttuple = NULL; + Oid typeNamespace; + Form_pg_object_type objtypetup = NULL; + Oid typoid = InvalidOid; + Datum values[Natts_pg_object_type] = {0}; + bool isnull[Natts_pg_object_type] = {0}; + bool replaces[Natts_pg_object_type] = {0}; + ListCell* func = NULL; + HeapTuple tup = NULL; + HeapTuple proctup = NULL; + ScanKeyData entry; + Relation procrel = NULL; + TupleDesc tupledesc = NULL; + char *mapOrder = NULL; + Oid mapid = InvalidOid; + Oid orderid = InvalidOid; + bool issubtype = true; + + /* 1. Check if this type exists */ + typeNamespace = RangeVarGetAndCheckCreationNamespace(stmt->typevar, NoLock, NULL, RELKIND_COMPOSITE_TYPE); + typoid = + GetSysCacheOid2(TYPENAMENSP, CStringGetDatum(stmt->typevar->relname), ObjectIdGetDatum(typeNamespace)); + if (!OidIsValid(typoid)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("type \"%s\" not exists", stmt->typevar->relname))); + objecttuple = SearchSysCache1(OBJECTTYPE, ObjectIdGetDatum(typoid)); + objectrel = heap_open(ObjectTypeRelationId, RowExclusiveLock); + objectypetupdesc = RelationGetDescr(objectrel); + if (!HeapTupleIsValid(objecttuple)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("object type \"%s\" not exists", stmt->typevar->relname))); + objtypetup = (Form_pg_object_type)GETSTRUCT(objecttuple); + /* 2. Check if type body already created */ + if (objtypetup->isbodydefined && !(stmt->replace)) { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("type body \"%s\" already exists", stmt->typevar->relname))); + } + /* deal with self in type method */ + DealTypeMethodSelfParam(stmt, typoid, stmt->methodlist); + + /* Inherit methods from super type */ + if (OidIsValid(objtypetup->supertypeoid)) { + List *inhmethod = MergeObjectTypeMethod(stmt, objtypetup->supertypeoid); + DealTypeMethodSelfParam(stmt, typoid, inhmethod); + inhmethod = list_concat(inhmethod, stmt->methodlist); + stmt->methodlist = inhmethod; + } else { + issubtype = false; + } + /* 3. Recurisively build type method, if function doesnot exist while creating type body, report an error */ + ScanKeyInit(&entry, Anum_pg_proc_packageid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(typoid)); + procrel = heap_open(ProcedureRelationId, AccessShareLock); + + tupledesc = RelationGetDescr(procrel); + SysScanDesc scan = systable_beginscan(procrel, InvalidOid, false, NULL, 1, &entry); + while ((proctup = systable_getnext(scan)) != NULL) { + Form_pg_proc proc = (Form_pg_proc)GETSTRUCT(proctup); + bool isnull = true; + /* Find method type from pg_object */ + Oid result = HeapTupleGetOid(proctup); + Assert(result >= FirstBootstrapObjectId); + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(result), CharGetDatum(OBJECT_TYPE_PROC)); + if (!HeapTupleIsValid(objTuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("method with oid %u is not exist.", result))); + } + char proctype = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isnull)); + ReleaseSysCache(objTuple); + char* funcnameintype = NameStr(proc->proname); + /* Check method declared in type is also defined in type body */ + bool functiondeined = false; + + if (proctype == OBJECTTYPE_NULL_PROC || isnull) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object method \"%s\" type is invalid", NameStr(proc->proname)))); + if (proctype == OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC) { + continue; + } + /* Check typelist in type body */ + foreach(func, stmt->methodlist) { + CreateFunctionStmt* method = (CreateFunctionStmt*)lfirst(func); + char* funcname = NULL; + Oid bodyreturntypeid = InvalidOid; + bool ismemberprocedure = method->isProcedure && OBJECTTYPE_MEMBER_PROC; + + QualifiedNameGetCreationNamespace(method->funcname, &funcname); + /* comparete type declaration in type and type body */ + if (strcmp(funcname, funcnameintype) != 0) + continue; + /* Compare return type */ + if (!is_same_function(proctup, tupledesc, method)) + continue; + /* Check return type */ + if (method->returnType != NULL) { + Type typtup = LookupTypeName(NULL, method->returnType, NULL); + if (!HeapTupleIsValid(typtup)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" return type not exist", NameStr(proc->proname)))); + bodyreturntypeid = typeTypeId(typtup); + ReleaseSysCache(typtup); + } else { + bodyreturntypeid = get_typeoid(PG_CATALOG_NAMESPACE, "void"); + } + + if ((proc->prorettype != bodyreturntypeid) && (!ismemberprocedure)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define return type error", NameStr(proc->proname)))); + if (!functiondeined) { + functiondeined = true; + } + } + if (!functiondeined) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type declare method \"%s\" must define type body", NameStr(proc->proname)))); + } + systable_endscan(scan); + heap_close(procrel, NoLock); + + u_sess->plsql_cxt.isCreateTypeBody = true; + + /* Check typelist in type body */ + foreach(func, stmt->methodlist) { + CreateFunctionStmt* method = (CreateFunctionStmt*)lfirst(func); + method->replace = true; + if (method->typfunckind == OBJECTTYPE_ORDER_PROC || method->typfunckind == OBJECTTYPE_MAP_PROC) + QualifiedNameGetCreationNamespace(method->funcname, &mapOrder); + CreateFunction(method, NULL, InvalidOid, typoid); + } + /* Get map/order method of object */ + if (mapOrder != NULL) { + GetObjectTypeMapOrderMethod(typoid, mapOrder, &mapid, &orderid); + } + + /* + * 4. Update pg_object_type if type body already exists, otherwise create type body. + */ + if (!objtypetup->isbodydefined || stmt->replace) { + replaces[Anum_pg_object_type_isbodydefined-1] = true; + values[Anum_pg_object_type_isbodydefined-1] = BoolGetDatum(true); + isnull[Anum_pg_object_type_isbodydefined-1] = false; + + replaces[Anum_pg_object_type_mapmethod-1] = true; + values[Anum_pg_object_type_mapmethod-1] = ObjectIdGetDatum(mapid); + isnull[Anum_pg_object_type_mapmethod-1] = false; + + replaces[Anum_pg_object_type_ordermethod-1] = true; + values[Anum_pg_object_type_ordermethod-1] = ObjectIdGetDatum(orderid); + isnull[Anum_pg_object_type_ordermethod-1] = false; + + replaces[Anum_pg_object_type_typebodydeclsrc-1] = true; + values[Anum_pg_object_type_typebodydeclsrc-1] = CStringGetTextDatum(stmt->typebody); + isnull[Anum_pg_object_type_typebodydeclsrc-1] = false; + tup = heap_modify_tuple(objecttuple, objectypetupdesc, values, isnull, replaces); + CatalogTupleUpdate(objectrel, &tup->t_self, tup); + } + ReleaseSysCache(objecttuple); + heap_freetuple_ext(tup); + heap_close(objectrel, RowExclusiveLock); + u_sess->plsql_cxt.isCreateTypeBody = false; +} + +static void DealTypeMethodSelfParam(CompositeTypeStmt* stmt, Oid typoid, List* methodlist) +{ + ListCell* func = NULL; + List* typ = list_make1(makeString(stmt->typevar->relname)); + + if (stmt->typevar->schemaname) + typ = lcons(makeString(stmt->typevar->schemaname), typ); + + /* 3. build method recursively */ + foreach(func, methodlist) { + CreateFunctionStmt* submethod = (CreateFunctionStmt*)lfirst(func); + char* funcname = NULL; + FunctionParameter *firstparam = NULL; + FunctionParameter *self = makeNode(FunctionParameter); + self->name = pstrdup("self"); + self->argType = makeTypeNameFromNameList(typ); + self->mode = FUNC_PARAM_INOUT; + + submethod->replace = stmt->replace;/* replace method while replace type */ + QualifiedNameGetCreationNamespace(submethod->funcname, &funcname); + if (submethod->parameters != NULL) { + firstparam = (FunctionParameter*) linitial(submethod->parameters); + /* Check self parameter type */ + if (((NULL != firstparam->name) && (strcmp(firstparam->name, "self") == 0)) + && (submethod->typfunckind != OBJECTTYPE_CONSTRUCTOR_PROC)) { + if (firstparam->mode == FUNC_PARAM_INOUT) { + self->mode = FUNC_PARAM_INOUT; + submethod->parameters = list_delete_first(submethod->parameters); + submethod->parameters = lcons(self, submethod->parameters); + } + continue; + } + } + + /* + * The first parameter of construct function should be self, fix it if missing. + * Also, check function name and type name and build return value for object type. + */ + if (submethod->typfunckind == OBJECTTYPE_CONSTRUCTOR_PROC) { + submethod->returnType = makeTypeNameFromOid(typoid, -1); + if (firstparam == NULL || ((firstparam != NULL) && ((NULL != firstparam->name) + && (strcmp(firstparam->name, "self") != 0)))) { + self->mode = FUNC_PARAM_OUT; + submethod->parameters = lcons(self, submethod->parameters); + } else { + firstparam->mode = FUNC_PARAM_OUT; + } + if (stmt->typevar->schemaname) + submethod->funcname = lcons(makeString(stmt->typevar->schemaname), submethod->funcname); + } + + /* member, order method's first parameter is self, fix it if doesn't have one */ + if (submethod->typfunckind == OBJECTTYPE_MAP_PROC + || submethod->typfunckind == OBJECTTYPE_ORDER_PROC) { + self->mode = FUNC_PARAM_IN; + submethod->parameters = lcons(self, submethod->parameters); + } + if (submethod->typfunckind == OBJECTTYPE_MEMBER_PROC) { + self->mode = FUNC_PARAM_INOUT; + submethod->parameters = lcons(self, submethod->parameters); + if (submethod->isProcedure) { + submethod->returnType = NULL; + } + } + } +} + +static bool is_same_function(HeapTuple proctup, TupleDesc tupdesc, CreateFunctionStmt* method) +{ + bool isnull; + List *param = NULL; + char* language = NULL; + bool isWindowFunc = false; + bool isStrict = false; + bool isLeakProof = false; + char volatility; + ArrayType* proconfig = NULL; + float4 procost; + float4 prorows; + List* as_clause = NIL; + bool fenced = IS_SINGLE_NODE ? false:true; + bool shippable = false; + bool package = false; + bool isPipelined = false; + HeapTuple langtup; + Form_pg_proc proc = (Form_pg_proc)GETSTRUCT(proctup); + Form_pg_language lang; + Datum fencedintype; + Datum shippableintype; + bool finalintype = true; + bool security = false; + FunctionPartitionInfo* partInfo = NULL; + + /* Compare param list */ + param = object_type_get_function_arguments(proctup); + if (!isSameTypeMethodArgList(param, method->parameters, method->funcname)) { + return false; + } + + /* Compare option */ + compute_attributes_sql_style((const List*)method->options, &as_clause, &language, &isWindowFunc, &volatility, + &isStrict, &security, &isLeakProof, &proconfig, &procost, &prorows, + &fenced, &shippable, &package, &isPipelined, &partInfo); + + /* Validate language */ + langtup = SearchSysCache1(LANGOID, ObjectIdGetDatum(proc->prolang)); + if (!HeapTupleIsValid(langtup)) + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for language %u", proc->prolang))); + lang = (Form_pg_language)GETSTRUCT(langtup); + if (strcmp(NameStr(lang->lanname), language) != 0) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define language error", NameStr(proc->proname)))); + ReleaseSysCache(langtup); + + /* Validate isWindowFunc */ + if (isWindowFunc != proc->proiswindow) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define Iswindow option error", NameStr(proc->proname)))); + /* Validate proisstrict */ + if (isStrict != proc->proisstrict) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define strict option error", NameStr(proc->proname)))); + /* Validate isLeakProof */ + if (isLeakProof != proc->proleakproof) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define leakproof option error", NameStr(proc->proname)))); + /* Validate fenced */ + fencedintype = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_fenced, &isnull); + if (!isnull && (shippable != DatumGetBool(fencedintype))) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define fence option error", NameStr(proc->proname)))); + /* Validate shippable */ + shippableintype = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_shippable, &isnull); + if (!isnull && (shippable != DatumGetBool(shippableintype))) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define shippable option error", NameStr(proc->proname)))); + /* Validate final in type */ + Oid result = HeapTupleGetOid(proctup); + /* Find isfinal from pg_object */ + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(result), CharGetDatum(OBJECT_TYPE_PROC)); + if (HeapTupleIsValid(objTuple)) { + finalintype = GET_ISFINAL(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isnull)); + ReleaseSysCache(objTuple); + } + if (!isnull && (finalintype != method->isfinal)) + ereport(ERROR, (errcode(ERRCODE_OBJECT_TYPE_METHOD_DEFINE_ERROR), + errmsg("type body method \"%s\" define final option error", NameStr(proc->proname)))); + return true; +} + +static void GetSuperTypeAttribute(CompositeTypeStmt* stmt, Oid supertypeoid) +{ + HeapTuple supertuple = NULL; + Form_pg_type supertypeform = NULL; + /* 1. find and validate supertype info in pg_type. */ + supertuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(supertypeoid)); + if (!HeapTupleIsValid(supertuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("super object type with OID %u does not exist", supertypeoid))); + supertypeform = (Form_pg_type)GETSTRUCT(supertuple); + /* raise an error if not object type */ + if (!OidIsValid(supertypeform->typrelid) || supertypeform->typtype != TYPTYPE_ABSTRACT_OBJECT) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("super object type with OID %u is not object type", supertypeoid))); + + stmt->coldeflist = MergeObjectTypeAttributes(stmt->coldeflist, supertypeoid, supertypeform->typtypmod); + ReleaseSysCache(supertuple); +} + +static List* MergeObjectTypeAttributes(List* schema, Oid supertypeid, int32 typmod) +{ + List* inhSchema = NIL; + TupleDesc tupledesc; + AttrNumber parant_attno; + + tupledesc = lookup_rowtype_tupdesc(supertypeid, typmod); + + for (parant_attno = 1; parant_attno <= tupledesc->natts; parant_attno++) { + Form_pg_attribute attribute = &tupledesc->attrs[parant_attno - 1]; + char* attributeName = NameStr(attribute->attname); + ColumnDef* def = NULL; + + /* Ignore dropped columns in the parent */ + if (attribute->attisdropped) + continue; + + /* Now, create a new inherited column */ + def = makeNode(ColumnDef); + def->colname = pstrdup(attributeName); + def->typname = makeTypeNameFromOid(attribute->atttypid, attribute->atttypmod); + def->inhcount = 1; + def->is_local = false; + def->is_not_null = attribute->attnotnull; + def->is_from_type = false; + def->storage = attribute->attstorage; + def->kvtype = attribute->attkvtype; + def->cmprs_mode = attribute->attcmprmode; + def->raw_default = NULL; + def->generatedCol = '\0'; + def->cooked_default = NULL; + def->collClause = NULL; + def->collOid = attribute->attcollation; + def->constraints = NIL; + inhSchema = lappend(inhSchema, def); + } + + inhSchema = list_concat(inhSchema, schema); + schema = inhSchema; + ReleaseTupleDesc(tupledesc); + + return schema; +} + +static List* GetSuperTypeMethod(Oid supertypeoid) +{ + List* inhmethod = NIL; + Relation procrel = NULL; + TupleDesc tupledesc = NULL; + HeapTuple proctup; + ScanKeyData entry; + ScanKeyInit(&entry, Anum_pg_proc_packageid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(supertypeoid)); + procrel = heap_open(ProcedureRelationId, AccessShareLock); + + tupledesc = RelationGetDescr(procrel); + SysScanDesc scan = systable_beginscan(procrel, InvalidOid, false, NULL, 1, &entry); + while ((proctup = systable_getnext(scan)) != NULL) { + Form_pg_proc proc = (Form_pg_proc)GETSTRUCT(proctup); + bool isnull = true; + /* Find method type from pg_object */ + Oid result = HeapTupleGetOid(proctup); + Assert(result >= FirstBootstrapObjectId); + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(result), CharGetDatum(OBJECT_TYPE_PROC)); + if (!HeapTupleIsValid(objTuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("method with oid %u is not exist.", result))); + } + Datum object_options = SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isnull); + char proctype = GET_PROTYPEKIND(object_options); + bool isfinal = GET_ISFINAL(object_options); + ReleaseSysCache(objTuple); + if (proctype == OBJECTTYPE_NULL_PROC || isnull) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("super object method \"%s\" type is invalid. ", NameStr(proc->proname)))); + if (proctype == OBJECTTYPE_MEMBER_PROC || proctype == OBJECTTYPE_STATIC_PROC + || proctype == OBJECTTYPE_MAP_PROC || proctype == OBJECTTYPE_ORDER_PROC) { + char prokind = CharGetDatum(heap_getattr(proctup, Anum_pg_proc_prokind, tupledesc, &isnull)); + char* procSource = TextDatumGetCString(heap_getattr(proctup, Anum_pg_proc_prosrc, tupledesc, &isnull)); + + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->inputHeaderSrc = NULL; + n->funcname = list_make1(makeString(pstrdup(NameStr(proc->proname)))); + n->parameters = object_type_get_function_arguments(proctup); + if (proc->prorettype != supertypeoid) + n->returnType = makeTypeName(get_typename(proc->prorettype)); + n->typfunckind = proctype; + n->isfinal = isfinal; + n->options = lappend(n->options, makeDefElem("as", (Node*)list_make1(makeString(procSource)))); + n->options = lappend(n->options, makeDefElem("language", (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = prokind; + inhmethod = lappend(inhmethod, n); + } + } + systable_endscan(scan); + heap_close(procrel, NoLock); + return inhmethod; +} + +static List* MergeObjectTypeMethod(CompositeTypeStmt* stmt, Oid supertypeoid) +{ + ListCell* submethodcell = NULL; + bool supertypemap = false; + List* inhmethod = NIL; + + /* 1. Get supertype accroding to supertype oid */ + inhmethod = GetSuperTypeMethod(supertypeoid); + + foreach (submethodcell, stmt->methodlist) { + CreateFunctionStmt* submethod = (CreateFunctionStmt*)lfirst(submethodcell); + char* subfuncname = NULL; + bool issame = false; + ListCell* cell = NULL; + QualifiedNameGetCreationNamespace(submethod->funcname, &subfuncname); + + if (submethod->typfunckind == OBJECTTYPE_ORDER_PROC) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("UNDER object order method \"%s\" can not defined", subfuncname))); + } + + cell = list_head(inhmethod); + + /* recursive supertype */ + while (cell != NULL) { + CreateFunctionStmt* parentdef = (CreateFunctionStmt*)lfirst(cell); + char* parentfuncname = NULL; + + cell = lnext(cell); + QualifiedNameGetCreationNamespace(parentdef->funcname, &parentfuncname); + /* subtype override supertype's map method */ + if (parentdef->typfunckind == OBJECTTYPE_MAP_PROC) { + supertypemap = true; + } + if (strcmp(subfuncname, parentfuncname) == 0) { + /* Same funcname and same args */ + if ((submethod->typfunckind == OBJECTTYPE_MEMBER_PROC + || submethod->typfunckind == OBJECTTYPE_STATIC_PROC) && parentdef->isfinal) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("super object method \"%s\" is FINAL. ", parentfuncname))); + } + if (submethod->typfunckind != parentdef->typfunckind) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object method \"%s\" type is not same. ", parentfuncname))); + } + + if (isSameTypeMethodArgList(parentdef->parameters, submethod->parameters, submethod->funcname)) { + /* delete supertype method from method list */ + list_delete(inhmethod, submethod); + issame = true; + } + if (submethod->typfunckind == OBJECTTYPE_MAP_PROC) { + list_delete(inhmethod, submethod); + } + } + + if (parentdef->parameters != NULL) { + FunctionParameter *firstparam = (FunctionParameter*)linitial(parentdef->parameters); + + if ((NULL != firstparam->name) + && (strcmp(firstparam->name, "self") == 0) && (firstparam->mode != FUNC_PARAM_INOUT)) + parentdef->parameters = list_delete_first(parentdef->parameters); + } + } + + if (submethod->typfunckind == OBJECTTYPE_MAP_PROC && !supertypemap) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("super type map method not exists, sub type cannot define."))); + } + return inhmethod; +} + +static bool isSameTypeMethodArgList(List* argList1, List* argList2, List* funcname) +{ + ListCell* cell = NULL; + int length1 = list_length(argList1); + int length2 = list_length(argList2); + bool enableOutparamOverride = enable_out_param_override(); + bool isSameName = true; + FunctionParameter** arr1 = (FunctionParameter**)palloc(length1 *sizeof(FunctionParameter*)); + FunctionParameter** arr2 = (FunctionParameter**)palloc(length2 *sizeof(FunctionParameter*)); + FunctionParameter* fp1 = NULL; + FunctionParameter* fp2 = NULL; + int inArgNum1 = 0; + int inArgNum2 = 0; + int inLoc1 = 0; + int inLoc2 = 0; + int length = 0; + + foreach(cell, argList1) { + arr1[length] = (FunctionParameter*)lfirst(cell); + /* Do not compare implicit parameter self */ + if ((length ==0) && ((NULL != arr1[length]->name) && (strcmp(arr1[length]->name, "self") == 0))) + continue; + if (arr1[length]->mode != FUNC_PARAM_OUT) { + inArgNum1++; + } + length = length + 1; + } + length1 = length; + length = 0; + + foreach(cell, argList2) { + arr2[length] = (FunctionParameter*)lfirst(cell); + /* Do not compare implicit parameter self */ + if ((length ==0) && ((NULL != arr2[length]->name) && (strcmp(arr2[length]->name, "self") == 0))) + continue; + if (arr2[length]->mode != FUNC_PARAM_OUT) { + inArgNum2++; + } + length = length + 1; + } + length2 = length; + if (!enableOutparamOverride) { + if (inArgNum1 != inArgNum2) { + return false; + } else if (inArgNum1 == inArgNum2 && length1 != length2) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmodule(MOD_PLSQL), + errmsg("can not override out param:%s", + NameListToString(funcname)))); + } + } else { + if (length1 != length2) { + return false; + } + } + + for (int i = 0, j = 0; i < length1 || j < length2; i++, j++) { + if (!enableOutparamOverride) { + fp1 = arr1[inLoc1]; + fp2 = arr2[inLoc2]; + } else { + fp1 = arr1[i]; + fp2 = arr2[j]; + } + TypeName* t1 = fp1->argType; + TypeName* t2 = fp2->argType; + if (!enableOutparamOverride) { + if (fp1->mode == FUNC_PARAM_OUT && fp2->mode == FUNC_PARAM_OUT) { + continue; + } else if (fp1->mode != FUNC_PARAM_OUT && fp2->mode == FUNC_PARAM_OUT) { + inLoc1++; + continue; + } else if (fp1->mode == FUNC_PARAM_OUT && fp2->mode != FUNC_PARAM_OUT) { + inLoc2++; + continue; + } else { + inLoc1++; + inLoc2++; + } + } + Oid toid1 = InvalidOid; + Oid toid2 = InvalidOid; + Type typtup1; + Type typtup2; + typtup1 = LookupTypeName(NULL, t1, NULL); + typtup2 = LookupTypeName(NULL, t2, NULL); + bool isTableOf1 = false; + bool isTableOf2 = false; + Oid baseOid1 = InvalidOid; + Oid baseOid2 = InvalidOid; + if (HeapTupleIsValid(typtup1)) { + toid1 = typeTypeId(typtup1); + if (((Form_pg_type)GETSTRUCT(typtup1))->typtype == TYPTYPE_TABLEOF) { + baseOid1 = ((Form_pg_type)GETSTRUCT(typtup1))->typelem; + isTableOf1 = true; + } + ReleaseSysCache(typtup1); + } + + if (HeapTupleIsValid(typtup2)) { + toid2 = typeTypeId(typtup2); + if (((Form_pg_type)GETSTRUCT(typtup2))->typtype == TYPTYPE_TABLEOF) { + baseOid2 = ((Form_pg_type)GETSTRUCT(typtup2))->typelem; + isTableOf2 = true; + } + ReleaseSysCache(typtup2); + } + + /* If table of type should check its base type */ + if (isTableOf1 == isTableOf2 && isTableOf1) { + if (baseOid1 != baseOid2 || fp1->mode != fp2->mode) { + pfree_ext(arr1); + pfree_ext(arr2); + return false; + } + } else if (toid1 != toid2 || fp1->mode != fp2->mode) { + pfree_ext(arr1); + pfree_ext(arr2); + return false; + } + if (fp1->name == NULL || fp2->name == NULL) { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("type is not exists."))); + } + if (strcmp(fp1->name, fp2->name) != 0) { + isSameName = false; + } + } + pfree_ext(arr1); + pfree_ext(arr2); + return true; +} + +static Oid SubTypeInheritBaseType(CompositeTypeStmt* stmt) +{ + Oid supertypeoid = InvalidOid; + Oid typeNamespace = InvalidOid; + HeapTuple supertuple = NULL; + Form_pg_object_type supertypeform = NULL; + + if (stmt->issubtype) { + if (NULL == stmt->supertype) + return InvalidOid; + + /* 1.Check if supertype exists */ + typeNamespace = RangeVarGetAndCheckCreationNamespace(stmt->supertype, NoLock, NULL, RELKIND_COMPOSITE_TYPE); + RangeVarAdjustRelationPersistence(stmt->supertype, typeNamespace); + supertypeoid = + GetSysCacheOid2(TYPENAMENSP, CStringGetDatum(stmt->supertype->relname), ObjectIdGetDatum(typeNamespace)); + if (!OidIsValid(supertypeoid)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("SUPER TYPE \"%s\" not exists.", stmt->supertype->relname))); + } + + /* 2. Is supertype allow to be inherited */ + supertuple = SearchSysCache1(OBJECTTYPE, ObjectIdGetDatum(supertypeoid)); + if (!HeapTupleIsValid(supertuple)) + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object type with oid %u does not exist.", supertypeoid))); + supertypeform = (Form_pg_object_type)GETSTRUCT(supertuple); + if (supertypeform->isfinal) + ereport(ERROR, (errcode(ERRCODE_CREATE_SUBTYPE_UNDER_FINAL), + errmsg("attempting to create a subtype UNDER a FINAL type"))); + /* 3. subtype inherite supertype's parameter */ + GetSuperTypeAttribute(stmt, supertypeoid); + ReleaseSysCache(supertuple); + } + return supertypeoid; +} + +static List* object_type_get_function_arguments(HeapTuple proctup) +{ + int numargs; + Oid* argtypes = NULL; + char** argnames = NULL; + char* argmodes = NULL; + int i; + List* paramlist = NULL; + Form_pg_proc proc = (Form_pg_proc)GETSTRUCT(proctup); + numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes); + + for (i = 0; i < numargs; i++) { + FunctionParameter* n = makeNode(FunctionParameter); + n->argType = makeTypeNameFromNameList(get_typename_with_schema(argtypes[i])); + n->name = argnames ? argnames[i] : NULL; + n->mode = FUNC_PARAM_IN; + n->defexpr = NULL; + if (argmodes != NULL) { + switch (argmodes[i]) { + case PROARGMODE_IN: + n->mode = FUNC_PARAM_IN; + break; + case PROARGMODE_OUT: + n->mode = FUNC_PARAM_OUT; + break; + case PROARGMODE_INOUT: + n->mode = FUNC_PARAM_INOUT; + break; + case PROARGMODE_VARIADIC: + n->mode = FUNC_PARAM_VARIADIC; + break; + case PROARGMODE_TABLE: + n->mode = FUNC_PARAM_TABLE; + break; + default: + ereport(ERROR, (errcode(ERRCODE_CREATE_SUBTYPE_UNDER_FINAL), + errmsg("object function \"%s\" argument \"%s\" mod error.", NameStr(proc->proname), n->name))); + } + } + paramlist = lappend(paramlist, n); + } + return paramlist; +} + +static List* ConstructQualifiedName(char* catalogname, char* schemaname, char* relname) +{ + List* qualifiedName = NIL; + if (catalogname) { + qualifiedName = list_make1(makeString(catalogname)); + if (schemaname) { + if (relname) { + qualifiedName = lappend(qualifiedName, makeString(relname)); + } + } else { + if (relname) { + qualifiedName = lappend(qualifiedName, makeString(relname)); + } + } + } else { + if (schemaname) { + qualifiedName = list_make1(makeString(schemaname)); + if (relname) { + qualifiedName = lappend(qualifiedName, makeString(relname)); + } + } else { + if (relname) { + qualifiedName = lappend(qualifiedName, makeString(relname)); + } + } + } + return qualifiedName; +} /* * AlterDomainDefault * @@ -3375,7 +4773,8 @@ ObjectAddress RenameType(RenameStmt* stmt) * free-standing composite type, and not a table's rowtype. We want people * to use ALTER TABLE not ALTER TYPE for that case. */ - if (typTup->typtype == TYPTYPE_COMPOSITE && get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE) + if (((typTup->typtype == TYPTYPE_COMPOSITE) || (typTup->typtype == TYPTYPE_ABSTRACT_OBJECT)) + && (get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("%s is a table's row type", format_type_be(typeOid)), @@ -3414,7 +4813,7 @@ ObjectAddress RenameType(RenameStmt* stmt) * If type is composite we need to rename associated pg_class entry too. * RenameRelationInternal will call RenameTypeInternal automatically. */ - if (typTup->typtype == TYPTYPE_COMPOSITE) + if ((typTup->typtype == TYPTYPE_COMPOSITE) || (typTup->typtype == TYPTYPE_ABSTRACT_OBJECT)) RenameRelationInternal(typTup->typrelid, newTypeName); else RenameTypeInternal(typeOid, newTypeName, typTup->typnamespace); @@ -3473,7 +4872,8 @@ ObjectAddress AlterTypeOwner(List* names, Oid newOwnerId, ObjectType objecttype, * free-standing composite type, and not a table's rowtype. We want people * to use ALTER TABLE not ALTER TYPE for that case. */ - if (typTup->typtype == TYPTYPE_COMPOSITE && get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE) + if (((typTup->typtype == TYPTYPE_COMPOSITE) || (typTup->typtype == TYPTYPE_ABSTRACT_OBJECT)) + && get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("%s is a table's row type", format_type_be(typeOid)), @@ -3525,9 +4925,9 @@ ObjectAddress AlterTypeOwner(List* names, Oid newOwnerId, ObjectType objecttype, * up the pg_class entry properly. That will call back to * AlterTypeOwnerInternal to take care of the pg_type entry(s). */ - if (typTup->typtype == TYPTYPE_COMPOSITE) + if ((typTup->typtype == TYPTYPE_COMPOSITE) || (typTup->typtype == TYPTYPE_ABSTRACT_OBJECT)) { ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock); - else { + } else { /* * We can just apply the modification directly. * @@ -3831,9 +5231,11 @@ Oid AlterTypeNamespaceInternal( /* Detect whether type is a composite type (but not a table rowtype) */ isCompositeType = - (typform->typtype == TYPTYPE_COMPOSITE && get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE); + ((typform->typtype == TYPTYPE_COMPOSITE || typform->typtype == TYPTYPE_ABSTRACT_OBJECT) + && get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE); /* Enforce not-table-type if requested */ - if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType && errorOnTableType) + if ((typform->typtype == TYPTYPE_COMPOSITE || typform->typtype == TYPTYPE_ABSTRACT_OBJECT) + && !isCompositeType && errorOnTableType) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("%s is a table's row type", format_type_be(typeOid)), @@ -3881,7 +5283,8 @@ Oid AlterTypeNamespaceInternal( * Update dependency on schema, if any --- a table rowtype has not got * one, and neither does an implicit array. */ - if ((isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) && !isImplicitArray) + if ((isCompositeType || (typform->typtype != TYPTYPE_COMPOSITE) || (typform->typtype == TYPTYPE_ABSTRACT_OBJECT)) + && !isImplicitArray) if (changeDependencyFor(TypeRelationId, typeOid, NamespaceRelationId, oldNspOid, nspOid) != 1) ereport(ERROR, (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), diff --git a/contrib/dolphin/plugin_optimizer/util/clauses.cpp b/contrib/dolphin/plugin_optimizer/util/clauses.cpp index beedec7b85132fb117688b8200bdbaf3ce89a480..ab7096c9f6e7c27554a7b7081ece847a3157ff85 100644 --- a/contrib/dolphin/plugin_optimizer/util/clauses.cpp +++ b/contrib/dolphin/plugin_optimizer/util/clauses.cpp @@ -1194,6 +1194,9 @@ static bool contain_specified_functions_walker(Node* node, check_function_contex } else if (IsA(node, Query) && context->deep) { /* Recurse into subselects */ return query_tree_walker((Query*)node, (bool (*)())contain_specified_functions_walker, context, 0); + } else if (IsA(node, UserSetElem)) { + /* UserSetElem is volatile */ + return context->checktype == CONTAIN_VOLATILE_FUNTION; } return expression_tree_walker(node, (bool (*)())contain_specified_functions_walker, context); } @@ -3409,6 +3412,22 @@ Node* eval_const_expressions_mutator(Node* node, eval_const_expressions_context* return eval_const_expressions_mutator((Node*)phv->phexpr, context); } break; + case T_TypeCast: + { + TypeCast *tc = (TypeCast*)node; + Node *defResNode = tc->arg; + Oid sourceTypeId = exprType(defResNode); + Oid ptype = tc->typname->typeOid; + if (can_coerce_type(1, &sourceTypeId, &ptype, COERCION_IMPLICIT)) { + return coerce_type(NULL, defResNode, sourceTypeId, ptype, -1, + COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1); + } else { + ereport(ERROR, + (errcode(ERRCODE_CANNOT_COERCE), errmsg("could not convert type %s to %s", + format_type_be(sourceTypeId), format_type_be(ptype)))); + } + break; + } default: break; } @@ -5154,8 +5173,10 @@ Query* inline_set_returning_function(PlannerInfo* root, RangeTblEntry* rte) * returning is a single composite column which is not what we need. */ if (!check_sql_fn_retval(func_oid, fexpr->funcresulttype, querytree_list, &modifyTargetList, NULL) && - (get_typtype(fexpr->funcresulttype) == TYPTYPE_COMPOSITE || fexpr->funcresulttype == RECORDOID)) + (get_typtype(fexpr->funcresulttype) == TYPTYPE_COMPOSITE + || get_typtype(fexpr->funcresulttype) == TYPTYPE_ABSTRACT_OBJECT || fexpr->funcresulttype == RECORDOID)) { goto fail; /* reject not-whole-tuple-result cases */ + } /* * If we had to modify the tlist to make it match, and the statement is diff --git a/contrib/dolphin/plugin_optimizer/util/plancat.cpp b/contrib/dolphin/plugin_optimizer/util/plancat.cpp index 8c3ce4c1f7f4ab3659106d45c1169f6218403949..f4cb76ecf178ff652a65e2e18749ea3453f7a516 100644 --- a/contrib/dolphin/plugin_optimizer/util/plancat.cpp +++ b/contrib/dolphin/plugin_optimizer/util/plancat.cpp @@ -734,6 +734,16 @@ void get_relation_info(PlannerInfo* root, Oid relationObjectId, bool inhparent, /* Grab the fdwroutine info using the relcache, while we have it */ if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE || relation->rd_rel->relkind == RELKIND_STREAM) { + /* Check if the access to foreign tables is restricted*/ + if (unlikely(RESTRICT_NONSYSTEM_RELATION_KIND_FOREIGN_TABLE)) { + /* There can not be built-in FDW handler */ + Assert(RelationGetRelid(relation) >= FirstNormalObjectId); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("Access to non-system forign table is restricted."), + errcause("Access to non-system forign table is restricted."), + erraction("Check the value of restrict_nonsystem_relation_kind."))); + } rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation)); rel->fdwroutine = GetFdwRoutineForRelation(relation, true); } else { diff --git a/contrib/dolphin/plugin_parser/analyze.cpp b/contrib/dolphin/plugin_parser/analyze.cpp index 8a3b7ca608a7c483095ee70f36f0cab80246dc1c..3c03860a9e1241c73a61be33fb090bccd29eeeff 100644 --- a/contrib/dolphin/plugin_parser/analyze.cpp +++ b/contrib/dolphin/plugin_parser/analyze.cpp @@ -35,6 +35,7 @@ #include "catalog/pgxc_class.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "commands/typecmds.h" #include "utils/fmgroids.h" #include "utils/snapmgr.h" #endif @@ -507,6 +508,12 @@ Query* transformVariableAlterEventStmt(ParseState* pstate, AlterEventStmt* stmt) static Query* TransformCompositeTypeStmt(ParseState* pstate, CompositeTypeStmt* stmt) { Query* result = makeNode(Query); + /* object type handle replace by itself */ + if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE || stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE_BODY) { + result->utilityStmt = (Node*)stmt; + result->commandType = CMD_UTILITY; + return result; + } result->commandType = CMD_UTILITY; Oid old_type_oid = InvalidOid; diff --git a/contrib/dolphin/plugin_parser/gram.y b/contrib/dolphin/plugin_parser/gram.y index 3b82786cfe058fd8b4ce702849fd6e8b8d94dd52..80afad167c35d9fdbb64b47603690aebcd86bcd1 100644 --- a/contrib/dolphin/plugin_parser/gram.y +++ b/contrib/dolphin/plugin_parser/gram.y @@ -61,12 +61,15 @@ #include "catalog/index.h" #include "catalog/namespace.h" #include "catalog/pg_proc.h" +#include "catalog/pg_type.h" #include "catalog/gs_package.h" #include "catalog/pg_am.h" +#include "catalog/pg_object.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type_fn.h" #include "commands/defrem.h" #include "commands/trigger.h" +#include "commands/typecmds.h" #ifdef ENABLE_MULTIPLE_NODES #include "distribute_core.h" #endif @@ -689,7 +692,7 @@ static bool GreaterThanHour (List* int_type); CreateResourcePoolStmt AlterResourcePoolStmt DropResourcePoolStmt CreateWorkloadGroupStmt AlterWorkloadGroupStmt DropWorkloadGroupStmt CreateAppWorkloadGroupMappingStmt AlterAppWorkloadGroupMappingStmt DropAppWorkloadGroupMappingStmt - MergeStmt PurgeStmt CreateMatViewStmt RefreshMatViewStmt CreateAmStmt + MergeStmt PurgeStmt CreateMatViewStmt RefreshMatViewStmt CreateMatViewLogStmt DropMatViewLogStmt CreateAmStmt CreateWeakPasswordDictionaryStmt DropWeakPasswordDictionaryStmt AlterGlobalConfigStmt DropGlobalConfigStmt CreatePublicationStmt AlterPublicationStmt @@ -711,6 +714,13 @@ static bool GreaterThanHour (List* int_type); %type features_clause hyperparameter_name_value_list target_clause with_hyperparameters_clause /* */ +/* oracle object type */ +%type type_body_subprogram Method_specList object_func_args_with_defaults object_proc_args method_decl_in_type_list +%type element_spec element_decl_in_type subprogram_decl_in_type constructor_decl_in_type map_order_decl_in_type +%type final_clause inheritance_clause + + + %type select_no_parens select_no_parens_without_withclause select_with_parens select_clause simple_select values_clause insert_empty_values @@ -837,7 +847,7 @@ static bool GreaterThanHour (List* int_type); any_operator expr_list attrs callfunc_args callfunc_args_or_empty dolphin_attrs rename_user_clause rename_list target_list insert_column_list set_target_list rename_clause_list rename_clause set_clause_list set_clause multiple_set_clause - ctext_expr_list ctext_row def_list tsconf_def_list indirection opt_indirection dolphin_indirection opt_dolphin_indirection + ctext_expr_list ctext_row def_list tsconf_def_list indirection opt_indirection dolphin_indirection case_sensitive_indirection opt_dolphin_indirection reloption_list tblspc_option_list cfoption_list group_clause TriggerFuncArgs select_limit opt_select_limit opt_delete_limit opclass_item_list opclass_drop_list opclass_purpose opt_opfamily transaction_mode_list_or_empty @@ -874,7 +884,7 @@ static bool GreaterThanHour (List* int_type); %type OptTempTableName %type into_clause create_as_target create_as_target_dolphin create_mv_target opt_into_clause -%type createfunc_opt_item createproc_opt_item common_func_opt_item dostmt_opt_item +%type createfunc_opt_item createproc_opt_item common_func_opt_item alter_function_common_func_opt_item create_function_common_func_opt_item dostmt_opt_item %type func_arg func_arg_with_default table_func_column %type arg_class %type func_return func_type @@ -948,7 +958,7 @@ static bool GreaterThanHour (List* int_type); %type columnDef columnOptions columnDefForTableElement %type def_elem tsconf_def_elem reloption_elem tblspc_option_elem old_aggr_elem cfoption_elem %type def_arg columnElem where_clause where_or_current_clause start_with_expr connect_by_expr - a_expr a_expr_without_sconst b_expr c_expr c_expr_noparen c_expr_without_sconst AexprConst AexprConst_without_Sconst indirection_el siblings_clause + a_expr a_expr_without_interval a_expr_without_sconst b_expr c_expr c_expr_noparen c_expr_without_sconst AexprConst AexprConst_without_Sconst indirection_el case_sensitive_indirection_el siblings_clause columnref in_expr in_sum_expr start_with_clause having_clause func_table array_expr set_ident_expr set_expr set_expr_extension ExclusionWhereClause fulltext_match_params func_table_with_table %type ExclusionConstraintList ExclusionConstraintElem @@ -1010,7 +1020,7 @@ static bool GreaterThanHour (List* int_type); %type Sconst comment_text notify_payload DolphinColColId %type RoleId RoleIdWithOutCurrentUser TypeOwner opt_granted_by opt_boolean_or_string ColId_or_Sconst Dolphin_ColId_or_Sconst definer_user definer_expression UserId %type var_list guc_value_extension_list schema_var_list -%type ColId ColLabel var_name dolphin_var_name schema_var type_function_name param_name charset_collate_name opt_password opt_replace show_index_schema_opt ColIdForTableElement PrivilegeColId +%type ColId ColLabel CaseSensitiveColLabel var_name dolphin_var_name schema_var type_function_name param_name charset_collate_name opt_password opt_replace show_index_schema_opt ColIdForTableElement PrivilegeColId %type var_value zone_value %type DolphinColId DolphinColLabel dolphin_indirection_el /* for keyword which could be a column/table alias name, use alias_name_xxxx*/ @@ -1175,6 +1185,9 @@ static bool GreaterThanHour (List* int_type); %type condition_number %type condition_information statement_information +/* MATVIEW */ +%type build_deferred + %type on_table opt_engine engine_option opt_engine_without_empty opt_compression opt_compression_without_empty set_compress_type opt_row_format row_format_option %type into_empty opt_temporary opt_values_in replace_empty %type compression_args @@ -1222,7 +1235,7 @@ static bool GreaterThanHour (List* int_type); ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUDIT AUTHID AUTHORIZATION AUTOEXTEND AUTOEXTEND_SIZE AUTOMAPPED AUTO_INCREMENT AVG_ROW_LENGTH AGAINST BACKWARD BARRIER BEFORE BEGIN_NON_ANOYBLOCK BEGIN_P BETWEEN BIGINT BINARY BINARY_P BINARY_DOUBLE BINARY_DOUBLE_INF BINARY_DOUBLE_NAN BINARY_INTEGER BIT BLANKS - BLOB_P BLOCKCHAIN BODY_P BOGUS BOOLEAN_P BOTH BUCKETCNT BY BYTEAWITHOUTORDER BYTEAWITHOUTORDERWITHEQUAL + BLOB_P BLOCKCHAIN BODY_P BOGUS BOOLEAN_P BOTH BUCKETCNT BUILD BY BYTEAWITHOUTORDER BYTEAWITHOUTORDERWITHEQUAL CACHE CALL CALLED CANCELABLE CASCADE CASCADED CASE CAST CATALOG_P CATALOG_NAME CHAIN CHANGE CHANNEL CHAR_P CHARACTER CHARACTERISTICS CHARACTERSET CHARSET CHECK CHECKPOINT CHECKSUM CLASS CLASS_ORIGIN CLEAN CLIENT CLIENT_MASTER_KEY CLIENT_MASTER_KEYS CLOB CLOSE @@ -1267,7 +1280,7 @@ static bool GreaterThanHour (List* int_type); LABEL LANGUAGE LARGE_P LAST_DAY_FUNC LAST_P LC_COLLATE_P LC_CTYPE_P LEADING LEAKPROOF LEAST LESS LEFT LEVEL LIKE LINES LIMIT LIST LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP - LOCATE LOCATION LOCK_P LOCKED LOG_P LOGGING LOGIN_ANY LOGIN_FAILURE LOGIN_SUCCESS LOGOUT LOGS LOOP LOW_PRIORITY + LOCATE LOCATION LOCK_P LOCKED LOG_ON LOG_P LOGGING LOGIN_ANY LOGIN_FAILURE LOGIN_SUCCESS LOGOUT LOGS LOOP LOW_PRIORITY MAPPING MASKING MASTER MATCH MATERIALIZED MATCHED MAXEXTENTS MAXSIZE MAXTRANS MAXVALUE MEDIUMINT MEMORY MERGE MESSAGE_TEXT METHOD MICROSECOND_P MID MIN_ROWS MINUTE_P MINUTE_MICROSECOND_P MINUTE_SECOND_P MINVALUE MINEXTENTS MODE MODEL MODIFY_P MONTH_P MOVE MOVEMENT MYSQL_ERRNO MOD MODIFIES MAX_ROWS @@ -1322,7 +1335,7 @@ static bool GreaterThanHour (List* int_type); ZEROFILL ZONE - AST DB_B_JSON DB_B_JSONB DB_B_BOX DB_B_CIRCLE DB_B_POLYGON DB_B_BYTEA DB_B_TIMETZ DB_B_TIMESTAMPTZ DB_B_POINT DB_B_CIDR + AST DB_B_JSON DB_B_JSONB DB_B_BOX DB_B_CIRCLE DB_B_LSEG DB_B_PATH DB_B_POLYGON DB_B_BYTEA DB_B_TIMETZ DB_B_TIMESTAMPTZ DB_B_POINT DB_B_CIDR WEIGHT_STRING REVERSE %token ALGORITHM_UNDEFINED ALGORITHM_MERGE ALGORITHM_TEMPTABLE @@ -1429,7 +1442,7 @@ static bool GreaterThanHour (List* int_type); * blame any funny behavior of UNBOUNDED on the SQL standard, though. */ %nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */ -%nonassoc IDENT GENERATED NULL_P PARTITION SUBPARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP DB_B_JSON DB_B_JSONB DB_B_BOX DB_B_CIRCLE DB_B_POLYGON DB_B_BYTEA DB_B_TIMETZ DB_B_TIMESTAMPTZ DB_B_POINT DB_B_CIDR +%nonassoc IDENT GENERATED NULL_P PARTITION SUBPARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP DB_B_JSON DB_B_JSONB DB_B_BOX DB_B_CIRCLE DB_B_LSEG DB_B_PATH DB_B_POLYGON DB_B_BYTEA DB_B_TIMETZ DB_B_TIMESTAMPTZ DB_B_POINT DB_B_CIDR %left Op OPERATOR '@' /* multi-character ops and user-defined operators */ %nonassoc NOTNULL %nonassoc ISNULL @@ -1462,6 +1475,14 @@ static bool GreaterThanHour (List* int_type); %left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL ENCRYPTED STRAIGHT_JOIN /* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */ %right PRESERVE STRIP_P +%token CONSTRUCTOR FINAL MAP MEMBER RESULT SELF STATIC_P UNDER +%token SELF_INOUT + STATIC_FUNCTION + MEMBER_FUNCTION + STATIC_PROCEDURE + MEMBER_PROCEDURE + CONSTRUCTOR_FUNCTION + MAP_MEMBER %% /* @@ -1639,6 +1660,8 @@ stmt : | CreatePackageBodyStmt | CreateGroupStmt | CreateMatViewStmt + | CreateMatViewLogStmt + | DropMatViewLogStmt | CreateModelStmt // DB4AI | CreateNodeStmt | CreateOpClassStmt @@ -10225,6 +10248,7 @@ TypedTableElement: ColIdForTableElement: DOLPHINIDENT { $$ = $1->str; } | unreserved_keyword_without_key { $$ = pstrdup($1); } | col_name_keyword { $$ = pstrdup($1); } + | PROXY { $$ = pstrdup($1); } ; columnDefForTableElement: ColIdForTableElement Typename opt_charset KVType ColCmprsMode create_generic_options ColQualList @@ -12992,7 +13016,7 @@ OptSnapshotStratify: *****************************************************************************/ CreateMatViewStmt: - CREATE OptNoLog opt_incremental MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + CREATE OptNoLog INCREMENTAL MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data { CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); ctas->query = $8; @@ -13002,14 +13026,8 @@ CreateMatViewStmt: /* cram additional flags into the IntoClause */ $6->rel->relpersistence = $2; $6->skipData = !($9); - if ($6->skipData) { - const char* message = "WITH NO DATA for materialized views not yet supported"; - InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); - ereport(errstate, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("WITH NO DATA for materialized views not yet supported"))); - } - if ($3 && $6->options) { + $6->ivm = true; + if ($6->options) { const char* message = "options for incremental materialized views not yet supported"; InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); ereport(errstate, @@ -13017,7 +13035,7 @@ CreateMatViewStmt: errmsg("options for incremental materialized views not yet supported"))); } #ifndef ENABLE_MULTIPLE_NODES - if ($3 && $6->distributeby) { + if ($6->distributeby) { const char* message = "It's not supported to specify distribute key on incremental materialized views"; InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); ereport(errstate, @@ -13029,10 +13047,47 @@ CreateMatViewStmt: ereport(errstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("matview is not supported while DMS and DSS enabled."))); } - - $6->ivm = $3; + $$ = (Node *) ctas; } + | CREATE MATERIALIZED VIEW create_mv_target build_deferred AS SelectStmt + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ctas->query = $7; + ctas->into = $4; + ctas->relkind = OBJECT_MATVIEW; + ctas->is_select_into = false; + /* cram additional flags into the IntoClause */ + $4->rel->relpersistence = RELPERSISTENCE_PERMANENT; + $4->skipData = $5; + $4->ivm = false; + + if (ENABLE_DMS) { + ereport(errstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("matview is not supported while DMS and DSS enabled."))); + } + + $$ = (Node *) ctas; + } + | CREATE MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ctas->query = $6; + ctas->into = $4; + ctas->relkind = OBJECT_MATVIEW; + ctas->is_select_into = false; + /* cram additional flags into the IntoClause */ + $4->rel->relpersistence = RELPERSISTENCE_PERMANENT; + $4->skipData = !($7); + $4->ivm = false; + + if (ENABLE_DMS) { + ereport(errstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("matview is not supported while DMS and DSS enabled."))); + } + + $$ = (Node *) ctas; + } ; create_mv_target: @@ -13066,6 +13121,10 @@ opt_incremental: | /*EMPTY*/ { $$ = FALSE; } ; +build_deferred: + BUILD DEFERRED { $$ = TRUE; } + | BUILD IMMEDIATE { $$ = FALSE; } + ; /***************************************************************************** * @@ -13092,6 +13151,23 @@ RefreshMatViewStmt: } ; +CreateMatViewLogStmt: + CREATE MATERIALIZED VIEW LOG_ON qualified_name + { + CreateMatViewLogStmt* stmt = makeNode(CreateMatViewLogStmt); + stmt->relation = $5; + $$ = (Node*)stmt; + } + ; + +DropMatViewLogStmt: + DROP MATERIALIZED VIEW LOG_ON qualified_name + { + DropMatViewLogStmt* stmt = makeNode(DropMatViewLogStmt); + stmt->relation = $5; + $$ = (Node*)stmt; + } + ; /***************************************************************************** * @@ -15139,7 +15215,7 @@ CreateTrigStmt: (errcode(ERRCODE_SYNTAX_ERROR), errmsg("or replace is not supported here."), parser_errposition(@2))); } - if ($3 != NULL) + if ($3 != NULL && !u_sess->attr.attr_common.enable_dump_trigger_definer) { ereport(errstate, (errcode(ERRCODE_SYNTAX_ERROR), @@ -15230,8 +15306,8 @@ CreateTrigStmt: n->whenClause = $11; n->trgordername = $12->trigger_name; n->is_follows = $12->is_follows; - FunctionSources *funSource = (FunctionSources *)$14; - n->funcSource = funSource; + FunctionSources *funcSource = (FunctionSources *)$14; + n->funcSource = funcSource; n->isconstraint = FALSE; n->deferrable = FALSE; n->initdeferred = FALSE; @@ -15274,8 +15350,8 @@ CreateTrigStmt: n->whenClause = $14; n->trgordername = $15->trigger_name; n->is_follows = $15->is_follows; - FunctionSources *funSource = (FunctionSources *)$17; - n->funcSource = funSource; + FunctionSources *funcSource = (FunctionSources *)$17; + n->funcSource = funcSource; n->isconstraint = FALSE; n->deferrable = FALSE; n->initdeferred = FALSE; @@ -15592,11 +15668,11 @@ enable_trigger: ; qualified_trigger_name: - name + DolphinColColId { $$ = makeRangeVar(NULL, $1, @1); } - | ColId indirection + | DolphinColColId case_sensitive_indirection { check_qualified_name($2, yyscanner); $$ = makeRangeVar(NULL, NULL, @1); @@ -15812,6 +15888,11 @@ DefineStmt: n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); n->replace = false; n->coldeflist = $6; + n->final = true; + n->typekind = TYPE_COMPOSITE_DEFAULT; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = NULL; $$ = (Node *)n; } | CREATE OR REPLACE TYPE_P any_name as_is '(' OptTableFuncElementList ')' @@ -15822,6 +15903,297 @@ DefineStmt: n->typevar = makeRangeVarFromAnyName($5, @5, yyscanner); n->replace = true; n->coldeflist = $8; + n->final = true; + n->typekind = TYPE_COMPOSITE_DEFAULT; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = NULL; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name as_is OBJECT_P '(' OptTableFuncElementList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + if ($7 == NIL) { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("no attributes found in object type \"%s\"",strVal(linitial($3))))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + /* Cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); + n->replace = false; + n->coldeflist = $7; + n->final = $9; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = NULL; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @6, @8-@6+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P any_name as_is OBJECT_P '(' OptTableFuncElementList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + if ($9 == NIL) { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("no attributes found in object type \"%s\"",strVal(linitial($5))))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + /* Cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($5, @5, yyscanner); + n->replace = true; + n->coldeflist = $9; + n->final = $11; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = NULL; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @8, @10-@8+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name as_is OBJECT_P '(' TableFuncElementList ',' Method_specList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + /* Cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); + n->replace = false; + n->coldeflist = $7; + n->final = $11; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = $9; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @6, @10-@6+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P any_name as_is OBJECT_P '(' TableFuncElementList ',' Method_specList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + /* Cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($5, @5, yyscanner); + n->replace = true; + n->coldeflist = $9; + n->final = $13; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->issubtype = false; + n->supertype = NULL; + n->methodlist = $11; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @8, @12-@8+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name UNDER any_name '(' TableFuncElementList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); + n->supertype = makeRangeVarFromAnyName($5, @5, yyscanner); + n->coldeflist = $7; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->replace = false; + n->final = $9; + n->issubtype = true; + n->methodlist = NULL; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @6, @8-@6+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P any_name UNDER any_name '(' TableFuncElementList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($5, @5, yyscanner); + n->supertype = makeRangeVarFromAnyName($7, @7, yyscanner); + n->coldeflist = $9; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->replace = true; + n->final = $11; + n->issubtype = true; + n->methodlist = NULL; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @8, @10-@8+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name UNDER any_name '(' TableFuncElementList ',' Method_specList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); + n->supertype = makeRangeVarFromAnyName($5, @5, yyscanner); + n->coldeflist = $7; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->replace = false; + n->final = $11; + n->issubtype = true; + n->methodlist = $9; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @6, @10-@6+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P any_name UNDER any_name '(' TableFuncElementList ',' Method_specList ')' final_clause + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typespec; + initStringInfo(&typespec); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($5, @5, yyscanner); + n->supertype = makeRangeVarFromAnyName($7, @7, yyscanner); + n->coldeflist = $9; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE; + n->replace = true; + n->final = $13; + n->issubtype = true; + n->methodlist = $11; + + appendBinaryStringInfo(&typespec, yyextra->core_yy_extra.scanbuf + @8, @12-@8+1); + n->typespec = typespec.data; + n->typebody = NULL; + $$ = (Node *)n; + } + | CREATE TYPE_P BODY_P any_name as_is type_body_subprogram + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typebody; + initStringInfo(&typebody); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($4, @4, yyscanner); + n->replace = false; + n->methodlist = $6; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE_BODY; + appendBinaryStringInfo(&typebody, yyextra->core_yy_extra.scanbuf + @5, yylloc - @5 +1); + n->typebody = typebody.data; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P BODY_P any_name as_is type_body_subprogram + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TYPE AS OBJECT is only support in A-format database"))); + } + + CompositeTypeStmt *n = makeNode(CompositeTypeStmt); + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + StringInfoData typebody; + initStringInfo(&typebody); + + /* cannot use qualified_name, sigh */ + n->typevar = makeRangeVarFromAnyName($6, @6, yyscanner); + n->replace = true; + n->methodlist = $8; + n->typekind = TYPE_COMPOSITE_OBJECT_TYPE_BODY; + appendBinaryStringInfo(&typebody, yyextra->core_yy_extra.scanbuf + @7, yylloc - @7 +1); + n->typebody = typebody.data; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name as_is VARRAY '(' ICONST ')' OF func_type + { + TableOfTypeStmt *n = makeNode(TableOfTypeStmt); + n->typname = $3; + n->reftypname = $10; + n->replace = false; + n->typtype = TYPTYPE_VARRAY; + n->typecategory = TYPCATEGORY_VARRAY; + $$ = (Node *)n; + } + | CREATE OR REPLACE TYPE_P any_name as_is VARRAY '(' ICONST ')' OF func_type + { + TableOfTypeStmt *n = makeNode(TableOfTypeStmt); + n->typname = $5; + n->reftypname = $12; + n->replace = true; + n->typtype = TYPTYPE_VARRAY; + n->typecategory = TYPCATEGORY_VARRAY; $$ = (Node *)n; } | CREATE TYPE_P any_name as_is TABLE OF func_type @@ -15830,6 +16202,8 @@ DefineStmt: n->replace = false; n->typname = $3; n->reftypname = $7; + n->typtype = TYPTYPE_TABLEOF; + n->typecategory = TYPCATEGORY_TABLEOF; $$ = (Node *)n; } | CREATE OR REPLACE TYPE_P any_name as_is TABLE OF func_type @@ -15838,6 +16212,8 @@ DefineStmt: n->replace = true; n->typname = $5; n->reftypname = $9; + n->typtype = TYPTYPE_TABLEOF; + n->typecategory = TYPCATEGORY_TABLEOF; $$ = (Node *)n; } | CREATE TYPE_P any_name as_is ENUM_P '(' opt_enum_val_list ')' @@ -15909,6 +16285,568 @@ DefineStmt: $$ = (Node *)n; } ; +type_body_subprogram: method_decl_in_type_list ';' END_P ';' + { $$ = $1;}; + +Method_specList: element_spec + { + $$ = list_make1($1); + } + | Method_specList ',' element_spec + { + $$ = lappend($1, $3); + } + ; + +element_spec : inheritance_clause MEMBER_FUNCTION func_name_opt_arg object_proc_args RETURN func_return + { + if ($4 != NIL && NULL != (FunctionParameter*)linitial($4)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($4); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = false; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->returnType = $6; + n->typfunckind = OBJECTTYPE_MEMBER_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause STATIC_FUNCTION func_name_opt_arg object_proc_args RETURN func_return + { + if ($4 != NIL && NULL != (FunctionParameter*)linitial($4)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($4); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = false; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->returnType = $6; + n->typfunckind = OBJECTTYPE_STATIC_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause MEMBER_PROCEDURE func_name_opt_arg object_proc_args + { + if ($4 != NIL && NULL != (FunctionParameter*)linitial($4)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($4); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + int count = get_outarg_num($4); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = false; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->returnType = NULL; + if (count == 0) + { + n->returnType = makeTypeName("void"); + n->returnType->typmods = NULL; + n->returnType->arrayBounds = NULL; + } + n->typfunckind = OBJECTTYPE_MEMBER_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = true; + $$ = (Node*)n; + } + | inheritance_clause STATIC_PROCEDURE func_name_opt_arg proc_args + { + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + int count = get_outarg_num($4); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = false; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->returnType = NULL; + if (count == 0) + { + n->returnType = makeTypeName("void"); + n->returnType->typmods = NULL; + n->returnType->arrayBounds = NULL; + } + n->typfunckind = OBJECTTYPE_STATIC_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = true; + $$ = (Node*)n; + } + | inheritance_clause CONSTRUCTOR_FUNCTION func_name_opt_arg object_proc_args RETURN SELF AS RESULT + { + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->returnType = NULL; + n->typfunckind = OBJECTTYPE_CONSTRUCTOR_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause MAP_MEMBER FUNCTION func_name_opt_arg object_proc_args RETURN func_return + { + if ($5 != NIL && NULL != (FunctionParameter*)linitial($5)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($5); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $4; + n->parameters = $5; + n->returnType = $7; + n->typfunckind = OBJECTTYPE_MAP_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause MAP_MEMBER PROCEDURE func_name_opt_arg object_proc_args + { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Only a function can be a MAP,ORDER or CONSTRUCTOR method"))); + } + | inheritance_clause ORDER MEMBER_PROCEDURE func_name_opt_arg object_proc_args + { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Only a function can be a MAP,ORDER or CONSTRUCTOR method"))); + } + | inheritance_clause ORDER MEMBER_FUNCTION func_name_opt_arg object_proc_args RETURN func_return + { + if ($5 != NIL && NULL != (FunctionParameter*)linitial($5)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($5); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + List *list = list_make1(makeDefElem("as", (Node *)list_make1(makeString("begin\nend")))); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $4; + n->parameters = $5; + n->returnType = $7; + n->typfunckind = OBJECTTYPE_ORDER_PROC; + n->isfinal = $1; + list = lappend(list, makeDefElem("language", (Node*) makeString("plpgsql"))); + n->options = list; + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + +final_clause: FINAL { $$ = true;} + | NOT FINAL { $$ = false;} + | /* EMPTY */ { $$ = true; } /*FINAL for default, allow to create subtype*/ + ; + +inheritance_clause: FINAL { $$ = true;} + | NOT FINAL { $$ = false;} + | /* EMPTY */ { $$ = false; }/*NOT FINAL for default, allow subtype to override method*/ + ; + +object_func_args_with_defaults: '(' SELF_INOUT func_type ',' func_args_with_defaults_list ')' + { + FunctionParameter *self = makeNode(FunctionParameter); + self->name = pstrdup("self"); + self->argType = $3; + self->mode = FUNC_PARAM_INOUT; + self->defexpr = NULL; + $$ = list_concat(list_make1(self), $5); + } + | '(' func_args_with_defaults_list ')' { $$ = $2; } + | '(' ')' { $$ = NIL; } + ; + +object_proc_args: object_func_args_with_defaults { $$ = $1; } + | /* EMPTY */ { $$ = NIL; } + ; + +method_decl_in_type_list: + element_decl_in_type { $$ = list_make1($1); } + | method_decl_in_type_list ';' element_decl_in_type { $$ = lappend($1, $3); } + ; + +element_decl_in_type: subprogram_decl_in_type + | constructor_decl_in_type + | map_order_decl_in_type + {$$ = $1;} + ; + +subprogram_decl_in_type : inheritance_clause MEMBER_FUNCTION func_name_opt_arg object_proc_args RETURN func_return opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + if ($4 != NIL && NULL != (FunctionParameter*)linitial($4)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($4); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @8); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$10; + n->isOraStyle = true; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = $6; + n->options = $7; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->typfunckind = OBJECTTYPE_MEMBER_PROC; + n->isfinal = $1; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause STATIC_FUNCTION func_name_opt_arg object_proc_args RETURN func_return opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @8); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$10; + n->isOraStyle = true; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = $6; + n->options = $7; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->typfunckind = OBJECTTYPE_STATIC_PROC; + n->isfinal = $1; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause MEMBER_PROCEDURE func_name_opt_arg object_proc_args opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + if ($4 != NIL && NULL != (FunctionParameter*)linitial($4)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($4); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @6); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$8; + int count = get_outarg_num($4); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + + n->funcname = $3; + n->parameters = $4; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = NULL; + n->isProcedure = true; + if (0 == count) + { + n->returnType = makeTypeName("void"); + n->returnType->typmods = NULL; + n->returnType->arrayBounds = NULL; + } + n->options = $5; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + + n->withClause = NIL; + u_sess->parser_cxt.isCreateFuncOrProc = false; + n->typfunckind = OBJECTTYPE_MEMBER_PROC; + n->isfinal = $1; + $$ = (Node*)n; + } + | inheritance_clause STATIC_PROCEDURE func_name_opt_arg object_proc_args opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + int rc = 0; + rc = CompileWhich(); + if ((rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) && u_sess->cmd_cxt.CurrentExtensionObject == InvalidOid) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @6); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$8; + int count = get_outarg_num($4); + n->isOraStyle = true; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + + n->funcname = $3; + n->parameters = $4; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = NULL; + n->isProcedure = true; + if (0 == count) + { + n->returnType = makeTypeName("void"); + n->returnType->typmods = NULL; + n->returnType->arrayBounds = NULL; + } + n->options = $5; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + + n->withClause = NIL; + u_sess->parser_cxt.isCreateFuncOrProc = false; + n->typfunckind = OBJECTTYPE_STATIC_PROC; + n->isfinal = $1; + $$ = (Node*)n; + } + ; + +constructor_decl_in_type: inheritance_clause CONSTRUCTOR_FUNCTION func_name_opt_arg object_proc_args RETURN SELF AS RESULT opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @6); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$12; + n->isOraStyle = true; + + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = NULL; + n->options = $9; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $3; + n->parameters = $4; + n->typfunckind = OBJECTTYPE_CONSTRUCTOR_PROC; + n->isfinal = $1; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node *)n; + } + ; + +map_order_decl_in_type : inheritance_clause MAP_MEMBER FUNCTION func_name_opt_arg object_proc_args RETURN func_return opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + if ($5 != NIL && NULL != (FunctionParameter*)linitial($5)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($5); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @6); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$11; + n->isOraStyle = true; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = $7; + n->options = $8; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $4; + n->parameters = $5; + n->typfunckind = OBJECTTYPE_MAP_PROC; + n->isfinal = $1; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause MAP_MEMBER PROCEDURE func_name_opt_arg object_proc_args opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Only a function can be a MAP,ORDER or CONSTRUCTOR method"))); + } + | inheritance_clause ORDER MEMBER_FUNCTION func_name_opt_arg object_proc_args RETURN func_return opt_createproc_opt_list as_is{ + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + if ($5 != NIL && NULL != (FunctionParameter*)linitial($5)) + { + FunctionParameter* firstparam = (FunctionParameter*)linitial($5); + if ((NULL != firstparam->name) && (strcmp(firstparam->name,"self") == 0) && !(firstparam->mode == FUNC_PARAM_IN || firstparam->mode == FUNC_PARAM_INOUT)) + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("the SELF parameter can be declared only as IN or as IN OUT"))); + } + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(pg_yyget_extra(yyscanner)->core_yy_extra.scanbuf, @6); + } + CreateFunctionStmt* n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$11; + n->isOraStyle = true; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + n->returnType = $7; + n->options = $8; + n->isPrivate = false; + n->replace = true; + n->definer = NULL; + n->funcname = $4; + n->parameters = $5; + n->typfunckind = OBJECTTYPE_ORDER_PROC; + n->isfinal = $1; + n->options = lappend(n->options, makeDefElem("as", + (Node*)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node*)makeString("plpgsql"))); + n->withClause = NULL; + n->isProcedure = false; + $$ = (Node*)n; + } + | inheritance_clause ORDER MEMBER_PROCEDURE func_name_opt_arg object_proc_args opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + } subprogram_body + { + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Only a function can be a MAP,ORDER or CONSTRUCTOR method"))); + } + ; opt_cfoptions: WITH cfoptions { $$ = $2; } | /* EMPTY */ { $$ = NIL; } @@ -20142,7 +21080,7 @@ CreateFunctionStmt: u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @10); } CreateFunctionStmt *n = makeNode(CreateFunctionStmt); - FunctionSources *funSource = (FunctionSources *)$12; + FunctionSources *funcSource = (FunctionSources *)$12; n->isOraStyle = true; n->isPrivate = false; n->replace = $2; @@ -20152,14 +21090,14 @@ CreateFunctionStmt: } n->funcname = $5; n->parameters = $6; - n->inputHeaderSrc = FormatFuncArgType(yyscanner, funSource->headerSrc, n->parameters); + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); if (enable_plpgsql_gsdependency_guc()) { n->funcHeadSrc = ParseFuncHeadSrc(yyscanner); } n->returnType = $8; n->options = $9; n->options = lappend(n->options, makeDefElem("as", - (Node *)list_make1(makeString(funSource->bodySrc)))); + (Node *)list_make1(makeString(funcSource->bodySrc)))); n->withClause = NIL; n->isProcedure = false; @@ -20353,7 +21291,7 @@ callfunc_args: func_arg_expr n->end_time_expr = NULL; n->interval_time = NULL; n->complete_preserve = $12; - n->event_status = (EventStatus)$12; + n->event_status = (EventStatus)$13; n->event_comment_str = $14; n->event_query_str = $16; $$ = (Node *)n; @@ -20492,7 +21430,7 @@ interval_list: opt_interval_cell { $$ = $1; } opt_interval_cell: interval_cell | /* EMPTY */ { $$ = NULL; } -interval_cell: INTERVAL a_expr interval_unit +interval_cell: INTERVAL a_expr_without_interval interval_unit { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("any2interval"); @@ -22170,6 +23108,30 @@ opt_createproc_opt_list: /* * Options common to both CREATE FUNCTION and ALTER FUNCTION */ +create_function_common_func_opt_item: + common_func_opt_item + { + $$ = $1; + } + | FunctionSetResetClause %prec '(' ')' + { + /* we abuse the normal content of a DefElem here */ + $$ = makeDefElem("set", (Node *)$1); + } + ; + +alter_function_common_func_opt_item: + common_func_opt_item + { + $$ = $1; + } + | FunctionSetResetClause + { + /* we abuse the normal content of a DefElem here */ + $$ = makeDefElem("set", (Node *)$1); + } + ; + common_func_opt_item: CALLED ON NULL_P INPUT_P { @@ -22251,11 +23213,6 @@ common_func_opt_item: { $$ = makeDefElem("rows", (Node *)$2); } - | FunctionSetResetClause %prec '(' ')' - { - /* we abuse the normal content of a DefElem here */ - $$ = makeDefElem("set", (Node *)$1); - } | FENCED { $$ = makeDefElem("fenced", (Node *)makeInteger(TRUE)); @@ -22365,7 +23322,7 @@ createfunc_opt_item: { $$ = makeDefElem("pipelined", (Node *)makeInteger(TRUE)); } - | common_func_opt_item + | create_function_common_func_opt_item { $$ = $1; } @@ -22373,7 +23330,7 @@ createfunc_opt_item: createproc_opt_item: - common_func_opt_item + create_function_common_func_opt_item { $$ = $1; } @@ -22958,8 +23915,8 @@ AlterProcedureStmt: alterfunc_opt_list: /* At least one option must be specified */ - common_func_opt_item { $$ = list_make1($1); } - | alterfunc_opt_list common_func_opt_item { $$ = lappend($1, $2); } + alter_function_common_func_opt_item { $$ = list_make1($1); } + | alterfunc_opt_list alter_function_common_func_opt_item { $$ = lappend($1, $2); } ; /* Ignored, merely for SQL compliance */ @@ -32466,9 +33423,21 @@ GenericType: { /* for B_FORMAT compatibility, float4(n) refers to float4 */ if (($1 != NULL) && (strcmp($1, "float4") == 0 || strcmp($1, "float") == 0)) { - $$ = transferFloat4TypeInBFormat($1, $2, @2, yyscanner); + if (GetSessionContext()->treat_float_with_precision_as_float_type) { + $$ = makeTypeName("float4"); + $$->location = @1; + if ($2 != NULL && list_length($2) >= 1) { + ereport(NOTICE, (errmsg("it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on."))); + } + } else { + $$ = transferFloat4TypeInBFormat($1, $2, @2, yyscanner); + } } else if (($1 != NULL) && (strcmp($1, "double") == 0) && ($2 != NULL) && (list_length($2) == 2)) { - if ((*(A_Const*)list_nth($2, 1)).val.val.ival == 0) { + if (GetSessionContext()->treat_float_with_precision_as_float_type) { + $$ = makeTypeName("float8"); + $$->location = @1; + ereport(NOTICE, (errmsg("it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on."))); + } else if ((*(A_Const*)list_nth($2, 1)).val.val.ival == 0) { $$ = parseFloatTypeByPrecision((*(A_Const*)list_nth($2, 0)).val.val.ival, @2, yyscanner, false); $$->location = @1; } else { @@ -32847,11 +33816,16 @@ Numeric: NumericNoConflict { $$ = $1; } dolphin_float: '(' Iconst ',' Iconst ')' { - if ($4 == 0) { - $$ = parseFloatTypeByPrecision($2, @2, yyscanner, false); + if (GetSessionContext()->treat_float_with_precision_as_float_type) { + $$ = makeTypeName("float4"); + ereport(NOTICE, (errmsg("it may cause the result in loss of precision when using float4 or float8 with precision and dolphin.treat_float_with_precision_as_float_type is on."))); } else { - $$ = SystemTypeName("numeric"); - $$->typmods = list_make2(makeIntConst($2, @2), makeIntConst($4, @4)); + if ($4 == 0) { + $$ = parseFloatTypeByPrecision($2, @2, yyscanner, false); + } else { + $$ = SystemTypeName("numeric"); + $$->typmods = list_make2(makeIntConst($2, @2), makeIntConst($4, @4)); + } } } ; @@ -34014,7 +34988,10 @@ client_logic_type: * c_expr is all the productions that are common to a_expr and b_expr; * it's factored out just to eliminate redundant coding. */ -a_expr: a_expr_without_sconst { $$ = $1; } +a_expr: a_expr_without_interval { $$ = $1; } + | interval_cell + ; +a_expr_without_interval: a_expr_without_sconst { $$ = $1; } /* Sconst precedence should lower than SCONST, so when we meet SCONST, we will try to do shift, to read more SCONST as possible */ | Sconst %prec TEXT_P { $$ = makeStringConst($1, @1); } ; @@ -34091,7 +35068,7 @@ a_expr_without_sconst: c_expr_without_sconst { $$ = $1; } { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); } | a_expr '=' a_expr { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); } - | interval_cell + | a_expr '@' a_expr { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "@", $1, $3, @2); } | a_expr CmpNullOp a_expr %prec CmpNullOp @@ -36405,6 +37382,7 @@ func_expr_common_subexpr: | EXTRACT '(' extract_list ')' { FuncCall *n = makeNode(FuncCall); +#ifdef DOLPHIN if (list_length($3) == 2) { A_Const* con = (A_Const*)linitial($3); char* argname = strVal(&con->val); @@ -36427,6 +37405,10 @@ func_expr_common_subexpr: n->funcname = SystemFuncName("date_part"); } } +#else + n->funcname = SystemFuncName("extract_internal"); + n->args = $3; +#endif n->args = $3; n->agg_order = NIL; n->agg_star = FALSE; @@ -36603,7 +37585,8 @@ func_expr_common_subexpr: * substring(A, B, C) - thomas 2000-11-28 */ FuncCall *n = makeNode(FuncCall); - n->funcname = SystemFuncName("substring"); + /* under B compatibility, substring is same as substr */ + n->funcname = SystemFuncName("substr"); n->args = $3; n->agg_order = NIL; n->agg_star = FALSE; @@ -36982,7 +37965,7 @@ func_expr_common_subexpr: n->call_func = false; $$ = (Node *)n; } - | DATE_ADD_P '(' a_expr ',' INTERVAL a_expr interval_unit ')' + | DATE_ADD_P '(' a_expr ',' INTERVAL a_expr_without_interval interval_unit ')' { bool isGreatThanHour = GreaterThanHour($7); FuncCall *n1 = makeNode(FuncCall); @@ -37009,7 +37992,22 @@ func_expr_common_subexpr: $$ = (Node *)n2; } - | DATE_SUB_P '(' a_expr ',' INTERVAL a_expr interval_unit ')' + | DATE_ADD_P '(' a_expr ',' a_expr_without_interval ')' + { + FuncCall *n2 = makeNode(FuncCall); + n2->funcname = SystemFuncName("date_add"); + n2->args = list_make2($3, $5); + n2->agg_order = NIL; + n2->agg_star = FALSE; + n2->agg_distinct = FALSE; + n2->func_variadic = FALSE; + n2->over = NULL; + n2->location = @1; + n2->call_func = false; + + $$ = (Node *)n2; + } + | DATE_SUB_P '(' a_expr ',' INTERVAL a_expr_without_interval interval_unit ')' { bool isGreatThanHour = GreaterThanHour($7); FuncCall *n1 = makeNode(FuncCall); @@ -37034,6 +38032,21 @@ func_expr_common_subexpr: n2->location = @1; n2->call_func = false; + $$ = (Node *)n2; + } + | DATE_SUB_P '(' a_expr ',' a_expr_without_interval ')' + { + FuncCall *n2 = makeNode(FuncCall); + n2->funcname = SystemFuncName("date_sub"); + n2->args = list_make2($3, $5); + n2->agg_order = NIL; + n2->agg_star = FALSE; + n2->agg_distinct = FALSE; + n2->func_variadic = FALSE; + n2->over = NULL; + n2->location = @1; + n2->call_func = false; + $$ = (Node *)n2; } ; @@ -38036,6 +39049,47 @@ indirection: | indirection indirection_el { $$ = lappend($1, $2); } ; +case_sensitive_indirection_el: + '.' CaseSensitiveColLabel + { + $$ = (Node *) makeString($2); + } + | ORA_JOINOP + { + $$ = (Node *) makeString("(+)"); + } + | '.' '*' + { + $$ = (Node *) makeNode(A_Star); + } + | '[' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = NULL; + ai->uidx = $2; + $$ = (Node *) ai; + } + | '[' a_expr ':' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = $2; + ai->uidx = $4; + $$ = (Node *) ai; + } + | '[' a_expr ',' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = $2; + ai->uidx = $4; + $$ = (Node *) ai; + } + ; + +case_sensitive_indirection: + case_sensitive_indirection_el { $$ = list_make1($1); } + | case_sensitive_indirection case_sensitive_indirection_el { $$ = lappend($1, $2); } + ; + dolphin_indirection: dolphin_indirection_el { $$ = list_make1($1); } | dolphin_indirection dolphin_indirection_el { $$ = lappend($1, $2); } @@ -38277,6 +39331,22 @@ target_el: a_expr AS DolphinColLabel { $$ = (ResTarget*) $1; } + | interval_cell + { + $$ = makeNode(ResTarget); + $$->name = pstrdup("interval"); + $$->indirection = NIL; + $$->val = (Node *)$1; + $$->location = @1; + } + | interval_cell SCONST + { + $$ = makeNode(ResTarget); + $$->name = $2; + $$->indirection = NIL; + $$->val = (Node *)$1; + $$->location = @1; + } ; connect_by_root_expr: a_expr normal_ident '.' normal_ident @@ -38582,6 +39652,14 @@ DOLPHINIDENT: IDENT { $$ = CreateDolphinIdent(pstrdup($1), false); } + | DB_B_LSEG + { + $$ = CreateDolphinIdent(pstrdup($1), false); + } + | DB_B_PATH + { + $$ = CreateDolphinIdent(pstrdup($1), false); + } | DB_B_POLYGON { $$ = CreateDolphinIdent(pstrdup($1), false); @@ -38773,6 +39851,18 @@ AexprConst_without_Sconst: Iconst tmp->location = @1; $$ = makeStringConstCast($2, @2, tmp); } + | DB_B_LSEG SCONST + { + TypeName * tmp = SystemTypeName("lseg"); + tmp->location = @1; + $$ = makeStringConstCast($2, @2, tmp); + } + | DB_B_PATH SCONST + { + TypeName * tmp = SystemTypeName("path"); + tmp->location = @1; + $$ = makeStringConstCast($2, @2, tmp); + } | DB_B_POLYGON SCONST { TypeName * tmp = SystemTypeName("polygon"); @@ -39379,6 +40469,15 @@ ColLabel: normal_ident { $$ = $1; } } ; +CaseSensitiveColLabel: + DOLPHINIDENT { $$ = $1->str; } + | '\''DOLPHINIDENT'\'' { $$ = $2->str; } + | unreserved_keyword { $$ = pstrdup($1); } + | col_name_keyword { $$ = pstrdup($1); } + | type_func_name_keyword { $$ = pstrdup($1); } + | reserved_keyword { $$ = pstrdup($1); } + ; + DelimiterStmt: DELIMITER { base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); yyextra->core_yy_extra.is_define_delimiter = true; @@ -39526,6 +40625,7 @@ alias_name_unreserved_keyword_without_key: | BLANKS | BLOCKCHAIN | BODY_P + | BUILD | CACHE | CALLED | CANCELABLE @@ -39571,6 +40671,7 @@ alias_name_unreserved_keyword_without_key: | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CONSTRAINTS + | CONSTRUCTOR | CONTAINS | CONTENT_P | CONTVIEW @@ -39666,6 +40767,7 @@ alias_name_unreserved_keyword_without_key: | FILLER | FILL_MISSING_FIELDS | FILTER + | FINAL | FIRST_P | FLUSH | FOLLOWING @@ -39738,6 +40840,7 @@ alias_name_unreserved_keyword_without_key: | MAXEXTENTS | MAXSIZE | MAXTRANS + | MEMBER | MEMORY | MERGE | MESSAGE_TEXT @@ -39848,6 +40951,7 @@ alias_name_unreserved_keyword_without_key: | RESOURCE | RESTART | RESTRICT + | RESULT | RETURNED_SQLSTATE | RETURNS | REUSE @@ -39871,6 +40975,7 @@ alias_name_unreserved_keyword_without_key: | SECOND_P | SECONDARY_ENGINE_ATTRIBUTE | SECURITY + | SELF | SEQUENCE | SEQUENCES | SERIALIZABLE @@ -39901,6 +41006,7 @@ alias_name_unreserved_keyword_without_key: | STARTS | STATEMENT | STATEMENT_ID + | STATIC_P | STATISTICS | STATS_AUTO_RECALC | STATS_PERSISTENT @@ -39955,6 +41061,7 @@ alias_name_unreserved_keyword_without_key: | VALIDATION | VALIDATOR | VARIABLES + | VARRAY | VCGROUP | VERSION_P | VIEW @@ -42724,7 +43831,7 @@ static void checkDeleteRelationError() } #ifndef MAX_SUPPORTED_FUNC_FOR_PART_EXPR -#define MAX_SUPPORTED_FUNC_FOR_PART_EXPR 25 +#define MAX_SUPPORTED_FUNC_FOR_PART_EXPR 26 #endif static void CheckPartitionExpr(Node* expr, int* colCount) { @@ -42741,7 +43848,7 @@ static void CheckPartitionExpr(Node* expr, int* colCount) CheckPartitionExpr(a_expr->lexpr, colCount); CheckPartitionExpr(a_expr->rexpr, colCount); } else if (expr->type == T_FuncCall) { - char* validFuncName[MAX_SUPPORTED_FUNC_FOR_PART_EXPR] = {"abs","ceiling","datediff","day","dayofmonth","dayofweek","dayofyear","extract","floor","hour", + char* validFuncName[MAX_SUPPORTED_FUNC_FOR_PART_EXPR] = {"abs","ceiling","datediff","day","dayofmonth","dayofweek","dayofyear","extract","b_extract","floor","hour", "microsecond","minute","mod","month","quarter","second","time_to_sec","to_days","to_seconds","unix_timestamp","weekday","year","yearweek","date_part","div"}; char* funcname = strVal(llast(((FuncCall*)expr)->funcname)); int count = 0; @@ -43289,6 +44396,9 @@ static List* GetNameListFromDolphinString(List* dolphinStringList) */ static void with_rollup_check_elems_count(Node* expr) { + if (IsA(expr, CoalesceExpr)) { + return; + } /* check if expr has multiple column with parenthesis */ if (!IsA(expr, ColumnRef)) { if (IsA(expr, RowExpr)) { diff --git a/contrib/dolphin/plugin_parser/parse_agg.cpp b/contrib/dolphin/plugin_parser/parse_agg.cpp index b706ac7731f2a99a9e7ce52766a95d279d5ba0ab..4f4c84b448bbaa9fe013e8dc3d5c90a41d8dda40 100644 --- a/contrib/dolphin/plugin_parser/parse_agg.cpp +++ b/contrib/dolphin/plugin_parser/parse_agg.cpp @@ -233,7 +233,8 @@ void transformAggregateCall(ParseState* pstate, Aggref* agg, List* args, List* a * didn't find any local vars or aggs. */ if (min_varlevel == 0) { - if (pstate->p_hasAggs && checkExprHasAggs((Node*)agg->args)) { + if (pstate->p_hasAggs && + (checkExprHasAggs((Node*)agg->args) || checkExprHasAggs((Node*)agg->aggdirectargs))) { ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), errmsg("aggregate function calls cannot be nested"), diff --git a/contrib/dolphin/plugin_parser/parse_coerce.cpp b/contrib/dolphin/plugin_parser/parse_coerce.cpp index f48cbcaf2183d51551ef8c66ac1b2809dfb31d41..d7989005292667c6c1584c818a47150da295d9c2 100644 --- a/contrib/dolphin/plugin_parser/parse_coerce.cpp +++ b/contrib/dolphin/plugin_parser/parse_coerce.cpp @@ -2101,7 +2101,8 @@ static bool category_can_be_matched(TYPCATEGORY preferCategory, TYPCATEGORY next {TYPCATEGORY_UNKNOWN, TYPCATEGORY_STRING}, {TYPCATEGORY_UNKNOWN, TYPCATEGORY_NUMERIC}, {TYPCATEGORY_NUMERIC, TYPCATEGORY_STRING}, {TYPCATEGORY_NUMERIC, TYPCATEGORY_UNKNOWN}, {TYPCATEGORY_STRING, TYPCATEGORY_DATETIME}, {TYPCATEGORY_STRING, TYPCATEGORY_TIMESPAN}, - {TYPCATEGORY_UNKNOWN, TYPCATEGORY_DATETIME}, {TYPCATEGORY_UNKNOWN, TYPCATEGORY_TIMESPAN}}; + {TYPCATEGORY_UNKNOWN, TYPCATEGORY_DATETIME}, {TYPCATEGORY_UNKNOWN, TYPCATEGORY_TIMESPAN}, + {TYPCATEGORY_DATETIME, TYPCATEGORY_UNKNOWN}}; for (unsigned int i = 0; i < sizeof(categoryMatchedList) / sizeof(categoryMatchedList[0]); i++) { if (preferCategory == categoryMatchedList[i][0] && nextCategory == categoryMatchedList[i][1]) { diff --git a/contrib/dolphin/plugin_parser/parse_expr.cpp b/contrib/dolphin/plugin_parser/parse_expr.cpp index ce7d5ddad8615a90d63b7f73cc191ea12afb8451..216ec8b7a57747de0d97ec73fba1307b641ae188 100644 --- a/contrib/dolphin/plugin_parser/parse_expr.cpp +++ b/contrib/dolphin/plugin_parser/parse_expr.cpp @@ -21,8 +21,10 @@ #include "catalog/pg_attrdef.h" #include "catalog/pg_enum.h" #include "catalog/pg_type.h" +#include "catalog/pg_object.h" #include "catalog/pg_proc.h" #include "catalog/gs_package.h" +#include "catalog/pg_proc_fn.h" #include "catalog/gs_collation.h" #include "catalog/pg_proc_ext.h" #include "commands/dbcommands.h" @@ -63,6 +65,8 @@ #include "plugin_utils/varlena.h" #include "plugin_commands/mysqlmode.h" #include "plugin_utils/varlena.h" +#include "plugin_utils/datetime.h" +#include "plugin_utils/timestamp.h" #endif #include "tcop/tcopprot.h" @@ -202,6 +206,101 @@ void DealWithBoolType(ParseState** pstate, Node** lexpr, Node** rexpr) } } +/* Get result oid of interval operation when dealling with UNKNOWN*/ +Oid GetIntervalOpOid(Node* lexpr, Node* rexpr) +{ + if (!ENABLE_B_CMPT_MODE || lexpr->type != T_Const || ((Const*)lexpr)->constisnull || rexpr->type != T_FuncExpr) { + return UNKNOWNOID; + } + + Const* cons = (Const*)lexpr; + char* timeval = DatumGetCString(cons->constvalue); + FuncExpr* func = (FuncExpr*)rexpr; + + if (list_length(func->args) < 2) { + return UNKNOWNOID; + } + + Node* arg = (Node *)lsecond(func->args); + Const* const_type = (Const*)arg; + int int_type = DatumGetInt32(const_type->constvalue); + + struct pg_tm tt; + struct pg_tm* tm = &tt; + fsec_t fsec; + int tm_type = DTK_NONE; + + if (!cstring_to_tm(timeval, tm, fsec, tm_type)) { + return UNKNOWNOID; + } + + if (tm_type == DTK_DATE && (int_type & (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) + | INTERVAL_MASK(SECOND) | INTERVAL_MASK(MICROSECOND))) == 0) { + return DATEOID; + } else { + return TIMESTAMPOID; + } +} + +Oid GetDateIntervalOpOid(Node* expr) +{ + if (expr->type != T_FuncExpr) { + return DATEOID; + } + + FuncExpr* func = (FuncExpr*)expr; + + if (list_length(func->args) < 2) { + return DATEOID; + } + + Node* arg = (Node *)lsecond(func->args); + Const* const_type = (Const*)arg; + int int_type = DatumGetInt32(const_type->constvalue); + + if ((int_type & (INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) + | INTERVAL_MASK(SECOND) | INTERVAL_MASK(MICROSECOND))) == 0) { + return DATEOID; + } else { + return TIMESTAMPOID; + } +} + +void DealWithIntervalType(ParseState** pstate, Node** lexpr, Node** rexpr, char* opername) +{ + + Oid leftType = exprType(*lexpr); + Oid rightType = exprType(*rexpr); + if ((leftType != INTERVALOID && rightType != INTERVALOID) || + (strcmp(opername, "+") != 0 && strcmp(opername, "-") != 0)) { + return; + } + + if (strcmp(opername, "+") == 0) { + if (leftType == UNKNOWNOID && rightType == INTERVALOID) { + *lexpr = coerce_to_target_type(*pstate, *lexpr, UNKNOWNOID, + GetIntervalOpOid(*lexpr, *rexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } else if (rightType == UNKNOWNOID && leftType == INTERVALOID) { + *rexpr = coerce_to_target_type(*pstate, *rexpr, UNKNOWNOID, + GetIntervalOpOid(*rexpr, *lexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } else if (leftType == DATEOID && rightType == INTERVALOID) { + *lexpr = coerce_to_target_type(*pstate, *lexpr, DATEOID, + GetDateIntervalOpOid(*rexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } else if (rightType == DATEOID && leftType == INTERVALOID) { + *rexpr = coerce_to_target_type(*pstate, *rexpr, DATEOID, + GetDateIntervalOpOid(*lexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } + } else { + if (leftType == UNKNOWNOID && rightType == INTERVALOID) { + *lexpr = coerce_to_target_type(*pstate, *lexpr, UNKNOWNOID, + GetIntervalOpOid(*lexpr, *rexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } else if (leftType == DATEOID && rightType == INTERVALOID) { + *lexpr = coerce_to_target_type(*pstate, *lexpr, DATEOID, + GetDateIntervalOpOid(*rexpr), MAX_INTERVAL_PRECISION, COERCION_EXPLICIT, COERCE_EXPLICIT_CAST, -1); + } + } +} + void CoerceConstToTargetType(ParseState** pstate, Node** lexpr, Node** rexpr, A_Expr* a, char* opername) { Oid leftType = exprType(*lexpr); @@ -1496,8 +1595,11 @@ static bool isCol2Function(List* fields) if (OidIsValid(pkgOid)) { bool isNull = false; + bool ispackage = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_package, &isNull); Datum packageid_datum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_packageid, &isNull); - Oid packageid = ObjectIdGetDatum(packageid_datum); + Oid packageid = InvalidOid; + if (!isNull && ispackage) + packageid = ObjectIdGetDatum(packageid_datum); if (packageid != pkgOid) { continue; } @@ -1632,6 +1734,7 @@ static Node* transformAExprOp(ParseState* pstate, A_Expr* a) if (strcmp(strVal(linitial(a->name)), "=") == 0) { DealWithBoolType(&pstate, &lexpr, &rexpr); } + DealWithIntervalType(&pstate, &lexpr, &rexpr, strVal(linitial(a->name))); CoerceConstToTargetType(&pstate, &lexpr, &rexpr, a, strVal(linitial(a->name))); #endif result = (Node*)make_op(pstate, a->name, lexpr, rexpr, last_srf, a->location); @@ -2000,7 +2103,12 @@ static bool NeedExtractOutParam(FuncCall* fn, Node* result) return false; } #ifndef ENABLE_MULTIPLE_NODES - return enable_out_param_override(); + char objMethodKind = get_object_method_kind(funcexpr->funcid); + if ((objMethodKind == OBJECTTYPE_CONSTRUCTOR_PROC) || (objMethodKind == OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC)) { + return false; + } else { + return enable_out_param_override(); + } #else return false; #endif @@ -2884,7 +2992,33 @@ static Node* transformCaseExpr(ParseState* pstate, CaseExpr* c) /* casecollid will be set by parse_collate.c */ /* Convert default result clause, if necessary */ - newc->defresult = (Expr*)coerce_to_common_type(pstate, (Node*)newc->defresult, ptype, "CASE/ELSE"); + if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && c->fromDecode) { + Node *defResNode = (Node*)newc->defresult; + Oid sourceTypeId = exprType(defResNode); + if (sourceTypeId != ptype) { + /* + * only check if type can be coerced, return TypeCast node + * the TypeCast node will be executed when truly needed + */ + if (can_coerce_type(1, &sourceTypeId, &ptype, COERCION_IMPLICIT)) { + TypeCast *n = makeNode(TypeCast); + n->arg = defResNode; + n->typname = makeTypeNameFromOid(ptype, -1); + n->location = -1; + newc->defresult = (Expr*)n; + } else { + ereport(ERROR, + (errcode(ERRCODE_CANNOT_COERCE), + errmsg("%s could not convert type %s to %s", + "CASE/ELSE", + format_type_be(sourceTypeId), + format_type_be(ptype)), + parser_errposition(pstate, exprLocation(defResNode)))); + } + } + } else { + newc->defresult = (Expr*)coerce_to_common_type(pstate, (Node*)newc->defresult, ptype, "CASE/ELSE"); + } /* Convert when-clause results, if necessary */ foreach (l, newc->args) { diff --git a/contrib/dolphin/plugin_parser/parse_func.cpp b/contrib/dolphin/plugin_parser/parse_func.cpp index aff5942194c0e57e80b04a8c2fc0f0ecd1e4f04d..c3c27353d33f32cd54fef34bcebb73a5a7dc85b9 100644 --- a/contrib/dolphin/plugin_parser/parse_func.cpp +++ b/contrib/dolphin/plugin_parser/parse_func.cpp @@ -32,6 +32,7 @@ #include "plugin_parser/parse_relation.h" #include "plugin_parser/parse_target.h" #include "plugin_parser/parse_type.h" +#include "plugin_parser/parse_oper.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -1664,6 +1665,10 @@ FuncDetailCode func_get_detail(List* funcname, List* fargs, List* fargnames, int *retset = false; return FUNCDETAIL_AGGREGATE; } + if (strcmp(objname, "bit_and") == 0 && + (IsIntType(*argtypes) || IsUnsignedIntType(*argtypes))) { + *argtypes = UINT8OID; + } #endif #ifndef ENABLE_MULTIPLE_NODES @@ -1813,7 +1818,12 @@ FuncDetailCode func_get_detail(List* funcname, List* fargs, List* fargnames, int Node* arg1 = (Node*)linitial(fargs); bool iscoercion = false; - if (sourceType == UNKNOWNOID && IsA(arg1, Const)) { + if (sourceType == UNKNOWNOID && IsA(arg1, Const) +#ifdef DOLPHIN + /* uuid(xxx) is not allow to be treated as coercion */ + && targetType != UUIDOID +#endif + ) { /* always treat typename('literal') as coercion */ iscoercion = true; } else { diff --git a/contrib/dolphin/plugin_parser/parse_oper.cpp b/contrib/dolphin/plugin_parser/parse_oper.cpp index 4913cb05c7790c13b34327544239fa6d53fca4bf..b32ea90ddf9cbe0cb406891c4eddf2d68fabbdd8 100644 --- a/contrib/dolphin/plugin_parser/parse_oper.cpp +++ b/contrib/dolphin/plugin_parser/parse_oper.cpp @@ -589,6 +589,10 @@ Operator oper(ParseState* pstate, List* opname, Oid ltypeId, Oid rtypeId, bool n ltypeId = TEXTOID; } else if (ltypeId == INTERVALOID && rtypeId == UNKNOWNOID) { rtypeId = TEXTOID; + } else if (type_is_enum(ltypeId) && rtypeId == INTERVALOID) { + ltypeId = ANYENUMOID; + } else if (ltypeId == INTERVALOID && type_is_enum(rtypeId)) { + rtypeId = ANYENUMOID; } } /** diff --git a/contrib/dolphin/plugin_parser/parse_target.cpp b/contrib/dolphin/plugin_parser/parse_target.cpp index 2953b2827a797547eeabda76446777964319fe21..1d0e09f707b6a27fe600f1fa0bfd45fb92a7a670 100644 --- a/contrib/dolphin/plugin_parser/parse_target.cpp +++ b/contrib/dolphin/plugin_parser/parse_target.cpp @@ -499,6 +499,10 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, ParseExprKind exprKi checkArrayTypeInsert(pstate, expr); } + if (IsA(expr, Param) && DISABLE_RECORD_TYPE_IN_DML && type_id == RECORDOID) { + ereport(ERROR, (errcode(ERRCODE_PLPGSQL_ERROR), + errmsg("The record type variable cannot be used as an insertion value."))); + } ELOG_FIELD_NAME_START(colname); /* @@ -1386,7 +1390,13 @@ static List* ExpandRowReference(ParseState* pstate, Node* expr, bool targetlist) if (IsA(expr, Var) && ((Var*)expr)->vartype == RECORDOID) { tupleDesc = expandRecordVariable(pstate, (Var*)expr, 0); } else if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) { - tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr), exprTypmod(expr)); + if (IsA(expr, RowExpr) && ((RowExpr*)expr)->row_typeid == RECORDOID) { + RowExpr* rowexpr = (RowExpr*)expr; + tupleDesc = ExecTypeFromExprList(rowexpr->args, rowexpr->colnames); + BlessTupleDesc(tupleDesc); + } else { + tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr), exprTypmod(expr)); + } } if (unlikely(tupleDesc == NULL)) { diff --git a/contrib/dolphin/plugin_parser/parse_type.cpp b/contrib/dolphin/plugin_parser/parse_type.cpp index aba50d5488058049bbd59e9618f8e589b991277c..e8e5fc1ad0e430b7d4b97a94651d99c462eade8b 100644 --- a/contrib/dolphin/plugin_parser/parse_type.cpp +++ b/contrib/dolphin/plugin_parser/parse_type.cpp @@ -432,6 +432,10 @@ Type LookupTypeNameExtended(ParseState* pstate, const TypeName* typname, int32* if (isPkgType) { typoid = LookupTypeInPackage(typname->names, typeName, pkgOid); } + /* try to find in func */ + if (!OidIsValid(typoid)) { + typoid = LookupTypeInFunc(typeName); + } if (!OidIsValid(typoid)) { /* Unqualified type name, so search the search path */ typoid = TypenameGetTypidExtended(typeName, temp_ok); @@ -1914,6 +1918,35 @@ bool IsBinaryType(Oid typid) typid == MEDIUMBLOBOID || typid == LONGBLOBOID); } #else + +/* find type in curr function */ +Oid LookupTypeInFunc(const char *typeName) +{ + Oid typOid = InvalidOid; + char* castTypeName = NULL; + Oid func_oid = InvalidOid; + + if (u_sess->plsql_cxt.curr_compile_context != NULL + && u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile != NULL) { + func_oid = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_oid; + } + + if (!OidIsValid(func_oid)) { + return typOid; + } + + castTypeName = CastPackageTypeName(typeName, func_oid, false, true); + Oid namespaceId = getCurrentNamespace(); + if (OidIsValid(namespaceId)) { + typOid = GetSysCacheOid2(TYPENAMENSP, PointerGetDatum(castTypeName), ObjectIdGetDatum(namespaceId)); + if (!OidIsValid(typOid)) { + typOid = TryLookForSynonymType(castTypeName, namespaceId); + } + } + pfree_ext(castTypeName); + return typOid; +} + bool IsBinaryType(Oid typid) { if (u_sess->hook_cxt.isBinaryType != NULL) { diff --git a/contrib/dolphin/plugin_parser/parse_utilcmd.cpp b/contrib/dolphin/plugin_parser/parse_utilcmd.cpp index 3c0e29f9510215f72b0a79e97b283cc825a33435..4c66014d8b4eb46f002329cccbf0b5c88cd63ccc 100644 --- a/contrib/dolphin/plugin_parser/parse_utilcmd.cpp +++ b/contrib/dolphin/plugin_parser/parse_utilcmd.cpp @@ -319,8 +319,8 @@ Oid transform_default_collation(const char* collate, int charset, Oid def_coll_o } } else { coll_tup = t_thrd.lsc_cxt.FetchTupleFromCatCList(list, 0); -#ifndef DOLPHIN charset = ((Form_pg_collation)GETSTRUCT(coll_tup))->collencoding; +#ifndef DOLPHIN if (!is_attr && charset == PG_INVALID_ENCODING) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("collation \"%s\" have no corresponding encoding", collate))); diff --git a/contrib/dolphin/plugin_parser/parser.cpp b/contrib/dolphin/plugin_parser/parser.cpp index d1369a5bee3e53475957e725fcab54c0fa84f0bd..d99ba755662744dcf667615980916f22287bf0dc 100644 --- a/contrib/dolphin/plugin_parser/parser.cpp +++ b/contrib/dolphin/plugin_parser/parser.cpp @@ -413,6 +413,26 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner) break; } break; + case LOG_P: + /* + * For materialized view log, view log must be reduced to one token + */ + GET_NEXT_TOKEN(); + + switch (next_token) { + case ON: + cur_token = LOG_ON; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; case WITH: /* * WITH TIME must be reduced to one token @@ -826,30 +846,121 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner) break; } break; - case CURSOR: - GET_NEXT_TOKEN(); - core_yystype_1 = cur_yylval; // the value of cursor - cur_yylloc_1 = cur_yylloc; // the lloc of cursor - next_token_1 = next_token; // the token after curosr - GET_NEXT_TOKEN(); - core_yystype_2 = cur_yylval; // the value after cursor - cur_yylloc_2 = cur_yylloc; // the lloc after cursor - next_token_2 = next_token; // the token after after curosr - - if (next_token_1 == '(' && (is_select_stmt_definitely(next_token))) { - PARSE_CURSOR_PARENTHESES_AS_EXPR(); - } else if (is_prefer_parse_cursor_parentheses_as_expr() && !is_cursor_function_exist()) { - PARSE_CURSOR_PARENTHESES_AS_EXPR(); - } else { - PARSE_CURSOR_PARENTHESES_AS_FUNCTION(); - } - - if (t_thrd.proc->workingVersionNum < CURSOR_EXPRESSION_VERSION_NUMBER && - cur_token == CURSOR_EXPR) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Unsupported feature: cursor expression during the upgrade"))); - } - break; + case CURSOR: + GET_NEXT_TOKEN(); + core_yystype_1 = cur_yylval; // the value of cursor + cur_yylloc_1 = cur_yylloc; // the lloc of cursor + next_token_1 = next_token; // the token after curosr + if (next_token_1 != '(') { + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + } else { + GET_NEXT_TOKEN(); + core_yystype_2 = cur_yylval; // the value after cursor + cur_yylloc_2 = cur_yylloc; // the lloc after cursor + next_token_2 = next_token; // the token after after curosr + + if (next_token_1 == '(' && (is_select_stmt_definitely(next_token))) { + PARSE_CURSOR_PARENTHESES_AS_EXPR(); + } else if (is_prefer_parse_cursor_parentheses_as_expr() && !is_cursor_function_exist()) { + PARSE_CURSOR_PARENTHESES_AS_EXPR(); + } else { + PARSE_CURSOR_PARENTHESES_AS_FUNCTION(); + } + if (t_thrd.proc->workingVersionNum < CURSOR_EXPRESSION_VERSION_NUMBER && + cur_token == CURSOR_EXPR) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Unsupported feature: cursor expression during the upgrade"))); + } + } + break; + case STATIC_P: + GET_NEXT_TOKEN(); + switch (next_token) { + /* static function/procedure */ + case FUNCTION: + cur_token = STATIC_FUNCTION; + break; + case PROCEDURE: + cur_token = STATIC_PROCEDURE; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; + case MEMBER: + GET_NEXT_TOKEN(); + switch (next_token) { + /* MEMBER function/procedure */ + case FUNCTION: + cur_token = MEMBER_FUNCTION; + break; + case PROCEDURE: + cur_token = MEMBER_PROCEDURE; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; + case CONSTRUCTOR: + GET_NEXT_TOKEN(); + switch (next_token) { + /* MEMBER function/procedure */ + case FUNCTION: + cur_token = CONSTRUCTOR_FUNCTION; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; + case MAP: + GET_NEXT_TOKEN(); + switch (next_token) { + case MEMBER: + cur_token = MAP_MEMBER; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; + case SELF: + GET_NEXT_TOKEN(); + switch (next_token) { + case INOUT: + cur_token = SELF_INOUT; + break; + default: + /* save the lookahead token for next time */ + SET_LOOKAHEAD_TOKEN(); + /* and back up the output info to cur_token */ + lvalp->core_yystype = cur_yylval; + *llocp = cur_yylloc; + break; + } + break; #ifdef DOLPHIN case EXPLAIN: @@ -1254,7 +1365,9 @@ const struct ignore_keyword_opt_data ignore_keywords[] = { {"interval", INTERVAL}, {"binary_double_infinity", BINARY_DOUBLE_INF}, {"binary_double_nan", BINARY_DOUBLE_NAN}, - {"straight_join", STRAIGHT_JOIN} + {"straight_join", STRAIGHT_JOIN}, + {"binary", BINARY}, + {"prior", PRIOR} }; #define INGORE_KEYWORDS_LEN (sizeof(ignore_keywords) / sizeof(struct ignore_keyword_opt_data)) diff --git a/contrib/dolphin/plugin_parser/scan.l b/contrib/dolphin/plugin_parser/scan.l index eebb66ae6f23c4ad2ec0d5946421033f770869d9..b00493f2adf20d94fa1c9e1cf3a6efafa4dfd15e 100644 --- a/contrib/dolphin/plugin_parser/scan.l +++ b/contrib/dolphin/plugin_parser/scan.l @@ -1948,15 +1948,10 @@ handle_float_overflow(char *token, core_yyscan_t yyscanner) } errno = 0; - val = strtod(result, &endptr); - - // if val < 1E-130, we assume it is 0 - if (val != 0 && log10(val) < -130) { - result = "0"; - } else if (errno == ERANGE) { - if (val == 0.0) { - result = "0"; - } else { + val = strtod(result, &endptr); + + if (errno == ERANGE) { + if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL) { yyerror("number overflow"); } } diff --git a/contrib/dolphin/plugin_pl/plpgsql/src/gram.y b/contrib/dolphin/plugin_pl/plpgsql/src/gram.y index 5e010a5821c53ec42a408662fe2253049c8fba0d..c24e6194178db3733df91b91fea5b1b1a4299ccb 100644 --- a/contrib/dolphin/plugin_pl/plpgsql/src/gram.y +++ b/contrib/dolphin/plugin_pl/plpgsql/src/gram.y @@ -16,16 +16,19 @@ #include "utils/plpgsql_domain.h" #include "utils/plpgsql.h" +#include "access/transam.h" #include "access/xact.h" #include "access/tupconvert.h" #include "catalog/dependency.h" #include "catalog/gs_package.h" #include "catalog/gs_dependencies_fn.h" #include "catalog/namespace.h" +#include "catalog/pg_object.h" #include "catalog/pg_proc.h" #include "catalog/pg_synonym.h" #include "catalog/pg_type.h" #include "catalog/pg_type_fn.h" +#include "catalog/pg_object_type.h" #include "commands/typecmds.h" #include "funcapi.h" #include "nodes/makefuncs.h" @@ -138,7 +141,7 @@ static bool is_paren_friendly_datatype(TypeName *name); static void plpgsql_parser_funcname(const char *s, char **output, int numidents); static PLpgSQL_stmt *make_callfunc_stmt(const char *sqlstart, - int location, bool is_assign, bool eaten_first_token, List* funcNameList = NULL, int arrayFuncDno = -1, bool isCallFunc = false); + int location, bool is_assign, bool eaten_first_token, List* funcNameList = NULL, int arrayFuncDno = -1, bool isCallFunc = false, PLwdatum *objtypwdatum = NULL); static PLpgSQL_stmt *make_callfunc_stmt_no_arg(const char *sqlstart, int location, bool withsemicolon = false, List* funcNameList = NULL); static PLpgSQL_expr *read_sql_construct6(int until, int until2, @@ -240,14 +243,15 @@ static PLpgSQL_type* build_type_from_record_var(int dno, int location); static PLpgSQL_type * build_array_type_from_elemtype(PLpgSQL_type *elem_type); static PLpgSQL_var* plpgsql_build_nested_variable(PLpgSQL_var *nest_table, bool isconst, char* name, int lineno); static void read_multiset(StringInfoData* ds, char* tableName1, Oid typeOid1); -static Oid get_table_type(PLpgSQL_datum* datum); -static void read_multiset(StringInfoData* ds, char* tableName1, Oid typeOid1); +static void CastTypeVariableNameToString(StringInfoData* ds, List* idents, bool needDot = true); static Oid get_table_type(PLpgSQL_datum* datum); static Node* make_columnDef_from_attr(PLpgSQL_rec_attr* attr); static TypeName* make_typename_from_datatype(PLpgSQL_type* datatype); static Oid plpgsql_build_package_record_type(const char* typname, List* list, bool add2namespace); static void plpgsql_build_package_array_type(const char* typname, Oid elemtypoid, char arraytype, TypeDependExtend* dependExtend = NULL); static void plpgsql_build_package_refcursor_type(const char* typname); +static Oid plpgsql_build_anonymous_subtype(char* typname, PLpgSQL_type* newp, const List* RangeList, bool isNotNull); +static Oid plpgsql_build_function_package_subtype(char* typname, PLpgSQL_type* newp, const List* RangeList, bool isNotNull); int plpgsql_yylex_single(void); static void get_datum_tok_type(PLpgSQL_datum* target, int* tok_flag); static bool copy_table_var_indents(char* tableName, char* idents, int tablevar_namelen); @@ -274,6 +278,14 @@ static void check_record_nest_tableof_index(PLpgSQL_datum* datum); static void check_tableofindex_args(int tableof_var_dno, Oid argtype); static bool need_build_row_for_func_arg(PLpgSQL_rec **rec, PLpgSQL_row **row, int out_arg_num, int all_arg, int *varnos, char *p_argmodes); static void processFunctionRecordOutParam(int varno, Oid funcoid, int* outparam); +static void yylex_object_type_selfparam(char** fieldnames, + int *varnos, + int nfields, + PLpgSQL_row **row, + PLpgSQL_rec **rec, + int *retvarno, + PLwdatum *objtypwdatum, + bool overload = false); static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch); %} @@ -363,10 +375,10 @@ static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch); %type decl_sect %type declare_sect_b %type decl_varname declare_condname -%type decl_varname_list +%type decl_varname_list opt_subtype_range %type decl_const decl_notnull exit_type %type decl_defval decl_rec_defval decl_cursor_query -%type decl_datatype opt_cursor_returntype +%type decl_datatype opt_cursor_returntype subtype_base_type %type decl_collate %type decl_cursor_args %type decl_cursor_arglist assign_list @@ -417,6 +429,7 @@ static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch); %type varray_var %type table_var %type record_var +%type subtype_base_collect_type %type expr_until_parenthesis %type opt_scrollable %type opt_fetch_direction @@ -453,7 +466,7 @@ static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch); %token T_PLACEHOLDER /* place holder , for IN/OUT parameters */ %token T_LABELLOOP T_LABELWHILE T_LABELREPEAT %token T_VARRAY T_ARRAY_FIRST T_ARRAY_LAST T_ARRAY_COUNT T_ARRAY_EXISTS T_ARRAY_PRIOR T_ARRAY_NEXT T_ARRAY_DELETE T_ARRAY_EXTEND T_ARRAY_TRIM T_VARRAY_VAR T_RECORD -%token T_TABLE T_TABLE_VAR T_PACKAGE_VARIABLE +%token T_TABLE T_TABLE_VAR T_PACKAGE_VARIABLE T_OBJECT_TYPE_VAR_METHOD %token T_PACKAGE_CURSOR_ISOPEN T_PACKAGE_CURSOR_FOUND T_PACKAGE_CURSOR_NOTFOUND T_PACKAGE_CURSOR_ROWCOUNT %token LESS_LESS %token GREATER_GREATER @@ -615,6 +628,7 @@ static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch); %token K_STACKED %token K_STRICT %token K_SUBCLASS_ORIGIN +%token K_SUBTYPE %token K_SYS_REFCURSOR %token K_TABLE %token K_TABLE_NAME @@ -1346,7 +1360,9 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no if (var->dtype == PLPGSQL_DTYPE_VAR) ((PLpgSQL_var *) var)->default_val = $6; else if (var->dtype == PLPGSQL_DTYPE_ROW || var->dtype == PLPGSQL_DTYPE_RECORD) { - ((PLpgSQL_row *) var)->default_val = $6; + PLpgSQL_row * row = (PLpgSQL_row *) var; + if (!(row->atomically_null_object && pg_strcasecmp($6->query, "select null") == 0)) + row->default_val = $6; } else if (var->dtype == PLPGSQL_DTYPE_CURSORROW) { ((PLpgSQL_rec *) var)->default_val = $6; } @@ -2106,8 +2122,123 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no u_sess->plsql_cxt.have_error = true; } } + | K_SUBTYPE decl_varname K_IS subtype_base_type decl_notnull ';' + { + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("SUBTYPE is only supported in database which dbcompatibility='A'"))); + } + IsInPublicNamespace($2->name); + PLpgSQL_type *newp = $4; + Oid newtypeoid = InvalidOid; + + if (PLPGSQL_TTYPE_ROW == newp->ttype) { + /* handle when basetype is ROW */ + plpgsql_build_synonym($2->name, newp->typname); + } else if (F_ARRAY_IN == newp->typinput.fn_oid) { + /* collection handle in next project */ + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmodule(MOD_PLSQL), + errmsg("array or table type nested by table type is not supported yet."), + errdetail("Define table type \"%s\" of array or table type is not supported yet.", $2->name), + errcause("feature not supported"), + erraction("check define of table type"))); + u_sess->plsql_cxt.have_error = true; + } else { + /* basstype is not a row, build subtype, save constraint in plsql cache */ + if (IS_ANONYMOUS_BLOCK) { + newtypeoid = plpgsql_build_anonymous_subtype($2->name, newp, NULL, $5); + } else { + newtypeoid = plpgsql_build_function_package_subtype($2->name, newp, NULL, $5); + } + + pfree_ext($2->name); + pfree_ext($2); + } + } + | K_SUBTYPE decl_varname K_IS record_var ';' + { + /* copy all params if basetype is record, build a new record */ + List* attr_list = NIL; + PLpgSQL_type* newp = (PLpgSQL_type*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$4]; + PLpgSQL_rec_type* old = (PLpgSQL_rec_type*)newp; + for (int i = 0; i < old->attrnum; i++) { + PLpgSQL_rec_attr* attr = (PLpgSQL_rec_attr*)palloc0(sizeof(PLpgSQL_rec_attr)); + attr->attrname = pstrdup(old->attrnames[i]); + attr->type = old->types[i]; + attr->notnull = old->notnulls[i]; + attr->defaultvalue = old->defaultvalues[i]; + attr_list = lappend(attr_list, attr); + } + if (attr_list == NIL) { + elog(errstate, "Execption when defining subtype"); + u_sess->plsql_cxt.have_error = true; + } + PLpgSQL_rec_type* rec = NULL; + rec = plpgsql_build_rec_type($2->name, $2->lineno, attr_list, true); + if (IS_PACKAGE) { + rec->typoid = plpgsql_build_package_record_type($2->name, attr_list, true); + } else if (enable_plpgsql_gsdependency()){ + ListCell* cell = NULL; + foreach(cell, attr_list) { + gsplsql_build_gs_type_in_body_dependency(((PLpgSQL_rec_attr*)lfirst(cell))->type); + } + } + list_free_deep(attr_list); + } + | K_SUBTYPE decl_varname K_IS subtype_base_collect_type ';' + { + /* SUBTYPE basse type is table/varray type */ + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT){ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("SUBTYPE is only supported in database which dbcompatibility='A'"))); + } + IsInPublicNamespace($2->name); + PLpgSQL_var *arrarytype = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$4]; + PLpgSQL_type *newp = arrarytype->datatype; + plpgsql_build_varrayType($2->name, $2->lineno, newp, true); + if (IS_PACKAGE) { + plpgsql_build_package_array_type($2->name, newp->typoid, TYPCATEGORY_ARRAY, newp->dependExtend); + } else if (enable_plpgsql_gsdependency()) { + gsplsql_build_gs_type_in_body_dependency(newp); + } + pfree_ext($2->name); + pfree_ext($2); + } + ; + +subtype_base_type: T_REFCURSOR + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmodule(MOD_PLSQL), + errmsg("ref cursor type nested by record is not supported yet."), + errdetail("Define record type of ref cursor type is not supported yet."), + errcause("feature not supported"), + erraction("check define of record type"))); + u_sess->plsql_cxt.have_error = true; + } + | decl_datatype + { + $$ = $1; + } ; +subtype_base_collect_type: + varray_var + { + $$ = $1; + } + | table_var + { + $$ = $1; + } + ; + + error_code : ICONST { $$ = $1; @@ -2129,6 +2260,8 @@ init_proc : yyclearin; } +opt_subtype_range : + { $$ = NIL; }; record_attr_list : record_attr { @@ -2259,6 +2392,15 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval attr->attrname = $1; PLpgSQL_type *var_type = ((PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$2])->datatype; + PLpgSQL_var *varray_type = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$2]; + + if (varray_type->nest_table != NULL) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("nested table of type is not supported as record type attribute"), + parser_errposition(@3))); + u_sess->plsql_cxt.have_error = true; + } PLpgSQL_type *new_var_type = build_array_type_from_elemtype(var_type); new_var_type->collectionType = var_type->collectionType; new_var_type->tableOfIndexType = var_type->tableOfIndexType; @@ -2287,7 +2429,7 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval $$ = attr; } - | attr_name table_var decl_notnull decl_rec_defval + | attr_name table_var decl_notnull decl_rec_defval { PLpgSQL_rec_attr *attr = NULL; @@ -2883,7 +3025,7 @@ stmt_perform : K_PERFORM {u_sess->parser_cxt.isPerform = true;} expr_until_semi } ; -stmt_assign : assign_var assign_operator expr_until_semi +stmt_assign : assign_var assign_operator {GetSessionContext()->is_set_stmt = true;} expr_until_semi { PLpgSQL_stmt_assign *newp; @@ -2891,8 +3033,9 @@ stmt_assign : assign_var assign_operator expr_until_semi newp->cmd_type = PLPGSQL_STMT_ASSIGN; newp->lineno = plpgsql_location_to_lineno(@1); newp->varno = $1; - newp->expr = $3; + newp->expr = $4; newp->sqlString = plpgsql_get_curline_query(); + GetSessionContext()->is_set_stmt = false; $$ = (PLpgSQL_stmt *)newp; } @@ -3113,6 +3256,10 @@ getdiag_item : K_ROW_COUNT { $$ = PLPGSQL_GETDIAG_ERROR_CONTEXT; } + | K_PG_EXCEPTION_HINT + { + $$ = PLPGSQL_GETDIAG_ERROR_HINT; + } | K_MESSAGE_TEXT { $$ = PLPGSQL_GETDIAG_MESSAGE_TEXT; @@ -5327,6 +5474,67 @@ stmt_execsql : K_ALTER yyerror("syntax error"); } } + | T_OBJECT_TYPE_VAR_METHOD + { + int tok = -1; + bool FuncNoarg = false; + char* serverName = NULL; + PLwdatum *objtypwdatum = NULL; + PLwdatum objtypwdatumtemp; + objtypwdatumtemp.datum = yylval.wdatum.datum; + objtypwdatumtemp.idents = yylval.wdatum.idents; + objtypwdatumtemp.quoted = yylval.wdatum.quoted; + objtypwdatumtemp.ident = yylval.wdatum.ident; + objtypwdatumtemp.dno = yylval.wdatum.dno; + objtypwdatum = &objtypwdatumtemp; + PLpgSQL_row* row = (PLpgSQL_row*)yylval.wdatum.datum; + HeapTuple typtuple = NULL; + Form_pg_type typeform = NULL; + char* nspname = NULL; + StringInfoData ds; + char* name = NULL; + bool isCallFunc = false; + + initStringInfo(&ds); + typtuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(row->datatype->typoid)); + if (!HeapTupleIsValid(typtuple)) + ereport(errstate, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object type with OID %u does not exist", row->datatype->typoid))); + typeform = (Form_pg_type)GETSTRUCT(typtuple); + nspname = get_namespace_name(typeform->typnamespace); + if (NULL != nspname) { + appendStringInfo(&ds, "%s.",nspname); + } + appendStringInfo(&ds, "%s",objtypwdatumtemp.ident); + ReleaseSysCache(typtuple); + name = pstrdup(ds.data); + pfree_ext(ds.data); + + tok = yylex(); + if ('(' == tok) + isCallFunc = is_function(name, false, false); + else if (';' == tok) { + isCallFunc = is_function(name, false, false); + FuncNoarg = true; + } + plpgsql_push_back_token(tok); + if (isCallFunc) { + if (FuncNoarg) { + $$ = make_callfunc_stmt_no_arg(name, @1); + } else { + PLpgSQL_stmt* stmt = make_callfunc_stmt(name, @1, false, false, NULL, -1, false, objtypwdatum); + if (stmt->cmd_type == PLPGSQL_STMT_PERFORM) { + ((PLpgSQL_stmt_perform*)stmt)->expr->is_funccall = true; + } else if (stmt->cmd_type == PLPGSQL_STMT_EXECSQL) { + ((PLpgSQL_stmt_execsql*)stmt)->sqlstmt->is_funccall = true; + } + $$ = stmt; + } + } else { + $$ = make_execsql_stmt(T_OBJECT_TYPE_VAR_METHOD, @1); + } + } | T_CWORD '(' { @@ -6402,6 +6610,8 @@ expr_until_semi : bool isCallFunc = false; PLpgSQL_expr* expr = NULL; List* funcNameList = NULL; + PLwdatum *objtypwdatum = NULL; + PLwdatum objtypwdatumtemp; if (!enable_out_param_override() && u_sess->parser_cxt.isPerform) { u_sess->parser_cxt.isPerform = false; } @@ -6427,14 +6637,44 @@ expr_until_semi : (errcode(ERRCODE_SYNTAX_ERROR), errmsg("perform not support expression when open guc proc_outparam_override"))); u_sess->plsql_cxt.have_error = true; + } else if (plpgsql_is_token_match2(T_OBJECT_TYPE_VAR_METHOD,'(')) { + PLpgSQL_row *row = NULL; + HeapTuple typtuple = NULL; + Form_pg_type typeform = NULL; + char* nspname = NULL; + StringInfoData ds; + tok = yylex(); + objtypwdatumtemp.datum = yylval.wdatum.datum; + objtypwdatumtemp.idents = yylval.wdatum.idents; + objtypwdatumtemp.quoted = yylval.wdatum.quoted; + objtypwdatumtemp.ident = yylval.wdatum.ident; + objtypwdatumtemp.dno = yylval.wdatum.dno; + objtypwdatum = &objtypwdatumtemp; + initStringInfo(&ds); + row = (PLpgSQL_row*)yylval.wdatum.datum; + typtuple = SearchSysCache1(TYPEOID,ObjectIdGetDatum(row->datatype->typoid)); + if (!HeapTupleIsValid(typtuple)) + ereport(errstate, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("object type with OID %u does not exist", row->datatype->typoid))); + typeform = (Form_pg_type)GETSTRUCT(typtuple); + nspname = get_namespace_name(typeform->typnamespace); + if (NULL != nspname) { + appendStringInfo(&ds, "%s.",nspname); + } + appendStringInfo(&ds, "%s",objtypwdatumtemp.ident); + ReleaseSysCache(typtuple); + name = pstrdup(ds.data); + pfree_ext(ds.data); + isCallFunc = is_function(name, true, false); } if (isCallFunc || (enable_out_param_override() && u_sess->parser_cxt.isPerform)) { if (u_sess->parser_cxt.isPerform) { - stmt = make_callfunc_stmt(name, yylloc, false, false, funcNameList, -1, true); + stmt = make_callfunc_stmt(name, yylloc, false, false, funcNameList, -1, true, objtypwdatum); } else { - stmt = make_callfunc_stmt(name, yylloc, true, false, funcNameList, -1, isCallFunc); + stmt = make_callfunc_stmt(name, yylloc, true, false, funcNameList, -1, isCallFunc, objtypwdatum); } if (u_sess->parser_cxt.isPerform) { u_sess->parser_cxt.stmt = (void*)stmt; @@ -6461,7 +6701,12 @@ expr_until_semi : plpgsql_pkg_add_unknown_var_to_namespace(wholeName); } } - expr = read_sql_expression(';', ";"); + if (GetSessionContext()->is_set_stmt) { + int tok1; + expr = read_sql_expression2(',', ';', ", or ;", &tok1); + } else { + expr = read_sql_expression(';', ";"); + } #ifndef ENABLE_MULTIPLE_NODES if (enable_out_param_override() && PLSQL_COMPILE_OUTPARAM && !IsInitdb && IsNormalProcessingMode()) { @@ -7171,7 +7416,7 @@ static int get_func_out_arg_num(char* p_argmodes, int all_arg) * Notes : */ static PLpgSQL_stmt * -make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eaten_first_token, List* funcNameList, int arrayFuncDno, bool isCallFunc) +make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eaten_first_token, List* funcNameList, int arrayFuncDno, bool isCallFunc, PLwdatum *objtypwdatum) { int nparams = 0; int nfields = 0; @@ -7328,7 +7573,9 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate InsertErrorMessage(message, plpgsql_yylloc); ereport(errstate, (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function \"%s\" isn't exclusive ", sqlstart))); + errmsg("function \"%s\" isn't exclusive ", sqlstart), + errdetail("The overload function must be package function or function with PACKAGE keyword.And do not mix overload functions of O style and PG style."), + errcause("The overload function must be package function."))); } } @@ -7375,14 +7622,18 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate * if eaten_first_token is true,first token is '(' ,so if next token is ')',it means * no args */ - if (eaten_first_token==true) { - if (tok == ')') - noargs = TRUE; + if (NULL != objtypwdatum) { + noargs = false; } else { - if ((tok = yylex()) == ')') - noargs = TRUE; + if (eaten_first_token==true) { + if (tok == ')') + noargs = TRUE; + } else { + if ((tok = yylex()) == ')') + noargs = TRUE; + } + plpgsql_push_back_token(tok); } - plpgsql_push_back_token(tok); if (isCallFunc && is_function_with_plpgsql_language_and_outparam(clist->oid)) { is_assign = false; @@ -7438,7 +7689,24 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate if (plpgsql_is_token_match2(T_DATUM, PARA_EQUALS) || plpgsql_is_token_match2(T_WORD, PARA_EQUALS)) { - + int varno = -1; + /*For objtype.member methods, explicit add a self parameter*/ + if (0 == i && NULL != objtypwdatum) { + if ('b' == p_argmodes[i]) { + nfields++; + pos_outer++; + yylex_object_type_selfparam(fieldnames, varnos, pos_outer, &row, &rec, &varno, objtypwdatum); + processFunctionRecordOutParam(varno, clist->oid, &out_param_dno); + } + CastTypeVariableNameToString(&func_inparas, objtypwdatum->idents, false); + nparams++; + i++; + if ((tok = yylex()) == ')') { + break; + } + plpgsql_push_back_token(tok); + j = 1; + } tok = yylex(); if (T_DATUM == tok) appendStringInfoString(&argname, NameOfDatum(&yylval.wdatum)); @@ -7460,7 +7728,6 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate * if argmodes is 'i', just append the text, else, * row or rec should be assigned to store the out arg values */ - int varno = -1; switch (p_argmodes[j]) { case 'i': @@ -7541,8 +7808,25 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate } else { - tok = yylex(); int varno = -1; + /*For objtype.member methods, explicit add a self parameter*/ + if (0 == i && NULL != objtypwdatum) { + if ('b' == p_argmodes[i]) { + nfields++; + pos_outer++; + yylex_object_type_selfparam(fieldnames, varnos, pos_outer, &row, &rec, &varno, objtypwdatum); + processFunctionRecordOutParam(varno, clist->oid, &out_param_dno); + } + CastTypeVariableNameToString(&func_inparas, objtypwdatum->idents, false); + nparams++; + if ((tok = yylex()) == ')') { + i++; + break; + } + plpgsql_push_back_token(tok); + continue; + } + tok = yylex(); /* p_argmodes may be null, 'i'->in , 'o'-> out ,'b' inout,others error */ switch (p_argmodes[i]) { @@ -7665,6 +7949,17 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate { for ( i = 0; i < narg; i++) { + /*For objtype.member methods, explicit add a self parameter*/ + if (0 == i && NULL != objtypwdatum) { + CastTypeVariableNameToString(&func_inparas, objtypwdatum->idents, false); + nparams++; + if ((tok = yylex()) == ')') { + i++; + break; + } + plpgsql_push_back_token(tok); + continue; + } tok = yylex(); if (T_PLACEHOLDER == tok) placeholders++; @@ -7693,6 +7988,19 @@ make_callfunc_stmt(const char *sqlstart, int location, bool is_assign, bool eate while (true) { int varno = -1; + if (0 == nfields && NULL != objtypwdatum) { + CastTypeVariableNameToString(&func_inparas, objtypwdatum->idents, false); + yylex_object_type_selfparam(fieldnames, varnos, pos_outer, &row, &rec, &varno, objtypwdatum); + namedarg[nfields] = false; + namedargnamses[nfields] = NULL; + nparams++; + nfields++; + if ((tok = yylex()) == ')') { + break; + } + plpgsql_push_back_token(tok); + continue; + } /* for named arguemnt */ if (plpgsql_is_token_match2(T_DATUM, PARA_EQUALS) || plpgsql_is_token_match2(T_WORD, PARA_EQUALS)) @@ -8155,6 +8463,9 @@ is_function(const char *name, bool is_assign, bool no_parenthesis, List* funcNam int narg = 0; int i = 0; char *cp[3] = {0}; + bool isNull = false; + Datum typeIdDatum = InvalidOid; + char typMethodKind = OBJECTTYPE_NULL_PROC; /* the function is_function is only to judge if it's a function call, so memory used in it is all temp */ AutoContextSwitch plCompileCxtGuard(u_sess->plsql_cxt.curr_compile_context->compile_tmp_cxt); @@ -8233,6 +8544,18 @@ is_function(const char *name, bool is_assign, bool no_parenthesis, List* funcNam } return false; } + bool ispackage = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_package, &isNull); + typeIdDatum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_packageid, &isNull); + /*Find method type from pg_object*/ + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(clist->oid), CharGetDatum(OBJECT_TYPE_PROC)); + if (HeapTupleIsValid(objTuple)) { + typMethodKind = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isNull)); + ReleaseSysCache(objTuple); + } + if (!isNull && !ispackage && OidIsValid(ObjectIdGetDatum(typeIdDatum)) && (typMethodKind == OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC || typMethodKind == OBJECTTYPE_CONSTRUCTOR_PROC)) { + ReleaseSysCache(proctup); + return false; + } /* get the all args informations, only "in" parameters if p_argmodes is null */ narg = get_func_arg_info(proctup,&p_argtypes, &p_argnames, &p_argmodes); @@ -8301,7 +8624,18 @@ is_function(const char *name, bool is_assign, bool no_parenthesis, List* funcNam } return false; } - + bool ispackage = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_package, &isNull); + typeIdDatum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_packageid, &isNull); + /*Find method type from pg_object*/ + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(clist->oid), CharGetDatum(OBJECT_TYPE_PROC)); + if (HeapTupleIsValid(objTuple)) { + typMethodKind = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isNull)); + ReleaseSysCache(objTuple); + } + if (!isNull && !ispackage && OidIsValid(ObjectIdGetDatum(typeIdDatum)) && (typMethodKind == OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC || typMethodKind == OBJECTTYPE_CONSTRUCTOR_PROC)) { + ReleaseSysCache(proctup); + return false; + } /* get the all args informations, only "in" parameters if p_argmodes is null */ narg = get_func_arg_info(proctup,&p_argtypes, &p_argnames, &p_argmodes); if (p_argmodes) @@ -8577,14 +8911,18 @@ static bool construct_object_type(StringInfo ds, ArrayParseContext *context, Typ return true; } PLpgSQL_type *type = parse_datatype(name_str, loc);\ - pfree_ext(name_str); type = get_real_elemtype(type); if (type->collectionType == PLPGSQL_COLLECTION_ARRAY || \ type->collectionType == PLPGSQL_COLLECTION_TABLE) { + pfree_ext(name_str); return construct_array_start(ds, context, type, tok, parenlevel, loc); } - appendStringInfoString(ds, "ROW"); + if (type->typtyp == TYPTYPE_ABSTRACT_OBJECT) + appendStringInfo(ds, name_str); + else + appendStringInfo(ds, "ROW"); + pfree_ext(name_str); return true; } @@ -8767,6 +9105,11 @@ read_sql_construct6(int until, int loc = 0; int curloc = 0; int brack_cnt = 0; + int nest_layers = 0; + int left_brace_count = 0; + int right_brace_count = 0; + bool stop_count = false; + int stop_tok; /* mark if there are 2 table of index by var call functions in an expr */ int tableof_func_dno = -1; int tableof_var_dno = -1; @@ -8795,6 +9138,14 @@ read_sql_construct6(int until, { prev_tok = tok; tok = yylex(); + if (tok == '\"' || tok == '\'') { + if (stop_count && stop_tok == tok) { + stop_count = false; + } else { + stop_count = true; + stop_tok = tok; + } + } tokenstack = push_token_stack(tok, tokenstack); loc = yylloc; if (startlocation < 0) /* remember loc of first token */ @@ -8902,13 +9253,18 @@ read_sql_construct6(int until, ds_changed = true; break; case T_VARRAY_VAR: + { idents = yylval.wdatum.idents; + PLpgSQL_var* var = (PLpgSQL_var*)(yylval.wdatum.datum); if (idents == NIL) { AddNamespaceIfPkgVar(yylval.wdatum.ident, save_IdentifierLookup); } tok = yylex(); if (tok == '(' || tok == '[') { push_array_parse_stack(&context, parenlevel, ARRAY_ACCESS); + } else if (OidIsValid(var->datatype->tableOfIndexType) && + (',' == tok || ')' == tok || ';' == tok)) { + is_have_tableof_index_var = true; } curloc = yylloc; plpgsql_push_back_token(tok); @@ -8921,6 +9277,7 @@ read_sql_construct6(int until, ds_changed = true; break; } + } case T_ARRAY_FIRST: { Oid indexType = get_table_index_type(yylval.wdatum.datum, &tableof_func_dno); @@ -9085,6 +9442,8 @@ read_sql_construct6(int until, brack_cnt--; /* fall through */ case ')': + if (!stop_count) + right_brace_count++; if (context.list_right_bracket && context.list_right_bracket->length && linitial_int(context.list_right_bracket) == parenlevel) { /* append bracket instead of parentheses */ @@ -9142,6 +9501,8 @@ read_sql_construct6(int until, brack_cnt++; /* fall through */ case '(': + if (!stop_count) + left_brace_count++; if (context.list_left_bracket && context.list_left_bracket->length && linitial_int(context.list_left_bracket) == parenlevel - 1) { appendStringInfoString(&ds, left_bracket); @@ -9353,6 +9714,10 @@ read_sql_construct6(int until, yylval = temptokendata->lval; u_sess->plsql_cxt.curr_compile_context->plpgsql_yyleng = temptokendata->leng; } + if (left_brace_count == 0) + { + nest_layers = var->nest_layers; + } ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc); break; } @@ -9374,22 +9739,35 @@ read_sql_construct6(int until, } int dno = yylval.wdatum.datum->dno; PLpgSQL_var *var = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[dno]; + if (left_brace_count == 0) + { + nest_layers = var->nest_layers; + } ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc); break; } case T_DATUM: - idents = yylval.wdatum.idents; - if(prev_tok != '.' && list_length(idents) >= 3) { - plpgsql_cast_reference_list(idents, &ds, false); - ds_changed = true; - break; - } else { - tok = yylex(); - curloc = yylloc; - plpgsql_push_back_token(tok); - plpgsql_append_source_text(&ds, loc, curloc); - ds_changed = true; - break; + { + idents = yylval.wdatum.idents; + int dno = yylval.wdatum.datum->dno; + PLpgSQL_datum *datum = (PLpgSQL_datum *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[dno]; + if (datum->dtype == PLPGSQL_DTYPE_RECFIELD) { + PLpgSQL_recfield *rec_field = (PLpgSQL_recfield *)datum; + PLpgSQL_rec *rec = (PLpgSQL_rec *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[rec_field->recparentno]; + rec->field_need_check = lappend_int(rec->field_need_check, dno); + } + if(prev_tok != '.' && list_length(idents) >= 3) { + plpgsql_cast_reference_list(idents, &ds, false); + ds_changed = true; + break; + } else { + tok = yylex(); + curloc = yylloc; + plpgsql_push_back_token(tok); + plpgsql_append_source_text(&ds, loc, curloc); + ds_changed = true; + break; + } } case T_WORD: AddNamespaceIfPkgVar(yylval.word.ident, save_IdentifierLookup); @@ -9398,6 +9776,33 @@ read_sql_construct6(int until, case T_CWORD: ds_changed = construct_cword(&ds, &context, &tok, parenlevel, loc); break; + case T_OBJECT_TYPE_VAR_METHOD: + { + appendStringInfo(&ds, " %s(", yylval.wdatum.ident); + CastTypeVariableNameToString(&ds, yylval.wdatum.idents, false); + ds_changed = true; + + parenlevel++; + // Look ahead for another token to specify var.method format + tok = yylex(); + if ('(' == tok) { + int tok1 = yylex(); + /*if var.method()*/ + if (tok1 == ')') { + appendStringInfo(&ds, ")"); + parenlevel--; + } else { /* method with parameters*/ + appendStringInfo(&ds, ","); + plpgsql_push_back_token(tok1); + } + } else { + /*var.method*/ + appendStringInfo(&ds, ")"); + parenlevel--; + plpgsql_push_back_token(tok); + } + } + break; default: tok = yylex(); @@ -9442,7 +9847,9 @@ read_sql_construct6(int until, if (IS_ARRAY_STATE(context.list_array_state, ARRAY_COERCE)) { /* always append right parentheses at end of each element */ appendStringInfoString(&ds, right_parentheses); - plpgsql_append_object_typename(&ds, (PLpgSQL_type *)linitial(context.list_datatype)); + if ((left_brace_count - right_brace_count) > nest_layers) { + plpgsql_append_object_typename(&ds, (PLpgSQL_type *)linitial(context.list_datatype)); + } SET_ARRAY_STATE(context.list_array_state, ARRAY_SEPERATOR); } } @@ -9616,6 +10023,35 @@ static void read_multiset(StringInfoData* ds, char* tableName1, Oid typeOid1) appendStringInfoString(ds, funcName); } +static void CastTypeVariableNameToString(StringInfoData* ds, List* idents, bool needDot) +{ + char* name1 = NULL; + char* name2 = NULL; + + switch (list_length(idents)) { + case 1: + /* object type var */ + name1 = strVal(linitial(idents)); + appendStringInfo(ds, "%s", name1); + break; + case 2: + /* package.var */ + name1 = strVal(linitial(idents)); + name2 = strVal(lsecond(idents)); + appendStringInfo(ds,"%s.%s", name1, name2); + break; + default: + yyerror("syntax error of array functions"); + break; + } + + if (needDot) { + appendStringInfo(ds, ", "); + } else { + appendStringInfo(ds, " "); + } +} + static bool copy_table_var_indents(char* tableName, char* idents, int tablevar_namelen) { List* namelist = NIL; @@ -12567,36 +13003,6 @@ static int get_nest_tableof_layer(PLpgSQL_var *var, const char *typname, int err return depth + 1; } -static void getPkgFuncTypeName(char* typname, char** functypname, char** pkgtypname) -{ - if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile != NULL) { - *functypname = CastPackageTypeName(typname, - u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_oid, false); - if (strlen(*functypname) >= NAMEDATALEN) { - const char* message = "record name too long"; - InsertErrorMessage(message, plpgsql_yylloc, true); - ereport(ERROR, - (errcode(ERRCODE_NAME_TOO_LONG), - errmsg("type name too long"), - errdetail("record name %s with func oid %d should be less the %d letters.", - typname, u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_oid, NAMEDATALEN))); - } - } - if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package != NULL) { - *pkgtypname = CastPackageTypeName(typname, - u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid, true); - if (strlen(*pkgtypname) >= NAMEDATALEN) { - const char* message = "record name too long"; - InsertErrorMessage(message, plpgsql_yylloc, true); - ereport(ERROR, - (errcode(ERRCODE_NAME_TOO_LONG), - errmsg("type name too long"), - errdetail("record name %s with package name %s should be less the %d letters.", - typname, u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_signature, NAMEDATALEN))); - } - } -} - /* * look up composite type from namespace */ @@ -13079,10 +13485,15 @@ static void plpgsql_build_package_array_type(const char* typname,Oid elemtypoid if (arraytype == TYPCATEGORY_TABLEOF || arraytype == TYPCATEGORY_TABLEOF_VARCHAR || arraytype == TYPCATEGORY_TABLEOF_INTEGER) { + typtyp = TYPTYPE_TABLEOF; + if (UNDEFINEDOID != elemtypoid) { + elemtypoid = get_array_type(elemtypoid); + } + } else if (arraytype == TYPCATEGORY_VARRAY) { + typtyp = TYPTYPE_VARRAY; if (UNDEFINEDOID != elemtypoid) { elemtypoid = get_array_type(elemtypoid); } - typtyp = TYPTYPE_TABLEOF; } else { typtyp = TYPTYPE_BASE; } @@ -13094,13 +13505,13 @@ static void plpgsql_build_package_array_type(const char* typname,Oid elemtypoid referenced = TypeCreate(InvalidOid, /* force the type's OID to this */ casttypename, /* Array type name */ - pkgNamespaceOid, /* Same namespace as parent */ + pkgNamespaceOid, /* Same namespace as parent */ InvalidOid, /* Not composite, no relationOid */ 0, /* relkind, also N/A here */ ownerId, /* owner's ID */ -1, /* Internal size (varlena) */ - typtyp, /* Not composite - typelem is */ - arraytype, /* type-category (array or table of) */ + typtyp, /* Not composite - typelem is */ + arraytype, /* type-category (array or table of) */ false, /* array types are never preferred */ DEFAULT_TYPDELIM, /* default array delimiter */ F_ARRAY_IN, /* array input proc */ @@ -13110,7 +13521,7 @@ static void plpgsql_build_package_array_type(const char* typname,Oid elemtypoid InvalidOid, /* typmodin procedure - none */ InvalidOid, /* typmodout procedure - none */ F_ARRAY_TYPANALYZE, /* array analyze procedure */ - elemtypoid, /* array element type - the rowtype */ + elemtypoid, /* array element type - the rowtype */ false, /* yes, this is an array type */ InvalidOid, /* this has no array type */ InvalidOid, /* domain base type - irrelevant */ @@ -13254,6 +13665,293 @@ static TypeName* make_typename_from_datatype(PLpgSQL_type* datatype) return makeTypeNameFromOid(datatype->typoid, datatype->atttypmod, datatype->dependExtend); } +/* + * build SUBTYPE in ANONYMOUS_BLOCK + * typname : name of subtype to be create + * newp : base type info + * RangeList : unsuport in opengauss util now, use to supprt type like pls_interge + * isNotNull : is not null + */ +static Oid plpgsql_build_anonymous_subtype(char* typname, PLpgSQL_type* newp, const List* RangeList, bool isNotNull) +{ + /* some variable */ + Oid NamespaceOid = InvalidOid; + Oid ownerId = InvalidOid; + Oid newtypeoid = InvalidOid; + HeapTuple baseTypeTup; + Form_pg_type baseType; + ObjectAddress referenced; + PLpgSQL_type* res = NULL; + SubTypeRange* typerange = NULL; + + /* check is typname too long */ + if (strlen(typname) >= NAMEDATALEN) { + ereport(errstate, + (errcode(ERRCODE_NAME_TOO_LONG), + errmsg("type name too long"))); + u_sess->plsql_cxt.have_error = true; + } + + if (!OidIsValid(NamespaceOid)) { + NamespaceOid = getCurrentNamespace(); + } + + /* check for duplicate name */ + Oid oldtypeoid = GetSysCacheOid2(TYPENAMENSP, PointerGetDatum(typname), ObjectIdGetDatum(NamespaceOid)); + if (OidIsValid(oldtypeoid)) { + ereport(errstate, + (errmodule(MOD_PLSQL), + errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("duplicate type name"), + errdetail("type name of \"%s\" duplicated with an existed type when build subtype.", typname), + errcause("duplicate type name"), + erraction("modify subtype name"))); + u_sess->plsql_cxt.have_error = true; + } + + ownerId = GetUserIdFromNspId(NamespaceOid); + if (!OidIsValid(ownerId)) { + ownerId = GetUserId(); + } + + baseTypeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(newp->typoid), 0, 0, 0 ); + baseType = (Form_pg_type)GETSTRUCT(baseTypeTup); + /* refer DOMAIN */ + referenced = TypeCreate(InvalidOid, /* force the type's OID to this */ + typname, /* Array type name */ + NamespaceOid, /* Same namespace as parent */ + InvalidOid, /* Not composite, no relationOid */ + 0, /* relkind, also N/A here */ + ownerId, /* owner's ID */ + baseType->typlen, /* Internal size (varlena) */ + TYPTYPE_DOMAIN, /* Not composite - typelem is */ + baseType->typcategory, /* type-category (array or table of) */ + false, /* array types are never preferred */ + baseType->typdelim, /* default array delimiter */ + F_SUBTYPE_IN, /* input proc */ + baseType->typoutput, /* output proc */ + F_SUBTYPE_RECV, /* recv (bin) proc */ + baseType->typsend, /* send (bin) proc */ + baseType->typmodin, /* typmodin procedure - none */ + baseType->typmodout, /* typmodout procedure - none */ + baseType->typanalyze, /* array analyze procedure */ + baseType->typelem, /* array element type - the rowtype */ + false, /* yes, this is an array type */ + baseType->typarray, /* this has no array type */ + newp->typoid, /* domain base type - irrelevant */ + NULL, /* default value - none */ + NULL, /* default binary representation */ + baseType->typbyval, /* passed by reference */ + baseType->typalign, /* alignment - must be the largest! */ + baseType->typstorage, /* fully TOASTable */ + newp->atttypmod, /* typmod */ + baseType->typndims, /* array dimensions for typBaseType */ + isNotNull, /* Type NOT NULL */ + baseType->typcollation); + + ReleaseSysCache(baseTypeTup); + + CommandCounterIncrement(); + + if (RangeList != NIL) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not support range in subtype"))); + } + + /* get the oid of type we built just now, for saving subtype into func. we can delete type when we delete func */ + newtypeoid = GetSysCacheOid2(TYPENAMENSP, PointerGetDatum(typname), ObjectIdGetDatum(NamespaceOid)); + res = plpgsql_build_datatype(newtypeoid, -1, InvalidOid); + res->dtype = PLPGSQL_DTYPE_SUBTYPE; + res->ttype = PLPGSQL_TTYPE_SCALAR; + res->ispkg = false; + res->typoid = newtypeoid; + int varno = plpgsql_adddatum((PLpgSQL_datum*)res); + plpgsql_ns_additem(PLPGSQL_NSTYPE_SUBTYPE, varno, typname); + + return newtypeoid; +} + +/* + * Suild SUBTYPE in FUNKTION or PACKAGE + * What's difference with anonym block: + * 1. Subtype has different name, it need concat oid in pkg/func + * 2. Subtype isn't needed to delete immediately, constraints will + * be released when obj released + * typname : name of subtype to be create + * newp : base type info + * RangeList : unsuport in opengauss util now, use to supprt type like pls_interge + * isNotNull : is not null + */ +static Oid +plpgsql_build_function_package_subtype(char* typname, PLpgSQL_type* newp, const List* RangeList, bool isNotNull) +{ + /* some variable */ + Oid NamespaceOid = InvalidOid; + Oid ownerId = InvalidOid; + HeapTuple typeTup; + Form_pg_type baseType; + ObjectAddress myself; + ObjectAddress referenced; + char* functypname = NULL; + char* pkgtypname = NULL; + char* schamaname = NULL; + Oid pkgoid = InvalidOid; + SubTypeRange* typerange = NULL; + char* casttypename = NULL; + bool sameType = false; + + /* it should be a function if curr_package is null */ + PLpgSQL_package* curr_package = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package; + PLpgSQL_function* curr_function = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile; + + AssertEreport(curr_package || curr_function, MOD_PLSQL, "Error defining subtype range"); + + if (RangeList != NIL) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not support range in subtype"))); + } + + + /* exchange name into oid_typname, check length in this function */ + getPkgFuncTypeName(typname, &functypname, &pkgtypname); + + if (curr_package) { + NamespaceOid = curr_package->namespaceOid; + } + if (!OidIsValid(NamespaceOid)) { + NamespaceOid = getCurrentNamespace(); + } + + Oid oldtypeoid = getOldTypeOidByTypeName(&casttypename, &schamaname, functypname, pkgtypname, &pkgoid); + + HeapTuple old_typtuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oldtypeoid)); + /* check can old record we use */ + if (HeapTupleIsValid(old_typtuple)) { + Form_pg_type typform = (Form_pg_type)GETSTRUCT(old_typtuple); + if (typform->typbasetype != newp->typoid){ + ereport(errstate, + (errmodule(MOD_PLSQL), + errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("duplicate type name"), + errdetail("type name of \"%s\" duplicated with an existed type when build subtype.", typname), + errcause("duplicate type name"), + erraction("modify subtype name"))); + } else { + sameType = true; + } + ReleaseSysCache(old_typtuple); + } + + if (OidIsValid(oldtypeoid) && sameType) { + /* skip same check for we have build it, get the constraint and return */ + if (!IsPackageDependType(oldtypeoid, pkgoid)) { + /* create dependency if there wasn't any one */ + referenced.classId = TypeRelationId; + referenced.objectId = oldtypeoid; + referenced.objectSubId = 0; + /* create dependency relation with pkg/func */ + if (curr_package) { + myself.classId = PackageRelationId; + myself.objectId = curr_package->pkg_oid; + myself.objectSubId = 0; + } else { + myself.classId = ProcedureRelationId; + myself.objectId = curr_function->fn_oid; + myself.objectSubId = 0; + } + recordDependencyOn(&referenced, &myself, DEPENDENCY_AUTO); + } + CommandCounterIncrement(); + + /* save to current ns*/ + PLpgSQL_type* res = plpgsql_build_datatype(oldtypeoid, -1, InvalidOid); + res->dtype = PLPGSQL_DTYPE_SUBTYPE; + res->ttype = PLPGSQL_TTYPE_SCALAR; + res->ispkg = false; + res->typoid = oldtypeoid; + int varno = plpgsql_adddatum((PLpgSQL_datum*)res); + plpgsql_ns_additem(PLPGSQL_NSTYPE_SUBTYPE, varno, typname); + + pfree_ext(functypname); + pfree_ext(pkgtypname); + + return oldtypeoid; + } + ownerId = GetUserIdFromNspId(NamespaceOid); + if (!OidIsValid(ownerId)) { + ownerId = GetUserId(); + } + + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(newp->typoid), 0, 0, 0); + baseType = (Form_pg_type)GETSTRUCT(typeTup); + + /* refer DOMAIN */ + referenced = TypeCreate(InvalidOid, /* force the type's OID to this */ + casttypename, /* Array type name */ + NamespaceOid, /* Same namespace as parent */ + InvalidOid, /* Not composite, no relationOid */ + 0, /* relkind, also N/A here */ + ownerId, /* owner's ID */ + baseType->typlen, /* Internal size (varlena) */ + TYPTYPE_DOMAIN, /* Not composite - typelem is */ + baseType->typcategory, /* type-category (array or table of) */ + false, /* array types are never preferred */ + baseType->typdelim, /* default array delimiter */ + F_SUBTYPE_IN, /* input proc */ + baseType->typoutput, /* output proc */ + F_SUBTYPE_RECV, /* recv (bin) proc */ + baseType->typsend, /* send (bin) proc */ + baseType->typmodin, /* typmodin procedure - none */ + baseType->typmodout, /* typmodout procedure - none */ + baseType->typanalyze, /* array analyze procedure */ + baseType->typelem, /* no array element type */ + false, /* yes, this is an array type */ + baseType->typarray, /* no array for subtype */ + newp->typoid, /* domain base type - irrelevant */ + NULL, /* default value - none */ + NULL, /* default binary representation */ + baseType->typbyval, /* passed by reference */ + baseType->typalign, /* alignment - must be the largest! */ + baseType->typstorage, /* fully TOASTable */ + newp->atttypmod, /* typmod */ + baseType->typndims, /* array dimensions for typBaseType */ + isNotNull, /* Type NOT NULL */ + baseType->typcollation); /* type's collation */ + + ReleaseSysCache(typeTup); + CommandCounterIncrement(); + + /* build dependcy relation with FUNC/PKG */ + if (curr_package) { + myself.classId = PackageRelationId; + myself.objectId = curr_package->pkg_oid; + myself.objectSubId = 0; + } else { + myself.classId = ProcedureRelationId; + myself.objectId = curr_function->fn_oid; + myself.objectSubId = 0; + } + recordDependencyOn(&referenced, &myself, DEPENDENCY_AUTO); + + CommandCounterIncrement(); + + /* save to datum in current function */ + Oid newtypeoid = GetSysCacheOid2(TYPENAMENSP, PointerGetDatum(casttypename), ObjectIdGetDatum(NamespaceOid)); + PLpgSQL_type* res = plpgsql_build_datatype(newtypeoid, -1, InvalidOid); + res->dtype = PLPGSQL_DTYPE_SUBTYPE; + res->ttype = PLPGSQL_TTYPE_SCALAR; + res->ispkg = false; + res->typoid = newtypeoid; + int varno = plpgsql_adddatum((PLpgSQL_datum*)res); + plpgsql_ns_additem(PLPGSQL_NSTYPE_SUBTYPE, varno, typname); + + pfree_ext(functypname); + pfree_ext(pkgtypname); + return newtypeoid; +} + /* * Check block starting and ending labels match. */ @@ -14514,3 +15212,48 @@ static void CheckParallelCursorOpr(PLpgSQL_stmt_fetch* fetch) ereport(ERROR, (errmsg("only support FETCH CURSOR for parallel cursor \"%s\"", var->varname))); } } + +static void +yylex_object_type_selfparam(char ** fieldnames, + int *varnos, + int nfields, + PLpgSQL_row **row, + PLpgSQL_rec **rec, + int *retvarno, + PLwdatum *objtypwdatum, + bool overload) +{ + StringInfoData ds; + initStringInfo(&ds); + if (NULL != objtypwdatum && NULL != objtypwdatum->idents) + CastTypeVariableNameToString(&ds, objtypwdatum->idents, false); + if (!overload) { + if (PLPGSQL_DTYPE_ROW == objtypwdatum->datum->dtype) { + fieldnames[nfields] = pstrdup(ds.data); + int varno = objtypwdatum->dno; + varnos[nfields] = varno; + *row = (PLpgSQL_row *)objtypwdatum->datum; + *retvarno = varno; + } else if (PLPGSQL_DTYPE_RECORD == objtypwdatum->datum->dtype) { + check_assignable(objtypwdatum->datum, yylloc); + fieldnames[nfields] = pstrdup(ds.data); + varnos[nfields] = objtypwdatum->dno; + *row = (PLpgSQL_row *)objtypwdatum->datum; + } else if(PLPGSQL_DTYPE_REC == objtypwdatum->datum->dtype) { + check_assignable(objtypwdatum->datum, yylloc); + fieldnames[nfields] = pstrdup(ds.data); + varnos[nfields] = objtypwdatum->dno; + *rec = (PLpgSQL_rec *)objtypwdatum->datum; + } else { + const char *message = "It is not a object type variable"; + InsertErrorMessage(message, plpgsql_yylloc); + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("\"%s\" is not a object variable", NameOfDatum(&yylval.wdatum)))); + } + } else { + fieldnames[nfields] = NULL; + varnos[nfields] = -1; + } + pfree_ext(ds.data); +} \ No newline at end of file diff --git a/contrib/dolphin/plugin_pl/plpgsql/src/pl_comp.cpp b/contrib/dolphin/plugin_pl/plpgsql/src/pl_comp.cpp index b37dfe40aa7fd0dc998a44e94477c61ccecb0844..46b2bfcf89bda1dd046e7b50cdd1a64c74c5f77d 100644 --- a/contrib/dolphin/plugin_pl/plpgsql/src/pl_comp.cpp +++ b/contrib/dolphin/plugin_pl/plpgsql/src/pl_comp.cpp @@ -19,8 +19,10 @@ #include +#include "catalog/pg_synonym.h" #include "catalog/namespace.h" #include "catalog/pg_namespace.h" +#include "catalog/pg_object.h" #include "catalog/pg_proc.h" #include "catalog/pg_proc_fn.h" #include "catalog/gs_package.h" @@ -104,7 +106,8 @@ static bool plpgsql_lookup_tripword_datum(int itemno, const char* word2, const c static void get_datum_tok_type(PLpgSQL_datum* target, int* tok_flag); static PLpgSQL_type* plpgsql_get_cursor_type_relid(const char* cursorname, const char* colname, MemoryContext oldCxt); static int find_package_rowfield(PLpgSQL_datum* datum, const char* pkgName, const char* schemaName = NULL); - +static bool isObjectTypeMethod(char* compWord, char* firstword, char* secondWord, + char* thirdWord, PLwdatum* wdatum, int* nsflag); extern bool is_func_need_cache(Oid funcid, const char* func_name); @@ -160,8 +163,9 @@ PLpgSQL_function* plpgsql_compile(FunctionCallInfo fcinfo, bool for_validator, b * try to find one in the hash table. */ PLpgSQL_function* func = (PLpgSQL_function*)fcinfo->flinfo->fn_extra; + bool ispackage = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_package, &isnull); Datum pkgoiddatum = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_packageid, &isnull); - Oid packageOid = DatumGetObjectId(pkgoiddatum); + Oid packageOid = ispackage ? DatumGetObjectId(pkgoiddatum) : InvalidOid; Oid old_value = saveCallFromPkgOid(packageOid); if (enable_plpgsql_gsdependency_guc()) { if (func == NULL) { @@ -296,10 +300,22 @@ recheck: { List* ref_obj_list = gsplsql_prepare_recompile_func(func_oid, proc_struct->pronamespace, packageOid, isRecompile); SetCurrCompilePgObjStatus(true); + bool isNull = false; + /* Find method type from pg_object */ + char protypkind = OBJECTTYPE_NULL_PROC; + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, + ObjectIdGetDatum(func_oid), CharGetDatum(OBJECT_TYPE_PROC)); + if (HeapTupleIsValid(objTuple)) { + protypkind = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isnull)); + ReleaseSysCache(objTuple); + } + if (!isNull && (protypkind == OBJECTTYPE_MEMBER_PROC || protypkind == OBJECTTYPE_CONSTRUCTOR_PROC)) + u_sess->plsql_cxt.typfunckind = protypkind; func = do_compile(fcinfo, proc_tup, func, &hashkey, for_validator); UpdateCurrCompilePgObjStatus(save_curr_status); gsplsql_complete_recompile_func(ref_obj_list); (void)CompileStatusSwtichTo(save_compile_status); + u_sess->plsql_cxt.typfunckind = OBJECTTYPE_NULL_PROC; } PG_CATCH(); { @@ -311,6 +327,7 @@ recheck: InsertError(func_oid); } #endif + u_sess->plsql_cxt.typfunckind = OBJECTTYPE_NULL_PROC; SetCurrCompilePgObjStatus(save_compile_status); popToOldCompileContext(save_compile_context); (void)CompileStatusSwtichTo(save_compile_status); @@ -605,6 +622,38 @@ int getCompileStatus() return u_sess->plsql_cxt.compile_status; } +/* check functionname and typename */ +void getPkgFuncTypeName(char *typname, char **functypname, char **pkgtypname) +{ + if (NULL == u_sess->plsql_cxt.curr_compile_context) { + return; + } + if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile != NULL) { + *functypname = CastPackageTypeName(typname, + u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_oid, false); + if (strlen(*functypname) >= NAMEDATALEN) { + ereport(ERROR, + (errcode(ERRCODE_NAME_TOO_LONG), + errmsg("type name too long"), + errdetail("record name %s with func oid %d should be less the %d letters.", + typname, u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile->fn_oid, NAMEDATALEN))); + } + } + if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package != NULL) { + *pkgtypname = CastPackageTypeName(typname, + u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid, true); + if (strlen(*pkgtypname) >= NAMEDATALEN) { + ereport(ERROR, + (errcode(ERRCODE_NAME_TOO_LONG), + errmsg("type name too long"), + errdetail("record name %s with package name %s should be less the %d letters.", + typname, + u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_signature, + NAMEDATALEN))); + } + } +} + PLpgSQL_resolve_option GetResolveOption() { return (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) ? @@ -723,8 +772,9 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup, } char* proc_source = TextDatumGetCString(prosrcdatum); + bool ispackage = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_package, &isnull); Datum pkgoiddatum = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_packageid, &isnull); - if (!isnull) { + if (!isnull && ispackage) { pkgoid = ObjectIdGetDatum(pkgoiddatum); } if (OidIsValid(Anum_pg_proc_proisprivate)) { @@ -2046,7 +2096,14 @@ static Node* resolve_column_ref(ParseState* pstate, PLpgSQL_expr* expr, ColumnRe #endif if (nse == NULL) { - return NULL; /* name not known to plpgsql */ + /* Attemt to find parameter in object type's explicit self parameter field */ + char* selfparam = "self"; + nnames_wholerow = 2; + nnames_field = 1; + colname = name1; + nse = plpgsql_ns_lookup(expr->ns, false, selfparam, name1, name3, &nnames); + if (nse == NULL) + return NULL; /* name not known to plpgsql */ } if (nse->itemtype == PLPGSQL_NSTYPE_UNKNOWN) { if (nse->pkgname == NULL) { @@ -2830,7 +2887,8 @@ bool plpgsql_parse_dblword(char* word1, char* word2, PLwdatum* wdatum, PLcword* } } if (!exist) { - break; + ereport(ERROR, (errmodule(MOD_PLSQL), errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("record \"%s\" has no field \"%s\"", rec->refname, word2))); } } } @@ -2927,6 +2985,23 @@ bool plpgsql_parse_dblword(char* word1, char* word2, PLwdatum* wdatum, PLcword* wdatum->idents = idents; return true; } + /* Try to find varray word in self's field for object type */ + if ((OBJECTTYPE_MEMBER_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_CONSTRUCTOR_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_MAP_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_ORDER_PROC == u_sess->plsql_cxt.typfunckind) + && isVarrayWord(word2, "self", word1, NULL, wdatum, nsflag)) { + wdatum->ident = NULL; + wdatum->quoted = false; + wdatum->idents = idents; + return true; + } + if (isObjectTypeMethod(word2, word1, NULL, NULL, wdatum, nsflag)) { + wdatum->ident = word2; + wdatum->idents = list_make1(makeString(word1)); + return true; + } /* Nothing found */ cword->idents = idents; return false; @@ -3084,6 +3159,11 @@ bool plpgsql_parse_tripword(char* word1, char* word2, char* word3, PLwdatum* wda wdatum->idents = idents; return true; } + if (isObjectTypeMethod(word3, word1, word2, NULL, wdatum, tok_flag)) { + wdatum->ident = word3; + wdatum->idents = list_make2(makeString(word1), makeString(word2)); + return true; + } /* Nothing found */ cword->idents = idents; @@ -3899,9 +3979,12 @@ PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno, PLpgSQ row->dtype = PLPGSQL_DTYPE_ROW; row->refname = pstrdup(refname); row->lineno = lineno; + row->datatype = dtype; row->addNamespace = add2namespace; row->varname = varname == NULL ? NULL : pstrdup(varname); row->default_val = NULL; + if (dtype->typtyp == TYPTYPE_ABSTRACT_OBJECT) + row->atomically_null_object = true; varno = plpgsql_adddatum((PLpgSQL_datum*)row); if (add2namespace) { plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, varno, refname, pkgname); @@ -3916,6 +3999,7 @@ PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno, PLpgSQ } case PLPGSQL_TTYPE_CURSORROW: { PLpgSQL_rec* rec = (PLpgSQL_rec*)palloc0(sizeof(PLpgSQL_rec)); + rec->field_need_check = NIL; rec->dtype = PLPGSQL_DTYPE_CURSORROW; rec->refname = pstrdup(refname); rec->lineno = lineno; @@ -3936,15 +4020,17 @@ PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno, PLpgSQ } rec->tupdesc = getCursorTupleDesc(rec->expr, false, false); - - nulls = (bool *)palloc(rec->tupdesc->natts * sizeof(bool)); - rc = memset_s(nulls, rec->tupdesc->natts * sizeof(bool), true, rec->tupdesc->natts * sizeof(bool)); - securec_check(rc, "\0", "\0"); - - rec->tup = (HeapTuple)tableam_tops_form_tuple(rec->tupdesc, NULL, nulls); - rec->freetupdesc = (rec->tupdesc != NULL) ? true : false; - rec->freetup = (rec->tup != NULL) ? true : false; - pfree_ext(nulls); + if (rec->tupdesc) { + nulls = (bool*)palloc(rec->tupdesc->natts * sizeof(bool)); + rc = memset_s(nulls, rec->tupdesc->natts * sizeof(bool), true, + rec->tupdesc->natts * sizeof(bool)); + securec_check(rc, "\0", "\0"); + rec->tup = (HeapTuple)tableam_tops_form_tuple(rec->tupdesc, NULL, nulls); + /* compile_tmp_cx will automatically free, there is no need to set free mark. */ + rec->freetupdesc = false; + rec->freetup = false; + pfree_ext(nulls); + } if (target_cxt) { temp = MemoryContextSwitchTo(temp); @@ -3994,8 +4080,10 @@ PLpgSQL_variable* plpgsql_build_variable(const char* refname, int lineno, PLpgSQ row = build_row_from_rec_type(refname, lineno, (PLpgSQL_rec_type*)dtype); row->addNamespace = add2namespace; + row->datatype = dtype; row->varname = varname == NULL ? NULL : pstrdup(varname); row->default_val = NULL; + row->atomically_null_object = false; varno = plpgsql_adddatum((PLpgSQL_datum*)row); if (add2namespace) { plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, varno, refname, pkgname); @@ -4169,6 +4257,99 @@ PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List* return result; } +/* + * typname: SUBTYPE name + * basetypname: base type name + */ +void plpgsql_build_synonym(char* typname, char* basetypname) +{ + CreateSynonymStmt stmt; + stmt.replace = true; + Node* lc = NULL; + List* synList = NIL; + List* objList = NIL; + Oid NamespaceOid = InvalidOid; + char* functypname = NULL; + char* pkgtypname = NULL; + ObjectAddress myself, referenced; + + PLpgSQL_package* curr_package = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package; + PLpgSQL_function* curr_function = u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile; + + getPkgFuncTypeName(typname, &functypname, &pkgtypname); + + if (curr_package) { + NamespaceOid = curr_package->namespaceOid; + } + if (!OidIsValid(NamespaceOid)) { + NamespaceOid = getCurrentNamespace(); + } + + if (curr_package) { + lc = (Node*)makeString(curr_package->pkg_signature); + synList = lappend(synList, lc); + } + + lc = (Node*)makeString(typname); + synList = lappend(synList, lc); + + lc = (Node*)makeString(basetypname); + objList = lappend(objList, lc); + + stmt.synName = synList; + stmt.objName = objList; + + HeapTuple tuple = SearchSysCache2(SYNONYMNAMENSP, PointerGetDatum(typname), ObjectIdGetDatum(NamespaceOid)); + if (!HeapTupleIsValid(tuple)) { + CreateSynonym(&stmt); + CommandCounterIncrement(); + } else { + Form_pg_synonym synForm = (Form_pg_synonym)GETSTRUCT(tuple); + if (pg_strcasecmp(synForm->synobjname.data, basetypname) != 0) { + ereport(ERROR, + (errmsg( + "The basetypename are different from synonym \"%s\": "\ + "the old basetype is \"%s\", the new base type is \"%s\".", + typname, synForm->synobjname.data, basetypname))); + } + ReleaseSysCache(tuple); + pfree_ext(functypname); + pfree_ext(pkgtypname); + return ; + } + + tuple = SearchSysCache2(SYNONYMNAMENSP, PointerGetDatum(typname), ObjectIdGetDatum(NamespaceOid)); + if (!HeapTupleIsValid(tuple)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("synonym \"%s\" does not exist", typname))); + } + Oid synOid = HeapTupleGetOid(tuple); + ReleaseSysCache(tuple); + + /* build dependency on Synonym */ + if (curr_package) { + myself.classId = PackageRelationId; + myself.objectId = curr_package->pkg_oid; + myself.objectSubId = 0; + } else { + myself.classId = ProcedureRelationId; + myself.objectId = curr_function->fn_oid; + myself.objectSubId = 0; + } + + referenced.classId = PgSynonymRelationId; + referenced.objectId = synOid; + referenced.objectSubId = 0; + recordDependencyOn(&referenced, &myself, DEPENDENCY_AUTO); + + PgObjectOption objectOpt = {true, true, false, false}; + CreatePgObject(synOid, OBJECT_TYPE_SYNONYM, GetUserId(), objectOpt); + + CommandCounterIncrement(); + + pfree_ext(functypname); + pfree_ext(pkgtypname); +} + /* * Build a row-variable data structure given the pg_class OID. */ @@ -4200,6 +4381,7 @@ PLpgSQL_row* build_row_from_class(Oid class_oid) row->fieldnames = (char**)palloc(sizeof(char*) * row->nfields); row->varnos = (int*)palloc(sizeof(int) * row->nfields); row->default_val = NULL; + row->atomically_null_object = false; for (int i = 0; i < row->nfields; i++) { Form_pg_attribute attr_struct; @@ -4260,7 +4442,8 @@ static PLpgSQL_row* build_row_from_vars(PLpgSQL_variable** vars, int numvars) row->fieldnames = (char**)palloc(numvars * sizeof(char*)); row->varnos = (int*)palloc(numvars * sizeof(int)); row->default_val = NULL; - + row->atomically_null_object = false; + for (int i = 0; i < numvars; i++) { PLpgSQL_variable* var = vars[i]; Oid typoid = RECORDOID; @@ -4315,6 +4498,7 @@ PLpgSQL_row* build_row_from_tuple_desc(const char* rowname, int lineno, TupleDes row->fieldnames = (char**)palloc(row->nfields * sizeof(char*)); row->varnos = (int*)palloc(row->nfields * sizeof(int)); row->default_val = NULL; + row->atomically_null_object = false; for (int i = 0; i < desc->natts; i++) { Form_pg_attribute pg_att_form = &desc->attrs[i]; @@ -4418,7 +4602,9 @@ PLpgSQL_type* plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, T } PLpgSQL_type* typ = NULL; - if (((Form_pg_type)GETSTRUCT(type_tup))->typtype == TYPTYPE_TABLEOF) { + Form_pg_type type_struct = (Form_pg_type)GETSTRUCT(type_tup); + char typtyp = type_struct->typtype; + if (type_struct->typtype == TYPTYPE_TABLEOF) { /* if type is table of, find the base type tuple */ Oid base_oid = ((Form_pg_type)GETSTRUCT(type_tup))->typelem; HeapTuple base_type_tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(base_oid)); @@ -4430,14 +4616,29 @@ PLpgSQL_type* plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, T } typ = build_datatype(base_type_tup, typmod, collation); typ->collectionType = PLPGSQL_COLLECTION_TABLE; - if (((Form_pg_type)GETSTRUCT(type_tup))->typcategory == TYPCATEGORY_TABLEOF_VARCHAR) { + if (type_struct->typcategory == TYPCATEGORY_TABLEOF_VARCHAR) { typ->tableOfIndexType = VARCHAROID; - } else if (((Form_pg_type)GETSTRUCT(type_tup))->typcategory == TYPCATEGORY_TABLEOF_INTEGER) { + } else if (type_struct->typcategory == TYPCATEGORY_TABLEOF_INTEGER) { typ->tableOfIndexType = INT4OID; } ReleaseSysCache(base_type_tup); + } else if (type_struct->typtype == TYPTYPE_VARRAY) { + /* if type is varray, find the base type tuple */ + Oid base_oid = type_struct->typelem; + HeapTuple base_type_tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(base_oid)); + if (!HeapTupleIsValid(base_type_tup)) { + ereport(ERROR, + (errmodule(MOD_PLSQL), + errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for type %u, type Oid is invalid", base_oid))); + } + typ = build_datatype(base_type_tup, typmod, collation); + typ->collectionType = PLPGSQL_COLLECTION_TABLE; + typ->tableOfIndexType = InvalidOid; + ReleaseSysCache(base_type_tup); } else { typ = build_datatype(type_tup, typmod, collation); + typ->collectionType = PLPGSQL_COLLECTION_NONE; } ReleaseSysCache(type_tup); if (enable_plpgsql_gsdependency() && NULL != typ) { @@ -4445,6 +4646,7 @@ PLpgSQL_type* plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, T typ->dependExtend = type_depend_extend; typ->dependExtend->typeOid = typeOid; } + typ->typtyp = typtyp; return typ; } @@ -4498,6 +4700,7 @@ PLpgSQL_type* build_datatype(HeapTuple type_tup, int32 typmod, Oid collation) typ->ttype = PLPGSQL_TTYPE_SCALAR; break; case TYPTYPE_COMPOSITE: + case TYPTYPE_ABSTRACT_OBJECT: AssertEreport(OidIsValid(type_struct->typrelid), MOD_PLSQL, "It is invalid oid."); typ->ttype = PLPGSQL_TTYPE_ROW; break; @@ -4915,8 +5118,9 @@ static void compute_function_hashkey(HeapTuple proc_tup, FunctionCallInfo fcinfo hashkey->funcOid = fcinfo->flinfo->fn_oid; bool isnull = false; + bool ispackage = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_package, &isnull); Datum packageOid_datum = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_packageid, &isnull); - Oid packageOid = DatumGetObjectId(packageOid_datum); + Oid packageOid = ispackage ? DatumGetObjectId(packageOid_datum) : InvalidOid; hashkey->packageOid = packageOid; /* get call context */ hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo); @@ -5748,6 +5952,32 @@ Oid searchsubtypebytypeId(Oid typeOid, int32 *typmod) return type == TYPTYPE_TABLEOF ? searchsubtypebytypeId(resultType, typmod) : resultType; } +static bool isObjectTypeMethod(char* compWord, char* firstWord, char* secondWord, + char* thirdWord, PLwdatum* wdatum, int* nsflag) +{ + PLpgSQL_nsitem *ns = NULL; + bool ret = false; + + ns = plpgsql_ns_lookup(plpgsql_ns_top(), false, firstWord, secondWord, thirdWord, NULL); + if (ns == NULL) { + return false; + } + + if (ns->itemtype == PLPGSQL_NSTYPE_ROW) { + /* object type var reference method: var.method, package.var.method, schema.package.var.method */ + PLpgSQL_row* var = (PLpgSQL_row*)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[ns->itemno]; + if (var->datatype && var->datatype->dtype != PLPGSQL_DTYPE_RECORD_TYPE + && var->datatype->typtyp == TYPTYPE_ABSTRACT_OBJECT) { + wdatum->datum = u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[ns->itemno]; + wdatum->dno = ns->itemno; + *nsflag = PLPGSQL_TOK_OBJECT_TYPE_VAR_METHOD; + return true; + } + } + + return ret; +} + void checkArrayTypeInsert(ParseState* pstate, Expr* expr) { Param* param = NULL; diff --git a/contrib/dolphin/plugin_pl/plpgsql/src/pl_handler.cpp b/contrib/dolphin/plugin_pl/plpgsql/src/pl_handler.cpp index ddb8ab5c1a1858499d0240f6c9cb7cb50321947c..1cb2784f18eecd40b3f4e5eeb7c3553fa2cbdde9 100644 --- a/contrib/dolphin/plugin_pl/plpgsql/src/pl_handler.cpp +++ b/contrib/dolphin/plugin_pl/plpgsql/src/pl_handler.cpp @@ -22,6 +22,7 @@ #include "catalog/pg_cast.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" +#include "catalog/pg_object_type.h" #include "catalog/gs_package.h" #include "catalog/pg_language.h" #include "catalog/pg_proc_fn.h" @@ -292,13 +293,14 @@ static void ProcInsertGsSource(Oid funcOid, bool status) bool isnull = false; /* Skip nested create function stmt within package body */ + bool ispackage = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_package, &isnull); Datum packageIdDatum = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_packageid, &isnull); if (isnull) { ereport(ERROR, (errmodule(MOD_PLSQL), errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("The prokind of the function is null"), errhint("Check whether the definition of the function is complete in the pg_proc system table."))); } - Oid packageOid = DatumGetObjectId(packageIdDatum); + Oid packageOid = ispackage ? DatumGetObjectId(packageIdDatum) : InvalidOid; if (OidIsValid(packageOid)) { ReleaseSysCache(procTup); return; @@ -584,8 +586,9 @@ static Oid get_package_id(Oid func_oid) errmsg("cache lookup failed for function %u, while compile function", func_oid))); } proc_struct = (Form_pg_proc)GETSTRUCT(proc_tup); + bool ispackage = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_package, &isnull); package_oid_datum = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_packageid, &isnull); - package_oid = DatumGetObjectId(package_oid_datum); + package_oid = ispackage ? DatumGetObjectId(package_oid_datum) : InvalidOid; if (OidIsValid(package_oid)) { pkgtup = SearchSysCache1(PACKAGEOID, ObjectIdGetDatum(package_oid)); @@ -796,6 +799,44 @@ Datum b_plpgsql_call_handler(PG_FUNCTION_ARGS) int pkgDatumsNumber = 0; bool savedisAllowCommitRollback = true; bool enableProcCoverage = u_sess->attr.attr_common.enable_proc_coverage; + + + /* Check if type body exists if using type method */ + HeapTuple proc_tup = NULL; + bool isnull = false; + /* + * If the function in a package, thne compile the package, and find the compiled function in + * pkg->proc_compiled_list + */ + proc_tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid)); + if (!HeapTupleIsValid(proc_tup)) { + ereport(ERROR, (errmodule(MOD_PLSQL), errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for function %u, while compile function.", func_oid))); + } + bool ispackage = SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_package, &isnull); + Oid protypoid = ispackage ? InvalidOid : DatumGetObjectId( + SysCacheGetAttr(PROCOID, proc_tup, Anum_pg_proc_packageid, &isnull)); + /* Find method type from pg_object */ + char typmethodkind = OBJECTTYPE_NULL_PROC; + HeapTuple objTuple = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(func_oid), CharGetDatum(OBJECT_TYPE_PROC)); + if (HeapTupleIsValid(objTuple)) { + typmethodkind = GET_PROTYPEKIND(SysCacheGetAttr(PGOBJECTID, objTuple, Anum_pg_object_options, &isnull)); + ReleaseSysCache(objTuple); + } + if (OidIsValid(protypoid) && (typmethodkind != OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC) && + (typmethodkind != TABLE_VARRAY_CONSTRUCTOR_PROC)) { + HeapTuple tuple = SearchSysCache1(OBJECTTYPE, ObjectIdGetDatum(protypoid)); + if (!HeapTupleIsValid(tuple)) { + ereport(ERROR, (errmodule(MOD_PLSQL), errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for object type %u, while compile function.", protypoid))); + } + Form_pg_object_type pg_object_type_struct = (Form_pg_object_type)GETSTRUCT(tuple); + if (!pg_object_type_struct->isbodydefined) + ereport(ERROR, (errmodule(MOD_PLSQL), errcode(ERRCODE_OBJECT_TYPE_BODY_DEFINE_ERROR), + errmsg("type body \"%s\" not define", get_typename(protypoid)))); + ReleaseSysCache(tuple); + } + ReleaseSysCache(proc_tup); /* * if the atomic stored in fcinfo is false means allow * commit/rollback within stored procedure. @@ -1598,6 +1639,7 @@ Datum b_plpgsql_validator(PG_FUNCTION_ARGS) InsertError(u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package->pkg_oid); } u_sess->plsql_cxt.isCreateFunction = false; + u_sess->plsql_cxt.isCreateTypeBody = false; } } #endif @@ -1607,6 +1649,8 @@ Datum b_plpgsql_validator(PG_FUNCTION_ARGS) u_sess->plsql_cxt.package_as_line = 0; u_sess->plsql_cxt.package_first_line = 0; u_sess->plsql_cxt.isCreateFunction = false; + u_sess->plsql_cxt.isCreateTypeBody = false; + u_sess->plsql_cxt.typfunckind = OBJECTTYPE_NULL_PROC; ereport(DEBUG3, (errmodule(MOD_NEST_COMPILE), errcode(ERRCODE_LOG), errmsg("%s clear curr_compile_context because of error.", __func__))); /* reset nest plpgsql compile */ diff --git a/contrib/dolphin/plugin_pl/plpgsql/src/pl_scanner.cpp b/contrib/dolphin/plugin_pl/plpgsql/src/pl_scanner.cpp index 9b832755514d675e334f5536a8c54b60ee47b76a..d1637e97aa5875db4ad253076269bb07bb38abc0 100644 --- a/contrib/dolphin/plugin_pl/plpgsql/src/pl_scanner.cpp +++ b/contrib/dolphin/plugin_pl/plpgsql/src/pl_scanner.cpp @@ -17,6 +17,8 @@ #include "utils/builtins.h" #include "utils/plpgsql.h" #include "utils/pl_package.h" +#include "catalog/pg_object.h" +#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "catalog/gs_package.h" #include "plugin_mb/pg_wchar.h" @@ -309,6 +311,21 @@ int plpgsql_yylex(void) { tok1 = T_PLACEHOLDER; } + } else if ((OBJECTTYPE_MEMBER_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_CONSTRUCTOR_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_DEFAULT_CONSTRUCTOR_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_MAP_PROC == u_sess->plsql_cxt.typfunckind + || OBJECTTYPE_ORDER_PROC == u_sess->plsql_cxt.typfunckind) + && ('=' == tok2 || COLON_EQUALS == tok2 || '[' == tok2 || '(' == tok2)) { + /* check self.A while creating type body */ + List* idents_bak = aux1.lval.cword.idents; + if (plpgsql_parse_dblword("self", aux1.lval.str, &aux1.lval.wdatum, &aux1.lval.cword, &dbl_tok_flag)) { + tok1 = T_DATUM; + } else { + /* reset */ + aux1.lval.cword.idents = idents_bak; + tok1 = T_DATUM; + } } else { tok1 = T_WORD; } @@ -821,6 +838,8 @@ static int get_self_defined_tok(int tok_flag) return T_TABLE_VAR; case PLPGSQL_TOK_PACKAGE_VARIABLE: return T_PACKAGE_VARIABLE; + case PLPGSQL_TOK_OBJECT_TYPE_VAR_METHOD: + return T_OBJECT_TYPE_VAR_METHOD; default: ereport(ERROR, (errmodule(MOD_PLSQL), diff --git a/contrib/dolphin/plugin_pl/plpgsql/src/pl_unreserved_kwlist.h b/contrib/dolphin/plugin_pl/plpgsql/src/pl_unreserved_kwlist.h index eb77963d52958539b4c37d328e8770f880a2dd8d..0cbbdda97ff70c625f30e83e09ae7d9e46a66db0 100755 --- a/contrib/dolphin/plugin_pl/plpgsql/src/pl_unreserved_kwlist.h +++ b/contrib/dolphin/plugin_pl/plpgsql/src/pl_unreserved_kwlist.h @@ -125,6 +125,7 @@ PG_KEYWORD("sqlstate", K_SQLSTATE) PG_KEYWORD("sqlwarning", K_SQLWARNING) PG_KEYWORD("stacked", K_STACKED) PG_KEYWORD("subclass_origin", K_SUBCLASS_ORIGIN) +PG_KEYWORD("subtype", K_SUBTYPE) PG_KEYWORD("sys_refcursor", K_SYS_REFCURSOR) PG_KEYWORD("table", K_TABLE) PG_KEYWORD("table_name", K_TABLE_NAME) diff --git a/contrib/dolphin/plugin_postgres.cpp b/contrib/dolphin/plugin_postgres.cpp index a49cbc424853fdefe7e52a8eba78433e2c4bfc9c..c178a3a736c6215ecc50894ebf91d4b3a00f69f1 100644 --- a/contrib/dolphin/plugin_postgres.cpp +++ b/contrib/dolphin/plugin_postgres.cpp @@ -1053,6 +1053,7 @@ void init_session_vars(void) cxt->is_create_alter_stmt = false; cxt->isDoCopy = false; cxt->isInTransformSet = false; + cxt->is_set_stmt = false; if (temp_Conn_Mysql_Info) { cxt->Conn_Mysql_Info = (conn_mysql_infoP_t)MemoryContextAllocZero(u_sess->self_mem_cxt, @@ -1447,6 +1448,15 @@ void init_session_vars(void) PGC_USERSET, 0, NULL, NULL, NULL); + DefineCustomBoolVariable("dolphin.treat_float_with_precision_as_float_type", + gettext_noop("This variable indicates treating a float type with precision as a float " + "type without precision. it may cause the result in loss of precision."), + NULL, + &GetSessionContext()->treat_float_with_precision_as_float_type, + false, + PGC_USERSET, + 0, + NULL, NULL, NULL); #endif } diff --git a/contrib/dolphin/plugin_protocol/auth.cpp b/contrib/dolphin/plugin_protocol/auth.cpp index 672670875cb4e3e9ffedcb7e8a775a5c8ace454c..b00a96028be29908f55681e9e6245c32ec7991ef 100644 --- a/contrib/dolphin/plugin_protocol/auth.cpp +++ b/contrib/dolphin/plugin_protocol/auth.cpp @@ -141,7 +141,7 @@ int dophin_conn_handshake(Port* port) pq_flush(); // read user login request packet - if (dq_getmessage(buf, 0) != STATUS_OK) { + if (dq_special_getmessage(buf, port) != STATUS_OK) { return EOF; } diff --git a/contrib/dolphin/plugin_protocol/bytestream.cpp b/contrib/dolphin/plugin_protocol/bytestream.cpp index 8dd29bcbd53a65928b31a37978d751830709da32..40b122dea7d929d0c58c10a4593bb1329df8e04e 100644 --- a/contrib/dolphin/plugin_protocol/bytestream.cpp +++ b/contrib/dolphin/plugin_protocol/bytestream.cpp @@ -60,6 +60,59 @@ fail: return EOF; } +int dq_special_getmessage(StringInfo buf, Port* port) +{ + uint32 nDataLen = 0; + int nSizeRecved = 0; + int nSizeRecvedTemp = 0; + int loopTimes = 0; + uint8 ser_num = 0; + + resetStringInfo(buf); + enlargeStringInfo(buf, PROTO_PAYLOAD_LEN); + // Read packet length + nSizeRecved = recv(port->sock, buf->data, PROTO_PAYLOAD_LEN, 0); + if (PROTO_PAYLOAD_LEN > nSizeRecved) { + ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("Failed to receive data"))); + return EOF; + } + buf->len = PROTO_PAYLOAD_LEN; + dq_get_payload_len(buf, &nDataLen); + //Disconnect and report an error when the received data length exceeds the required upper limit + if (PROTO_RECV_BUFFER_SIZE < nDataLen) { + ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("Abnormal data reception"))); + return EOF; + } + nSizeRecved = recv(port->sock, (char *)&ser_num, 1, 0); + if (ser_num != 1) { + ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("Abnormal data reception"))); + return EOF; + } + next_seqid = ser_num; + resetStringInfo(buf); + enlargeStringInfo(buf, nDataLen); + // read data + nSizeRecved = 0; + while (nSizeRecved < nDataLen) { + loopTimes++; + nSizeRecvedTemp = recv(port->sock, buf->data + nSizeRecved, nDataLen - nSizeRecved, 0); + if (nSizeRecvedTemp <= 0 || loopTimes > nDataLen) { + break; + } else { + nSizeRecved += nSizeRecvedTemp; + } + } + if (nSizeRecved != nDataLen) { + ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("Abnormal data reception"))); + return EOF; + } + + buf->len = nDataLen; + buf->cursor = 0; + buf->data[nSizeRecved] = '\0'; + return 0; +} + int dq_getmessage(StringInfo buf, uint32 maxlen) { uint32 len; diff --git a/contrib/dolphin/plugin_protocol/dqformat.cpp b/contrib/dolphin/plugin_protocol/dqformat.cpp index d37616a0ce2b747097b12cbf38eeda58250effc3..9228b3ad9fd3ac003f1300a293f56f0257c7dbe3 100644 --- a/contrib/dolphin/plugin_protocol/dqformat.cpp +++ b/contrib/dolphin/plugin_protocol/dqformat.cpp @@ -49,6 +49,7 @@ #define PROTO_TIME_LEN 8 #define PROTE_TIMESTATMP_LEN 12 +#define PACKETOFFSET_4 4 #define PACKETOFFSET_8 8 static com_stmt_param* make_stmt_parameters_bytype(int param_count, PreparedStatement *pstmt, @@ -147,9 +148,12 @@ network_mysqld_auth_request* read_login_request(StringInfo buf, Port* port) { network_mysqld_auth_request *auth = (network_mysqld_auth_request*) palloc0(sizeof(network_mysqld_auth_request)); dq_get_int4(buf, &auth->client_capabilities); - dq_get_int4(buf, &auth->max_packet_size); - dq_get_int1(buf, &auth->charset); - + if (buf->len != PACKETOFFSET_4) { + dq_get_int4(buf, &auth->max_packet_size); + dq_get_int1(buf, &auth->charset); + } else { + auth->max_packet_size = 0xfffff; + } if ((auth->client_capabilities & CLIENT_SSL)) { uint8 ssl_charset_code = 0; if (TlsSecureOpen(port)) { diff --git a/contrib/dolphin/plugin_protocol/server_startup.cpp b/contrib/dolphin/plugin_protocol/server_startup.cpp index 89bf7112ab4bf6ac3dd084524d66d5946089a148..8f46cf56b74582489d039ed69f1ae3778975b150 100644 --- a/contrib/dolphin/plugin_protocol/server_startup.cpp +++ b/contrib/dolphin/plugin_protocol/server_startup.cpp @@ -248,7 +248,7 @@ void server_listen_init(void) AutoMutexLock UserCachedLinesHashLock(&gUserCachedLinesHashLock); UserCachedLinesHashLock.lock(); if (b_UserCachedLinesHash == NULL) { - InitUserCachedLinesHashTable(); + InitUserCachedLinesHashTable(); } UserCachedLinesHashLock.unLock(); } @@ -473,6 +473,11 @@ UserCachedLinesHash* UserCachedLinesHashTableAccess(HASHACTION action, char* use ereport(ERROR, (errmsg("the user name is NULL"))); } + // Ensure that the hash table can be accessed even without initializing the plugin + if (b_UserCachedLinesHash == NULL) { + InitUserCachedLinesHashTable(); + } + result = (UserCachedLinesHash*)hash_search(b_UserCachedLinesHash, user_name, action, &found); if (action == HASH_ENTER) { Assert(!found); diff --git a/contrib/dolphin/plugin_storage/tupdesc.cpp b/contrib/dolphin/plugin_storage/tupdesc.cpp index 77745400b0d387e63aab3cc62ee4a816396c1dda..61d0c554e92ad376b71163696f76d84fc4457c7d 100644 --- a/contrib/dolphin/plugin_storage/tupdesc.cpp +++ b/contrib/dolphin/plugin_storage/tupdesc.cpp @@ -1130,7 +1130,8 @@ TupleDesc BuildDescForRelation(List *schema, Node *orientedFrom, char relkind, O (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("cache lookup failed for type %u", atttypid))); } typForm = (Form_pg_type)GETSTRUCT(typTupe); - if (typForm->typrelid >= FirstNormalObjectId && typForm->typtype == TYPTYPE_COMPOSITE) { + if (typForm->typrelid >= FirstNormalObjectId && (typForm->typtype == TYPTYPE_COMPOSITE + || typForm->typtype == TYPTYPE_ABSTRACT_OBJECT)) { HeapTuple relTupe = SearchSysCache1(RELOID, ObjectIdGetDatum(typForm->typrelid)); Form_pg_class relForm; if (HeapTupleIsValid(relTupe)) { diff --git a/contrib/dolphin/plugin_utility.cpp b/contrib/dolphin/plugin_utility.cpp index a1782ae0a9186422e406ae8c06a8324c20f9d99d..07eedb78ec782035662adef59475c58f563bfe91 100644 --- a/contrib/dolphin/plugin_utility.cpp +++ b/contrib/dolphin/plugin_utility.cpp @@ -239,6 +239,10 @@ static void analyze_tmptbl_debug_cn(Oid rel_id, Oid main_relid, VacuumStmt* stmt #endif extern void begin_delta_merge(VacuumStmt* stmt); +#ifdef DOLPHIN +extern int dolphin_process_command(StringInfo buf); +#endif + #ifdef ENABLE_MULTIPLE_NODES static void set_dndistinct_coors(VacuumStmt* stmt, int attnum); #endif @@ -3014,6 +3018,11 @@ void standard_ProcessUtility(processutility_context* processutility_cxt, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("non-DECLARE CURSOR PlannedStmt passed to ProcessUtility"))); } +#ifdef DOLPHIN + if (u_sess->proc_cxt.MyProcPort->protocol_config->fn_process_command == dolphin_process_command) { + ereport(ERROR, (errmsg("non-procedure CURSOR is not supported by mysql protocol."))); + } +#endif PerformCursorOpen(stmt, params, query_string, is_top_level); } break; @@ -5235,6 +5244,7 @@ ProcessUtilitySlow(Node *parse_tree, } #else AlterSchemaCommand((AlterSchemaStmt*)parse_tree); + commandCollected = true; #endif break; @@ -5639,17 +5649,41 @@ ProcessUtilitySlow(Node *parse_tree, if (u_sess->attr.attr_sql.enable_parallel_ddl && !is_first_node) { ExecUtilityStmtOnNodes_ParallelDDLMode( query_string, NULL, sent_to_remote, false, EXEC_ON_COORDS, false, first_exec_node); - address = DefineCompositeType(stmt->typevar, stmt->coldeflist); + if (stmt->typekind == TYPE_COMPOSITE_DEFAULT) + address = DefineCompositeType(stmt->typevar, stmt->coldeflist, stmt->replace); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE) + address = DefineObjectTypeSpec(stmt); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE_BODY) + DefineObjectTypeBody(stmt); + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("create composite type kind \"%s\" error.", stmt->typevar->relname))); ExecUtilityStmtOnNodes_ParallelDDLMode( query_string, NULL, sent_to_remote, false, EXEC_ON_DATANODES, false, first_exec_node); } else { - address = DefineCompositeType(stmt->typevar, stmt->coldeflist); + if (stmt->typekind == TYPE_COMPOSITE_DEFAULT) + address = DefineCompositeType(stmt->typevar, stmt->coldeflist, stmt->replace); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE) + address = DefineObjectTypeSpec(stmt); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE_BODY) + DefineObjectTypeBody(stmt); + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("create composite type kind \"%s\" error.", stmt->typevar->relname))); ExecUtilityStmtOnNodes(query_string, NULL, sent_to_remote, false, EXEC_ON_ALL_NODES, false); } } else #endif { - address = DefineCompositeType(stmt->typevar, stmt->coldeflist); + if (stmt->typekind == TYPE_COMPOSITE_DEFAULT) + address = DefineCompositeType(stmt->typevar, stmt->coldeflist, stmt->replace); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE) + address = DefineObjectTypeSpec(stmt); + else if (stmt->typekind == TYPE_COMPOSITE_OBJECT_TYPE_BODY) + DefineObjectTypeBody(stmt); + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("create composite type kind \"%s\" error.", stmt->typevar->relname))); } } break; @@ -6380,6 +6414,14 @@ ProcessUtilitySlow(Node *parse_tree, PG_END_TRY(); EventTriggerUndoInhibitCommandCollection(); } break; + + case T_CreateMatViewLogStmt: + address = CreateMatViewLog((CreateMatViewLogStmt*)parse_tree); + break; + + case T_DropMatViewLogStmt: + DropMatViewLog((DropMatViewLogStmt*)parse_tree); + break; case T_CreateTrigStmt: #ifdef DOLPHIN @@ -6673,7 +6715,7 @@ ProcessUtilitySlow(Node *parse_tree, ExecUtilityStmtOnNodes(query_string, exec_nodes, sent_to_remote, false, EXEC_ON_ALL_NODES, false); } } else { - ExecAlterOwnerStmt((AlterOwnerStmt*)parse_tree); + address = ExecAlterOwnerStmt((AlterOwnerStmt*)parse_tree); } #else AlterOwnerStmt *stmt = (AlterOwnerStmt *) parse_tree; @@ -6764,7 +6806,8 @@ ProcessUtilitySlow(Node *parse_tree, break; case OBJECT_TSPARSER: #ifdef PGXC - if (!IsInitdb) { + if (!IsInitdb && !u_sess->attr.attr_common.IsInplaceUpgrade + && !u_sess->exec_cxt.extension_is_valid) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("user-defined text search parser is not yet supported."))); @@ -9306,6 +9349,14 @@ const char* CreateCommandTag(Node* parse_tree) tag = "REFRESH MATERIALIZED VIEW"; break; + case T_CreateMatViewLogStmt: + tag = "CREATE MATERIALIZED VIEW LOG"; + break; + + case T_DropMatViewLogStmt: + tag = "DROP MATERIALIZED VIEW LOG"; + break; + #ifndef ENABLE_MULTIPLE_NODES case T_AlterSystemStmt: tag = "ALTER SYSTEM SET"; diff --git a/contrib/dolphin/plugin_utils/adt/date.cpp b/contrib/dolphin/plugin_utils/adt/date.cpp index 6feacd2783d29c0c83afec11de6739cd5740b8b7..4648065491f3a28cff516033c71667269815953c 100644 --- a/contrib/dolphin/plugin_utils/adt/date.cpp +++ b/contrib/dolphin/plugin_utils/adt/date.cpp @@ -318,6 +318,9 @@ extern "C" DLL_PUBLIC Datum date_add_datetime_interval(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1_PUBLIC(date_add_timestamp_interval); extern "C" DLL_PUBLIC Datum date_add_timestamp_interval(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1_PUBLIC(date_add_date_interval); +extern "C" DLL_PUBLIC Datum date_add_date_interval(PG_FUNCTION_ARGS); + extern Datum DirectFunctionCall0(PGFunction func); #endif /* common code for timetypmodin and timetztypmodin */ @@ -6468,6 +6471,24 @@ Datum date_add_timestamp_interval(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +/** + * date_add(date, INTERVAL expr UNIT) +*/ +Datum date_add_date_interval(PG_FUNCTION_ARGS) +{ + int errlevel = (!fcinfo->can_ignore && SQL_MODE_STRICT() ? ERROR : WARNING); + DateADT date = PG_GETARG_DATEADT(0); + Interval *span = PG_GETARG_INTERVAL_P(1); + Timestamp datetime = DatumGetTimestamp(DirectFunctionCall1Coll(date_timestamp, InvalidOid, + date, fcinfo->can_ignore)); + Timestamp result; + if (datetime_add_interval(datetime, span, &result)) { + return DirectFunctionCall1Coll(timestamp_date, InvalidOid, result, fcinfo->can_ignore); + } + ereport(errlevel, (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW), errmsg("date/time field value out of range"))); + PG_RETURN_NULL(); +} + static int64 getPartFromTm(pg_tm* tm, fsec_t fsec, int part) { int64 result = 0; diff --git a/contrib/dolphin/plugin_utils/adt/json.cpp b/contrib/dolphin/plugin_utils/adt/json.cpp index b451c246fa81abc54f582e98cd040303825b55d5..d021796a5870fce8f8211ebcdef5a87cbfe13d4b 100644 --- a/contrib/dolphin/plugin_utils/adt/json.cpp +++ b/contrib/dolphin/plugin_utils/adt/json.cpp @@ -2965,4 +2965,28 @@ Datum cast_json(PG_FUNCTION_ARGS) datum_to_json(val, false, result, tcategory, typoutput, false); PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len)); } + + +PG_FUNCTION_INFO_V1_PUBLIC(text_json); +extern "C" DLL_PUBLIC Datum text_json(PG_FUNCTION_ARGS); +Datum text_json(PG_FUNCTION_ARGS) +{ + text* input = PG_GETARG_TEXT_P(0); + char* str = TextDatumGetCString(input); + // error will not be ignored in mysql for json type + return DirectFunctionCall1(json_in, CStringGetDatum(str)); +} + + +PG_FUNCTION_INFO_V1_PUBLIC(varchar_json); +extern "C" DLL_PUBLIC Datum varchar_json(PG_FUNCTION_ARGS); +Datum varchar_json(PG_FUNCTION_ARGS) +{ + Datum input = PG_GETARG_DATUM(0); + char* str = NULL; + str = DatumGetCString(DirectFunctionCall1(varcharout, input)); + // error will not be ignored in mysql for json type + return DirectFunctionCall1(json_in, CStringGetDatum(str)); +} + #endif diff --git a/contrib/dolphin/plugin_utils/adt/pgstatfuncs.cpp b/contrib/dolphin/plugin_utils/adt/pgstatfuncs.cpp index e25e4f12d3ced0fe1c83cb4ce3a6991fef46fc8a..163f91d81f5a0cd68f418cf95dd48eee88919fbc 100644 --- a/contrib/dolphin/plugin_utils/adt/pgstatfuncs.cpp +++ b/contrib/dolphin/plugin_utils/adt/pgstatfuncs.cpp @@ -99,7 +99,7 @@ #define DISPLACEMENTS_VALUE 32 #define MAX_DURATION_TIME 60 #define DSS_IO_STAT_COLUMN_NUM 3 -#define ONDEMAND_RECOVERY_STAT_COLUMN_NUM 10 +#define ONDEMAND_RECOVERY_STAT_COLUMN_NUM 12 const uint32 INDEX_STATUS_VIEW_COL_NUM = 3; @@ -8723,6 +8723,9 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS) TupleDescInitEntry(tupledesc, (AttrNumber)10, "isvalid", BOOLOID, -1, 0); TupleDescInitEntry(tupledesc, (AttrNumber)11, "usage_count", INT2OID, -1, 0); TupleDescInitEntry(tupledesc, (AttrNumber)12, "pinning_backends", INT4OID, -1, 0); + TupleDescInitEntry(tupledesc, (AttrNumber)13, "segfileno", INT4OID, -1, 0); + TupleDescInitEntry(tupledesc, (AttrNumber)14, "segblockno", OIDOID, -1, 0); + TupleDescInitEntry(tupledesc, (AttrNumber)15, "aio_in_process", BOOLOID, -1, 0); fctx->tupdesc = BlessTupleDesc(tupledesc); @@ -8769,6 +8772,8 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS) fctx->record[i].blocknum = bufHdr->tag.blockNum; fctx->record[i].usagecount = BUF_STATE_GET_USAGECOUNT(buf_state); fctx->record[i].pinning_backends = BUF_STATE_GET_REFCOUNT(buf_state); + fctx->record[i].segfileno = bufHdr->extra->seg_fileno; + fctx->record[i].segblockno = bufHdr->extra->seg_blockno; if (buf_state & BM_DIRTY) fctx->record[i].isdirty = true; @@ -8781,6 +8786,12 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS) else fctx->record[i].isvalid = false; + if (bufHdr->extra->aio_in_progress) { + fctx->record[i].aio_in_process = true; + } else { + fctx->record[i].aio_in_process = false; + } + UnlockBufHdr(bufHdr, buf_state); } @@ -8825,6 +8836,9 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS) nulls[9] = false; nulls[10] = true; nulls[11] = true; + nulls[12] = true; + nulls[13] = true; + nulls[14] = true; } else { values[1] = ObjectIdGetDatum(fctx->record[i].relfilenode); nulls[1] = false; @@ -8848,6 +8862,12 @@ Datum pg_buffercache_pages(PG_FUNCTION_ARGS) nulls[10] = false; values[11] = Int32GetDatum(fctx->record[i].pinning_backends); nulls[11] = false; + values[12] = Int32GetDatum(fctx->record[i].segfileno); + nulls[12] = false; + values[13] = ObjectIdGetDatum((int64)fctx->record[i].segblockno); + nulls[13] = false; + values[14] = BoolGetDatum(fctx->record[i].aio_in_process); + nulls[14] = false; } /* Build and return the tuple. */ @@ -14793,6 +14813,8 @@ Datum get_ondemand_recovery_status(PG_FUNCTION_ARGS) TupleDescInitEntry(tupdesc, (AttrNumber)i++, "ondemand_recovery_status", TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber)i++, "realtime_build_status", TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber)i++, "recovery_pause_status", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)i++, "record_item_num", OIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber)i++, "record_item_mbytes", OIDOID, -1, 0); tupdesc = BlessTupleDesc(tupdesc); @@ -14856,24 +14878,27 @@ Datum get_ondemand_recovery_status(PG_FUNCTION_ARGS) switch (stat.recoveryPauseStatus) { case NOT_PAUSE: - values[i] = CStringGetTextDatum("NOT PAUSE"); + values[i++] = CStringGetTextDatum("NOT PAUSE"); break; case PAUSE_FOR_SYNC_REDO: - values[i] = CStringGetTextDatum("PAUSE(for sync record)"); + values[i++] = CStringGetTextDatum("PAUSE(for sync record)"); break; case PAUSE_FOR_PRUNE_HASHMAP: - values[i] = CStringGetTextDatum("PAUSE(for hashmap full)"); + values[i++] = CStringGetTextDatum("PAUSE(for hashmap full)"); break; case PAUSE_FOR_PRUNE_TRXN_QUEUE: - values[i] = CStringGetTextDatum("PAUSE(for trxn queue full)"); + values[i++] = CStringGetTextDatum("PAUSE(for trxn queue full)"); break; case PAUSE_FOR_PRUNE_SEG_QUEUE: - values[i] = CStringGetTextDatum("PAUSE(for seg queue full)"); + values[i++] = CStringGetTextDatum("PAUSE(for seg queue full)"); break; default: ereport(ERROR, (errmsg("Invalid recovery pause status."))); break; } + uint32 recordItemMemUsedInMB = stat.recordItemMemUsed / 1024 / 1024; + values[i++] = UInt32GetDatum(stat.recordItemNum); + values[i++] = UInt32GetDatum(recordItemMemUsedInMB); HeapTuple heap_tuple = heap_form_tuple(tupdesc, values, nulls); result = HeapTupleGetDatum(heap_tuple); @@ -15304,9 +15329,6 @@ Datum query_page_distribution_info_internal(text* relname, ForkNumber fork, Bloc int is_found = 0; int ret = get_drc_info(&is_found, drc_info); - if (ret != DMS_SUCCESS) { - ereport(ERROR, (errmsg("[SS] some errors occurred while querying DRC!"))); - } if (!is_found) { ereport(INFO, (errmsg("[SS] could not find a DRC entry in DRC for page (%u/%u/%u/%d/%d %d-%u)!", rnode.spcNode, rnode.dbNode, rnode.relNode, rnode.bucketNode, rnode.opt, fork, blockno))); @@ -15318,6 +15340,10 @@ Datum query_page_distribution_info_internal(text* relname, ForkNumber fork, Bloc iterate->iterate_idx = 0; count = (drc_info->claimed_owner == masterId) ? count : count + 1; + if (ret != DMS_SUCCESS) { + ereport(WARNING, (errmsg("[SS] some errors occurred while querying DRC!"))); + iterate->iterate_idx = DMS_MAX_INSTANCES; + } funcctx->user_fctx = (void*)iterate; funcctx->tuple_desc = create_query_page_distribution_info_tupdesc(); funcctx->max_calls = (!is_found) ? 0 : (count + 1); diff --git a/contrib/dolphin/plugin_utils/adt/regexp.cpp b/contrib/dolphin/plugin_utils/adt/regexp.cpp index 6d53fc9f2cce54cc8371322e05ee99be62d33f97..c90ebea6d9538e8dab30e9899a325b5b80c6a3ed 100644 --- a/contrib/dolphin/plugin_utils/adt/regexp.cpp +++ b/contrib/dolphin/plugin_utils/adt/regexp.cpp @@ -1222,6 +1222,7 @@ static regexp_matches_ctx* setup_regexp_matches(text* orig_str, text* pattern, /* search for the pattern, perhaps repeatedly */ prev_match_end = 0; while (RE_wchar_execute(cpattern, wide_str, wide_len, start_search, pmatch_len, pmatch)) { + CHECK_FOR_INTERRUPTS(); /* * If requested, ignore degenerate matches, which are zero-length * matches occurring at the start or end of a string or just after a diff --git a/contrib/dolphin/plugin_utils/adt/ri_triggers.cpp b/contrib/dolphin/plugin_utils/adt/ri_triggers.cpp index 599f96df5f1205632c08761d94ed5042c569a510..fcf998b72ca0fba8bc39fb5daf2470042586d5bf 100644 --- a/contrib/dolphin/plugin_utils/adt/ri_triggers.cpp +++ b/contrib/dolphin/plugin_utils/adt/ri_triggers.cpp @@ -2937,13 +2937,14 @@ static bool ri_PerformCheck(RI_QueryKey* qkey, SPIPlanPtr qplan, Relation fk_rel if (spi_result < 0) ereport(ERROR, (errcode(ERRCODE_SPI_EXECUTE_FAILURE), errmsg("SPI_execute_snapshot returned %d", spi_result))); - if (expect_OK >= 0 && spi_result != expect_OK) + if (expect_OK >= 0 && spi_result != expect_OK && u_sess->attr.attr_common.foreign_key_checks) ri_ReportViolation( qkey, constrname ? constrname : "", pk_rel, fk_rel, new_tuple ? new_tuple : old_tuple, NULL, true); /* XXX wouldn't it be clearer to do this part at the caller? */ if (constrname != NULL && expect_OK == SPI_OK_SELECT && - (SPI_processed == 0) == (qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK)) + (SPI_processed == 0) == (qkey->constr_queryno == RI_PLAN_CHECK_LOOKUPPK) && + u_sess->attr.attr_common.foreign_key_checks) ri_ReportViolation(qkey, constrname, pk_rel, fk_rel, new_tuple ? new_tuple : old_tuple, NULL, false); return SPI_processed != 0; diff --git a/contrib/dolphin/plugin_utils/adt/rowtypes.cpp b/contrib/dolphin/plugin_utils/adt/rowtypes.cpp index e5a7023213e1ad7cca75cf2f7177fccfd86a1996..4937d726cf6b134dd625984cbb660157a157e3a2 100644 --- a/contrib/dolphin/plugin_utils/adt/rowtypes.cpp +++ b/contrib/dolphin/plugin_utils/adt/rowtypes.cpp @@ -22,6 +22,7 @@ #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/typcache.h" +#include "catalog/pg_object_type.h" #ifdef DOLPHIN #include "catalog/pg_operator.h" #include "nodes/makefuncs.h" @@ -201,8 +202,13 @@ Datum record_in(PG_FUNCTION_ARGS) } } - column_data = buf.data; - nulls[i] = false; + if ((0 == buf.len) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !ACCEPT_EMPTY_STR) { + column_data = NULL; + nulls[i] = true; + } else { + column_data = buf.data; + nulls[i] = false; + } } /* @@ -833,6 +839,8 @@ static int record_cmp(FunctionCallInfo fcinfo) int i1; int i2; int j; + Oid orderid = InvalidOid; + Oid mapid = InvalidOid; /* Extract type info from the tuples */ tupType1 = HeapTupleHeaderGetTypeId(record1); @@ -844,6 +852,13 @@ static int record_cmp(FunctionCallInfo fcinfo) tupdesc2 = lookup_rowtype_tupdesc(tupType2, tupTypmod2); ncolumns2 = tupdesc2->natts; + /* Object types have their own order methods, just use it. */ + if (tupType2 == tupType1 && isNeedObjectCmp(tupType1, &mapid, &orderid)) { + ReleaseTupleDesc(tupdesc1); + ReleaseTupleDesc(tupdesc2); + return ObjectIntanceCmp(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), mapid, orderid); + } + /* Build temporary HeapTuple control structures */ tuple1.t_len = HeapTupleHeaderGetDatumLength(record1); ItemPointerSetInvalid(&(tuple1.t_self)); diff --git a/contrib/dolphin/plugin_utils/adt/ruleutils.cpp b/contrib/dolphin/plugin_utils/adt/ruleutils.cpp index 8a2dd70034e4df925314702836003cab641d5c99..b0ad4adfe4c126493b4fa948f180394a80b94eb3 100644 --- a/contrib/dolphin/plugin_utils/adt/ruleutils.cpp +++ b/contrib/dolphin/plugin_utils/adt/ruleutils.cpp @@ -1233,10 +1233,17 @@ static void get_table_partitiondef(StringInfo query, StringInfo buf, Oid tableoi if (partstrategy == PART_STRATEGY_INTERVAL) { resetStringInfo(query); - appendStringInfo(query, - "SELECT p.`interval`[1] AS `interval` FROM pg_partition p " - "WHERE p.parentid = %u AND p.parttype = '%c' AND p.partstrategy = '%c'", - tableoid, PART_OBJ_TYPE_PARTED_TABLE, PART_STRATEGY_INTERVAL); + if (!u_sess->attr.attr_sql.dolphin) { + appendStringInfo(query, + "SELECT p.interval[1] AS interval FROM pg_partition p " + "WHERE p.parentid = %u AND p.parttype = '%c' AND p.partstrategy = '%c'", + tableoid, PART_OBJ_TYPE_PARTED_TABLE, PART_STRATEGY_INTERVAL); + } else { + appendStringInfo(query, + "SELECT p.`interval`[1] AS `interval` FROM pg_partition p " + "WHERE p.parentid = %u AND p.parttype = '%c' AND p.partstrategy = '%c'", + tableoid, PART_OBJ_TYPE_PARTED_TABLE, PART_STRATEGY_INTERVAL); + } (void)SPI_execute(query->data, true, INT_MAX); Assert(SPI_processed == 1); @@ -3255,8 +3262,17 @@ static char* pg_get_triggerdef_worker(Oid trigid, bool pretty) appendStringInfo(&buf, "CREATE TRIGGER %s ", quote_identifier(tgname)); } } else { - appendStringInfo(&buf, "CREATE %sTRIGGER %s ", OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "", - quote_identifier(tgname)); + if (OidIsValid(trigrec->tgconstraint)) { + appendStringInfo(&buf, "CREATE CONSTRAINT TRIGGER %s ", quote_identifier(tgname)); + } else { + value = fastgetattr(ht_trig, Anum_pg_trigger_tgowner, tgrel->rd_att, &isnull); + if (DatumGetObjectId(value) != GetUserId()) { + appendStringInfo(&buf, "CREATE DEFINER = %s TRIGGER %s ", GetUserNameFromId(DatumGetObjectId(value)), + quote_identifier(tgname)); + } else { + appendStringInfo(&buf, "CREATE TRIGGER %s ", quote_identifier(tgname)); + } + } } if (TRIGGER_FOR_BEFORE(trigrec->tgtype)) @@ -4895,6 +4911,7 @@ char* pg_get_functiondef_worker(Oid funcid, int* headerlines) bool isOraFunc = false; bool isDolphinStyle = false; char* pkgname = NULL; + char* typname = NULL; initStringInfo(&buf); /* Look up the function */ @@ -4939,21 +4956,30 @@ char* pg_get_functiondef_worker(Oid funcid, int* headerlines) Datum datum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prokind, &isnull); proIsProcedure = isnull ? false : PROC_IS_PRO(CharGetDatum(datum)); } - + bool ispackage = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_package, &isnull); Datum packageOidDatum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_packageid, &isnull); - if (!isnull) + if (!isnull && ispackage) { Oid packageoid = DatumGetObjectId(packageOidDatum); if (OidIsValid(packageoid)) { pkgname = GetPackageName(packageoid); } + } + if (!isnull && !ispackage) { + Oid typeoid = DatumGetObjectId(packageOidDatum); + if (OidIsValid(typeoid)) { + typname = get_typename(typeoid); + } } if (proIsProcedure) { if (pkgname != NULL) { appendStringInfo(&buf, "CREATE OR REPLACE PROCEDURE %s(", quote_qualified_identifier(nsp, pkgname, name)); - } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + } else if (typname != NULL) { + appendStringInfo(&buf, "CREATE OR REPLACE PROCEDURE %s(", + quote_qualified_identifier(nsp, typname, name)); + } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { appendStringInfo(&buf, "CREATE DEFINER = %s PROCEDURE %s(", GetUserNameFromId(proc->proowner), quote_qualified_identifier(nsp, name)); } else { @@ -4965,7 +4991,10 @@ char* pg_get_functiondef_worker(Oid funcid, int* headerlines) if (pkgname != NULL) { appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(", quote_qualified_identifier(nsp, pkgname, name)); - } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + } else if (typname != NULL) { + appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(", + quote_qualified_identifier(nsp, typname, name)); + } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { appendStringInfo(&buf, "CREATE DEFINER = %s FUNCTION %s(", GetUserNameFromId(proc->proowner), quote_qualified_identifier(nsp, name)); } else { @@ -9140,6 +9169,12 @@ static char* get_variable( /* Identify names to use */ schemaname = NULL; /* default assumptions */ + + if (NULL != rte->relname && u_sess->hook_cxt.forTsdbHook) { + rte->relname = get_rel_name(rte->relid); + rte->eref->aliasname = rte->relname; + } + refname = rte->eref->aliasname; /* Exceptions occur only if the RTE is alias-less */ @@ -11049,6 +11084,16 @@ static void get_rule_expr(Node* node, deparse_context* context, bool showimplici appendStringInfo(buf, "CURSOR(%s)", stmt->raw_query_str); } break; + case T_TypeCast: { + TypeCast* tc = (TypeCast*) node; + if (showimplicit) { + get_coercion_expr(tc->arg, context, tc->typname->typeOid, -1, node); + } else { + /* don't show the implicit cast */ + get_rule_expr_paren(tc->arg, context, false, node, no_alias); + } + } break; + #ifdef USE_SPQ case T_DMLActionExpr: appendStringInfo(buf, "DMLAction"); @@ -12217,32 +12262,39 @@ static void get_delete_from_partition_clause(RangeTblEntry* rte, StringInfo buf) appendStringInfo(buf, " PARTITION ("); #ifdef DOLPHIN - ListCell *partNameCell = NULL; - ListCell *subpartNameCell = NULL; + ListCell *partNameCell = list_head(rte->partitionNameList); + ListCell *subpartNameCell = list_head(rte->subpartitionNameList); char *nameStr = NULL; - forfour(partCell, rte->partitionOidList, subpartCell, rte->subpartitionOidList, - partNameCell, rte->partitionNameList, subpartNameCell, rte->subpartitionNameList) { -#else forboth(partCell, rte->partitionOidList, subpartCell, rte->subpartitionOidList) { -#endif partitionOid = lfirst_oid(subpartCell); List *list = rte->subpartitionNameList; -#ifdef DOLPHIN - nameStr = strVal(lfirst(subpartNameCell)); -#endif + if (unlikely(subpartNameCell != NULL)) { + nameStr = strVal(lfirst(subpartNameCell)); + } if (!OidIsValid(partitionOid)) { /* InvalidOid means all subpartitions of this partition, just use partition oid. */ partitionOid = lfirst_oid(partCell); -#ifdef DOLPHIN - nameStr = strVal(lfirst(partNameCell)); -#endif + if (unlikely(partNameCell != NULL)) { + nameStr = strVal(lfirst(partNameCell)); + } } -#ifdef DOLPHIN name = getPartitionName(partitionOid, true); if (name == NULL) { name = nameStr; } -#else + if (unlikely(partNameCell != NULL)) { + partNameCell = lnext(partNameCell); + } + if (unlikely(subpartNameCell != NULL)) { + subpartNameCell = lnext(subpartNameCell); + } +#else + forboth(partCell, rte->partitionOidList, subpartCell, rte->subpartitionOidList) { + partitionOid = lfirst_oid(subpartCell); + if (!OidIsValid(partitionOid)) { + /* InvalidOid means all subpartitions of this partition, just use partition oid. */ + partitionOid = lfirst_oid(partCell); + } name = getPartitionName(partitionOid, false); #endif if (first) { @@ -13096,8 +13148,9 @@ static char* generate_function_name( ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for function %u", funcid))); procform = (Form_pg_proc)GETSTRUCT(proctup); proname = NameStr(procform->proname); + bool ispackage = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_package, &isnull); pkgOiddatum = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_packageid, &isnull); - if (!isnull) { + if (!isnull && ispackage) { pkgOid = DatumGetObjectId(pkgOiddatum); pkgname = GetPackageName(pkgOid); } diff --git a/contrib/dolphin/plugin_utils/adt/timestamp.cpp b/contrib/dolphin/plugin_utils/adt/timestamp.cpp index 46e84206cce4bcaa30c0e45ac0fe617d0b5d49c5..69ecf04eb6bd133e6ff00dfa6800cd8ddeaf7c73 100644 --- a/contrib/dolphin/plugin_utils/adt/timestamp.cpp +++ b/contrib/dolphin/plugin_utils/adt/timestamp.cpp @@ -592,8 +592,14 @@ bool TimestampTypeCheck(char* str, bool can_ignore, struct pg_tm* tm, Timestamp if (tm2timestamp(tm, fsec, NULL, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range: \"%s\"", str))); - break; + if (tm->tm_year < MIN_VALUE_YEAR || tm->tm_year > MAX_VALUE_YEAR || tm->tm_year == 0) { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("invalid data for \"year = %d\", value must be between -4712 and 9999," \ + " and not be 0", tm->tm_year))); + } + break; case DTK_EPOCH: result = SetEpochTimestamp(); break; diff --git a/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp b/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp index 06d6f6813ed239c1108f0611765aa5271b4b6330..4680722259622b0d707d9930eab06c8f67c514bb 100644 --- a/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp +++ b/contrib/dolphin/plugin_utils/adt/unsigned_int.cpp @@ -4309,7 +4309,7 @@ int128 text_uintInternal(Datum txt, int128 min, int128 max, char* intType, bool int128 result; tmp = DatumGetCString(DirectFunctionCall1(textout, txt)); - result = DatumGetInt128(DirectFunctionCall1Coll(int16in, InvalidOid, CStringGetDatum(tmp), canIgnore)); + result = DatumGetInt128(DirectFunctionCall1Coll(int16in, InvalidOid, CStringGetDatum(tmp), canIgnore)); pfree_ext(tmp); /* keyword IGNORE has higher priority than sql mode */ @@ -4912,7 +4912,7 @@ Datum bpchar_uint8(PG_FUNCTION_ARGS) Datum result; tmp = DatumGetCString(DirectFunctionCall1(bpcharout, txt)); - result = DirectFunctionCall1Coll(uint8in, InvalidOid, CStringGetDatum(tmp), fcinfo->can_ignore); + result = DirectFunctionCall1Coll(uint8in, InvalidOid, CStringGetDatum(tmp), fcinfo->can_ignore); pfree_ext(tmp); PG_RETURN_DATUM(result); @@ -4974,7 +4974,7 @@ Datum varchar_uint8(PG_FUNCTION_ARGS) Datum result; tmp = DatumGetCString(DirectFunctionCall1(varcharout, txt)); - result = DirectFunctionCall1Coll(uint8in, InvalidOid, CStringGetDatum(tmp), fcinfo->can_ignore); + result = DirectFunctionCall1Coll(uint8in, InvalidOid, CStringGetDatum(tmp), fcinfo->can_ignore); pfree_ext(tmp); PG_RETURN_DATUM(result); @@ -5342,4 +5342,98 @@ Datum dolphin_enumnot(PG_FUNCTION_ARGS) ReleaseSysCache(tup); PG_RETURN_UINT64(~DatumGetUInt64(DirectFunctionCall1(f8_cast_ui8, Float8GetDatum(result)))); } + +PG_FUNCTION_INFO_V1_PUBLIC(int8_cmp_uint1); +extern "C" DLL_PUBLIC Datum int8_cmp_uint1(PG_FUNCTION_ARGS); +Datum int8_cmp_uint1(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + uint8 arg2 = PG_GETARG_UINT8(1); + + if (arg1 > arg2) { + PG_RETURN_INT32(1); + } else if (arg1 < arg2) { + PG_RETURN_INT32(-1); + } else { + PG_RETURN_INT32(0); + } +} + +PG_FUNCTION_INFO_V1_PUBLIC(int8_cmp_uint2); +extern "C" DLL_PUBLIC Datum int8_cmp_uint2(PG_FUNCTION_ARGS); +Datum int8_cmp_uint2(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + uint16 arg2 = PG_GETARG_UINT16(1); + + if (arg1 > arg2) { + PG_RETURN_INT32(1); + } else if (arg1 < arg2) { + PG_RETURN_INT32(-1); + } else { + PG_RETURN_INT32(0); + } +} + +PG_FUNCTION_INFO_V1_PUBLIC(int8_cmp_uint4); +extern "C" DLL_PUBLIC Datum int8_cmp_uint4(PG_FUNCTION_ARGS); +Datum int8_cmp_uint4(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + uint32 arg2 = PG_GETARG_UINT32(1); + + if (arg1 > arg2) { + PG_RETURN_INT32(1); + } else if (arg1 < arg2) { + PG_RETURN_INT32(-1); + } else { + PG_RETURN_INT32(0); + } +} + +PG_FUNCTION_INFO_V1_PUBLIC(int8_cmp_uint8); +extern "C" DLL_PUBLIC Datum int8_cmp_uint8(PG_FUNCTION_ARGS); +Datum int8_cmp_uint8(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + uint64 arg2 = PG_GETARG_UINT64(1); + if (arg1 < 0 || (uint64)arg1 < arg2) { + PG_RETURN_INT32(-1); + } else if ((uint64)arg1 > arg2) { + PG_RETURN_INT32(1); + } else { + PG_RETURN_INT32(0); + } +} + +PG_FUNCTION_INFO_V1_PUBLIC(int2_eq_uint1); +extern "C" DLL_PUBLIC Datum int2_eq_uint1(PG_FUNCTION_ARGS); +Datum int2_eq_uint1(PG_FUNCTION_ARGS) +{ + int16 arg1 = PG_GETARG_INT16(0); + uint8 arg2 = PG_GETARG_UINT8(1); + + PG_RETURN_BOOL(arg1 == arg2); +} + +PG_FUNCTION_INFO_V1_PUBLIC(int4_eq_uint1); +extern "C" DLL_PUBLIC Datum int4_eq_uint1(PG_FUNCTION_ARGS); +Datum int4_eq_uint1(PG_FUNCTION_ARGS) +{ + int32 arg1 = PG_GETARG_INT32(0); + uint8 arg2 = PG_GETARG_UINT8(1); + + PG_RETURN_BOOL(arg1 == arg2); +} + +PG_FUNCTION_INFO_V1_PUBLIC(int8_eq_uint1); +extern "C" DLL_PUBLIC Datum int8_eq_uint1(PG_FUNCTION_ARGS); +Datum int8_eq_uint1(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + uint8 arg2 = PG_GETARG_UINT8(1); + + PG_RETURN_BOOL(arg1 == arg2); +} + #endif diff --git a/contrib/dolphin/plugin_utils/adt/varbit.cpp b/contrib/dolphin/plugin_utils/adt/varbit.cpp index 1194a9f38949241cf1f348fe8ea73eabfc5e4ec4..c23cae66e2ec0171ff60faaccb5c40fe155816e8 100644 --- a/contrib/dolphin/plugin_utils/adt/varbit.cpp +++ b/contrib/dolphin/plugin_utils/adt/varbit.cpp @@ -2619,9 +2619,24 @@ PG_FUNCTION_INFO_V1_PUBLIC(bittovarbinary); extern "C" DLL_PUBLIC Datum bittovarbinary(PG_FUNCTION_ARGS); Datum bittovarbinary(PG_FUNCTION_ARGS) { - Datum dec = bittobigint(PG_GETARG_VARBIT_P(0), true); - Datum str = DirectFunctionCall1(uint8out, dec); - PG_RETURN_DATUM(DirectFunctionCall1(byteain, str)); + VarBit* bits = PG_GETARG_VARBIT_P(0); + int bytelen = VARBITBYTES(bits); + int charsperbyte = 2; + int bitcharlen = 4; + int strlen = bytelen * charsperbyte; + char* result = (char*)palloc(strlen + charsperbyte + 1); + char* str = result; + result[0] = '\\'; + result[1] = 'x'; + result[strlen + charsperbyte] = '\0'; + result += charsperbyte; + do { + char s1 = char(bits->bit_dat[--bytelen] >> bitcharlen); + char s2 = char(bits->bit_dat[bytelen] & 0xf); + result[--strlen] = HEX_CHARS[s2]; + result[--strlen] = HEX_CHARS[s1]; + } while (bytelen > 0); + PG_RETURN_DATUM(DirectFunctionCall1(dolphin_binaryin, CStringGetDatum(str))); } Datum bit_bin_in(PG_FUNCTION_ARGS) diff --git a/contrib/dolphin/plugin_utils/adt/varlena.cpp b/contrib/dolphin/plugin_utils/adt/varlena.cpp index a5fe01e8e40fb7b46697a8f7a6c51961bbde2554..32653d4c35d4c3ddaff622e297edf73c654f774f 100644 --- a/contrib/dolphin/plugin_utils/adt/varlena.cpp +++ b/contrib/dolphin/plugin_utils/adt/varlena.cpp @@ -65,6 +65,7 @@ #include "plugin_utils/varbit.h" #include "plugin_utils/timestamp.h" #include "plugin_utils/date.h" +#include "plugin_utils/int16.h" #include "libpq/libpq-int.h" #include "plugin_utils/varlena.h" #include "catalog/pg_cast.h" @@ -1708,13 +1709,13 @@ Datum text_substr_no_len(PG_FUNCTION_ARGS) * * The result is always a freshly palloc'd datum. */ -text* text_substring(Datum str, int32 start, int32 length, bool length_not_specified) +text* text_substring(Datum str, int64 start, int64 length, bool length_not_specified) { - int32 eml = pg_database_encoding_max_length(); - int32 S = start; /* start position */ - int32 S1; /* adjusted start position */ - int32 L1; /* adjusted substring length */ - int32 E; /* end position */ + int64 eml = pg_database_encoding_max_length(); + int64 S = start; /* start position */ + int64 S1; /* adjusted start position */ + int64 L1; /* adjusted substring length */ + int64 E; /* end position */ /* * SQL99 says S can be zero or negative, but we still must fetch from the @@ -1733,7 +1734,7 @@ text* text_substring(Datum str, int32 start, int32 length, bool length_not_speci /* SQL99 says to throw an error for E < S, i.e., negative length */ ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); L1 = -1; /* silence stupider compilers */ - } else if (pg_add_s32_overflow(S, length, &E)) { + } else if (pg_add_s64_overflow(S, length, &E)) { /* * L could be large enough for S + L to overflow, in which case * the substring must run to end of string. @@ -1758,12 +1759,12 @@ text* text_substring(Datum str, int32 start, int32 length, bool length_not_speci * detoasting, so we'll grab a conservatively large slice now and go * back later to do the right thing */ - int32 slice_start; - int32 slice_size; - int32 slice_strlen; + int64 slice_start; + int64 slice_size; + int64 slice_strlen; text* slice = NULL; - int32 E1; - int32 i; + int64 E1; + int64 i; char* p = NULL; char* s = NULL; text* ret = NULL; @@ -1782,7 +1783,7 @@ text* text_substring(Datum str, int32 start, int32 length, bool length_not_speci /* SQL99 says to throw an error for E < S, i.e., negative length */ ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); slice_size = L1 = -1; /* silence stupider compilers */ - } else if (pg_add_s32_overflow(S, length, &E)) { + } else if (pg_add_s64_overflow(S, length, &E)) { /* * L could be large enough for S + L to overflow, in which case * the substring must run to end of string. @@ -1808,7 +1809,7 @@ text* text_substring(Datum str, int32 start, int32 length, bool length_not_speci * position plus substring length times the encoding max length. * If that overflows, we can just use -1. */ - if (pg_mul_s32_overflow(E, eml, &slice_size)) { + if (pg_mul_s64_overflow(E, eml, &slice_size)) { slice_size = -1; } } @@ -5896,6 +5897,38 @@ Datum to_hex64(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(cstring_to_text(ptr)); } #ifdef DOLPHIN +PG_FUNCTION_INFO_V1_PUBLIC(uint1_to_hex); +extern "C" DLL_PUBLIC Datum uint1_to_hex(PG_FUNCTION_ARGS); +Datum uint1_to_hex(PG_FUNCTION_ARGS) +{ + uint8 arg = PG_GETARG_UINT8(0); + PG_RETURN_DATUM(DirectFunctionCall1(int_to_hex, Int128GetDatum((int128)arg))); +} + +PG_FUNCTION_INFO_V1_PUBLIC(uint2_to_hex); +extern "C" DLL_PUBLIC Datum uint2_to_hex(PG_FUNCTION_ARGS); +Datum uint2_to_hex(PG_FUNCTION_ARGS) +{ + uint16 arg = PG_GETARG_UINT16(0); + PG_RETURN_DATUM(DirectFunctionCall1(int_to_hex, Int128GetDatum((int128)arg))); +} + +PG_FUNCTION_INFO_V1_PUBLIC(uint4_to_hex); +extern "C" DLL_PUBLIC Datum uint4_to_hex(PG_FUNCTION_ARGS); +Datum uint4_to_hex(PG_FUNCTION_ARGS) +{ + uint32 arg = PG_GETARG_UINT32(0); + PG_RETURN_DATUM(DirectFunctionCall1(int_to_hex, Int128GetDatum((int128)arg))); +} + +PG_FUNCTION_INFO_V1_PUBLIC(uint8_to_hex); +extern "C" DLL_PUBLIC Datum uint8_to_hex(PG_FUNCTION_ARGS); +Datum uint8_to_hex(PG_FUNCTION_ARGS) +{ + uint64 arg = PG_GETARG_UINT64(0); + PG_RETURN_DATUM(DirectFunctionCall1(int_to_hex, Int128GetDatum((int128)arg))); +} + #define HEX_BUF_LEN 32 /* * Convert an int128 to a string containing a base 16 (hex) representation of the input. @@ -7632,95 +7665,109 @@ Datum text_concat_ws(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } -/* - * Return first n characters in the string. When n is negative, - * return all but last |n| characters. - */ -Datum text_left(PG_FUNCTION_ARGS) +Datum text_left_right_helper(text* str, int64 n, bool isleft, PG_FUNCTION_ARGS) { - text* str = PG_GETARG_TEXT_PP(0); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)str)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_left could not support more than 1GB clob/blob data"))); - } const char* p = VARDATA_ANY(str); - int len = VARSIZE_ANY_EXHDR(str); - int n = PG_GETARG_INT32(1); - int part_off = 0; - int rlen; + int64 len = VARSIZE_ANY_EXHDR(str); + int64 part_off = 0; + int64 off; text* part_str = NULL; if (n < 0) { #ifdef DOLPHIN PG_RETURN_TEXT_P(cstring_to_text("")); #else - n = pg_mbstrlen_with_len(p, len) + n; + n = isleft ? (pg_mbstrlen_with_len(p, len) + n) : -n; #endif + } else if (!isleft) { + n = pg_mbstrlen_with_len(p, len) - n; } if (n >= 0) { - part_str = text_substring(PointerGetDatum(str), 1, n, false); + part_str = text_substring(PointerGetDatum(str), (int64)1, (int64)n, false); if (part_str != NULL) { part_off = VARSIZE_ANY_EXHDR(part_str); pfree_ext(part_str); } } #ifdef DOLPHIN - rlen = pg_mbcliplen(p, len, part_off); + off = pg_mbcliplen(p, len, part_off); #else - rlen = pg_mbcharcliplen(p, len, part_off); + off = pg_mbcharcliplen(p, len, part_off); #endif - if (0 == rlen && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !ACCEPT_EMPTY_STR) { + if ((isleft && 0 == off || !isleft && 0 == (len - off)) && + u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !ACCEPT_EMPTY_STR) { PG_RETURN_NULL(); } - PG_RETURN_TEXT_P(cstring_to_text_with_len(p, rlen)); + PG_RETURN_TEXT_P((isleft ? cstring_to_text_with_len(p, off) : cstring_to_text_with_len(p + off, len - off))); } + /* - * Return last n characters in the string. When n is negative, - * return all but first |n| characters. + * Return first n characters in the string. When n is negative, + * return all but last |n| characters. */ -Datum text_right(PG_FUNCTION_ARGS) +Datum text_left(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)str)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_right could not support more than 1GB clob/blob data"))); + errmsg("text_left could not support more than 1GB clob/blob data"))); } - const char* p = VARDATA_ANY(str); - int len = VARSIZE_ANY_EXHDR(str); int n = PG_GETARG_INT32(1); - int part_off = 0; - int off; - text* part_str = NULL; + return text_left_right_helper(str, n, true, fcinfo); +} - if (n < 0) #ifdef DOLPHIN +PG_FUNCTION_INFO_V1_PUBLIC(text_left_numeric); +extern "C" DLL_PUBLIC Datum text_left_numeric(PG_FUNCTION_ARGS); +Datum text_left_numeric(PG_FUNCTION_ARGS) +{ + text* str = PG_GETARG_TEXT_PP(0); + if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)str)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("text_left could not support more than 1GB clob/blob data"))); + } + int128 n = DatumGetInt128(DirectFunctionCall1(numeric_int16, PG_GETARG_DATUM(1))); + if (n > (int128)INT64_MAX) { PG_RETURN_TEXT_P(cstring_to_text("")); -#else - n = -n; + } + return text_left_right_helper(str, (int64)n, true, fcinfo); +} #endif - else - n = pg_mbstrlen_with_len(p, len) - n; - if (n >= 0) { - part_str = text_substring(PointerGetDatum(str), 1, n, false); - if (part_str != NULL) { - part_off = VARSIZE_ANY_EXHDR(part_str); - pfree_ext(part_str); - } +/* + * Return last n characters in the string. When n is negative, + * return all but first |n| characters. + */ +Datum text_right(PG_FUNCTION_ARGS) +{ + text* str = PG_GETARG_TEXT_PP(0); + if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)str)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("text_right could not support more than 1GB clob/blob data"))); } + int n = PG_GETARG_INT32(1); + return text_left_right_helper(str, n, false, fcinfo); +} + #ifdef DOLPHIN - off = pg_mbcliplen(p, len, part_off); -#else - off = pg_mbcharcliplen(p, len, part_off); -#endif - if (0 == (len - off) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && !ACCEPT_EMPTY_STR) { - PG_RETURN_NULL(); +PG_FUNCTION_INFO_V1_PUBLIC(text_right_numeric); +extern "C" DLL_PUBLIC Datum text_right_numeric(PG_FUNCTION_ARGS); +Datum text_right_numeric(PG_FUNCTION_ARGS) +{ + text* str = PG_GETARG_TEXT_PP(0); + if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)str)) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("text_right could not support more than 1GB clob/blob data"))); } - - PG_RETURN_TEXT_P(cstring_to_text_with_len(p + off, len - off)); + int128 n = DatumGetInt128(DirectFunctionCall1(numeric_int16, PG_GETARG_DATUM(1))); + if (n > (int128)INT64_MAX) { + PG_RETURN_TEXT_P(cstring_to_text("")); + } + return text_left_right_helper(str, (int64)n, false, fcinfo); } +#endif /* * Return reversed string @@ -8251,7 +8298,7 @@ Datum db_b_format_locale(PG_FUNCTION_ARGS) } Oid first_param_oid = get_fn_expr_argtype(fcinfo->flinfo, 0); char* ch_value = db_b_format_get_cstring(PG_GETARG_DATUM(0), first_param_oid); - int precision = PG_GETARG_INT32(1); + int precision = (int)PG_GETARG_INT64(1); Oid third_param_oid = get_fn_expr_argtype(fcinfo->flinfo, 2); if (PG_ARGISNULL(2)) { @@ -8268,7 +8315,7 @@ Datum db_b_format(PG_FUNCTION_ARGS) } Oid first_oid = get_fn_expr_argtype(fcinfo->flinfo, 0); char* ch_value = db_b_format_get_cstring(PG_GETARG_DATUM(0), first_oid); - int precision = PG_GETARG_INT32(1); + int precision = (int)PG_GETARG_INT64(1); PG_RETURN_TEXT_P(cstring_to_text(db_b_format_transfer(ch_value, precision, "en_US"))); } #endif @@ -9247,6 +9294,55 @@ Datum bytea_right(PG_FUNCTION_ARGS) } } +static Datum binary_right_numeric_interval(PG_FUNCTION_ARGS) +{ + int128 n = DatumGetInt128(DirectFunctionCall1(numeric_int16, PG_GETARG_DATUM(1))); + if (n > (int128)INT64_MAX) { + PG_RETURN_NULL(); + } + Datum txtResult = DirectFunctionCall2Coll(text_right_numeric, PG_GET_COLLATION(), + PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), fcinfo->can_ignore); + return DirectFunctionCall1Coll(texttoraw, PG_GET_COLLATION(), txtResult, fcinfo->can_ignore); +} + +static Datum binary_left_numeric_interval(PG_FUNCTION_ARGS) +{ + int128 n = DatumGetInt128(DirectFunctionCall1(numeric_int16, PG_GETARG_DATUM(1))); + if (n > (int128)INT64_MAX) { + PG_RETURN_NULL(); + } + Datum txtResult = DirectFunctionCall2Coll(text_left_numeric, PG_GET_COLLATION(), + PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), fcinfo->can_ignore); + return DirectFunctionCall1Coll(texttoraw, PG_GET_COLLATION(), txtResult, fcinfo->can_ignore); +} + +PG_FUNCTION_INFO_V1_PUBLIC(bytea_right_numeric); +extern "C" DLL_PUBLIC Datum bytea_right_numeric(PG_FUNCTION_ARGS); +Datum bytea_right_numeric(PG_FUNCTION_ARGS) +{ + return binary_right_numeric_interval(fcinfo); +} + +PG_FUNCTION_INFO_V1_PUBLIC(blob_right_numeric); +extern "C" DLL_PUBLIC Datum blob_right_numeric(PG_FUNCTION_ARGS); +Datum blob_right_numeric(PG_FUNCTION_ARGS) +{ + return binary_right_numeric_interval(fcinfo); +} + +PG_FUNCTION_INFO_V1_PUBLIC(bytea_left_numeric); +extern "C" DLL_PUBLIC Datum bytea_left_numeric(PG_FUNCTION_ARGS); +Datum bytea_left_numeric(PG_FUNCTION_ARGS) +{ + return binary_left_numeric_interval(fcinfo); +} + +PG_FUNCTION_INFO_V1_PUBLIC(blob_left_numeric); +extern "C" DLL_PUBLIC Datum blob_left_numeric(PG_FUNCTION_ARGS); +Datum blob_left_numeric(PG_FUNCTION_ARGS) +{ + return binary_left_numeric_interval(fcinfo); +} bool isNumeric(const char* str) { diff --git a/contrib/dolphin/proto_jdbc/class/MySQLJdbcTest.java b/contrib/dolphin/proto_jdbc/class/MySQLJdbcTest.java index acbf171a6855058fbd260fd1eaf172aed15b2c1c..ee575ff408d00893da6d2fd32dc39269fd516b2b 100644 --- a/contrib/dolphin/proto_jdbc/class/MySQLJdbcTest.java +++ b/contrib/dolphin/proto_jdbc/class/MySQLJdbcTest.java @@ -139,6 +139,9 @@ public class MySQLJdbcTest { System.out.println(resultSet.getObject(i)); } } + statement.executeQuery("START TRANSACTION;"); + statement.executeQuery("CURSOR cursor2 FOR VALUES(1,2),(0,3) ORDER BY 1;"); + statement.executeQuery("END;"); } } } diff --git a/contrib/dolphin/rollback_script/dolphin--4.0--3.0.sql b/contrib/dolphin/rollback_script/dolphin--4.0--3.0.sql index 6abc0b28dfb7d5a36cb3319af8e0b5662d315e83..18ff06d7d0c0ef93d93f7472f2ceae7485c084bc 100644 --- a/contrib/dolphin/rollback_script/dolphin--4.0--3.0.sql +++ b/contrib/dolphin/rollback_script/dolphin--4.0--3.0.sql @@ -43,6 +43,30 @@ DROP FUNCTION IF EXISTS pg_catalog.mid(varbinary, int, int); DROP FUNCTION IF EXISTS pg_catalog.mid(bit, int); DROP FUNCTION IF EXISTS pg_catalog.mid(bit, int, int); +DROP FUNCTION IF EXISTS pg_catalog.mid(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(boolean, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(binary, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(varbinary, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(bit, bit); + +DROP FUNCTION IF EXISTS pg_catalog.mid(text, bit, int); +DROP FUNCTION IF EXISTS pg_catalog.mid(boolean, bit, int); +DROP FUNCTION IF EXISTS pg_catalog.mid(binary, bit, int); +DROP FUNCTION IF EXISTS pg_catalog.mid(varbinary, bit, int); +DROP FUNCTION IF EXISTS pg_catalog.mid(bit, bit, int); + +DROP FUNCTION IF EXISTS pg_catalog.mid(text, int, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(boolean, int, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(binary, int, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(varbinary, int, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(bit, int, bit); + +DROP FUNCTION IF EXISTS pg_catalog.mid(text, bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(boolean, bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(binary, bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(varbinary, bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.mid(bit, bit, bit); + DROP FUNCTION IF EXISTS pg_catalog.log10(float8); CREATE OR REPLACE FUNCTION pg_catalog.log10(float8) RETURNS float8 @@ -122,6 +146,372 @@ DROP FUNCTION IF EXISTS pg_catalog.microsecond(json); DROP FUNCTION IF EXISTS pg_catalog.microsecond(integer); DROP FUNCTION IF EXISTS pg_catalog.microsecond(float); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, year); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, text); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, json); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, year); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, text); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, json); +DROP FUNCTION IF EXISTS pg_catalog.right(year, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(year, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(year, year); +DROP FUNCTION IF EXISTS pg_catalog.right(year, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(year, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(year, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(year, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(year, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, text); +DROP FUNCTION IF EXISTS pg_catalog.right(year, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(year, json); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, year); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, text); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, json); +DROP FUNCTION IF EXISTS pg_catalog.right(json, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(json, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(json, year); +DROP FUNCTION IF EXISTS pg_catalog.right(json, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(json, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(json, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(json, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(json, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, text); +DROP FUNCTION IF EXISTS pg_catalog.right(json, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(json, json); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, year); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, text); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, json); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, year); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, text); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, json); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, year); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, text); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, json); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(text, year); +DROP FUNCTION IF EXISTS pg_catalog.right(text, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(text, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(text, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(text, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(text, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, text); +DROP FUNCTION IF EXISTS pg_catalog.right(text, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(text, json); + +DROP FUNCTION IF EXISTS pg_catalog.left(bit, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, year); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, text); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, json); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, year); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, text); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, json); +DROP FUNCTION IF EXISTS pg_catalog.left(year, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(year, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(year, year); +DROP FUNCTION IF EXISTS pg_catalog.left(year, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(year, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(year, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(year, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(year, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, text); +DROP FUNCTION IF EXISTS pg_catalog.left(year, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(year, json); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, year); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, text); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, json); +DROP FUNCTION IF EXISTS pg_catalog.left(json, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(json, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(json, year); +DROP FUNCTION IF EXISTS pg_catalog.left(json, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(json, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(json, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(json, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(json, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, text); +DROP FUNCTION IF EXISTS pg_catalog.left(json, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(json, json); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, year); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, text); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, json); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, year); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, text); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, json); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, year); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, text); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, json); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(text, year); +DROP FUNCTION IF EXISTS pg_catalog.left(text, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(text, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(text, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(text, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(text, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, text); +DROP FUNCTION IF EXISTS pg_catalog.left(text, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(text, json); +DROP FUNCTION IF EXISTS pg_catalog.left(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(text, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(text, numeric); + DROP OPERATOR IF EXISTS pg_catalog.>(boolean, bit); DROP OPERATOR IF EXISTS pg_catalog.>=(boolean, bit); DROP OPERATOR IF EXISTS pg_catalog.<(boolean, bit); @@ -392,6 +782,7 @@ DROP OPERATOR CLASS IF EXISTS pg_catalog.uint1_ops USING ubtree; DROP OPERATOR CLASS IF EXISTS pg_catalog.uint2_ops USING ubtree; DROP OPERATOR CLASS IF EXISTS pg_catalog.uint4_ops USING ubtree; DROP OPERATOR CLASS IF EXISTS pg_catalog.uint8_ops USING ubtree; +DROP OPERATOR CLASS IF EXISTS pg_catalog.year_ops USING ubtree; DROP FUNCTION IF EXISTS pg_catalog.chara(variadic arr "any") cascade; CREATE OR REPLACE FUNCTION pg_catalog.chara(variadic arr "any") returns text LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'm_char'; @@ -455,6 +846,17 @@ CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (date) RETURNS float8 LANGUAGE CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (time) RETURNS float8 LANGUAGE SQL STABLE STRICT as 'select pg_catalog.date_part(''week'', $1)'; CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (timestamp(0) with time zone) RETURNS float8 LANGUAGE SQL STABLE STRICT as 'select pg_catalog.date_part(''week'', $1)'; +DROP FUNCTION IF EXISTS pg_catalog.hex(uint1); +DROP FUNCTION IF EXISTS pg_catalog.hex(uint2); +DROP FUNCTION IF EXISTS pg_catalog.hex(uint4); +DROP FUNCTION IF EXISTS pg_catalog.hex(uint8); + +-- binary +DROP AGGREGATE IF EXISTS pg_catalog.bit_and(binary); +DROP FUNCTION IF EXISTS pg_catalog.binary_and(binary, binary) CASCADE; +DROP FUNCTION IF EXISTS pg_catalog.binary_varbinary(binary) CASCADE; +-- uint8 +drop aggregate if exists pg_catalog.bit_and(uint8); -- json DROP aggregate IF EXISTS pg_catalog.max(json); DROP aggregate IF EXISTS pg_catalog.min(json); @@ -559,6 +961,20 @@ DROP FUNCTION IF EXISTS pg_catalog.op_tblob_add_intr (tinyblob, interval); DROP FUNCTION IF EXISTS pg_catalog.op_intr_add_tblob (interval, tinyblob); DROP FUNCTION IF EXISTS pg_catalog.op_tblob_sub_intr (tinyblob, interval); +DROP OPERATOR IF EXISTS pg_catalog.+ (anyenum, interval); +DROP OPERATOR IF EXISTS pg_catalog.+ (interval, anyenum); +DROP OPERATOR IF EXISTS pg_catalog.- (anyenum, interval); +DROP OPERATOR IF EXISTS pg_catalog.+ (anyset, interval); +DROP OPERATOR IF EXISTS pg_catalog.+ (interval, anyset); +DROP OPERATOR IF EXISTS pg_catalog.- (anyset, interval); + +DROP FUNCTION IF EXISTS pg_catalog.op_enum_add_intr (anyenum, interval); +DROP FUNCTION IF EXISTS pg_catalog.op_intr_add_enum (interval, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.op_enum_sub_intr (anyenum, interval); +DROP FUNCTION IF EXISTS pg_catalog.op_set_add_intr (anyset, interval); +DROP FUNCTION IF EXISTS pg_catalog.op_intr_add_set (interval, anyset); +DROP FUNCTION IF EXISTS pg_catalog.op_set_sub_intr (anyset, interval); + DROP FUNCTION IF EXISTS pg_catalog.op_num_add_intr (numeric, interval); DROP FUNCTION IF EXISTS pg_catalog.op_text_add_intr (text, interval); DROP FUNCTION IF EXISTS pg_catalog.op_date_add_intr (date, interval); @@ -583,6 +999,7 @@ DROP FUNCTION IF EXISTS pg_catalog.date_sub (timestamptz, interval); DROP FUNCTION IF EXISTS pg_catalog.date_sub (timestamp without time zone, interval); DROP FUNCTION IF EXISTS pg_catalog.date_add (timestamptz, interval); DROP FUNCTION IF EXISTS pg_catalog.date_add (timestamp without time zone, interval); +DROP FUNCTION IF EXISTS pg_catalog.date_add_interval(date, interval); CREATE OR REPLACE FUNCTION pg_catalog.date_add (time, interval) RETURNS time AS $$ SELECT pg_catalog.adddate($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.date_sub (time, interval) RETURNS time AS $$ SELECT pg_catalog.adddate($1, -$2) $$ LANGUAGE SQL; @@ -989,9 +1406,35 @@ drop cast if exists ("binary" as char); CREATE CAST ("binary" AS varchar) WITH FUNCTION pg_catalog.Varlena2Varchar(anyelement) AS ASSIGNMENT; CREATE CAST ("binary" AS char) WITH FUNCTION pg_catalog.Varlena2Bpchar(anyelement) AS ASSIGNMENT; -DROP FUNCTION IF EXISTS pg_catalog.substring(bit, bit); -DROP FUNCTION IF EXISTS pg_catalog.substring(bytea, bit); -DROP FUNCTION IF EXISTS pg_catalog.substring(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.substr(bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.substr(bytea, bit); +DROP FUNCTION IF EXISTS pg_catalog.substr(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.substr(bit, int, int); +DROP FUNCTION IF EXISTS pg_catalog.substr(bit, int); DROP FUNCTION IF EXISTS pg_catalog.set_native_password(text, text, text); -DROP FUNCTION IF EXISTS pg_catalog.set_caching_sha2_password(text, text, text); \ No newline at end of file +DROP FUNCTION IF EXISTS pg_catalog.set_caching_sha2_password(text, text, text); + +-- fix merge join +DROP OPERATOR CLASS pg_catalog.int8_uint_bt_ops USING btree; +DROP OPERATOR CLASS pg_catalog.int8_uint_hash_ops USING hash; +DROP OPERATOR IF EXISTS pg_catalog.=(int2, uint1); +DROP OPERATOR IF EXISTS pg_catalog.=(int4, uint1); +DROP OPERATOR IF EXISTS pg_catalog.=(int8, uint1); +DROP FUNCTION IF EXISTS pg_catalog.int8_cmp_uint1(int8, uint1); +DROP FUNCTION IF EXISTS pg_catalog.int8_cmp_uint2(int8, uint2); +DROP FUNCTION IF EXISTS pg_catalog.int8_cmp_uint4(int8, uint4); +DROP FUNCTION IF EXISTS pg_catalog.int8_cmp_uint8(int8, uint8); +DROP FUNCTION IF EXISTS pg_catalog.int2_eq_uint1(int2, uint1); +DROP FUNCTION IF EXISTS pg_catalog.int4_eq_uint1(int4, uint1); +DROP FUNCTION IF EXISTS pg_catalog.int8_eq_uint1(int8, uint1); + +DROP FUNCTION IF EXISTS pg_catalog.db_b_format("any", int8) cascade; +DROP FUNCTION IF EXISTS pg_catalog.db_b_format("any", int8, "any") cascade; +CREATE OR REPLACE FUNCTION pg_catalog.db_b_format("any", int4) RETURNS text LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'db_b_format'; +CREATE OR REPLACE FUNCTION pg_catalog.db_b_format("any", int4, "any") RETURNS text LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'db_b_format_locale'; + +drop CAST (varchar as json); +drop CAST (text as json); +DROP FUNCTION IF EXISTS pg_catalog.varchar_json(varchar); +DROP FUNCTION IF EXISTS pg_catalog.varchar_json(text); diff --git a/contrib/dolphin/sql/alter_function_test/alter_function.sql b/contrib/dolphin/sql/alter_function_test/alter_function.sql index 356373cc0909979f3b9af4b8e6636466d1be4ef2..5ced0e37ec6126e155ea2d8bfce7e2887bd6b56b 100755 --- a/contrib/dolphin/sql/alter_function_test/alter_function.sql +++ b/contrib/dolphin/sql/alter_function_test/alter_function.sql @@ -87,7 +87,7 @@ end; $$ LANGUAGE PLPGSQL; alter FUNCTION f5 no sql; - +alter FUNCTION f5() set query_dop = 2; create table t1 (a int); diff --git a/contrib/dolphin/sql/b_rowtype.sql b/contrib/dolphin/sql/b_rowtype.sql new file mode 100644 index 0000000000000000000000000000000000000000..32d0615473c1078ce614d9ce606cebe92991ed91 --- /dev/null +++ b/contrib/dolphin/sql/b_rowtype.sql @@ -0,0 +1,25 @@ +create schema b_rowtype; + +create table t_Compare_Case0017(first_name varchar(100), last_name varchar(100)); +set behavior_compat_options='allow_procedure_compile_check'; +create table t_CurRowtype_PLObject_Case0017(first_name varchar(100), last_name varchar(100)); +insert into t_CurRowtype_PLObject_Case0017 values('Jason','Statham'); + +create trigger tri_CurRowtype_PLObject_Case0017 before insert on t_CurRowtype_PLObject_Case0017 for each row +declare + cursor cur_1 is select * from t_CurRowtype_PLObject_Case0017; + source cur_1%rowtype; +begin + source.first_name:=new.first_name; + source.last_name:=new.last_name; + insert into t_Compare_Case0017 values (source.first_name,source.last_name); + return new; +end; +/ + +insert into t_CurRowtype_PLObject_Case0017 values('Jason_New','Statham_New'); +reset behavior_compat_options; +drop trigger tri_CurRowtype_PLObject_Case0017; +drop table t_Compare_Case0017; +drop table t_CurRowtype_PLObject_Case0017; +drop schema b_rowtype cascade; diff --git a/contrib/dolphin/sql/builtin_funcs/b_compatibility_substr_func.sql b/contrib/dolphin/sql/builtin_funcs/b_compatibility_substr_func.sql index 08be76b1f4c4d1758e732635e070f8e1b62dc2c8..a51963d0eeacdb2d229dfc875a211f272b1add7b 100644 --- a/contrib/dolphin/sql/builtin_funcs/b_compatibility_substr_func.sql +++ b/contrib/dolphin/sql/builtin_funcs/b_compatibility_substr_func.sql @@ -217,6 +217,25 @@ select c1, mid(`char`, 3, 4), mid(`varchar`, 3, 4), mid(`binary`, 3, 4), mid(`va select c1, mid(`bit1`, 2), mid(`bit8`, 2), mid(`bit15`, 2), mid(`bit64`, 2) from t_bit order by c1; select c1, mid(`bit1`, 2, 2), mid(`bit8`, 2, 2), mid(`bit15`, 2, 2), mid(`bit64`, 2, 2) from t_bit order by c1; +-- test mid pos、length is bit type +select c1, mid(`int1`, b'11'), mid(`uint1`, b'11'), mid(`int2`, b'11'), mid(`uint2`, b'11'), mid(`int4`, b'11'), mid(`uint4`, b'11'), mid(`int8`, b'11'), mid(`uint8`, b'11'), mid(`float4`, b'11'), mid(`float8`, b'11'), mid(`boolean`, b'11') from t_number order by c1; +select c1, mid(`int1`, b'11', 2), mid(`uint1`, b'11', 2), mid(`int2`, b'11', 2), mid(`uint2`, b'11', 2), mid(`int4`, b'11', 2), mid(`uint4`, b'11', 2), mid(`int8`, b'11', 2), mid(`uint8`, b'11', 2), mid(`float4`, b'11', 2), mid(`float8`, b'11', 2), mid(`boolean`, b'11', 2) from t_number order by c1; +select c1, mid(`int1`, 2, b'11'), mid(`uint1`, 2, b'11'), mid(`int2`, 2, b'11'), mid(`uint2`, 2, b'11'), mid(`int4`, 2, b'11'), mid(`uint4`, 2, b'11'), mid(`int8`, 2, b'11'), mid(`uint8`, 2, b'11'), mid(`float4`, 2, b'11'), mid(`float8`, 2, b'11'), mid(`boolean`, 2, b'11') from t_number order by c1; +select c1, mid(`int1`, b'11', b'11'), mid(`uint1`, b'11', b'11'), mid(`int2`, b'11', b'11'), mid(`uint2`, b'11', b'11'), mid(`int4`, b'11', b'11'), mid(`uint4`, b'11', b'11'), mid(`int8`, b'11', b'11'), mid(`uint8`, b'11', b'11'), mid(`float4`, b'11', b'11'), mid(`float8`, b'11', b'11'), mid(`boolean`, b'11', b'11') from t_number order by c1; + +set dolphin.sql_mode = 'sql_mode_strict,sql_mode_full_group,pipes_as_concat,ansi_quotes,no_zero_date,pad_char_to_full_length,auto_recompile_function,error_for_division_by_zero'; -- with pad_char_to_full_length +select c1, mid(`char`, b'11'), mid(`varchar`, b'11'), mid(`binary`, b'11'), mid(`varbinary`, b'11'), mid(`text`, b'11') from t_str order by c1; +set dolphin.sql_mode = 'sql_mode_strict,sql_mode_full_group,pipes_as_concat,ansi_quotes,no_zero_date,auto_recompile_function,error_for_division_by_zero'; -- without pad_char_to_full_length +select c1, mid(`char`, b'11'), mid(`varchar`, b'11'), mid(`binary`, b'11'), mid(`varbinary`, b'11'), mid(`text`, b'11') from t_str order by c1; +select c1, mid(`char`, b'11', 4), mid(`varchar`, b'11', 4), mid(`binary`, b'11', 4), mid(`varbinary`, b'11', 4), mid(`text`, b'11', 4) from t_str order by c1; +select c1, mid(`char`, 3, b'100'), mid(`varchar`, 3, b'100'), mid(`binary`, 3, b'100'), mid(`varbinary`, 3, b'100'), mid(`text`, 3, b'100') from t_str order by c1; +select c1, mid(`char`, b'11', b'100'), mid(`varchar`, b'11', b'100'), mid(`binary`, b'11', b'100'), mid(`varbinary`, b'11', b'100'), mid(`text`, b'11', b'100') from t_str order by c1; + +select c1, mid(`bit1`, b'10'), mid(`bit8`, b'10'), mid(`bit15`, b'10'), mid(`bit64`, b'10') from t_bit order by c1; +select c1, mid(`bit1`, b'10', 3), mid(`bit8`, b'10', 3), mid(`bit15`, b'10', 3), mid(`bit64`, b'10', 3) from t_bit order by c1; +select c1, mid(`bit1`, 2, b'11'), mid(`bit8`, 2, b'11'), mid(`bit15`, 2, b'11'), mid(`bit64`, 2, b'11') from t_bit order by c1; +select c1, mid(`bit1`, b'10', b'11'), mid(`bit8`, b'10', b'11'), mid(`bit15`, b'10', b'11'), mid(`bit64`, b'10', b'11') from t_bit order by c1; + drop table t_number; drop table t_bit; drop table t_str; diff --git a/contrib/dolphin/sql/builtin_funcs/db_b_format.sql b/contrib/dolphin/sql/builtin_funcs/db_b_format.sql index 0bb7655fb5ec69c37db945a4a15dc8825adba0fb..3e17e7ac7ac7d45856219b226c9511253cab78ad 100644 --- a/contrib/dolphin/sql/builtin_funcs/db_b_format.sql +++ b/contrib/dolphin/sql/builtin_funcs/db_b_format.sql @@ -116,6 +116,19 @@ select format(1, 1, null); select format(null, null, 1); select format(null, null, null); +-- test overflow +select format(123123.456,100000000000); +select format(123123.456,1000000000000); +select format(123123.456,10000000000000); +select format(123123.456,545634633746483465436546345635436587463); +select format(123123.456,'513513413546587468514351345435413'); + +select format(123123.456,100000000000,'de_DE'); +select format(123123.456,1000000000000,'de_DE'); +select format(123123.456,10000000000000,'de_DE'); +select format(123123.456,545634633746483465436546345635436587463,'de_DE'); +select format(123123.456,'513513413546587468514351345435413','de_DE'); + -- test for setting b_compatibility_mode back to false set dolphin.b_compatibility_mode = 0; select format(1234.456, 2); diff --git a/contrib/dolphin/sql/case_sensitive_test/trigger.sql b/contrib/dolphin/sql/case_sensitive_test/trigger.sql new file mode 100644 index 0000000000000000000000000000000000000000..4d20ba7323e92df77cb94b9c0b5dd94a1f81cc0f --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/trigger.sql @@ -0,0 +1,28 @@ +\c table_name_test_db; +set dolphin.lower_case_table_names to 0; +create table t1(c1 int); +create table t2(c1 int); +create trigger tg_case_1 before insert on t1 for each row update t2 set c1 = c1 + 1; +create trigger TG_CASE_1 before insert on t1 for each row update t2 set c1 = c1 + 1; +create schema s1; +create schema S1; +create table s1.t1(c1 int); +create table s1.t2(c1 int); +create table S1.t1(c1 int); +create table S1.t2(c1 int); +create trigger s1.tg_case_2 before insert on s1.t1 for each row update s1.t2 set c1 = c1 + 1; +create trigger s1.TG_CASE_2 before insert on s1.t1 for each row update s1.t2 set c1 = c1 + 1; +create trigger S1.tg_case_3 before insert on S1.t1 for each row update S1.t2 set c1 = c1 + 1; +create trigger S1.TG_CASE_3 before insert on S1.t1 for each row update S1.t2 set c1 = c1 + 1; +select tgname from pg_trigger where lower(tgname) like 'tg_case_%' order by tgname asc; + +drop trigger tg_case_1; +drop trigger TG_CASE_1; +drop trigger s1.tg_case_2; +drop trigger s1.TG_CASE_2; +drop trigger S1.tg_case_3; +drop trigger S1.TG_CASE_3; +drop table t1; +drop table t2; +drop schema s1 cascade; +drop schema S1 cascade; diff --git a/contrib/dolphin/sql/create_function_test/b_compat_create_func.sql b/contrib/dolphin/sql/create_function_test/b_compat_create_func.sql index baa9bf106828ac5047b240d0152fcdd269e4d9b6..d8d5d1fdea4393b240a85fd5c335c690f9c79bc2 100644 --- a/contrib/dolphin/sql/create_function_test/b_compat_create_func.sql +++ b/contrib/dolphin/sql/create_function_test/b_compat_create_func.sql @@ -519,6 +519,41 @@ select test_function_030('aaa') is null; drop table if exists test_table_030; drop function if exists test_function_030; +CREATE PROCEDURE p_log_job_info_bak() +AS DECLARE +begin + raise notice '1'; + commit; +END; +/ + +create procedure p_gen_rpt_init_self_recovery() +AS +DECLARE + temp_wtg_id BIGINT; + CURSOR crs_ar FOR (SELECT wtg_id + FROM temp_init_sr_previous + ORDER BY 1); +BEGIN + CREATE TEMPORARY TABLE temp_init_sr_previous(wtg_id BIGINT); + OPEN crs_ar; +ar_loop:LOOP + FETCH crs_ar INTO temp_wtg_id; + IF NOT FOUND THEN + leave ar_loop; + END IF; + END LOOP; + CLOSE crs_ar; + DROP TEMPORARY TABLE temp_init_sr_previous; + + CALL p_log_job_info_bak(); +END; +/ + +call p_gen_rpt_init_self_recovery(); +drop procedure p_log_job_info_bak; +DROP PROCEDURE p_gen_rpt_init_self_recovery; + -- expect error: there is no parameter $1, other error is wrong!!! select :lable; select :loop; diff --git a/contrib/dolphin/sql/db_b_new_gram_test.sql b/contrib/dolphin/sql/db_b_new_gram_test.sql index e487bfc17834dc975b29ff5c586ed9af5fd647f7..aafe8db6c399947bd504f921649dc590968d84ad 100644 --- a/contrib/dolphin/sql/db_b_new_gram_test.sql +++ b/contrib/dolphin/sql/db_b_new_gram_test.sql @@ -540,4 +540,28 @@ create index bmu1 on t1(a); explain (costs off) select count(a) from t1 ignore index(bdx); explain (costs off) select count(a) from t1 ignore index(bmu); explain (costs off) select count(a) from t1 ignore index(bm); + +-- with rollup + +create table table_json_a(SITE_NAME_I18N json); +insert into table_json_a values('{"i18nValue": {"en_US": "测试字符串-en", "es_ES": "测试字符串01-es", "ja_JP": "PDC测试字符串01-jp", "zh_CN": "PDC测试字符串01-zh"}, "defaultValue": "PDC测试字符串01"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001-大熊猫-EN", "es_ES": "", "ja_JP": "", "zh_CN": ""}, "defaultValue": "WF001-大熊猫"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001-10-us", "es_ES": "WF001-10-es", "ja_JP": "WF001-10-jp", "zh_CN": "WF001-10-cn"}, "defaultValue": "WF001-10"}'); +insert into table_json_a values ('{"i18nValue": {"en_US": "WF001一期-en", "es_ES": "WF001一期-ES", "ja_JP": "WF001一期-JP", "zh_CN": "WF001一期-zh"}, "defaultValue": "WF001一期"}'); + + +CREATE TABLE table_json_b (name_i18n json); +insert into table_json_b values('{"i18nValue": {"en_US": "测试字符串-en", "es_ES": "测试字符串01-es", "ja_JP": "PDC测试字符串01-jp", "zh_CN": "PDC测试字符串01-zh"}, "defaultValue": "PDC测试字符串01"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001-大熊猫-EN", "es_ES": "", "ja_JP": "", "zh_CN": ""}, "defaultValue": "WF001-大熊猫"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001-10-us", "es_ES": "WF001-10-es", "ja_JP": "WF001-10-jp", "zh_CN": "WF001-10-cn"}, "defaultValue": "WF001-10"}'); +insert into table_json_b values ('{"i18nValue": {"en_US": "WF001一期-en", "es_ES": "WF001一期-ES", "ja_JP": "WF001一期-JP", "zh_CN": "WF001一期-zh"}, "defaultValue": "WF001一期"}'); + + +select count(*) from table_json_a,table_json_b group by + coalesce(table_json_b.NAME_I18N->>'$.i18nValue.zh_CN', table_json_b.NAME_I18N->>'$.defaultValue'), + coalesce(table_json_a.SITE_NAME_I18N->>'$.i18nValue.zh_CN', table_json_a.SITE_NAME_I18N->>'$.defaultValue') with rollup; + +drop table table_json_a; +drop table table_json_b; + drop table t1; \ No newline at end of file diff --git a/contrib/dolphin/sql/db_b_plpgsql_test.sql b/contrib/dolphin/sql/db_b_plpgsql_test.sql index bef160711bdb95eb1eac2b8a0549d0545b4a79d6..c03527cb78ff242d022c1276335a6c22cf2ecd0a 100644 --- a/contrib/dolphin/sql/db_b_plpgsql_test.sql +++ b/contrib/dolphin/sql/db_b_plpgsql_test.sql @@ -144,5 +144,20 @@ end; / call proc_abort_050_02(); +delimiter // +create or replace procedure test_set(out res int) +begin +declare a int; +declare b int; +declare c int; +set a=1, b=2, c=3; +set res=a+b+c; +end; +// +delimiter ; + +call test_set(@res); +drop procedure test_set; + drop schema db_b_plpgsql_test cascade; reset current_schema; diff --git a/contrib/dolphin/sql/foreign_key_checks_test.sql b/contrib/dolphin/sql/foreign_key_checks_test.sql new file mode 100644 index 0000000000000000000000000000000000000000..3ce2d04d75455539cbb46fb9c64c02a2773c6c01 --- /dev/null +++ b/contrib/dolphin/sql/foreign_key_checks_test.sql @@ -0,0 +1,54 @@ +create schema foreign_key_checks_test; +set current_schema to 'foreign_key_checks_test'; + +-- test FOREIGN_KEY_CHECKS +create table parent_table(id INT PRIMARY KEY); +CREATE TABLE child_table( +id INT PRIMARY KEY, +parent_id INT, +FOREIGN KEY (parent_id) REFERENCES parent_table(id) +); + +insert into parent_table values (1),(2),(3); +insert into child_table values (11, 1); +insert into child_table values (15, 5); -- error expectly +SET FOREIGN_KEY_CHECKS=0; +insert into child_table values (15, 5); -- success expectly + +SET FOREIGN_KEY_CHECKS=1; +update child_table set parent_id = 6 where parent_id = 1; -- error expectly +SET FOREIGN_KEY_CHECKS=0; +update child_table set parent_id = 6 where parent_id = 1; -- success expectly + + +drop table child_table; +drop table parent_table; + + +SET FOREIGN_KEY_CHECKS=1; +create table parent_table(id INT PRIMARY KEY); +CREATE TABLE child_table( +id INT PRIMARY KEY, +parent_id INT, +FOREIGN KEY (parent_id) REFERENCES parent_table(id) +); + +insert into parent_table values (1),(2),(3); +insert into child_table values (11, 1); + +delete from parent_table where id = 1; --error expectly +SET FOREIGN_KEY_CHECKS=0; +delete from parent_table where id = 1; --success expectly + +SET FOREIGN_KEY_CHECKS=1; +alter table parent_table drop column id; --error expectly +SET FOREIGN_KEY_CHECKS=0; +alter table parent_table drop column id; --error expectly + +SET FOREIGN_KEY_CHECKS=1; +drop table parent_table; -- error expectly +drop table child_table; +drop table parent_table; -- success expectly + +drop schema foreign_key_checks_test cascade; +reset current_schema; diff --git a/contrib/dolphin/sql/ignore_keyword_list.sql b/contrib/dolphin/sql/ignore_keyword_list.sql index 6493ad759be8bee18766fe40ebf469ae40f8cb6f..ba0bbf9fa7e9eae870863b2a776ec192603c4d3d 100644 --- a/contrib/dolphin/sql/ignore_keyword_list.sql +++ b/contrib/dolphin/sql/ignore_keyword_list.sql @@ -1,8 +1,6 @@ create schema ignore_keyword_list; set current_schema to 'ignore_keyword_list'; -create schema ignore_keyword_list; -set current_schema to 'ignore_keyword_list'; select 1 interval; --error set disable_keyword_options = 'interval'; select 1 interval; --ok @@ -11,7 +9,11 @@ set disable_keyword_options = 'interval,interval'; select 1 interval; --ok reset disable_keyword_options; select 1 interval; --error +create table t1 (binary int); +create table t2 (prior int); +set disable_keyword_options ='prior,binary'; +create table t1 (binary int); +create table t2 (prior int); +reset current_schema; drop schema ignore_keyword_list cascade; -drop schema ignore_keyword_list cascade; -reset current_schema; diff --git a/contrib/dolphin/sql/json_insert.sql b/contrib/dolphin/sql/json_insert.sql index 71d74be10437461bb5219e0718946cc0ff9d2444..3e8426f23432354f8c4c7aca176e080c18572103 100644 --- a/contrib/dolphin/sql/json_insert.sql +++ b/contrib/dolphin/sql/json_insert.sql @@ -76,5 +76,24 @@ insert into test values (JSON_INSERT('{"a": 43, "b": {"c": true}}', '$.b[4]', 'Test')); select * from test; + +create table t_json(c1 json); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::text); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::varchar); +insert into t_json values ('{"k1":"v1","k2":"v2"}'::char(30)); +insert into t_json values ('{"k1":"v1","k2"}'::text); +insert into t_json values ('{"k1":"v1","k2"}'::varchar); +insert into t_json values ('{"k1":"v1","k2"}'::char(30)); +select * from t_json; +update t_json set c1 = '{"k1":"v1","k3":"v3"}'::text; +update t_json set c1 = '{"k1":"v1","k4":"v4"}'::varchar; +update t_json set c1 = '{"k1":"v1","k4":"v4"}'::char(30); +select * from t_json; + +insert ignore into t_json values ('{"k1":"v1","k2"}'::text); +insert ignore into t_json values ('{"k1":"v1","k2"}'::varchar); +insert ignore into t_json values ('{"k1":"v1","k2"}'::char(30)); + +drop table t_json; drop schema test_json_insert cascade; reset current_schema; \ No newline at end of file diff --git a/contrib/dolphin/sql/partition_test1.sql b/contrib/dolphin/sql/partition_test1.sql index 76edc1729fe64d51bd16312872c902d81e6ee692..7fa44caa93bb847d684443951f2964f45d440ad1 100644 --- a/contrib/dolphin/sql/partition_test1.sql +++ b/contrib/dolphin/sql/partition_test1.sql @@ -368,5 +368,31 @@ insert into RangePartionLevel1_IntegerTypes values (1,2); insert into RangePartionLevel1_IntegerTypes values (1,65535); drop table RangePartionLevel1_IntegerTypes; + +create table t_select_0019(col01 int,col02 varchar(255)) +partition by list(col01) ( +partition p1 values in (1000), +partition p2 values in (2000), +partition p3 values in (3000), +partition p4 values in (4000), +partition p5 values in (5000), +partition p6 values in (6000) +); +select * into t_select_0019_p1 from t_select_0019 partition (p1, p3, p5, p6); +select * from t_select_0019_p1; +drop table t_select_0019; +drop table t_select_0019_p1; + + +-- extract +create table t_partition_range_0181_1( id int not null, ename varchar(30), hired date not null default '1970-01-01', separated date not null default '9999-12-31', job varchar(30) not null, store_id int not null ) partition by range(extract(year from separated))( partition p0 values less than (1995), partition p1 values less than (2000), partition p2 values less than (2005)); + +create table t_partition_range_0181_2( id int, purchased date ) partition by range(year(purchased)) subpartition by hash(id)( partition p0 values less than (1990) ( subpartition s0, subpartition s1), partition p1 values less than (2000) ( subpartition s2, subpartition s3), partition p2 values less than (maxvalue) ( subpartition s4, subpartition s5)); + +select relname, parttype, partstrategy, boundaries,reltablespace,intervaltablespace,`interval`,transit from pg_partition where parentid in (select oid from pg_class where relname like 't_partition_range_0181%'); + +drop table t_partition_range_0181_1; +drop table t_partition_range_0181_2; + drop schema partition_test1 cascade; reset current_schema; diff --git a/contrib/dolphin/sql/string_func_test/db_b_left_right_test.sql b/contrib/dolphin/sql/string_func_test/db_b_left_right_test.sql index 2820cc3a6a0bc1c679933dd6cda36007f92a48ed..7e543c45f41da432ecd073d8736ca1b5425f0b37 100644 --- a/contrib/dolphin/sql/string_func_test/db_b_left_right_test.sql +++ b/contrib/dolphin/sql/string_func_test/db_b_left_right_test.sql @@ -77,5 +77,2379 @@ select left('abc',5/2); select right('abc',2.5); select right('abc',5/2); +select left('dont!', b'10010'); +select right('dont!', b'10010'); +select left('dont!', X'FF'); +select right('dont!', X'FF'); +select left('dont!', '9223372036854775807'); +select right('dont!', '9223372036854775807'); +select right('dont!', 9223372036854775807); +select right('dont!', 9223372036854775808); + +\x +CREATE TABLE test_type_table +( + `int1` tinyint, + `uint1` tinyint unsigned, + `int2` smallint, + `uint2` smallint unsigned, + `int4` integer, + `uint4` integer unsigned, + `int8` bigint, + `uint8` bigint unsigned, + `float4` float4, + `float8` float8, + `numeric` decimal(20, 6), + `bit1` bit(1), + `bit64` bit(64), + `boolean` boolean, + `date` date, + `time` time, + `time(4)` time(4), + `datetime` datetime, + `datetime(4)` datetime(4) default '2022-11-11 11:11:11', + `timestamp` timestamp, + `timestamp(4)` timestamp(4) default '2022-11-11 11:11:11', + `year` year, + `char` char(100), + `varchar` varchar(100), + `binary` binary(100), + `varbinary` varbinary(100), + `tinyblob` tinyblob, + `blob` blob, + `mediumblob` mediumblob, + `longblob` longblob, + `text` text, + `enum_t` enum('a', 'b', 'c'), + `set_t` set('a', 'b', 'c'), + `json` json +); + +insert into test_type_table values(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,b'1', b'111', true,'2023-02-05', '19:10:50', '19:10:50.3456', '2023-02-05 19:10:50', '2023-02-05 19:10:50.456', '2023-02-05 19:10:50', '2023-02-05 19:10:50.456', '2023','1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a', '1.23a','a', 'a,c',json_object('a', 1, 'b', 2)); + +select +right(`int1`,`int1`), +right(`int1`,`uint1`), +right(`int1`,`int2`), +right(`int1`,`uint2`), +right(`int1`,`int4`), +right(`int1`,`uint4`), +right(`int1`,`int8`), +right(`int1`,`uint8`), +right(`int1`,`float4`), +right(`int1`,`float8`), +right(`int1`,`numeric`), +right(`int1`,`bit1`), +right(`int1`,`bit64`), +right(`int1`,`boolean`), +right(`int1`,`date`), +right(`int1`,`time`), +right(`int1`,`time(4)`), +right(`int1`,`datetime`), +right(`int1`,`datetime(4)`), +right(`int1`,`timestamp`), +right(`int1`,`timestamp(4)`), +right(`int1`,`year`), +right(`int1`,`char`), +right(`int1`,`varchar`), +right(`int1`,`binary`), +right(`int1`,`varbinary`), +right(`int1`,`tinyblob`), +right(`int1`,`blob`), +right(`int1`,`mediumblob`), +right(`int1`,`longblob`), +right(`int1`,`text`), +right(`int1`,`enum_t`), +right(`int1`,`set_t`), +right(`int1`,`json`), +right(`uint1`,`int1`), +right(`uint1`,`uint1`), +right(`uint1`,`int2`), +right(`uint1`,`uint2`), +right(`uint1`,`int4`), +right(`uint1`,`uint4`), +right(`uint1`,`int8`), +right(`uint1`,`uint8`), +right(`uint1`,`float4`), +right(`uint1`,`float8`), +right(`uint1`,`numeric`), +right(`uint1`,`bit1`), +right(`uint1`,`bit64`), +right(`uint1`,`boolean`), +right(`uint1`,`date`), +right(`uint1`,`time`), +right(`uint1`,`time(4)`), +right(`uint1`,`datetime`), +right(`uint1`,`datetime(4)`), +right(`uint1`,`timestamp`), +right(`uint1`,`timestamp(4)`), +right(`uint1`,`year`), +right(`uint1`,`char`), +right(`uint1`,`varchar`), +right(`uint1`,`binary`), +right(`uint1`,`varbinary`), +right(`uint1`,`tinyblob`), +right(`uint1`,`blob`), +right(`uint1`,`mediumblob`), +right(`uint1`,`longblob`), +right(`uint1`,`text`), +right(`uint1`,`enum_t`), +right(`uint1`,`set_t`), +right(`uint1`,`json`), +right(`int2`,`int1`), +right(`int2`,`uint1`), +right(`int2`,`int2`), +right(`int2`,`uint2`), +right(`int2`,`int4`), +right(`int2`,`uint4`), +right(`int2`,`int8`), +right(`int2`,`uint8`), +right(`int2`,`float4`), +right(`int2`,`float8`), +right(`int2`,`numeric`), +right(`int2`,`bit1`), +right(`int2`,`bit64`), +right(`int2`,`boolean`), +right(`int2`,`date`), +right(`int2`,`time`), +right(`int2`,`time(4)`), +right(`int2`,`datetime`), +right(`int2`,`datetime(4)`), +right(`int2`,`timestamp`), +right(`int2`,`timestamp(4)`), +right(`int2`,`year`), +right(`int2`,`char`), +right(`int2`,`varchar`), +right(`int2`,`binary`), +right(`int2`,`varbinary`), +right(`int2`,`tinyblob`), +right(`int2`,`blob`), +right(`int2`,`mediumblob`), +right(`int2`,`longblob`), +right(`int2`,`text`), +right(`int2`,`enum_t`), +right(`int2`,`set_t`), +right(`int2`,`json`), +right(`uint2`,`int1`), +right(`uint2`,`uint1`), +right(`uint2`,`int2`), +right(`uint2`,`uint2`), +right(`uint2`,`int4`), +right(`uint2`,`uint4`), +right(`uint2`,`int8`), +right(`uint2`,`uint8`), +right(`uint2`,`float4`), +right(`uint2`,`float8`), +right(`uint2`,`numeric`), +right(`uint2`,`bit1`), +right(`uint2`,`bit64`), +right(`uint2`,`boolean`), +right(`uint2`,`date`), +right(`uint2`,`time`), +right(`uint2`,`time(4)`), +right(`uint2`,`datetime`), +right(`uint2`,`datetime(4)`), +right(`uint2`,`timestamp`), +right(`uint2`,`timestamp(4)`), +right(`uint2`,`year`), +right(`uint2`,`char`), +right(`uint2`,`varchar`), +right(`uint2`,`binary`), +right(`uint2`,`varbinary`), +right(`uint2`,`tinyblob`), +right(`uint2`,`blob`), +right(`uint2`,`mediumblob`), +right(`uint2`,`longblob`), +right(`uint2`,`text`), +right(`uint2`,`enum_t`), +right(`uint2`,`set_t`), +right(`uint2`,`json`), +right(`int4`,`int1`), +right(`int4`,`uint1`), +right(`int4`,`int2`), +right(`int4`,`uint2`), +right(`int4`,`int4`), +right(`int4`,`uint4`), +right(`int4`,`int8`), +right(`int4`,`uint8`), +right(`int4`,`float4`), +right(`int4`,`float8`), +right(`int4`,`numeric`), +right(`int4`,`bit1`), +right(`int4`,`bit64`), +right(`int4`,`boolean`), +right(`int4`,`date`), +right(`int4`,`time`), +right(`int4`,`time(4)`), +right(`int4`,`datetime`), +right(`int4`,`datetime(4)`), +right(`int4`,`timestamp`), +right(`int4`,`timestamp(4)`), +right(`int4`,`year`), +right(`int4`,`char`), +right(`int4`,`varchar`), +right(`int4`,`binary`), +right(`int4`,`varbinary`), +right(`int4`,`tinyblob`), +right(`int4`,`blob`), +right(`int4`,`mediumblob`), +right(`int4`,`longblob`), +right(`int4`,`text`), +right(`int4`,`enum_t`), +right(`int4`,`set_t`), +right(`int4`,`json`), +right(`uint4`,`int1`), +right(`uint4`,`uint1`), +right(`uint4`,`int2`), +right(`uint4`,`uint2`), +right(`uint4`,`int4`), +right(`uint4`,`uint4`), +right(`uint4`,`int8`), +right(`uint4`,`uint8`), +right(`uint4`,`float4`), +right(`uint4`,`float8`), +right(`uint4`,`numeric`), +right(`uint4`,`bit1`), +right(`uint4`,`bit64`), +right(`uint4`,`boolean`), +right(`uint4`,`date`), +right(`uint4`,`time`), +right(`uint4`,`time(4)`), +right(`uint4`,`datetime`), +right(`uint4`,`datetime(4)`), +right(`uint4`,`timestamp`), +right(`uint4`,`timestamp(4)`), +right(`uint4`,`year`), +right(`uint4`,`char`), +right(`uint4`,`varchar`), +right(`uint4`,`binary`), +right(`uint4`,`varbinary`), +right(`uint4`,`tinyblob`), +right(`uint4`,`blob`), +right(`uint4`,`mediumblob`), +right(`uint4`,`longblob`), +right(`uint4`,`text`), +right(`uint4`,`enum_t`), +right(`uint4`,`set_t`), +right(`uint4`,`json`), +right(`int8`,`int1`), +right(`int8`,`uint1`), +right(`int8`,`int2`), +right(`int8`,`uint2`), +right(`int8`,`int4`), +right(`int8`,`uint4`), +right(`int8`,`int8`), +right(`int8`,`uint8`), +right(`int8`,`float4`), +right(`int8`,`float8`), +right(`int8`,`numeric`), +right(`int8`,`bit1`), +right(`int8`,`bit64`), +right(`int8`,`boolean`), +right(`int8`,`date`), +right(`int8`,`time`), +right(`int8`,`time(4)`), +right(`int8`,`datetime`), +right(`int8`,`datetime(4)`), +right(`int8`,`timestamp`), +right(`int8`,`timestamp(4)`), +right(`int8`,`year`), +right(`int8`,`char`), +right(`int8`,`varchar`), +right(`int8`,`binary`), +right(`int8`,`varbinary`), +right(`int8`,`tinyblob`), +right(`int8`,`blob`), +right(`int8`,`mediumblob`), +right(`int8`,`longblob`), +right(`int8`,`text`), +right(`int8`,`enum_t`), +right(`int8`,`set_t`), +right(`int8`,`json`), +right(`uint8`,`int1`), +right(`uint8`,`uint1`), +right(`uint8`,`int2`), +right(`uint8`,`uint2`), +right(`uint8`,`int4`), +right(`uint8`,`uint4`), +right(`uint8`,`int8`), +right(`uint8`,`uint8`), +right(`uint8`,`float4`), +right(`uint8`,`float8`), +right(`uint8`,`numeric`), +right(`uint8`,`bit1`), +right(`uint8`,`bit64`), +right(`uint8`,`boolean`), +right(`uint8`,`date`), +right(`uint8`,`time`), +right(`uint8`,`time(4)`), +right(`uint8`,`datetime`), +right(`uint8`,`datetime(4)`), +right(`uint8`,`timestamp`), +right(`uint8`,`timestamp(4)`), +right(`uint8`,`year`), +right(`uint8`,`char`), +right(`uint8`,`varchar`), +right(`uint8`,`binary`), +right(`uint8`,`varbinary`), +right(`uint8`,`tinyblob`), +right(`uint8`,`blob`), +right(`uint8`,`mediumblob`), +right(`uint8`,`longblob`), +right(`uint8`,`text`), +right(`uint8`,`enum_t`), +right(`uint8`,`set_t`), +right(`uint8`,`json`), +right(`float4`,`int1`), +right(`float4`,`uint1`), +right(`float4`,`int2`), +right(`float4`,`uint2`), +right(`float4`,`int4`), +right(`float4`,`uint4`), +right(`float4`,`int8`), +right(`float4`,`uint8`), +right(`float4`,`float4`), +right(`float4`,`float8`), +right(`float4`,`numeric`), +right(`float4`,`bit1`), +right(`float4`,`bit64`), +right(`float4`,`boolean`), +right(`float4`,`date`), +right(`float4`,`time`), +right(`float4`,`time(4)`), +right(`float4`,`datetime`), +right(`float4`,`datetime(4)`), +right(`float4`,`timestamp`), +right(`float4`,`timestamp(4)`), +right(`float4`,`year`), +right(`float4`,`char`), +right(`float4`,`varchar`), +right(`float4`,`binary`), +right(`float4`,`varbinary`), +right(`float4`,`tinyblob`), +right(`float4`,`blob`), +right(`float4`,`mediumblob`), +right(`float4`,`longblob`), +right(`float4`,`text`), +right(`float4`,`enum_t`), +right(`float4`,`set_t`), +right(`float4`,`json`), +right(`float8`,`int1`), +right(`float8`,`uint1`), +right(`float8`,`int2`), +right(`float8`,`uint2`), +right(`float8`,`int4`), +right(`float8`,`uint4`), +right(`float8`,`int8`), +right(`float8`,`uint8`), +right(`float8`,`float4`), +right(`float8`,`float8`), +right(`float8`,`numeric`), +right(`float8`,`bit1`), +right(`float8`,`bit64`), +right(`float8`,`boolean`), +right(`float8`,`date`), +right(`float8`,`time`), +right(`float8`,`time(4)`), +right(`float8`,`datetime`), +right(`float8`,`datetime(4)`), +right(`float8`,`timestamp`), +right(`float8`,`timestamp(4)`), +right(`float8`,`year`), +right(`float8`,`char`), +right(`float8`,`varchar`), +right(`float8`,`binary`), +right(`float8`,`varbinary`), +right(`float8`,`tinyblob`), +right(`float8`,`blob`), +right(`float8`,`mediumblob`), +right(`float8`,`longblob`), +right(`float8`,`text`), +right(`float8`,`enum_t`), +right(`float8`,`set_t`), +right(`float8`,`json`), +right(`numeric`,`int1`), +right(`numeric`,`uint1`), +right(`numeric`,`int2`), +right(`numeric`,`uint2`), +right(`numeric`,`int4`), +right(`numeric`,`uint4`), +right(`numeric`,`int8`), +right(`numeric`,`uint8`), +right(`numeric`,`float4`), +right(`numeric`,`float8`), +right(`numeric`,`numeric`), +right(`numeric`,`bit1`), +right(`numeric`,`bit64`), +right(`numeric`,`boolean`), +right(`numeric`,`date`), +right(`numeric`,`time`), +right(`numeric`,`time(4)`), +right(`numeric`,`datetime`), +right(`numeric`,`datetime(4)`), +right(`numeric`,`timestamp`), +right(`numeric`,`timestamp(4)`), +right(`numeric`,`year`), +right(`numeric`,`char`), +right(`numeric`,`varchar`), +right(`numeric`,`binary`), +right(`numeric`,`varbinary`), +right(`numeric`,`tinyblob`), +right(`numeric`,`blob`), +right(`numeric`,`mediumblob`), +right(`numeric`,`longblob`), +right(`numeric`,`text`), +right(`numeric`,`enum_t`), +right(`numeric`,`set_t`), +right(`numeric`,`json`), +right(`bit1`,`int1`), +right(`bit1`,`uint1`), +right(`bit1`,`int2`), +right(`bit1`,`uint2`), +right(`bit1`,`int4`), +right(`bit1`,`uint4`), +right(`bit1`,`int8`), +right(`bit1`,`uint8`), +right(`bit1`,`float4`), +right(`bit1`,`float8`), +right(`bit1`,`numeric`), +right(`bit1`,`bit1`), +right(`bit1`,`bit64`), +right(`bit1`,`boolean`), +right(`bit1`,`date`), +right(`bit1`,`time`), +right(`bit1`,`time(4)`), +right(`bit1`,`datetime`), +right(`bit1`,`datetime(4)`), +right(`bit1`,`timestamp`), +right(`bit1`,`timestamp(4)`), +right(`bit1`,`year`), +right(`bit1`,`char`), +right(`bit1`,`varchar`), +right(`bit1`,`binary`), +right(`bit1`,`varbinary`), +right(`bit1`,`tinyblob`), +right(`bit1`,`blob`), +right(`bit1`,`mediumblob`), +right(`bit1`,`longblob`), +right(`bit1`,`text`), +right(`bit1`,`enum_t`), +right(`bit1`,`set_t`), +right(`bit1`,`json`), +right(`bit64`,`int1`), +right(`bit64`,`uint1`), +right(`bit64`,`int2`), +right(`bit64`,`uint2`), +right(`bit64`,`int4`), +right(`bit64`,`uint4`), +right(`bit64`,`int8`), +right(`bit64`,`uint8`), +right(`bit64`,`float4`), +right(`bit64`,`float8`), +right(`bit64`,`numeric`), +right(`bit64`,`bit1`), +right(`bit64`,`bit64`), +right(`bit64`,`boolean`), +right(`bit64`,`date`), +right(`bit64`,`time`), +right(`bit64`,`time(4)`), +right(`bit64`,`datetime`), +right(`bit64`,`datetime(4)`), +right(`bit64`,`timestamp`), +right(`bit64`,`timestamp(4)`), +right(`bit64`,`year`), +right(`bit64`,`char`), +right(`bit64`,`varchar`), +right(`bit64`,`binary`), +right(`bit64`,`varbinary`), +right(`bit64`,`tinyblob`), +right(`bit64`,`blob`), +right(`bit64`,`mediumblob`), +right(`bit64`,`longblob`), +right(`bit64`,`text`), +right(`bit64`,`enum_t`), +right(`bit64`,`set_t`), +right(`bit64`,`json`), +right(`boolean`,`int1`), +right(`boolean`,`uint1`), +right(`boolean`,`int2`), +right(`boolean`,`uint2`), +right(`boolean`,`int4`), +right(`boolean`,`uint4`), +right(`boolean`,`int8`), +right(`boolean`,`uint8`), +right(`boolean`,`float4`), +right(`boolean`,`float8`), +right(`boolean`,`numeric`), +right(`boolean`,`bit1`), +right(`boolean`,`bit64`), +right(`boolean`,`boolean`), +right(`boolean`,`date`), +right(`boolean`,`time`), +right(`boolean`,`time(4)`), +right(`boolean`,`datetime`), +right(`boolean`,`datetime(4)`), +right(`boolean`,`timestamp`), +right(`boolean`,`timestamp(4)`), +right(`boolean`,`year`), +right(`boolean`,`char`), +right(`boolean`,`varchar`), +right(`boolean`,`binary`), +right(`boolean`,`varbinary`), +right(`boolean`,`tinyblob`), +right(`boolean`,`blob`), +right(`boolean`,`mediumblob`), +right(`boolean`,`longblob`), +right(`boolean`,`text`), +right(`boolean`,`enum_t`), +right(`boolean`,`set_t`), +right(`boolean`,`json`), +right(`date`,`int1`), +right(`date`,`uint1`), +right(`date`,`int2`), +right(`date`,`uint2`), +right(`date`,`int4`), +right(`date`,`uint4`), +right(`date`,`int8`), +right(`date`,`uint8`), +right(`date`,`float4`), +right(`date`,`float8`), +right(`date`,`numeric`), +right(`date`,`bit1`), +right(`date`,`bit64`), +right(`date`,`boolean`), +right(`date`,`date`), +right(`date`,`time`), +right(`date`,`time(4)`), +right(`date`,`datetime`), +right(`date`,`datetime(4)`), +right(`date`,`timestamp`), +right(`date`,`timestamp(4)`), +right(`date`,`year`), +right(`date`,`char`), +right(`date`,`varchar`), +right(`date`,`binary`), +right(`date`,`varbinary`), +right(`date`,`tinyblob`), +right(`date`,`blob`), +right(`date`,`mediumblob`), +right(`date`,`longblob`), +right(`date`,`text`), +right(`date`,`enum_t`), +right(`date`,`set_t`), +right(`date`,`json`), +right(`time`,`int1`), +right(`time`,`uint1`), +right(`time`,`int2`), +right(`time`,`uint2`), +right(`time`,`int4`), +right(`time`,`uint4`), +right(`time`,`int8`), +right(`time`,`uint8`), +right(`time`,`float4`), +right(`time`,`float8`), +right(`time`,`numeric`), +right(`time`,`bit1`), +right(`time`,`bit64`), +right(`time`,`boolean`), +right(`time`,`date`), +right(`time`,`time`), +right(`time`,`time(4)`), +right(`time`,`datetime`), +right(`time`,`datetime(4)`), +right(`time`,`timestamp`), +right(`time`,`timestamp(4)`), +right(`time`,`year`), +right(`time`,`char`), +right(`time`,`varchar`), +right(`time`,`binary`), +right(`time`,`varbinary`), +right(`time`,`tinyblob`), +right(`time`,`blob`), +right(`time`,`mediumblob`), +right(`time`,`longblob`), +right(`time`,`text`), +right(`time`,`enum_t`), +right(`time`,`set_t`), +right(`time`,`json`), +right(`time(4)`,`int1`), +right(`time(4)`,`uint1`), +right(`time(4)`,`int2`), +right(`time(4)`,`uint2`), +right(`time(4)`,`int4`), +right(`time(4)`,`uint4`), +right(`time(4)`,`int8`), +right(`time(4)`,`uint8`), +right(`time(4)`,`float4`), +right(`time(4)`,`float8`), +right(`time(4)`,`numeric`), +right(`time(4)`,`bit1`), +right(`time(4)`,`bit64`), +right(`time(4)`,`boolean`), +right(`time(4)`,`date`), +right(`time(4)`,`time`), +right(`time(4)`,`time(4)`), +right(`time(4)`,`datetime`), +right(`time(4)`,`datetime(4)`), +right(`time(4)`,`timestamp`), +right(`time(4)`,`timestamp(4)`), +right(`time(4)`,`year`), +right(`time(4)`,`char`), +right(`time(4)`,`varchar`), +right(`time(4)`,`binary`), +right(`time(4)`,`varbinary`), +right(`time(4)`,`tinyblob`), +right(`time(4)`,`blob`), +right(`time(4)`,`mediumblob`), +right(`time(4)`,`longblob`), +right(`time(4)`,`text`), +right(`time(4)`,`enum_t`), +right(`time(4)`,`set_t`), +right(`time(4)`,`json`), +right(`datetime`,`int1`), +right(`datetime`,`uint1`), +right(`datetime`,`int2`), +right(`datetime`,`uint2`), +right(`datetime`,`int4`), +right(`datetime`,`uint4`), +right(`datetime`,`int8`), +right(`datetime`,`uint8`), +right(`datetime`,`float4`), +right(`datetime`,`float8`), +right(`datetime`,`numeric`), +right(`datetime`,`bit1`), +right(`datetime`,`bit64`), +right(`datetime`,`boolean`), +right(`datetime`,`date`), +right(`datetime`,`time`), +right(`datetime`,`time(4)`), +right(`datetime`,`datetime`), +right(`datetime`,`datetime(4)`), +right(`datetime`,`timestamp`), +right(`datetime`,`timestamp(4)`), +right(`datetime`,`year`), +right(`datetime`,`char`), +right(`datetime`,`varchar`), +right(`datetime`,`binary`), +right(`datetime`,`varbinary`), +right(`datetime`,`tinyblob`), +right(`datetime`,`blob`), +right(`datetime`,`mediumblob`), +right(`datetime`,`longblob`), +right(`datetime`,`text`), +right(`datetime`,`enum_t`), +right(`datetime`,`set_t`), +right(`datetime`,`json`), +right(`datetime(4)`,`int1`), +right(`datetime(4)`,`uint1`), +right(`datetime(4)`,`int2`), +right(`datetime(4)`,`uint2`), +right(`datetime(4)`,`int4`), +right(`datetime(4)`,`uint4`), +right(`datetime(4)`,`int8`), +right(`datetime(4)`,`uint8`), +right(`datetime(4)`,`float4`), +right(`datetime(4)`,`float8`), +right(`datetime(4)`,`numeric`), +right(`datetime(4)`,`bit1`), +right(`datetime(4)`,`bit64`), +right(`datetime(4)`,`boolean`), +right(`datetime(4)`,`date`), +right(`datetime(4)`,`time`), +right(`datetime(4)`,`time(4)`), +right(`datetime(4)`,`datetime`), +right(`datetime(4)`,`datetime(4)`), +right(`datetime(4)`,`timestamp`), +right(`datetime(4)`,`timestamp(4)`), +right(`datetime(4)`,`year`), +right(`datetime(4)`,`char`), +right(`datetime(4)`,`varchar`), +right(`datetime(4)`,`binary`), +right(`datetime(4)`,`varbinary`), +right(`datetime(4)`,`tinyblob`), +right(`datetime(4)`,`blob`), +right(`datetime(4)`,`mediumblob`), +right(`datetime(4)`,`longblob`), +right(`datetime(4)`,`text`), +right(`datetime(4)`,`enum_t`), +right(`datetime(4)`,`set_t`), +right(`datetime(4)`,`json`), +right(`timestamp`,`int1`), +right(`timestamp`,`uint1`), +right(`timestamp`,`int2`), +right(`timestamp`,`uint2`), +right(`timestamp`,`int4`), +right(`timestamp`,`uint4`), +right(`timestamp`,`int8`), +right(`timestamp`,`uint8`), +right(`timestamp`,`float4`), +right(`timestamp`,`float8`), +right(`timestamp`,`numeric`), +right(`timestamp`,`bit1`), +right(`timestamp`,`bit64`), +right(`timestamp`,`boolean`), +right(`timestamp`,`date`), +right(`timestamp`,`time`), +right(`timestamp`,`time(4)`), +right(`timestamp`,`datetime`), +right(`timestamp`,`datetime(4)`), +right(`timestamp`,`timestamp`), +right(`timestamp`,`timestamp(4)`), +right(`timestamp`,`year`), +right(`timestamp`,`char`), +right(`timestamp`,`varchar`), +right(`timestamp`,`binary`), +right(`timestamp`,`varbinary`), +right(`timestamp`,`tinyblob`), +right(`timestamp`,`blob`), +right(`timestamp`,`mediumblob`), +right(`timestamp`,`longblob`), +right(`timestamp`,`text`), +right(`timestamp`,`enum_t`), +right(`timestamp`,`set_t`), +right(`timestamp`,`json`), +right(`timestamp(4)`,`int1`), +right(`timestamp(4)`,`uint1`), +right(`timestamp(4)`,`int2`), +right(`timestamp(4)`,`uint2`), +right(`timestamp(4)`,`int4`), +right(`timestamp(4)`,`uint4`), +right(`timestamp(4)`,`int8`), +right(`timestamp(4)`,`uint8`), +right(`timestamp(4)`,`float4`), +right(`timestamp(4)`,`float8`), +right(`timestamp(4)`,`numeric`), +right(`timestamp(4)`,`bit1`), +right(`timestamp(4)`,`bit64`), +right(`timestamp(4)`,`boolean`), +right(`timestamp(4)`,`date`), +right(`timestamp(4)`,`time`), +right(`timestamp(4)`,`time(4)`), +right(`timestamp(4)`,`datetime`), +right(`timestamp(4)`,`datetime(4)`), +right(`timestamp(4)`,`timestamp`), +right(`timestamp(4)`,`timestamp(4)`), +right(`timestamp(4)`,`year`), +right(`timestamp(4)`,`char`), +right(`timestamp(4)`,`varchar`), +right(`timestamp(4)`,`binary`), +right(`timestamp(4)`,`varbinary`), +right(`timestamp(4)`,`tinyblob`), +right(`timestamp(4)`,`blob`), +right(`timestamp(4)`,`mediumblob`), +right(`timestamp(4)`,`longblob`), +right(`timestamp(4)`,`text`), +right(`timestamp(4)`,`enum_t`), +right(`timestamp(4)`,`set_t`), +right(`timestamp(4)`,`json`), +right(`year`,`int1`), +right(`year`,`uint1`), +right(`year`,`int2`), +right(`year`,`uint2`), +right(`year`,`int4`), +right(`year`,`uint4`), +right(`year`,`int8`), +right(`year`,`uint8`), +right(`year`,`float4`), +right(`year`,`float8`), +right(`year`,`numeric`), +right(`year`,`bit1`), +right(`year`,`bit64`), +right(`year`,`boolean`), +right(`year`,`date`), +right(`year`,`time`), +right(`year`,`time(4)`), +right(`year`,`datetime`), +right(`year`,`datetime(4)`), +right(`year`,`timestamp`), +right(`year`,`timestamp(4)`), +right(`year`,`year`), +right(`year`,`char`), +right(`year`,`varchar`), +right(`year`,`binary`), +right(`year`,`varbinary`), +right(`year`,`tinyblob`), +right(`year`,`blob`), +right(`year`,`mediumblob`), +right(`year`,`longblob`), +right(`year`,`text`), +right(`year`,`enum_t`), +right(`year`,`set_t`), +right(`year`,`json`), +right(`char`,`int1`), +right(`char`,`uint1`), +right(`char`,`int2`), +right(`char`,`uint2`), +right(`char`,`int4`), +right(`char`,`uint4`), +right(`char`,`int8`), +right(`char`,`uint8`), +right(`char`,`float4`), +right(`char`,`float8`), +right(`char`,`numeric`), +right(`char`,`bit1`), +right(`char`,`bit64`), +right(`char`,`boolean`), +right(`char`,`date`), +right(`char`,`time`), +right(`char`,`time(4)`), +right(`char`,`datetime`), +right(`char`,`datetime(4)`), +right(`char`,`timestamp`), +right(`char`,`timestamp(4)`), +right(`char`,`year`), +right(`char`,`char`), +right(`char`,`varchar`), +right(`char`,`binary`), +right(`char`,`varbinary`), +right(`char`,`tinyblob`), +right(`char`,`blob`), +right(`char`,`mediumblob`), +right(`char`,`longblob`), +right(`char`,`text`), +right(`char`,`enum_t`), +right(`char`,`set_t`), +right(`char`,`json`), +right(`varchar`,`int1`), +right(`varchar`,`uint1`), +right(`varchar`,`int2`), +right(`varchar`,`uint2`), +right(`varchar`,`int4`), +right(`varchar`,`uint4`), +right(`varchar`,`int8`), +right(`varchar`,`uint8`), +right(`varchar`,`float4`), +right(`varchar`,`float8`), +right(`varchar`,`numeric`), +right(`varchar`,`bit1`), +right(`varchar`,`bit64`), +right(`varchar`,`boolean`), +right(`varchar`,`date`), +right(`varchar`,`time`), +right(`varchar`,`time(4)`), +right(`varchar`,`datetime`), +right(`varchar`,`datetime(4)`), +right(`varchar`,`timestamp`), +right(`varchar`,`timestamp(4)`), +right(`varchar`,`year`), +right(`varchar`,`char`), +right(`varchar`,`varchar`), +right(`varchar`,`binary`), +right(`varchar`,`varbinary`), +right(`varchar`,`tinyblob`), +right(`varchar`,`blob`), +right(`varchar`,`mediumblob`), +right(`varchar`,`longblob`), +right(`varchar`,`text`), +right(`varchar`,`enum_t`), +right(`varchar`,`set_t`), +right(`varchar`,`json`), +right(`binary`,`int1`), +right(`binary`,`uint1`), +right(`binary`,`int2`), +right(`binary`,`uint2`), +right(`binary`,`int4`), +right(`binary`,`uint4`), +right(`binary`,`int8`), +right(`binary`,`uint8`), +right(`binary`,`float4`), +right(`binary`,`float8`), +right(`binary`,`numeric`), +right(`binary`,`bit1`), +right(`binary`,`bit64`), +right(`binary`,`boolean`), +right(`binary`,`date`), +right(`binary`,`time`), +right(`binary`,`time(4)`), +right(`binary`,`datetime`), +right(`binary`,`datetime(4)`), +right(`binary`,`timestamp`), +right(`binary`,`timestamp(4)`), +right(`binary`,`year`), +right(`binary`,`char`), +right(`binary`,`varchar`), +right(`binary`,`binary`), +right(`binary`,`varbinary`), +right(`binary`,`tinyblob`), +right(`binary`,`blob`), +right(`binary`,`mediumblob`), +right(`binary`,`longblob`), +right(`binary`,`text`), +right(`binary`,`enum_t`), +right(`binary`,`set_t`), +right(`binary`,`json`), +right(`varbinary`,`int1`), +right(`varbinary`,`uint1`), +right(`varbinary`,`int2`), +right(`varbinary`,`uint2`), +right(`varbinary`,`int4`), +right(`varbinary`,`uint4`), +right(`varbinary`,`int8`), +right(`varbinary`,`uint8`), +right(`varbinary`,`float4`), +right(`varbinary`,`float8`), +right(`varbinary`,`numeric`), +right(`varbinary`,`bit1`), +right(`varbinary`,`bit64`), +right(`varbinary`,`boolean`), +right(`varbinary`,`date`), +right(`varbinary`,`time`), +right(`varbinary`,`time(4)`), +right(`varbinary`,`datetime`), +right(`varbinary`,`datetime(4)`), +right(`varbinary`,`timestamp`), +right(`varbinary`,`timestamp(4)`), +right(`varbinary`,`year`), +right(`varbinary`,`char`), +right(`varbinary`,`varchar`), +right(`varbinary`,`binary`), +right(`varbinary`,`varbinary`), +right(`varbinary`,`tinyblob`), +right(`varbinary`,`blob`), +right(`varbinary`,`mediumblob`), +right(`varbinary`,`longblob`), +right(`varbinary`,`text`), +right(`varbinary`,`enum_t`), +right(`varbinary`,`set_t`), +right(`varbinary`,`json`), +right(`tinyblob`,`int1`), +right(`tinyblob`,`uint1`), +right(`tinyblob`,`int2`), +right(`tinyblob`,`uint2`), +right(`tinyblob`,`int4`), +right(`tinyblob`,`uint4`), +right(`tinyblob`,`int8`), +right(`tinyblob`,`uint8`), +right(`tinyblob`,`float4`), +right(`tinyblob`,`float8`), +right(`tinyblob`,`numeric`), +right(`tinyblob`,`bit1`), +right(`tinyblob`,`bit64`), +right(`tinyblob`,`boolean`), +right(`tinyblob`,`date`), +right(`tinyblob`,`time`), +right(`tinyblob`,`time(4)`), +right(`tinyblob`,`datetime`), +right(`tinyblob`,`datetime(4)`), +right(`tinyblob`,`timestamp`), +right(`tinyblob`,`timestamp(4)`), +right(`tinyblob`,`year`), +right(`tinyblob`,`char`), +right(`tinyblob`,`varchar`), +right(`tinyblob`,`binary`), +right(`tinyblob`,`varbinary`), +right(`tinyblob`,`tinyblob`), +right(`tinyblob`,`blob`), +right(`tinyblob`,`mediumblob`), +right(`tinyblob`,`longblob`), +right(`tinyblob`,`text`), +right(`tinyblob`,`enum_t`), +right(`tinyblob`,`set_t`), +right(`tinyblob`,`json`), +right(`blob`,`int1`), +right(`blob`,`uint1`), +right(`blob`,`int2`), +right(`blob`,`uint2`), +right(`blob`,`int4`), +right(`blob`,`uint4`), +right(`blob`,`int8`), +right(`blob`,`uint8`), +right(`blob`,`float4`), +right(`blob`,`float8`), +right(`blob`,`numeric`), +right(`blob`,`bit1`), +right(`blob`,`bit64`), +right(`blob`,`boolean`), +right(`blob`,`date`), +right(`blob`,`time`), +right(`blob`,`time(4)`), +right(`blob`,`datetime`), +right(`blob`,`datetime(4)`), +right(`blob`,`timestamp`), +right(`blob`,`timestamp(4)`), +right(`blob`,`year`), +right(`blob`,`char`), +right(`blob`,`varchar`), +right(`blob`,`binary`), +right(`blob`,`varbinary`), +right(`blob`,`tinyblob`), +right(`blob`,`blob`), +right(`blob`,`mediumblob`), +right(`blob`,`longblob`), +right(`blob`,`text`), +right(`blob`,`enum_t`), +right(`blob`,`set_t`), +right(`blob`,`json`), +right(`mediumblob`,`int1`), +right(`mediumblob`,`uint1`), +right(`mediumblob`,`int2`), +right(`mediumblob`,`uint2`), +right(`mediumblob`,`int4`), +right(`mediumblob`,`uint4`), +right(`mediumblob`,`int8`), +right(`mediumblob`,`uint8`), +right(`mediumblob`,`float4`), +right(`mediumblob`,`float8`), +right(`mediumblob`,`numeric`), +right(`mediumblob`,`bit1`), +right(`mediumblob`,`bit64`), +right(`mediumblob`,`boolean`), +right(`mediumblob`,`date`), +right(`mediumblob`,`time`), +right(`mediumblob`,`time(4)`), +right(`mediumblob`,`datetime`), +right(`mediumblob`,`datetime(4)`), +right(`mediumblob`,`timestamp`), +right(`mediumblob`,`timestamp(4)`), +right(`mediumblob`,`year`), +right(`mediumblob`,`char`), +right(`mediumblob`,`varchar`), +right(`mediumblob`,`binary`), +right(`mediumblob`,`varbinary`), +right(`mediumblob`,`tinyblob`), +right(`mediumblob`,`blob`), +right(`mediumblob`,`mediumblob`), +right(`mediumblob`,`longblob`), +right(`mediumblob`,`text`), +right(`mediumblob`,`enum_t`), +right(`mediumblob`,`set_t`), +right(`mediumblob`,`json`), +right(`longblob`,`int1`), +right(`longblob`,`uint1`), +right(`longblob`,`int2`), +right(`longblob`,`uint2`), +right(`longblob`,`int4`), +right(`longblob`,`uint4`), +right(`longblob`,`int8`), +right(`longblob`,`uint8`), +right(`longblob`,`float4`), +right(`longblob`,`float8`), +right(`longblob`,`numeric`), +right(`longblob`,`bit1`), +right(`longblob`,`bit64`), +right(`longblob`,`boolean`), +right(`longblob`,`date`), +right(`longblob`,`time`), +right(`longblob`,`time(4)`), +right(`longblob`,`datetime`), +right(`longblob`,`datetime(4)`), +right(`longblob`,`timestamp`), +right(`longblob`,`timestamp(4)`), +right(`longblob`,`year`), +right(`longblob`,`char`), +right(`longblob`,`varchar`), +right(`longblob`,`binary`), +right(`longblob`,`varbinary`), +right(`longblob`,`tinyblob`), +right(`longblob`,`blob`), +right(`longblob`,`mediumblob`), +right(`longblob`,`longblob`), +right(`longblob`,`text`), +right(`longblob`,`enum_t`), +right(`longblob`,`set_t`), +right(`longblob`,`json`), +right(`text`,`int1`), +right(`text`,`uint1`), +right(`text`,`int2`), +right(`text`,`uint2`), +right(`text`,`int4`), +right(`text`,`uint4`), +right(`text`,`int8`), +right(`text`,`uint8`), +right(`text`,`float4`), +right(`text`,`float8`), +right(`text`,`numeric`), +right(`text`,`bit1`), +right(`text`,`bit64`), +right(`text`,`boolean`), +right(`text`,`date`), +right(`text`,`time`), +right(`text`,`time(4)`), +right(`text`,`datetime`), +right(`text`,`datetime(4)`), +right(`text`,`timestamp`), +right(`text`,`timestamp(4)`), +right(`text`,`year`), +right(`text`,`char`), +right(`text`,`varchar`), +right(`text`,`binary`), +right(`text`,`varbinary`), +right(`text`,`tinyblob`), +right(`text`,`blob`), +right(`text`,`mediumblob`), +right(`text`,`longblob`), +right(`text`,`text`), +right(`text`,`enum_t`), +right(`text`,`set_t`), +right(`text`,`json`), +right(`enum_t`,`int1`), +right(`enum_t`,`uint1`), +right(`enum_t`,`int2`), +right(`enum_t`,`uint2`), +right(`enum_t`,`int4`), +right(`enum_t`,`uint4`), +right(`enum_t`,`int8`), +right(`enum_t`,`uint8`), +right(`enum_t`,`float4`), +right(`enum_t`,`float8`), +right(`enum_t`,`numeric`), +right(`enum_t`,`bit1`), +right(`enum_t`,`bit64`), +right(`enum_t`,`boolean`), +right(`enum_t`,`date`), +right(`enum_t`,`time`), +right(`enum_t`,`time(4)`), +right(`enum_t`,`datetime`), +right(`enum_t`,`datetime(4)`), +right(`enum_t`,`timestamp`), +right(`enum_t`,`timestamp(4)`), +right(`enum_t`,`year`), +right(`enum_t`,`char`), +right(`enum_t`,`varchar`), +right(`enum_t`,`binary`), +right(`enum_t`,`varbinary`), +right(`enum_t`,`tinyblob`), +right(`enum_t`,`blob`), +right(`enum_t`,`mediumblob`), +right(`enum_t`,`longblob`), +right(`enum_t`,`text`), +right(`enum_t`,`enum_t`), +right(`enum_t`,`set_t`), +right(`enum_t`,`json`), +right(`set_t`,`int1`), +right(`set_t`,`uint1`), +right(`set_t`,`int2`), +right(`set_t`,`uint2`), +right(`set_t`,`int4`), +right(`set_t`,`uint4`), +right(`set_t`,`int8`), +right(`set_t`,`uint8`), +right(`set_t`,`float4`), +right(`set_t`,`float8`), +right(`set_t`,`numeric`), +right(`set_t`,`bit1`), +right(`set_t`,`bit64`), +right(`set_t`,`boolean`), +right(`set_t`,`date`), +right(`set_t`,`time`), +right(`set_t`,`time(4)`), +right(`set_t`,`datetime`), +right(`set_t`,`datetime(4)`), +right(`set_t`,`timestamp`), +right(`set_t`,`timestamp(4)`), +right(`set_t`,`year`), +right(`set_t`,`char`), +right(`set_t`,`varchar`), +right(`set_t`,`binary`), +right(`set_t`,`varbinary`), +right(`set_t`,`tinyblob`), +right(`set_t`,`blob`), +right(`set_t`,`mediumblob`), +right(`set_t`,`longblob`), +right(`set_t`,`text`), +right(`set_t`,`enum_t`), +right(`set_t`,`set_t`), +right(`set_t`,`json`), +right(`json`,`int1`), +right(`json`,`uint1`), +right(`json`,`int2`), +right(`json`,`uint2`), +right(`json`,`int4`), +right(`json`,`uint4`), +right(`json`,`int8`), +right(`json`,`uint8`), +right(`json`,`float4`), +right(`json`,`float8`), +right(`json`,`numeric`), +right(`json`,`bit1`), +right(`json`,`bit64`), +right(`json`,`boolean`), +right(`json`,`date`), +right(`json`,`time`), +right(`json`,`time(4)`), +right(`json`,`datetime`), +right(`json`,`datetime(4)`), +right(`json`,`timestamp`), +right(`json`,`timestamp(4)`), +right(`json`,`year`), +right(`json`,`char`), +right(`json`,`varchar`), +right(`json`,`binary`), +right(`json`,`varbinary`), +right(`json`,`tinyblob`), +right(`json`,`blob`), +right(`json`,`mediumblob`), +right(`json`,`longblob`), +right(`json`,`text`), +right(`json`,`enum_t`), +right(`json`,`set_t`), +right(`json`,`json`) +from test_type_table; + +select +left(`int1`,`int1`), +left(`int1`,`uint1`), +left(`int1`,`int2`), +left(`int1`,`uint2`), +left(`int1`,`int4`), +left(`int1`,`uint4`), +left(`int1`,`int8`), +left(`int1`,`uint8`), +left(`int1`,`float4`), +left(`int1`,`float8`), +left(`int1`,`numeric`), +left(`int1`,`bit1`), +left(`int1`,`bit64`), +left(`int1`,`boolean`), +left(`int1`,`date`), +left(`int1`,`time`), +left(`int1`,`time(4)`), +left(`int1`,`datetime`), +left(`int1`,`datetime(4)`), +left(`int1`,`timestamp`), +left(`int1`,`timestamp(4)`), +left(`int1`,`year`), +left(`int1`,`char`), +left(`int1`,`varchar`), +left(`int1`,`binary`), +left(`int1`,`varbinary`), +left(`int1`,`tinyblob`), +left(`int1`,`blob`), +left(`int1`,`mediumblob`), +left(`int1`,`longblob`), +left(`int1`,`text`), +left(`int1`,`enum_t`), +left(`int1`,`set_t`), +left(`int1`,`json`), +left(`uint1`,`int1`), +left(`uint1`,`uint1`), +left(`uint1`,`int2`), +left(`uint1`,`uint2`), +left(`uint1`,`int4`), +left(`uint1`,`uint4`), +left(`uint1`,`int8`), +left(`uint1`,`uint8`), +left(`uint1`,`float4`), +left(`uint1`,`float8`), +left(`uint1`,`numeric`), +left(`uint1`,`bit1`), +left(`uint1`,`bit64`), +left(`uint1`,`boolean`), +left(`uint1`,`date`), +left(`uint1`,`time`), +left(`uint1`,`time(4)`), +left(`uint1`,`datetime`), +left(`uint1`,`datetime(4)`), +left(`uint1`,`timestamp`), +left(`uint1`,`timestamp(4)`), +left(`uint1`,`year`), +left(`uint1`,`char`), +left(`uint1`,`varchar`), +left(`uint1`,`binary`), +left(`uint1`,`varbinary`), +left(`uint1`,`tinyblob`), +left(`uint1`,`blob`), +left(`uint1`,`mediumblob`), +left(`uint1`,`longblob`), +left(`uint1`,`text`), +left(`uint1`,`enum_t`), +left(`uint1`,`set_t`), +left(`uint1`,`json`), +left(`int2`,`int1`), +left(`int2`,`uint1`), +left(`int2`,`int2`), +left(`int2`,`uint2`), +left(`int2`,`int4`), +left(`int2`,`uint4`), +left(`int2`,`int8`), +left(`int2`,`uint8`), +left(`int2`,`float4`), +left(`int2`,`float8`), +left(`int2`,`numeric`), +left(`int2`,`bit1`), +left(`int2`,`bit64`), +left(`int2`,`boolean`), +left(`int2`,`date`), +left(`int2`,`time`), +left(`int2`,`time(4)`), +left(`int2`,`datetime`), +left(`int2`,`datetime(4)`), +left(`int2`,`timestamp`), +left(`int2`,`timestamp(4)`), +left(`int2`,`year`), +left(`int2`,`char`), +left(`int2`,`varchar`), +left(`int2`,`binary`), +left(`int2`,`varbinary`), +left(`int2`,`tinyblob`), +left(`int2`,`blob`), +left(`int2`,`mediumblob`), +left(`int2`,`longblob`), +left(`int2`,`text`), +left(`int2`,`enum_t`), +left(`int2`,`set_t`), +left(`int2`,`json`), +left(`uint2`,`int1`), +left(`uint2`,`uint1`), +left(`uint2`,`int2`), +left(`uint2`,`uint2`), +left(`uint2`,`int4`), +left(`uint2`,`uint4`), +left(`uint2`,`int8`), +left(`uint2`,`uint8`), +left(`uint2`,`float4`), +left(`uint2`,`float8`), +left(`uint2`,`numeric`), +left(`uint2`,`bit1`), +left(`uint2`,`bit64`), +left(`uint2`,`boolean`), +left(`uint2`,`date`), +left(`uint2`,`time`), +left(`uint2`,`time(4)`), +left(`uint2`,`datetime`), +left(`uint2`,`datetime(4)`), +left(`uint2`,`timestamp`), +left(`uint2`,`timestamp(4)`), +left(`uint2`,`year`), +left(`uint2`,`char`), +left(`uint2`,`varchar`), +left(`uint2`,`binary`), +left(`uint2`,`varbinary`), +left(`uint2`,`tinyblob`), +left(`uint2`,`blob`), +left(`uint2`,`mediumblob`), +left(`uint2`,`longblob`), +left(`uint2`,`text`), +left(`uint2`,`enum_t`), +left(`uint2`,`set_t`), +left(`uint2`,`json`), +left(`int4`,`int1`), +left(`int4`,`uint1`), +left(`int4`,`int2`), +left(`int4`,`uint2`), +left(`int4`,`int4`), +left(`int4`,`uint4`), +left(`int4`,`int8`), +left(`int4`,`uint8`), +left(`int4`,`float4`), +left(`int4`,`float8`), +left(`int4`,`numeric`), +left(`int4`,`bit1`), +left(`int4`,`bit64`), +left(`int4`,`boolean`), +left(`int4`,`date`), +left(`int4`,`time`), +left(`int4`,`time(4)`), +left(`int4`,`datetime`), +left(`int4`,`datetime(4)`), +left(`int4`,`timestamp`), +left(`int4`,`timestamp(4)`), +left(`int4`,`year`), +left(`int4`,`char`), +left(`int4`,`varchar`), +left(`int4`,`binary`), +left(`int4`,`varbinary`), +left(`int4`,`tinyblob`), +left(`int4`,`blob`), +left(`int4`,`mediumblob`), +left(`int4`,`longblob`), +left(`int4`,`text`), +left(`int4`,`enum_t`), +left(`int4`,`set_t`), +left(`int4`,`json`), +left(`uint4`,`int1`), +left(`uint4`,`uint1`), +left(`uint4`,`int2`), +left(`uint4`,`uint2`), +left(`uint4`,`int4`), +left(`uint4`,`uint4`), +left(`uint4`,`int8`), +left(`uint4`,`uint8`), +left(`uint4`,`float4`), +left(`uint4`,`float8`), +left(`uint4`,`numeric`), +left(`uint4`,`bit1`), +left(`uint4`,`bit64`), +left(`uint4`,`boolean`), +left(`uint4`,`date`), +left(`uint4`,`time`), +left(`uint4`,`time(4)`), +left(`uint4`,`datetime`), +left(`uint4`,`datetime(4)`), +left(`uint4`,`timestamp`), +left(`uint4`,`timestamp(4)`), +left(`uint4`,`year`), +left(`uint4`,`char`), +left(`uint4`,`varchar`), +left(`uint4`,`binary`), +left(`uint4`,`varbinary`), +left(`uint4`,`tinyblob`), +left(`uint4`,`blob`), +left(`uint4`,`mediumblob`), +left(`uint4`,`longblob`), +left(`uint4`,`text`), +left(`uint4`,`enum_t`), +left(`uint4`,`set_t`), +left(`uint4`,`json`), +left(`int8`,`int1`), +left(`int8`,`uint1`), +left(`int8`,`int2`), +left(`int8`,`uint2`), +left(`int8`,`int4`), +left(`int8`,`uint4`), +left(`int8`,`int8`), +left(`int8`,`uint8`), +left(`int8`,`float4`), +left(`int8`,`float8`), +left(`int8`,`numeric`), +left(`int8`,`bit1`), +left(`int8`,`bit64`), +left(`int8`,`boolean`), +left(`int8`,`date`), +left(`int8`,`time`), +left(`int8`,`time(4)`), +left(`int8`,`datetime`), +left(`int8`,`datetime(4)`), +left(`int8`,`timestamp`), +left(`int8`,`timestamp(4)`), +left(`int8`,`year`), +left(`int8`,`char`), +left(`int8`,`varchar`), +left(`int8`,`binary`), +left(`int8`,`varbinary`), +left(`int8`,`tinyblob`), +left(`int8`,`blob`), +left(`int8`,`mediumblob`), +left(`int8`,`longblob`), +left(`int8`,`text`), +left(`int8`,`enum_t`), +left(`int8`,`set_t`), +left(`int8`,`json`), +left(`uint8`,`int1`), +left(`uint8`,`uint1`), +left(`uint8`,`int2`), +left(`uint8`,`uint2`), +left(`uint8`,`int4`), +left(`uint8`,`uint4`), +left(`uint8`,`int8`), +left(`uint8`,`uint8`), +left(`uint8`,`float4`), +left(`uint8`,`float8`), +left(`uint8`,`numeric`), +left(`uint8`,`bit1`), +left(`uint8`,`bit64`), +left(`uint8`,`boolean`), +left(`uint8`,`date`), +left(`uint8`,`time`), +left(`uint8`,`time(4)`), +left(`uint8`,`datetime`), +left(`uint8`,`datetime(4)`), +left(`uint8`,`timestamp`), +left(`uint8`,`timestamp(4)`), +left(`uint8`,`year`), +left(`uint8`,`char`), +left(`uint8`,`varchar`), +left(`uint8`,`binary`), +left(`uint8`,`varbinary`), +left(`uint8`,`tinyblob`), +left(`uint8`,`blob`), +left(`uint8`,`mediumblob`), +left(`uint8`,`longblob`), +left(`uint8`,`text`), +left(`uint8`,`enum_t`), +left(`uint8`,`set_t`), +left(`uint8`,`json`), +left(`float4`,`int1`), +left(`float4`,`uint1`), +left(`float4`,`int2`), +left(`float4`,`uint2`), +left(`float4`,`int4`), +left(`float4`,`uint4`), +left(`float4`,`int8`), +left(`float4`,`uint8`), +left(`float4`,`float4`), +left(`float4`,`float8`), +left(`float4`,`numeric`), +left(`float4`,`bit1`), +left(`float4`,`bit64`), +left(`float4`,`boolean`), +left(`float4`,`date`), +left(`float4`,`time`), +left(`float4`,`time(4)`), +left(`float4`,`datetime`), +left(`float4`,`datetime(4)`), +left(`float4`,`timestamp`), +left(`float4`,`timestamp(4)`), +left(`float4`,`year`), +left(`float4`,`char`), +left(`float4`,`varchar`), +left(`float4`,`binary`), +left(`float4`,`varbinary`), +left(`float4`,`tinyblob`), +left(`float4`,`blob`), +left(`float4`,`mediumblob`), +left(`float4`,`longblob`), +left(`float4`,`text`), +left(`float4`,`enum_t`), +left(`float4`,`set_t`), +left(`float4`,`json`), +left(`float8`,`int1`), +left(`float8`,`uint1`), +left(`float8`,`int2`), +left(`float8`,`uint2`), +left(`float8`,`int4`), +left(`float8`,`uint4`), +left(`float8`,`int8`), +left(`float8`,`uint8`), +left(`float8`,`float4`), +left(`float8`,`float8`), +left(`float8`,`numeric`), +left(`float8`,`bit1`), +left(`float8`,`bit64`), +left(`float8`,`boolean`), +left(`float8`,`date`), +left(`float8`,`time`), +left(`float8`,`time(4)`), +left(`float8`,`datetime`), +left(`float8`,`datetime(4)`), +left(`float8`,`timestamp`), +left(`float8`,`timestamp(4)`), +left(`float8`,`year`), +left(`float8`,`char`), +left(`float8`,`varchar`), +left(`float8`,`binary`), +left(`float8`,`varbinary`), +left(`float8`,`tinyblob`), +left(`float8`,`blob`), +left(`float8`,`mediumblob`), +left(`float8`,`longblob`), +left(`float8`,`text`), +left(`float8`,`enum_t`), +left(`float8`,`set_t`), +left(`float8`,`json`), +left(`numeric`,`int1`), +left(`numeric`,`uint1`), +left(`numeric`,`int2`), +left(`numeric`,`uint2`), +left(`numeric`,`int4`), +left(`numeric`,`uint4`), +left(`numeric`,`int8`), +left(`numeric`,`uint8`), +left(`numeric`,`float4`), +left(`numeric`,`float8`), +left(`numeric`,`numeric`), +left(`numeric`,`bit1`), +left(`numeric`,`bit64`), +left(`numeric`,`boolean`), +left(`numeric`,`date`), +left(`numeric`,`time`), +left(`numeric`,`time(4)`), +left(`numeric`,`datetime`), +left(`numeric`,`datetime(4)`), +left(`numeric`,`timestamp`), +left(`numeric`,`timestamp(4)`), +left(`numeric`,`year`), +left(`numeric`,`char`), +left(`numeric`,`varchar`), +left(`numeric`,`binary`), +left(`numeric`,`varbinary`), +left(`numeric`,`tinyblob`), +left(`numeric`,`blob`), +left(`numeric`,`mediumblob`), +left(`numeric`,`longblob`), +left(`numeric`,`text`), +left(`numeric`,`enum_t`), +left(`numeric`,`set_t`), +left(`numeric`,`json`), +left(`bit1`,`int1`), +left(`bit1`,`uint1`), +left(`bit1`,`int2`), +left(`bit1`,`uint2`), +left(`bit1`,`int4`), +left(`bit1`,`uint4`), +left(`bit1`,`int8`), +left(`bit1`,`uint8`), +left(`bit1`,`float4`), +left(`bit1`,`float8`), +left(`bit1`,`numeric`), +left(`bit1`,`bit1`), +left(`bit1`,`bit64`), +left(`bit1`,`boolean`), +left(`bit1`,`date`), +left(`bit1`,`time`), +left(`bit1`,`time(4)`), +left(`bit1`,`datetime`), +left(`bit1`,`datetime(4)`), +left(`bit1`,`timestamp`), +left(`bit1`,`timestamp(4)`), +left(`bit1`,`year`), +left(`bit1`,`char`), +left(`bit1`,`varchar`), +left(`bit1`,`binary`), +left(`bit1`,`varbinary`), +left(`bit1`,`tinyblob`), +left(`bit1`,`blob`), +left(`bit1`,`mediumblob`), +left(`bit1`,`longblob`), +left(`bit1`,`text`), +left(`bit1`,`enum_t`), +left(`bit1`,`set_t`), +left(`bit1`,`json`), +left(`bit64`,`int1`), +left(`bit64`,`uint1`), +left(`bit64`,`int2`), +left(`bit64`,`uint2`), +left(`bit64`,`int4`), +left(`bit64`,`uint4`), +left(`bit64`,`int8`), +left(`bit64`,`uint8`), +left(`bit64`,`float4`), +left(`bit64`,`float8`), +left(`bit64`,`numeric`), +left(`bit64`,`bit1`), +left(`bit64`,`bit64`), +left(`bit64`,`boolean`), +left(`bit64`,`date`), +left(`bit64`,`time`), +left(`bit64`,`time(4)`), +left(`bit64`,`datetime`), +left(`bit64`,`datetime(4)`), +left(`bit64`,`timestamp`), +left(`bit64`,`timestamp(4)`), +left(`bit64`,`year`), +left(`bit64`,`char`), +left(`bit64`,`varchar`), +left(`bit64`,`binary`), +left(`bit64`,`varbinary`), +left(`bit64`,`tinyblob`), +left(`bit64`,`blob`), +left(`bit64`,`mediumblob`), +left(`bit64`,`longblob`), +left(`bit64`,`text`), +left(`bit64`,`enum_t`), +left(`bit64`,`set_t`), +left(`bit64`,`json`), +left(`boolean`,`int1`), +left(`boolean`,`uint1`), +left(`boolean`,`int2`), +left(`boolean`,`uint2`), +left(`boolean`,`int4`), +left(`boolean`,`uint4`), +left(`boolean`,`int8`), +left(`boolean`,`uint8`), +left(`boolean`,`float4`), +left(`boolean`,`float8`), +left(`boolean`,`numeric`), +left(`boolean`,`bit1`), +left(`boolean`,`bit64`), +left(`boolean`,`boolean`), +left(`boolean`,`date`), +left(`boolean`,`time`), +left(`boolean`,`time(4)`), +left(`boolean`,`datetime`), +left(`boolean`,`datetime(4)`), +left(`boolean`,`timestamp`), +left(`boolean`,`timestamp(4)`), +left(`boolean`,`year`), +left(`boolean`,`char`), +left(`boolean`,`varchar`), +left(`boolean`,`binary`), +left(`boolean`,`varbinary`), +left(`boolean`,`tinyblob`), +left(`boolean`,`blob`), +left(`boolean`,`mediumblob`), +left(`boolean`,`longblob`), +left(`boolean`,`text`), +left(`boolean`,`enum_t`), +left(`boolean`,`set_t`), +left(`boolean`,`json`), +left(`date`,`int1`), +left(`date`,`uint1`), +left(`date`,`int2`), +left(`date`,`uint2`), +left(`date`,`int4`), +left(`date`,`uint4`), +left(`date`,`int8`), +left(`date`,`uint8`), +left(`date`,`float4`), +left(`date`,`float8`), +left(`date`,`numeric`), +left(`date`,`bit1`), +left(`date`,`bit64`), +left(`date`,`boolean`), +left(`date`,`date`), +left(`date`,`time`), +left(`date`,`time(4)`), +left(`date`,`datetime`), +left(`date`,`datetime(4)`), +left(`date`,`timestamp`), +left(`date`,`timestamp(4)`), +left(`date`,`year`), +left(`date`,`char`), +left(`date`,`varchar`), +left(`date`,`binary`), +left(`date`,`varbinary`), +left(`date`,`tinyblob`), +left(`date`,`blob`), +left(`date`,`mediumblob`), +left(`date`,`longblob`), +left(`date`,`text`), +left(`date`,`enum_t`), +left(`date`,`set_t`), +left(`date`,`json`), +left(`time`,`int1`), +left(`time`,`uint1`), +left(`time`,`int2`), +left(`time`,`uint2`), +left(`time`,`int4`), +left(`time`,`uint4`), +left(`time`,`int8`), +left(`time`,`uint8`), +left(`time`,`float4`), +left(`time`,`float8`), +left(`time`,`numeric`), +left(`time`,`bit1`), +left(`time`,`bit64`), +left(`time`,`boolean`), +left(`time`,`date`), +left(`time`,`time`), +left(`time`,`time(4)`), +left(`time`,`datetime`), +left(`time`,`datetime(4)`), +left(`time`,`timestamp`), +left(`time`,`timestamp(4)`), +left(`time`,`year`), +left(`time`,`char`), +left(`time`,`varchar`), +left(`time`,`binary`), +left(`time`,`varbinary`), +left(`time`,`tinyblob`), +left(`time`,`blob`), +left(`time`,`mediumblob`), +left(`time`,`longblob`), +left(`time`,`text`), +left(`time`,`enum_t`), +left(`time`,`set_t`), +left(`time`,`json`), +left(`time(4)`,`int1`), +left(`time(4)`,`uint1`), +left(`time(4)`,`int2`), +left(`time(4)`,`uint2`), +left(`time(4)`,`int4`), +left(`time(4)`,`uint4`), +left(`time(4)`,`int8`), +left(`time(4)`,`uint8`), +left(`time(4)`,`float4`), +left(`time(4)`,`float8`), +left(`time(4)`,`numeric`), +left(`time(4)`,`bit1`), +left(`time(4)`,`bit64`), +left(`time(4)`,`boolean`), +left(`time(4)`,`date`), +left(`time(4)`,`time`), +left(`time(4)`,`time(4)`), +left(`time(4)`,`datetime`), +left(`time(4)`,`datetime(4)`), +left(`time(4)`,`timestamp`), +left(`time(4)`,`timestamp(4)`), +left(`time(4)`,`year`), +left(`time(4)`,`char`), +left(`time(4)`,`varchar`), +left(`time(4)`,`binary`), +left(`time(4)`,`varbinary`), +left(`time(4)`,`tinyblob`), +left(`time(4)`,`blob`), +left(`time(4)`,`mediumblob`), +left(`time(4)`,`longblob`), +left(`time(4)`,`text`), +left(`time(4)`,`enum_t`), +left(`time(4)`,`set_t`), +left(`time(4)`,`json`), +left(`datetime`,`int1`), +left(`datetime`,`uint1`), +left(`datetime`,`int2`), +left(`datetime`,`uint2`), +left(`datetime`,`int4`), +left(`datetime`,`uint4`), +left(`datetime`,`int8`), +left(`datetime`,`uint8`), +left(`datetime`,`float4`), +left(`datetime`,`float8`), +left(`datetime`,`numeric`), +left(`datetime`,`bit1`), +left(`datetime`,`bit64`), +left(`datetime`,`boolean`), +left(`datetime`,`date`), +left(`datetime`,`time`), +left(`datetime`,`time(4)`), +left(`datetime`,`datetime`), +left(`datetime`,`datetime(4)`), +left(`datetime`,`timestamp`), +left(`datetime`,`timestamp(4)`), +left(`datetime`,`year`), +left(`datetime`,`char`), +left(`datetime`,`varchar`), +left(`datetime`,`binary`), +left(`datetime`,`varbinary`), +left(`datetime`,`tinyblob`), +left(`datetime`,`blob`), +left(`datetime`,`mediumblob`), +left(`datetime`,`longblob`), +left(`datetime`,`text`), +left(`datetime`,`enum_t`), +left(`datetime`,`set_t`), +left(`datetime`,`json`), +left(`datetime(4)`,`int1`), +left(`datetime(4)`,`uint1`), +left(`datetime(4)`,`int2`), +left(`datetime(4)`,`uint2`), +left(`datetime(4)`,`int4`), +left(`datetime(4)`,`uint4`), +left(`datetime(4)`,`int8`), +left(`datetime(4)`,`uint8`), +left(`datetime(4)`,`float4`), +left(`datetime(4)`,`float8`), +left(`datetime(4)`,`numeric`), +left(`datetime(4)`,`bit1`), +left(`datetime(4)`,`bit64`), +left(`datetime(4)`,`boolean`), +left(`datetime(4)`,`date`), +left(`datetime(4)`,`time`), +left(`datetime(4)`,`time(4)`), +left(`datetime(4)`,`datetime`), +left(`datetime(4)`,`datetime(4)`), +left(`datetime(4)`,`timestamp`), +left(`datetime(4)`,`timestamp(4)`), +left(`datetime(4)`,`year`), +left(`datetime(4)`,`char`), +left(`datetime(4)`,`varchar`), +left(`datetime(4)`,`binary`), +left(`datetime(4)`,`varbinary`), +left(`datetime(4)`,`tinyblob`), +left(`datetime(4)`,`blob`), +left(`datetime(4)`,`mediumblob`), +left(`datetime(4)`,`longblob`), +left(`datetime(4)`,`text`), +left(`datetime(4)`,`enum_t`), +left(`datetime(4)`,`set_t`), +left(`datetime(4)`,`json`), +left(`timestamp`,`int1`), +left(`timestamp`,`uint1`), +left(`timestamp`,`int2`), +left(`timestamp`,`uint2`), +left(`timestamp`,`int4`), +left(`timestamp`,`uint4`), +left(`timestamp`,`int8`), +left(`timestamp`,`uint8`), +left(`timestamp`,`float4`), +left(`timestamp`,`float8`), +left(`timestamp`,`numeric`), +left(`timestamp`,`bit1`), +left(`timestamp`,`bit64`), +left(`timestamp`,`boolean`), +left(`timestamp`,`date`), +left(`timestamp`,`time`), +left(`timestamp`,`time(4)`), +left(`timestamp`,`datetime`), +left(`timestamp`,`datetime(4)`), +left(`timestamp`,`timestamp`), +left(`timestamp`,`timestamp(4)`), +left(`timestamp`,`year`), +left(`timestamp`,`char`), +left(`timestamp`,`varchar`), +left(`timestamp`,`binary`), +left(`timestamp`,`varbinary`), +left(`timestamp`,`tinyblob`), +left(`timestamp`,`blob`), +left(`timestamp`,`mediumblob`), +left(`timestamp`,`longblob`), +left(`timestamp`,`text`), +left(`timestamp`,`enum_t`), +left(`timestamp`,`set_t`), +left(`timestamp`,`json`), +left(`timestamp(4)`,`int1`), +left(`timestamp(4)`,`uint1`), +left(`timestamp(4)`,`int2`), +left(`timestamp(4)`,`uint2`), +left(`timestamp(4)`,`int4`), +left(`timestamp(4)`,`uint4`), +left(`timestamp(4)`,`int8`), +left(`timestamp(4)`,`uint8`), +left(`timestamp(4)`,`float4`), +left(`timestamp(4)`,`float8`), +left(`timestamp(4)`,`numeric`), +left(`timestamp(4)`,`bit1`), +left(`timestamp(4)`,`bit64`), +left(`timestamp(4)`,`boolean`), +left(`timestamp(4)`,`date`), +left(`timestamp(4)`,`time`), +left(`timestamp(4)`,`time(4)`), +left(`timestamp(4)`,`datetime`), +left(`timestamp(4)`,`datetime(4)`), +left(`timestamp(4)`,`timestamp`), +left(`timestamp(4)`,`timestamp(4)`), +left(`timestamp(4)`,`year`), +left(`timestamp(4)`,`char`), +left(`timestamp(4)`,`varchar`), +left(`timestamp(4)`,`binary`), +left(`timestamp(4)`,`varbinary`), +left(`timestamp(4)`,`tinyblob`), +left(`timestamp(4)`,`blob`), +left(`timestamp(4)`,`mediumblob`), +left(`timestamp(4)`,`longblob`), +left(`timestamp(4)`,`text`), +left(`timestamp(4)`,`enum_t`), +left(`timestamp(4)`,`set_t`), +left(`timestamp(4)`,`json`), +left(`year`,`int1`), +left(`year`,`uint1`), +left(`year`,`int2`), +left(`year`,`uint2`), +left(`year`,`int4`), +left(`year`,`uint4`), +left(`year`,`int8`), +left(`year`,`uint8`), +left(`year`,`float4`), +left(`year`,`float8`), +left(`year`,`numeric`), +left(`year`,`bit1`), +left(`year`,`bit64`), +left(`year`,`boolean`), +left(`year`,`date`), +left(`year`,`time`), +left(`year`,`time(4)`), +left(`year`,`datetime`), +left(`year`,`datetime(4)`), +left(`year`,`timestamp`), +left(`year`,`timestamp(4)`), +left(`year`,`year`), +left(`year`,`char`), +left(`year`,`varchar`), +left(`year`,`binary`), +left(`year`,`varbinary`), +left(`year`,`tinyblob`), +left(`year`,`blob`), +left(`year`,`mediumblob`), +left(`year`,`longblob`), +left(`year`,`text`), +left(`year`,`enum_t`), +left(`year`,`set_t`), +left(`year`,`json`), +left(`char`,`int1`), +left(`char`,`uint1`), +left(`char`,`int2`), +left(`char`,`uint2`), +left(`char`,`int4`), +left(`char`,`uint4`), +left(`char`,`int8`), +left(`char`,`uint8`), +left(`char`,`float4`), +left(`char`,`float8`), +left(`char`,`numeric`), +left(`char`,`bit1`), +left(`char`,`bit64`), +left(`char`,`boolean`), +left(`char`,`date`), +left(`char`,`time`), +left(`char`,`time(4)`), +left(`char`,`datetime`), +left(`char`,`datetime(4)`), +left(`char`,`timestamp`), +left(`char`,`timestamp(4)`), +left(`char`,`year`), +left(`char`,`char`), +left(`char`,`varchar`), +left(`char`,`binary`), +left(`char`,`varbinary`), +left(`char`,`tinyblob`), +left(`char`,`blob`), +left(`char`,`mediumblob`), +left(`char`,`longblob`), +left(`char`,`text`), +left(`char`,`enum_t`), +left(`char`,`set_t`), +left(`char`,`json`), +left(`varchar`,`int1`), +left(`varchar`,`uint1`), +left(`varchar`,`int2`), +left(`varchar`,`uint2`), +left(`varchar`,`int4`), +left(`varchar`,`uint4`), +left(`varchar`,`int8`), +left(`varchar`,`uint8`), +left(`varchar`,`float4`), +left(`varchar`,`float8`), +left(`varchar`,`numeric`), +left(`varchar`,`bit1`), +left(`varchar`,`bit64`), +left(`varchar`,`boolean`), +left(`varchar`,`date`), +left(`varchar`,`time`), +left(`varchar`,`time(4)`), +left(`varchar`,`datetime`), +left(`varchar`,`datetime(4)`), +left(`varchar`,`timestamp`), +left(`varchar`,`timestamp(4)`), +left(`varchar`,`year`), +left(`varchar`,`char`), +left(`varchar`,`varchar`), +left(`varchar`,`binary`), +left(`varchar`,`varbinary`), +left(`varchar`,`tinyblob`), +left(`varchar`,`blob`), +left(`varchar`,`mediumblob`), +left(`varchar`,`longblob`), +left(`varchar`,`text`), +left(`varchar`,`enum_t`), +left(`varchar`,`set_t`), +left(`varchar`,`json`), +left(`binary`,`int1`), +left(`binary`,`uint1`), +left(`binary`,`int2`), +left(`binary`,`uint2`), +left(`binary`,`int4`), +left(`binary`,`uint4`), +left(`binary`,`int8`), +left(`binary`,`uint8`), +left(`binary`,`float4`), +left(`binary`,`float8`), +left(`binary`,`numeric`), +left(`binary`,`bit1`), +left(`binary`,`bit64`), +left(`binary`,`boolean`), +left(`binary`,`date`), +left(`binary`,`time`), +left(`binary`,`time(4)`), +left(`binary`,`datetime`), +left(`binary`,`datetime(4)`), +left(`binary`,`timestamp`), +left(`binary`,`timestamp(4)`), +left(`binary`,`year`), +left(`binary`,`char`), +left(`binary`,`varchar`), +left(`binary`,`binary`), +left(`binary`,`varbinary`), +left(`binary`,`tinyblob`), +left(`binary`,`blob`), +left(`binary`,`mediumblob`), +left(`binary`,`longblob`), +left(`binary`,`text`), +left(`binary`,`enum_t`), +left(`binary`,`set_t`), +left(`binary`,`json`), +left(`varbinary`,`int1`), +left(`varbinary`,`uint1`), +left(`varbinary`,`int2`), +left(`varbinary`,`uint2`), +left(`varbinary`,`int4`), +left(`varbinary`,`uint4`), +left(`varbinary`,`int8`), +left(`varbinary`,`uint8`), +left(`varbinary`,`float4`), +left(`varbinary`,`float8`), +left(`varbinary`,`numeric`), +left(`varbinary`,`bit1`), +left(`varbinary`,`bit64`), +left(`varbinary`,`boolean`), +left(`varbinary`,`date`), +left(`varbinary`,`time`), +left(`varbinary`,`time(4)`), +left(`varbinary`,`datetime`), +left(`varbinary`,`datetime(4)`), +left(`varbinary`,`timestamp`), +left(`varbinary`,`timestamp(4)`), +left(`varbinary`,`year`), +left(`varbinary`,`char`), +left(`varbinary`,`varchar`), +left(`varbinary`,`binary`), +left(`varbinary`,`varbinary`), +left(`varbinary`,`tinyblob`), +left(`varbinary`,`blob`), +left(`varbinary`,`mediumblob`), +left(`varbinary`,`longblob`), +left(`varbinary`,`text`), +left(`varbinary`,`enum_t`), +left(`varbinary`,`set_t`), +left(`varbinary`,`json`), +left(`tinyblob`,`int1`), +left(`tinyblob`,`uint1`), +left(`tinyblob`,`int2`), +left(`tinyblob`,`uint2`), +left(`tinyblob`,`int4`), +left(`tinyblob`,`uint4`), +left(`tinyblob`,`int8`), +left(`tinyblob`,`uint8`), +left(`tinyblob`,`float4`), +left(`tinyblob`,`float8`), +left(`tinyblob`,`numeric`), +left(`tinyblob`,`bit1`), +left(`tinyblob`,`bit64`), +left(`tinyblob`,`boolean`), +left(`tinyblob`,`date`), +left(`tinyblob`,`time`), +left(`tinyblob`,`time(4)`), +left(`tinyblob`,`datetime`), +left(`tinyblob`,`datetime(4)`), +left(`tinyblob`,`timestamp`), +left(`tinyblob`,`timestamp(4)`), +left(`tinyblob`,`year`), +left(`tinyblob`,`char`), +left(`tinyblob`,`varchar`), +left(`tinyblob`,`binary`), +left(`tinyblob`,`varbinary`), +left(`tinyblob`,`tinyblob`), +left(`tinyblob`,`blob`), +left(`tinyblob`,`mediumblob`), +left(`tinyblob`,`longblob`), +left(`tinyblob`,`text`), +left(`tinyblob`,`enum_t`), +left(`tinyblob`,`set_t`), +left(`tinyblob`,`json`), +left(`blob`,`int1`), +left(`blob`,`uint1`), +left(`blob`,`int2`), +left(`blob`,`uint2`), +left(`blob`,`int4`), +left(`blob`,`uint4`), +left(`blob`,`int8`), +left(`blob`,`uint8`), +left(`blob`,`float4`), +left(`blob`,`float8`), +left(`blob`,`numeric`), +left(`blob`,`bit1`), +left(`blob`,`bit64`), +left(`blob`,`boolean`), +left(`blob`,`date`), +left(`blob`,`time`), +left(`blob`,`time(4)`), +left(`blob`,`datetime`), +left(`blob`,`datetime(4)`), +left(`blob`,`timestamp`), +left(`blob`,`timestamp(4)`), +left(`blob`,`year`), +left(`blob`,`char`), +left(`blob`,`varchar`), +left(`blob`,`binary`), +left(`blob`,`varbinary`), +left(`blob`,`tinyblob`), +left(`blob`,`blob`), +left(`blob`,`mediumblob`), +left(`blob`,`longblob`), +left(`blob`,`text`), +left(`blob`,`enum_t`), +left(`blob`,`set_t`), +left(`blob`,`json`), +left(`mediumblob`,`int1`), +left(`mediumblob`,`uint1`), +left(`mediumblob`,`int2`), +left(`mediumblob`,`uint2`), +left(`mediumblob`,`int4`), +left(`mediumblob`,`uint4`), +left(`mediumblob`,`int8`), +left(`mediumblob`,`uint8`), +left(`mediumblob`,`float4`), +left(`mediumblob`,`float8`), +left(`mediumblob`,`numeric`), +left(`mediumblob`,`bit1`), +left(`mediumblob`,`bit64`), +left(`mediumblob`,`boolean`), +left(`mediumblob`,`date`), +left(`mediumblob`,`time`), +left(`mediumblob`,`time(4)`), +left(`mediumblob`,`datetime`), +left(`mediumblob`,`datetime(4)`), +left(`mediumblob`,`timestamp`), +left(`mediumblob`,`timestamp(4)`), +left(`mediumblob`,`year`), +left(`mediumblob`,`char`), +left(`mediumblob`,`varchar`), +left(`mediumblob`,`binary`), +left(`mediumblob`,`varbinary`), +left(`mediumblob`,`tinyblob`), +left(`mediumblob`,`blob`), +left(`mediumblob`,`mediumblob`), +left(`mediumblob`,`longblob`), +left(`mediumblob`,`text`), +left(`mediumblob`,`enum_t`), +left(`mediumblob`,`set_t`), +left(`mediumblob`,`json`), +left(`longblob`,`int1`), +left(`longblob`,`uint1`), +left(`longblob`,`int2`), +left(`longblob`,`uint2`), +left(`longblob`,`int4`), +left(`longblob`,`uint4`), +left(`longblob`,`int8`), +left(`longblob`,`uint8`), +left(`longblob`,`float4`), +left(`longblob`,`float8`), +left(`longblob`,`numeric`), +left(`longblob`,`bit1`), +left(`longblob`,`bit64`), +left(`longblob`,`boolean`), +left(`longblob`,`date`), +left(`longblob`,`time`), +left(`longblob`,`time(4)`), +left(`longblob`,`datetime`), +left(`longblob`,`datetime(4)`), +left(`longblob`,`timestamp`), +left(`longblob`,`timestamp(4)`), +left(`longblob`,`year`), +left(`longblob`,`char`), +left(`longblob`,`varchar`), +left(`longblob`,`binary`), +left(`longblob`,`varbinary`), +left(`longblob`,`tinyblob`), +left(`longblob`,`blob`), +left(`longblob`,`mediumblob`), +left(`longblob`,`longblob`), +left(`longblob`,`text`), +left(`longblob`,`enum_t`), +left(`longblob`,`set_t`), +left(`longblob`,`json`), +left(`text`,`int1`), +left(`text`,`uint1`), +left(`text`,`int2`), +left(`text`,`uint2`), +left(`text`,`int4`), +left(`text`,`uint4`), +left(`text`,`int8`), +left(`text`,`uint8`), +left(`text`,`float4`), +left(`text`,`float8`), +left(`text`,`numeric`), +left(`text`,`bit1`), +left(`text`,`bit64`), +left(`text`,`boolean`), +left(`text`,`date`), +left(`text`,`time`), +left(`text`,`time(4)`), +left(`text`,`datetime`), +left(`text`,`datetime(4)`), +left(`text`,`timestamp`), +left(`text`,`timestamp(4)`), +left(`text`,`year`), +left(`text`,`char`), +left(`text`,`varchar`), +left(`text`,`binary`), +left(`text`,`varbinary`), +left(`text`,`tinyblob`), +left(`text`,`blob`), +left(`text`,`mediumblob`), +left(`text`,`longblob`), +left(`text`,`text`), +left(`text`,`enum_t`), +left(`text`,`set_t`), +left(`text`,`json`), +left(`enum_t`,`int1`), +left(`enum_t`,`uint1`), +left(`enum_t`,`int2`), +left(`enum_t`,`uint2`), +left(`enum_t`,`int4`), +left(`enum_t`,`uint4`), +left(`enum_t`,`int8`), +left(`enum_t`,`uint8`), +left(`enum_t`,`float4`), +left(`enum_t`,`float8`), +left(`enum_t`,`numeric`), +left(`enum_t`,`bit1`), +left(`enum_t`,`bit64`), +left(`enum_t`,`boolean`), +left(`enum_t`,`date`), +left(`enum_t`,`time`), +left(`enum_t`,`time(4)`), +left(`enum_t`,`datetime`), +left(`enum_t`,`datetime(4)`), +left(`enum_t`,`timestamp`), +left(`enum_t`,`timestamp(4)`), +left(`enum_t`,`year`), +left(`enum_t`,`char`), +left(`enum_t`,`varchar`), +left(`enum_t`,`binary`), +left(`enum_t`,`varbinary`), +left(`enum_t`,`tinyblob`), +left(`enum_t`,`blob`), +left(`enum_t`,`mediumblob`), +left(`enum_t`,`longblob`), +left(`enum_t`,`text`), +left(`enum_t`,`enum_t`), +left(`enum_t`,`set_t`), +left(`enum_t`,`json`), +left(`set_t`,`int1`), +left(`set_t`,`uint1`), +left(`set_t`,`int2`), +left(`set_t`,`uint2`), +left(`set_t`,`int4`), +left(`set_t`,`uint4`), +left(`set_t`,`int8`), +left(`set_t`,`uint8`), +left(`set_t`,`float4`), +left(`set_t`,`float8`), +left(`set_t`,`numeric`), +left(`set_t`,`bit1`), +left(`set_t`,`bit64`), +left(`set_t`,`boolean`), +left(`set_t`,`date`), +left(`set_t`,`time`), +left(`set_t`,`time(4)`), +left(`set_t`,`datetime`), +left(`set_t`,`datetime(4)`), +left(`set_t`,`timestamp`), +left(`set_t`,`timestamp(4)`), +left(`set_t`,`year`), +left(`set_t`,`char`), +left(`set_t`,`varchar`), +left(`set_t`,`binary`), +left(`set_t`,`varbinary`), +left(`set_t`,`tinyblob`), +left(`set_t`,`blob`), +left(`set_t`,`mediumblob`), +left(`set_t`,`longblob`), +left(`set_t`,`text`), +left(`set_t`,`enum_t`), +left(`set_t`,`set_t`), +left(`set_t`,`json`), +left(`json`,`int1`), +left(`json`,`uint1`), +left(`json`,`int2`), +left(`json`,`uint2`), +left(`json`,`int4`), +left(`json`,`uint4`), +left(`json`,`int8`), +left(`json`,`uint8`), +left(`json`,`float4`), +left(`json`,`float8`), +left(`json`,`numeric`), +left(`json`,`bit1`), +left(`json`,`bit64`), +left(`json`,`boolean`), +left(`json`,`date`), +left(`json`,`time`), +left(`json`,`time(4)`), +left(`json`,`datetime`), +left(`json`,`datetime(4)`), +left(`json`,`timestamp`), +left(`json`,`timestamp(4)`), +left(`json`,`year`), +left(`json`,`char`), +left(`json`,`varchar`), +left(`json`,`binary`), +left(`json`,`varbinary`), +left(`json`,`tinyblob`), +left(`json`,`blob`), +left(`json`,`mediumblob`), +left(`json`,`longblob`), +left(`json`,`text`), +left(`json`,`enum_t`), +left(`json`,`set_t`), +left(`json`,`json`) +from test_type_table; +drop table test_type_table; + +select right('2022-12-12',b'1010'); +select right(b'1001010','2022-12-12'); +select right(false,2); +select left('2022-12-12',b'1010'); + drop schema db_b_left_right_test cascade; -reset current_schema; \ No newline at end of file +reset current_schema; diff --git a/contrib/dolphin/sql/string_func_test/db_b_substr_test.sql b/contrib/dolphin/sql/string_func_test/db_b_substr_test.sql index 57300940da9a3686b9c873113322b892a51eee4d..a4de1d56cf876fec93eaaca2c53932cfa8468e38 100644 --- a/contrib/dolphin/sql/string_func_test/db_b_substr_test.sql +++ b/contrib/dolphin/sql/string_func_test/db_b_substr_test.sql @@ -215,5 +215,13 @@ select substring('10010'::bytea, b'11'); select substring('11'::text, b'10010'); select substring('10010'::text, b'11'); +select substr('abcd', '2', '3'); + +drop table if exists t_substring_0033; +create table t_substring_0033 (c1 text ,c2 varchar(20),c3 text); +insert t_substring_0033 value('0/8',b'010','22cc'); +select substring(c1,c2,c3) from t_substring_0033; +drop table t_substring_0033; + drop schema db_b_substr_test cascade; reset current_schema; diff --git a/contrib/dolphin/sql/test_alter_table.sql b/contrib/dolphin/sql/test_alter_table.sql index 2d6b0559532a4b406c9bf89f6ff7b436d26b7dee..6cb9a68fc891cebc31e3aefa44a0b5c5f0316ae5 100644 --- a/contrib/dolphin/sql/test_alter_table.sql +++ b/contrib/dolphin/sql/test_alter_table.sql @@ -223,5 +223,13 @@ and relnamespace != (select oid from pg_namespace where nspname = 'pg_catalog') and c.relname != 'my_locks' group by c.relname; +-- test column table with alter table drop index +drop table if exists t_grammar0029; +create table t_grammar0029(id int unique, sex text) +with(orientation=column); +drop index if exists id_grammar0029; +create index id_grammar0029 on t_grammar0029 using psort(id) tablespace pg_default; +alter table t_grammar0029 drop key id_grammar0029; + drop schema db_alter_table cascade; reset current_schema; diff --git a/contrib/dolphin/sql/test_charset_collate.sql b/contrib/dolphin/sql/test_charset_collate.sql index 5f3da2017cfca000d5eda732280a1e2b5015d0ee..9259d7cd09cfeba8ded5da8dabad624e839932d8 100644 --- a/contrib/dolphin/sql/test_charset_collate.sql +++ b/contrib/dolphin/sql/test_charset_collate.sql @@ -67,6 +67,10 @@ alter table test_collate4 add column c4 text charset 'aaa' collate 'aaa'; alter table test_collate4 modify column c1 text collate 'bbb'; create table test_collate5(c1 text collate 'aaa', c2 text collate 'utf8mb4_bin', c3 text)collate 'aaa'; +-- different charset +show b_format_behavior_compat_options; +create table test_collate6(a text) charset gbk; +create table test_collate6(a text) collate gbk_bin; -- invalid schema collate create schema test1 charset 'aaa'; set schema 'test1'; diff --git a/contrib/dolphin/sql/test_datatype.sql b/contrib/dolphin/sql/test_datatype.sql index abe288bbb520a4493cfaea2eb459c0b853833e1d..37bc0475ce31911ce551ac45331f2cda3239a909 100644 --- a/contrib/dolphin/sql/test_datatype.sql +++ b/contrib/dolphin/sql/test_datatype.sql @@ -186,5 +186,19 @@ select * from t_bit; drop table test_bit64; drop table t_bit; + +-- test treat_float_with_precision_as_float_type +create table test_double(c1 double, c2 double(10, 0), c3 double(15, 3), c4 float, c5 float4, c6 float4(10, 0), c7 float4(7, 5), c8 float(10, 0), c9 float(7, 5), c10 float4(5)); +\d+ test_double; +drop table test_double; +set dolphin.treat_float_with_precision_as_float_type = true; +create table test_double(c1 double, c2 double(10, 0), c3 double(15, 3), c4 float, c5 float4, c6 float4(10, 0), c7 float4(7, 5), c8 float(10, 0), c9 float(7, 5), c10 float4(5)); +\d+ test_double; +insert into test_double values (12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456, 12.3456); +select * from test_double; +drop table test_double; + +reset dolphin.treat_float_with_precision_as_float_type; + drop schema b_datatype_test cascade; reset current_schema; \ No newline at end of file diff --git a/contrib/dolphin/sql/test_geometric_operator.sql b/contrib/dolphin/sql/test_geometric_operator.sql new file mode 100644 index 0000000000000000000000000000000000000000..c27cfe798480a91bb263417b78c1250559572e5b --- /dev/null +++ b/contrib/dolphin/sql/test_geometric_operator.sql @@ -0,0 +1,38 @@ +create schema test_geometric_operator; +set current_schema to 'test_geometric_operator'; +set dolphin.b_compatibility_mode to off; + +SELECT box '((0,0),(1,1))' + point '(2.0,0)' AS RESULT; +SELECT box '((0,0),(1,1))' - point '(2.0,0)' AS RESULT; +SELECT box '((0,0),(1,1))' * point '(2.0,0)' AS RESULT; +SELECT box '((0,0),(2,2))' / point '(2.0,0)' AS RESULT; +SELECT box '((1,-1),(-1,1))' # box '((1,1),(-2,-2))' AS RESULT; +SELECT # path'((1,0),(0,1),(-1,0))' AS RESULT; +SELECT @-@ path '((0,0),(1,0))' AS RESULT; +SELECT @@ circle '((0,0),10)' AS RESULT; +SELECT circle '((0,0),1)' <-> circle '((5,0),1)' AS RESULT; +SELECT box '((0,0),(1,1))' && box '((0,0),(2,2))' AS RESULT; +SELECT circle '((0,0),1)' << circle '((5,0),1)' AS RESULT; +SELECT circle '((5,0),1)' >> circle '((0,0),1)' AS RESULT; +SELECT box '((0,0),(1,1))' &< box '((0,0),(2,2))' AS RESULT; +SELECT box '((0,0),(3,3))' &> box '((0,0),(2,2))' AS RESULT; +SELECT box '((0,0),(3,3))' <<| box '((3,4),(5,5))' AS RESULT; +SELECT box '((3,4),(5,5))' |>> box '((0,0),(3,3))' AS RESULT; +SELECT box '((0,0),(1,1))' &<| box '((0,0),(2,2))' AS RESULT; +SELECT box '((0,0),(3,3))' |&> box '((0,0),(2,2))' AS RESULT; +SELECT box '((0,0),(-3,-3))' <^ box '((0,0),(2,2))' AS RESULT; +SELECT box '((0,0),(2,2))' >^ box '((0,0),(-3,-3))' AS RESULT; +SELECT lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))' AS RESULT; +SELECT ?- lseg '((-1,0),(1,0))' AS RESULT; +SELECT point '(1,0)' ?- point '(0,0)' AS RESULT; +SELECT ?| lseg '((-1,0),(1,0))' AS RESULT; +SELECT point '(0,1)' ?| point '(0,0)' AS RESULT; +SELECT lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))' AS RESULT; +SELECT lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))' AS RESULT; +SELECT circle '((0,0),2)' @> point '(1,1)' AS RESULT; +SELECT point '(1,1)' <@ circle '((0,0),2)' AS RESULT; +SELECT polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))' AS RESULT; + +reset dolphin.b_compatibility_mode; +drop schema test_geometric_operator cascade; +reset current_schema; \ No newline at end of file diff --git a/contrib/dolphin/sql/test_interval_expr.sql b/contrib/dolphin/sql/test_interval_expr.sql index 883ac2342e859b8c68ebcd5d1a3483f4cfc9d0e2..74171e038397f3e8d64383a8440d54c60c4f3590 100644 --- a/contrib/dolphin/sql/test_interval_expr.sql +++ b/contrib/dolphin/sql/test_interval_expr.sql @@ -67,6 +67,27 @@ select interval '1 2 3' minute_microsecond; select interval '1 2 3' minute to microsecond; select interval '1 2' second_microsecond; select interval '1 2' second to microsecond; +select interval 1 year year; +select interval 1 month month; +select interval 1 day day; +select interval 1 hour hour; +select interval 1 minute minute; +select interval 1 second second; +select date'20020304' + interval 1 hour; +select interval 1 hour + date'20020304'; +select date'20020304' - interval 1 hour; +select date'20020304' + interval 1 minute; +select interval 1 minute + date'20020304'; +select date'20020304' - interval 1 minute; +select date'20020304' + interval 1 second; +select interval 1 second + date'20020304'; +select date'20020304' - interval 1 second; +select date'20020304' * interval 1 hour; +select date'20020304' / interval 1 hour; +select date'20020304' * interval 1 minute; +select date'20020304' / interval 1 minute; +select date'20020304' * interval 1 second; +select date'20020304' / interval 1 second; create table k_1(a json,b blob,c longblob,d mediumblob,e tinyblob,f binary(20)); insert k_1 values('"2024-01-11 11:49:25"','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25','2024-01-11 11:49:25'); @@ -228,6 +249,91 @@ select date_sub(time'38:59:58', interval '5 4' hour_second); select date_sub(time'38:59:58', interval '5 4' minute_second); select date_sub(time'38:59:58', interval '5 4' week); set dolphin.cmpt_version=5.7; + +select date_add('2022-06-10 15:15:15', -10::interval year ) as updated_date; +select date_sub('2022-06-10 15:15:15', -10::interval year ) as updated_date; +select date_add('2022-06-10 15:15:15', -10::interval hour ) as updated_date; +select date_sub('2022-06-10 15:15:15', -10::interval hour ) as updated_date; +select date_add('2022-06-10 15:15:15', 10::interval year ) as updated_date; +select date_sub('2022-06-10 15:15:15', 10::interval year ) as updated_date; +select date_add('2022-06-10 15:15:15', 10::interval hour ) as updated_date; +select date_sub('2022-06-10 15:15:15', 10::interval hour ) as updated_date; +-- 运算 +select '2024-07-05 14:25:59' + interval 1 minute + 1; +select '2024-07-05' + interval 1 minute + 1; +select '2024-07-05 14:25:59' + interval 1 year + 1; +select '2024-07-05' + interval 1 year + 1; +select '2024-07-05 14:25:59' + interval 1 day + 1; +select '2024-07-05' + interval 1 day + 1; +select '2024-07-05 14:25:59' + interval 1 year_month + 1; +select '2024-07-05' + interval 1 year_month + 1; +select '2024-07-05 14:25:59' + interval 1 day_hour + 1; +select '2024-07-05' + interval 1 day_hour + 1; +select interval 1 minute + '2024-07-05 14:25:59' + 1; +select interval 1 minute + '2024-07-05' + 1; +select interval 1 year +'2024-07-05 14:25:59' + 1; +select interval 1 year + '2024-07-05' + 1; +select interval 1 day + '2024-07-05 14:25:59' + 1; +select interval 1 day + '2024-07-05' + 1; +select interval 1 year_month + '2024-07-05 14:25:59' + 1; +select interval 1 year_month + '2024-07-05' + interval 1 year_month + 1; +select interval 1 day_hour + '2024-07-05 14:25:59' + 1; +select interval 1 day_hour + '2024-07-05' + 1; +select '2024-07-05 14:25:59' - interval 1 minute + 1; +select '2024-07-05' - interval 1 minute + 1; +select '2024-07-05 14:25:59' - interval 1 year + 1; +select '2024-07-05' - interval 1 year + 1; +select '2024-07-05 14:25:59' - interval 1 day + 1; +select '2024-07-05' - interval 1 day + 1; +select '2024-07-05 14:25:59' - interval 1 year_month + 1; +select '2024-07-05' - interval 1 year_month + 1; +select '2024-07-05 14:25:59' - interval 1 day_hour + 1; +select '2024-07-05' - interval 1 day_hour + 1; + +select '20230205231050.968789' + interval 1 minute; +select '20230205231050.968789' + interval 1 hour; +select '20230205231050.968789' + interval 1 year; +select '20230205231050.968789' + interval 1 day; +select '20230205231050.968789' + interval 1 year_month; +select '20230205231050.968789' + interval 1 day_hour; +select '20230205231050.968789' + interval 1 day_microsecond; +select interval 1 minute + '20230205231050.968789'; +select interval 1 hour + '20230205231050.968789'; +select interval 1 year + '20230205231050.968789'; +select interval 1 day + '20230205231050.968789'; +select interval 1 year_month + '20230205231050.968789'; +select interval 1 day_hour + '20230205231050.968789'; +select interval 1 day_microsecond + '20230205231050.968789'; +select '20230205231050.968789' - interval 1 minute; +select '20230205231050.968789' - interval 1 hour; +select '20230205231050.968789' - interval 1 year; +select '20230205231050.968789' - interval 1 day; +select '20230205231050.968789' - interval 1 year_month; +select '20230205231050.968789' - interval 1 day_hour; +select '20230205231050.968789' - interval 1 day_microsecond; + +select '2023-02-28 14:25:59.999999' + interval 1 day_microsecond; +select '2023-02-28 14:25:59.999999' + interval 1 year; +select '2023-02-28 14:25:59.999999' + interval 1 month; +select '2023-02-28 14:25:59.999999' + interval 1 day; +select '2023-02-28 14:25:59.999999' + interval 1 hour; +select '2023-02-28 14:25:59.999999' + interval 1 minute; +select '2023-02-28 14:25:59.999999' + interval 1 second; +select interval 1 day_microsecond + '2023-02-28 14:25:59.999999'; +select interval 1 year + '2023-02-28 14:25:59.999999'; +select interval 1 month + '2023-02-28 14:25:59.999999'; +select interval 1 day + '2023-02-28 14:25:59.999999'; +select interval 1 hour + '2023-02-28 14:25:59.999999'; +select interval 1 minute + '2023-02-28 14:25:59.999999'; +select interval 1 second + '2023-02-28 14:25:59.999999'; +select '2023-02-28 14:25:59.999999' - interval 1 day_microsecond; +select '2023-02-28 14:25:59.999999' - interval 1 year; +select '2023-02-28 14:25:59.999999' - interval 1 month; +select '2023-02-28 14:25:59.999999' - interval 1 day; +select '2023-02-28 14:25:59.999999' - interval 1 hour; +select '2023-02-28 14:25:59.999999' - interval 1 minute; +select '2023-02-28 14:25:59.999999' - interval 1 second; + -- 全类型兼容 create table all_types_table ( `int1` tinyint, @@ -1410,6 +1516,18 @@ select datetime'2024-06-11 14:29:25'+ interval datetime'2024-02-11 14:29:25' min select timestamp'2024-06-11 14:29:25'+ interval timestamp'2024-02-11 14:29:25' minute; select timestamp'9990-06-11 14:29:25' + interval 9 year; select timestamp'9990-06-11 14:29:25' + interval 99 year; + +select '2003-11-11 00:00:50'::blob + interval '2' second; +select interval '2' second + '2003-11-11 00:00:50'::blob; +select '2003-11-11 00:00:50'::longblob + interval '2' second; +select interval '2' second + '2003-11-11 00:00:50'::longblob; +select '2003-11-11 00:00:50'::mediumblob + interval '2' second; +select interval '2' second + '2003-11-11 00:00:50'::mediumblob; +select '2003-11-11 00:00:50'::tinyblob + interval '2' second; +select interval '2' second + '2003-11-11 00:00:50'::tinyblob; +select '20031111000050'::json + interval '2' second; +select interval '2' second + '20031111000050'::json; + drop table all_types_table cascade; drop schema test_interval_expr cascade; reset current_schema; diff --git a/contrib/dolphin/sql/test_mysql_enum.sql b/contrib/dolphin/sql/test_mysql_enum.sql index 32dba01048c65a239ef23aace9b658a6ff804a9d..3befa53aebabbebd80f544d69c6e4e23fe48c75e 100644 --- a/contrib/dolphin/sql/test_mysql_enum.sql +++ b/contrib/dolphin/sql/test_mysql_enum.sql @@ -343,3 +343,17 @@ CREATE TYPE typenum AS ENUM ( 'a', 'a '); --expect success CREATE TYPE typenum AS ENUM ( 'a', ' a'); DROP TYPE typenum; + +create table enum_test_table1(a enum('2024-07-05', '2024-07-05 14:59:58', '14:59:59')); +insert enum_test_table1 values('2024-07-05'), ('2024-07-05 14:59:58'), ('14:59:59'); +select a + interval 1 day as 'a + interval 1 day' from enum_test_table1; +select interval 1 day + a as 'interval 1 day + a' from enum_test_table1; +select a - interval 1 day as 'a - interval 1 day' from enum_test_table1; +drop table enum_test_table1; + +create table set_t(a set('2024-07-05', '2024-07-05 14:59:58', '14:59:59')); +insert set_t values('2024-07-05'), ('2024-07-05 14:59:58'), ('14:59:59'); +select a + interval 1 day as 'a + interval 1 day' from set_t; +select interval 1 day + a as 'interval 1 day + a' from set_t; +select a - interval 1 day as 'a - interval 1 day' from set_t; +drop table set_t; diff --git a/contrib/dolphin/sql/test_proxy.sql b/contrib/dolphin/sql/test_proxy.sql index 71df3cf6dafa0438af17d73bd9f1833024c4a844..fdd4eb42e6914838a247b60a86077221b894f3ff 100644 --- a/contrib/dolphin/sql/test_proxy.sql +++ b/contrib/dolphin/sql/test_proxy.sql @@ -96,6 +96,12 @@ drop role test_proxy_u1; drop role test_proxy_u2; drop role test_proxy_u3; +-- test PROXY as colname +create table t1 (proxy int); +insert into t1 values (1); +select proxy from t1; +drop table t1; + drop schema db_proxy cascade; drop schema tst_schema1 cascade; reset current_schema; diff --git a/contrib/dolphin/sql/test_uuid_short.sql b/contrib/dolphin/sql/test_uuid_short.sql index d23822b55cd32dc5a8803a9935c5408c592446ed..596a2667aa61931fbf6a33d9dea3e2384651a19a 100644 --- a/contrib/dolphin/sql/test_uuid_short.sql +++ b/contrib/dolphin/sql/test_uuid_short.sql @@ -5,5 +5,8 @@ select uuid_short(); select uuid_short(); +select uuid(null); +select uuid(1); + drop schema test_uuid_short cascade; reset current_schema; \ No newline at end of file diff --git a/contrib/dolphin/sql/uint_agg.sql b/contrib/dolphin/sql/uint_agg.sql index b65f89e36beaba2e615a0ace8b2b47ed7497bac0..8d2ac0a26b5af1f7fe043b889ed3bc52eb2e0570 100644 --- a/contrib/dolphin/sql/uint_agg.sql +++ b/contrib/dolphin/sql/uint_agg.sql @@ -85,6 +85,54 @@ create table smp_test(a uint4, b uint8); insert into smp_test select generate_series(1, 100000), generate_series(2, 100001); insert into smp_test select a + 100000, b from smp_test; +-- varbinary test +set dolphin.sql_mode = ''; +drop table if exists t; +CREATE TABLE t(i INT, li BIGINT, b VARBINARY(8), lb VARBINARY(24), d DOUBLE GENERATED ALWAYS AS (i*1.0)); +INSERT INTO t(i, li, b, lb) VALUES +(NULL, NULL, NULL, NULL), +(0, 0, X'0000000000000000', +X'000000000000000000000000000000000000000000000000'), +(0, 0, X'0000000000000000', +X'000000000000000000000000000000000000000000000000'), +(1, 1, X'0000000000000001', +X'000000000000000000000000000000000000000000000001'), +(1, 1, X'0000000000000001', +X'000000000000000000000000000000000000000000000001'), +(2, 2, X'0000000000000002', +X'000000000000000000000000000000000000000000000002'), +(2, 2, X'0000000000000002', +X'000000000000000000000000000000000000000000000002'), +(3, 3, X'0000000000000003', +X'000000000000000000000000000000000000000000000003'), +(3, 3, X'0000000000000003', +X'000000000000000000000000000000000000000000000003'), +(4, 4, X'0000000000000004', +X'000000000000000000000000000000000000000000000004'), +(4, 4, X'0000000000000004', +X'000000000000000000000000000000000000000000000004'), +(5, 5, X'0000000000000005', +X'000000000000000000000000000000000000000000000005'), +(6, 6, X'0000000000000006', +X'000000000000000000000000000000000000000000000006'), +(X'01234567', X'0123456789ABCDEF', X'0123456789ABCDEF', +X'000000000000000000000000000000000123456789ABCDEF'), +(X'01200567', X'0120056789ABCDEF', X'0120056789ABCDEF', +X'0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF'), +(X'01200567', X'0120056789ABCDEF', X'0120056789ABCDEF', +X'0120056789ABCDEF0120056789ABCDEF0120056789ABCDEF'), +(X'01200117', X'0120011789ABCDEF', X'0120011789ABCDEF', +X'0120011789ABCDEF0120011789ABCDEF0120011789ABCDEF'); + +SELECT HEX(i), HEX(li), HEX(b), HEX(lb), +HEX(BIT_AND(i) OVER w), HEX(BIT_AND(li) OVER w), +HEX(BIT_AND(b) OVER w), HEX(BIT_AND(lb) OVER w), +SUM(d) OVER w AS dsum +FROM t +WINDOW w AS (ORDER BY i ROWS 2 PRECEDING); +drop table t; +reset dolphin.sql_mode; + set query_dop = 2; explain(costs off, verbose) select avg(a), avg(b) from smp_test; explain(costs off, verbose) select bit_and(a), bit_and(b) from smp_test; diff --git a/contrib/dolphin/sql/uint_join.sql b/contrib/dolphin/sql/uint_join.sql index 2fb7f8c772741c90deadee56e326b562ba1231f0..747f5d95b0b91cd7615a730cd9b7bff4ada6f241 100644 --- a/contrib/dolphin/sql/uint_join.sql +++ b/contrib/dolphin/sql/uint_join.sql @@ -48,4 +48,88 @@ select * from scott.emp join scott.dept using(deptno, mgr); select * from scott.emp natural join scott.dept; drop schema scott cascade; -reset current_schema; \ No newline at end of file +reset current_schema; + +-- test merge join +set enable_hashjoin to off; +set enable_nestloop to off; +set enable_mergejoin to on; +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; + +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT1); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id uint2); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT4); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; +create table business_order (id bigint NOT NULL); +create table statement (business_order_id bigint NOT NULL, user_invoice_account_id UINT8); +create table user_invoice_account (id bigint NOT NULL); +insert into business_order values(generate_series(-2, 3)); +insert into statement values(generate_series(-1, 3), generate_series(2, 5)); +insert into user_invoice_account values(generate_series(-3, 4)); +explain (costs off) select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; +select * from business_order bo + left join statement s on bo.id = s.business_order_id + left join user_invoice_account uia on s.user_invoice_account_id = uia.id + order by bo.id, business_order_id, user_invoice_account_id, uia.id; + +reset enable_hashjoin; +reset enable_nestloop; +reset enable_mergejoin; +drop table if exists business_order; +drop table if exists statement; +drop table if exists user_invoice_account; diff --git a/contrib/dolphin/sql/ustore_test.sql b/contrib/dolphin/sql/ustore_test.sql new file mode 100644 index 0000000000000000000000000000000000000000..b94ac5e2806f4bb4035d7856d12a08019feb5c4d --- /dev/null +++ b/contrib/dolphin/sql/ustore_test.sql @@ -0,0 +1,15 @@ +create schema ustore_test; +set current_schema to 'ustore_test'; + +set enable_default_ustore_table = true; + + +create table t_year_0005(ts1 year primary key, ts2 year(2)check(ts2 > 1998), ts3 year(4) default 2012); +create table t_year_0005_01(ts1 year primary key, ts2 year(2)check(ts2 > 1998), ts3 year(4) default 2012); + +-- clear +drop table if exists t_year_0005 cascade; +drop table if exists t_year_0005_01 cascade; +reset enable_default_ustore_table; +drop schema ustore_test cascade; +reset current_schema; \ No newline at end of file diff --git a/contrib/dolphin/tablecmds.cpp b/contrib/dolphin/tablecmds.cpp index b9cf11d313014b5e7c29bac7a761b9911916c7b6..b826006b11db3533349d8839bc8da73b60c04bcc 100644 --- a/contrib/dolphin/tablecmds.cpp +++ b/contrib/dolphin/tablecmds.cpp @@ -943,6 +943,7 @@ inline static bool CStoreSupportATCmd(AlterTableType cmdtype) case AT_VisibleIndexDirect: #ifdef DOLPHIN case AT_RebuildIndex: + case AT_DropIndex: #endif ret = true; break; @@ -1351,6 +1352,7 @@ static List* AddDefaultOptionsIfNeed(List* options, const char relkind, CreateSt ereport(ERROR, (errcode(ERRCODE_INVALID_OPTION), errmsg("There is a conflict caused by storage_type and orientation"))); } + bool noSupportTable = segment || isCStore || isTsStore || relkind != RELKIND_RELATION || stmt->relation->relpersistence == RELPERSISTENCE_UNLOGGED || stmt->relation->relpersistence == RELPERSISTENCE_TEMP || @@ -1404,7 +1406,7 @@ static List* AddDefaultOptionsIfNeed(List* options, const char relkind, CreateSt } if (g_instance.attr.attr_storage.enable_ustore && u_sess->attr.attr_sql.enable_default_ustore_table && relkind != RELKIND_MATVIEW && !IsSystemNamespace(relnamespace) && !assignedStorageType) { - DefElem *def2 = makeDefElem("storage_type", (Node *)makeString(TABLE_ACCESS_METHOD_USTORE)); + DefElem *def2 = makeDefElem("storage_type", (Node *)makeString(TABLE_ACCESS_METHOD_USTORE_LOWER)); res = lappend(options, def2); } } @@ -2400,7 +2402,12 @@ ObjectAddress DefineRelation(CreateStmt* stmt, char relkind, Oid ownerId, Object /* Check namespace permissions. */ AclResult aclresult; - aclresult = pg_namespace_aclcheck(namespaceId, ownerId, ACL_CREATE); + if (DB_IS_CMPT(PG_FORMAT) && u_sess->hook_cxt.forTsdbHook) { + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE); + } else { + aclresult = pg_namespace_aclcheck(namespaceId, ownerId, ACL_CREATE); + } + bool anyResult = false; if (aclresult != ACLCHECK_OK && !IsSysSchema(namespaceId)) { anyResult = CheckRelationCreateAnyPrivilege(ownerId, relkind); @@ -4323,7 +4330,7 @@ static bool CheckClassFormPermission(Form_pg_class classform) } /* Allow DROP to table owner, schema owner or users who have DROP privilege of the target object */ -static void DropRelationPermissionCheck(char relkind, Oid relOid, Oid nspOid, const char* relname) +void DropRelationPermissionCheck(char relkind, Oid relOid, Oid nspOid, const char* relname) { AclResult aclresult; if (relkind == RELKIND_INDEX) { @@ -11731,7 +11738,7 @@ void check_of_type(HeapTuple typetuple) Form_pg_type typ = (Form_pg_type)GETSTRUCT(typetuple); bool typeOk = false; - if (typ->typtype == TYPTYPE_COMPOSITE) { + if (typ->typtype == TYPTYPE_COMPOSITE || typ->typtype == TYPTYPE_ABSTRACT_OBJECT) { Relation typeRelation; Assert(OidIsValid(typ->typrelid)); @@ -13770,6 +13777,8 @@ static ObjectAddress ATExecAddColumn(List** wqueue, AlteredTableInfo* tab, Relat query_str = CheckPgRewriteFirstAfter(rel); tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE; tab->is_first_after = true; + } else if (rel->rd_rel->relkind == RELKIND_RELATION) { + query_str = CheckPgRewriteFirstAfter(rel); } InsertPgAttributeTuple(attrdesc, &attribute, NULL); @@ -13812,6 +13821,19 @@ static ObjectAddress ATExecAddColumn(List** wqueue, AlteredTableInfo* tab, Relat /* create or replace view */ ReplaceViewQueryFirstAfter(query_str); + } else if (rel->rd_rel->relkind == RELKIND_RELATION && query_str != NIL) { + ListCell* viewinfo = NULL; + bool isViewValid = true; + foreach (viewinfo, query_str) { + ViewInfoForAdd *info = (ViewInfoForAdd *)lfirst(viewinfo); + isViewValid &= GetPgObjectValid(info->ev_class, OBJECT_TYPE_VIEW); + if (!isViewValid) { + break; + } + } + if (isViewValid) { + ReplaceViewQueryFirstAfter(query_str); + } } /* @@ -14296,6 +14318,7 @@ static ObjectAddress ATExecDropNotNull(Relation rel, const char* colName, LOCKMO List* indexoidlist = NIL; ListCell* indexoidscan = NULL; ObjectAddress address; + Oid replidindex; /* * lookup the attribute @@ -14323,6 +14346,9 @@ static ObjectAddress ATExecDropNotNull(Relation rel, const char* colName, LOCKMO /* Loop over all indexes on the relation */ indexoidlist = RelationGetIndexList(rel); + /* replica identity index */ + replidindex = rel->rd_replidindex; + foreach (indexoidscan, indexoidlist) { Oid indexoid = lfirst_oid(indexoidscan); HeapTuple indexTuple; @@ -14353,6 +14379,16 @@ static ObjectAddress ATExecDropNotNull(Relation rel, const char* colName, LOCKMO } } + /* REPLICA IDENTIFY can't drop not null */ + if (replidindex == indexoid) { + for (i = 0; i < indnkeyatts; i++) { + if (indexStruct->indkey.values[i] == attnum) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("column \"%s\" used as replica identity can't drop not null", colName))); + } + } + ReleaseSysCache(indexTuple); } @@ -20228,6 +20264,18 @@ bool static transformCompressedOptions(Relation rel, bytea* relOption, List* def return false; } + if (g_instance.attr.attr_common.support_extended_features) { + ereport(WARNING, + (errmsg("The compressed relation you are using is an unofficial supported extended feature.")) + ); + } else { + ereport(ERROR, + (errmsg("The compressed relation you are trying to create or alter " + "is an unofficial supported extended feature."), + errhint("Turn on GUC 'support_extended_features' to enable it.")) + ); + } + /* If the relkind doesn't support compressed options, check if delist contains compressed options. * If does, throw exception. */ @@ -21213,7 +21261,7 @@ static void copy_relation_data(Relation rel, SMgrRelation* dstptr, ForkNumber fo UnlockReleaseBuffer(buf); } else { if (RelationIsUstoreFormat(rel)) { - if (ExecuteUndoActionsPageForPartition(rel, dst, forkNum, blkno, blkno, ROLLBACK_OP_FOR_MOVE_TBLSPC)) { + if (ExecuteUndoActionsForPartition(rel, dst, forkNum, blkno, blkno, ROLLBACK_OP_FOR_MOVE_TBLSPC)) { *dstptr = dst = smgropen(newFileNode, backendId); src = rel->rd_smgr; } @@ -21462,7 +21510,7 @@ static void mergeHeapBlock(Relation src, Relation dest, ForkNumber forkNum, char pToastInfo.destToastRelOid = dest->rd_id; pToastInfo.chunkIdHashTable = chunkIdHashTable; } - if (ExecuteUndoActionsPageForPartition(src, dest->rd_smgr, forkNum, src_blkno, dest_blkno, + if (ExecuteUndoActionsForPartition(src, dest->rd_smgr, forkNum, src_blkno, dest_blkno, ROLLBACK_OP_FOR_MERGE_PARTITION, &pToastInfo)) { RelationOpenSmgr(dest); } @@ -26724,8 +26772,8 @@ void ATExecSetIndexVisibleState(Oid objOid, bool newState) if (dirty) { HeapTuple newitup = NULL; Datum values[Natts_pg_index]; - bool nulls[Natts_pg_class]; - bool replaces[Natts_pg_class]; + bool nulls[Natts_pg_index]; + bool replaces[Natts_pg_index]; errno_t rc; rc = memset_s(values, sizeof(values), 0, sizeof(values)); securec_check(rc, "\0", "\0"); @@ -28593,7 +28641,7 @@ static bool checkChunkIdRepeat(List* srcPartToastRels, int selfIndex, Oid chunkI return false; } -static void ExecUndoActionsPageForRelation(Relation rel) +static void ExecuteUndoActionsForRelation(Relation rel) { Assert(RelationIsUstoreFormat(rel)); @@ -28606,25 +28654,25 @@ static void ExecUndoActionsPageForRelation(Relation rel) } for (BlockNumber blkno = 0; blkno < srcHeapBlocks; blkno ++) { - ExecuteUndoActionsPageForPartition(rel, rel->rd_smgr, MAIN_FORKNUM, blkno, blkno, + ExecuteUndoActionsForPartition(rel, rel->rd_smgr, MAIN_FORKNUM, blkno, blkno, ROLLBACK_OP_FOR_EXCHANGE_PARTITION); } RelationCloseSmgr(rel); } -static void ExecUndoActionsPageForExchangePartition(Relation partTableRel, Oid partOid, Relation ordTableRel) +static void ExecuteUndoActionsForExchangePartition(Relation partTableRel, Oid partOid, Relation ordTableRel) { Partition part = NULL; Relation partRel = NULL; part = partitionOpen(partTableRel, partOid, NoLock); partRel = partitionGetRelation(partTableRel, part); - ExecUndoActionsPageForRelation(partRel); + ExecuteUndoActionsForRelation(partRel); releaseDummyRelation(&partRel); partitionClose(partTableRel, part, NoLock); - ExecUndoActionsPageForRelation(ordTableRel); + ExecuteUndoActionsForRelation(ordTableRel); } // Description : Execute exchange @@ -28709,7 +28757,7 @@ static void ATExecExchangePartition(Relation partTableRel, AlterTableCmd* cmd) checkIndexForExchange(partTableRel, partOid, ordTableRel, &partIndexList, &ordIndexList); if (RelationIsUstoreFormat(partTableRel)) { - ExecUndoActionsPageForExchangePartition(partTableRel, partOid, ordTableRel); + ExecuteUndoActionsForExchangePartition(partTableRel, partOid, ordTableRel); } // Check if the tables are colstore @@ -34231,7 +34279,7 @@ void ExecutePurge(PurgeStmt *stmt) } case PURGE_RECYCLEBIN: { Oid userId = GetUserId(); - /* + /* * Superusers bypass all permission checking. * Database Security: Support seperation of privilege. */ @@ -34499,7 +34547,8 @@ void CheckRelAutoIncrementIndex(Oid relid, LOCKMODE lockmode) Relation idxrel = index_open(lfirst_oid(l), AccessShareLock); Form_pg_index index = idxrel->rd_index; - if (IndexIsValid(index) && + /* auto_increment column in dolphin support non-unique/primary index */ + if (IndexIsValid(index) && (u_sess->attr.attr_sql.dolphin || index->indisunique || index->indisprimary) && #ifndef DOLPHIN (index->indisunique || index->indisprimary) && #endif diff --git a/contrib/dolphin/upgrade_script/dolphin--3.0--4.0.sql b/contrib/dolphin/upgrade_script/dolphin--3.0--4.0.sql index b187ac6a2914785b7b1dfa995ee790828c73b25c..f298724a614f601a3886af75affcd1b8102733da 100644 --- a/contrib/dolphin/upgrade_script/dolphin--3.0--4.0.sql +++ b/contrib/dolphin/upgrade_script/dolphin--3.0--4.0.sql @@ -43,6 +43,30 @@ CREATE OR REPLACE FUNCTION pg_catalog.mid(varbinary, int, int) RETURNS varbinary CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, int) RETURNS varbinary LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'bit_substr_no_len'; CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, int, int) RETURNS varbinary LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'bit_substr'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(text, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(boolean, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(binary, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(varbinary, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int)::varbinary(65535)'; + +CREATE OR REPLACE FUNCTION pg_catalog.mid(text, bit, int) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(boolean, bit, int) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1::text, $2::int, $3)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(binary, bit, int) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1::bytea, $2::int, $3)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(varbinary, bit, int) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, bit, int) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3)::varbinary(65535)'; + +CREATE OR REPLACE FUNCTION pg_catalog.mid(text, int, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2, $3::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(boolean, int, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2, $3::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(binary, int, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2, $3::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(varbinary, int, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2, $3::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, int, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2, $3::int)::varbinary(65535)'; + +CREATE OR REPLACE FUNCTION pg_catalog.mid(text, bit, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(boolean, bit, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3::int)::varchar'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(binary, bit, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(varbinary, bit, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3::int)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.mid(bit, bit, bit) RETURNS varbinary LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.mid($1, $2::int, $3::int)::varbinary(65535)'; + CREATE OR REPLACE FUNCTION pg_catalog.log10(float8) RETURNS double precision LANGUAGE INTERNAL IMMUTABLE STRICT as 'dlog10'; CREATE OR REPLACE FUNCTION pg_catalog.lower(int8) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.lower(cast($1 as TEXT))::varchar'; @@ -106,6 +130,737 @@ CREATE OR REPLACE FUNCTION pg_catalog.microsecond (json) RETURNS int8 LANGUAGE S CREATE OR REPLACE FUNCTION pg_catalog.microsecond (integer) RETURNS int8 LANGUAGE SQL STABLE STRICT as 'SELECT microsecond($1::text)'; CREATE OR REPLACE FUNCTION pg_catalog.microsecond (float) RETURNS int8 LANGUAGE SQL STABLE STRICT as 'SELECT microsecond($1::text)'; +DROP FUNCTION IF EXISTS pg_catalog.left(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(text, numeric); +CREATE OR REPLACE FUNCTION pg_catalog.left(text, numeric) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'text_left_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, cast($2 as numeric))'; +DROP FUNCTION IF EXISTS pg_catalog.right(text, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(text, numeric); +CREATE OR REPLACE FUNCTION pg_catalog.right(text, numeric) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'text_right_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, cast($2 as numeric))'; + +DROP FUNCTION IF EXISTS pg_catalog.right(bit, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, year); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, text); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(bit, json); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, year); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, text); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(boolean, json); +DROP FUNCTION IF EXISTS pg_catalog.right(year, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(year, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(year, year); +DROP FUNCTION IF EXISTS pg_catalog.right(year, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(year, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(year, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(year, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(year, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(year, text); +DROP FUNCTION IF EXISTS pg_catalog.right(year, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(year, json); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(tinyblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(mediumblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(longblob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, year); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, text); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, json); +DROP FUNCTION IF EXISTS pg_catalog.right(blob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, year); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, text); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(anyenum, json); +DROP FUNCTION IF EXISTS pg_catalog.right(json, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(json, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(json, year); +DROP FUNCTION IF EXISTS pg_catalog.right(json, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(json, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(json, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(json, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(json, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(json, text); +DROP FUNCTION IF EXISTS pg_catalog.right(json, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(json, json); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, year); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, text); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(binary, json); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, year); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, text); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(varbinary, json); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, bit); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, year); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, text); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, json); +DROP FUNCTION IF EXISTS pg_catalog.right(bytea, numeric); +DROP FUNCTION IF EXISTS pg_catalog.right(text, year); +DROP FUNCTION IF EXISTS pg_catalog.right(text, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(text, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.right(text, binary); +DROP FUNCTION IF EXISTS pg_catalog.right(text, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.right(text, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, blob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, longblob); +DROP FUNCTION IF EXISTS pg_catalog.right(text, text); +DROP FUNCTION IF EXISTS pg_catalog.right(text, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.right(text, json); +CREATE OR REPLACE FUNCTION pg_catalog.right(text, year) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, timestamp with time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, timestamp without time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, binary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, varbinary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, text) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, anyenum) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(text, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, numeric) RETURNS bytea LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'bytea_right_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, bit) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, year) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, timestamp with time zone) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, timestamp without time zone) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, binary) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, varbinary) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, tinyblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, blob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, mediumblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, longblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, text) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, anyenum) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bytea, json) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(binary, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(varbinary, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(boolean, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(year, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, numeric) RETURNS blob LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'blob_right_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, bit) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, year) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, timestamp with time zone) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, timestamp without time zone) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, binary) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, varbinary) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, tinyblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, blob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, mediumblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, longblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, text) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, anyenum) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(blob, json) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(tinyblob, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, numeric) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, bit) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, year) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, timestamp with time zone) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, timestamp without time zone) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, binary) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, varbinary) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, tinyblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, blob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, mediumblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, longblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, text) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, anyenum) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(mediumblob, json) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, numeric) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, bit) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, year) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, timestamp with time zone) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, timestamp without time zone) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, binary) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, varbinary) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, tinyblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, blob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, mediumblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, longblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, text) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, anyenum) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(longblob, json) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(bit, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::blob, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(anyenum, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, numeric) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, year) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, timestamp with time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, timestamp without time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, binary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, varbinary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, text) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, anyenum) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.right(json, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.right($1::text, $2::number)'; + +DROP FUNCTION IF EXISTS pg_catalog.left(bit, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, year); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, text); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(bit, json); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, year); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, text); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(boolean, json); +DROP FUNCTION IF EXISTS pg_catalog.left(year, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(year, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(year, year); +DROP FUNCTION IF EXISTS pg_catalog.left(year, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(year, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(year, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(year, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(year, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(year, text); +DROP FUNCTION IF EXISTS pg_catalog.left(year, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(year, json); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(tinyblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(mediumblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(longblob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, year); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, text); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, json); +DROP FUNCTION IF EXISTS pg_catalog.left(blob, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, year); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, text); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(anyenum, json); +DROP FUNCTION IF EXISTS pg_catalog.left(json, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(json, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(json, year); +DROP FUNCTION IF EXISTS pg_catalog.left(json, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(json, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(json, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(json, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(json, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(json, text); +DROP FUNCTION IF EXISTS pg_catalog.left(json, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(json, json); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, year); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, text); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(binary, json); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, year); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, text); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(varbinary, json); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, bit); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, year); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, text); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, json); +DROP FUNCTION IF EXISTS pg_catalog.left(bytea, numeric); +DROP FUNCTION IF EXISTS pg_catalog.left(text, year); +DROP FUNCTION IF EXISTS pg_catalog.left(text, timestamp with time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(text, timestamp without time zone); +DROP FUNCTION IF EXISTS pg_catalog.left(text, binary); +DROP FUNCTION IF EXISTS pg_catalog.left(text, varbinary); +DROP FUNCTION IF EXISTS pg_catalog.left(text, tinyblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, blob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, mediumblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, longblob); +DROP FUNCTION IF EXISTS pg_catalog.left(text, text); +DROP FUNCTION IF EXISTS pg_catalog.left(text, anyenum); +DROP FUNCTION IF EXISTS pg_catalog.left(text, json); +CREATE OR REPLACE FUNCTION pg_catalog.left(text, year) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, timestamp with time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, timestamp without time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, binary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, varbinary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, text) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, anyenum) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(text, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, numeric) RETURNS bytea LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'bytea_left_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, bit) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, year) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, timestamp with time zone) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, timestamp without time zone) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, binary) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, varbinary) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, tinyblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, blob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, mediumblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, longblob) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, text) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, anyenum) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bytea, json) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(binary, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(varbinary, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::bytea, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(boolean, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(year, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, numeric) RETURNS blob LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'blob_left_numeric'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, bit) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, year) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, timestamp with time zone) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, timestamp without time zone) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, binary) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, varbinary) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, tinyblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, blob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, mediumblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, longblob) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, text) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, anyenum) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(blob, json) RETURNS blob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(tinyblob, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, numeric) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, bit) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, year) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, timestamp with time zone) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, timestamp without time zone) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, binary) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, varbinary) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, tinyblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, blob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, mediumblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, longblob) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, text) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, anyenum) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(mediumblob, json) RETURNS mediumblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::mediumblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, numeric) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, bit) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, year) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, timestamp with time zone) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, timestamp without time zone) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, binary) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, varbinary) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, tinyblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, blob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, mediumblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, longblob) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, text) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, anyenum) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(longblob, json) RETURNS longblob LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::longblob'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, numeric) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::varbinary(65535), $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, bit) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, year) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, timestamp with time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, timestamp without time zone) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, binary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, varbinary) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, tinyblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, blob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, mediumblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, longblob) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, text) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, anyenum) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(bit, json) RETURNS varbinary(65535) LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::blob, $2::number)::varbinary(65535)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, numeric) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, bit) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, year) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, timestamp with time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, timestamp without time zone) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, binary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, varbinary) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, tinyblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, blob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, mediumblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, longblob) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, text) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, anyenum) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(anyenum, json) RETURNS varchar LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, numeric) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, year) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, timestamp with time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, timestamp without time zone) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, binary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, varbinary) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, text) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, anyenum) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; +CREATE OR REPLACE FUNCTION pg_catalog.left(json, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.left($1::text, $2::number)'; + -- bit bool compare CREATE OR REPLACE FUNCTION pg_catalog.bool_bit_gt(boolean, bit) returns bool LANGUAGE SQL IMMUTABLE STRICT as 'select ($1::int > $2::int)'; CREATE OPERATOR pg_catalog.>(leftarg = boolean, rightarg = bit, COMMUTATOR = operator(pg_catalog.<), procedure = pg_catalog.bool_bit_gt); @@ -567,6 +1322,16 @@ CREATE OPERATOR CLASS pg_catalog.uint8_ops FUNCTION 1 pg_catalog.uint8_int8cmp(uint8, int8), FUNCTION 2 pg_catalog.uint8_sortsupport(internal); +CREATE OPERATOR CLASS pg_catalog.year_ops + DEFAULT FOR TYPE year USING ubtree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 year_cmp(year, year), + FUNCTION 2 year_sortsupport(internal); + DROP FUNCTION IF EXISTS pg_catalog.chara(variadic arr "any") cascade; CREATE OR REPLACE FUNCTION pg_catalog.chara(variadic arr "any") returns varbinary LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'm_char'; @@ -630,6 +1395,21 @@ CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (year) RETURNS integer LANGUAGE CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (binary) RETURNS integer LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_part(''week'', cast($1 as timestamp(0) without time zone))::integer'; CREATE OR REPLACE FUNCTION pg_catalog.weekofyear (text) RETURNS integer LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_part(''week'', cast($1 as timestamp(0) without time zone))::integer'; +CREATE OR REPLACE FUNCTION pg_catalog.hex(uint1) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'uint1_to_hex'; +CREATE OR REPLACE FUNCTION pg_catalog.hex(uint2) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'uint2_to_hex'; +CREATE OR REPLACE FUNCTION pg_catalog.hex(uint4) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'uint4_to_hex'; +CREATE OR REPLACE FUNCTION pg_catalog.hex(uint8) RETURNS text LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'uint8_to_hex'; + +-- binary +DROP AGGREGATE IF EXISTS pg_catalog.bit_and(binary); +DROP FUNCTION IF EXISTS pg_catalog.binary_and(binary, binary) CASCADE; +DROP FUNCTION IF EXISTS pg_catalog.binary_varbinary(binary) CASCADE; +CREATE OR REPLACE FUNCTION pg_catalog.binary_and(binary, binary) RETURNS binary LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'binaryand'; +CREATE OR REPLACE FUNCTION pg_catalog.binary_varbinary(binary) RETURNS varbinary LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'binary_varbinary'; +CREATE AGGREGATE pg_catalog.bit_and(binary) (SFUNC = pg_catalog.binary_and, STYPE = binary, FINALFUNC = binary_varbinary); +-- uint8 +drop aggregate if exists pg_catalog.bit_and(uint8); +create aggregate pg_catalog.bit_and(uint8) (SFUNC=uint8and, cFUNC = uint8and, STYPE= uint8, initcond = '18446744073709551615'); -- json max/min CREATE OR REPLACE FUNCTION pg_catalog.json_larger(json, json) RETURNS json LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin','json_larger'; CREATE OR REPLACE FUNCTION pg_catalog.json_smaller(json, json) RETURNS json LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin','json_smaller'; @@ -679,35 +1459,37 @@ CREATE OR REPLACE FUNCTION pg_catalog.date_add(timestamptz, interval) RETURNS ti CREATE OR REPLACE FUNCTION pg_catalog.date_sub(timestamp without time zone, interval) RETURNS timestamp without time zone AS $$ SELECT pg_catalog.date_add($1, -$2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.date_sub(timestamptz, interval) RETURNS timestamptz AS $$ SELECT pg_catalog.date_add($1, -$2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.date_add_interval(date, interval) RETURNS date LANGUAGE C STABLE STRICT as '$libdir/dolphin', 'date_add_date_interval'; + CREATE OR REPLACE FUNCTION pg_catalog.op_num_add_intr (numeric, interval) RETURNS text AS $$ SELECT pg_catalog.date_add($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_text_add_intr (text, interval) RETURNS text AS $$ SELECT pg_catalog.date_add($1, $2) $$ LANGUAGE SQL; -CREATE OR REPLACE FUNCTION pg_catalog.op_date_add_intr (date, interval) RETURNS text AS $$ SELECT pg_catalog.date_add($1, $2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_date_add_intr (date, interval) RETURNS date AS $$ SELECT pg_catalog.date_add_interval($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_dttm_add_intr (timestamp without time zone, interval) RETURNS timestamp without time zone AS $$ SELECT pg_catalog.date_add($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_tmsp_add_intr (timestamptz, interval) RETURNS timestamptz AS $$ SELECT pg_catalog.date_add($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_num (interval, numeric) RETURNS text AS $$ SELECT pg_catalog.date_add($2, $1) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_text (interval, text) RETURNS text AS $$ SELECT pg_catalog.date_add($2, $1) $$ LANGUAGE SQL; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_date (interval, date) RETURNS text AS $$ SELECT pg_catalog.date_add($2, $1) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_date (interval, date) RETURNS date AS $$ SELECT pg_catalog.date_add_interval($2, $1) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_dttm (interval, timestamp without time zone) RETURNS timestamp without time zone AS $$ SELECT pg_catalog.date_add($2, $1) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_tmsp (interval, timestamptz) RETURNS timestamptz AS $$ SELECT pg_catalog.date_add($2, $1) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_num_sub_intr (numeric, interval) RETURNS text AS $$ SELECT pg_catalog.date_sub($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_text_sub_intr (text, interval) RETURNS text AS $$ SELECT pg_catalog.date_sub($1, $2) $$ LANGUAGE SQL; -CREATE OR REPLACE FUNCTION pg_catalog.op_date_sub_intr (date, interval) RETURNS text AS $$ SELECT pg_catalog.date_sub($1, $2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_date_sub_intr (date, interval) RETURNS date AS $$ SELECT pg_catalog.date_add_interval($1, -$2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_dttm_sub_intr (timestamp without time zone, interval) RETURNS timestamp without time zone AS $$ SELECT pg_catalog.date_sub($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_tmsp_sub_intr (timestamptz, interval) RETURNS timestamptz AS $$ SELECT pg_catalog.date_sub($1, $2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.op_json_add_intr (json, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($1 as text), $2)'; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_json (interval, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add($1, cast($2 as text))'; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_json (interval, json) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($2 as text), $1)'; CREATE OR REPLACE FUNCTION pg_catalog.op_json_sub_intr (json, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_sub(cast($1 as text), $2)'; CREATE OR REPLACE FUNCTION pg_catalog.op_blob_add_intr (blob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($1 as text), $2)'; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_blob (interval, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add($1, cast($2 as text))'; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_blob (interval, blob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($2 as text), $1)'; CREATE OR REPLACE FUNCTION pg_catalog.op_blob_sub_intr (blob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_sub(cast($1 as text), $2)'; CREATE OR REPLACE FUNCTION pg_catalog.op_lblob_add_intr (longblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($1 as text), $2)'; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_lblob (interval, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add($1, cast($2 as text))'; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_lblob (interval, longblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($2 as text), $1)'; CREATE OR REPLACE FUNCTION pg_catalog.op_lblob_sub_intr (longblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_sub(cast($1 as text), $2)'; CREATE OR REPLACE FUNCTION pg_catalog.op_mblob_add_intr (mediumblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($1 as text), $2)'; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_mblob (interval, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add($1, cast($2 as text))'; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_mblob (interval, mediumblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($2 as text), $1)'; CREATE OR REPLACE FUNCTION pg_catalog.op_mblob_sub_intr (mediumblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_sub(cast($1 as text), $2)'; CREATE OR REPLACE FUNCTION pg_catalog.op_tblob_add_intr (tinyblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($1 as text), $2)'; -CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_tblob (interval, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add($1, cast($2 as text))'; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_tblob (interval, tinyblob) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_add(cast($2 as text), $1)'; CREATE OR REPLACE FUNCTION pg_catalog.op_tblob_sub_intr (tinyblob, interval) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_sub(cast($1 as text), $2)'; CREATE OPERATOR pg_catalog.+ (leftarg = numeric, rightarg = interval, procedure = op_num_add_intr, commutator = operator(pg_catalog.+)); @@ -734,7 +1516,7 @@ CREATE OPERATOR pg_catalog.- (leftarg = tinyblob, rightarg = interval, procedure DO $$ BEGIN - update pg_catalog.pg_operator set oprresult = 'text'::regtype, oprcode = 'op_date_add_intr'::regproc + update pg_catalog.pg_operator set oprresult = 'date'::regtype, oprcode = 'op_date_add_intr'::regproc where oprname = '+' and oprleft = 'date'::regtype and oprright = 'interval'::regtype; update pg_catalog.pg_operator set oprresult = 'timestamp without time zone'::regtype, oprcode = 'op_dttm_add_intr'::regproc where oprname = '+' and oprleft = 'timestamp without time zone'::regtype and oprright = 'interval'::regtype; @@ -743,7 +1525,7 @@ BEGIN update pg_catalog.pg_operator set oprresult = 'text'::regtype, oprcode = 'op_time_add_intr'::regproc where oprname = '+' and oprleft = 'time'::regtype and oprright = 'interval'::regtype; - update pg_catalog.pg_operator set oprresult = 'text'::regtype, oprcode = 'op_intr_add_date'::regproc + update pg_catalog.pg_operator set oprresult = 'date'::regtype, oprcode = 'op_intr_add_date'::regproc where oprname = '+' and oprleft = 'interval'::regtype and oprright = 'date'::regtype; update pg_catalog.pg_operator set oprresult = 'timestamp without time zone'::regtype, oprcode = 'op_intr_add_dttm'::regproc where oprname = '+' and oprleft = 'interval'::regtype and oprright = 'timestamp without time zone'::regtype; @@ -752,7 +1534,7 @@ BEGIN update pg_catalog.pg_operator set oprresult = 'text'::regtype, oprcode = 'op_intr_add_time'::regproc where oprname = '+' and oprleft = 'interval'::regtype and oprright = 'time'::regtype; - update pg_catalog.pg_operator set oprresult = 'text'::regtype, oprcode = 'op_date_sub_intr'::regproc + update pg_catalog.pg_operator set oprresult = 'date'::regtype, oprcode = 'op_date_sub_intr'::regproc where oprname = '-' and oprleft = 'date'::regtype and oprright = 'interval'::regtype; update pg_catalog.pg_operator set oprresult = 'timestamp without time zone'::regtype, oprcode = 'op_dttm_sub_intr'::regproc where oprname = '-' and oprleft = 'timestamp without time zone'::regtype and oprright = 'interval'::regtype; @@ -778,6 +1560,20 @@ CREATE OR REPLACE FUNCTION pg_catalog.date_sub(numeric, interval, boolean) RETUR CREATE OR REPLACE FUNCTION pg_catalog.date_sub(year, interval, boolean) RETURNS text AS $$ SELECT pg_catalog.date_add($1, -$2) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pg_catalog.date_sub(date, interval, boolean) RETURNS text AS $$ SELECT pg_catalog.date_add($1, -$2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_enum_add_intr (anyenum, interval) RETURNS text AS $$ SELECT pg_catalog.op_text_add_intr($1::text, $2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_enum (interval, anyenum) RETURNS text AS $$ SELECT pg_catalog.op_intr_add_text($1, $2::text) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_enum_sub_intr (anyenum, interval) RETURNS text AS $$ SELECT pg_catalog.op_text_sub_intr($1::text, $2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_set_add_intr (anyset, interval) RETURNS text AS $$ SELECT pg_catalog.op_text_add_intr($1::text, $2) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_intr_add_set (interval, anyset) RETURNS text AS $$ SELECT pg_catalog.op_intr_add_text($1, $2::text) $$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION pg_catalog.op_set_sub_intr (anyset, interval) RETURNS text AS $$ SELECT pg_catalog.op_text_sub_intr($1::text, $2) $$ LANGUAGE SQL; + +CREATE OPERATOR pg_catalog.+ (leftarg = anyenum, rightarg = interval, procedure = op_enum_add_intr, commutator = operator(pg_catalog.+)); +CREATE OPERATOR pg_catalog.+ (leftarg = interval, rightarg = anyenum, procedure = op_intr_add_enum, commutator = operator(pg_catalog.+)); +CREATE OPERATOR pg_catalog.- (leftarg = anyenum, rightarg = interval, procedure = op_enum_sub_intr, commutator = operator(pg_catalog.-)); +CREATE OPERATOR pg_catalog.+ (leftarg = anyset, rightarg = interval, procedure = op_set_add_intr, commutator = operator(pg_catalog.+)); +CREATE OPERATOR pg_catalog.+ (leftarg = interval, rightarg = anyset, procedure = op_intr_add_set, commutator = operator(pg_catalog.+)); +CREATE OPERATOR pg_catalog.- (leftarg = anyset, rightarg = interval, procedure = op_set_sub_intr, commutator = operator(pg_catalog.-)); + create or replace function pg_catalog.any2interval(anyelement, integer) returns interval LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin','any2interval'; create or replace function pg_catalog.any2interval(anyelement, integer, integer) returns interval LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin','any2interval'; @@ -1179,12 +1975,79 @@ CREATE OR REPLACE FUNCTION pg_catalog.round(timestamp without time zone) RETURNS CREATE OR REPLACE FUNCTION pg_catalog.round(anyenum) RETURNS double precision LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.round(cast($1 as double precision))::double precision'; CREATE OR REPLACE FUNCTION pg_catalog.round(anyset) RETURNS double precision LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.round(cast($1 as double precision))::double precision'; -CREATE OR REPLACE FUNCTION pg_catalog.substring(bit, bit) RETURNS bit LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; -CREATE OR REPLACE FUNCTION pg_catalog.substring(bytea, bit) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; -CREATE OR REPLACE FUNCTION pg_catalog.substring(text, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; +CREATE OR REPLACE FUNCTION pg_catalog.substr(bit, bit) RETURNS bit LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; +CREATE OR REPLACE FUNCTION pg_catalog.substr(bytea, bit) RETURNS bytea LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; +CREATE OR REPLACE FUNCTION pg_catalog.substr(text, bit) RETURNS text LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2::integer)'; +CREATE OR REPLACE FUNCTION pg_catalog.substr(bit, int, int) RETURNS bit LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2, $3)'; +CREATE OR REPLACE FUNCTION pg_catalog.substr(bit, int) RETURNS bit LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.substring($1, $2)'; drop cast if exists ("binary" as varchar); drop cast if exists ("binary" as char); CREATE CAST ("binary" AS varchar) WITH FUNCTION pg_catalog.Varlena2Varchar(anyelement) AS IMPLICIT; CREATE CAST ("binary" AS char) WITH FUNCTION pg_catalog.Varlena2Bpchar(anyelement) AS IMPLICIT; +-- fix merge join +CREATE OR REPLACE FUNCTION pg_catalog.int8_cmp_uint1(int8, uint1) + RETURNS int4 LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int8_cmp_uint1'; +CREATE OR REPLACE FUNCTION pg_catalog.int8_cmp_uint2(int8, uint2) + RETURNS int4 LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int8_cmp_uint2'; +CREATE OR REPLACE FUNCTION pg_catalog.int8_cmp_uint4(int8, uint4) + RETURNS int4 LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int8_cmp_uint4'; +CREATE OR REPLACE FUNCTION pg_catalog.int8_cmp_uint8(int8, uint8) + RETURNS int4 LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int8_cmp_uint8'; + +CREATE OR REPLACE FUNCTION pg_catalog.int2_eq_uint1(int2, uint1) + RETURNS bool LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int2_eq_uint1'; + +CREATE OR REPLACE FUNCTION pg_catalog.int4_eq_uint1(int4, uint1) + RETURNS bool LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int4_eq_uint1'; + +CREATE OR REPLACE FUNCTION pg_catalog.int8_eq_uint1(int8, uint1) + RETURNS bool LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'int8_eq_uint1'; + +CREATE OPERATOR pg_catalog.=( + leftarg = int2, rightarg = uint1, + procedure = pg_catalog.int2_eq_uint1, commutator = operator(pg_catalog.=), + restrict = eqsel, join = eqjoinsel, HASHES, MERGES +); + +CREATE OPERATOR pg_catalog.=( + leftarg = int4, rightarg = uint1, + procedure = pg_catalog.int4_eq_uint1, commutator = operator(pg_catalog.=), + restrict = eqsel, join = eqjoinsel, HASHES, MERGES +); + +CREATE OPERATOR pg_catalog.=( + leftarg = int8, rightarg = uint1, + procedure = pg_catalog.int8_eq_uint1, commutator = operator(pg_catalog.=), + restrict = eqsel, join = eqjoinsel, HASHES, MERGES +); + +CREATE OPERATOR CLASS pg_catalog.int8_uint_bt_ops + FOR TYPE int8 USING btree FAMILY pg_catalog.integer_ops AS + OPERATOR 3 =(int8, uint1), + OPERATOR 3 =(int8, uint2), + OPERATOR 3 =(int8, uint4), + OPERATOR 3 =(int8, uint8), + + FUNCTION 1 pg_catalog.int8_cmp_uint1(int8,uint1), + FUNCTION 1 pg_catalog.int8_cmp_uint2(int8,uint2), + FUNCTION 1 pg_catalog.int8_cmp_uint4(int8,uint4), + FUNCTION 1 pg_catalog.int8_cmp_uint8(int8,uint8); + +CREATE OPERATOR CLASS pg_catalog.int8_uint_hash_ops + FOR TYPE int8 USING hash family pg_catalog.integer_ops AS + OPERATOR 1 =(int8, uint1), + FUNCTION 1 (int8, uint1) hashint8(int8); + +DROP FUNCTION IF EXISTS pg_catalog.db_b_format("any", int4) cascade; +DROP FUNCTION IF EXISTS pg_catalog.db_b_format("any", int4, "any") cascade; +CREATE OR REPLACE FUNCTION pg_catalog.db_b_format("any", int8) RETURNS text LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'db_b_format'; +CREATE OR REPLACE FUNCTION pg_catalog.db_b_format("any", int8, "any") RETURNS text LANGUAGE C IMMUTABLE as '$libdir/dolphin', 'db_b_format_locale'; + +CREATE OR REPLACE FUNCTION pg_catalog.varchar_json(varchar) RETURNS json LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'varchar_json'; +CREATE CAST (varchar as json) WITH FUNCTION pg_catalog.varchar_json(varchar) AS ASSIGNMENT; + +CREATE OR REPLACE FUNCTION pg_catalog.varchar_json(text) RETURNS json LANGUAGE C IMMUTABLE STRICT as '$libdir/dolphin', 'text_json'; +CREATE CAST (text as json) WITH FUNCTION pg_catalog.varchar_json(text) AS ASSIGNMENT; + diff --git a/contrib/orafce/parse_keyword.c b/contrib/orafce/parse_keyword.c index e359637017913be9f219279f4f8e3c8c28ca9612..345eca4d6fc15379dca8b0f84a65ef34d9205746 100644 --- a/contrib/orafce/parse_keyword.c +++ b/contrib/orafce/parse_keyword.c @@ -1,19 +1,9 @@ #include "postgres.h" +#include "parser/scanner.h" +#include "parser/kwlookup.h" #include "parse_keyword.h" -#if PG_VERSION_NUM >= 90600 - -#include "common/keywords.h" - -#else - -#include "parser/keywords.h" - -#endif - -#if PG_VERSION_NUM >= 120000 - const char * orafce_scan_keyword(const char *text, int *keycode) { @@ -28,22 +18,3 @@ orafce_scan_keyword(const char *text, int *keycode) return NULL; } - -#else - -const char * -orafce_scan_keyword(const char *text, int *keycode) -{ - const ScanKeyword *keyword; - - keyword = ScanKeywordLookup(text, ScanKeywords, NumScanKeywords); - if (keyword) - { - *keycode = keyword->value; - return keyword->name; - } - - return NULL; -} - -#endif diff --git a/contrib/orafce/varchar2.c b/contrib/orafce/varchar2.c index 306c50bac6841660179ea204a0704fb0850a2c31..3d5f00b63d2c2c8341114c75986e185559a81719 100644 --- a/contrib/orafce/varchar2.c +++ b/contrib/orafce/varchar2.c @@ -132,15 +132,7 @@ varchar2recv(PG_FUNCTION_ARGS) Datum orafce_varchar_transform(PG_FUNCTION_ARGS) { -#if PG_VERSION_NUM < 120000 - - return varchar_transform(fcinfo); - -#else - - return varchar_support(fcinfo); - -#endif + return varchar_support(fcinfo); } diff --git a/contrib/spq_plugin/src/guc_spq.cpp b/contrib/spq_plugin/src/guc_spq.cpp index 4f88f428288cde50e8eb8674453f7a718e1aa241..e4bd726fb7daf7e0a7086d871a388b28568c5b59 100644 --- a/contrib/spq_plugin/src/guc_spq.cpp +++ b/contrib/spq_plugin/src/guc_spq.cpp @@ -1684,7 +1684,7 @@ static bool spq_verify_gauss_cluster_map_syntax(const char *liststring) MemoryContextSwitchTo(oldContext); return false; } - if (!SplitIdentifierString(rawname, ',', &nodelist)) { + if (!SplitIdentifierString(rawname, ',', &nodelist, false)) { pfree(rawname); /* syntax error in name list */ GUC_check_errdetail("spq cluster map is invalid, name|ip|port,..."); @@ -1699,7 +1699,7 @@ static bool spq_verify_gauss_cluster_map_syntax(const char *liststring) List *itemlist; char *name, *ip, *port; char *nodestring = pstrdup((char *)lfirst(lnode)); - (void)SplitIdentifierString(nodestring, '|', &itemlist); + (void)SplitIdentifierString(nodestring, '|', &itemlist, false); if (list_length(itemlist) != 3) { GUC_check_errdetail("spq cluster map is invalid, name|ip|port,..."); pfree(rawname); diff --git a/contrib/timescaledb/CMakeLists.txt b/contrib/timescaledb/CMakeLists.txt index 2019bb95b1c7cf6380b86a9cb0d2f86555be5b02..7e3cb34aabd395affd9d305c85d5af24b5883620 100644 --- a/contrib/timescaledb/CMakeLists.txt +++ b/contrib/timescaledb/CMakeLists.txt @@ -48,7 +48,7 @@ else () endif () # Set project name, version, and language. Language needs to be set for compiler checks -project(timescaledb VERSION ${VERSION} LANGUAGES C CXX) +project(timescaledb VERSION ${VERSION} LANGUAGES CXX) if (NOT CMAKE_BUILD_TYPE) # Default to Release builds @@ -64,6 +64,10 @@ message(STATUS "Install method is '${PROJECT_INSTALL_METHOD}'") option(TS_COVERAGE_ONLY "run in debug mode with assertions disabled to provide more accurate test-coverage info") +# add security compilation options +add_compile_options(-fstack-protector-strong) +add_link_options(-Wl,-z,relro,-z,now) + if (CMAKE_BUILD_TYPE MATCHES Debug) # CMAKE_BUILD_TYPE is set at CMake configuration type. But usage of CMAKE_C_FLAGS_DEBUG is # determined at build time by running cmake --build . --config Debug (at least on Windows). @@ -78,54 +82,6 @@ endif (CMAKE_BUILD_TYPE MATCHES Debug) set(SUPPORTED_COMPILERS "GNU" "Clang" "AppleClang" "MSVC") -# Check for a supported compiler -if (NOT CMAKE_C_COMPILER_ID IN_LIST SUPPORTED_COMPILERS) - message(FATAL_ERROR "Unsupported compiler ${CMAKE_C_COMPILER_ID}. Supported compilers are: ${SUPPORTED_COMPILERS}") -endif () - -if(CMAKE_C_COMPILER_ID MATCHES "GNU|AppleClang|Clang") - # These two flags generate too many errors currently, but we - # probably want these optimizations enabled. - - # TODO: -fdelete-null-pointer-checks -Wnull-dereference - - # This flag avoid some subtle bugs related to standard conversions, - # but currently does not compile because we are using too many - # implicit conversions that potentially lose precision. - - # TODO: -Wconversions - add_compile_options(-Wempty-body -Wvla) - if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "7") - add_compile_options(-Wimplicit-fallthrough) - endif() - - # Not sure when it was added to Clang, but it is mentioned in the - # release notes for Clang 3.3 - if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "3.3") - add_compile_options(-Wimplicit-fallthrough) - endif() - -endif() - -# Check for supported platforms and compiler flags -if (WIN32) - if (NOT CMAKE_CONFIGURATION_TYPES) - # Default to only include Release builds so MSBuild.exe 'just works' - set(CMAKE_CONFIGURATION_TYPES Release CACHE STRING "Semicolon separated list of supported configuration types, only supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything else will be ignored." FORCE) - endif () -elseif (UNIX) - # On UNIX, the compiler needs to support -fvisibility=hidden to hide symbols by default - check_c_compiler_flag(-fvisibility=hidden CC_SUPPORTS_VISIBILITY_HIDDEN) - - if (NOT CC_SUPPORTS_VISIBILITY_HIDDEN) - message(FATAL_ERROR "The compiler ${CMAKE_C_COMPILER_ID} does not support -fvisibility=hidden") - endif (NOT CC_SUPPORTS_VISIBILITY_HIDDEN) -else () - message(FATAL_ERROR "Unsupported platform") -endif () - -message(STATUS "Using compiler ${CMAKE_C_COMPILER_ID}") - if (ENABLE_CODECOVERAGE) message(STATUS "Running code coverage") diff --git a/contrib/timescaledb/bootstrap b/contrib/timescaledb/bootstrap index 6518f17484d30cdfbec3563b68623772842dace8..c42cf4564acb96b04a9e8da731b41e99ab13f4a7 100644 --- a/contrib/timescaledb/bootstrap +++ b/contrib/timescaledb/bootstrap @@ -10,7 +10,26 @@ if ! command -v cmake >/dev/null 2>&1; then exit 1 fi -BUILD_DIR=${BUILD_DIR:-./build} +default_build_dir="./build" +BUILD_DIR="$default_build_dir" + +other_args=() + +# parse --prefix +for arg in "$@"; do + case $arg in + --prefix=*) + prefix="${arg#*=}" + prefix=$(echo "$prefix" | sed 's:/*$::') + BUILD_DIR="${prefix}/build" + ;; + *) + # CMAKE params + other_args+=("$arg") + ;; + esac +done + BUILD_FORCE_REMOVE=${BUILD_FORCE_REMOVE:-false} SRC_DIR=$(dirname $0) if [[ ! ${SRC_DIR} == /* ]]; then @@ -24,7 +43,7 @@ set -u mkdir -p ${BUILD_DIR} && \ cd ${BUILD_DIR} && \ - cmake ${SRC_DIR} "$@" + cmake ${SRC_DIR} "${other_args[@]}" echo "TimescaleDB build system initialized in ${BUILD_DIR}. To compile, do:" echo -e "\033[1mcd ${BUILD_DIR} && make\033[0m" diff --git a/contrib/timescaledb/run_to_build.sh b/contrib/timescaledb/run_to_build.sh index 051f2dad16774973924efcc78e04f45eae098376..d354d87491c318f1b5205284552d850409581cb4 100644 --- a/contrib/timescaledb/run_to_build.sh +++ b/contrib/timescaledb/run_to_build.sh @@ -1 +1 @@ -./bootstrap -DUSE_OPENSSL=0 -DREGRESS_CHECKS=OFF -DENABLE_BBOX=ON -DENABLE_MOT=ON \ No newline at end of file +./contrib/timescaledb/bootstrap -DUSE_OPENSSL=0 -DREGRESS_CHECKS=OFF -DENABLE_BBOX=ON -DENABLE_MOT=ON --prefix=contrib/timescaledb \ No newline at end of file