# compat-tools **Repository Path**: enmotech/compat-tools ## Basic Information - **Project Name**: compat-tools - **Description**: Other databases (Oracle, MySQL, SQL Server, etc.) compatible views & functions for openGauss - **Primary Language**: SQL - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 46 - **Forks**: 18 - **Created**: 2020-12-15 - **Last Updated**: 2025-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: MogDB, Oracle, openGauss, MySQL, db ## README # compat-tools ## Introduction This project is a collection of compatibility tools designed to create the necessary compatibility functions and system views after migrating to openGauss from other heterogeneous databases, to facilitate subsequent system operation and maintenance and application transformation. The script has version control function, when running the script directly, it will be processed according to the following three situations: 1. if the object to be created does not exist in the target database, it will be created directly. 2. if the version of the object to be created is higher than the version of the object in the target database, it will be upgraded and rebuilt. 3. if the version of the object to be created is not higher than the version of the object in the target database, the creation is skipped. ## Software Architecture ### SQL files - runMe.sql: General script that creates all compatibility objects. - checkMe.sql: General check script that checks if the compatibility objects in the target database need to be upgraded. - flush_privileges.sql: Privileges flush script that grants permissions to all users of the compatibility objects. - uninstall.sql: Uninstall script that removes a set of compatibility-related objects created by compat-tools. - Oracle_Views.sql: Oracle database compatibility data dictionary and views. - Oracle_Functions.sql: Oracle database compatibility functions - Oracle_Packages.sql: Oracle database compatibility packages - MySQL_Views.sql: MySQL database compatibility data dictionary and views //TODO - MySQL_Functions.sql: MySQL database compatibility functions - DB2_Functions.sql: DB2 database compatibility functions ### Python Scripts - test.py: Automated test script that relies on the docker service to automate checking the execution of scripts across openGauss versions (note: this is a test script that is tested before each version of compat-tools is released, and is not required for end-users to utilize this script) - batch_executor.py: Batch execution scheduler for multiple databases, it can execute object creation or version checking for multiple databases in the same database instance at the same time. ## Usage Execute sql commands directly in the openGauss database. > Note: All the following operations need to be performed in the current directory where the script is located. ### Create all compatibility objects Creates all compatibility objects including: views, functions, packages, etc. ```shell # Local user, logging into the default database gsql -f runMe.sql # Detailed creation syntax, note the test user permissions (requires sysadmin permissions, as of version 3.0, only the initial user is supported for local creation) gsql -h 127.0.0.1 -p 5432 -U test -d database_name -f runMe.sql ``` ### Create a single class of compatibility objects The following instructions use the Oracle compatibility views as an example; other compatibility object scripts can be created in this manner. ```shell # Local user, logging into the default database gsql -f Oracle_Views.sql # Detailed creation syntax, note the test user permissions (requires sysadmin permissions, as of version 3.0, only the initial user is supported for local creation) gsql -h 127.0.0.1 -p 5432 -U test -d database_name -f Oracle_Views.sql ``` ### Check version Checks if objects in the target database need to be upgraded. ```shell # Local user, logging into the default database gsql -f checkMe.sql # Detailed creation syntax, note the test user permissions (requires sysadmin permissions, as of version 3.0, only the initial user is supported for local creation) gsql -h 127.0.0.1 -p 5432 -U test -d database_name -f checkMe.sql ``` ### Uninstall Compat-tools Uninstalls a set of compatibility objects created by Compat-tools. ```shell # Local user, logging into the default database gsql -f uninstall.sql # Detailed creation syntax, note the test user permissions (requires sysadmin permissions, as of version 3.0, only the initial user is supported for local creation) gsql -h 127.0.0.1 -p 5432 -U test -d database_name -f uninstall.sql ``` ### Batch execution By default, the runMe.sql or checkMe.sql scripts are executed against only one set of connected databases. If you want to create objects for more than one set of databases in a database instance, then you can use the batch_executor.py script. ```shell # View the command line options supported by the batch scheduler script python3 batch_executor.py -h # Batch create compatibility objects for all databases in the instance python3 batch_executor.py -f runMe.sql # Check the version of the compatibility object for postgres,hongye databases only. python3 batch_executor.py -d 'postgres,hongye' -f checkMe.sql ``` ### Function test SQL scripts can be functionally tested using the built-in `test.py` automated test script when using the current tool: Note: This test script needs to be executed on a server with Docker installed and an extranet environment. ``` python3 test.py ``` After the test script is executed, a `test_result.md` result document is generated to record the results of the test, as well as the details of the failed test cases, if any. There are two main parts of the test document: 1. Test summary: the test summary shows the current version of the target database that has been tested, a list of database compatibility, and the overall test results. 2. Failure details: If there are failed test cases, the failure details are shown. ## Result Description At the end of the script run, the following two types of content are automatically output: 1. The compatibility objects involved in the current script, and the corresponding operation contents ```shell gsql:Oracle_Functions.sql:1035: NOTICE: -- ===================================================================== gsql:Oracle_Functions.sql:1035: NOTICE: -- Compat Object List: gsql:Oracle_Functions.sql:1035: NOTICE: -- ===================================================================== gsql:Oracle_Functions.sql:1035: NOTICE: | type | name | version | language | operation | gsql:Oracle_Functions.sql:1035: NOTICE: |-----------|--------------------------------------------------|---------|----------|---------------------| gsql:Oracle_Functions.sql:1035: NOTICE: | function | months_between(timestamptz,timestamptz) | 2.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | sys_guid() | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | aggregate | wm_concat(text) | 1.0 | internal | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | nvl2(anyelement,anyelement,anyelement) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | trunc(timestamp,text) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | trunc(timestamptz,text) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | nanvl(numeric,numeric) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | regexp_substr(text,text,int4) | 2.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | regexp_substr(text,text,int4,int4,text,int4) | 2.0 | plpgsql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | regexp_instr(text,text,int4,int4,int4,text,int4) | 1.0 | plpgsql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | regexp_replace(text,text,text,int4,int4,text) | 1.0 | plpgsql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | regexp_count(text,text,int4,text) | 2.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | replace(text,text) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | ora_hash(anyelement,int4,int4) | 1.0 | plpgsql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | show(text) | 1.0 | sql | Skip due to version | gsql:Oracle_Functions.sql:1035: NOTICE: | function | show_parameter(text) | 1.0 | sql | Skip due to version | ``` 2. Summary of the test cases built into this script. Make sure that all test cases are up to date and that there are no test cases of type `FAILED`. ```shell gsql:Oracle_Functions.sql:1035: NOTICE: -- ===================================================================== gsql:Oracle_Functions.sql:1035: NOTICE: -- Function Test Result: gsql:Oracle_Functions.sql:1035: NOTICE: -- ===================================================================== gsql:Oracle_Functions.sql:1035: NOTICE: | result_type | case_count | start_time | complete_time | gsql:Oracle_Functions.sql:1035: NOTICE: |-------------|------------|----------------------------|----------------------------| gsql:Oracle_Functions.sql:1035: NOTICE: | PASSED | 387 | 2021-11-25 09:42:20.016619 | 2021-11-25 09:42:52.127892 | gsql:Oracle_Functions.sql:1035: NOTICE: | NULL | 6 | 2021-11-25 09:42:20.016619 | 2021-11-25 09:42:20.016619 | ``` 3. The following cases may fail when the database compatibility mode is A (default mode): The following use cases fail because the empty string is considered NULL in A mode (similar to the behavior in Oracle), which causes the use cases to fail and can be ignored. ```shell gsql:runMe.sql:139: NOTICE: -- ===================================================================== gsql:runMe.sql:139: NOTICE: -- Test Detail (Failed or Null): gsql:runMe.sql:139: NOTICE: -- ===================================================================== gsql:runMe.sql:139: NOTICE: | test_expression | result | expect | complete_time | gsql:runMe.sql:139: NOTICE: |----------------------------------------------|-----------------|-----------------|---------------------| gsql:runMe.sql:139: NOTICE: | find_in_set('','a,b,c,dx') | | = 0 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | find_in_set('x','') | | = 0 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | find_in_set('','a,b,c,,dx') | | = 4 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | find_in_set('', string_to_array('a,b,c,d ... | | = 0 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | find_in_set('x', string_to_array('', ',')) | | = 0 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | find_in_set('', string_to_array('a,b,c,, ... | | = 4 | 2021-12-07 07:46:32 | gsql:runMe.sql:139: NOTICE: | isnull('')::text | true | = 'false' | 2021-12-07 07:46:32 | ``` ### Query created compatibility objects and versions ```sql select * from compat_tools.compat_version; ``` ### Query test case details ```sql select * from compat_tools.compat_testing; ``` ## Oracle Compatibility Views Oracle_Views.sql contains the following types of Oracle compatibility views: ### Management views: ALL\_\*, DBA\_\*, USER\_\* > The `ALL_` view is currently compatible with the `DBA_` view and does not do permission checking, which will be considered in later releases. > When installing a view by default, if the object name in the kernel dictionary is in lowercase, it will be converted to uppercase in the query result, while mixed case will remain unchanged. You can revert to the case in the kernel dictionary by executing the following command after the installation of the view is complete: ```bash gsql -f Oracle_Views_Upper.sql -v UPPER="'N'" ``` > If you want to switch to converted uppercase, execute the following command: ```bash gsql -f Oracle_Views_Upper.sql -v UPPER="'Y'" ``` * [DBA,ALL,USER]\_CATALOG * [DBA,ALL,USER]\_CONS\_COLUMNS * [DBA,ALL,USER]\_CONSTRAINTS * [DBA,ALL,USER]\_DATA\_FILES * [DBA,ALL,USER]\_DEPENDENCIES * [DBA,ALL,USER]\_IND\_COLUMNS * [DBA,ALL,USER]\_IND\_EXPRESSIONS * [DBA,ALL,USER]\_IND\_PARTITIONS * [DBA,ALL,USER]\_IND\_STATISTICS * [DBA,ALL,USER]\_INDEX\_USAGE * [DBA,ALL,USER]\_INDEXES * [DBA,ALL,USER]\_OBJECTS * [DBA,ALL,USER]\_PART\_INDEXES * [DBA,ALL,USER]\_PART\_TABLES * [DBA,ALL,USER]\_PROCEDURES * [DBA,ALL,USER]\_SEGMENTS * [DBA,ALL,USER]\_SEQUENCES * [DBA,ALL,USER]\_SOURCE * [DBA,ALL,USER]\_SYNONYMS * [DBA,ALL,USER]\_TAB\_COL\_STATISTICS * [DBA,ALL,USER]\_TAB\_COLS * [DBA,ALL,USER]\_TAB\_COLUMNS * [DBA,ALL,USER]\_TAB\_COMMENTS * [DBA,ALL,USER]\_COL\_COMMENTS * [DBA,ALL,USER]\_TAB\_MODIFICATIONS * [DBA,ALL,USER]\_TAB\_PARTITIONS * [DBA,ALL,USER]\_TAB\_SUBPARTITIONS * [DBA,ALL,USER]\_PART\_KEY\_COLUMNS * [DBA,ALL,USER]\_SUBPART\_KEY\_COLUMNS * [DBA,ALL,USER]\_TAB\_STATISTICS * [DBA,ALL,USER]\_TABLES * [DBA,ALL,USER]\_TABLESPACES * [DBA,ALL,USER]\_TRIGGER\_COLS * [DBA,ALL,USER]\_TRIGGERS * [DBA,ALL,USER]\_TYPES * [DBA,ALL,USER]\_VIEWS * [DBA,ALL,USER]\_JOBS * [DBA,ALL,USER]\_JOBS\_RUNNING * [DBA,ALL,USER]\_MVIEWS * [DBA,ALL,USER]\_MVIEW\_LOGS * [DBA,ALL,USER]\_MVIEW\_COMMENTS * [DBA,ALL,USER]\_USERS * [DBA,ALL]\_DIRECTORIES * DBA_ROLES * [DBA,USER]\_ROLE\_PRIVS * [DBA,ALL,USER]\_TAB\_PRIVS * PRODUCT\_COMPONENT\_VERSION * PLAN\_TABLE * DBA\_SOURCE\_ALL * NLS\_DATABASE\_PARAMETERS * NLS\_INSTANCE\_PARAMETERS * NLS\_SESSION\_PARAMETERS ### Other short names views * DICTIONARY * DICT * COLS * IND * OBJ * TAB * DUAL (For 2.0 and above) ### Dynamic performance views: GV\\$, V\$ * [GV,V]\\$DATABASE -- V\\$DATABASE View current database, GV\$DATABASE View all databases * [GV,V]$INSTANCE * [GV,V]$DATAFILE * [GV,V]$LOCK * [GV,V]$PARAMETER * [GV,V]$PARAMETER\_VALID\_VALUES * [GV,V]$SESSION * [GV,V]$SESSTAT * [GV,V]$SPPARAMETER * [GV,V]$SYSSTAT * [GV,V]$TABLESPACE * [GV,V]$VERSION * [GV,V]$NLS\_PARAMETERS * [GV,V]$NLS\_VALID\_VALUES * [GV,V]$SYSTEM\_WAIT\_CLASS * [GV,V]$SQL * [GV,V]$OPTION * [GV,V]$LICENSE * [GV,V]$STATNAME * [GV,V]$MYSTAT * [GV,V]$LISTENER_NETWORK ### Permission-unified query views * DBA\_DETAIL\_PRIVILEGES * DBA\_ALL\_PRIVILEGES * DBA\_ALL\_PRIVILEGES\_SQL ## Oracle compatibility functions ### Character functions - regexp_substr(text,text,int4) - regexp_substr(text,text,int4,int4,text,int4) -- Note: the last argument p_subexpr is not supported. - regexp_instr(text,text,int4,int4,text,int4) - regexp_replace(text,text,text,int4,int4,text) - regexp_count(text,text,int4,text) - regexp_count(text,text,int4) - regexp_count(text,text) - replace(text,text) - instrb(text,text,int4,int4) - soundex(text) - asciistr(text) - unistr(text) - convert(text,text,text) ### Time functions - months_between(timestamp, timestamp) - trunc(timestamp, text) - trunc(timestamptz, text) - round(timestamptz,text) - tz_offset(text) - numtoyminterval(numeric,text) - systimestamp() - sys_extract_utc(timestamptz) - new_time(timestamp,text,text) ### Numeric functions - nanvl(numeric,numeric) - bitor(int8,int8) - bitxor(int8,int8) - bin_to_num(int4[]) - sinh(numeric) - cosh(numeric) - tanh(numeric) - remainder(numeric,numeric) - round_ties_to_even(numeric,int4) ### Aggregation functions - wm_concat(text) - bit_and_agg(numeric) - bit_or_agg(numeric) - bit_xor_agg(numeric) - any_value(anyelement) - kurtosis_pop(numeric) - kurtosis_samp(numeric) - skewness_pop(numeric) - skewness_samp(numeric) ### NULL-related functions - nullif(anyelement, anyelement) - nvl2(anyelement, anyelement, anyelement) - nvl2(text, text, text) - nvl2(numeric, numeric, numeric) - nvl2(timestamptz, timestamptz, timestamptz) - lnnvl(bool) ### Other functions - sys_guid() - ora_hash(anyelement,bigint,bigint) - show(text) -- Provides function similar to `show xxx` for viewing related parameters in Oracle. - show_parameter(text) -- Equivalent to `show(text)` - dump(anyelement,numeric,int4,int4) - vsize(any) - to_blob(raw) - nls_charset_name(int4) - nls_charset_id(text) - sys_context(text,text,int4) - userenv(text) - empty_clob() ## Oracle management packages ### DBMS_METADATA * get_ddl(object_type, object_name, schema_name) ### DBMS_OUTPUT * enable(int4) * disable() * get_line(text, int4) * get_lines(text[], int4) * new_line() * put(text) * put_line(text) ### DBMS_RANDOM - initialize(int4) -- deprecated in Oracle - normal() - random() -- deprecated in Oracle - seed(int4) - seed(text) - string(text,int4) - terminate() -- deprecated in Oracle - value() - value(numeric,numeric) ### DBMS_JOB - broken(int8,bool,timestamp) - change(int8,text,timestamp,text,int4,bool) - instance(int8,int4,bool) - interval(int8,text) - next_date(int8,timestamp) - remove(int8) - run(int8,bool) - submit(int8,text,timestamp,text,bool,int4,bool) - user_export(int8,text) - what(int8,text) ### DBMS_LOCK - sleep(float8) - allocate_unique(text,text,int4) - request(int8,int4,int4,bool) - request(text,int4,int4,bool) - release(int8) - release(text) ### dbms_application_info - read_client_info(text) - read_module(text,text) - set_client_info(text) - set_module(text,text) ### dbms_obfuscation_toolkit - md5(text) ### dbms_utility - canonicalize(text) - comma_to_table(text,int4,text[]) - table_to_comma(text[],int4,text) - db_version(text,text) - exec_ddl_statement(text) ### utl_url - escape(text,bool,text) - unescape(text,text) ### utl_encode - base64_encode(raw) - base64_decode(raw) - text_encode(text,text,int4) - text_decode(text,text,int4) - quoted_printable_encode(raw) - quoted_printable_decode(raw) - mimeheader_encode(text,text,int4) - mimeheader_decode(text) - uuencode(raw,int1,text,text) - uudecode(raw) ### utl_raw - cast_to_varchar2 - cast_to_raw(text) - concat(raw,raw,raw,raw,raw,raw,raw,raw,raw,raw,raw,raw) - length(raw) - substr(raw,int4,int4) - transliterate(raw,raw,raw,raw) - translate(raw,raw,raw) - copies(raw,int8) - overlay(raw,raw,int4,int4,raw) - xrange(raw,raw) - reverse(raw) - compare(raw,raw,raw) - convert(raw,text,text) - bit_and(raw,raw) - bit_or(raw,raw) - bit_xor(raw,raw) - bit_complement(raw) - cast_to_number(raw) - cast_from_number(numeric) - cast_to_binary_integer(raw,int1) - cast_from_binary_integer(int4,int1) ### dbms_lob - getlength(blob) - getlength(clob) - open(blob,int) - open(clob,int) - freetemporary(blob) - freetemporary(clob) - substr(blob,int4,int4) - substr(clob,int4,int4) - instr(blob,raw,int4,int4) - instr(clob,text,int4,int4) - createtemporary(blob,bool,int4) - createtemporary(clob,bool,int4) - close(blob) - close(clob) - append(blob,blob) - append(clob,clob) - compare(blob,blob,int4,int4,int4) - compare(clob,clob,int4,int4,int4) - copy(blob,blob,int4,int4,int4) - copy(clob,clob,int4,int4,int4) - erase(blob,int4,int4) - erase(clob,int4,int4) - read(blob,int4,int4,raw) - read(clob,int4,int4,text) - trim(blob,int4) - trim(clob,int4) - write(blob,int4,int4,raw) - write(clob,int4,int4,text) - writeappend(blob,int4,raw) - writeappend(clob,int4,text) ### dbms_snapshot - refresh(text,text) ### utl_match - edit_distance(text,text) - edit_distance_similarity(text,text) ## Oracle compatibility types - pls_integer ## MySQL compatibility functions ### NULL- related functions > Note: `ifnull` is equivalent to the generic `coalesce` function. It is recommended to modify SQL to use the `coalesce` function, which is supported by almost all databases, if conditions allow. - ifnull(text,text) - ifnull(numeric,numeric) - ifnull(timestamp,timestamp) - ifnull(timestamptz,timestamptz) - isnull(text) -- Note: openGauss will recognize '' empty strings as NULL if the database is created with the default A-compatible mode. - isnull(numeric) - isnull(timestamptz) ### Conditional control functions - if(bool,bool,bool) - if(bool,text,text) - if(bool,numeric,numeric) - if(bool,timestamptz,timestamptz) ### Character functions - find_in_set(text,text) - find_in_set(text,text[]) - field(text,text[]) - elt(int4,text[]) - strcmp(text,text) - insert(text,int8,int8,text) - lcase(text) - ucase(text) - space(int4) - mid(text,int8,int8) - locate(text,text,int4) - to_base64(text) - from_base64(text) ### Numeric functions - field(numeric,numeric[]) - log10(numeric) - log10(float8) - rand(int4) ### Time functions - unix_timestamp(timestamp) - unix_timestamp(timestamptz) - from_unixtime(int8) - from_unixtime(numeric) - from_unixtime(numeric,text) - to_days(timestamp) - to_days(timestamptz) - to_days(text) - to_days(text,text) - to_days(int8) - to_seconds(timestamp) - to_seconds(timestamptz) - timediff(timestamptz,timestamptz) - time_to_sec(time) - sec_to_time(int4) - date_format(timestamp, text) - date_format(timestamptz, text) - timestampdiff(text,timestamptz,timestamptz) -- Note: Schema must be prefixed with pg_catalog. and the first unit argument must be wrapped in single quotes. - str_to_date(text,text) -- Due to time type differences between MySQL and openGauss, this compatibility function is not fully consistent, please refer to the use case description at the end of the corresponding function for details. - curdate() - yearweek(timestamp,int4) -- Since openGauss uses iso standard for week start time, the second parameter of MySQL is 3, so this function is not fully compatible. - yearweek(timestamptz,int4) - yearweek(text,int4) - date_add(timestamp,interval) -- The number in the second argument needs to be wrapped in single quotes - date_add(timestamptz,interval) ### Other functions - uuid() -- Use hash based on a random value + timestamp to compute the uuid. - uuid_to_bin(uuid, int4) - bin_to_uuid(bytea, int4) - conv(text, int4, int4) -- currently only supports binary, decimal, hexadecimal conversion. - json_extract(json,text) - json_extract(json,text[]) ## DB2 compatibility functions ### NULL-related functions > Note: `value` is equivalent to the generic `coalesce` function, if possible, it is recommended to modify SQL to use the `coalesce` function, which is supported by almost all databases. - value(text,text) - value(numeric,numeric) - value(timestamp,timestamp) - value(timestamptz,timestamptz) ### Character functions - posstr(text,text) - locate_in_string(text,text,int4,int4,text) - regexp_match_count(text,text,int4,text,text) ### Time functions - year (text) - year (timestamptz) - year (interval) - month (text) - month (timestamptz) - month (interval) - quarter (timestamptz) - week (timestamptz) - day (text) - day (timestamptz) - day (interval) - hour (text) - hour (timestamptz) - hour (interval) - minute (text) - minute (timestamptz) - minute (interval) - second (text) - second (timestamptz) - second (interval) - days (timestamptz) - dayofyear (timestamptz) - dayofweek (timestamptz) - dayofweek_iso (timestamptz) - dayname (timestamptz) - monthname (timestamptz) - midnight_seconds (timestamptz) - next_day (timestamptz,text,text) - next_month (timestamptz) - next_quarter (timestamptz) - next_week (timestamptz) - next_year (timestamptz) - last_day (timestamptz) - first_day (timestamptz) - this_month (timestamptz) - this_quarter (timestamptz) - this_week (timestamptz) - this_year (timestamptz) - days_between (timestamptz,timestamptz) - years_between (timestamptz,timestamptz) - ymd_between (timestamptz,timestamptz) ## Roadmap