aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarsaly <marsaly@yandex-team.com>2023-01-18 12:28:36 +0300
committermarsaly <marsaly@yandex-team.com>2023-01-18 12:28:36 +0300
commitf23d6eff014dc53e1bc818d359d9afd11ba919c0 (patch)
tree26523db46897762055878f8f129efbfc5c3214b9
parentb1b9ed7fe8ec050a481ad42bed290404595b8089 (diff)
downloadydb-f23d6eff014dc53e1bc818d359d9afd11ba919c0.tar.gz
Поддержка сравнения массивов ПГ
-rw-r--r--contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat308
-rw-r--r--ydb/library/yql/parser/pg_catalog/CMakeLists.darwin.txt8
-rw-r--r--ydb/library/yql/parser/pg_catalog/CMakeLists.linux-aarch64.txt8
-rw-r--r--ydb/library/yql/parser/pg_catalog/CMakeLists.linux.txt8
-rw-r--r--ydb/library/yql/parser/pg_catalog/catalog.cpp330
-rw-r--r--ydb/library/yql/parser/pg_catalog/catalog.h64
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/CMakeLists.darwin.txt3
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux-aarch64.txt3
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux.txt3
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp33
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp15
-rw-r--r--ydb/library/yql/parser/pg_wrapper/CMakeLists.darwin.txt1
-rw-r--r--ydb/library/yql/parser/pg_wrapper/CMakeLists.linux-aarch64.txt1
-rw-r--r--ydb/library/yql/parser/pg_wrapper/CMakeLists.linux.txt1
-rw-r--r--ydb/library/yql/parser/pg_wrapper/parser.cpp3
-rw-r--r--ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/lsyscache.c24
-rw-r--r--ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/typcache.c20
-rw-r--r--ydb/library/yql/parser/pg_wrapper/type_cache.cpp506
-rw-r--r--ydb/library/yql/parser/pg_wrapper/type_cache.h24
-rw-r--r--ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.darwin.txt2
-rw-r--r--ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux-aarch64.txt2
-rw-r--r--ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux.txt2
-rw-r--r--ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp198
23 files changed, 1461 insertions, 106 deletions
diff --git a/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat b/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat
new file mode 100644
index 0000000000..8e480efd28
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat
@@ -0,0 +1,308 @@
+#----------------------------------------------------------------------
+#
+# pg_opfamily.dat
+# Initial contents of the pg_opfamily system catalog.
+#
+# Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_opfamily.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '397',
+ opfmethod => 'btree', opfname => 'array_ops' },
+{ oid => '627',
+ opfmethod => 'hash', opfname => 'array_ops' },
+{ oid => '423',
+ opfmethod => 'btree', opfname => 'bit_ops' },
+{ oid => '424', oid_symbol => 'BOOL_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bool_ops' },
+{ oid => '426', oid_symbol => 'BPCHAR_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bpchar_ops' },
+{ oid => '427',
+ opfmethod => 'hash', opfname => 'bpchar_ops' },
+{ oid => '428', oid_symbol => 'BYTEA_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bytea_ops' },
+{ oid => '429',
+ opfmethod => 'btree', opfname => 'char_ops' },
+{ oid => '431',
+ opfmethod => 'hash', opfname => 'char_ops' },
+{ oid => '434',
+ opfmethod => 'btree', opfname => 'datetime_ops' },
+{ oid => '435',
+ opfmethod => 'hash', opfname => 'date_ops' },
+{ oid => '1970',
+ opfmethod => 'btree', opfname => 'float_ops' },
+{ oid => '1971',
+ opfmethod => 'hash', opfname => 'float_ops' },
+{ oid => '1974', oid_symbol => 'NETWORK_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'network_ops' },
+{ oid => '1975',
+ opfmethod => 'hash', opfname => 'network_ops' },
+{ oid => '3550',
+ opfmethod => 'gist', opfname => 'network_ops' },
+{ oid => '3794',
+ opfmethod => 'spgist', opfname => 'network_ops' },
+{ oid => '1976', oid_symbol => 'INTEGER_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'integer_ops' },
+{ oid => '1977',
+ opfmethod => 'hash', opfname => 'integer_ops' },
+{ oid => '1982',
+ opfmethod => 'btree', opfname => 'interval_ops' },
+{ oid => '1983',
+ opfmethod => 'hash', opfname => 'interval_ops' },
+{ oid => '1984',
+ opfmethod => 'btree', opfname => 'macaddr_ops' },
+{ oid => '1985',
+ opfmethod => 'hash', opfname => 'macaddr_ops' },
+{ oid => '3371',
+ opfmethod => 'btree', opfname => 'macaddr8_ops' },
+{ oid => '3372',
+ opfmethod => 'hash', opfname => 'macaddr8_ops' },
+{ oid => '1988',
+ opfmethod => 'btree', opfname => 'numeric_ops' },
+{ oid => '1998',
+ opfmethod => 'hash', opfname => 'numeric_ops' },
+{ oid => '1989', oid_symbol => 'OID_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'oid_ops' },
+{ oid => '1990',
+ opfmethod => 'hash', opfname => 'oid_ops' },
+{ oid => '1991',
+ opfmethod => 'btree', opfname => 'oidvector_ops' },
+{ oid => '1992',
+ opfmethod => 'hash', opfname => 'oidvector_ops' },
+{ oid => '2994',
+ opfmethod => 'btree', opfname => 'record_ops' },
+{ oid => '6194',
+ opfmethod => 'hash', opfname => 'record_ops' },
+{ oid => '3194',
+ opfmethod => 'btree', opfname => 'record_image_ops' },
+{ oid => '1994', oid_symbol => 'TEXT_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'text_ops' },
+{ oid => '1995',
+ opfmethod => 'hash', opfname => 'text_ops' },
+{ oid => '1996',
+ opfmethod => 'btree', opfname => 'time_ops' },
+{ oid => '1997',
+ opfmethod => 'hash', opfname => 'time_ops' },
+{ oid => '1999',
+ opfmethod => 'hash', opfname => 'timestamptz_ops' },
+{ oid => '2000',
+ opfmethod => 'btree', opfname => 'timetz_ops' },
+{ oid => '2001',
+ opfmethod => 'hash', opfname => 'timetz_ops' },
+{ oid => '2002',
+ opfmethod => 'btree', opfname => 'varbit_ops' },
+{ oid => '2040',
+ opfmethod => 'hash', opfname => 'timestamp_ops' },
+{ oid => '2095', oid_symbol => 'TEXT_PATTERN_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'text_pattern_ops' },
+{ oid => '2097', oid_symbol => 'BPCHAR_PATTERN_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bpchar_pattern_ops' },
+{ oid => '2099',
+ opfmethod => 'btree', opfname => 'money_ops' },
+{ oid => '2222', oid_symbol => 'BOOL_HASH_FAM_OID',
+ opfmethod => 'hash', opfname => 'bool_ops' },
+{ oid => '2223',
+ opfmethod => 'hash', opfname => 'bytea_ops' },
+{ oid => '2789',
+ opfmethod => 'btree', opfname => 'tid_ops' },
+{ oid => '2225',
+ opfmethod => 'hash', opfname => 'xid_ops' },
+{ oid => '5032',
+ opfmethod => 'hash', opfname => 'xid8_ops' },
+{ oid => '5067',
+ opfmethod => 'btree', opfname => 'xid8_ops' },
+{ oid => '2226',
+ opfmethod => 'hash', opfname => 'cid_ops' },
+{ oid => '2227',
+ opfmethod => 'hash', opfname => 'tid_ops' },
+{ oid => '2229',
+ opfmethod => 'hash', opfname => 'text_pattern_ops' },
+{ oid => '2231',
+ opfmethod => 'hash', opfname => 'bpchar_pattern_ops' },
+{ oid => '2235',
+ opfmethod => 'hash', opfname => 'aclitem_ops' },
+{ oid => '2593',
+ opfmethod => 'gist', opfname => 'box_ops' },
+{ oid => '2594',
+ opfmethod => 'gist', opfname => 'poly_ops' },
+{ oid => '2595',
+ opfmethod => 'gist', opfname => 'circle_ops' },
+{ oid => '1029',
+ opfmethod => 'gist', opfname => 'point_ops' },
+{ oid => '2745',
+ opfmethod => 'gin', opfname => 'array_ops' },
+{ oid => '2968',
+ opfmethod => 'btree', opfname => 'uuid_ops' },
+{ oid => '2969',
+ opfmethod => 'hash', opfname => 'uuid_ops' },
+{ oid => '3253',
+ opfmethod => 'btree', opfname => 'pg_lsn_ops' },
+{ oid => '3254',
+ opfmethod => 'hash', opfname => 'pg_lsn_ops' },
+{ oid => '3522',
+ opfmethod => 'btree', opfname => 'enum_ops' },
+{ oid => '3523',
+ opfmethod => 'hash', opfname => 'enum_ops' },
+{ oid => '3626',
+ opfmethod => 'btree', opfname => 'tsvector_ops' },
+{ oid => '3655',
+ opfmethod => 'gist', opfname => 'tsvector_ops' },
+{ oid => '3659',
+ opfmethod => 'gin', opfname => 'tsvector_ops' },
+{ oid => '3683',
+ opfmethod => 'btree', opfname => 'tsquery_ops' },
+{ oid => '3702',
+ opfmethod => 'gist', opfname => 'tsquery_ops' },
+{ oid => '3901',
+ opfmethod => 'btree', opfname => 'range_ops' },
+{ oid => '3903',
+ opfmethod => 'hash', opfname => 'range_ops' },
+{ oid => '3919',
+ opfmethod => 'gist', opfname => 'range_ops' },
+{ oid => '3474',
+ opfmethod => 'spgist', opfname => 'range_ops' },
+{ oid => '4015',
+ opfmethod => 'spgist', opfname => 'quad_point_ops' },
+{ oid => '4016',
+ opfmethod => 'spgist', opfname => 'kd_point_ops' },
+{ oid => '4017', oid_symbol => 'TEXT_SPGIST_FAM_OID',
+ opfmethod => 'spgist', opfname => 'text_ops' },
+{ oid => '4033',
+ opfmethod => 'btree', opfname => 'jsonb_ops' },
+{ oid => '4034',
+ opfmethod => 'hash', opfname => 'jsonb_ops' },
+{ oid => '4036',
+ opfmethod => 'gin', opfname => 'jsonb_ops' },
+{ oid => '4037',
+ opfmethod => 'gin', opfname => 'jsonb_path_ops' },
+{ oid => '4054',
+ opfmethod => 'brin', opfname => 'integer_minmax_ops' },
+{ oid => '4602',
+ opfmethod => 'brin', opfname => 'integer_minmax_multi_ops' },
+{ oid => '4572',
+ opfmethod => 'brin', opfname => 'integer_bloom_ops' },
+{ oid => '4055',
+ opfmethod => 'brin', opfname => 'numeric_minmax_ops' },
+{ oid => '4603',
+ opfmethod => 'brin', opfname => 'numeric_minmax_multi_ops' },
+{ oid => '4056',
+ opfmethod => 'brin', opfname => 'text_minmax_ops' },
+{ oid => '4573',
+ opfmethod => 'brin', opfname => 'text_bloom_ops' },
+{ oid => '4574',
+ opfmethod => 'brin', opfname => 'numeric_bloom_ops' },
+{ oid => '4058',
+ opfmethod => 'brin', opfname => 'timetz_minmax_ops' },
+{ oid => '4604',
+ opfmethod => 'brin', opfname => 'timetz_minmax_multi_ops' },
+{ oid => '4575',
+ opfmethod => 'brin', opfname => 'timetz_bloom_ops' },
+{ oid => '4059',
+ opfmethod => 'brin', opfname => 'datetime_minmax_ops' },
+{ oid => '4605',
+ opfmethod => 'brin', opfname => 'datetime_minmax_multi_ops' },
+{ oid => '4576',
+ opfmethod => 'brin', opfname => 'datetime_bloom_ops' },
+{ oid => '4062',
+ opfmethod => 'brin', opfname => 'char_minmax_ops' },
+{ oid => '4577',
+ opfmethod => 'brin', opfname => 'char_bloom_ops' },
+{ oid => '4064',
+ opfmethod => 'brin', opfname => 'bytea_minmax_ops' },
+{ oid => '4578',
+ opfmethod => 'brin', opfname => 'bytea_bloom_ops' },
+{ oid => '4065',
+ opfmethod => 'brin', opfname => 'name_minmax_ops' },
+{ oid => '4579',
+ opfmethod => 'brin', opfname => 'name_bloom_ops' },
+{ oid => '4068',
+ opfmethod => 'brin', opfname => 'oid_minmax_ops' },
+{ oid => '4606',
+ opfmethod => 'brin', opfname => 'oid_minmax_multi_ops' },
+{ oid => '4580',
+ opfmethod => 'brin', opfname => 'oid_bloom_ops' },
+{ oid => '4069',
+ opfmethod => 'brin', opfname => 'tid_minmax_ops' },
+{ oid => '4581',
+ opfmethod => 'brin', opfname => 'tid_bloom_ops' },
+{ oid => '4607',
+ opfmethod => 'brin', opfname => 'tid_minmax_multi_ops' },
+{ oid => '4070',
+ opfmethod => 'brin', opfname => 'float_minmax_ops' },
+{ oid => '4608',
+ opfmethod => 'brin', opfname => 'float_minmax_multi_ops' },
+{ oid => '4582',
+ opfmethod => 'brin', opfname => 'float_bloom_ops' },
+{ oid => '4074',
+ opfmethod => 'brin', opfname => 'macaddr_minmax_ops' },
+{ oid => '4609',
+ opfmethod => 'brin', opfname => 'macaddr_minmax_multi_ops' },
+{ oid => '4583',
+ opfmethod => 'brin', opfname => 'macaddr_bloom_ops' },
+{ oid => '4109',
+ opfmethod => 'brin', opfname => 'macaddr8_minmax_ops' },
+{ oid => '4610',
+ opfmethod => 'brin', opfname => 'macaddr8_minmax_multi_ops' },
+{ oid => '4584',
+ opfmethod => 'brin', opfname => 'macaddr8_bloom_ops' },
+{ oid => '4075',
+ opfmethod => 'brin', opfname => 'network_minmax_ops' },
+{ oid => '4611',
+ opfmethod => 'brin', opfname => 'network_minmax_multi_ops' },
+{ oid => '4102',
+ opfmethod => 'brin', opfname => 'network_inclusion_ops' },
+{ oid => '4585',
+ opfmethod => 'brin', opfname => 'network_bloom_ops' },
+{ oid => '4076',
+ opfmethod => 'brin', opfname => 'bpchar_minmax_ops' },
+{ oid => '4586',
+ opfmethod => 'brin', opfname => 'bpchar_bloom_ops' },
+{ oid => '4077',
+ opfmethod => 'brin', opfname => 'time_minmax_ops' },
+{ oid => '4612',
+ opfmethod => 'brin', opfname => 'time_minmax_multi_ops' },
+{ oid => '4587',
+ opfmethod => 'brin', opfname => 'time_bloom_ops' },
+{ oid => '4078',
+ opfmethod => 'brin', opfname => 'interval_minmax_ops' },
+{ oid => '4613',
+ opfmethod => 'brin', opfname => 'interval_minmax_multi_ops' },
+{ oid => '4588',
+ opfmethod => 'brin', opfname => 'interval_bloom_ops' },
+{ oid => '4079',
+ opfmethod => 'brin', opfname => 'bit_minmax_ops' },
+{ oid => '4080',
+ opfmethod => 'brin', opfname => 'varbit_minmax_ops' },
+{ oid => '4081',
+ opfmethod => 'brin', opfname => 'uuid_minmax_ops' },
+{ oid => '4614',
+ opfmethod => 'brin', opfname => 'uuid_minmax_multi_ops' },
+{ oid => '4589',
+ opfmethod => 'brin', opfname => 'uuid_bloom_ops' },
+{ oid => '4103',
+ opfmethod => 'brin', opfname => 'range_inclusion_ops' },
+{ oid => '4082',
+ opfmethod => 'brin', opfname => 'pg_lsn_minmax_ops' },
+{ oid => '4615',
+ opfmethod => 'brin', opfname => 'pg_lsn_minmax_multi_ops' },
+{ oid => '4590',
+ opfmethod => 'brin', opfname => 'pg_lsn_bloom_ops' },
+{ oid => '4104',
+ opfmethod => 'brin', opfname => 'box_inclusion_ops' },
+{ oid => '5000',
+ opfmethod => 'spgist', opfname => 'box_ops' },
+{ oid => '5008',
+ opfmethod => 'spgist', opfname => 'poly_ops' },
+{ oid => '4199',
+ opfmethod => 'btree', opfname => 'multirange_ops' },
+{ oid => '4225',
+ opfmethod => 'hash', opfname => 'multirange_ops' },
+{ oid => '6158',
+ opfmethod => 'gist', opfname => 'multirange_ops' },
+
+]
diff --git a/ydb/library/yql/parser/pg_catalog/CMakeLists.darwin.txt b/ydb/library/yql/parser/pg_catalog/CMakeLists.darwin.txt
index 6b0dc697e2..46e12b4a6e 100644
--- a/ydb/library/yql/parser/pg_catalog/CMakeLists.darwin.txt
+++ b/ydb/library/yql/parser/pg_catalog/CMakeLists.darwin.txt
@@ -30,6 +30,7 @@ target_sources(yql-parser-pg_catalog.global PRIVATE
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/1ecd65c896f36a3990d870644a6da9c8.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/46b25697572e7e60703079b71cd18295.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/15e039bc35a86f84476091e328dd74ea.cpp
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/f2374a475345069a2bfd38b387dfa11a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/462597d51509ecdc14b417ce082dc53b.cpp
@@ -70,6 +71,13 @@ resources(yql-parser-pg_catalog.global
pg_aggregate.dat
)
resources(yql-parser-pg_catalog.global
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
+ INPUTS
+ ${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat
+ KEYS
+ pg_opfamily.dat
+)
+resources(yql-parser-pg_catalog.global
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
INPUTS
${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opclass.dat
diff --git a/ydb/library/yql/parser/pg_catalog/CMakeLists.linux-aarch64.txt b/ydb/library/yql/parser/pg_catalog/CMakeLists.linux-aarch64.txt
index 21f796f0b4..56ead14794 100644
--- a/ydb/library/yql/parser/pg_catalog/CMakeLists.linux-aarch64.txt
+++ b/ydb/library/yql/parser/pg_catalog/CMakeLists.linux-aarch64.txt
@@ -32,6 +32,7 @@ target_sources(yql-parser-pg_catalog.global PRIVATE
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/1ecd65c896f36a3990d870644a6da9c8.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/46b25697572e7e60703079b71cd18295.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/15e039bc35a86f84476091e328dd74ea.cpp
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/f2374a475345069a2bfd38b387dfa11a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/462597d51509ecdc14b417ce082dc53b.cpp
@@ -72,6 +73,13 @@ resources(yql-parser-pg_catalog.global
pg_aggregate.dat
)
resources(yql-parser-pg_catalog.global
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
+ INPUTS
+ ${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat
+ KEYS
+ pg_opfamily.dat
+)
+resources(yql-parser-pg_catalog.global
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
INPUTS
${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opclass.dat
diff --git a/ydb/library/yql/parser/pg_catalog/CMakeLists.linux.txt b/ydb/library/yql/parser/pg_catalog/CMakeLists.linux.txt
index 21f796f0b4..56ead14794 100644
--- a/ydb/library/yql/parser/pg_catalog/CMakeLists.linux.txt
+++ b/ydb/library/yql/parser/pg_catalog/CMakeLists.linux.txt
@@ -32,6 +32,7 @@ target_sources(yql-parser-pg_catalog.global PRIVATE
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/1ecd65c896f36a3990d870644a6da9c8.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/46b25697572e7e60703079b71cd18295.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/15e039bc35a86f84476091e328dd74ea.cpp
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/f2374a475345069a2bfd38b387dfa11a.cpp
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/462597d51509ecdc14b417ce082dc53b.cpp
@@ -72,6 +73,13 @@ resources(yql-parser-pg_catalog.global
pg_aggregate.dat
)
resources(yql-parser-pg_catalog.global
+ ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/cfe805d97f50bda16fa4bad21fa16589.cpp
+ INPUTS
+ ${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opfamily.dat
+ KEYS
+ pg_opfamily.dat
+)
+resources(yql-parser-pg_catalog.global
${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/ca7bb755fe32f897eb03cf6004d1ad2a.cpp
INPUTS
${CMAKE_SOURCE_DIR}/contrib/libs/postgresql/src/include/catalog/pg_opclass.dat
diff --git a/ydb/library/yql/parser/pg_catalog/catalog.cpp b/ydb/library/yql/parser/pg_catalog/catalog.cpp
index 1b992efa5c..50e6cdb031 100644
--- a/ydb/library/yql/parser/pg_catalog/catalog.cpp
+++ b/ydb/library/yql/parser/pg_catalog/catalog.cpp
@@ -8,8 +8,14 @@
namespace NYql::NPg {
+constexpr ui32 InvalidOid = 0;
constexpr ui32 AnyOid = 2276;
constexpr ui32 AnyArrayOid = 2277;
+//constexpr ui32 AnyElementOid = 2283;
+//constexpr ui32 AnyNonArrayOid = 2776;
+//constexpr ui32 AnyCompatibleOid = 5077;
+//constexpr ui32 AnyCompatibleArrayOid = 5078;
+//constexpr ui32 AnyCompatibleNonArrayOid = 5079;
using TOperators = THashMap<ui32, TOperDesc>;
@@ -21,11 +27,15 @@ using TCasts = THashMap<ui32, TCastDesc>;
using TAggregations = THashMap<ui32, TAggregateDesc>;
+// We parse OpFamilies' IDs for now. If we ever needed oid_symbol,
+// create TOpFamilyDesc class alike other catalogs
+using TOpFamilies = THashMap<TString, ui32>;
+
using TOpClasses = THashMap<std::pair<EOpClassMethod, ui32>, TOpClassDesc>;
-using TAmOps = THashMap<std::tuple<TString, ui32, ui32, ui32>, TAmOpDesc>;
+using TAmOps = THashMap<std::tuple<ui32, ui32, ui32, ui32>, TAmOpDesc>;
-using TAmProcs = THashMap<std::tuple<TString, ui32, ui32, ui32>, TAmProcDesc>;
+using TAmProcs = THashMap<std::tuple<ui32, ui32, ui32, ui32>, TAmProcDesc>;
bool IsCompatibleTo(ui32 actualType, ui32 expectedType, const TTypes& types) {
if (!actualType) {
@@ -333,6 +343,7 @@ struct TLazyTypeInfo {
TString ReceiveFunc;
TString ModInFunc;
TString ModOutFunc;
+ TString SubscriptFunc;
};
class TTypesParser : public TParser {
@@ -370,6 +381,26 @@ public:
} else if (key == "typdelim") {
Y_ENSURE(value.size() == 1);
LastType.TypeDelim = value[0];
+ } else if (key == "typtype") {
+ Y_ENSURE(value.size() == 1);
+ const auto typType = value[0];
+
+ LastType.TypType =
+ (typType == 'b') ? ETypType::Base :
+ (typType == 'c') ? ETypType::Composite :
+ (typType == 'd') ? ETypType::Domain :
+ (typType == 'e') ? ETypType::Enum :
+ (typType == 'm') ? ETypType::Multirange :
+ (typType == 'p') ? ETypType::Pseudo :
+ (typType == 'r') ? ETypType::Range :
+ ythrow yexception() << "Unknown typtype value: " << value;
+ } else if (key == "typcollation") {
+ // hardcode collations for now. There are only three of 'em in .dat file
+ LastType.TypeCollation =
+ (value == "default") ? DefaultCollationOid :
+ (value == "C") ? C_CollationOid :
+ (value == "POSIX") ? PosixCollationOid :
+ ythrow yexception() << "Unknown typcollation value: " << value;
} else if (key == "typelem") {
LastLazyTypeInfo.ElementType = value; // resolve later
} else if (key == "typinput") {
@@ -384,6 +415,8 @@ public:
LastLazyTypeInfo.ModInFunc = value; // resolve later
} else if (key == "typmodout") {
LastLazyTypeInfo.ModOutFunc = value; // resolve later
+ } else if (key == "typsubscript") {
+ LastLazyTypeInfo.SubscriptFunc = value; // resolve later
} else if (key == "typbyval") {
if (value == "f") {
LastType.PassByValue = false;
@@ -498,6 +531,15 @@ public:
} else {
ythrow yexception() << "Unknown castmethod value: " << value;
}
+ } else if (key == "castcontext") {
+ Y_ENSURE(value.size() == 1);
+ const auto castCtx = value[0];
+
+ LastCast.CoercionCode =
+ (castCtx == 'i') ? ECoercionCode::Implicit :
+ (castCtx == 'a') ? ECoercionCode::Assignment :
+ (castCtx == 'e') ? ECoercionCode::Explicit :
+ ythrow yexception() << "Unknown castcontext value: " << value;
}
}
@@ -711,11 +753,59 @@ private:
TString LastDeserializeFunc;
};
+class TOpFamiliesParser : public TParser {
+public:
+ TOpFamiliesParser(TOpFamilies& opFamilies)
+ : OpFamilies(opFamilies)
+ {}
+
+ void OnKey(const TString& key, const TString& value) override {
+ if (key == "oid") {
+ LastOpfId = FromString<ui32>(value);
+ } else if (key == "opfmethod") {
+ if (value == "btree" || value == "hash") {
+ LastOpfMethod = value;
+ } else {
+ IsSupported = false;
+ }
+ } else if (key == "opfname") {
+ LastOpfName = value;
+ }
+ }
+
+ void OnFinish() override {
+ if (IsSupported) {
+ Y_ENSURE(LastOpfId != InvalidOid);
+
+ // TODO: log or throw if dict keys aren't unique
+ // opfamily references have opf_method/opf_name format in PG catalogs
+ OpFamilies[LastOpfMethod.append('/').append(
+ LastOpfName)] = LastOpfId; // LastOpfMethod is modified here. Use with caution till its reinit
+ }
+
+ IsSupported = true;
+ LastOpfId = InvalidOid;
+ LastOpfMethod.clear();
+ LastOpfName.clear();
+ }
+
+private:
+ TOpFamilies& OpFamilies;
+
+ ui32 LastOpfId = InvalidOid;
+
+ TString LastOpfMethod;
+ TString LastOpfName;
+ bool IsSupported = true;
+};
+
class TOpClassesParser : public TParser {
public:
- TOpClassesParser(TOpClasses& opClasses, const THashMap<TString, ui32>& typeByName)
- : OpClasses(opClasses)
- , TypeByName(typeByName)
+ TOpClassesParser(TOpClasses& opClasses, const THashMap<TString, ui32>& typeByName,
+ const TOpFamilies &opFamilies)
+ : OpClasses(opClasses)
+ , TypeByName(typeByName)
+ , OpFamilies(opFamilies)
{}
void OnKey(const TString& key, const TString& value) override {
@@ -735,40 +825,70 @@ public:
LastOpClass.Name = value;
} else if (key == "opcfamily") {
LastOpClass.Family = value;
+ auto opFamilyPtr = OpFamilies.FindPtr(value);
+
+ if (opFamilyPtr) {
+ LastOpClass.FamilyId = *opFamilyPtr;
+ } else {
+ IsSupported = false;
+ }
+ } else if (key == "opcdefault") {
+ IsDefault = (value[0] != 'f');
}
}
- void OnFinish() override {
- if (IsSupported) {
- Y_ENSURE(!LastOpClass.Name.empty());
- OpClasses[std::make_pair(LastOpClass.Method, LastOpClass.TypeId)] = LastOpClass;
- }
+void OnFinish() override {
+ // Only default opclasses are used so far
+ if (IsSupported && IsDefault) {
+ Y_ENSURE(!LastOpClass.Name.empty());
- IsSupported = true;
- LastOpClass = TOpClassDesc();
+ const auto key = std::make_pair(LastOpClass.Method, LastOpClass.TypeId);
+
+ if (OpClasses.contains(key)) {
+ throw yexception() << "Duplicate opclass: (" << (key.first == EOpClassMethod::Btree ? "btree" : "hash")
+ << ", " << key.second << ")";
+ }
+ OpClasses[key] = LastOpClass;
}
+ IsSupported = true;
+ IsDefault = true;
+ LastOpClass = TOpClassDesc();
+}
+
private:
TOpClasses& OpClasses;
+
const THashMap<TString, ui32>& TypeByName;
+ const TOpFamilies OpFamilies;
+
TOpClassDesc LastOpClass;
bool IsSupported = true;
+ bool IsDefault = true;
};
class TAmOpsParser : public TParser {
public:
TAmOpsParser(TAmOps& amOps, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators)
+ const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators,
+ const TOpFamilies &opFamilies)
: AmOps(amOps)
, TypeByName(typeByName)
, Types(types)
, OperatorsByName(operatorsByName)
, Operators(operators)
+ , OpFamilies(opFamilies)
{}
void OnKey(const TString& key, const TString& value) override {
if (key == "amopfamily") {
LastAmOp.Family = value;
+ auto opFamilyPtr = OpFamilies.FindPtr(value);
+ if (opFamilyPtr) {
+ LastAmOp.FamilyId = *opFamilyPtr;
+ } else {
+ IsSupported = false;
+ }
} else if (key == "amoplefttype") {
auto leftTypePtr = TypeByName.FindPtr(value);
Y_ENSURE(leftTypePtr);
@@ -787,49 +907,65 @@ public:
}
void OnFinish() override {
- auto operIdPtr = OperatorsByName.FindPtr(LastOp);
- Y_ENSURE(operIdPtr);
- for (const auto& id : *operIdPtr) {
- const auto& d = Operators.FindPtr(id);
- Y_ENSURE(d);
- if (d->Kind == EOperKind::Binary &&
- IsCompatibleTo(LastAmOp.LeftType, d->LeftType, Types) &&
- IsCompatibleTo(LastAmOp.RightType, d->RightType, Types)) {
- Y_ENSURE(!LastAmOp.OperId);
- LastAmOp.OperId = d->OperId;
+ if (IsSupported) {
+ auto operIdPtr = OperatorsByName.FindPtr(LastOp);
+ Y_ENSURE(operIdPtr);
+ for (const auto& id : *operIdPtr) {
+ const auto& d = Operators.FindPtr(id);
+ Y_ENSURE(d);
+ if (d->Kind == EOperKind::Binary &&
+ IsCompatibleTo(LastAmOp.LeftType, d->LeftType, Types) &&
+ IsCompatibleTo(LastAmOp.RightType, d->RightType, Types)) {
+ Y_ENSURE(!LastAmOp.OperId);
+ LastAmOp.OperId = d->OperId;
+ }
}
- }
- Y_ENSURE(LastAmOp.OperId);
- AmOps[std::make_tuple(LastAmOp.Family, LastAmOp.Strategy, LastAmOp.LeftType, LastAmOp.RightType)] = LastAmOp;
+ Y_ENSURE(LastAmOp.OperId);
+ AmOps[std::make_tuple(LastAmOp.FamilyId, LastAmOp.Strategy, LastAmOp.LeftType, LastAmOp.RightType)] = LastAmOp;
+ }
LastAmOp = TAmOpDesc();
LastOp = "";
+ IsSupported = true;
}
private:
TAmOps& AmOps;
+
const THashMap<TString, ui32>& TypeByName;
const TTypes& Types;
const THashMap<TString, TVector<ui32>>& OperatorsByName;
const TOperators& Operators;
+ const TOpFamilies& OpFamilies;
+
TAmOpDesc LastAmOp;
TString LastOp;
+ bool IsSupported = true;
};
class TAmProcsParser : public TParser {
public:
TAmProcsParser(TAmProcs& amProcs, const THashMap<TString, ui32>& typeByName,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs)
+ const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs,
+ const TOpFamilies& opFamilies)
: AmProcs(amProcs)
, TypeByName(typeByName)
, ProcByName(procByName)
, Procs(procs)
+ , OpFamilies(opFamilies)
{}
void OnKey(const TString& key, const TString& value) override {
if (key == "amprocfamily") {
LastAmProc.Family = value;
+ auto opFamilyPtr = OpFamilies.FindPtr(value);
+
+ if (opFamilyPtr) {
+ LastAmProc.FamilyId = *opFamilyPtr;
+ } else {
+ IsSupported = false;
+ }
} else if (key == "amproclefttype") {
auto leftTypePtr = TypeByName.FindPtr(value);
Y_ENSURE(leftTypePtr);
@@ -846,31 +982,38 @@ public:
}
void OnFinish() override {
- if (LastName.find('(') == TString::npos) {
- auto procIdPtr = ProcByName.FindPtr(LastName);
- Y_ENSURE(procIdPtr);
- for (const auto& id : *procIdPtr) {
- const auto& d = Procs.FindPtr(id);
- Y_ENSURE(d);
- Y_ENSURE(!LastAmProc.ProcId);
- LastAmProc.ProcId = d->ProcId;
- }
+ if (IsSupported) {
+ if (LastName.find('(') == TString::npos) {
+ auto procIdPtr = ProcByName.FindPtr(LastName);
+ Y_ENSURE(procIdPtr);
+ for (const auto& id : *procIdPtr) {
+ const auto& d = Procs.FindPtr(id);
+ Y_ENSURE(d);
+ Y_ENSURE(!LastAmProc.ProcId);
+ LastAmProc.ProcId = d->ProcId;
+ }
- Y_ENSURE(LastAmProc.ProcId);
- AmProcs[std::make_tuple(LastAmProc.Family, LastAmProc.ProcNum, LastAmProc.LeftType, LastAmProc.RightType)] = LastAmProc;
+ Y_ENSURE(LastAmProc.ProcId);
+ AmProcs[std::make_tuple(LastAmProc.FamilyId, LastAmProc.ProcNum, LastAmProc.LeftType, LastAmProc.RightType)] = LastAmProc;
+ }
}
LastAmProc = TAmProcDesc();
LastName = "";
+ IsSupported = true;
}
private:
TAmProcs& AmProcs;
+
const THashMap<TString, ui32>& TypeByName;
const THashMap<TString, TVector<ui32>>& ProcByName;
const TProcs& Procs;
+ const TOpFamilies& OpFamilies;
+
TAmProcDesc LastAmProc;
TString LastName;
+ bool IsSupported = true;
};
TOperators ParseOperators(const TString& dat, const THashMap<TString, ui32>& typeByName,
@@ -911,25 +1054,35 @@ TCasts ParseCasts(const TString& dat, const THashMap<TString, ui32>& typeByName,
return ret;
}
-TOpClasses ParseOpClasses(const TString& dat, const THashMap<TString, ui32>& typeByName) {
+TOpFamilies ParseOpFamilies(const TString& dat) {
+ TOpFamilies ret;
+ TOpFamiliesParser parser(ret);
+ parser.Do(dat);
+ return ret;
+}
+
+TOpClasses ParseOpClasses(const TString& dat, const THashMap<TString, ui32>& typeByName,
+ const TOpFamilies& opFamilies) {
TOpClasses ret;
- TOpClassesParser parser(ret, typeByName);
+ TOpClassesParser parser(ret, typeByName, opFamilies);
parser.Do(dat);
return ret;
}
TAmOps ParseAmOps(const TString& dat, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators) {
+ const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators,
+ const TOpFamilies& opFamilies) {
TAmOps ret;
- TAmOpsParser parser(ret, typeByName, types, operatorsByName, operators);
+ TAmOpsParser parser(ret, typeByName, types, operatorsByName, operators, opFamilies);
parser.Do(dat);
return ret;
}
TAmProcs ParseAmProcs(const TString& dat, const THashMap<TString, ui32>& typeByName,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs) {
+ const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs,
+ const TOpFamilies& opFamilies) {
TAmProcs ret;
- TAmProcsParser parser(ret, typeByName, procByName, procs);
+ TAmProcsParser parser(ret, typeByName, procByName, procs, opFamilies);
parser.Do(dat);
return ret;
}
@@ -946,6 +1099,8 @@ struct TCatalog {
Y_ENSURE(NResource::FindExact("pg_cast.dat", &castData));
TString aggData;
Y_ENSURE(NResource::FindExact("pg_aggregate.dat", &aggData));
+ TString opFamiliesData;
+ Y_ENSURE(NResource::FindExact("pg_opfamily.dat", &opFamiliesData));
TString opClassData;
Y_ENSURE(NResource::FindExact("pg_opclass.dat", &opClassData));
TString amProcData;
@@ -964,28 +1119,16 @@ struct TCatalog {
}
}
- for (const auto& [k, v]: lazyTypeInfos) {
- if (!v.ElementType) {
- continue;
- }
-
- auto elemTypePtr = TypeByName.FindPtr(v.ElementType);
- Y_ENSURE(elemTypePtr);
- auto typePtr = Types.FindPtr(k);
- Y_ENSURE(typePtr);
- typePtr->ElementTypeId = *elemTypePtr;
- }
-
Procs = ParseProcs(procData, TypeByName);
- for (const auto& [k, v]: Procs) {
+ for (const auto& [k, v] : Procs) {
ProcByName[v.Name].push_back(k);
}
const ui32 cstringId = 2275;
const ui32 byteaId = 17;
const ui32 internalId = 2281;
- for (const auto&[k, v] : lazyTypeInfos) {
+ for (const auto& [k, v] : lazyTypeInfos) {
auto typePtr = Types.FindPtr(k);
Y_ENSURE(typePtr);
@@ -1048,6 +1191,23 @@ struct TCatalog {
Y_ENSURE(modOutFuncPtr->ArgTypes.size() == 1);
typePtr->TypeModOutFuncId = modOutFuncIdPtr->at(0);
}
+
+ if (v.SubscriptFunc) {
+ auto subscriptFuncIdPtr = ProcByName.FindPtr(v.SubscriptFunc);
+ Y_ENSURE(subscriptFuncIdPtr);
+ Y_ENSURE(subscriptFuncIdPtr->size() == 1);
+ auto subscriptFuncPtr = Procs.FindPtr(subscriptFuncIdPtr->at(0));
+ Y_ENSURE(subscriptFuncPtr);
+ Y_ENSURE(subscriptFuncPtr->ArgTypes.size() == 1);
+ typePtr->TypeSubscriptFuncId = subscriptFuncIdPtr->at(0);
+ }
+
+ if (v.ElementType) {
+ auto elemTypePtr = TypeByName.FindPtr(v.ElementType);
+ Y_ENSURE(elemTypePtr);
+
+ typePtr->ElementTypeId = *elemTypePtr;
+ }
}
Casts = ParseCasts(castData, TypeByName, Types, ProcByName, Procs);
@@ -1065,16 +1225,17 @@ struct TCatalog {
AggregationsByName[v.Name].push_back(k);
}
- OpClasses = ParseOpClasses(opClassData, TypeByName);
- AmOps = ParseAmOps(amOpData, TypeByName, Types, OperatorsByName, Operators);
- AmProcs = ParseAmProcs(amProcData, TypeByName, ProcByName, Procs);
- for (auto&[k, v] : Types) {
+ TOpFamilies opFamilies = ParseOpFamilies(opFamiliesData);
+ OpClasses = ParseOpClasses(opClassData, TypeByName, opFamilies);
+ AmOps = ParseAmOps(amOpData, TypeByName, Types, OperatorsByName, Operators, opFamilies);
+ AmProcs = ParseAmProcs(amProcData, TypeByName, ProcByName, Procs, opFamilies);
+ for (auto& [k, v] : Types) {
if (v.TypeId != v.ArrayTypeId) {
auto btreeOpClassPtr = OpClasses.FindPtr(std::make_pair(EOpClassMethod::Btree, v.TypeId));
if (btreeOpClassPtr) {
- auto lessAmOpPtr = AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->Family, ui32(EBtreeAmStrategy::Less), v.TypeId, v.TypeId));
+ auto lessAmOpPtr = AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmStrategy::Less), v.TypeId, v.TypeId));
Y_ENSURE(lessAmOpPtr);
- auto equalAmOpPtr = AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->Family, ui32(EBtreeAmStrategy::Equal), v.TypeId, v.TypeId));
+ auto equalAmOpPtr = AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmStrategy::Equal), v.TypeId, v.TypeId));
Y_ENSURE(equalAmOpPtr);
auto lessOperPtr = Operators.FindPtr(lessAmOpPtr->OperId);
Y_ENSURE(lessOperPtr);
@@ -1083,14 +1244,14 @@ struct TCatalog {
v.LessProcId = lessOperPtr->ProcId;
v.EqualProcId = equalOperPtr->ProcId;
- auto compareAmProcPtr = AmProcs.FindPtr(std::make_tuple(btreeOpClassPtr->Family, ui32(EBtreeAmProcNum::Compare), v.TypeId, v.TypeId));
+ auto compareAmProcPtr = AmProcs.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmProcNum::Compare), v.TypeId, v.TypeId));
Y_ENSURE(compareAmProcPtr);
v.CompareProcId = compareAmProcPtr->ProcId;
}
auto hashOpClassPtr = OpClasses.FindPtr(std::make_pair(EOpClassMethod::Hash, v.TypeId));
if (hashOpClassPtr) {
- auto hashAmProcPtr = AmProcs.FindPtr(std::make_tuple(hashOpClassPtr->Family, ui32(EHashAmProcNum::Hash), v.TypeId, v.TypeId));
+ auto hashAmProcPtr = AmProcs.FindPtr(std::make_tuple(hashOpClassPtr->FamilyId, ui32(EHashAmProcNum::Hash), v.TypeId, v.TypeId));
Y_ENSURE(hashAmProcPtr);
v.HashProcId = hashAmProcPtr->ProcId;
}
@@ -1206,19 +1367,19 @@ bool HasType(const TStringBuf& name) {
const TTypeDesc& LookupType(const TString& name) {
const auto& catalog = TCatalog::Instance();
- auto typeIdPtr = catalog.TypeByName.FindPtr(name);
+ const auto typeIdPtr = catalog.TypeByName.FindPtr(name);
if (!typeIdPtr) {
throw yexception() << "No such type: " << name;
}
- auto typePtr = catalog.Types.FindPtr(*typeIdPtr);
+ const auto typePtr = catalog.Types.FindPtr(*typeIdPtr);
Y_ENSURE(typePtr);
return *typePtr;
}
const TTypeDesc& LookupType(ui32 typeId) {
const auto& catalog = TCatalog::Instance();
- auto typePtr = catalog.Types.FindPtr(typeId);
+ const auto typePtr = catalog.Types.FindPtr(typeId);
if (!typePtr) {
throw yexception() << "No such type: " << typeId;
}
@@ -1331,19 +1492,25 @@ bool HasOpClass(EOpClassMethod method, ui32 typeId) {
return catalog.OpClasses.contains(std::make_pair(method, typeId));
}
-const TOpClassDesc& LookupOpClass(EOpClassMethod method, ui32 typeId) {
+const TOpClassDesc* LookupDefaultOpClass(EOpClassMethod method, ui32 typeId) {
const auto& catalog = TCatalog::Instance();
- auto opClassPtr = catalog.OpClasses.FindPtr(std::make_pair(method, typeId));
- if (!opClassPtr) {
- throw yexception() << "No such opclass";
- }
+ const auto opClassPtr = catalog.OpClasses.FindPtr(std::make_pair(method, typeId));
+ if (opClassPtr)
+ return opClassPtr;
- return *opClassPtr;
+ throw yexception() << "No such opclass";
+
+ // TODO: support binary coercible and preferred types as define in PG's GetDefaultOpClass()
+}
+
+bool HasAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType) {
+ const auto &catalog = TCatalog::Instance();
+ return catalog.AmOps.contains(std::make_tuple(familyId, strategy, leftType, rightType));
}
-const TAmOpDesc& LookupAmOp(const TString& family, ui32 strategy, ui32 leftType, ui32 rightType) {
+const TAmOpDesc& LookupAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType) {
const auto& catalog = TCatalog::Instance();
- auto amOpPtr = catalog.AmOps.FindPtr(std::make_tuple(family, strategy, leftType, rightType));
+ const auto amOpPtr = catalog.AmOps.FindPtr(std::make_tuple(familyId, strategy, leftType, rightType));
if (!amOpPtr) {
throw yexception() << "No such amop";
}
@@ -1351,9 +1518,14 @@ const TAmOpDesc& LookupAmOp(const TString& family, ui32 strategy, ui32 leftType,
return *amOpPtr;
}
-const TAmProcDesc& LookupAmProc(const TString& family, ui32 num, ui32 leftType, ui32 rightType) {
+bool HasAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType) {
+ const auto &catalog = TCatalog::Instance();
+ return catalog.AmProcs.contains(std::make_tuple(familyId, num, leftType, rightType));
+}
+
+const TAmProcDesc& LookupAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType) {
const auto& catalog = TCatalog::Instance();
- auto amProcPtr = catalog.AmProcs.FindPtr(std::make_tuple(family, num, leftType, rightType));
+ auto amProcPtr = catalog.AmProcs.FindPtr(std::make_tuple(familyId, num, leftType, rightType));
if (!amProcPtr) {
throw yexception() << "No such amproc";
}
diff --git a/ydb/library/yql/parser/pg_catalog/catalog.h b/ydb/library/yql/parser/pg_catalog/catalog.h
index ad62ce037f..12cc8812f0 100644
--- a/ydb/library/yql/parser/pg_catalog/catalog.h
+++ b/ydb/library/yql/parser/pg_catalog/catalog.h
@@ -2,6 +2,7 @@
#include <util/generic/maybe.h>
#include <util/generic/string.h>
#include <util/generic/vector.h>
+#include <util/stream/output.h>
namespace NYql::NPg {
@@ -38,6 +39,23 @@ struct TProcDesc {
bool ReturnSet = false;
};
+// Copied from pg_collation_d.h
+constexpr ui32 InvalidCollationOid = 0;
+constexpr ui32 DefaultCollationOid = 100;
+constexpr ui32 C_CollationOid = 950;
+constexpr ui32 PosixCollationOid = 951;
+
+// Copied from pg_type_d.h, TYPTYPE_* constants
+enum class ETypType : char {
+ Base = 'b',
+ Composite = 'c',
+ Domain = 'd',
+ Enum = 'e',
+ Multirange = 'm',
+ Pseudo = 'p',
+ Range = 'r',
+};
+
struct TTypeDesc {
ui32 TypeId = 0;
ui32 ArrayTypeId = 0;
@@ -47,18 +65,30 @@ struct TTypeDesc {
char Category = '\0';
char TypeAlign = '\0';
char TypeDelim = ',';
+
+ /*
+ * Collation: InvalidCollationOid if type cannot use collations, nonzero (typically
+ * DefaultCollationOid) for collatable base types, possibly some other
+ * OID for domains over collatable types
+ */
+ ui32 TypeCollation = InvalidCollationOid;
+
ui32 InFuncId = 0;
ui32 OutFuncId = 0;
ui32 SendFuncId = 0;
ui32 ReceiveFuncId = 0;
ui32 TypeModInFuncId = 0;
ui32 TypeModOutFuncId = 0;
+ ui32 TypeSubscriptFuncId = 0;
i32 TypeLen = 0;
// from opclass
ui32 LessProcId = 0;
ui32 EqualProcId = 0;
ui32 CompareProcId = 0;
ui32 HashProcId = 0;
+
+ // If TypType is 'c', typrelid is the OID of the class' entry in pg_class.
+ ETypType TypType = ETypType::Base;
};
enum class ECastMethod {
@@ -67,11 +97,19 @@ enum class ECastMethod {
Binary
};
+enum class ECoercionCode : char {
+ Unknown = '?', // not specified
+ Implicit = 'i', // coercion in context of expression
+ Assignment = 'a', // coercion in context of assignment
+ Explicit = 'e', // explicit cast operation
+};
+
struct TCastDesc {
ui32 SourceId = 0;
ui32 TargetId = 0;
ECastMethod Method = ECastMethod::Function;
ui32 FunctionId = 0;
+ ECoercionCode CoercionCode = ECoercionCode::Unknown;
};
enum class EAggKind {
@@ -103,10 +141,12 @@ struct TOpClassDesc {
ui32 TypeId = 0;
TString Name;
TString Family;
+ ui32 FamilyId = 0;
};
struct TAmOpDesc {
TString Family;
+ ui32 FamilyId = 0;
ui32 Strategy = 0;
ui32 LeftType = 0;
ui32 RightType = 0;
@@ -123,6 +163,7 @@ enum class EBtreeAmStrategy {
struct TAmProcDesc {
TString Family;
+ ui32 FamilyId = 0;
ui32 ProcNum = 0;
ui32 LeftType = 0;
ui32 RightType = 0;
@@ -158,11 +199,28 @@ bool HasAggregation(const TStringBuf& name);
const TAggregateDesc& LookupAggregation(const TStringBuf& name, const TVector<ui32>& argTypeIds);
bool HasOpClass(EOpClassMethod method, ui32 typeId);
-const TOpClassDesc& LookupOpClass(EOpClassMethod method, ui32 typeId);
+const TOpClassDesc* LookupDefaultOpClass(EOpClassMethod method, ui32 typeId);
-const TAmOpDesc& LookupAmOp(const TString& family, ui32 strategy, ui32 leftType, ui32 rightType);
-const TAmProcDesc& LookupAmProc(const TString& family, ui32 num, ui32 leftType, ui32 rightType);
+bool HasAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType);
+const TAmOpDesc& LookupAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType);
+
+bool HasAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType);
+const TAmProcDesc& LookupAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType);
bool IsCompatibleTo(ui32 actualType, ui32 expectedType);
+inline bool IsArrayType(const TTypeDesc& typeDesc) noexcept {
+ return typeDesc.ArrayTypeId == typeDesc.TypeId;
+}
+
+}
+
+template <>
+inline void Out<NYql::NPg::ETypType>(IOutputStream& o, NYql::NPg::ETypType typType) {
+ o.Write(static_cast<std::underlying_type<NYql::NPg::ETypType>::type>(typType));
+}
+
+template <>
+inline void Out<NYql::NPg::ECoercionCode>(IOutputStream& o, NYql::NPg::ECoercionCode coercionCode) {
+ o.Write(static_cast<std::underlying_type<NYql::NPg::ECoercionCode>::type>(coercionCode));
}
diff --git a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.darwin.txt b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.darwin.txt
index 4d95f99586..9caa9852f3 100644
--- a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.darwin.txt
+++ b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.darwin.txt
@@ -10,6 +10,7 @@
add_executable(ydb-library-yql-parser-pg_catalog-ut)
target_include_directories(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
contrib-libs-cxxsupp
@@ -17,6 +18,7 @@ target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
library-cpp-cpuid_check
cpp-testing-unittest_main
yql-parser-pg_catalog
+ yql-parser-pg_wrapper
)
target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
-Wl,-no_deduplicate
@@ -26,6 +28,7 @@ target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
)
target_sources(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp
)
add_test(
NAME
diff --git a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux-aarch64.txt b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux-aarch64.txt
index 661964561e..3e8d5bac42 100644
--- a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux-aarch64.txt
+++ b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux-aarch64.txt
@@ -10,6 +10,7 @@
add_executable(ydb-library-yql-parser-pg_catalog-ut)
target_include_directories(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
contrib-libs-linux-headers
@@ -18,6 +19,7 @@ target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
library-cpp-lfalloc
cpp-testing-unittest_main
yql-parser-pg_catalog
+ yql-parser-pg_wrapper
)
target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
-ldl
@@ -31,6 +33,7 @@ target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
)
target_sources(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp
)
add_test(
NAME
diff --git a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux.txt b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux.txt
index cbec079ba1..27da60823c 100644
--- a/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux.txt
+++ b/ydb/library/yql/parser/pg_catalog/ut/CMakeLists.linux.txt
@@ -10,6 +10,7 @@
add_executable(ydb-library-yql-parser-pg_catalog-ut)
target_include_directories(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
contrib-libs-linux-headers
@@ -20,6 +21,7 @@ target_link_libraries(ydb-library-yql-parser-pg_catalog-ut PUBLIC
library-cpp-cpuid_check
cpp-testing-unittest_main
yql-parser-pg_catalog
+ yql-parser-pg_wrapper
)
target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
-ldl
@@ -33,6 +35,7 @@ target_link_options(ydb-library-yql-parser-pg_catalog-ut PRIVATE
)
target_sources(ydb-library-yql-parser-pg_catalog-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp
)
add_test(
NAME
diff --git a/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp b/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp
new file mode 100644
index 0000000000..ad178a2ca2
--- /dev/null
+++ b/ydb/library/yql/parser/pg_catalog/ut/catalog_consts_ut.cpp
@@ -0,0 +1,33 @@
+#include <ydb/library/yql/parser/pg_catalog/catalog.h>
+
+// see pg_attribute_printf macro in c.h
+// should expand to nothing
+#undef __GNUC__
+#undef __IBMC__
+
+extern "C" {
+#include "postgres.h"
+#include "catalog/pg_collation_d.h"
+#include "access/stratnum.h"
+
+#undef Min
+#undef Max
+}
+
+#include <library/cpp/testing/unittest/registar.h>
+
+Y_UNIT_TEST_SUITE(TConstantsTests) {
+ Y_UNIT_TEST(TestCollationConsts) {
+ UNIT_ASSERT(NYql::NPg::DefaultCollationOid == DEFAULT_COLLATION_OID);
+ UNIT_ASSERT(NYql::NPg::C_CollationOid == C_COLLATION_OID);
+ UNIT_ASSERT(NYql::NPg::PosixCollationOid == POSIX_COLLATION_OID);
+ }
+
+ Y_UNIT_TEST(BTreeAmStrategyConsts) {
+ UNIT_ASSERT(static_cast<ui32>(NYql::NPg::EBtreeAmStrategy::Less) == BTLessStrategyNumber);
+ UNIT_ASSERT(static_cast<ui32>(NYql::NPg::EBtreeAmStrategy::LessOrEqual) == BTLessEqualStrategyNumber);
+ UNIT_ASSERT(static_cast<ui32>(NYql::NPg::EBtreeAmStrategy::Equal) == BTEqualStrategyNumber);
+ UNIT_ASSERT(static_cast<ui32>(NYql::NPg::EBtreeAmStrategy::GreaterOrEqual) == BTGreaterEqualStrategyNumber);
+ UNIT_ASSERT(static_cast<ui32>(NYql::NPg::EBtreeAmStrategy::Greater) == BTGreaterStrategyNumber);
+ }
+}
diff --git a/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp b/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
index 52dceecbd9..045518a3b9 100644
--- a/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
+++ b/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp
@@ -26,6 +26,8 @@ Y_UNIT_TEST_SUITE(TTypesTests) {
UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1009);
UNIT_ASSERT_VALUES_EQUAL(ret.Name, "text");
UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, 0);
+ UNIT_ASSERT_VALUES_EQUAL(ret.TypeCollation, DefaultCollationOid);
+ UNIT_ASSERT_VALUES_EQUAL(ret.TypType, ETypType::Base);
UNIT_ASSERT(ret.LessProcId);
UNIT_ASSERT(ret.EqualProcId);
UNIT_ASSERT(ret.CompareProcId);
@@ -36,6 +38,8 @@ Y_UNIT_TEST_SUITE(TTypesTests) {
UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1017);
UNIT_ASSERT_VALUES_EQUAL(ret.Name, "point");
UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, LookupType("float8").TypeId);
+ UNIT_ASSERT_VALUES_EQUAL(ret.TypType, ETypType::Base);
+ UNIT_ASSERT(ret.TypeSubscriptFuncId);
UNIT_ASSERT(!ret.LessProcId);
UNIT_ASSERT(!ret.EqualProcId);
UNIT_ASSERT(!ret.CompareProcId);
@@ -46,6 +50,8 @@ Y_UNIT_TEST_SUITE(TTypesTests) {
UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1009);
UNIT_ASSERT_VALUES_EQUAL(ret.Name, "_text");
UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, 25);
+ UNIT_ASSERT_VALUES_EQUAL(ret.TypeCollation, DefaultCollationOid);
+ UNIT_ASSERT_VALUES_EQUAL(ret.TypType, ETypType::Base);
}
}
@@ -99,6 +105,7 @@ Y_UNIT_TEST_SUITE(TCastsTests) {
auto ret = LookupCast(LookupType("int8").TypeId, LookupType("int4").TypeId);
UNIT_ASSERT_VALUES_EQUAL(ret.SourceId, LookupType("int8").TypeId);
UNIT_ASSERT_VALUES_EQUAL(ret.TargetId, LookupType("int4").TypeId);
+ UNIT_ASSERT_VALUES_EQUAL(ret.CoercionCode, ECoercionCode::Assignment);
UNIT_ASSERT(ret.Method == ECastMethod::Function);
UNIT_ASSERT_VALUES_UNEQUAL(ret.FunctionId, 0);
@@ -171,20 +178,22 @@ Y_UNIT_TEST_SUITE(TAggregationsTests) {
Y_UNIT_TEST_SUITE(TOpClassesTests) {
Y_UNIT_TEST(TestMissing) {
- UNIT_ASSERT_EXCEPTION(LookupOpClass(EOpClassMethod::Btree, LookupType("json").TypeId), yexception);
+ UNIT_ASSERT_EXCEPTION(LookupDefaultOpClass(EOpClassMethod::Btree, LookupType("json").TypeId), yexception);
}
Y_UNIT_TEST(TestOk) {
- auto ret = LookupOpClass(EOpClassMethod::Btree, LookupType("int4").TypeId);
+ auto ret = *LookupDefaultOpClass(EOpClassMethod::Btree, LookupType("int4").TypeId);
UNIT_ASSERT(ret.Method == EOpClassMethod::Btree);
UNIT_ASSERT_VALUES_EQUAL(ret.TypeId, LookupType("int4").TypeId);
UNIT_ASSERT_VALUES_EQUAL(ret.Name, "int4_ops");
UNIT_ASSERT_VALUES_EQUAL(ret.Family, "btree/integer_ops");
+ UNIT_ASSERT_VALUES_EQUAL(ret.FamilyId, 1976);
- ret = LookupOpClass(EOpClassMethod::Hash, LookupType("int4").TypeId);
+ ret = *LookupDefaultOpClass(EOpClassMethod::Hash, LookupType("int4").TypeId);
UNIT_ASSERT(ret.Method == EOpClassMethod::Hash);
UNIT_ASSERT_VALUES_EQUAL(ret.TypeId, LookupType("int4").TypeId);
UNIT_ASSERT_VALUES_EQUAL(ret.Name, "int4_ops");
UNIT_ASSERT_VALUES_EQUAL(ret.Family, "hash/integer_ops");
+ UNIT_ASSERT_VALUES_EQUAL(ret.FamilyId, 1977);
}
}
diff --git a/ydb/library/yql/parser/pg_wrapper/CMakeLists.darwin.txt b/ydb/library/yql/parser/pg_wrapper/CMakeLists.darwin.txt
index dae4e344ea..624d3a5aa7 100644
--- a/ydb/library/yql/parser/pg_wrapper/CMakeLists.darwin.txt
+++ b/ydb/library/yql/parser/pg_wrapper/CMakeLists.darwin.txt
@@ -132,6 +132,7 @@ target_sources(yql-parser-pg_wrapper PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/parser.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/thread_inits.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/type_cache.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/port/pg_crc32c_sse42.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/port/pg_crc32c_sse42_choose.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/access/brin/brin.c
diff --git a/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux-aarch64.txt b/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux-aarch64.txt
index d02e7246d8..27c23b07fd 100644
--- a/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux-aarch64.txt
+++ b/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux-aarch64.txt
@@ -131,6 +131,7 @@ target_sources(yql-parser-pg_wrapper PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/parser.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/thread_inits.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/type_cache.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/access/brin/brin.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/access/brin/brin_bloom.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/access/brin/brin_inclusion.c
diff --git a/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux.txt b/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux.txt
index af95f6e790..23b996059d 100644
--- a/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux.txt
+++ b/ydb/library/yql/parser/pg_wrapper/CMakeLists.linux.txt
@@ -133,6 +133,7 @@ target_sources(yql-parser-pg_wrapper PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/parser.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/thread_inits.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/type_cache.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/port/pg_crc32c_sse42.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/port/pg_crc32c_sse42_choose.c
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/access/brin/brin.c
diff --git a/ydb/library/yql/parser/pg_wrapper/parser.cpp b/ydb/library/yql/parser/pg_wrapper/parser.cpp
index 2bf1b7ebd9..4dbee8cd7d 100644
--- a/ydb/library/yql/parser/pg_wrapper/parser.cpp
+++ b/ydb/library/yql/parser/pg_wrapper/parser.cpp
@@ -52,6 +52,7 @@ extern "C" {
extern __thread Latch LocalLatchData;
extern void destroy_timezone_hashtable();
+extern void destroy_typecache_hashtable();
extern void free_current_locale_conv();
const char *progname;
@@ -302,6 +303,8 @@ extern "C" void setup_pg_thread_cleanup() {
struct TThreadCleanup {
~TThreadCleanup() {
destroy_timezone_hashtable();
+ destroy_typecache_hashtable();
+
free_current_locale_conv();
ResourceOwnerDelete(CurrentResourceOwner);
MemoryContextDelete(TopMemoryContext);
diff --git a/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/lsyscache.c b/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/lsyscache.c
index efeb31ffb6..9c1c51e287 100644
--- a/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/lsyscache.c
+++ b/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/lsyscache.c
@@ -161,8 +161,8 @@ get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
* Returns InvalidOid if there is no pg_amop entry for the given keys.
*/
Oid
-get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
- int16 strategy)
+get_opfamily_member_original(Oid opfamily, Oid lefttype, Oid righttype,
+ int16 strategy)
{
HeapTuple tp;
Form_pg_amop amop_tup;
@@ -791,7 +791,7 @@ comparison_ops_are_compatible(Oid opno1, Oid opno2)
* Returns InvalidOid if there is no pg_amproc entry for the given keys.
*/
Oid
-get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
+get_opfamily_proc_original(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
{
HeapTuple tp;
Form_pg_amproc amproc_tup;
@@ -1253,7 +1253,7 @@ get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
* operator given the operator oid.
*/
RegProcedure
-get_opcode(Oid opno)
+get_opcode_original(Oid opno)
{
HeapTuple tp;
@@ -2757,15 +2757,17 @@ get_array_type(Oid typid)
Oid
get_promoted_array_type(Oid typid)
{
- Oid array_type = get_array_type(typid);
+ Oid array_type = get_array_type(typid);
- if (OidIsValid(array_type))
- return array_type;
- if (OidIsValid(get_element_type(typid)))
- return typid;
- return InvalidOid;
+ if (OidIsValid(array_type))
+ return array_type;
+ if (OidIsValid(get_element_type(typid)))
+ return typid;
+ return InvalidOid;
}
+extern Oid get_base_element_type(Oid typid);
+
/*
* get_base_element_type
* Given the type OID, get the typelem, looking "through" any domain
@@ -2776,7 +2778,7 @@ get_promoted_array_type(Oid typid)
* about the typmod of the array.
*/
Oid
-get_base_element_type(Oid typid)
+get_base_element_type_original(Oid typid)
{
/*
* We loop to find the bottom base type in a stack of domains.
diff --git a/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/typcache.c b/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/typcache.c
index abe0c08313..6860026d04 100644
--- a/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/typcache.c
+++ b/ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/typcache.c
@@ -289,14 +289,14 @@ static void load_typcache_tupdesc(TypeCacheEntry *typentry);
static void load_rangetype_info(TypeCacheEntry *typentry);
static void load_multirangetype_info(TypeCacheEntry *typentry);
static void load_domaintype_info(TypeCacheEntry *typentry);
-static int dcs_cmp(const void *a, const void *b);
+static int dcs_cmp(const void *a, const void *b);
static void decr_dcc_refcount(DomainConstraintCache *dcc);
static void dccref_deletion_callback(void *arg);
static List *prep_domain_constraints(List *constraints, MemoryContext execctx);
-static bool array_element_has_equality(TypeCacheEntry *typentry);
-static bool array_element_has_compare(TypeCacheEntry *typentry);
-static bool array_element_has_hashing(TypeCacheEntry *typentry);
-static bool array_element_has_extended_hashing(TypeCacheEntry *typentry);
+bool array_element_has_equality(TypeCacheEntry *typentry);
+bool array_element_has_compare(TypeCacheEntry *typentry);
+bool array_element_has_hashing(TypeCacheEntry *typentry);
+bool array_element_has_extended_hashing(TypeCacheEntry *typentry);
static void cache_array_element_properties(TypeCacheEntry *typentry);
static bool record_fields_have_equality(TypeCacheEntry *typentry);
static bool record_fields_have_compare(TypeCacheEntry *typentry);
@@ -335,7 +335,7 @@ static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc,
* are InvalidOid or not.
*/
TypeCacheEntry *
-lookup_type_cache(Oid type_id, int flags)
+lookup_type_cache_original(Oid type_id, int flags)
{
TypeCacheEntry *typentry;
bool found;
@@ -1414,7 +1414,7 @@ DomainHasConstraints(Oid type_id)
* component datatype(s).
*/
-static bool
+bool
array_element_has_equality(TypeCacheEntry *typentry)
{
if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
@@ -1422,7 +1422,7 @@ array_element_has_equality(TypeCacheEntry *typentry)
return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
}
-static bool
+bool
array_element_has_compare(TypeCacheEntry *typentry)
{
if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
@@ -1430,7 +1430,7 @@ array_element_has_compare(TypeCacheEntry *typentry)
return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
}
-static bool
+bool
array_element_has_hashing(TypeCacheEntry *typentry)
{
if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
@@ -1438,7 +1438,7 @@ array_element_has_hashing(TypeCacheEntry *typentry)
return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
}
-static bool
+bool
array_element_has_extended_hashing(TypeCacheEntry *typentry)
{
if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
diff --git a/ydb/library/yql/parser/pg_wrapper/type_cache.cpp b/ydb/library/yql/parser/pg_wrapper/type_cache.cpp
new file mode 100644
index 0000000000..022df30572
--- /dev/null
+++ b/ydb/library/yql/parser/pg_wrapper/type_cache.cpp
@@ -0,0 +1,506 @@
+//==================================================================================
+// lookup_type_cache reimplemented for YQL
+//==================================================================================
+
+#include <util/system/compiler.h>
+#include <ydb/library/yql/parser/pg_catalog/catalog.h>
+
+extern "C" {
+#include "postgres.h"
+#include "catalog/pg_operator_d.h"
+#include "access/hash.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/typcache.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+}
+
+#include "type_cache.h"
+
+namespace NYql {
+
+typedef struct HTAB HTAB;
+
+static __thread HTAB *YQL_TypeCacheHash = nullptr;
+
+HTAB *init_type_cache() {
+ if (CacheMemoryContext == nullptr)
+ CreateCacheMemoryContext();
+
+ HASHCTL ctl = {
+ .keysize = sizeof(Oid),
+ .entrysize = sizeof(TypeCacheEntry)
+ };
+
+ return hash_create("Type information cache", 64, &ctl,
+ HASH_ELEM | HASH_BLOBS);
+}
+
+extern "C" {
+extern bool array_element_has_equality(TypeCacheEntry *typentry);
+extern bool array_element_has_compare(TypeCacheEntry *typentry);
+extern bool array_element_has_hashing(TypeCacheEntry *typentry);
+extern bool array_element_has_extended_hashing(TypeCacheEntry *typentry);
+
+/*
+ * lookup_type_cache
+ *
+ * Fetch the type cache entry for the specified datatype, and make sure that
+ * all the fields requested by bits in 'flags' are valid.
+ *
+ * The the caller needs to check whether the fields are InvalidOid or not.
+ */
+TypeCacheEntry*
+lookup_type_cache(Oid type_id, int flags) {
+ if (Y_UNLIKELY(YQL_TypeCacheHash == nullptr)) {
+ YQL_TypeCacheHash = init_type_cache();
+ }
+
+ // Try to look up an existing entry
+ auto typentry = static_cast<TypeCacheEntry*>(hash_search(YQL_TypeCacheHash,
+ &type_id,
+ HASH_FIND, nullptr));
+
+ if (typentry == nullptr) {
+ const auto &typeDesc = NYql::NPg::LookupType(type_id);
+
+ bool found;
+
+ typentry = static_cast<TypeCacheEntry*>(hash_search(YQL_TypeCacheHash,
+ (void *) &type_id,
+ HASH_ENTER, &found));
+
+ Y_ASSERT(!found); // it wasn't there a moment ago
+
+ memset(typentry, 0, sizeof(TypeCacheEntry));
+
+ // These fields can never change, by definition
+ typentry->type_id = type_id;
+ // PG 14 seems to use type_id_hash in syscache invalidation callback only, we don't touch the field
+ // since YQL doesn't use the callback
+ // typentry->type_id_hash = 0; // GetSysCacheHashValue1(TYPEOID, ObjectIdGetDatum(type_id));
+
+ typentry->typlen = typeDesc.TypeLen;
+ typentry->typbyval = typeDesc.PassByValue;
+ typentry->typalign = typeDesc.TypeAlign;
+ // TODO: fill depending on the typstorage, if toasting gets implemented in PG
+ typentry->typstorage = TYPSTORAGE_PLAIN; //typtup->typstorage;
+ typentry->typtype = static_cast<char>(typeDesc.TypType);
+
+ // TODO: fill for composite types only. Don't touch until YQL supports those
+ Y_ASSERT(typeDesc.TypType != NYql::NPg::ETypType::Composite);
+ // typentry->typrelid = 0; //typtup->typrelid;
+
+ typentry->typsubscript = typeDesc.TypeSubscriptFuncId;
+ typentry->typelem = typeDesc.ElementTypeId;
+ typentry->typcollation = typeDesc.TypeCollation;
+ typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
+
+ // We don't fill base domain type since domains aren't supported in YQL
+ }
+ // typentries don't change from callbacks, cause we have none
+
+ /*
+ * Look up opclasses if we haven't already and any dependent info is
+ * requested.
+ */
+ if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_LT_OPR | TYPECACHE_GT_OPR |
+ TYPECACHE_CMP_PROC |
+ TYPECACHE_EQ_OPR_FINFO | TYPECACHE_CMP_PROC_FINFO |
+ TYPECACHE_BTREE_OPFAMILY)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
+ {
+ const auto opClassDescPtr = NYql::NPg::LookupDefaultOpClass(NYql::NPg::EOpClassMethod::Btree, type_id);
+
+ if (opClassDescPtr != nullptr) {
+ typentry->btree_opf = opClassDescPtr->FamilyId;
+ typentry->btree_opintype = opClassDescPtr->TypeId;
+ } else {
+ typentry->btree_opf = typentry->btree_opintype = InvalidOid;
+ }
+
+ /*
+ * Reset information derived from btree opclass. Note in particular
+ * that we'll redetermine the eq_opr even if we previously found one;
+ * this matters in case a btree opclass has been added to a type that
+ * previously had only a hash opclass.
+ */
+ typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
+ TCFLAGS_CHECKED_LT_OPR |
+ TCFLAGS_CHECKED_GT_OPR |
+ TCFLAGS_CHECKED_CMP_PROC);
+ typentry->flags |= TCFLAGS_CHECKED_BTREE_OPCLASS;
+ }
+
+ /*
+ * If we need to look up equality operator, and there's no btree opclass,
+ * force lookup of hash opclass.
+ */
+ if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
+ typentry->btree_opf == InvalidOid)
+ flags |= TYPECACHE_HASH_OPFAMILY;
+
+ if ((flags & (TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO |
+ TYPECACHE_HASH_EXTENDED_PROC |
+ TYPECACHE_HASH_EXTENDED_PROC_FINFO |
+ TYPECACHE_HASH_OPFAMILY)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
+ {
+ const auto opClassDescPtr = NYql::NPg::LookupDefaultOpClass(NYql::NPg::EOpClassMethod::Hash, type_id);
+
+ if (opClassDescPtr != nullptr) {
+ typentry->hash_opf = opClassDescPtr->FamilyId;
+ typentry->hash_opintype = opClassDescPtr->TypeId;
+ } else {
+ typentry->hash_opf = typentry->hash_opintype = InvalidOid;
+ }
+
+ /*
+ * Reset information derived from hash opclass. We do *not* reset the
+ * eq_opr; if we already found one from the btree opclass, that
+ * decision is still good.
+ */
+ typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
+ TCFLAGS_CHECKED_HASH_EXTENDED_PROC);
+ typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
+ }
+
+ /*
+ * Look for requested operators and functions, if we haven't already.
+ */
+ if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
+ {
+ ui32 eq_opr = InvalidOid;
+
+ if (typentry->btree_opf != InvalidOid) {
+ eq_opr = get_opfamily_member(typentry->btree_opf,
+ typentry->btree_opintype,
+ typentry->btree_opintype,
+ BTEqualStrategyNumber);
+ }
+
+ if (eq_opr == InvalidOid &&
+ typentry->hash_opf != InvalidOid) {
+ eq_opr = get_opfamily_member(typentry->hash_opf,
+ typentry->hash_opintype,
+ typentry->hash_opintype,
+ HTEqualStrategyNumber);
+ }
+
+ /*
+ * If the proposed equality operator is array_eq or record_eq, check
+ * to see if the element type or column types support equality. If
+ * not, array_eq or record_eq would fail at runtime, so we don't want
+ * to report that the type has equality. (We can omit similar
+ * checking for ranges and multiranges because ranges can't be created
+ * in the first place unless their subtypes support equality.)
+ */
+ if (eq_opr == ARRAY_EQ_OP &&
+ !array_element_has_equality(typentry))
+ eq_opr = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (eq_opr == RECORD_EQ_OP /* &&
+ !record_fields_have_equality(typentry) */)
+ eq_opr = InvalidOid;
+
+ /* Force update of eq_opr_finfo only if we're changing state */
+ if (typentry->eq_opr != eq_opr)
+ typentry->eq_opr_finfo.fn_oid = InvalidOid;
+
+ typentry->eq_opr = eq_opr;
+
+ /*
+ * Reset info about hash functions whenever we pick up new info about
+ * equality operator. This is so we can ensure that the hash
+ * functions match the operator.
+ */
+ typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
+ TCFLAGS_CHECKED_HASH_EXTENDED_PROC);
+ typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
+ }
+
+ if ((flags & TYPECACHE_LT_OPR) &&
+ !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
+ {
+ ui32 lt_opr = InvalidOid;
+
+ if (typentry->btree_opf != InvalidOid) {
+ lt_opr = get_opfamily_member(typentry->btree_opf,
+ typentry->btree_opintype,
+ typentry->btree_opintype,
+ BTLessStrategyNumber);
+ }
+
+ /*
+ * As above, make sure array_cmp or record_cmp will succeed; but again
+ * we need no special check for ranges or multiranges.
+ */
+ if (lt_opr == ARRAY_LT_OP &&
+ !array_element_has_compare(typentry))
+ lt_opr = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (lt_opr == RECORD_LT_OP /* &&
+ !record_fields_have_compare(typentry) */)
+ lt_opr = InvalidOid;
+
+ typentry->lt_opr = lt_opr;
+ typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
+ }
+
+ if ((flags & TYPECACHE_GT_OPR) &&
+ !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
+ {
+ ui32 gt_opr = InvalidOid;
+
+ if (typentry->btree_opf != InvalidOid) {
+ gt_opr = get_opfamily_member(typentry->btree_opf,
+ typentry->btree_opintype,
+ typentry->btree_opintype,
+ BTGreaterStrategyNumber);
+ }
+
+ /*
+ * As above, make sure array_cmp or record_cmp will succeed; but again
+ * we need no special check for ranges or multiranges.
+ */
+ if (gt_opr == ARRAY_GT_OP &&
+ !array_element_has_compare(typentry))
+ gt_opr = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (gt_opr == RECORD_GT_OP /* &&
+ !record_fields_have_compare(typentry) */)
+ gt_opr = InvalidOid;
+
+ typentry->gt_opr = gt_opr;
+ typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
+ }
+
+ if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
+ {
+ Oid cmp_proc = InvalidOid;
+
+ if (typentry->btree_opf != InvalidOid)
+ cmp_proc = get_opfamily_proc(typentry->btree_opf,
+ typentry->btree_opintype,
+ typentry->btree_opintype,
+ BTORDER_PROC);
+
+ /*
+ * As above, make sure array_cmp or record_cmp will succeed; but again
+ * we need no special check for ranges or multiranges.
+ */
+ if (cmp_proc == F_BTARRAYCMP &&
+ !array_element_has_compare(typentry))
+ cmp_proc = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (cmp_proc == F_BTRECORDCMP /* &&
+ !record_fields_have_compare(typentry) */)
+ cmp_proc = InvalidOid;
+
+ /* Force update of cmp_proc_finfo only if we're changing state */
+ if (typentry->cmp_proc != cmp_proc)
+ typentry->cmp_proc_finfo.fn_oid = InvalidOid;
+
+ typentry->cmp_proc = cmp_proc;
+ typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
+ }
+
+ if ((flags & (TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
+ {
+ Oid hash_proc = InvalidOid;
+
+ /*
+ * We insist that the eq_opr, if one has been determined, match the
+ * hash opclass; else report there is no hash function.
+ */
+ if (typentry->hash_opf != InvalidOid &&
+ (!OidIsValid(typentry->eq_opr) ||
+ typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
+ typentry->hash_opintype,
+ typentry->hash_opintype,
+ HTEqualStrategyNumber))) {
+ hash_proc = get_opfamily_proc(typentry->hash_opf,
+ typentry->hash_opintype,
+ typentry->hash_opintype,
+ HASHSTANDARD_PROC);
+ }
+
+ /*
+ * As above, make sure hash_array, hash_record, or hash_range will
+ * succeed.
+ */
+ if (hash_proc == F_HASH_ARRAY &&
+ !array_element_has_hashing(typentry))
+ hash_proc = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (hash_proc == F_HASH_RECORD /* &&
+ !record_fields_have_hashing(typentry) */)
+ hash_proc = InvalidOid;
+ // TODO: uncomment when YQL supports PG ranges
+ else if (hash_proc == F_HASH_RANGE /* &&
+ !range_element_has_hashing(typentry) */)
+ hash_proc = InvalidOid;
+
+ /*
+ * Likewise for hash_multirange.
+ */
+ // TODO: uncomment when YQL supports PG multiranges
+ if (hash_proc == F_HASH_MULTIRANGE /* &&
+ !multirange_element_has_hashing(typentry) */)
+ hash_proc = InvalidOid;
+
+ /* Force update of hash_proc_finfo only if we're changing state */
+ if (typentry->hash_proc != hash_proc)
+ typentry->hash_proc_finfo.fn_oid = InvalidOid;
+
+ typentry->hash_proc = hash_proc;
+ typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
+ }
+
+ if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
+ TYPECACHE_HASH_EXTENDED_PROC_FINFO)) &&
+ !(typentry->flags & TCFLAGS_CHECKED_HASH_EXTENDED_PROC))
+ {
+ Oid hash_extended_proc = InvalidOid;
+
+ /*
+ * We insist that the eq_opr, if one has been determined, match the
+ * hash opclass; else report there is no hash function.
+ */
+ if (typentry->hash_opf != InvalidOid &&
+ (!OidIsValid(typentry->eq_opr) ||
+ typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
+ typentry->hash_opintype,
+ typentry->hash_opintype,
+ HTEqualStrategyNumber)))
+ {
+ hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
+ typentry->hash_opintype,
+ typentry->hash_opintype,
+ HASHEXTENDED_PROC);
+ }
+
+ /*
+ * As above, make sure hash_array_extended, hash_record_extended, or
+ * hash_range_extended will succeed.
+ */
+ if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
+ !array_element_has_extended_hashing(typentry))
+ hash_extended_proc = InvalidOid;
+ // TODO: uncomment when YQL supports PG records
+ else if (hash_extended_proc == F_HASH_RECORD_EXTENDED /* &&
+ !record_fields_have_extended_hashing(typentry) */)
+ hash_extended_proc = InvalidOid;
+ // TODO: uncomment when YQL supports PG ranges
+ else if (hash_extended_proc == F_HASH_RANGE_EXTENDED /* &&
+ !range_element_has_extended_hashing(typentry) */)
+ hash_extended_proc = InvalidOid;
+
+ /*
+ * Likewise for hash_multirange_extended.
+ */
+ // TODO: uncomment when YQL supports PG multiranges
+ if (hash_extended_proc == F_HASH_MULTIRANGE_EXTENDED /* &&
+ !multirange_element_has_extended_hashing(typentry) */)
+ hash_extended_proc = InvalidOid;
+
+ /* Force update of proc finfo only if we're changing state */
+ if (typentry->hash_extended_proc != hash_extended_proc)
+ typentry->hash_extended_proc_finfo.fn_oid = InvalidOid;
+
+ typentry->hash_extended_proc = hash_extended_proc;
+ typentry->flags |= TCFLAGS_CHECKED_HASH_EXTENDED_PROC;
+ }
+
+ /*
+ * Set up fmgr lookup info as requested
+ *
+ * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
+ * which is not quite right (they're really in the hash table's private
+ * memory context) but this will do for our purposes.
+ */
+ if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
+ typentry->eq_opr_finfo.fn_oid == InvalidOid &&
+ typentry->eq_opr != InvalidOid)
+ {
+ ui32 eq_opr_func = get_opcode(typentry->eq_opr);
+ if (eq_opr_func != InvalidOid)
+ fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
+ CacheMemoryContext);
+ }
+
+ if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
+ typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
+ typentry->cmp_proc != InvalidOid)
+ {
+ fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
+ CacheMemoryContext);
+ }
+
+ if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
+ typentry->hash_proc_finfo.fn_oid == InvalidOid &&
+ typentry->hash_proc != InvalidOid)
+ {
+ fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
+ CacheMemoryContext);
+ }
+
+ if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
+ typentry->hash_extended_proc_finfo.fn_oid == InvalidOid &&
+ typentry->hash_extended_proc != InvalidOid)
+ {
+ fmgr_info_cxt(typentry->hash_extended_proc,
+ &typentry->hash_extended_proc_finfo,
+ CacheMemoryContext);
+ }
+
+ return typentry;
+}
+
+Oid
+get_base_element_type(Oid type_id) {
+ const auto& typeDesc = NYql::NPg::LookupType(type_id);
+
+ return (typeDesc.TypeSubscriptFuncId == F_ARRAY_SUBSCRIPT_HANDLER)
+ ? typeDesc.ElementTypeId
+ : InvalidOid;
+}
+
+Oid
+get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy) {
+ if (NYql::NPg::HasAmOp(opfamily, strategy, lefttype, righttype)) {
+ const auto &opDesc = NYql::NPg::LookupAmOp(opfamily, strategy, lefttype, righttype);
+ return opDesc.OperId;
+ }
+ return InvalidOid;
+}
+
+Oid
+get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum) {
+ if (NYql::NPg::HasAmProc(opfamily, procnum, lefttype, righttype)) {
+ const auto &procDesc = NYql::NPg::LookupAmProc(opfamily, procnum, lefttype, righttype);
+ return procDesc.ProcId;
+ }
+ return InvalidOid;
+}
+
+RegProcedure
+get_opcode(Oid opno)
+{
+ const auto& oprDesc = NYql::NPg::LookupOper(opno);
+ return oprDesc.ProcId;
+}
+
+void destroy_typecache_hashtable() {
+ hash_destroy(YQL_TypeCacheHash);
+ YQL_TypeCacheHash = nullptr;
+}
+
+}
+} \ No newline at end of file
diff --git a/ydb/library/yql/parser/pg_wrapper/type_cache.h b/ydb/library/yql/parser/pg_wrapper/type_cache.h
new file mode 100644
index 0000000000..d3b225cb6b
--- /dev/null
+++ b/ydb/library/yql/parser/pg_wrapper/type_cache.h
@@ -0,0 +1,24 @@
+#pragma once
+
+namespace NYql {
+
+// Private flag bits in the TypeCacheEntry.flags field
+constexpr ui32 TCFLAGS_HAVE_PG_TYPE_DATA = 0x000001;
+constexpr ui32 TCFLAGS_CHECKED_BTREE_OPCLASS = 0x000002;
+constexpr ui32 TCFLAGS_CHECKED_HASH_OPCLASS = 0x000004;
+constexpr ui32 TCFLAGS_CHECKED_EQ_OPR = 0x000008;
+constexpr ui32 TCFLAGS_CHECKED_LT_OPR = 0x000010;
+constexpr ui32 TCFLAGS_CHECKED_GT_OPR = 0x000020;
+constexpr ui32 TCFLAGS_CHECKED_CMP_PROC = 0x000040;
+constexpr ui32 TCFLAGS_CHECKED_HASH_PROC = 0x000080;
+constexpr ui32 TCFLAGS_CHECKED_HASH_EXTENDED_PROC = 0x000100;
+constexpr ui32 TCFLAGS_CHECKED_ELEM_PROPERTIES = 0x000200;
+constexpr ui32 TCFLAGS_HAVE_ELEM_EQUALITY = 0x000400;
+constexpr ui32 TCFLAGS_HAVE_ELEM_COMPARE = 0x000800;
+constexpr ui32 TCFLAGS_HAVE_ELEM_HASHING = 0x001000;
+constexpr ui32 TCFLAGS_HAVE_ELEM_EXTENDED_HASHING = 0x002000;
+
+// Copied from nbtree.h
+constexpr ui32 BTORDER_PROC = 1;
+
+}
diff --git a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.darwin.txt b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.darwin.txt
index cf6bc5596d..4c3ddfb126 100644
--- a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.darwin.txt
+++ b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.darwin.txt
@@ -13,6 +13,7 @@ target_compile_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
)
target_include_directories(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_wrapper-ut PUBLIC
contrib-libs-cxxsupp
@@ -35,6 +36,7 @@ target_link_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
target_sources(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/parser_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/sort_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/minikql/comp_nodes/ut/mkql_test_factory.cpp
)
add_test(
diff --git a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux-aarch64.txt b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux-aarch64.txt
index 94052d15f1..c0b3cba1cc 100644
--- a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux-aarch64.txt
+++ b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux-aarch64.txt
@@ -13,6 +13,7 @@ target_compile_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
)
target_include_directories(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_wrapper-ut PUBLIC
contrib-libs-linux-headers
@@ -40,6 +41,7 @@ target_link_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
target_sources(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/parser_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/sort_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/minikql/comp_nodes/ut/mkql_test_factory.cpp
)
add_test(
diff --git a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux.txt b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux.txt
index 08bcc2f954..9d8e7c0138 100644
--- a/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux.txt
+++ b/ydb/library/yql/parser/pg_wrapper/ut/CMakeLists.linux.txt
@@ -13,6 +13,7 @@ target_compile_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
)
target_include_directories(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/postgresql/src/include
)
target_link_libraries(ydb-library-yql-parser-pg_wrapper-ut PUBLIC
contrib-libs-linux-headers
@@ -42,6 +43,7 @@ target_link_options(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
target_sources(ydb-library-yql-parser-pg_wrapper-ut PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/parser_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/sort_ut.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/minikql/comp_nodes/ut/mkql_test_factory.cpp
)
add_test(
diff --git a/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp b/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp
new file mode 100644
index 0000000000..b73f51901e
--- /dev/null
+++ b/ydb/library/yql/parser/pg_wrapper/ut/type_cache_ut.cpp
@@ -0,0 +1,198 @@
+#include <library/cpp/testing/unittest/registar.h>
+#include <library/cpp/testing/hook/hook.h>
+
+// see pg_attribute_printf macro in c.h
+// should expand to nothing
+#undef __GNUC__
+#undef __IBMC__
+
+extern "C" {
+#include "postgres.h"
+#include "utils/typcache.h"
+
+#undef Min
+#undef Max
+
+#include <ydb/library/yql/parser/pg_wrapper/thread_inits.h>
+}
+
+#include "type_cache.h"
+
+using namespace ::NYql;
+
+Y_UNIT_TEST_SUITE(TLookupTypeCacheTests) {
+ // Defined in pg_type.dat
+ constexpr ui32 INT4_TYPEID = 23;
+ constexpr ui32 ANYARRAY_TYPEID = 2277;
+
+ TypeCacheEntry* cacheEntry = nullptr;
+
+ // We initialize a basic minimally initialized PG cache entry
+ // The tests then fill in various parts of it
+ Y_TEST_HOOK_BEFORE_RUN(InitTest) {
+ pg_thread_init();
+
+ cacheEntry = lookup_type_cache(INT4_TYPEID, 0);
+ }
+
+ Y_UNIT_TEST(TestEqOpr) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->eq_opr != InvalidOid);
+ UNIT_ASSERT(cacheEntry->eq_opr_finfo.fn_addr);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_EQ_OPR));
+ }
+
+ Y_UNIT_TEST(TestEqOprArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->eq_opr == InvalidOid);
+ UNIT_ASSERT(cacheEntry->eq_opr_finfo.fn_addr == nullptr);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_EQ_OPR));
+ }
+
+ Y_UNIT_TEST(TestLtOpr) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_LT_OPR);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->lt_opr != InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_LT_OPR));
+ }
+
+ Y_UNIT_TEST(TestLtOprArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_LT_OPR);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->lt_opr == InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_LT_OPR));
+ }
+
+ Y_UNIT_TEST(TestGtOpr) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_GT_OPR);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->gt_opr != InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_GT_OPR));
+ }
+
+ Y_UNIT_TEST(TestGtOprArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_GT_OPR);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->gt_opr == InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_GT_OPR));
+ }
+
+ Y_UNIT_TEST(TestCmpProc) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->cmp_proc != InvalidOid);
+ UNIT_ASSERT(cacheEntry->cmp_proc_finfo.fn_addr);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_CMP_PROC));
+ }
+
+ Y_UNIT_TEST(TestCmpProcArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->btree_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->btree_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->cmp_proc == InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_BTREE_OPCLASS | TCFLAGS_CHECKED_CMP_PROC));
+ }
+
+ Y_UNIT_TEST(TestHashProc) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->hash_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->hash_proc != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_proc_finfo.fn_addr);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_HASH_OPCLASS | TCFLAGS_CHECKED_HASH_PROC));
+ }
+
+ Y_UNIT_TEST(TestHashProcArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->hash_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->hash_proc == InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_HASH_OPCLASS | TCFLAGS_CHECKED_HASH_PROC));
+ }
+
+ Y_UNIT_TEST(TestHashExtendedProc) {
+ auto cacheEntry = lookup_type_cache(INT4_TYPEID, TYPECACHE_HASH_EXTENDED_PROC | TYPECACHE_HASH_EXTENDED_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->hash_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_opintype == INT4_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->hash_extended_proc != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_extended_proc_finfo.fn_addr);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_HASH_OPCLASS | TCFLAGS_CHECKED_HASH_EXTENDED_PROC));
+ }
+
+ Y_UNIT_TEST(TestHashExtendedProcArray) {
+ auto cacheEntry = lookup_type_cache(ANYARRAY_TYPEID, TYPECACHE_HASH_EXTENDED_PROC | TYPECACHE_HASH_EXTENDED_PROC_FINFO);
+
+ UNIT_ASSERT(cacheEntry);
+
+ UNIT_ASSERT(cacheEntry->hash_opf != InvalidOid);
+ UNIT_ASSERT(cacheEntry->hash_opintype == ANYARRAY_TYPEID);
+
+ UNIT_ASSERT(cacheEntry->hash_extended_proc == InvalidOid);
+
+ UNIT_ASSERT(cacheEntry->flags & (TCFLAGS_CHECKED_HASH_OPCLASS | TCFLAGS_CHECKED_HASH_EXTENDED_PROC));
+ }
+}