E.3. Release 13.8-23.4

E.3.1. Oracle Compatibility
E.3.2. pl/sql Enhancements
E.3.3. MySQL Compatibility
E.3.4. Lightdb-x New Features
E.3.5. ltjdbc Enhancements
E.3.6. Add Reserved Keywords

Release date: 2023-12-31

E.3.1. Oracle Compatibility

  • Supports the set definecommand, which can be used to enable or disable variable replacement functionality. see set define on/off command.

  • Client command line support '/'. see Slashes.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    Select 1+2;
    ?column? 
    ----------
    3
    (1 row)
    
    /
                  
  • Uppercase field names can be added with double quotation marks during queries. see Lexical Structure.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create table t1(id int, "Id" int);
    
    insert into t1 values(1,2),(3,4),(5,6);
    
    select "ID" from t1;
     ID 
    ----
      1
      3
      5
    (3 rows)       
                  
  • Addition and subtraction of timestamp,oracle.dateand numeric values are supported. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    Create table t_data(dt date, d1 integer, d2 bigint, d3 smallint, d4 numeric(10, 2), dd date);
    
    insert into t_data values(to_date('2023-11-28 20:10:30', 'YYYY-MM-DD HH24:mi:ss'), 1, 2, 3, 4.4, to_date('2023-11-27 20:10:30', 'YYYY-MM-DD HH24:mi:ss'));
    
    insert into t_data values(to_date('2023-11-28 00:00:01', 'YYYY-MM-DD HH24:mi:ss'), 1, 2, 3, 4.5, to_date('2023-11-27 00:00:02', 'YYYY-MM-DD HH24:mi:ss'));
    
    select dt, dt - d1, dt - d1 + d2 , dt - d1 + d2 - d3, dt - d1 + d2 - d3 + d4, dt - dd from t_data;
             dt          |      ?column?       |      ?column?       |      ?column?       |      ?column?       |        ?column?        
    ---------------------+---------------------+---------------------+---------------------+---------------------+------------------------
     2023-11-28 20:10:30 | 2023-11-27 20:10:30 | 2023-11-29 20:10:30 | 2023-11-26 20:10:30 | 2023-12-01 05:46:30 | 1.00000000000000000000
     2023-11-28 00:00:01 | 2023-11-27 00:00:01 | 2023-11-29 00:00:01 | 2023-11-26 00:00:01 | 2023-11-30 12:00:01 | 0.99998842592592592500
    (2 rows)
                  
  • Rownum can be used as an rvalue expression. See ROWNUM.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    SELECT TO_CHAR(TO_DATE(TRIM('20230110'), 'YYYYMMDD') + ROWNUM, 'YYYYMMDD') from dual;
     to_char  
    ----------
     20230111
    (1 row)
                  
  • The value type in the decode function parameter is equivalent to the invalid 0 in the decimal place of the value. see DECODE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    SELECT decode(0.0, 0, 1, 2), decode(0, 0, 1, 2), decode(0, 0.0, 1, 2), decode(0, 1, 2, 0.0, 4, 5)  FROM dual;
     decode | decode | decode | decode 
    --------+--------+--------+--------
          1 |      1 |      1 | 4
    (1 row)
    
    SELECT decode(1.10, 1.1, 1, 2) FROM dual;
     decode 
    --------
          1
    (1 row)
    
    SELECT decode(1.0, 1, 1, 2) FROM dual;
     decode 
    --------
          1
    (1 row)
                  
  • The substr function supports a combination of text,numeric,numeric or text,numeric. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create table tt_substr(a number(10), b number(10));
    
    INSERT INTO tt_substr (a, b) VALUES(2, 1);
    
    select substr('aaaaa'::varchar2, 2, a + b) FROM tt_substr;
     substr 
    --------
     aaa
    (1 row)
    
    select substr('aaaaa'::varchar2, a) FROM tt_substr;
     substr 
    --------
     aaaa
    (1 row)
                  
  • The to_char function changes the date and number format to text format. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    Select to_char(sysdate+1 + interval '-1' year,'d','NLS_DATE_LANGUAGE=''SIMPLIFIED CHINESE''');
     to_char 
    ---------
     6
    (1 row)
                  
  • The rawtohex function supports the uuid type as a parameter. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select rawtohex(sys_guid()) from dual;
                 rawtohex             
    ----------------------------------
     6653ab0b8ad34634bdc1645f3f264455
    (1 row)
                  
  • The rowidtochar function converts the rowid type to a character type. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create table tt1(idd int);
    
    insert into tt1 values(3);
    
    create table tt7 as select rowidtochar(rowid) as rowid1,*  from tt1;
    
    \d tt7
                     Table "public.tt7"
     Column |   Type   | Collation | Nullable | Default 
    --------+----------+-----------+----------+---------
     rowid1 | varchar2 |           |          | 
     idd    | integer  |           |          | 
                  
  • The to_timestamp converts the character time value to a timestamp format. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    SELECT TO_TIMESTAMP('2023-10-11 10:10:10', 'YYYY-MM-DD HH:MI:SS PM')  FROM dual;
          to_timestamp      
    ------------------------
     2023-10-11 10:10:10+08
    (1 row)
                  
  • Support empty_clob/empty_blob initialization of LOB objects, The return is not null, empty_blob() is null is not established. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    Select empty_clob();
     empty_clob 
    ------------
     
    (1 row)
    
    Select empty_blob();
     empty_blob 
    ------------
     \x
    (1 row)
                  
  • The systimestamp(n)supports precision parameters. see Date/Time Functions.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select current_timestamp,systimestamp(0);
           current_timestamp       |      systimestamp      
    -------------------------------+------------------------
     2024-01-02 01:48:16.899369-05 | 2024-01-02 01:48:17-05
    (1 row)
    
    select current_timestamp,systimestamp(1);
           current_timestamp       |       systimestamp       
    -------------------------------+--------------------------
     2024-01-02 01:48:16.900603-05 | 2024-01-02 01:48:16.9-05
                  
  • The parameters of the NVL function can be set to null. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select nvl(null::numeric, '0');
     nvl 
    -----
       0
    (1 row)
                  
  • The time string of the supported to_date function does not match the output data format. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select to_date('2022/02/02','yyyy-mm-dd') from dual;
           to_date       
    ---------------------
     2022-02-02 00:00:00
    (1 row)
            
  • The xmlparse and xmlagg functions are supported. see XML Functions.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    SELECT XMLPARSE(CONTENT '124 <purchaseOrder poNo="12435"> 
    <customerName> Acme Enterprises</customerName>
    <itemNo>32987457</itemNo>
    </purchaseOrder>' 
    WELLFORMED) AS PO FROM DUAL;
    
    po                         
    ---------------------------------------------------
     124 <purchaseOrder poNo="12435">                 
     <customerName> Acme Enterprises</customerName> 
     <itemNo>32987457</itemNo>                      
     </purchaseOrder>
    (1 row)
                  
  • Create a partition table name that does not exceed 31 characters in length. see CREATE TABLE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE test_partition_table_len_31__lh(a int,b int) 
    PARTITION BY list(a)
    SUBPARTITION BY hash(b)
    (
        PARTITION p11 VALUES(1,2,3,4),
        PARTITION p12 VALUES(5,6,7,8)
    ); 
                  
  • The object type can be rebuilt by replace. see CREATE TYPE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE OR REPLACE TYPE employee_type AS OBJECT(
    x int,
    y int,
    MEMBER FUNCTION psum(a int, b int) RETURN int,
    MEMBER PROCEDURE p(prompt varchar)
    );
    CREATE TYPE.
                  
  • Support commands of alter session enable/disable parallel dml. see ALTER SESSION.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    alter session enable parallel dml;
                  
  • Supports tabs view, a built-in view of all tablespaces and their associated objects in the database. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE measurement (                                                                                                                    
        city_id         int not null,
        logdate         date not null,
        peaktemp        int,
        unitsales       int
    ) PARTITION BY RANGE (logdate);
    
    SELECT table_name, tablespace_name FROM oracle.TABS WHERE TABLE_NAME IN ('TEST_VIEW', 'MEASUREMENT', 'MEASUREMENT_Y2018') ORDER BY TABLE_NAME;
    
    table_name  | tablespace_name 
    -------------+-----------------
     MEASUREMENT | DEFAULT
    (1 row)
                  
  • Support online conversion of regular tables to list type partitioned tables, and synchronously update indexes. see CREATE TABLE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE my_list_tab ( a NUMBER(38,0), cu VARCHAR2(20));
    insert into my_list_tab values(1,'china');
    insert into my_list_tab values(2,'THAILAND');
    insert into my_list_tab values(3,'GERMANY');
    insert into my_list_tab values(4,'ITALY');
    insert into my_list_tab values(5,'SWITZERLAND');
    insert into my_list_tab values(6,'AMERICA');
    insert into my_list_tab values(7,'INDIA');
    
    CREATE INDEX i_a ON my_list_tab (a);
    CREATE INDEX i_cu ON my_list_tab (cu);
    
    ALTER TABLE my_list_tab MODIFY PARTITION BY LIST (cu) (
       PARTITION asia VALUES ('CHINA', 'THAILAND'),
       PARTITION europe VALUES ('GERMANY', 'ITALY', 'SWITZERLAND'),
       PARTITION west VALUES ('AMERICA'),
       PARTITION east VALUES ('INDIA'),
       PARTITION rest VALUES (DEFAULT))
    online
       update indexes
      ( i_a GLOBAL,
        i_cu local
      );
    
    \d+ my_list_tab
                                 Partitioned table "public.my_list_tab"
     Column |     Type      | Collation | Nullable | Default | Storage  | Stats target | Description 
    --------+---------------+-----------+----------+---------+----------+--------------+-------------
     a      | numeric(38,0) |           |          |         | main     |              | 
     cu     | varchar2(20)  |           |          |         | extended |              | 
    Partition key: LIST (cu)
    Indexes:
        "i_a" btree (a)
        "i_cu" btree (cu)
    Partitions: "my_list_tab$asia" FOR VALUES IN ('CHINA', 'THAILAND'),
                "my_list_tab$east" FOR VALUES IN ('INDIA'),
                "my_list_tab$europe" FOR VALUES IN ('GERMANY', 'ITALY', 'SWITZERLAND'),
                "my_list_tab$west" FOR VALUES IN ('AMERICA'),
                "my_list_tab$rest" DEFAULT
                  
  • If (+) is used to join multiple tables in a SELECT query, you can specify the table name for the distinct column in the where condition. see SELECT.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    Create table t1(key1 int, key2 int);
    
    Create table t2(key1 int);
    
    Select * from t1, t2 where t1.key1(+)=t2.key1 and key2=2;
     key1 | key2 | key1 
    ------+------+------
    (0 rows)
                  
  • Supports the combination of aggregate count(*) and order by. see SELECT.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE EMP
    (   EMPNO    NUMBER(4, 0),
        ENAME    VARCHAR2(10),
        JOB      VARCHAR2(9),
        MGR      NUMBER(4, 0),
        HIREDATE DATE,
        SAL      NUMBER(7, 2),
        COMM     NUMBER(7, 2),
        DEPTNO   NUMBER(2, 0),
        DNAME    VARCHAR2(100),
        CONSTRAINT PK_EMP PRIMARY KEY (EMPNO)
    );
    
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7369, 'SMITH',  'CLERK',    7902, to_date('1980-12-17','yyyy-mm-dd'), 800.00,  null,    20, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7499, 'ALLEN',  'SALESMAN', 7698, to_date('1981-02-20','yyyy-mm-dd'), 1600.00, 300.00,  30, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7521, 'WARD',   'SALESMAN', 7698, to_date('1981-02-22','yyyy-mm-dd'), 1250.00, 500.00,  30, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7566, 'JONES',  'MANAGER',  7839, to_date('1981-04-02','yyyy-mm-dd'), 2975.00, null,    20, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7654, 'MARTIN', 'SALESMAN', 7698, to_date('1981-09-28','yyyy-mm-dd'), 1250.00, 1400.00, 30, null);
    
    select count(*) from emp order by empno;
     count 
    -------
         6
    (1 row)
                  
  • connect by supports binding variables. see SELECT.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    PREPARE my_query (VARCHAR) AS
    SELECT LEVEL, empno
    FROM emp
    CONNECT BY PRIOR empno = mgr
    START WITH ename = $1;
    
    EXECUTE my_query('ALLEN');
     level | empno 
    -------+-------
         1 |  7499
    (1 row)
                  
  • The merge into statement supports the branch of the insert statement and the use of table aliases. see MERGE INTO.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE EMP
    (   EMPNO    NUMBER(4, 0),
        ENAME    VARCHAR2(10),
        JOB      VARCHAR2(9),
        MGR      NUMBER(4, 0),
        HIREDATE DATE,
        SAL      NUMBER(7, 2),
        COMM     NUMBER(7, 2),
        DEPTNO   NUMBER(2, 0),
        DNAME    VARCHAR2(100),
        CONSTRAINT PK_EMP PRIMARY KEY (EMPNO)
    );
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7369, 'SMITH',  'CLERK',    7902, to_date('1980-12-17','yyyy-mm-dd'), 800.00,  null,    20, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7499, 'ALLEN',  'SALESMAN', 7698, to_date('1981-02-20','yyyy-mm-dd'), 1600.00, 300.00,  30, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7521, 'WARD',   'SALESMAN', 7698, to_date('1981-02-22','yyyy-mm-dd'), 1250.00, 500.00,  30, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7566, 'JONES',  'MANAGER',  7839, to_date('1981-04-02','yyyy-mm-dd'), 2975.00, null,    20, null);
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, DNAME) values (7654, 'MARTIN', 'SALESMAN', 7698, to_date('1981-09-28','yyyy-mm-dd'), 1250.00, 1400.00, 30, null);
     
    declare
    i number;
    begin
    execute immediate q'[MERGE INTO emp e
    USING (
        SELECT 
             1 as empno, 
            'ename' as ename
        FROM dual
    ) new_data
    ON (e.empno = new_data.empno)   
    WHEN MATCHED THEN 
        UPDATE SET e.ename = new_data.ename
    WHEN NOT MATCHED THEN 
        INSERT (e.empno, e.ename) VALUES (
            new_data.empno, 
            new_data.ename
        )]';
    commit;
    end;
    /
                  
  • Added 6 optimizer hints. see lt_hint_plan.

    • Supported ignore_row_on_dupkey_index hint, Prompt: Ignore unique key violations for specific column sets or specified indexes.

    • Supported push_subq hint. Prompt: Force the optimizer to push down the filter condition of the band link, and only use this condition to filter data at the end.

    • Supported no_push_subq hint. Prompt: Force the optimizer to push down the filter condition of the band link, and use this condition to filter the data as early as possible.

      For example:

      create database test_oracle with lightdb_syntax_compatible_type oracle;
      \c test_oracle
      
      create table test_no_push_subq1 as select * from pg_class order by oid limit 100;
      create table test_no_push_subq2 as select * from pg_class order by oid limit 100;
      create table test_no_push_subq3 as select * from pg_class order by oid limit 100;
      create table test_no_push_subq4 as select * from pg_class order by oid limit 100;
      
      EXPLAIN (COSTS false)
      select a.oid from test_no_push_subq1 a join test_no_push_subq3 b on a.reltype =b.reltype and a.oid = b.oid
      where a.oid = (select/*+no_push_subq*/ max(oid) from test_no_push_subq2);
                               QUERY PLAN                         
      ------------------------------------------------------------
       Hash Join
         Hash Cond: ((a.reltype = b.reltype) AND (a.oid = b.oid))
         Join Filter: (a.oid = $0)
         InitPlan 1 (returns $0)
           ->  Aggregate
                 ->  Seq Scan on test_no_push_subq2 @"lt#0"
         ->  Seq Scan on test_no_push_subq1 a @"lt#1"
         ->  Hash
               ->  Seq Scan on test_no_push_subq3 b @"lt#1"
      (9 rows)
      
    • Supported opt_param hint. Prompt: Modify the GUC parameters during the generation of an execution plan.

    • Supported no_star_transformation hint. Prompt: The optimizer does not perform star query transformations.

      For example:

      create database test_oracle with lightdb_syntax_compatible_type oracle;
      \c test_oracle
      
      CREATE TABLE times (
      
        time_id NUMBER PRIMARY KEY,
      
        calendar_quarter_desc VARCHAR2(20)
      
      );
      
      
      CREATE TABLE customers (
      
        cust_id NUMBER PRIMARY KEY,
      
        cust_city VARCHAR2(20),
      
        cust_state_province VARCHAR2(20)
      
      );
      
      
      CREATE TABLE channels (
      
        channel_id NUMBER PRIMARY KEY,
      
        channel_class VARCHAR2(20),
      
        channel_desc VARCHAR2(20)
      
      );
      
      
      CREATE TABLE sales (
      
        time_id NUMBER REFERENCES times(time_id),
      
        cust_id NUMBER REFERENCES customers(cust_id),
      
        channel_id NUMBER REFERENCES channels(channel_id),
      
        amount_sold NUMBER
      
      );
      
      EXPLAIN (COSTS false) SELECT/*+no_star_transformation*/ ch.channel_class, c.cust_city, t.calendar_quarter_desc,
             SUM(s.amount_sold) sales_amount
          FROM sales s, times t, customers c, channels ch
          WHERE s.time_id = t.time_id
          AND s.cust_id = c.cust_id
          AND s.channel_id = ch.channel_id
          AND c.cust_state_province = 'CA'
          AND ch.channel_desc in ('Internet','Catalog')
          AND t.calendar_quarter_desc IN ('1999-Q1','1999-Q2')
          GROUP BY ch.channel_class, c.cust_city, t.calendar_quarter_desc;
      LOG:  lt_hint_plan:
      used hint:
      no_star_transformation
      not used hint:
      duplication hint:
      error hint:
      
                                                    QUERY PLAN                    
                                 
      ----------------------------------------------------------------------------
      ---------------------------
       GroupAggregate
         Group Key: ch.channel_class, c.cust_city, t.calendar_quarter_desc
         ->  Sort
               Sort Key: ch.channel_class, c.cust_city, t.calendar_quarter_desc
               ->  Nested Loop
                     ->  Nested Loop
                           ->  Hash Join
                                 Hash Cond: (s.cust_id = c.cust_id)
                                 ->  Seq Scan on sales s @"lt#0"
                                 ->  Hash
                                       ->  Seq Scan on customers c @"lt#0"
                                             Filter: ((cust_state_province)::text 
      = 'CA'::text)
                           ->  Index Scan using times_pkey on times t @"lt#0"
                                 Index Cond: (time_id = s.time_id)
                                 Filter: ((calendar_quarter_desc)::text = ANY ('{1
      999-Q1,1999-Q2}'::text[]))
                     ->  Index Scan using channels_pkey on channels ch @"lt#0"
                           Index Cond: (channel_id = s.channel_id)
                           Filter: ((channel_desc)::text = ANY ('{Internet,Catalog
      }'::text[]))
      (18 rows)
                    
    • Supported no_push_pred hint. Prompt:The optimizer does not push the join predicate into a subquery.

      For example:

      create database test_oracle with lightdb_syntax_compatible_type oracle;
      \c test_oracle
      
      create table test_no_push_pred1 (key1 int primary key, key2 int);
      create table test_no_push_pred2 (key1 int primary key, key2 int);
      create table test_no_push_pred3 (key1 int primary key, key2 int);
      
      set enable_hashjoin to off;
      set enable_mergejoin to off;
      
      EXPLAIN (COSTS false)
      select /*+leading(a) no_push_pred(b)*/* from test_no_push_pred1 a join (select * from test_no_push_pred2 order by key1 limit 1) b on a.key1 =b.key2;
                                          QUERY PLAN                              
            
      ----------------------------------------------------------------------------
      ------
       Nested Loop
         Join Filter: (a.key1 = test_no_push_pred2.key2)
         ->  Seq Scan on test_no_push_pred1 a @"lt#1"
         ->  Materialize
               ->  Limit
                     ->  Index Scan using test_no_push_pred2_pkey on test_no_push_pred2
      (6 rows)
                    
    • Supported append hint. Prompt: The optimizer to use direct-path insertion for statements in insert select mode.

      For example:

      create database test_oracle with lightdb_syntax_compatible_type oracle;
      \c test_oracle
      
      create table test_append(key1 int, key2 int, key3 int, key4 int);
      create table test_append1(key1 int, key2 int, key3 int, key4 int);
      
      insert into test_append1 values(1,2,3,4);
      insert into test_append1 values(11,21,31,41);
      insert into test_append1 values(111,211,311,411);
      
      EXPLAIN (COSTS FALSE) insert/*+append */ into test_append select 1, 1, 1, 2 from dual;
      LOG:  lt_hint_plan:
      used hint:
      not used hint:
      append
      duplication hint:
      error hint:
      
                QUERY PLAN           
      -------------------------------
       Insert on test_append @"lt#1"
         ->  Result
      (2 rows)
                    
  • The to_char supports HH24MiSS time format. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select to_char(timestamp 'now','HH24MiSS');
     to_char 
    ---------
     042121
    (1 row)
                  
  • Table functions column_value pseudo-columns. see Table function.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create type phone as table of int;
    CREATE TYPE
    
    select column_value from table(phone(3,6,9));
     column_value 
    --------------
                3
                6
                9
    (3 rows)
                  
  • Support pivot function. Only single clustering functions, single columns and multiple groups are supported. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create table test123(name varchar(40),chinese int,math int, course varchar(40), score int);
    insert into test123 values('lisi',88,99,'math',99);
    insert into test123 values('lisi',88,99,'chinese',88);
    insert into test123 values('zhangsan',90,100,'chinese',90);
    insert into test123 values('zhangsan',90,100,'math',100);
    
    select * from test123 pivot (sum(score) for course in('chinese','math'));
       name   | chinese | math | 'chinese' | 'math' 
    ----------+---------+------+-----------+--------
     lisi     |      88 |   99 |        88 |     99
     lisi     |      89 |  100 |           |     99
     lisi     |     100 |   70 |       100 |       
     zhangsan |      76 |   89 |        99 |       
     zhangsan |      90 |  100 |        90 |    100
     zhangsan |      95 |   85 |           |    100
    (6 rows)
    
    drop table test123;
                  
  • Merge INTO supports CTE general table expressions. see MERGE INTO.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE TABLE target (tid integer, balance integer);
    CREATE TABLE source (sid integer, delta integer);
    INSERT INTO target VALUES (2, 20);
    INSERT INTO target VALUES (3, 30);
    
    INSERT INTO source VALUES (1, 11);
    INSERT INTO source VALUES (5, 55);
    
    WITH s AS ( 
        SELECT sid, delta
        FROM source ), 
    U AS ( 
    UPDATE target AS t  
        SET tid = 5
        FROM s 
        WHERE t.tid = s.sid
        RETURNING t.tid ) 
    INSERT INTO target ( 
        SELECT * FROM s where sid NOT IN (
            SELECT tid FROM U) );
    
    table target;
     tid | balance 
    -----+---------
       2 |      20
       3 |      30
       5 |      10
       1 |      11
    (4 rows)
                  
  • Immutable tables are supported. see CREATE TABLE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    CREATE IMMUTABLE TABLE trade_ledger1 
                           (id NUMBER,
                           luser VARCHAR2(40),
                           value NUMBER)
                          NO DROP
                          NO DELETE;
    CREATE TABLE
                  
  • The group by follows the string constant. see SELECT.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    select * from dual group by 1;
     dummy 
    -------
     X
    (1 row)
                  
  • Supported alter to add constraints to tables. see ALTER TABLE.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
    create table add_constraints(id int);
    
    alter table add_constraints add constraint u_add_constraints unique(id);
    ALTER TABLE
                  
  • Listagg on overflow truncate and error syntax are supported. see see orafce.

  • Creating views supports force editionable and with read only syntax. see CREATE VIEW.

  • Global temporary tables can be created in different schema modes. see System Catalogs.

  • varchar2 supports toast attributes. see orafce.

  • The number type is formatted without keeping the decimal suffix invalid 0. see orafce.

    For example:

    create database test_oracle with lightdb_syntax_compatible_type oracle;
    \c test_oracle
    
     select nvl(cast(NULL as int),'1.100');
     nvl 
    -----
     1.1
    (1 row)
                  
  • dblink is supported. see oracle_fdw.

E.3.2. pl/sql Enhancements

  • The number of input and output parameters supported by the function exceeds 100. see Anonymous Block.

  • The input and exit parameters of the stored procedure that can be created are sys_refcursor. see Creating Cursor Variables.

  • Support for varray arrays. see Varrays.

  • Anonymous blocks, functions, stored procedures, and packages support integer types with length information, up to 19 bits. see Integer Types.

  • Support execute immediate using in out syntax. see Executing Dynamic Commands.

E.3.3. MySQL Compatibility

  • Added CAST cast to SIGNED or UNSIGNED destination type. See MySQL Compatible Functions.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    select cast(2.5 as unsigned);
     numeric2unsigned 
    ------------------
                    3
    (1 row)
    
    select cast('2.5' as unsigned);
     numeric2unsigned 
    ------------------
                    3
    (1 row)
    
    select cast(2.5 as signed);
     signed 
    --------
          3
    (1 row)
    
    select cast('2.5' as signed);
     signed 
    --------
          2
    (1 row)
                    
  • Added cast to char target type, The default length of the char is 1, and the number of forcibly converted, the string will not be truncated if the length exceeds 1, and the upper limit is 1GB. See data type.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    select cast(2.5 as char);
     varchar 
    ---------
     2.5
    (1 row)
                    
  • Support for comparison of numeric types and null characters. The value of the string is 0. See MySQL Compatible Functions.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    select 0  = '';
     ?column? 
    ----------
     t
    (1 row)
                    

    When characters (including text, varchar, char only) are converted Numeric values (including int, bigint, numeric, small int only), Ignore invalid characters at the trail.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    select '1a' >'';
     ?column? 
    ----------
     t
    (1 row)
                    
  • Optimize transform_null_equals parameters. Compatible with null and '' relational operations. See MySQL Compatible Functions.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    SELECT '' IS null;
     ?column? 
    ----------
     f
    (1 row)
    
    SELECT null = '';
     ?column? 
    ----------
     
    (1 row)
                
  • Time types and strings are supported. See MySQL Compatible Functions.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    select current_date > '2023-01-01';
     ?column? 
    ----------
     t
    (1 row)
                    
  • Add a time type function.

    • DATEDIFF function. Support the difference between date and value type, and the difference between value type and value type; When the numeric type is floating-point type, the truncate floating-point type is an integer first, and then the difference is calculated. See MySQL Compatible Functions.

      For example:

      create database test_mysql with lightdb_syntax_compatible_type mysql;
      \c test_mysql
      SELECT DATEDIFF(curdate(),curdate()+1.5);
       datediff 
      ----------
             -1
      (1 row)
      
      SELECT DATEDIFF(curdate(),curdate()-1.5);
       datediff 
      ----------
              2
      (1 row)
                         
    • TIMESTAMPDIFFfunction. See MySQL Compatible Functions.

    • CURRENT_DATEfunction. See Current Date/Time.

    • CURDATEfunction. The function return format only supports 'YYYY-MM-DD', and does not support multiplication and division. See MySQL Compatible Functions.

    • QUARTERfunction. The return date represents the quarter, and the number range is 1 ~ 4. If the date is NULL, NULL is returned; Input parameters only support date and timestamp (datetime) types. See MySQL Compatible Functions.

    • LAST_DAYfunction. Returns the date value of the last day of the month in which the parameter is located. See MySQL Compatible Functions.

  • SUBSTRING_INDEXfunction. Returns the substring from the specified string before the specified delimiter appears n times. See MySQL Compatible Functions.

  • UUIDfunction. Generate a 36-byte UUID string. See MySQL Compatible Functions .

  • AESEncrypt and decrypt. Perform the following AES encryption and decryption and hexadecimal conversion operations. See MySQL Compatible Functions .

    • HEXfunction. The HEX function converts bytea data to text.

    • UNHEXfunction. The UNHEX function converts varchar data to bytea.

    • AES_ENCRYPTfunction. AES encryption functions.

    • AES_DECRYPTfunction. AES decryption function.

  • The time type supports string assignment. In the insert and update statements, Values of type char(n), varchar, and text can be used Assign a value to a property of type timestamp with time zone, datetime. See MySQL Compatible Functions.

  • Dynamic preprocessing statements are supported.

    • Support SET to assign values to @variables. See User Variable.

    • PREPARE FROM preprocessing syntax. See PREPARE.

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    create table my_table(a varchar(200));
    
    SET @sql = 'INSERT INTO my_table values(''a'')';  
                   @sql               
    ----------------------------------
     INSERT INTO my_table values('a')
    (1 row)
    
    PREPARE stmt FROM @sql;  
    
    EXECUTE stmt;
    INSERT 0 1
    
    DEALLOCATE PREPARE stmt;
                       
  • WITH ROLLUP syntax to generate extra rows in the aggregate query for data aggregation. See GROUP BY .

    For example:

    create database test_mysql with lightdb_syntax_compatible_type mysql;
    \c test_mysql
    CREATE TABLE score (
    	id int,
    	name varchar(100),
    	course varchar(100),
    	score int
    );
    
    INSERT INTO score VALUES(1,'zhangsan','yuwen',58);
    INSERT INTO score VALUES(2,'lisi','shuxue',38);
    
    SELECT name, COUNT(id), SUM(score) FROM score GROUP BY name WITH ROLLUP;
       name   | count | sum 
    ----------+-------+-----
              |     2 |  96
     lisi     |     1 |  38
     zhangsan |     1 |  58
    (3 rows)
                       
  • CASE WHEN type compatible. The result set of a CASE WHEN expression can be a character, a numeric value, a date. If it contains any two or more characters, values, and dates, the return value is a string. See Conditional Expressions .

  • Numeric types are compatible with Boolean types. The value of the integer type is used as a boolean. See MySQL Compatible Functions.

  • Autoincrement sequences support NULL. See MySQL Compatible Functions.

E.3.4. Lightdb-x New Features

  • Added a record of modifying the guc parameter in lightdb.conf See Parameter Interaction via SQL .

  • All types, system tables, and functions are built into the OID unchanged.

  • Adjust keyword level. See SQL Key Words .

  • The template library distinguishes between Oracle, MySQL and Postgres patterns. See CREATE DATABASE.

E.3.5. ltjdbc Enhancements

  • Support for converting numeric to varchar.

  • Support for converting int to double.

  • Support varchar conversion to long.

  • Support for converting timestamptz to java.time.LocalDateTime.

  • Anonymous block parameter binding is supported, and the maximum number of bindings is 32767.

  • The clob.setCharacterstream function is supported.

  • The getColumnType method of metaData returns the varchar2 type.

  • Primary key conflict throws an anomaly of java.sql.SQLIntegrityConstraintViolationException

  • The binding parameters are passed with setNull, and the types can be matched correctly.

E.3.6. Add Reserved Keywords

  • pivot.