i use the existing Postgres compatible parser from cockroachdb to generate the ast,
then i turn the ast to xorm builder, and use the builder to generate the translated sql
Most of the extracted codes origin of Postgres compatible parser: /cockroachdb/cockroach/tree/master/pkg/sql/parser
the project is WIP, now only limited grammar of postgres are supported, it's all from my project:
-
select a::int from bwill be translated to :SELECT CAST(a AS NUMBER) FROM b -
insert into a(field1) values('value1') on conflict (field1) do update set b = 'value2':MERGE INTO a t USING (select 'value1' field1 FROM DUAL) s ON ((SELECT t.field1 FROM DUAL) = s.field1) WHEN MATCHED THEN UPDATE SET b = 'value2' WHEN NOT MATCHED THEN INSERT (field1) VALUES(s.field1) -
insert into a(field1) values('value1') on conflict (field1) do update set b = 'value2' returning id:Savepoint a; MERGE INTO a t USING (select 'value1' field1 FROM DUAL) s ON ((SELECT t.field1 FROM DUAL) = s.field1) WHEN MATCHED THEN UPDATE SET b = 'value2' WHEN NOT MATCHED THEN INSERT (field1) VALUES(s.field1); SELECT id FROM a WHERE field1='value1'; commit; -
update a set b = 'value1' where c = 'value2' returning e:Savepoint a; UPDATE a SET b='value1' WHERE c='value2'; SELECT e FROM a WHERE c='value2'; commit; -
update a set b = 'value1' where c = now()(there are plenty of functions that are different, to support them, more works are needed)UPDATE a SET b='value1' WHERE c=(SYSTIMESTAMP) -
select title from tasks limit 1SELECT title FROM (SELECT title,ROWNUM RN FROM tasks) at WHERE at.RN<=1 -
select title from tasks limit 1 offset 2SELECT title FROM (SELECT * FROM (SELECT title,ROWNUM RN FROM tasks) at WHERE at.RN<=3) att WHERE att.RN>2 -
select * from tasks where title ilike 'sdf%':SELECT * FROM tasks WHERE UPPER(title) LIKE UPPER('sdf%') -
select (extract(year from now()) - extract(year from date_of_birth))::int from dual:SELECT CAST(extract(year FROM SYSTIMESTAMP) - extract(year FROM date_of_birth) AS NUMBER) FROM dual -
select count(distinct $1) from b:SELECT count(DISTINCT :1) FROM b -
update a set b = b+'1'::int:UPDATE a SET b=(b + CAST('1' AS NUMBER))
-
most functions which has no corresponding function in oracle
-
insert into *** returning id