I have a rush job to take an SQL product that works on PostGre and Amazon's RedShift, and port it to work on Oracle. (Note that "work" does not currently imply "optimally" but rather "correctly".)
All of our TABLEs are defined using an ORM (DBI), but all of our VIEWs are currently stored as in-line SQL.
My hope is that there is a relatively simple way to run encapsulate the SQL in a kind of generic sense and use some existing tools to translate it in to Dialect Specific SQL.
Trivial Example:
SELECT CAST(x AS DECIMAL(16,4)) AS foo FROM bah
=>SELECT CAST(x AS NUMBER(16,4)) AS foo FROM bah
That was simple. We have a "find and replace stage" when we deploy. The SQL is stored as CAST(x AS #DECIMAL#(16,4))
and then we replace #DECIMAL#
with a new string depending on what dialect we are deploying to.
Frustrating Example:
SELECT x % y AS modulo FROM foo
=>SELECT MOD(x, y) AS modulo FROM foo
And...
SELECT x / y AS int_div FROM foo
=>SELECT trunc(x / y) AS int_div FROM foo
I'm no PERL expert, so I'm looking for pointers on how to do some kind of macro expansion.
- The SQL would be stored with some kind of macro expression in the string
- A "processor" would be called with parameters including "dialect" and "sql"
- The "dialect" parameter would dictate the output of the macro expansion
Dialectless-SQL: SELECT #DIV(x,y)# AS z FROM foo
Dialect: RedShift
Output : SELECT x / y AS z FROM foo
Dialect: Oracle11g
Output : SELECT floor(x / y) AS z FROM foo
It would need to cope with sub-queries, etc:
Dialectless-SQL: SELECT #MOD(x, (SELECT MAX(y) FROM bah))# AS z FROM foo
Dialect: RedShift
Output : SELECT x % (SELECT MAX(y) FROM bah) AS z FROM foo
Dialect: Oracle11g
Output : SELECT mod(x, (SELECT MAX(y) FROM bah)) AS z FROM foo
Or any reliable method for storing "generic" SQL, and being able to translate it to "dialect specific" SQL.