Back to Contents


ODI Adaptation Guide For Oracle MySQL 5.x.x

Installation

Install MySQL and create a database
Prepare the runtime environment

Database concepts

Database concepts
Data storage concepts
Data consistency and concurrency management
Transactions handling
Defining database users

Data dictionary

BOOLEAN data type
CHARACTER data types
NUMERIC data types
DATE and DATETIME data types
INTERVAL data type
SERIAL data type
ROWIDs
Very large data types
Constraints
Name resolution of SQL objects
Data type conversion table

Data manipulation

Reserved words
Outer joins
Transactions handling
Temporary tables
Substrings in SQL
Name resolution of SQL objects
Database object name delimiters
MATCHES and LIKE conditions
Syntax of UPDATE statements

BDL programming

SERIAL data type
INFORMIX specific SQL statements in BDL
INSERT cursors
Cursors WITH HOLD
SELECT FOR UPDATE
UPDATE/DELETE WHERE CURRENT OF <cursor>
The LOAD and UNLOAD instructions
SQL Interruption
Scrollable Cursors

Runtime configuration

Install MySQL and create a database - database configuration/design tasks

  1. Supported MySQL versions are 5.0 and higher, MySQL 4.1.2 drivers are still be available, but MySQL version 4.1 is de-supported by the database vendor since January 2010.

  2. Install the MySQL Server on your computer. You can download packages from www.mysql.com.

  3. Configure the server with the appropriate storage engine:
    Note that In order to have transaction support by default, you must use a storage engine that supports transactional tables.
    The INNODB is a storage engine supporting transactions. In order to use this storage engine as default, set the next configuration parameter in the my.cnf or my.ini file:
      [mysqld]
      default-storage-engine = INNODB

    You can also set the default table type option in the command line when starting the engine:
      mysqld_safe --default-storage-engine=InnoDB

  4. Consider setting the sql-mode configuration parameter to get the appropriate behavior of the MySQL server:

  5. The mysqld process must be started to listen to database client connections. See MySQL documentation for more details about starting the database server process.

  6. Create a database user dedicated to your application, the application administrator.  Connect as the MySQL root user and GRANT all privileges to this user:
      mysql -u root
      ...
      mysql> grant all privileges on *.*
                   to 'mysuser'@'localhost'
                   identified by 'password';

  7. Connect as the application administrator and create a MySQL database with the CREATE DATABASE statement:
      mysql -u mysuser
      ...
      mysql> create database mydatabase;

  8. Create the application tables. Do not forget to convert INFORMIX data types to MySQL data types. See issue Data Type Conversion Table for more details. If you have a transactional-safe table handler activated by default, you do not need to specify the TYPE option.

Prepare the runtime environment - connecting to the database

  1. In order to connect to MySQL, you must have a MySQL database driver "dbmmys*" in FGLDIR/dbdrivers.

  2. The MySQL client software is required to connect to a database server. Check if the MySQL client library (libmysqlclient.*) is installed on the system. Note that the shared library version of the MySQL client library must match the libmysqlclient library version linked to the dbmmys*.so ODI driver. For example, dbmmys55x.so requires libmysqlclient.so.18 to be installed. 

  3. Make sure that the MySQL client environment variables are properly set. Check for example MYSQL_HOME (the path to the installation directory), DATADIR (the path to the data files directory), etc. See MySQL documentation for more details about client environment variables to be set.

  4. Verify the environment variable defining the search path for the database client shared library (libmysqlclient.so on UNIX, LIBMYSQL.dll on Windows). On UNIX platforms, the variable is specific to the operating system. For example, on Solaris and Linux systems, it is LD_LIBRARY_PATH, on AIX it is LIBPATH, or HP/UX it is SHLIB_PATH. On Windows, you define the DLL search path in the PATH environment variable.

    MySQL version

    Shared library environment setting

    MySQL 5.0 and higher

    UNIX: Add $MYSQL_HOME/lib to LD_LIBRARY_PATH (or its equivalent).
    Windows: Add %MYSQL_HOME%\bin to PATH.

  5. To verify if the MySQL client environment is correct, you can start the MySQL command interpreter:

         $ mysql dbname -u appadmin -p

  6. Set up the fglprofile entries for database connections.

    Important: Make sure that you are using the ODI driver corresponding to the database client and server version. Because Informix features emulation are dependant from the database server version, it is mandatory to use the same version of the database client and ODI driver as the server version.


DATE and DATETIME data types

INFORMIX provides two data types to store dates and time information:

MySQL provides the following data type to store dates:

String representing date time information:

INFORMIX is able to convert quoted strings to DATE / DATETIME data if the string contents matches environment parameters (i.e. DBDATE, GL_DATETIME). As in INFORMIX, MySQL can convert quoted strings to datetime data according the ISO datetime format ( YYYY-MM-DD hh:mm:ss' ).

Date arithmetic:

Solution:

MySQL has the same DATE data type as INFORMIX ( year, month, day ). So you can use MySQL DATE data type for INFORMIX DATE columns.

MySQL TIME data type can be used to store INFORMIX DATETIME HOUR TO SECOND values. The database interface makes the conversion automatically.

INFORMIX DATETIME values with any precision from YEAR to SECOND can be stored in MySQL DATETIME columns. The database interface makes the conversion automatically. Missing date or time parts default to 1900-01-01 00:00:00. For example, when using a DATETIME HOUR TO MINUTE with the value of "11:45", the MySQL DATETIME value will be "1900-01-01 11:45:00".

SQL Statements using expressions with TODAY / CURRENT /  EXTEND must be reviewed and adapted to the native syntax.

Literal DATETIME and INTERVAL expressions (i.e. DATETIME ( 1999-10-12) YEAR TO DAY) are not converted.


Reserved words

SQL object names like table and column names cannot be SQL reserved words in MySQL.

Solution:

Table or column names which are MySQL reserved words must be renamed.


ROWIDs

When creating a table, INFORMIX automatically adds a "ROWID" integer column (applies to non-fragmented tables only). The ROWID column is auto-filled with a unique number and can be used like a primary key to access a given row.

MySQL does not have an equivalent for the INFORMIX ROWID pseudo-column.

Solution:

ROWIDs are not supported. You must review the code using ROWIDs and use primary key columns instead.


Very large data types

INFORMIX uses the TEXT and BYTE data types to store very large texts or images. MySQL provides TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT, TINYBLOB, BLOB, MEDIUMBLOB and LONGBLOB data types.

Solution:

Starting with MySQL version 5.0, the database interface can convert BDL TEXT data to LONGTEXT and BYTE data to LONG BLOB.

Genero TEXT/BYTE program variables have a limit of 2 gigabytes, make sure that the large object data does not exceed this limit.

Because MySQL CHAR and VARCHAR cannot exceed 255 bytes, we recommend that you  use the MySQL TEXT type to store CHAR/VARCHAR values with a size larger than 255 bytes. When fetching TEXT columns from a MySQL database, these will be treated as CHAR/VARCHAR types by the MySQL database driver. See CHAR/VARCHAR types for more details.


SERIAL data type

INFORMIX supports the SERIAL, SERIAL8 and BIGSERIAL data types to produce automatic integer sequences. SERIAL is based on INTEGER (32 bit), while SERIAL8 and BIGSERIAL can store 64 bit integers:

INFORMIX allows you to insert rows with a value different from zero for a serial column. Using an explicit value will automatically increment the internal serial counter, to avoid conflicts with future INSERT statements that are using a zero value:
    CREATE TABLE tab ( k SERIAL );  --> internal counter = 0
    INSERT INTO tab VALUES ( 0 );   --> internal counter = 1
    INSERT INTO tab VALUES ( 10 );  --> internal counter = 10
    INSERT INTO tab VALUES ( 0 );   --> internal counter = 11
    DELETE FROM tab;                --> internal counter = 11
    INSERT INTO tab VALUES ( 0 );   --> internal counter = 12

MySQL supports the AUTO_INCREMENT column definition option as well as the SERIAL keyword:

Solution:

The INFORMIX SERIAL data type is emulated with MySQL AUTO_INCREMENT option. After an insert, SQLCA.SQLERRD[2] holds the last generated serial value. However, SQLCA.SQLERRD[2] is defined as an INTEGER, it cannot hold values from BIGINT auto incremented columns. If you are using BIGINT auto incremented columns, you must use the LAST_INSERT_ID() SQL function.

Note that AUTO_INCREMENT columns must be primary keys. This is handled automatically when you create a table in a BDL program.

Like Informix, MySQL allows to specify a zero for auto-incremented columns, however, for SQL portability, INSERT statements should be reviewed to remove the SERIAL column from the list.
For example, the following statement:
   INSERT INTO tab (col1,col2) VALUES (0, p_value)
can be converted to :
   INSERT INTO tab (col2) VALUES (p_value)
Static SQL INSERT using records defined from the schema file must also be reviewed :
   DEFINE rec LIKE tab.*
   INSERT INTO tab VALUES ( rec.* )   -- will use the serial column
can be converted to :
   INSERT INTO tab VALUES rec.* -- without braces, serial column is removed


Outer joins

In INFORMIX SQL, outer tables can be defined in the FROM clause with the OUTER keyword:

SELECT ... FROM a, OUTER(b)
 WHERE a.key = b.akey
SELECT ... FROM a, OUTER(b,OUTER(c))
 WHERE a.key = b.akey
   AND b.key1 = c.bkey1
   AND b.key2 = c.bkey2 

MySQL 3.23 supports the ANSI outer join syntax:

SELECT ... FROM cust LEFT OUTER JOIN order
                     ON cust.key = order.custno
SELECT ...
  FROM cust LEFT OUTER JOIN order
                 LEFT OUTER JOIN item
                 ON order.key = item.ordno
            ON cust.key = order.custno
 WHERE order.cdate > current date

See the MySQL reference for a complete description of the syntax.

Solution:

For better SQL portability, you should use the ANSI outer join syntax instead of the old Informix OUTER syntax.

The MySQL interface can convert most INFORMIX OUTER specifications to ANSI outer joins.

Prerequisites:

  1. In the FROM clause, the main table must be the first item and the outer tables must figure from left to right in the order of outer levels.
       Example which does not work : "FROM OUTER(tab2), tab1".
  2. The outer join in the WHERE part must use the table name as prefix.
       Example : "WHERE tab1.col1 = tab2.col2".

Restrictions:

  1. Additional conditions on outer table columns cannot be detected and therefore are not supported :
      Example : "... FROM tab1, OUTER(tab2) WHERE tab1.col1 = tab2.col2 AND tab2.colx > 10".
  2. Statements composed by 2 or more SELECT instructions using OUTERs are not supported.
      Example : "SELECT ... UNION SELECT" or "SELECT ... WHERE col IN (SELECT...)"

Notes:

  1. Table aliases are detected in OUTER expressions.
       OUTER example with table alias : "OUTER( tab1 alias1)".
  2. In the outer join, <outer table>.<col> can be placed on both right or left side of the equal sign.
       OUTER join example with table on the left : "WHERE outertab.col1 = maintab.col2 ".
  3. Table names detection is not case-sensitive.
       Example : "SELECT ... FROM tab1, TAB2 WHERE tab1.col1 = tab2.col2".
  4. Temporary tables are supported in OUTER specifications.

Database concepts

Most BDL applications use only one database entity (in the meaning of INFORMIX). But the same BDL application can connect to different occurrences of the same database schema, allowing several users to connect to those different databases.

Like INFORMIX servers, MySQL can handle multiple database entities. Tables created by a user can be accessed without the owner prefix by other users as long as they have access privileges to these tables.

Solution:

Create a MySQL database for each INFORMIX database. 


Data consistency and concurrency management

Data consistency involves readers which want to access data currently modified by writers and concurrency data access involves several writers accessing the same data for modification. Locking granularity defines the amount of data concerned when a lock is set (row, page, table, ...).

INFORMIX

INFORMIX uses a locking mechanism to handle data consistency and concurrency. When a process changes database information with UPDATE, INSERT or DELETE, an exclusive lock is set on the touched rows. The lock remains active until the end of the transaction. Statements performed outside a transaction are treated as a transaction containing a single operation and therefore release the locks immediately after execution. SELECT statements can set shared locks according to the isolation level. In case of locking conflicts (for example, when two processes want to acquire an exclusive lock on the same row for modification or when a writer is trying to modify data protected by a shared lock), the behavior of a process can be changed by setting the lock wait mode.

Control:

Defaults:

MySQL

When data is modified, exclusive locks are set and held until the end of the transaction. For data consistency, MySQL uses a locking mechanism. Readers must wait for writers as in INFORMIX.

Control:

Defaults:

Solution:

The SET ISOLATION TO ... INFORMIX syntax is replaced by SET SESSION TRANSACTION ISOLATION LEVEL ... in MySQL. The next table shows the isolation level mappings done by the MySQL database driver:

SET ISOLATION instruction in program Native SQL command
SET ISOLATION TO DIRTY READ SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET ISOLATION TO COMMITTED READ
  [READ COMMITTED] [RETAIN UPDATE LOCKS]
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
SET ISOLATION TO CURSOR STABILITY SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
SET ISOLATION TO REPEATABLE READ SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

For portability, it is recommended that you work with INFORMIX in the read committed isolation level, make processes wait for each other (lock mode wait), and create tables with the "lock mode row" option.

See INFORMIX and MySQL documentation for more details about data consistency, concurrency and locking mechanisms.


SELECT FOR UPDATE

A lot of BDL programs use pessimistic locking in order to avoid several users editing the same rows at the same time.

   DECLARE cc CURSOR FOR
         SELECT ... FROM tab WHERE ... FOR UPDATE
   OPEN cc
   FETCH cc <-- lock is acquired
   ...
   CLOSE cc <-- lock is released

MySQL locking mechanism depends upon the transaction manager. The default locking granularity is per table when you use the default non-transactional configuration. You must use the InnoDB Storage Engine to get transactions and locking mechanisms.

SELECT ... FOR UPDATE is only supported since MySQL version 6.0. Locks are released at the end of the transaction.

Solution:

Check if the MySQL storage engine supports SELECT FOR UPDATE, otherwise review the program logic.


Transactions handling

INFORMIX and MySQL handle transactions in a similar manner.

INFORMIX native mode (non ANSI):

MySQL :

Solution:

INFORMIX transaction handling commands are automatically converted to MySQL instructions to start, validate or cancel transactions.

MySQL does not support transactions by default. You must set the server system parameter table_type=InnoDB.

Regarding the transaction control instructions, the BDL applications do not have to be modified in order to work with MySQL, as long as you have a transaction manager installed with MySQL.

If you want to use savepoints, do not use the UNIQUE keyword in the savepoint declaration, always specify the savepoint name in ROLLBACK TO SAVEPOINT, and do not drop savepoints with RELEASE SAVEPOINT.


BOOLEAN data type

INFORMIX supports the BOOLEAN data type, which can store 't' or 'f' values. Genero BDL implements the BOOLEAN data type in a different way: As in other programming languages, Genero BOOLEAN stores integer values 1 or 0 (for TRUE or FALSE). The type was designed this way to assign the result of a Boolean expression to a BOOLEAN variable.

MySQL supports the BOOLEAN data type and stores 1 or 0 integer values for TRUE and FALSE.

Solution:

The MySQL database interface supports the BOOLEAN data type.


CHARACTER data types

INFORMIX supports following character data types:

In INFORMIX, both CHAR/VARCHAR and NCHAR/NVARCHAR data types can be used to store single-byte or multi-byte encoded character strings. The only difference between CHAR/VARCHAR and NCHAR/NVARCHAR is for sorting: N[VAR]CHAR types use the collation order, while [VAR]CHAR types use the byte order. The character set used to store strings in CHAR/VARCHAR/NCHAR/NVARCHAR columns is defined by the DB_LOCALE environment variable. The character set used by applications is defined by the CLIENT_LOCALE environment variable. Note that INFORMIX uses Byte Length Semantics (the size N that you specify in [VAR]CHAR(N) is expressed in bytes, not characters as in some other databases)

MySQL supports the following character data types:

With MySQL version 4, CHAR/VARCHAR with a size exceeding 255 characters are silently converted to TEXT columns. With later versions, you now get  an SQL error when trying to define a CHAR or VARCHAR column with a size greater than the limit. Also, before version MySQL 5.0.3, VARCHAR limit was 255 characters, starting with 5.0.3 the limit is 65535 characters.

MySQL uses Character Length Semantics to define the size of CHAR/VARCHAR columns, while INFORMIX and Genero use Byte Length Semantics.

MySQL can support multiple character sets, you can run the SHOW CHARACTER SET statement to list supported encodings. There are different configuration levels to define the character set used by MySQL to store data. The server character set defines the default for database character sets if not specified in the CREATE DATABASE command. You can even define a specific character set at the table and column level, but this is not recommended with Genero applications. The database character set is used to store CHAR and VARCHAR columns. The NCHAR and NATIONAL VARCHAR types use a predefined character which can be different from the database character set. In MySQL the national character set is UTF-8.

MySQL can automatically convert from/to the client and server characters sets. In the client applications, you define the character set with the SET NAMES instruction.

Note that by default, when fetching CHAR columns from MySQL, trailing blanks are trimmed. This does not matter as long as you fetch CHAR columns into CHAR variables, but this non-standard behavior will impact CHAR fetch into VARCHAR, or other SQL areas such as string concatenation for example. You can control the behavior of CHAR trailing blanks trimming with the PAD_CHAR_TO_FULL_LENGTH sql-mode parameter. But when this mode is used, the result of the SQL LENGTH() function will be different since trailing blanks are significant for that function in MySQL.

Solution:

INFORMIX CHAR(N) types must be mapped to MySQL CHAR(N) types. INFORMIX VARCHAR(N) or LVARCHAR(N) columns must be mapped to MySQL VARCHAR(N).

Review your database schema when using CHAR, VARCHAR and LVARCHAR columns with a size exceeding the MySQL limits: If you need to store character strings larger as the MySQL limit, you can use the MySQL text type. When using CHAR/VARCHAR/LVARCHAR types in CREATE TABLE, the SQL Translator converts to text if the size is bigger as 255. When fetching tinytext and text columns from the MySQL database, the MySQL database driver treats such columns as CHAR/VARCHAR, to emulate INFORMIX CHAR columns with a size greater than 255.

Note:  For each text column fetched from MySQL, the MySQL database driver needs to allocate a temporary string buffer of 65535 bytes. Keep in mind that text columns may have be created by CREATE TABLE using CHAR/VARCHAR/LVARCHAR with size>255. The memory used by this temporary buffer is freed when freeing the cursor.

You can store single-byte or multi-byte character strings in MySQL CHAR, VARCHAR and TEXT columns. 

Do not forget to properly define the client character set, which must correspond to the runtime system character set.

Keep in mind that MySQL uses Character Length Semantics regarding CHAR/VARCHAR sizes: When you define a CHAR(20) and the database character set is multi-byte, the MySQL column can hold more bytes/characters as the INFORMIX CHAR(20) type. For example, in UTF-8, you can store 20 é (e-acute) characters in MySQL CHAR(20), but Informix CHAR(20) can only store 10 of such characters, because in UTF-8, é is encoded with 2 bytes. Even if Genero uses Byte Length Semantics when you define a CHAR/VARCHAR variable, a good practice is to use the same sizes for MySQL CHAR/VARCHAR columns: You could then store more characters in the MySQL columns as the Genero variable can hold, but this is not a problem.

When extracting a database schema from a MySQL database, the schema extractor uses the size of the column in characters, not the octet length. If you have created a CHAR(10 (characters) ) column a in MySQL database using the UTF8 character set, the .sch file will get a size of 10 (bytes).

See also the section about Localization.


Constraints

Constraint naming syntax:

Both INFORMIX and MySQL support primary key, unique, foreign key and default, but the constraint naming syntax is different : MySQL expects the "CONSTRAINT" keyword before the constraint specification and INFORMIX expects it after.

UNIQUE constraint example:

INFORMIX MySQL
CREATE TABLE scott.emp (
...
empcode CHAR(10) UNIQUE
   [CONSTRAINT pk_emp],
...
CREATE TABLE scott.emp (
...
empcode CHAR(10)
   [CONSTRAINT pk_emp] UNIQUE,
...

Primary keys:

Like INFORMIX, MySQL creates an index to enforce PRIMARY KEY constraints (some RDBMS do not create indexes for constraints).  Using "CREATE UNIQUE INDEX" to define unique constraints is obsolete (use primary keys or a secondary key instead).

In MySQL, the name of a PRIMARY KEY is PRIMARY.

Unique constraints:

Like INFORMIX, MySQL creates an index to enforce UNIQUE constraints (some RDBMS do not create indexes for constraints).

When using a unique constraint, INFORMIX allows only one row with a NULL value, while MySQL allows several rows with NULL! Using CREATE UNIQUE INDEX is obsolete.

Foreign keys:

Both INFORMIX and MySQL support the ON DELETE CASCADE option. In MySQL, foreign key constraints are checked immediately, so NO ACTION and RESTRICT are the same.

Check constraints:

Check constraints are not yet supported in MySQL.

Solution:

Constraint naming syntax:

The database interface does not convert constraint naming expressions when creating tables from BDL programs. Review the database creation scripts to adapt the constraint naming clauses for MySQL.


Defining database users

Until version 11.70.xC2, INFORMIX database users must be created at the operating system level and be members of the 'informix' group. Starting with 11.70.xC2, INFORMIX supports database-only users with the CREATE USER instruction, as most other db servers. Any database user must have sufficient privileges to connect and use resources of the database; user rights are defined with the GRANT command.

MySQL users must be registered in the database. They are created with the GRANT SQL instruction:

   $ mysql -u root -pmanager --host orion test

   mysql> GRANT ALL PRIVILEGES ON * TO mike IDENTIFIED BY 'pswd';

Solution:

According to the application logic (is it a multi-user application ?), you have to create one or several MySQL users.


Temporary tables

INFORMIX temporary tables are created through the CREATE TEMP TABLE DDL instruction or through a SELECT ... INTO TEMP statement. Temporary tables are automatically dropped when the SQL session ends, but they can be dropped with the DROP TABLE command. There is no name conflict when several users create temporary tables with the same name.

INFORMIX allows you to create indexes on temporary tables. No name conflict occurs when several users create an index on a temporary table by using the same index identifier.

MySQL support temporary tables with the following syntax:

   CREATE TEMPORARY TABLE tablename ( coldefs )
    CREATE TEMPORARY TABLE tablename LIKE other-table

Solution:

In BDL, INFORMIX temporary tables instructions are converted to generate native SQL Server temporary tables.


Substrings in SQL

INFORMIX SQL statements can use subscripts on columns defined with the character data type:

    SELECT ... FROM tab1 WHERE col1[2,3] = 'RO'
    SELECT ... FROM tab1 WHERE col1[10]  = 'R'   -- Same as col1[10,10]
    UPDATE tab1 SET col1[2,3] = 'RO' WHERE ...
    SELECT ... FROM tab1 ORDER BY col1[1,3]

.. while MySQL provides the SUBSTR( ) function, to extract a substring from a string expression :

    SELECT .... FROM tab1 WHERE SUBSTRING(col1,2,3) = 'RO'
    SELECT SUBSTRING('Some text',6,3) ...   -- Gives 'tex'

Solution:

You must replace all INFORMIX col[x,y] expressions by SUBSTRING(col,x,y-x+1).

In UPDATE instructions, setting column values through subscripts will produce an error with MySQL :
    UPDATE tab1 SET col1[2,3] = 'RO' WHERE ...
   is converted to:
    UPDATE tab1 SET SUBSTRING(col1,2,(3-2+1)) = 'RO' WHERE ...

Column subscripts in ORDER BY expressions are also converted and produce an error with MySQL :
    SELECT ... FROM tab1 ORDER BY col1[1,3]
   is converted to:
    SELECT ... FROM tab1 ORDER BY SUBSTRING(col1,1,(3-1+1))


Name resolution of SQL objects

INFORMIX uses the following form to identify a SQL object:

  [database[@dbservername]:][{owner|"owner"}.]identifier

With MySQL, an object name takes the following form:

  [database.]identifier

Solution:

As a general rule, to write portable SQL, you should only use simple database object names without any database, server or owner qualifier and without quoted identifiers.


Database object name delimiters

INFORMIX identifies database object names with double quotes, while MySQL does not use the double quotes as database object identifiers.

Solution:

Check your programs for database object names having double quotes:

   WHERE "tabname"."colname" = "a string value"

should be written as follows:

   WHERE tabname.colname = 'a string value'


NUMERIC data types

INFORMIX supports several data types to store numbers:

INFORMIX Data Type Description
SMALLINT 16 bit signed integer
INT / INTEGER 32 bit signed integer
BIGINT 64 bit signed integer
INT8 64 bit signed integer (replaced by BIGINT)
DEC / DECIMAL Equivalent to DECIMAL(16)
DEC(p) / DECIMAL(p) Floating-point decimal number
DEC(p,s) / DECIMAL(p,s) Fixed-point decimal number
MONEY Equivalent to DECIMAL(16,2)
MONEY(p) Equivalent to DECIMAL(p,2)
MONEY(p,s) Equivalent to DECIMAL(p,s)
REAL / SMALLFLOAT 32-bit floating point decimal (C float)
DOUBLE PRECISION / FLOAT[(n)] 64-bit floating point decimal (C double)

Solution:

MySQL supports the following data types to store numbers:

MySQL data type Description
DECIMAL(p) Stores whole numeric numbers up to p digits (not floating point)
DECIMAL(p,s) Maximum precision depends on MySQL Version, see documentation.
FLOAT[(M,D)] 4 bytes variable precision
DOUBLE[(M,D)] 8 bytes variable precision
SMALLINT 16 bit signed integer
INTEGER 32 bit signed integer
BIGINT 64 bit signed integer

Note: Before MySQL 5.0.3, the maximum range of DECIMAL values is the same as for DOUBLE. Since MySQL 5.0.3, DECIMAL can store real precision numbers as in INFORMIX. However, the maximum number of digits depends on the version of MySQL, see documentation for more details. We strongly recommend that you make tests (INSERT+SELECT) to check whether large decimals are properly inserted and fetched back. 


MATCHES and LIKE in SQL conditions

INFORMIX supports MATCHES and LIKE in SQL statements. MySQL supports the LIKE statement as in INFORMIX, plus the ~ operators that are similar but different from the INFORMIX MATCHES operator.

MATCHES allows brackets to specify a set of matching characters at a given position:
   ( col MATCHES '[Pp]aris' )
   ( col MATCHES '[0-9][a-z]*' )
In this case, the LIKE statement has no equivalent feature.

The following substitutions must be done to convert a MATCHES condition to a LIKE condition:

Solution:

SQL statements using MATCHES expressions must be reviewed in order to use LIKE expressions.

See also: MATCHES operator in SQL Programming.


INFORMIX-specific SQL statements in BDL

The BDL compiler supports several INFORMIX specific SQL statements that have no meaning when using MySQL:

Solution:

Review your BDL source and remove all static SQL statements that are INFORMIX-specific.


INSERT cursors

INFORMIX supports insert cursors. An "insert cursor" is a special BDL cursor declared with an INSERT statement instead of a SELECT statement. When this kind of cursor is open, you can use the PUT instruction to add rows and the FLUSH instruction to insert the records into the database.

For INFORMIX database with transactions, OPEN, PUT and FLUSH instructions must be executed within a transaction.

MySQL does not support insert cursors.

Solution:

Insert cursors are emulated by the MySQL database interface.


Cursors WITH HOLD

INFORMIX closes opened cursors automatically when a transaction ends unless the WITH HOLD option is used in the DECLARE instruction. In MySQL, opened cursors using SELECT statements without a FOR UPDATE clause are not closed when a transaction ends. Actually, all MySQL cursors are 'WITH HOLD' cursors unless the FOR UPDATE clause is used in the SELECT statement.

Cursors declared FOR UPDATE and using the WITH HOLD option cannot be supported with MySQL because FOR UPDATE cursors are automatically closed by MySQL when the transaction ends.

Solution:

BDL cursors that are not declared "WITH HOLD" are automatically closed by the database interface when a COMMIT WORK or ROLLBACK WORK is performed.

Since MySQL automatically closes FOR UPDATE cursors when the transaction ends, opening cursors declared FOR UPDATE and WITH HOLD option results in an SQL error; in the same conditions, this does not normally appear with INFORMIX. Review the program logic in order to find another way to set locks.


UPDATE/DELETE WHERE CURRENT OF <cursor>

INFORMIX allows positioned UPDATEs and DELETEs with the "WHERE CURRENT OF <cursor>" clause, if the cursor has been DECLARED with a SELECT ... FOR UPDATE statement.

Solution:

WHERE CURRENT OF is not supported by MySQL; review your code for occurrences.


Syntax of UPDATE statements

INFORMIX allows a specific syntax for UPDATE statements:

    UPDATE table SET ( <col-list> ) = ( <val-list> )

or

    UPDATE table SET table.* = myrecord.*
    UPDATE table SET * = myrecord.*

Solution:

Static UPDATE statements using the above syntax are converted by the compiler to the standard form:

    UPDATE table SET column=value [,...]


INTERVAL data type

INFORMIX INTERVAL data type stores a value that represents a span of time. INTERVAL types are divided into two classes : year-month intervals and day-time intervals.

MySQL provides an INTERVAL data type, but it is totally different from the INFORMIX INTERVAL type. For example, you specify an INTERVAL literal as follows :

    25 years 2 months 23 days

Solution:

The INTERVAL data type is not well supported because the database server has no equivalent native data type. However, you can store into and retrieve from CHAR columns BDL INTERVAL values.


Data storage concepts

An attempt should be made to preserve as much of the storage information as possible when converting from INFORMIX to MySQL. Most important storage decisions made for INFORMIX database objects (like initial sizes and physical placement) can be reused for the MySQL database.

Storage concepts are quite similar in INFORMIX and in MySQL, but the names are different.


The LOAD and UNLOAD instructions

INFORMIX provides two SQL instructions to export / import data from / into a database table: The UNLOAD instruction copies rows from a database table into a text file and the LOAD instructions insert rows from a text file into a database table.

MySQL does not provide LOAD and UNLOAD instructions.

Solution:

LOAD and UNLOAD instructions are supported.


SQL Interruption

With INFORMIX, it is possible to interrupt a long running query if the SQL INTERRUPT ON option is set by the Genero program. The database server returns SQLCODE -213, which can be trapped to detect a user interruption.

    MAIN
      DEFINE n INTEGER
      DEFER INTERRUPT
      OPTIONS SQL INTERRUPT ON
      DATABASE test1
      WHENEVER ERROR CONTINUE
      -- Start long query (self join takes time)
      -- From now on, user can hit CTRL-C in TUI mode to stop the query
      SELECT COUNT(*) INTO n FROM customers a, customers b
           WHERE a.cust_id <> b.cust_id
      IF SQLCA.SQLCODE == -213 THEN
         DISPLAY "Statement was interrupted by user..."
         EXIT PROGRAM 1
      END IF
      WHENEVER ERROR STOP
      ...
    END MAIN

Solution:

SQL Interruption is not supported with MySQL; review your code for occurrences.


Scrollable Cursors

The Genero programming language supports scrollable cursors with the SCROLL keyword, as shown in the following code example: 

   DECLARE c1 SCROLL CURSOR FOR SELECT * FROM customers ORDER BY cust_name
   ...
   FETCH FIRST c1 INTO rec_cust.*
   ...
   FETCH NEXT c1 INTO rec_cust.*
   ...
   FETCH LAST c1 INTO rec_cust.*

MySQL 6.0 does not support native scrollable cursors.

Solution:

The MySQL database driver emulates scrollable cursors with temporary files. On UNIX, the temp files are created in the directory defined by the DBTEMP, TMPDIR, TEMP or TMP environment variables (the default is /tmp). On Windows, the temp files are created with the _tempnam() MSVCRT API call. 

Native scrollable cursors are normally handled by the database server (only pieces of the result-set are sent to the client application). With emulated scrollable cursors, when scrolling to the last row, all rows will be fetched into the temporary file. This can generate a lot of network traffic and can produce a large temporary file if the result-set contains a lot of rows. Additionally, programs are dependent on the file system resource allocated to the OS user (ulimit).

In case of a runtime system crash, the temporary files created for scrollable cursors are not removed automatically. Therefore, is it possible that you will find some unexpected files in the temp directory. Before removing such files, you must make sure that these files are no longer used by running processes. Recent operating systems take care of that, by removing unused temp files periodically.


Data type conversion table

INFORMIX Data Types MySQL Data Types
CHAR(n) CHAR(n) (n>255c => TEXT(n))
VARCHAR(n[,m]) VARCHAR(n) (n>255c => TEXT(n))
LVARCHAR(n) VARCHAR(n) (n>255c => TEXT(n))
NCHAR(n) NCHAR(n) (n>255c => TEXT(n))
NVARCHAR(n[,m]) NVARCHAR(n) (n>255c => TEXT(n))
BOOLEAN BOOLEAN
SMALLINT SMALLINT
INT / INTEGER INTEGER
BIGINT BIGINT
INT8 BIGINT
SERIAL[(start)] INTEGER (see note)
BIGSERIAL[(start)] BIGINT (see note)
SERIAL8[(start)] BIGINT (see note)
DOUBLE PRECISION / FLOAT[(n)] DOUBLE
REAL / SMALLFLOAT FLOAT
NUMERIC / DEC / DECIMAL(p,s) DECIMAL(p,s)
NUMERIC / DEC / DECIMAL(p) with p<=15 DECIMAL(p*2,p)
NUMERIC / DEC / DECIMAL(p) with >15 N/A
NUMERIC / DEC / DECIMAL DECIMAL(32,16) (unsupported!)
MONEY(p,s) DECIMAL(p,s)
MONEY(p) DECIMAL(p,2)
MONEY DECIMAL(16,2)
DATE DATE
DATETIME HOUR TO SECOND TIME
DATETIME q1 TO q2 (different from above) DATETIME (YYY-MM-DD hh:mm:ss)
INTERVAL q1 TO q2 CHAR(50)
TEXT MEDIUMTEXT / LONGTEXT (using <= 2Gb!)
BYTE MEDIUMBLOB / LONGBLOB (using <= 2Gb!)