From 4dc99e27793565fafa780e93431411de34fe7018 Mon Sep 17 00:00:00 2001 From: sandynz Date: Sun, 26 Jul 2020 23:32:40 +0800 Subject: [PATCH 1/3] Support PostgreSQL array type (#6408) --- .../PostgreSQLColumnTypeNameOidMappings.java | 475 ++++++++++++++++++ .../query/PostgreSQLColumnDescription.java | 23 +- .../infra/executor/sql/QueryResult.java | 10 +- .../jdbc/queryresult/MemoryQueryResult.java | 7 +- .../jdbc/queryresult/StreamQueryResult.java | 7 +- .../bind/PostgreSQLComBindExecutor.java | 6 +- .../text/PostgreSQLComQueryExecutor.java | 6 +- 7 files changed, 527 insertions(+), 7 deletions(-) create mode 100644 shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java new file mode 100644 index 0000000000000..6ad11f22e62d4 --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java @@ -0,0 +1,475 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.db.protocol.postgresql.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * Column type name and oid mappings. + */ +public class PostgreSQLColumnTypeNameOidMappings { + + // Data from PostgreSQL 12.3, by executing following sql: + // SELECT t.typname, t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid; + + // Hundred lines of map.put doesn't satisfy checkstyle rules: JavaNCSS, ExecutableStatementCount. So use string to parse. + private static final String ORIGINAL_RECORD_LINES = + "bool\t16\n" + + "bytea\t17\n" + + "char\t18\n" + + "name\t19\n" + + "int8\t20\n" + + "int2\t21\n" + + "int2vector\t22\n" + + "int4\t23\n" + + "regproc\t24\n" + + "text\t25\n" + + "oid\t26\n" + + "tid\t27\n" + + "xid\t28\n" + + "cid\t29\n" + + "oidvector\t30\n" + + "pg_type\t71\n" + + "pg_attribute\t75\n" + + "pg_proc\t81\n" + + "pg_class\t83\n" + + "json\t114\n" + + "xml\t142\n" + + "pg_node_tree\t194\n" + + "pg_ndistinct\t3361\n" + + "pg_dependencies\t3402\n" + + "pg_mcv_list\t5017\n" + + "pg_ddl_command\t32\n" + + "point\t600\n" + + "lseg\t601\n" + + "path\t602\n" + + "box\t603\n" + + "polygon\t604\n" + + "line\t628\n" + + "float4\t700\n" + + "float8\t701\n" + + "unknown\t705\n" + + "circle\t718\n" + + "money\t790\n" + + "macaddr\t829\n" + + "inet\t869\n" + + "cidr\t650\n" + + "macaddr8\t774\n" + + "aclitem\t1033\n" + + "bpchar\t1042\n" + + "varchar\t1043\n" + + "date\t1082\n" + + "time\t1083\n" + + "timestamp\t1114\n" + + "timestamptz\t1184\n" + + "interval\t1186\n" + + "timetz\t1266\n" + + "bit\t1560\n" + + "varbit\t1562\n" + + "numeric\t1700\n" + + "refcursor\t1790\n" + + "regprocedure\t2202\n" + + "regoper\t2203\n" + + "regoperator\t2204\n" + + "regclass\t2205\n" + + "regtype\t2206\n" + + "regrole\t4096\n" + + "regnamespace\t4089\n" + + "uuid\t2950\n" + + "pg_lsn\t3220\n" + + "tsvector\t3614\n" + + "gtsvector\t3642\n" + + "tsquery\t3615\n" + + "regconfig\t3734\n" + + "regdictionary\t3769\n" + + "jsonb\t3802\n" + + "jsonpath\t4072\n" + + "txid_snapshot\t2970\n" + + "int4range\t3904\n" + + "numrange\t3906\n" + + "tsrange\t3908\n" + + "tstzrange\t3910\n" + + "daterange\t3912\n" + + "int8range\t3926\n" + + "record\t2249\n" + + "_record\t2287\n" + + "cstring\t2275\n" + + "any\t2276\n" + + "anyarray\t2277\n" + + "void\t2278\n" + + "trigger\t2279\n" + + "event_trigger\t3838\n" + + "language_handler\t2280\n" + + "internal\t2281\n" + + "opaque\t2282\n" + + "anyelement\t2283\n" + + "anynonarray\t2776\n" + + "anyenum\t3500\n" + + "fdw_handler\t3115\n" + + "index_am_handler\t325\n" + + "tsm_handler\t3310\n" + + "table_am_handler\t269\n" + + "anyrange\t3831\n" + + "_bool\t1000\n" + + "_bytea\t1001\n" + + "_char\t1002\n" + + "_name\t1003\n" + + "_int8\t1016\n" + + "_int2\t1005\n" + + "_int2vector\t1006\n" + + "_int4\t1007\n" + + "_regproc\t1008\n" + + "_text\t1009\n" + + "_oid\t1028\n" + + "_tid\t1010\n" + + "_xid\t1011\n" + + "_cid\t1012\n" + + "_oidvector\t1013\n" + + "_json\t199\n" + + "_xml\t143\n" + + "_point\t1017\n" + + "_lseg\t1018\n" + + "_path\t1019\n" + + "_box\t1020\n" + + "_polygon\t1027\n" + + "_line\t629\n" + + "_float4\t1021\n" + + "_float8\t1022\n" + + "_circle\t719\n" + + "_money\t791\n" + + "_macaddr\t1040\n" + + "_inet\t1041\n" + + "_cidr\t651\n" + + "_macaddr8\t775\n" + + "_aclitem\t1034\n" + + "_bpchar\t1014\n" + + "_varchar\t1015\n" + + "_date\t1182\n" + + "_time\t1183\n" + + "_timestamp\t1115\n" + + "_timestamptz\t1185\n" + + "_interval\t1187\n" + + "_timetz\t1270\n" + + "_bit\t1561\n" + + "_varbit\t1563\n" + + "_numeric\t1231\n" + + "_refcursor\t2201\n" + + "_regprocedure\t2207\n" + + "_regoper\t2208\n" + + "_regoperator\t2209\n" + + "_regclass\t2210\n" + + "_regtype\t2211\n" + + "_regrole\t4097\n" + + "_regnamespace\t4090\n" + + "_uuid\t2951\n" + + "_pg_lsn\t3221\n" + + "_tsvector\t3643\n" + + "_gtsvector\t3644\n" + + "_tsquery\t3645\n" + + "_regconfig\t3735\n" + + "_regdictionary\t3770\n" + + "_jsonb\t3807\n" + + "_jsonpath\t4073\n" + + "_txid_snapshot\t2949\n" + + "_int4range\t3905\n" + + "_numrange\t3907\n" + + "_tsrange\t3909\n" + + "_tstzrange\t3911\n" + + "_daterange\t3913\n" + + "_int8range\t3927\n" + + "_cstring\t1263\n" + + "pg_attrdef\t12000\n" + + "pg_constraint\t12001\n" + + "pg_inherits\t12002\n" + + "pg_index\t12003\n" + + "pg_operator\t12004\n" + + "pg_opfamily\t12005\n" + + "pg_opclass\t12006\n" + + "pg_am\t12007\n" + + "pg_amop\t12008\n" + + "pg_amproc\t12009\n" + + "pg_language\t12010\n" + + "pg_largeobject_metadata\t12011\n" + + "pg_largeobject\t12012\n" + + "pg_aggregate\t12013\n" + + "pg_statistic_ext\t12014\n" + + "pg_statistic_ext_data\t12015\n" + + "pg_statistic\t12016\n" + + "pg_rewrite\t12017\n" + + "pg_trigger\t12018\n" + + "pg_event_trigger\t12019\n" + + "pg_description\t12020\n" + + "pg_cast\t12021\n" + + "pg_enum\t12022\n" + + "pg_namespace\t12023\n" + + "pg_conversion\t12024\n" + + "pg_depend\t12025\n" + + "pg_database\t1248\n" + + "pg_db_role_setting\t12026\n" + + "pg_tablespace\t12027\n" + + "pg_pltemplate\t12028\n" + + "pg_authid\t2842\n" + + "pg_auth_members\t2843\n" + + "pg_shdepend\t12029\n" + + "pg_shdescription\t12030\n" + + "pg_ts_config\t12031\n" + + "pg_ts_config_map\t12032\n" + + "pg_ts_dict\t12033\n" + + "pg_ts_parser\t12034\n" + + "pg_ts_template\t12035\n" + + "pg_extension\t12036\n" + + "pg_foreign_data_wrapper\t12037\n" + + "pg_foreign_server\t12038\n" + + "pg_user_mapping\t12039\n" + + "pg_foreign_table\t12040\n" + + "pg_policy\t12041\n" + + "pg_replication_origin\t12042\n" + + "pg_default_acl\t12043\n" + + "pg_init_privs\t12044\n" + + "pg_seclabel\t12045\n" + + "pg_shseclabel\t4066\n" + + "pg_collation\t12046\n" + + "pg_partitioned_table\t12047\n" + + "pg_range\t12048\n" + + "pg_transform\t12049\n" + + "pg_sequence\t12050\n" + + "pg_publication\t12051\n" + + "pg_publication_rel\t12052\n" + + "pg_subscription\t6101\n" + + "pg_subscription_rel\t12053\n" + + "pg_toast_2600\t12054\n" + + "pg_toast_2604\t12055\n" + + "pg_toast_3456\t12056\n" + + "pg_toast_2606\t12057\n" + + "pg_toast_826\t12058\n" + + "pg_toast_2609\t12059\n" + + "pg_toast_3466\t12060\n" + + "pg_toast_3079\t12061\n" + + "pg_toast_2328\t12062\n" + + "pg_toast_1417\t12063\n" + + "pg_toast_3118\t12064\n" + + "pg_toast_3394\t12065\n" + + "pg_toast_2612\t12066\n" + + "pg_toast_2615\t12067\n" + + "pg_toast_3350\t12068\n" + + "pg_toast_3256\t12069\n" + + "pg_toast_1255\t12070\n" + + "pg_toast_2618\t12071\n" + + "pg_toast_3596\t12072\n" + + "pg_toast_2619\t12073\n" + + "pg_toast_3381\t12074\n" + + "pg_toast_3429\t12075\n" + + "pg_toast_2620\t12076\n" + + "pg_toast_3600\t12077\n" + + "pg_toast_1247\t12078\n" + + "pg_toast_1418\t12079\n" + + "pg_toast_1260\t12080\n" + + "pg_toast_1262\t12081\n" + + "pg_toast_2964\t12082\n" + + "pg_toast_1136\t12083\n" + + "pg_toast_6000\t12084\n" + + "pg_toast_2396\t12085\n" + + "pg_toast_3592\t12086\n" + + "pg_toast_6100\t12087\n" + + "pg_toast_1213\t12088\n" + + "pg_roles\t12090\n" + + "pg_shadow\t12094\n" + + "pg_group\t12098\n" + + "pg_user\t12101\n" + + "pg_policies\t12104\n" + + "pg_rules\t12108\n" + + "pg_views\t12112\n" + + "pg_tables\t12116\n" + + "pg_matviews\t12120\n" + + "pg_indexes\t12124\n" + + "pg_sequences\t12128\n" + + "pg_stats\t12132\n" + + "pg_stats_ext\t12136\n" + + "pg_publication_tables\t12140\n" + + "pg_locks\t12144\n" + + "pg_cursors\t12147\n" + + "pg_available_extensions\t12150\n" + + "pg_available_extension_versions\t12153\n" + + "pg_prepared_xacts\t12156\n" + + "pg_prepared_statements\t12160\n" + + "pg_seclabels\t12163\n" + + "pg_settings\t12167\n" + + "pg_file_settings\t12172\n" + + "pg_hba_file_rules\t12175\n" + + "pg_timezone_abbrevs\t12178\n" + + "pg_timezone_names\t12181\n" + + "pg_config\t12184\n" + + "pg_stat_all_tables\t12187\n" + + "pg_stat_xact_all_tables\t12191\n" + + "pg_stat_sys_tables\t12195\n" + + "pg_stat_xact_sys_tables\t12199\n" + + "pg_stat_user_tables\t12202\n" + + "pg_stat_xact_user_tables\t12206\n" + + "pg_statio_all_tables\t12209\n" + + "pg_statio_sys_tables\t12213\n" + + "pg_statio_user_tables\t12216\n" + + "pg_stat_all_indexes\t12219\n" + + "pg_stat_sys_indexes\t12223\n" + + "pg_stat_user_indexes\t12226\n" + + "pg_statio_all_indexes\t12229\n" + + "pg_statio_sys_indexes\t12233\n" + + "pg_statio_user_indexes\t12236\n" + + "pg_statio_all_sequences\t12239\n" + + "pg_statio_sys_sequences\t12243\n" + + "pg_statio_user_sequences\t12246\n" + + "pg_stat_activity\t12249\n" + + "pg_stat_replication\t12253\n" + + "pg_stat_wal_receiver\t12257\n" + + "pg_stat_subscription\t12260\n" + + "pg_stat_ssl\t12263\n" + + "pg_stat_gssapi\t12266\n" + + "pg_replication_slots\t12269\n" + + "pg_stat_database\t12273\n" + + "pg_stat_database_conflicts\t12277\n" + + "pg_stat_user_functions\t12280\n" + + "pg_stat_xact_user_functions\t12284\n" + + "pg_stat_archiver\t12288\n" + + "pg_stat_bgwriter\t12291\n" + + "pg_stat_progress_vacuum\t12294\n" + + "pg_stat_progress_cluster\t12298\n" + + "pg_stat_progress_create_index\t12302\n" + + "pg_user_mappings\t12306\n" + + "pg_replication_origin_status\t12310\n" + + "test_array\t16396\n" + + "_test_array\t16395\n" + + "pg_toast_16394\t16398\n" + + "cardinal_number\t13032\n" + + "_cardinal_number\t13031\n" + + "character_data\t13035\n" + + "_character_data\t13034\n" + + "sql_identifier\t13037\n" + + "_sql_identifier\t13036\n" + + "information_schema_catalog_name\t13039\n" + + "time_stamp\t13042\n" + + "_time_stamp\t13041\n" + + "yes_or_no\t13044\n" + + "_yes_or_no\t13043\n" + + "applicable_roles\t13047\n" + + "administrable_role_authorizations\t13051\n" + + "attributes\t13054\n" + + "character_sets\t13058\n" + + "check_constraint_routine_usage\t13062\n" + + "check_constraints\t13066\n" + + "collations\t13070\n" + + "collation_character_set_applicability\t13074\n" + + "column_column_usage\t13078\n" + + "column_domain_usage\t13082\n" + + "column_privileges\t13086\n" + + "column_udt_usage\t13090\n" + + "columns\t13094\n" + + "constraint_column_usage\t13098\n" + + "constraint_table_usage\t13102\n" + + "domain_constraints\t13106\n" + + "domain_udt_usage\t13110\n" + + "domains\t13114\n" + + "enabled_roles\t13118\n" + + "key_column_usage\t13121\n" + + "parameters\t13125\n" + + "referential_constraints\t13129\n" + + "role_column_grants\t13133\n" + + "routine_privileges\t13136\n" + + "role_routine_grants\t13140\n" + + "routines\t13143\n" + + "schemata\t13147\n" + + "sequences\t13150\n" + + "sql_features\t13154\n" + + "pg_toast_13153\t13156\n" + + "sql_implementation_info\t13159\n" + + "pg_toast_13158\t13161\n" + + "sql_languages\t13164\n" + + "pg_toast_13163\t13166\n" + + "sql_packages\t13169\n" + + "pg_toast_13168\t13171\n" + + "sql_parts\t13174\n" + + "pg_toast_13173\t13176\n" + + "sql_sizing\t13179\n" + + "pg_toast_13178\t13181\n" + + "sql_sizing_profiles\t13184\n" + + "pg_toast_13183\t13186\n" + + "table_constraints\t13189\n" + + "table_privileges\t13193\n" + + "role_table_grants\t13197\n" + + "tables\t13200\n" + + "transforms\t13204\n" + + "triggered_update_columns\t13208\n" + + "triggers\t13212\n" + + "udt_privileges\t13216\n" + + "role_udt_grants\t13220\n" + + "usage_privileges\t13223\n" + + "role_usage_grants\t13227\n" + + "user_defined_types\t13230\n" + + "view_column_usage\t13234\n" + + "view_routine_usage\t13238\n" + + "view_table_usage\t13242\n" + + "views\t13246\n" + + "data_type_privileges\t13250\n" + + "element_types\t13254\n" + + "_pg_foreign_table_columns\t13258\n" + + "column_options\t13262\n" + + "_pg_foreign_data_wrappers\t13265\n" + + "foreign_data_wrapper_options\t13268\n" + + "foreign_data_wrappers\t13271\n" + + "_pg_foreign_servers\t13274\n" + + "foreign_server_options\t13278\n" + + "foreign_servers\t13281\n" + + "_pg_foreign_tables\t13284\n" + + "foreign_table_options\t13288\n" + + "foreign_tables\t13291\n" + + "_pg_user_mappings\t13294\n" + + "user_mapping_options\t13298\n" + + "user_mappings\t13302\n" + + "array_tc_0\t16426\n" + + "_array_tc_0\t16425\n" + + "pg_toast_16424\t16428\n" + + "array_tc_1\t16434\n" + + "_array_tc_1\t16433\n" + + "pg_toast_16432\t16436"; + + private static final Map COLUMN_TYPE_NAME_OID_MAP; + + static { + Map map = new HashMap<>(1024, 0.5F); + for (String line : ORIGINAL_RECORD_LINES.split("\n")) { + String[] values = line.split("\t"); + map.put(values[0], Integer.parseInt(values[1])); + } + COLUMN_TYPE_NAME_OID_MAP = map; + } + + /** + * Get type oid by database-specific column type name. + * + * @param columnTypeName PostgreSQL column type name, e.g. int4 + * @return type oid, e.g. 23 for int4 + * @throws IllegalArgumentException if no type oid could be found + */ + public static int getTypeOidByColumnTypeName(final String columnTypeName) throws IllegalArgumentException { + Integer oid = COLUMN_TYPE_NAME_OID_MAP.get(columnTypeName); + if (oid == null) { + throw new IllegalArgumentException(String.format("Cannot find PostgreSQL type oid for columnTypeName '%s'", columnTypeName)); + } + return oid; + } + +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java index f8c703dc35e5d..244c3d43b4286 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java @@ -17,13 +17,20 @@ package org.apache.shardingsphere.db.protocol.postgresql.packet.command.query; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Types; +import java.util.concurrent.ThreadLocalRandom; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnType; +import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnTypeNameOidMappings; /** * Column description for PostgreSQL. */ @Getter +@Slf4j public final class PostgreSQLColumnDescription { private final String columnName; @@ -40,10 +47,22 @@ public final class PostgreSQLColumnDescription { private final int dataFormat = 0; - public PostgreSQLColumnDescription(final String columnName, final int columnIndex, final int columnType, final int columnLength) { + public PostgreSQLColumnDescription(final String columnName, final int columnIndex, final int columnType, final int columnLength, final ResultSetMetaData resultSetMetaData) { this.columnName = columnName; this.columnIndex = columnIndex; - this.typeOID = PostgreSQLColumnType.valueOfJDBCType(columnType).getValue(); + if (Types.ARRAY == columnType && resultSetMetaData != null) { + String columnTypeName = null; + try { + columnTypeName = resultSetMetaData.getColumnTypeName(columnIndex); + } catch (SQLException e) { + if (ThreadLocalRandom.current().nextInt(10) == 6) { + log.error("getColumnTypeName failed, columnName={}, columnIndex={}", columnName, columnIndex, e); + } + } + this.typeOID = PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName(columnTypeName); + } else { + this.typeOID = PostgreSQLColumnType.valueOfJDBCType(columnType).getValue(); + } this.columnLength = columnLength; } } diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java index 84822d46adef0..2c4fd1c4bdf00 100644 --- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java +++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java @@ -18,6 +18,7 @@ package org.apache.shardingsphere.infra.executor.sql; import java.io.InputStream; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.Calendar; @@ -25,7 +26,14 @@ * Query result form SQL. */ public interface QueryResult { - + + /** + * Get JDBC ResultSetMetaData. + * + * @return {@linkplain ResultSetMetaData} + */ + ResultSetMetaData getResultSetMetaData(); + /** * iterate next data. * diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/MemoryQueryResult.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/MemoryQueryResult.java index 2e621317bac24..35d4c26f047a4 100644 --- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/MemoryQueryResult.java +++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/MemoryQueryResult.java @@ -111,7 +111,12 @@ private Object getRowValue(final ResultSet resultSet, final int columnIndex) thr return resultSet.getObject(columnIndex); } } - + + @Override + public ResultSetMetaData getResultSetMetaData() { + return resultSetMetaData; + } + @Override public boolean next() { if (rows.hasNext()) { diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/StreamQueryResult.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/StreamQueryResult.java index 18e0aba8776c6..ee2e1e185c95a 100644 --- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/StreamQueryResult.java +++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/queryresult/StreamQueryResult.java @@ -44,7 +44,12 @@ public StreamQueryResult(final ResultSet resultSet) throws SQLException { resultSetMetaData = resultSet.getMetaData(); this.resultSet = resultSet; } - + + @Override + public ResultSetMetaData getResultSetMetaData() { + return resultSetMetaData; + } + @Override public boolean next() throws SQLException { return resultSet.next(); diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java index ea5ab519c5d58..667b16942b465 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java @@ -17,6 +17,7 @@ package org.apache.shardingsphere.proxy.frontend.postgresql.command.query.binary.bind; +import java.sql.ResultSetMetaData; import lombok.Getter; import org.apache.shardingsphere.db.protocol.packet.DatabasePacket; import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnType; @@ -29,6 +30,7 @@ import org.apache.shardingsphere.db.protocol.postgresql.packet.command.query.text.PostgreSQLDataRowPacket; import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLCommandCompletePacket; import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLErrorResponsePacket; +import org.apache.shardingsphere.infra.executor.sql.QueryResult; import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.query.QueryHeader; import org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngine; import org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngineFactory; @@ -117,9 +119,11 @@ private Optional createQueryPacket(final QueryRe private List getPostgreSQLColumnDescriptions(final QueryResponse queryResponse) { List result = new LinkedList<>(); + List queryResults = queryResponse.getQueryResults(); + ResultSetMetaData resultSetMetaData = queryResults.size() > 0 ? queryResults.get(0).getResultSetMetaData() : null; int columnIndex = 0; for (QueryHeader each : queryResponse.getQueryHeaders()) { - result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength())); + result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength(), resultSetMetaData)); } return result; } diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java index 9fc8db24d7aae..a6fabfff2d76f 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java @@ -17,6 +17,7 @@ package org.apache.shardingsphere.proxy.frontend.postgresql.command.query.text; +import java.sql.ResultSetMetaData; import lombok.Getter; import org.apache.shardingsphere.db.protocol.packet.DatabasePacket; import org.apache.shardingsphere.db.protocol.postgresql.packet.PostgreSQLPacket; @@ -27,6 +28,7 @@ import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLCommandCompletePacket; import org.apache.shardingsphere.db.protocol.postgresql.packet.generic.PostgreSQLErrorResponsePacket; import org.apache.shardingsphere.infra.database.type.DatabaseTypes; +import org.apache.shardingsphere.infra.executor.sql.QueryResult; import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.query.QueryHeader; import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection; import org.apache.shardingsphere.proxy.backend.response.BackendResponse; @@ -102,9 +104,11 @@ private Optional createQueryPacket(final QueryRe private List getPostgreSQLColumnDescriptions(final QueryResponse queryResponse) { List result = new LinkedList<>(); + List queryResults = queryResponse.getQueryResults(); + ResultSetMetaData resultSetMetaData = queryResults.size() > 0 ? queryResults.get(0).getResultSetMetaData() : null; int columnIndex = 0; for (QueryHeader each : queryResponse.getQueryHeaders()) { - result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength())); + result.add(new PostgreSQLColumnDescription(each.getColumnName(), ++columnIndex, each.getColumnType(), each.getColumnLength(), resultSetMetaData)); } return result; } From 323b78060a516aec1ff9bc87df17ea328086f84c Mon Sep 17 00:00:00 2001 From: sandynz Date: Mon, 27 Jul 2020 23:50:14 +0800 Subject: [PATCH 2/3] Support PostgreSQL array type, unit test (#6408) --- ...stgreSQLColumnTypeNameOidMappingsTest.java | 37 ++++++++++++++++ .../PostgreSQLColumnDescriptionTest.java | 43 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java create mode 100644 shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java new file mode 100644 index 0000000000000..1ff1a6677849a --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.db.protocol.postgresql.constant; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PostgreSQLColumnTypeNameOidMappingsTest { + + @Test + public void assertIntegerArrayGot() { + int columnTypeName = PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName("_int4"); + assertEquals(1007, columnTypeName); + } + + @Test(expected = IllegalArgumentException.class) + public void assertIllegalArgExThrown() { + PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName("not_exist_type"); + } + +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java new file mode 100644 index 0000000000000..d8ce85acc701e --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.db.protocol.postgresql.packet.command.query; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Types; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class PostgreSQLColumnDescriptionTest { + + @Test + public void assertIntegerTypeOid() { + PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("age", 1, Types.INTEGER, 4, null); + Assert.assertEquals(23, description.getTypeOID()); + } + + @Test + public void assertIntegerArrayTypeOid() throws SQLException { + ResultSetMetaData resultSetMetaData = Mockito.mock(ResultSetMetaData.class); + Mockito.when(resultSetMetaData.getColumnTypeName(2)).thenReturn("_int4"); + PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("ages", 2, Types.ARRAY, 12, resultSetMetaData); + Assert.assertEquals(1007, description.getTypeOID()); + } + +} From 183713f9f557cf6b057636756ca1099a44aaec20 Mon Sep 17 00:00:00 2001 From: sandynz Date: Tue, 28 Jul 2020 22:52:57 +0800 Subject: [PATCH 3/3] Support PostgreSQL array type, follow review suggestion (#6408) --- .../constant/PostgreSQLArrayColumnType.java | 135 +++++ .../PostgreSQLColumnTypeNameOidMappings.java | 475 ------------------ .../query/PostgreSQLColumnDescription.java | 13 +- ...ava => PostgreSQLArrayColumnTypeTest.java} | 11 +- .../PostgreSQLColumnDescriptionTest.java | 8 +- .../infra/executor/sql/QueryResult.java | 2 +- 6 files changed, 152 insertions(+), 492 deletions(-) create mode 100644 shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnType.java delete mode 100644 shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java rename shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/{PostgreSQLColumnTypeNameOidMappingsTest.java => PostgreSQLArrayColumnTypeTest.java} (75%) diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnType.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnType.java new file mode 100644 index 0000000000000..a535931504d42 --- /dev/null +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnType.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.db.protocol.postgresql.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * Array column types for PostgreSQL. + */ +public class PostgreSQLArrayColumnType { + + private static final String ORIGINAL_RECORD_LINES = + "_aclitem 1034\n" + + "_array_tc_0 16425\n" + + "_array_tc_1 16433\n" + + "_bit 1561\n" + + "_bool 1000\n" + + "_box 1020\n" + + "_bpchar 1014\n" + + "_bytea 1001\n" + + "_cardinal_number 13031\n" + + "_char 1002\n" + + "_character_data 13034\n" + + "_cid 1012\n" + + "_cidr 651\n" + + "_circle 719\n" + + "_cstring 1263\n" + + "_date 1182\n" + + "_daterange 3913\n" + + "_float4 1021\n" + + "_float8 1022\n" + + "_gtsvector 3644\n" + + "_inet 1041\n" + + "_int2 1005\n" + + "_int2vector 1006\n" + + "_int4 1007\n" + + "_int4range 3905\n" + + "_int8 1016\n" + + "_int8range 3927\n" + + "_interval 1187\n" + + "_json 199\n" + + "_jsonb 3807\n" + + "_jsonpath 4073\n" + + "_line 629\n" + + "_lseg 1018\n" + + "_macaddr 1040\n" + + "_macaddr8 775\n" + + "_money 791\n" + + "_name 1003\n" + + "_numeric 1231\n" + + "_numrange 3907\n" + + "_oid 1028\n" + + "_oidvector 1013\n" + + "_path 1019\n" + + "_pg_foreign_data_wrappers 13265\n" + + "_pg_foreign_servers 13274\n" + + "_pg_foreign_table_columns 13258\n" + + "_pg_foreign_tables 13284\n" + + "_pg_lsn 3221\n" + + "_pg_user_mappings 13294\n" + + "_point 1017\n" + + "_polygon 1027\n" + + "_record 2287\n" + + "_refcursor 2201\n" + + "_regclass 2210\n" + + "_regconfig 3735\n" + + "_regdictionary 3770\n" + + "_regnamespace 4090\n" + + "_regoper 2208\n" + + "_regoperator 2209\n" + + "_regproc 1008\n" + + "_regprocedure 2207\n" + + "_regrole 4097\n" + + "_regtype 2211\n" + + "_sql_identifier 13036\n" + + "_test_array 16395\n" + + "_text 1009\n" + + "_tid 1010\n" + + "_time 1183\n" + + "_time_stamp 13041\n" + + "_timestamp 1115\n" + + "_timestamptz 1185\n" + + "_timetz 1270\n" + + "_tsquery 3645\n" + + "_tsrange 3909\n" + + "_tstzrange 3911\n" + + "_tsvector 3643\n" + + "_txid_snapshot 2949\n" + + "_uuid 2951\n" + + "_varbit 1563\n" + + "_varchar 1015\n" + + "_xid 1011\n" + + "_xml 143\n" + + "_yes_or_no 13043"; + + private static final Map COLUMN_TYPE_NAME_OID_MAP = new HashMap<>(128, 1.0F); + + static { + for (String line : ORIGINAL_RECORD_LINES.split("\n")) { + String[] values = line.split(" "); + COLUMN_TYPE_NAME_OID_MAP.put(values[0], Integer.parseInt(values[1])); + } + } + + /** + * Get type oid by database-specific column type name. + * + * @param columnTypeName PostgreSQL column type name, e.g. int4 + * @return type oid, e.g. 23 for int4 + * @throws IllegalArgumentException if no type oid could be found + */ + public static int getTypeOidByColumnTypeName(final String columnTypeName) throws IllegalArgumentException { + if (COLUMN_TYPE_NAME_OID_MAP.containsKey(columnTypeName)) { + return COLUMN_TYPE_NAME_OID_MAP.get(columnTypeName); + } + throw new IllegalArgumentException(String.format("Cannot find PostgreSQL type oid for columnTypeName '%s'", columnTypeName)); + } + +} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java deleted file mode 100644 index 6ad11f22e62d4..0000000000000 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappings.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.shardingsphere.db.protocol.postgresql.constant; - -import java.util.HashMap; -import java.util.Map; - -/** - * Column type name and oid mappings. - */ -public class PostgreSQLColumnTypeNameOidMappings { - - // Data from PostgreSQL 12.3, by executing following sql: - // SELECT t.typname, t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid; - - // Hundred lines of map.put doesn't satisfy checkstyle rules: JavaNCSS, ExecutableStatementCount. So use string to parse. - private static final String ORIGINAL_RECORD_LINES = - "bool\t16\n" - + "bytea\t17\n" - + "char\t18\n" - + "name\t19\n" - + "int8\t20\n" - + "int2\t21\n" - + "int2vector\t22\n" - + "int4\t23\n" - + "regproc\t24\n" - + "text\t25\n" - + "oid\t26\n" - + "tid\t27\n" - + "xid\t28\n" - + "cid\t29\n" - + "oidvector\t30\n" - + "pg_type\t71\n" - + "pg_attribute\t75\n" - + "pg_proc\t81\n" - + "pg_class\t83\n" - + "json\t114\n" - + "xml\t142\n" - + "pg_node_tree\t194\n" - + "pg_ndistinct\t3361\n" - + "pg_dependencies\t3402\n" - + "pg_mcv_list\t5017\n" - + "pg_ddl_command\t32\n" - + "point\t600\n" - + "lseg\t601\n" - + "path\t602\n" - + "box\t603\n" - + "polygon\t604\n" - + "line\t628\n" - + "float4\t700\n" - + "float8\t701\n" - + "unknown\t705\n" - + "circle\t718\n" - + "money\t790\n" - + "macaddr\t829\n" - + "inet\t869\n" - + "cidr\t650\n" - + "macaddr8\t774\n" - + "aclitem\t1033\n" - + "bpchar\t1042\n" - + "varchar\t1043\n" - + "date\t1082\n" - + "time\t1083\n" - + "timestamp\t1114\n" - + "timestamptz\t1184\n" - + "interval\t1186\n" - + "timetz\t1266\n" - + "bit\t1560\n" - + "varbit\t1562\n" - + "numeric\t1700\n" - + "refcursor\t1790\n" - + "regprocedure\t2202\n" - + "regoper\t2203\n" - + "regoperator\t2204\n" - + "regclass\t2205\n" - + "regtype\t2206\n" - + "regrole\t4096\n" - + "regnamespace\t4089\n" - + "uuid\t2950\n" - + "pg_lsn\t3220\n" - + "tsvector\t3614\n" - + "gtsvector\t3642\n" - + "tsquery\t3615\n" - + "regconfig\t3734\n" - + "regdictionary\t3769\n" - + "jsonb\t3802\n" - + "jsonpath\t4072\n" - + "txid_snapshot\t2970\n" - + "int4range\t3904\n" - + "numrange\t3906\n" - + "tsrange\t3908\n" - + "tstzrange\t3910\n" - + "daterange\t3912\n" - + "int8range\t3926\n" - + "record\t2249\n" - + "_record\t2287\n" - + "cstring\t2275\n" - + "any\t2276\n" - + "anyarray\t2277\n" - + "void\t2278\n" - + "trigger\t2279\n" - + "event_trigger\t3838\n" - + "language_handler\t2280\n" - + "internal\t2281\n" - + "opaque\t2282\n" - + "anyelement\t2283\n" - + "anynonarray\t2776\n" - + "anyenum\t3500\n" - + "fdw_handler\t3115\n" - + "index_am_handler\t325\n" - + "tsm_handler\t3310\n" - + "table_am_handler\t269\n" - + "anyrange\t3831\n" - + "_bool\t1000\n" - + "_bytea\t1001\n" - + "_char\t1002\n" - + "_name\t1003\n" - + "_int8\t1016\n" - + "_int2\t1005\n" - + "_int2vector\t1006\n" - + "_int4\t1007\n" - + "_regproc\t1008\n" - + "_text\t1009\n" - + "_oid\t1028\n" - + "_tid\t1010\n" - + "_xid\t1011\n" - + "_cid\t1012\n" - + "_oidvector\t1013\n" - + "_json\t199\n" - + "_xml\t143\n" - + "_point\t1017\n" - + "_lseg\t1018\n" - + "_path\t1019\n" - + "_box\t1020\n" - + "_polygon\t1027\n" - + "_line\t629\n" - + "_float4\t1021\n" - + "_float8\t1022\n" - + "_circle\t719\n" - + "_money\t791\n" - + "_macaddr\t1040\n" - + "_inet\t1041\n" - + "_cidr\t651\n" - + "_macaddr8\t775\n" - + "_aclitem\t1034\n" - + "_bpchar\t1014\n" - + "_varchar\t1015\n" - + "_date\t1182\n" - + "_time\t1183\n" - + "_timestamp\t1115\n" - + "_timestamptz\t1185\n" - + "_interval\t1187\n" - + "_timetz\t1270\n" - + "_bit\t1561\n" - + "_varbit\t1563\n" - + "_numeric\t1231\n" - + "_refcursor\t2201\n" - + "_regprocedure\t2207\n" - + "_regoper\t2208\n" - + "_regoperator\t2209\n" - + "_regclass\t2210\n" - + "_regtype\t2211\n" - + "_regrole\t4097\n" - + "_regnamespace\t4090\n" - + "_uuid\t2951\n" - + "_pg_lsn\t3221\n" - + "_tsvector\t3643\n" - + "_gtsvector\t3644\n" - + "_tsquery\t3645\n" - + "_regconfig\t3735\n" - + "_regdictionary\t3770\n" - + "_jsonb\t3807\n" - + "_jsonpath\t4073\n" - + "_txid_snapshot\t2949\n" - + "_int4range\t3905\n" - + "_numrange\t3907\n" - + "_tsrange\t3909\n" - + "_tstzrange\t3911\n" - + "_daterange\t3913\n" - + "_int8range\t3927\n" - + "_cstring\t1263\n" - + "pg_attrdef\t12000\n" - + "pg_constraint\t12001\n" - + "pg_inherits\t12002\n" - + "pg_index\t12003\n" - + "pg_operator\t12004\n" - + "pg_opfamily\t12005\n" - + "pg_opclass\t12006\n" - + "pg_am\t12007\n" - + "pg_amop\t12008\n" - + "pg_amproc\t12009\n" - + "pg_language\t12010\n" - + "pg_largeobject_metadata\t12011\n" - + "pg_largeobject\t12012\n" - + "pg_aggregate\t12013\n" - + "pg_statistic_ext\t12014\n" - + "pg_statistic_ext_data\t12015\n" - + "pg_statistic\t12016\n" - + "pg_rewrite\t12017\n" - + "pg_trigger\t12018\n" - + "pg_event_trigger\t12019\n" - + "pg_description\t12020\n" - + "pg_cast\t12021\n" - + "pg_enum\t12022\n" - + "pg_namespace\t12023\n" - + "pg_conversion\t12024\n" - + "pg_depend\t12025\n" - + "pg_database\t1248\n" - + "pg_db_role_setting\t12026\n" - + "pg_tablespace\t12027\n" - + "pg_pltemplate\t12028\n" - + "pg_authid\t2842\n" - + "pg_auth_members\t2843\n" - + "pg_shdepend\t12029\n" - + "pg_shdescription\t12030\n" - + "pg_ts_config\t12031\n" - + "pg_ts_config_map\t12032\n" - + "pg_ts_dict\t12033\n" - + "pg_ts_parser\t12034\n" - + "pg_ts_template\t12035\n" - + "pg_extension\t12036\n" - + "pg_foreign_data_wrapper\t12037\n" - + "pg_foreign_server\t12038\n" - + "pg_user_mapping\t12039\n" - + "pg_foreign_table\t12040\n" - + "pg_policy\t12041\n" - + "pg_replication_origin\t12042\n" - + "pg_default_acl\t12043\n" - + "pg_init_privs\t12044\n" - + "pg_seclabel\t12045\n" - + "pg_shseclabel\t4066\n" - + "pg_collation\t12046\n" - + "pg_partitioned_table\t12047\n" - + "pg_range\t12048\n" - + "pg_transform\t12049\n" - + "pg_sequence\t12050\n" - + "pg_publication\t12051\n" - + "pg_publication_rel\t12052\n" - + "pg_subscription\t6101\n" - + "pg_subscription_rel\t12053\n" - + "pg_toast_2600\t12054\n" - + "pg_toast_2604\t12055\n" - + "pg_toast_3456\t12056\n" - + "pg_toast_2606\t12057\n" - + "pg_toast_826\t12058\n" - + "pg_toast_2609\t12059\n" - + "pg_toast_3466\t12060\n" - + "pg_toast_3079\t12061\n" - + "pg_toast_2328\t12062\n" - + "pg_toast_1417\t12063\n" - + "pg_toast_3118\t12064\n" - + "pg_toast_3394\t12065\n" - + "pg_toast_2612\t12066\n" - + "pg_toast_2615\t12067\n" - + "pg_toast_3350\t12068\n" - + "pg_toast_3256\t12069\n" - + "pg_toast_1255\t12070\n" - + "pg_toast_2618\t12071\n" - + "pg_toast_3596\t12072\n" - + "pg_toast_2619\t12073\n" - + "pg_toast_3381\t12074\n" - + "pg_toast_3429\t12075\n" - + "pg_toast_2620\t12076\n" - + "pg_toast_3600\t12077\n" - + "pg_toast_1247\t12078\n" - + "pg_toast_1418\t12079\n" - + "pg_toast_1260\t12080\n" - + "pg_toast_1262\t12081\n" - + "pg_toast_2964\t12082\n" - + "pg_toast_1136\t12083\n" - + "pg_toast_6000\t12084\n" - + "pg_toast_2396\t12085\n" - + "pg_toast_3592\t12086\n" - + "pg_toast_6100\t12087\n" - + "pg_toast_1213\t12088\n" - + "pg_roles\t12090\n" - + "pg_shadow\t12094\n" - + "pg_group\t12098\n" - + "pg_user\t12101\n" - + "pg_policies\t12104\n" - + "pg_rules\t12108\n" - + "pg_views\t12112\n" - + "pg_tables\t12116\n" - + "pg_matviews\t12120\n" - + "pg_indexes\t12124\n" - + "pg_sequences\t12128\n" - + "pg_stats\t12132\n" - + "pg_stats_ext\t12136\n" - + "pg_publication_tables\t12140\n" - + "pg_locks\t12144\n" - + "pg_cursors\t12147\n" - + "pg_available_extensions\t12150\n" - + "pg_available_extension_versions\t12153\n" - + "pg_prepared_xacts\t12156\n" - + "pg_prepared_statements\t12160\n" - + "pg_seclabels\t12163\n" - + "pg_settings\t12167\n" - + "pg_file_settings\t12172\n" - + "pg_hba_file_rules\t12175\n" - + "pg_timezone_abbrevs\t12178\n" - + "pg_timezone_names\t12181\n" - + "pg_config\t12184\n" - + "pg_stat_all_tables\t12187\n" - + "pg_stat_xact_all_tables\t12191\n" - + "pg_stat_sys_tables\t12195\n" - + "pg_stat_xact_sys_tables\t12199\n" - + "pg_stat_user_tables\t12202\n" - + "pg_stat_xact_user_tables\t12206\n" - + "pg_statio_all_tables\t12209\n" - + "pg_statio_sys_tables\t12213\n" - + "pg_statio_user_tables\t12216\n" - + "pg_stat_all_indexes\t12219\n" - + "pg_stat_sys_indexes\t12223\n" - + "pg_stat_user_indexes\t12226\n" - + "pg_statio_all_indexes\t12229\n" - + "pg_statio_sys_indexes\t12233\n" - + "pg_statio_user_indexes\t12236\n" - + "pg_statio_all_sequences\t12239\n" - + "pg_statio_sys_sequences\t12243\n" - + "pg_statio_user_sequences\t12246\n" - + "pg_stat_activity\t12249\n" - + "pg_stat_replication\t12253\n" - + "pg_stat_wal_receiver\t12257\n" - + "pg_stat_subscription\t12260\n" - + "pg_stat_ssl\t12263\n" - + "pg_stat_gssapi\t12266\n" - + "pg_replication_slots\t12269\n" - + "pg_stat_database\t12273\n" - + "pg_stat_database_conflicts\t12277\n" - + "pg_stat_user_functions\t12280\n" - + "pg_stat_xact_user_functions\t12284\n" - + "pg_stat_archiver\t12288\n" - + "pg_stat_bgwriter\t12291\n" - + "pg_stat_progress_vacuum\t12294\n" - + "pg_stat_progress_cluster\t12298\n" - + "pg_stat_progress_create_index\t12302\n" - + "pg_user_mappings\t12306\n" - + "pg_replication_origin_status\t12310\n" - + "test_array\t16396\n" - + "_test_array\t16395\n" - + "pg_toast_16394\t16398\n" - + "cardinal_number\t13032\n" - + "_cardinal_number\t13031\n" - + "character_data\t13035\n" - + "_character_data\t13034\n" - + "sql_identifier\t13037\n" - + "_sql_identifier\t13036\n" - + "information_schema_catalog_name\t13039\n" - + "time_stamp\t13042\n" - + "_time_stamp\t13041\n" - + "yes_or_no\t13044\n" - + "_yes_or_no\t13043\n" - + "applicable_roles\t13047\n" - + "administrable_role_authorizations\t13051\n" - + "attributes\t13054\n" - + "character_sets\t13058\n" - + "check_constraint_routine_usage\t13062\n" - + "check_constraints\t13066\n" - + "collations\t13070\n" - + "collation_character_set_applicability\t13074\n" - + "column_column_usage\t13078\n" - + "column_domain_usage\t13082\n" - + "column_privileges\t13086\n" - + "column_udt_usage\t13090\n" - + "columns\t13094\n" - + "constraint_column_usage\t13098\n" - + "constraint_table_usage\t13102\n" - + "domain_constraints\t13106\n" - + "domain_udt_usage\t13110\n" - + "domains\t13114\n" - + "enabled_roles\t13118\n" - + "key_column_usage\t13121\n" - + "parameters\t13125\n" - + "referential_constraints\t13129\n" - + "role_column_grants\t13133\n" - + "routine_privileges\t13136\n" - + "role_routine_grants\t13140\n" - + "routines\t13143\n" - + "schemata\t13147\n" - + "sequences\t13150\n" - + "sql_features\t13154\n" - + "pg_toast_13153\t13156\n" - + "sql_implementation_info\t13159\n" - + "pg_toast_13158\t13161\n" - + "sql_languages\t13164\n" - + "pg_toast_13163\t13166\n" - + "sql_packages\t13169\n" - + "pg_toast_13168\t13171\n" - + "sql_parts\t13174\n" - + "pg_toast_13173\t13176\n" - + "sql_sizing\t13179\n" - + "pg_toast_13178\t13181\n" - + "sql_sizing_profiles\t13184\n" - + "pg_toast_13183\t13186\n" - + "table_constraints\t13189\n" - + "table_privileges\t13193\n" - + "role_table_grants\t13197\n" - + "tables\t13200\n" - + "transforms\t13204\n" - + "triggered_update_columns\t13208\n" - + "triggers\t13212\n" - + "udt_privileges\t13216\n" - + "role_udt_grants\t13220\n" - + "usage_privileges\t13223\n" - + "role_usage_grants\t13227\n" - + "user_defined_types\t13230\n" - + "view_column_usage\t13234\n" - + "view_routine_usage\t13238\n" - + "view_table_usage\t13242\n" - + "views\t13246\n" - + "data_type_privileges\t13250\n" - + "element_types\t13254\n" - + "_pg_foreign_table_columns\t13258\n" - + "column_options\t13262\n" - + "_pg_foreign_data_wrappers\t13265\n" - + "foreign_data_wrapper_options\t13268\n" - + "foreign_data_wrappers\t13271\n" - + "_pg_foreign_servers\t13274\n" - + "foreign_server_options\t13278\n" - + "foreign_servers\t13281\n" - + "_pg_foreign_tables\t13284\n" - + "foreign_table_options\t13288\n" - + "foreign_tables\t13291\n" - + "_pg_user_mappings\t13294\n" - + "user_mapping_options\t13298\n" - + "user_mappings\t13302\n" - + "array_tc_0\t16426\n" - + "_array_tc_0\t16425\n" - + "pg_toast_16424\t16428\n" - + "array_tc_1\t16434\n" - + "_array_tc_1\t16433\n" - + "pg_toast_16432\t16436"; - - private static final Map COLUMN_TYPE_NAME_OID_MAP; - - static { - Map map = new HashMap<>(1024, 0.5F); - for (String line : ORIGINAL_RECORD_LINES.split("\n")) { - String[] values = line.split("\t"); - map.put(values[0], Integer.parseInt(values[1])); - } - COLUMN_TYPE_NAME_OID_MAP = map; - } - - /** - * Get type oid by database-specific column type name. - * - * @param columnTypeName PostgreSQL column type name, e.g. int4 - * @return type oid, e.g. 23 for int4 - * @throws IllegalArgumentException if no type oid could be found - */ - public static int getTypeOidByColumnTypeName(final String columnTypeName) throws IllegalArgumentException { - Integer oid = COLUMN_TYPE_NAME_OID_MAP.get(columnTypeName); - if (oid == null) { - throw new IllegalArgumentException(String.format("Cannot find PostgreSQL type oid for columnTypeName '%s'", columnTypeName)); - } - return oid; - } - -} diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java index 244c3d43b4286..7259ac456a9ae 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescription.java @@ -20,11 +20,10 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; -import java.util.concurrent.ThreadLocalRandom; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLArrayColumnType; import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnType; -import org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLColumnTypeNameOidMappings; /** * Column description for PostgreSQL. @@ -50,16 +49,14 @@ public final class PostgreSQLColumnDescription { public PostgreSQLColumnDescription(final String columnName, final int columnIndex, final int columnType, final int columnLength, final ResultSetMetaData resultSetMetaData) { this.columnName = columnName; this.columnIndex = columnIndex; - if (Types.ARRAY == columnType && resultSetMetaData != null) { + if (Types.ARRAY == columnType && null != resultSetMetaData) { String columnTypeName = null; try { columnTypeName = resultSetMetaData.getColumnTypeName(columnIndex); - } catch (SQLException e) { - if (ThreadLocalRandom.current().nextInt(10) == 6) { - log.error("getColumnTypeName failed, columnName={}, columnIndex={}", columnName, columnIndex, e); - } + } catch (final SQLException ex) { + log.error("getColumnTypeName failed, columnName={}, columnIndex={}", columnName, columnIndex, ex); } - this.typeOID = PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName(columnTypeName); + this.typeOID = PostgreSQLArrayColumnType.getTypeOidByColumnTypeName(columnTypeName); } else { this.typeOID = PostgreSQLColumnType.valueOfJDBCType(columnType).getValue(); } diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnTypeTest.java similarity index 75% rename from shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java rename to shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnTypeTest.java index 1ff1a6677849a..352363cb5c23e 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLColumnTypeNameOidMappingsTest.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLArrayColumnTypeTest.java @@ -19,19 +19,20 @@ import org.junit.Test; -import static org.junit.Assert.assertEquals; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; -public class PostgreSQLColumnTypeNameOidMappingsTest { +public class PostgreSQLArrayColumnTypeTest { @Test public void assertIntegerArrayGot() { - int columnTypeName = PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName("_int4"); - assertEquals(1007, columnTypeName); + int columnTypeName = PostgreSQLArrayColumnType.getTypeOidByColumnTypeName("_int4"); + assertThat(columnTypeName, is(1007)); } @Test(expected = IllegalArgumentException.class) public void assertIllegalArgExThrown() { - PostgreSQLColumnTypeNameOidMappings.getTypeOidByColumnTypeName("not_exist_type"); + PostgreSQLArrayColumnType.getTypeOidByColumnTypeName("not_exist_type"); } } diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java index d8ce85acc701e..b622cfe872e36 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-postgresql/src/test/java/org/apache/shardingsphere/db/protocol/postgresql/packet/command/query/PostgreSQLColumnDescriptionTest.java @@ -20,16 +20,18 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; -import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + public class PostgreSQLColumnDescriptionTest { @Test public void assertIntegerTypeOid() { PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("age", 1, Types.INTEGER, 4, null); - Assert.assertEquals(23, description.getTypeOID()); + assertThat(description.getTypeOID(), is(23)); } @Test @@ -37,7 +39,7 @@ public void assertIntegerArrayTypeOid() throws SQLException { ResultSetMetaData resultSetMetaData = Mockito.mock(ResultSetMetaData.class); Mockito.when(resultSetMetaData.getColumnTypeName(2)).thenReturn("_int4"); PostgreSQLColumnDescription description = new PostgreSQLColumnDescription("ages", 2, Types.ARRAY, 12, resultSetMetaData); - Assert.assertEquals(1007, description.getTypeOID()); + assertThat(description.getTypeOID(), is(1007)); } } diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java index 2c4fd1c4bdf00..2509d5225d1a5 100644 --- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java +++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/QueryResult.java @@ -30,7 +30,7 @@ public interface QueryResult { /** * Get JDBC ResultSetMetaData. * - * @return {@linkplain ResultSetMetaData} + * @return JDBC ResultSetMetaData */ ResultSetMetaData getResultSetMetaData();