diff --git a/contrib/shark/expected/test_sysviews.out b/contrib/shark/expected/test_sysviews.out index bf40fe48ef4e170515d05f1f0dcdc2b17927f30c..6cb156db791fad40f28cc3cea7043566c9d22ba4 100644 --- a/contrib/shark/expected/test_sysviews.out +++ b/contrib/shark/expected/test_sysviews.out @@ -356,3 +356,321 @@ drop schema sys_view_test cascade; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to sequence sys_view_test.t_seq drop cascades to function sys_view_test.tg_log() +create schema sys_view_test_02; +set search_path to sys_view_test_02; +-- show views struct +\d information_schema_tsql.check_constraints + View "information_schema_tsql.check_constraints" + Column | Type | Modifiers +--------------------+-----------------+----------- + constraint_catalog | nvarchar2(128) | + constraint_schema | nvarchar2(128) | + constraint_name | name | + check_clause | nvarchar2(4000) | + +\d information_schema_tsql.columns + View "information_schema_tsql.columns" + Column | Type | Modifiers +--------------------------+------------------------------+----------- + table_catalog | nvarchar2(128) | + table_schema | nvarchar2(128) | + table_name | nvarchar2(128) | + column_name | nvarchar2(128) | + ordinal_position | integer | + column_default | nvarchar2(4000) | + is_nullable | information_schema.yes_or_no | + data_type | character varying(128) | + character_maximum_length | integer | + character_octet_length | integer | + numeric_precision | tinyint | + numeric_precision_radix | smallint | + numeric_scale | integer | + datetime_precision | smallint | + character_set_name | nvarchar2(128) | + collation_catalog | nvarchar2(128) | + collation_schema | nvarchar2(128) | + collation_name | nvarchar2(128) | + domain_catalog | nvarchar2(128) | + domain_schema | nvarchar2(128) | + domain_name | nvarchar2(128) | + +\d information_schema_tsql.tables + View "information_schema_tsql.tables" + Column | Type | Modifiers +---------------+-----------------------+----------- + table_catalog | nvarchar2(128) | + table_schema | nvarchar2(128) | + table_name | name | + table_type | character varying(10) | + +\d information_schema_tsql.views + View "information_schema_tsql.views" + Column | Type | Modifiers +-----------------+----------------------+----------- + table_catalog | nvarchar2(128) | + table_schema | nvarchar2(128) | + table_name | nvarchar2(128) | + view_definition | nvarchar2(4000) | + check_option | character varying(7) | + is_updatable | character varying(3) | + +\d sys.sysdatabases + View "sys.sysdatabases" + Column | Type | Modifiers +----------+-----------------------------+----------- + name | name | + dbid | oid | + sid | oid | + mode | smallint | + status | integer | + status2 | integer | + crdate | timestamp without time zone | + reserved | timestamp without time zone | + category | integer | + cmplevel | tinyint | + filename | nvarchar2(260) | + version | smallint | + +\d sys.schemas + View "sys.schemas" + Column | Type | Modifiers +--------------+---------+----------- + name | name | + schema_id | integer | + principal_id | integer | + +\d sys.sysusers + View "sys.sysusers" + Column | Type | Modifiers +-------------+------------------------+----------- + uid | integer | + status | smallint | + name | name | + sid | bytea | + roles | bytea | + createdate | date | + updatedate | date | + altuid | smallint | + password | bytea | + gid | smallint | + environ | character varying(255) | + hasdbaccess | integer | + islogin | integer | + isntname | integer | + isntgroup | integer | + isntuser | integer | + issqluser | integer | + isaliased | integer | + issqlrole | integer | + isapprole | integer | + +\d sys.databases + View "sys.databases" + Column | Type | Modifiers +--------------------------------------------+-----------------------------+----------- + name | character varying(128) | + database_id | oid | + source_database_id | integer | + owner_sid | oid | + create_date | timestamp without time zone | + compatibility_level | tinyint | + collation_name | name | + user_access | tinyint | + user_access_desc | nvarchar2(60) | + is_read_onliy | bit(1) | + is_auto_close_on | bit(1) | + is_auto_shrink_on | bit(1) | + state | tinyint | + state_desc | nvarchar2(60) | + is_in_standby | bit(1) | + is_cleanly_shutdown | bit(1) | + is_supplemental_logging_enabled | bit(1) | + snapshot_isolation_state | tinyint | + snapshot_isolation_state_desc | nvarchar2(60) | + is_read_committed_snapshot_on | bit(1) | + recovery_model | tinyint | + recovery_model_desc | nvarchar2(60) | + page_verify_option | tinyint | + page_verify_option_desc | nvarchar2(60) | + is_auto_create_stats_on | bit(1) | + is_auto_create_stats_incremental_on | bit(1) | + is_auto_update_stats_on | bit(1) | + is_auto_update_stats_async_on | bit(1) | + is_ansi_null_default_on | bit(1) | + is_ansi_nulls_on | bit(1) | + is_ansi_padding_on | bit(1) | + is_ansi_warnings_on | bit(1) | + is_concat_null_yields_null_on | bit(1) | + is_numeric_roundabort_on | bit(1) | + is_quoted_identifier_on | bit(1) | + is_recursive_triggers_on | bit(1) | + is_cursor_close_on_commit_on | bit(1) | + is_local_cursor_default | bit(1) | + is_fulltext_enabled | bit(1) | + is_trustworthy_on | bit(1) | + is_db_chaining_on | bit(1) | + is_parameterization_forced | bit(1) | + is_master_key_encrypted_by_server | bit(1) | + is_query_store_on | bit(1) | + is_published | bit(1) | + is_subscribed | bit(1) | + is_merge_published | bit(1) | + is_distributor | bit(1) | + is_sync_with_backup | bit(1) | + service_broker_guid | oid | + is_broker_enabled | bit(1) | + log_reuse_wait | tinyint | + log_reuse_wait_desc | nvarchar2(60) | + is_date_correlation_on | bit(1) | + is_cdc_enabled | bit(1) | + is_encrypted | bit(1) | + is_honor_broker_priority_on | bit(1) | + replica_id | oid | + group_database_id | oid | + resource_pool_id | integer | + default_language_lcid | smallint | + default_language_name | character varying(128) | + default_fulltext_language_lcid | integer | + default_fulltext_language_name | character varying(128) | + is_nested_triggers_on | bit(1) | + is_transform_noise_words_on | bit(1) | + two_digit_year_cutoff | smallint | + containment | tinyint | + containment_desc | character varying(60) | + target_recovery_time_in_seconds | integer | + delayed_durability | integer | + delayed_durability_desc | character varying(60) | + is_memory_optimized_elevate_to_snapshot_on | bit(1) | + is_federation_member | bit(1) | + is_remote_data_archive_enabled | bit(1) | + is_mixed_page_allocation_on | bit(1) | + is_temporal_history_retention_enabled | bit(1) | + catalog_collation_type | bit(1) | + catalog_collation_type_desc | nvarchar2(60) | + physical_database_name | nvarchar2(128) | + is_result_set_caching_on | bit(1) | + is_accelerated_database_recovery_on | bit(1) | + is_tempdb_spill_to_remote_store | bit(1) | + is_stale_page_detection_on | bit(1) | + is_memory_optimized_enabled | bit(1) | + is_ledger_on | bit(1) | + is_change_feed_enabled | bit(1) | + is_vorder_enable | bit(1) | + +-- prepare data +CREATE TABLE employees ( + name VARCHAR(50) NOT NULL, + age INT, + salary DECIMAL(10, 2), + -- CHECK 约束:年龄必须 >= 18 + CONSTRAINT chk_age CHECK (age >= 18) +); +CREATE VIEW high_salary_employees AS +SELECT name, age, salary +FROM employees +WHERE age >= 18 AND salary > 5000; +INSERT INTO employees (name, age, salary) VALUES ('张三', 25, 8000.00); +INSERT INTO employees (name, age, salary) VALUES ('李四', 26, 4000.00); +-- test select +select constraint_schema, constraint_name, check_clause +from information_schema_tsql.check_constraints c +inner join pg_namespace s on c.constraint_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + constraint_schema | constraint_name | check_clause +-------------------+-----------------+--------------------- + sys_view_test_02 | chk_age | CHECK ((age >= 18)) +(1 row) + +select table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, +character_octet_length, numeric_precision, numeric_precision_radix, numeric_scale, datetime_precision, character_set_name, collation_catalog, +collation_schema, collation_name, domain_catalog, domain_schema, domain_name +from information_schema_tsql.columns c +inner join pg_namespace s on c.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + table_schema | table_name | column_name | ordinal_position | column_default | is_nullable | data_type | character_maximum_length | character_octet_length | numeric_precision | numeric_precision_radix | numeric_scale | datetime_precision | character_set_name | collation_catalog | collation_schema | collation_name | domain_catalog | domain_schema | domain_name +------------------+-----------------------+-------------+------------------+----------------+-------------+-----------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+--------------------+-------------------+------------------+----------------+----------------+---------------+------------- + sys_view_test_02 | high_salary_employees | name | 1043 | | YES | character varying(50) | 50 | 50 | | | | | | | | default | | | + sys_view_test_02 | employees | name | 1043 | | NO | character varying(50) | 50 | 50 | | | | | | | | default | | | + sys_view_test_02 | high_salary_employees | salary | 1700 | | YES | numeric(10,2) | | | 10 | 10 | 2 | | | | | | | | + sys_view_test_02 | high_salary_employees | age | 23 | | YES | integer | | | 10 | 10 | 0 | | | | | | | | + sys_view_test_02 | employees | salary | 1700 | | YES | numeric(10,2) | | | 10 | 10 | 2 | | | | | | | | + sys_view_test_02 | employees | age | 23 | | YES | integer | | | 10 | 10 | 0 | | | | | | | | +(6 rows) + +select table_schema, table_name, table_type +from information_schema_tsql.tables t +inner join pg_namespace s on t.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + table_schema | table_name | table_type +------------------+-----------------------+------------ + sys_view_test_02 | employees | BASE TABLE + sys_view_test_02 | high_salary_employees | VIEW +(2 rows) + +select table_schema, table_name, view_definition, check_option, is_updatable +from information_schema_tsql.views v +inner join pg_namespace s on v.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + table_schema | table_name | view_definition | check_option | is_updatable +------------------+-----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+--------------+-------------- + sys_view_test_02 | high_salary_employees | SELECT employees.name, employees.age, employees.salary FROM employees WHERE ((employees.age >= 18) AND (employees.salary > (5000)::numeric)); | NONE | YES +(1 row) + +select sid, mode, status, status2, crdate, reserved, category, cmplevel, filename, version +from sys.sysdatabases; + sid | mode | status | status2 | crdate | reserved | category | cmplevel | filename | version +-----+------+--------+---------+--------------------------+--------------------------+----------+----------+----------+--------- + 10 | 0 | 0 | 0 | Mon Jan 01 00:00:00 1900 | Mon Jan 01 00:00:00 1900 | 0 | 0 | | + 10 | 0 | 0 | 0 | Mon Jan 01 00:00:00 1900 | Mon Jan 01 00:00:00 1900 | 0 | 0 | | + 10 | 0 | 0 | 0 | Mon Jan 01 00:00:00 1900 | Mon Jan 01 00:00:00 1900 | 0 | 0 | | + 10 | 0 | 0 | 0 | Mon Jan 01 00:00:00 1900 | Mon Jan 01 00:00:00 1900 | 0 | 0 | | + 10 | 0 | 0 | 0 | Mon Jan 01 00:00:00 1900 | Mon Jan 01 00:00:00 1900 | 0 | 0 | | +(5 rows) + +select name, schema_id, principal_id +from sys.schemas where schema_id < 16384; + name | schema_id | principal_id +--------------------+-----------+-------------- + pg_toast | 99 | 10 + cstore | 100 | 10 + pkg_service | 3988 | 10 + dbe_perf | 4988 | 10 + snapshot | 4989 | 10 + blockchain | 4990 | 10 + coverage | 4994 | 10 + xmltype | 12872 | 10 + pg_catalog | 11 | 10 + sqladvisor | 7813 | 10 + dbe_pldebugger | 4992 | 10 + dbe_pldeveloper | 4993 | 10 + dbe_sql_util | 9049 | 10 + information_schema | 14975 | 10 + db4ai | 4991 | 10 + public | 2200 | 10 +(16 rows) + +select * +from sys.sysusers where uid >1000 and uid < 16384; + uid | status | name | sid | roles | createdate | updatedate | altuid | password | gid | environ | hasdbaccess | islogin | isntname | isntgroup | isntuser | issqluser | isaliased | issqlrole | isapprole +------+--------+--------------------------+-----+-------+------------+------------+--------+----------+-----+---------+-------------+---------+----------+-----------+----------+-----------+-----------+-----------+----------- + 1044 | 0 | gs_role_copy_files | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1045 | 0 | gs_role_signal_backend | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1046 | 0 | gs_role_tablespace | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1047 | 0 | gs_role_replication | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1048 | 0 | gs_role_account_lock | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1055 | 0 | gs_role_pldebugger | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1056 | 0 | gs_role_directory_create | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 + 1059 | 0 | gs_role_directory_drop | | | | | 0 | | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 +(8 rows) + +select * +from sys.databases where database_id = 1; + name | database_id | source_database_id | owner_sid | create_date | compatibility_level | collation_name | user_access | user_access_desc | is_read_onliy | is_auto_close_on | is_auto_shrink_on | state | state_desc | is_in_standby | is_cleanly_shutdown | is_supplemental_logging_enabled | snapshot_isolation_state | snapshot_isolation_state_desc | is_read_committed_snapshot_on | recovery_model | recovery_model_desc | page_verify_option | page_verify_option_desc | is_auto_create_stats_on | is_auto_create_stats_incremental_on | is_auto_update_stats_on | is_auto_update_stats_async_on | is_ansi_null_default_on | is_ansi_nulls_on | is_ansi_padding_on | is_ansi_warnings_on | is_concat_null_yields_null_on | is_numeric_roundabort_on | is_quoted_identifier_on | is_recursive_triggers_on | is_cursor_close_on_commit_on | is_local_cursor_default | is_fulltext_enabled | is_trustworthy_on | is_db_chaining_on | is_parameterization_forced | is_master_key_encrypted_by_server | is_query_store_on | is_published | is_subscribed | is_merge_published | is_distributor | is_sync_with_backup | service_broker_guid | is_broker_enabled | log_reuse_wait | log_reuse_wait_desc | is_date_correlation_on | is_cdc_enabled | is_encrypted | is_honor_broker_priority_on | replica_id | group_database_id | resource_pool_id | default_language_lcid | default_language_name | default_fulltext_language_lcid | default_fulltext_language_name | is_nested_triggers_on | is_transform_noise_words_on | two_digit_year_cutoff | containment | containment_desc | target_recovery_time_in_seconds | delayed_durability | delayed_durability_desc | is_memory_optimized_elevate_to_snapshot_on | is_federation_member | is_remote_data_archive_enabled | is_mixed_page_allocation_on | is_temporal_history_retention_enabled | catalog_collation_type | catalog_collation_type_desc | physical_database_name | is_result_set_caching_on | is_accelerated_database_recovery_on | is_tempdb_spill_to_remote_store | is_stale_page_detection_on | is_memory_optimized_enabled | is_ledger_on | is_change_feed_enabled | is_vorder_enable +-----------+-------------+--------------------+-----------+-------------+---------------------+----------------+-------------+------------------+---------------+------------------+-------------------+-------+------------+---------------+---------------------+---------------------------------+--------------------------+-------------------------------+-------------------------------+----------------+---------------------+--------------------+-------------------------+-------------------------+-------------------------------------+-------------------------+-------------------------------+-------------------------+------------------+--------------------+---------------------+-------------------------------+--------------------------+-------------------------+--------------------------+------------------------------+-------------------------+---------------------+-------------------+-------------------+----------------------------+-----------------------------------+-------------------+--------------+---------------+--------------------+----------------+---------------------+---------------------+-------------------+----------------+---------------------+------------------------+----------------+--------------+-----------------------------+------------+-------------------+------------------+-----------------------+-----------------------+--------------------------------+--------------------------------+-----------------------+-----------------------------+-----------------------+-------------+------------------+---------------------------------+--------------------+-------------------------+--------------------------------------------+----------------------+--------------------------------+-----------------------------+---------------------------------------+------------------------+-----------------------------+------------------------+--------------------------+-------------------------------------+---------------------------------+----------------------------+-----------------------------+--------------+------------------------+------------------ + template1 | 1 | | 10 | | | UTF8 | 0 | MULTI_USER | 0 | 0 | 0 | 0 | ONLINE | 0 | 0 | 0 | 1 | ON | 1 | 1 | FULL | 0 | | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | 0 | NOTHING | 0 | 0 | 0 | 0 | | | | | | | | | | | 0 | NONE | 0 | 0 | | 0 | 0 | 0 | 0 | 0 | 0 | Not Applicable | | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 +(1 row) + +drop table employees; +drop view high_salary_employees; +reset search_path; +drop schema sys_view_test_02 cascade; diff --git a/contrib/shark/shark--1.0.sql b/contrib/shark/shark--1.0.sql index 5ce296042b9bdc9ecdabc42aab292e4d579f10a7..cb2e53ee7ddd7da0c8dbd514c798eec168c19334 100644 --- a/contrib/shark/shark--1.0.sql +++ b/contrib/shark/shark--1.0.sql @@ -556,4 +556,430 @@ lateral ( where has_table_privilege(quote_ident(s.nspname) ||'.'||quote_ident(c_tab.relname), 'SELECT'); grant select on sys.sysindexkeys to public; +CREATE SCHEMA information_schema_tsql; +GRANT USAGE ON SCHEMA information_schema_tsql TO PUBLIC; +SET search_path TO information_schema_tsql; + +CREATE OR REPLACE VIEW check_constraints AS +SELECT + cast(current_database() as nvarchar(128)) AS constraint_catalog, + cast(n.nspname as nvarchar(128)) AS constraint_schema, + cast(c.conname as name) AS constraint_name, + cast(pg_get_constraintdef(c.oid) as nvarchar(4000)) AS check_clause +FROM + pg_constraint c + JOIN pg_class t ON c.conrelid = t.oid + JOIN pg_namespace n ON t.relnamespace = n.oid +WHERE + c.contype = 'c'; -- 筛选 CHECK 约束 + +CREATE FUNCTION information_schema_tsql._pg_char_max_length(type text, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$SELECT + CASE WHEN type IN ('char', 'nchar', 'varchar', 'nvarchar') + THEN CASE WHEN typmod = -1 + THEN -1 + ELSE typmod - 4 + END + WHEN type IN ('text') + THEN 2147483647 + WHEN type = 'name' + THEN 64 + WHEN type IN ('xml', 'vector', 'sparsevec') + THEN -1 + ELSE null + END$$; + +CREATE FUNCTION information_schema_tsql._pg_char_octet_length(type text, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$SELECT + CASE WHEN type IN ('char', 'varchar') + THEN CASE WHEN typmod = -1 /* default typmod */ + THEN -1 + ELSE typmod - 4 + END + WHEN type IN ('nchar', 'nvarchar') + THEN CASE WHEN typmod = -1 /* default typmod */ + THEN -1 + ELSE (typmod - 4) * 2 + END + WHEN type IN ('text') + THEN 2147483647 /* 2^30 + 1 */ + WHEN type = 'name' + THEN 128 + WHEN type IN ('xml', 'vector', 'sparsevec') + THEN -1 + ELSE null + END$$; + +CREATE OR REPLACE FUNCTION information_schema_tsql._pgtsql_numeric_precision(type text, typid oid, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$ + SELECT + CASE typid + WHEN 21 /*int2*/ THEN 5 + WHEN 23 /*int4*/ THEN 10 + WHEN 20 /*int8*/ THEN 19 + WHEN 1700 /*numeric*/ THEN + CASE WHEN typmod = -1 THEN null + ELSE ((typmod - 4) >> 16) & 65535 + END + WHEN 700 /*float4*/ THEN 24 + WHEN 701 /*float8*/ THEN 53 + ELSE + CASE WHEN type = 'tinyint' THEN 3 + WHEN type = 'money' THEN 19 + WHEN type = 'decimal' THEN + CASE WHEN typmod = -1 THEN null + ELSE ((typmod - 4) >> 16) & 65535 + END + ELSE null + END + END +$$; + +CREATE OR REPLACE FUNCTION information_schema_tsql._pgtsql_numeric_precision_radix(type text, typid oid, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$SELECT + CASE WHEN typid IN (700, 701) THEN 2 + WHEN typid IN (20, 21, 23, 1700) THEN 10 + WHEN type IN ('tinyint', 'money') THEN 10 + ELSE null + END$$; + +CREATE OR REPLACE FUNCTION information_schema_tsql._pgtsql_numeric_scale(type text, typid oid, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$ + SELECT + CASE WHEN typid IN (21, 23, 20) THEN 0 + WHEN typid IN (1700) THEN + CASE WHEN typmod = -1 THEN null + ELSE (typmod - 4) & 65535 + END + WHEN type = 'tinyint' THEN 0 + WHEN type IN ('money') THEN 4 + WHEN type = 'decimal' THEN + CASE WHEN typmod = -1 THEN NULL + ELSE (typmod - 4) & 65535 + END + ELSE null + END +$$; + +CREATE OR REPLACE FUNCTION information_schema_tsql._pgtsql_datetime_precision(type text, typmod int4) RETURNS integer + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$SELECT + CASE WHEN type = 'date' + THEN 0 + WHEN type IN ('time', 'smalldatetime') + THEN CASE WHEN typmod < 0 THEN 6 ELSE typmod END + ELSE null + END +$$; + +CREATE OR REPLACE FUNCTION information_schema_tsql.is_d_format_schema(nspoid oid, nspname name) RETURNS boolean + LANGUAGE sql + IMMUTABLE + RETURNS NULL ON NULL INPUT + AS +$$SELECT + CASE WHEN nspname <> 'pg_catalog' AND nspname <> 'sys' AND nspname <> 'dbe_pldeveloper' AND nspname <> 'coverage' + AND nspname <> 'dbe_perf' AND nspname <> 'information_schema' AND nspname <> 'db4ai' AND nspname <> 'public' AND nspname <> 'information_schema_tsql' + AND (NOT pg_catalog.pg_is_other_temp_schema(nspoid)) + THEN true + ELSE false + END +$$; + +CREATE OR REPLACE VIEW information_schema_tsql.columns AS +SELECT + CAST(current_database() AS nvarchar(128)) AS table_catalog, + CAST(nc.nspname AS nvarchar(128)) AS table_schema, + CAST(c.relname AS nvarchar(128)) AS table_name, + CAST(a.attname AS nvarchar(128)) AS column_name, + CAST( + CASE WHEN t.typtype = 'd' THEN t.typbasetype ELSE a.atttypid END + AS int + ) AS ordinal_position, + CAST(pg_get_expr(ad.adbin, ad.adrelid) AS nvarchar(4000)) AS column_default, + CAST( + CASE + WHEN a.attnotnull THEN 'NO' + ELSE 'YES' + END AS information_schema.yes_or_no + ) AS is_nullable, + CAST(pg_catalog.format_type(a.atttypid, a.atttypmod) AS varchar(128)) AS data_type, + CAST( + information_schema_tsql._pg_char_max_length(t.typname, a.atttypmod) + AS int) + AS character_maximum_length, + CAST( + information_schema_tsql._pg_char_octet_length(t.typname, a.atttypmod) + AS int) + AS character_octet_length, + CAST(information_schema_tsql._pgtsql_numeric_precision(t.typname, a.atttypid, a.atttypmod) AS tinyint) AS numeric_precision, + CAST(information_schema_tsql._pgtsql_numeric_precision_radix(t.typname, a.atttypid, a.atttypmod) AS smallint) AS numeric_precision_radix, + CAST(information_schema_tsql._pgtsql_numeric_scale(t.typname, a.atttypid, a.atttypmod) AS int) AS numeric_scale, + CAST(information_schema_tsql._pgtsql_datetime_precision(t.typname, a.atttypmod) AS smallint) AS datetime_precision, + CAST(pg_encoding_to_char(co.collencoding) AS nvarchar(128)) AS character_set_name, + CAST(null as nvarchar(128)) as collation_catalog, + CAST(null as nvarchar(128)) as collation_schema, + CAST(co.collname AS nvarchar(128)) AS collation_name, + CAST(CASE WHEN t.typtype = 'd' AND nc.nspname <> 'pg_catalog' AND nc.nspname <> 'sys' THEN pg_catalog.current_database() ELSE null END + AS nvarchar(128)) AS domain_catalog, + CAST(CASE WHEN t.typtype = 'd' AND nc.nspname <> 'pg_catalog' AND nc.nspname <> 'sys' THEN nc.nspname ELSE null END + AS nvarchar(128)) AS domain_schema, + CAST(CASE WHEN t.typtype = 'd' AND nc.nspname <> 'pg_catalog' AND nc.nspname <> 'sys' THEN t.typname ELSE null END + AS nvarchar(128)) AS domain_name +FROM + pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace nc ON c.relnamespace = nc.oid + JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid + LEFT JOIN pg_catalog.pg_attrdef ad ON (a.attrelid, a.attnum) = (ad.adrelid, ad.adnum) + LEFT JOIN pg_catalog.pg_type t ON a.atttypid = t.oid + LEFT JOIN pg_catalog.pg_collation co ON t.typcollation = co.oid +WHERE information_schema_tsql.is_d_format_schema(nc.oid, nc.nspname) + AND c.relkind IN ('r', 'v', 'm', 'f') -- 表/视图/物化视图/外表 + AND a.attnum > 0 + AND NOT a.attisdropped + AND (pg_has_role(c.relowner, 'USAGE') + OR has_column_privilege(c.oid, a.attnum, + 'SELECT, INSERT, UPDATE, REFERENCES')); + +CREATE OR REPLACE VIEW information_schema_tsql.tables AS +SELECT CAST(pg_catalog.current_database() AS nvarchar(128)) AS table_catalog, + CAST(nc.nspname AS nvarchar(128)) AS table_schema, + CAST(c.relname AS name) AS table_name, + + CAST( + CASE WHEN nc.oid = pg_catalog.pg_my_temp_schema() THEN 'LOCAL TEMPORARY' + WHEN c.relkind = 'r' THEN 'BASE TABLE' + WHEN c.relkind = 'v' THEN 'VIEW' + ELSE null END + AS varchar(10)) AS table_type +FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) +WHERE c.relkind IN ('r', 'm', 'v', 'f') + AND information_schema_tsql.is_d_format_schema(nc.oid, nc.nspname) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + +CREATE OR REPLACE VIEW information_schema_tsql.views AS +SELECT CAST(pg_catalog.current_database() AS nvarchar(128)) AS table_catalog, + CAST(nc.nspname AS nvarchar(128)) AS table_schema, + CAST(c.relname AS nvarchar(128)) AS table_name, + + CAST( + CASE WHEN pg_catalog.pg_has_role(c.relowner, 'USAGE') + THEN pg_catalog.pg_get_viewdef(c.oid) + ELSE null END + AS nvarchar(4000)) AS view_definition, + + CAST( + CASE WHEN 'check_option=cascaded' = ANY (c.reloptions) + THEN 'CASCADED' + ELSE 'NONE' END + AS varchar(7)) AS check_option, + CAST(CASE WHEN pg_relation_is_updatable(c.oid, false) & 4 = 4 + THEN 'YES' ELSE 'NO' END + AS varchar(3)) AS is_updatable + FROM pg_namespace nc, pg_class c + WHERE c.relnamespace = nc.oid + AND c.relkind = 'v' + AND information_schema_tsql.is_d_format_schema(nc.oid, nc.nspname) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + +set search_path = 'sys'; +CREATE OR REPLACE VIEW sys.sysdatabases AS +SELECT + CAST(d.datname as name) AS name, -- 数据库名称 + CAST(d.oid as oid) AS dbid, -- 数据库唯一标识符(OID) + CAST(d.datdba as oid) AS sid, -- 数据库所有者用户 OID + CAST(0 as smallint) as mode, + CAST(0 as integer) as status, + CAST(0 as integer) as status2, + CAST('1900-01-01 00:00:00.000' as timestamp) as crdate, + CAST('1900-01-01 00:00:00.000' as timestamp) as reserved, + CAST( + CASE + WHEN EXISTS (SELECT 1 FROM pg_subscription WHERE subdbid = d.oid) + THEN 2 ELSE 0 + END as integer) + AS category, + CAST(0 as tinyint) as cmplevel, + CAST(NULL as nvarchar(260)) as filename, + CAST(NULL as smallint) as version +FROM pg_database d; + +CREATE OR REPLACE VIEW sys.schemas AS +SELECT + CAST(n.nspname as name) AS name, + CAST(n.oid as integer) AS schema_id, + CAST(n.nspowner AS integer) AS principal_id + FROM pg_namespace n + WHERE pg_catalog.pg_has_role(n.nspowner, 'USAGE'); + +-- 模拟 SQL Server 的 sys.sysusers +CREATE OR REPLACE VIEW sys.sysusers AS +SELECT + CAST(r.oid AS integer) AS uid, -- 用户/角色唯一标识符 + CAST(0 AS smallint) AS status, + CAST(r.rolname AS name) AS name, -- 用户/角色名称 + CAST(NULL AS bytea) AS sid, + CAST(NULL AS bytea) AS roles, + CAST(NULL AS date) AS createdate, + CAST(NULL AS date) AS updatedate, + CAST(0 AS smallint) AS altuid, + CAST(NULL AS bytea) AS password, + CAST(0 AS smallint) AS gid, + CAST(NULL AS varchar(255)) AS environ, + CAST( + CASE WHEN has_database_privilege(name, current_database(), 'CONNECT') + THEN 1 + ELSE 0 + END AS integer) + AS hasdbaccess, + CAST(r.rolcanlogin AS integer) AS islogin, + CAST(0 AS integer) AS isntname, + CAST(0 AS integer) AS isntgroup, + CAST(0 AS integer) AS isntuser, + CAST(r.rolcanlogin AS integer) AS issqluser, + CAST(0 AS integer) AS isaliased, + CAST(NOT r.rolcanlogin AS integer) AS issqlrole, + CAST(0 AS integer) AS isapprole +FROM pg_roles r +WHERE pg_has_role(r.rolname, 'USAGE'); -- 仅显示当前用户有权查看的角色 + +-- 模拟 SQL Server 的 sys.databases +CREATE OR REPLACE VIEW sys.databases AS +SELECT + CAST(d.datname AS VARCHAR(128)) AS name, + CAST(d.oid AS OID) AS database_id, + CAST(NULL AS INTEGER) AS source_database_id, + CAST( + CASE WHEN d.datdba > 0 THEN d.datdba ELSE NULL END + AS OID) AS owner_sid, + CAST(NULL AS TIMESTAMP) AS create_date, + CAST(NULL AS TINYINT) AS compatibility_level, + CAST(pg_catalog.getdatabaseencoding() AS NAME) AS collation_name, + CAST( + CASE WHEN datallowconn THEN 0 -- MULTI_USER + ELSE 1 -- SINGLE_USER (仅当数据库禁止连接时) + END AS TINYINT) AS user_access, + CAST( + CASE WHEN datallowconn THEN 'MULTI_USER' + ELSE 'SINGLE_USER' + END AS NVARCHAR(60)) AS user_access_desc, + CAST(0 AS BIT) AS is_read_onliy, + CAST(0 AS BIT) AS is_auto_close_on, + CAST(0 AS BIT) AS is_auto_shrink_on, + CAST(0 AS TINYINT) AS state, + CAST('ONLINE' AS NVARCHAR(60)) AS state_desc, + CAST( + CASE WHEN pg_is_in_recovery() THEN 1 + ELSE 0 END + AS BIT) AS is_in_standby, + CAST(0 AS BIT) AS is_cleanly_shutdown, + CAST(0 AS BIT) AS is_supplemental_logging_enabled, + CAST(1 AS TINYINT) AS snapshot_isolation_state, + CAST('ON' AS NVARCHAR(60)) AS snapshot_isolation_state_desc, + CAST( + CASE WHEN current_setting('default_transaction_isolation') = 'read committed' + THEN 1 + ELSE 0 + END AS BIT) AS is_read_committed_snapshot_on, + CAST(1 AS TINYINT) AS recovery_model, + CAST('FULL' AS NVARCHAR(60)) AS recovery_model_desc, + CAST(0 AS TINYINT) AS page_verify_option, + CAST(NULL AS NVARCHAR(60)) AS page_verify_option_desc, + CAST(1 AS BIT) AS is_auto_create_stats_on, + CAST(0 AS BIT) AS is_auto_create_stats_incremental_on, + CAST(0 AS BIT) AS is_auto_update_stats_on, + CAST(0 AS BIT) AS is_auto_update_stats_async_on, + CAST(1 AS BIT) AS is_ansi_null_default_on, + CAST(1 AS BIT) AS is_ansi_nulls_on, + CAST(0 AS BIT) AS is_ansi_padding_on, + CAST(0 AS BIT) AS is_ansi_warnings_on, + CAST(1 AS BIT) AS is_concat_null_yields_null_on, + CAST(0 AS BIT) AS is_numeric_roundabort_on, + CAST(1 AS BIT) AS is_quoted_identifier_on, + CAST(0 AS BIT) AS is_recursive_triggers_on, + CAST(0 AS BIT) AS is_cursor_close_on_commit_on, + CAST(0 AS BIT) AS is_local_cursor_default, + CAST(0 AS BIT) AS is_fulltext_enabled, + CAST(0 AS BIT) AS is_trustworthy_on, + CAST(0 AS BIT) AS is_db_chaining_on, + CAST(0 AS BIT) AS is_parameterization_forced, + CAST(0 AS BIT) AS is_master_key_encrypted_by_server, + CAST(0 AS BIT) AS is_query_store_on, + CAST(0 AS BIT) AS is_published, + CAST(0 AS BIT) AS is_subscribed, + CAST(0 AS BIT) AS is_merge_published, + CAST(0 AS BIT) AS is_distributor, + CAST(0 AS BIT) AS is_sync_with_backup, + CAST(NULL AS OID) AS service_broker_guid, + CAST(0 AS BIT) AS is_broker_enabled, + CAST(0 AS TINYINT) AS log_reuse_wait, + CAST('NOTHING' AS NVARCHAR(60)) as log_reuse_wait_desc, + CAST(0 AS BIT) AS is_date_correlation_on, + CAST(0 AS BIT) AS is_cdc_enabled, + CAST(0 AS BIT) AS is_encrypted, + CAST(0 AS BIT) AS is_honor_broker_priority_on, + CAST(NULL AS OID) AS replica_id, + CAST(NULL AS OID) AS group_database_id, + CAST(NULL AS INTEGER) AS resource_pool_id, + CAST(NULL AS SMALLINT) AS default_language_lcid, + CAST(NULL AS VARCHAR(128)) AS default_language_name, + CAST(NULL AS INTEGER) AS default_fulltext_language_lcid, + CAST(NULL AS VARCHAR(128)) AS default_fulltext_language_name, + CAST(NULL AS BIT) AS is_nested_triggers_on, + CAST(NULL AS BIT) AS is_transform_noise_words_on, + CAST(NULL AS SMALLINT) AS two_digit_year_cutoff, + CAST(0 AS TINYINT) AS containment, + CAST('NONE' AS VARCHAR(60)) AS containment_desc, + CAST(0 AS INTEGER) AS target_recovery_time_in_seconds, + CAST(0 AS INTEGER) AS delayed_durability, + CAST(NULL AS VARCHAR(60)) AS delayed_durability_desc, + CAST(0 AS BIT) AS is_memory_optimized_elevate_to_snapshot_on, + CAST(0 AS BIT) AS is_federation_member, + CAST(0 AS BIT) AS is_remote_data_archive_enabled, + CAST(0 AS BIT) AS is_mixed_page_allocation_on, + CAST(0 AS BIT) AS is_temporal_history_retention_enabled, + CAST(0 AS BIT) AS catalog_collation_type, + CAST('Not Applicable' AS NVARCHAR(60)) as catalog_collation_type_desc, + CAST(NULL AS NVARCHAR(128)) as physical_database_name, + CAST(0 AS BIT) as is_result_set_caching_on, + CAST(0 AS BIT) as is_accelerated_database_recovery_on, + CAST(0 AS BIT) as is_tempdb_spill_to_remote_store, + CAST(0 AS BIT) as is_stale_page_detection_on, + CAST(0 AS BIT) as is_memory_optimized_enabled, + CAST(0 AS BIT) as is_ledger_on, + CAST(0 AS BIT) as is_change_feed_enabled, + CAST(0 AS BIT) as is_vorder_enable +FROM pg_database d, pg_settings s +WHERE + s.name = 'wal_level'; + + reset search_path; diff --git a/contrib/shark/sql/test_sysviews.sql b/contrib/shark/sql/test_sysviews.sql index 0a2854756ee55ac5566e2ff7c1eab2882f136bbc..69d62230c7b7d90d729c3a78612b2a217e39c205 100644 --- a/contrib/shark/sql/test_sysviews.sql +++ b/contrib/shark/sql/test_sysviews.sql @@ -151,3 +151,73 @@ drop table student; reset search_path; drop schema sys_view_test cascade; + +create schema sys_view_test_02; +set search_path to sys_view_test_02; +-- show views struct +\d information_schema_tsql.check_constraints +\d information_schema_tsql.columns +\d information_schema_tsql.tables +\d information_schema_tsql.views +\d sys.sysdatabases +\d sys.schemas +\d sys.sysusers +\d sys.databases + +-- prepare data +CREATE TABLE employees ( + name VARCHAR(50) NOT NULL, + age INT, + salary DECIMAL(10, 2), + -- CHECK 约束:年龄必须 >= 18 + CONSTRAINT chk_age CHECK (age >= 18) +); + +CREATE VIEW high_salary_employees AS +SELECT name, age, salary +FROM employees +WHERE age >= 18 AND salary > 5000; + +INSERT INTO employees (name, age, salary) VALUES ('张三', 25, 8000.00); +INSERT INTO employees (name, age, salary) VALUES ('李四', 26, 4000.00); + +-- test select +select constraint_schema, constraint_name, check_clause +from information_schema_tsql.check_constraints c +inner join pg_namespace s on c.constraint_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + +select table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, +character_octet_length, numeric_precision, numeric_precision_radix, numeric_scale, datetime_precision, character_set_name, collation_catalog, +collation_schema, collation_name, domain_catalog, domain_schema, domain_name +from information_schema_tsql.columns c +inner join pg_namespace s on c.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + +select table_schema, table_name, table_type +from information_schema_tsql.tables t +inner join pg_namespace s on t.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + +select table_schema, table_name, view_definition, check_option, is_updatable +from information_schema_tsql.views v +inner join pg_namespace s on v.table_schema = s.nspname +where s.nspname = 'sys_view_test_02'; + +select sid, mode, status, status2, crdate, reserved, category, cmplevel, filename, version +from sys.sysdatabases; + +select name, schema_id, principal_id +from sys.schemas where schema_id < 16384; + +select * +from sys.sysusers where uid >1000 and uid < 16384; + +select * +from sys.databases where database_id = 1; + +drop table employees; +drop view high_salary_employees; + +reset search_path; +drop schema sys_view_test_02 cascade;