Automatic SQL Syntax Conversion
Aubit4GL allows you to connect to DBMS's (database management systems) from various vendors, as long the connection is via the SQL command language.
Unfortunately, the syntax of the SQL language can differ considerably from one vendor to another, and often valid syntax for one DBMS fails when executed against some other DBMS. One way around this is to maintain different versions of your application, eg. one for use with Informix, another for running against Oracle, another for PostgreSQL, and so on. Another way is to replace each SQL command in your source code with a number of alternatives in a case statement, depending on the target database type. Either way, your code will be difficult to maintain and harder to read.
Aubit4GL resolves this by providing a module that lets you write code using just one version or "dialect" of SQL, and have this converted into the correct form for whatever database you connect to at run-time.
In order to do this, Aubit4GL needs to know the following:
This can be changed by setting the environment variable A4GL_SQLDIALECT, or by setting the value of SQLDIALECT in the /etc/opt/aubit4gl/aubitrc file.
You can also change it at run-time using the SET SQL DIALECT command eg.
SET SQL DIALECT TO ORACLEThis will cause all subsequent statements to be treated as if they were written using Oracle syntax.
Note - the 4GL compiler is not guaranteed to handle commands using non-Informix syntax. If the compiler cannot understand a particular command, simply place itin a char variable (string), prepare it, and execute it.
For example, consider the steps taken to get the following Informix SQL statement to run correctly with PostgreSQL:
select last_name, first_name[1], (today-birthday)/365 age
from client
where last_name matches "M*"
select last_name, substr(first_name,1,1), (date(now())-birthday)/365 AS age
from client
where last_name ~ '^M.*'
Special configuration files are used to indicate what conversions are needed. They are located in the directory /opt/aubit4gl/etc/convertsql (this can be changed by setting the environment variable A4GL_SQLCNVPATH to an alternative location).
There is one file for each combination of source and target dialect, each file being named as source-target.cnv. For example, the rules for translating from Informix to PostgreSQL are in a file called INFORMIX-POSTGRESQL.cnv, in which the conversion rules for the above example are given as:
DOUBLE_TO_SINGLE_QUOTES MATCHES_TO_REGEX SUBSTRING_FUNCTION = substr REPLACE today = date(now()) COLUMN_ALIAS_AS
A command line utility, convertsql is available to convert these as well.
You may have to compile this program from source. Go to /opt/aubit4g/tools/convertsql, and follow the instructions in README.txt.
For example, to convert a file full of Informix SQL commands into SapDB compatible commands, you might execute:
convertsql INFORMIX SAPDB < mystuff.sql > mystuff2.sql
1) Simple directives, taking no arguments
DOUBLE_TO_SINGLE_QUOTES
Change double quotes (") to single quotes (') around literal strings.
MATCHES_TO_LIKE
Change Informix_style 'matches' clause to one using 'like',
and change * and ? to % and _ respectively.
eg:
matches 'X?Z*' -> like 'X_Z%'
MATCHES_TO_REGEX
Similar to 'matches-to-like' but uses the Postgres style regular
expression syntax,
eg:
matches 'X?Z*' -> ~ '^X.Z.*'
TABLE_ALIAS_AS
Insert the word "as" before table alias names in a 'from' clause
eg:
from ..., table1 t1, ... -> from ..., table1 as t1, ...
COLUMN_ALIAS_AS
Insert the word "as" before column/expression alias names in a
'select' clause
eg:
select ..., sum(amount) amt, ...
->
select ..., sum(amount) as amt, ...
ANSI_UPDATE_SYNTAX
Convert Informix-style "update ... set (..,..) = (..,..) " to the
ANSI standard format "update ... set ...=..., ...=... "
eg.
update mytable set (col1,col2,col3) = ("01", "X", 104) where ...
->
update mytable set col1="01", col2="X", col3=104 where ...
CONSTRAINT_NAME_AFTER
Move the constraint name in a constraint command to after the
constraint definition,
eg:
... constraint c_name unique
->
... unique constraint c_name
CONSTRAINT_NAME_BEFORE
Move the constraint name in a constraint command to before the
constraint definition,
eg:
... unique constraint c_name
->
... constraint c_name unique
2) Directives that take an argument ( in the rules below, replace the word "string" with the appropriate values )
SUBSTRING_FUNCTION = string
Change Informix-style string subscripting to a function call,
Replace 'string' with the name of the sql function.
eg.
where ... foo[3,5] = ....
->
where ... substr(foo,3,3)
3) Text replacement directives
Search and replace is not case-sensitive. For legibility, lower case
is used in the rules for search/replace strings to distinguish them from
the keywords (in upper case).
You may leave the replacement string (after the = sign) blank. This will
have the effect of removing the matched string from the converted output.
REPLACE before = after
Replace any occurrence of the string 'before' with 'after',
eg.
REPLACE rowid = oid
REPLACE current year to second = sysdate
REPLACE today = date(now())
REPLACE_EXPR before = after
Replace only if the 'before' text is found in an expression or where
an expression is allowed, such as in a where clause or a select clause.
eg.
REPLACE_EXPR sysdate = current year to second
REPLACE_EXPR today = date(now())
REPLACE COMMAND before = after
Replace, but only if the whole SQL statement matches the 'before' string
eg.
REPLACE_COMMAND set isolation to dirty read =
The example above has the effect of completely erasing the command.