Files
MBS/PROYECTO/otrodir/dbadministrator/fgldbslib.4gl
T

2448 lines
83 KiB
Plaintext

{
This library extracts column types and convert them to Informix encoded types.
Used by fgldbsch.4gl.
API functions:
fgldbsch_init() returning integer
-- initialization function
-- returns < 0 if problem
fgldbsch_set_parameter(name string, value string)
-- set fgldbsch parameters
dbname : Data source name
dbdriver : Database driver name
username : DB user name (login)
userpswd : DB user password
dbowner : DB table owner
tabname : Extract only this table
cvmeth : Conversion string (A/B/C sequence)
casens : Upper/Lower case conversion (C/U/L)
systabs : Extract system tables (Y/N)
compat : Old fglschema compat mode
verbose : Verbose mode (Y/N)
fgldbsch_connect() returning integer
-- connects to the server using parameters for connection info.
-- returns < 0 if problem
fgldbsch_disconnect() returning integer
-- disconnects from the database server
-- returns < 0 if problem
fgldbsch_get_db_type() returning string
-- returns the type of server (IFX, ORA, ADS, DB2, ASA, PGS, MYS)
fgldbsch_extract() returning integer
-- extracts schema information
-- returns < 0 if problem
fgldbsch_next_table() returning integer
-- 1 = new table found
-- 0 = no more tables
-- returns < 0 if problem
fgldbsch_get_table_name() returning string
-- returns name of current table
fgldbsch_get_column_count() returning integer
-- returns the number of columns in current table
fgldbsch_get_column_info(integer)
returning tabname string, colname string, nattype string,
ifxtype integer, ifxleng integer
-- returns the column info by column position
-- WARNING: ifxtype can be -1 to indicate an unsupported data type.
}
DEFINE params RECORD
dbname STRING,
dbdriver STRING,
dbowner STRING,
dbtype CHAR(3),
username STRING,
userpswd STRING,
tabname STRING,
cvmeth CHAR(40),
casens CHAR(1),
systabs CHAR(1),
compat CHAR(1),
verbose CHAR(1)
END RECORD
DEFINE current_tabname STRING
TYPE t_coldef RECORD
colname STRING,
nattype STRING,
ifxtype INTEGER,
ifxleng INTEGER
END RECORD
DEFINE coldef DYNAMIC ARRAY OF t_coldef
DEFINE new_tabname STRING
DEFINE new_coldef t_coldef
DEFINE s_msv_identity_prepared SMALLINT
CONSTANT dtiqual_year = 0
CONSTANT dtiqual_month = 2
CONSTANT dtiqual_day = 4
CONSTANT dtiqual_hour = 6
CONSTANT dtiqual_minute = 8
CONSTANT dtiqual_second = 10
CONSTANT dtiqual_frac1 = 11
CONSTANT dtiqual_frac2 = 12
CONSTANT dtiqual_frac3 = 13
CONSTANT dtiqual_frac4 = 14
CONSTANT dtiqual_frac5 = 15
#-------------------------------------------------------------------------------
FUNCTION fgldbsch_display_convtables()
DISPLAY ""
DISPLAY " Data type conversion tables"
DISPLAY " ---------------------------"
DISPLAY ""
DISPLAY "If you specify X, the columns with the corresponding data type will be"
DISPLAY "ignored and not appear in the schema file."
DISPLAY ""
DISPLAY "Informix to Informix conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " Informix Informix A Informix B "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 BOOLEAN BOOLEAN (ns) CHAR(1) "
DISPLAY " 2 INT8 INT8 (ns) DECIMAL(19,0) "
DISPLAY " 3 SERIAL8 SERIAL8 (ns) DECIMAL(19,0) "
DISPLAY " 4 LVARCHAR(m) LVARCHAR (ns) VARCHAR2(m) "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " (ns) = Not supported in 4gl."
DISPLAY ""
DISPLAY "Oracle conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " Oracle Informix A Informix B "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 NUMBER(p,s) DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 2 CHAR(n) CHAR(n) CHAR(n) "
DISPLAY " 3 VARCHAR(n) VARCHAR(n,0) CHAR(n) "
DISPLAY " 4 VARCHAR2(n) VARCHAR2(n) CHAR(n) "
DISPLAY " 5 DATE DATE DATETIME Y TO S "
DISPLAY " 6 NUMBER(5,0) SMALLINT DECIMAL(5,0) "
DISPLAY " 7 NUMBER(10,0) INTEGER DECIMAL(10,0) "
DISPLAY " 8 TIMESTAMP(n>0) DATETIME Y TO F(n) DATETIME Y TO F(n) "
DISPLAY " 9 INTERVAL Y(n) TO M INTERVAL Y(n) TO M INTERVAL Y(n) TO M "
DISPLAY " 10 INTERVAL D(n) TO S(p) INTERVAL D(n) TO F(p) INTERVAL D(n) TO F(p)"
DISPLAY " 11 FLOAT(p) DECIMAL(p/3) FLOAT "
DISPLAY " 12 TIMESTAMP(0) DATETIME Y TO S DATE "
DISPLAY " 13 BLOB BYTE BYTE "
DISPLAY " 14 CLOB TEXT TEXT "
DISPLAY " 15 NCHAR(n) CHAR(n) NCHAR(n) "
DISPLAY " 16 NVARCHAR2(n) VARCHAR2(n) NVARCHAR2(n) "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
DISPLAY "IBM DB2 conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " IBM DB2 Informix A "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 2 CHAR(n) CHAR(n) "
DISPLAY " 3 VARCHAR(n) VARCHAR(n,0) "
DISPLAY " 4 DATE DATE "
DISPLAY " 5 TIME DATETIME H TO S "
DISPLAY " 6 TIMESTAMP DATETIME Y TO F(5) "
DISPLAY " 7 SMALLINT SMALLINT "
DISPLAY " 8 INTEGER INTEGER "
DISPLAY " 9 REAL SMALLFLOAT "
DISPLAY " 10 DOUBLE FLOAT "
DISPLAY " 11 BLOB BYTE "
DISPLAY " 12 CLOB TEXT "
DISPLAY " 13 GRAPHIC(n) CHAR(n) "
DISPLAY " 14 VARGRAPHIC(n) VARCHAR2(n) "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
DISPLAY "SQL Server conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " SQL Server Informix A Informix B "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 DECIMAL(p,s) DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 2 CHAR(n) CHAR(n) CHAR(n) "
DISPLAY " 3 VARCHAR(n) VARCHAR(n,0) CHAR(n) "
DISPLAY " 4 SMALLDATETIME DATE DATE "
DISPLAY " 5 DATETIME DATETIME Y TO F(3) DATE "
DISPLAY " 6 SMALLINT SMALLINT SMALLINT "
DISPLAY " 7 INTEGER INTEGER INTEGER "
DISPLAY " 8 REAL SMALLFLOAT SMALLFLOAT "
DISPLAY " 9 FLOAT FLOAT FLOAT "
DISPLAY " 10 NCHAR(n) CHAR(n/2) NCHAR(n/2) "
DISPLAY " 11 NVARCHAR(n) VARCHAR2(n/2) NVARCHAR2(n/2) "
DISPLAY " 12 IMAGE BYTE BYTE "
DISPLAY " 13 TEXT TEXT TEXT "
DISPLAY " 14 NTEXT TEXT TEXT "
DISPLAY " 15 VARCHAR(MAX) TEXT TEXT "
DISPLAY " 16 NVARCHAR(MAX) TEXT TEXT "
DISPLAY " 17 VARBINARY(n) BYTE BYTE "
DISPLAY " 18 VARBINARY(MAX) BYTE BYTE "
DISPLAY " 19 TINYINT SMALLINT SMALLINT "
DISPLAY " 20 BIGINT DECIMAL(19,0) DECIMAL(19,0) "
DISPLAY " 21 UNIQUEIDENTIFIER CHAR(36) VARCHAR(36) "
DISPLAY " 22 BIT SMALLINT CHAR(1) "
DISPLAY " 23 DATE DATE DATE "
DISPLAY " 24 DATETIME2(0) DATETIME Y TO S DATE "
DISPLAY " 25 DATETIME2(n<=5) DATETIME Y TO F(n) DATE "
DISPLAY " 26 DATETIME2(6) VARCHAR2(26) VARCHAR2(26) "
DISPLAY " 27 DATETIME2(7) VARCHAR2(27) VARCHAR2(27) "
DISPLAY " 28 TIME(0) DATETIME H TO S DATETIME H TO S "
DISPLAY " 29 TIME(n<=5) DATETIME H TO F(n) DATETIME H TP F(n) "
DISPLAY " 30 TIME(6) VARCHAR(15) VARCHAR(15) "
DISPLAY " 31 TIME(7) VARCHAR(16) VARCHAR(16) "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
DISPLAY "PostgreSQL conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " PostgreSQL Informix A "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 2 FLOAT4 SMALLFLOAT "
DISPLAY " 3 FLOAT8 FLOAT "
DISPLAY " 4 CHAR(n) CHAR(n) "
DISPLAY " 5 VARCHAR(n) VARCHAR2(n) "
DISPLAY " 6 DATE DATE "
DISPLAY " 7 TIME DATETIME H TO S "
DISPLAY " 8 DATETIME DATETIME Y TO F(5) "
DISPLAY " 9 INT2 SMALLINT "
DISPLAY " 10 INT4 INTEGER "
DISPLAY " 11 BOOL CHAR(1) "
DISPLAY " 12 BIGINT DECIMAL(19,0) "
DISPLAY " 13 INT8 DECIMAL(19,0) "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
DISPLAY "MySQL conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " MySQL Informix A Informix B "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 CHAR(n) CHAR(n) CHAR(n) "
DISPLAY " 2 VARCHAR(n) VARCHAR2(n) VARCHAR(n) "
DISPLAY " 3 DECIMAL(p,s) DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 4 FLOAT SMALLFLOAT SMALLFLOAT "
DISPLAY " 5 DOUBLE FLOAT FLOAT "
DISPLAY " 6 TINYINT SMALLINT SMALLINT "
DISPLAY " 7 SMALLINT SMALLINT SMALLINT "
DISPLAY " 8 MEDIUMINT INTEGER INTEGER "
DISPLAY " 9 INTEGER INTEGER INTEGER "
DISPLAY " 10 BIGINT DECIMAL(19,0) DECIMAL(19,0) "
DISPLAY " 11 DATE DATE DATE "
DISPLAY " 12 TIME DATETIME H TO S DATETIME H TO S "
DISPLAY " 13 DATETIME DATETIME Y TO S DATETIME Y TO S "
DISPLAY " 14 TIMESTAMP DATETIME Y TO S DATETIME Y TO S "
DISPLAY " 15 ENUM(*) VARCHAR2(255) VARCHAR2(1024) "
DISPLAY " 16 TINYTEXT VARCHAR2(255) TEXT "
DISPLAY " 17 TEXT VARCHAR2(65535) TEXT "
DISPLAY " 18 MEDIUMTEXT TEXT TEXT "
DISPLAY " 19 LONGTEXT TEXT TEXT "
DISPLAY " 20 TINYBLOB BYTE BYTE "
DISPLAY " 21 BLOB BYTE BYTE "
DISPLAY " 22 MEDIUMBLOB BYTE BYTE "
DISPLAY " 23 LONGBLOB BYTE BYTE "
DISPLAY " 24 BINARY(M) BYTE BYTE "
DISPLAY " 25 VARBINARY(M) BYTE BYTE "
DISPLAY " 26 YEAR DATETIME Y TO Y SMALLINT "
DISPLAY " 27 BIT(M) SMALLINT SMALLINT "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
DISPLAY "Genero db conversion table:"
DISPLAY ""
DISPLAY " ------------------------------------------------------------------"
DISPLAY " Genero db Informix A "
DISPLAY " ------------------------------------------------------------------"
DISPLAY " 1 DECIMAL(p,s) DECIMAL(p,s) "
DISPLAY " 2 NUMERIC(p,s) DECIMAL(p,s) "
DISPLAY " 3 MONEY(p,s) MONEY(19,4) "
DISPLAY " 4 CHAR(n) CHAR(n) "
DISPLAY " 5 VARCHAR(n) VARCHAR2(n) "
DISPLAY " 6 VARCHAR2(n) VARCHAR2(n) "
DISPLAY " 7 NCHAR(n) NCHAR(n) "
DISPLAY " 8 NVARCHAR(n) NVARCHAR2(n) "
DISPLAY " 9 NVARCHAR2(n) NVARCHAR2(n) "
DISPLAY " 10 DATE DATE "
DISPLAY " 11 TIME DATETIME H TO S "
DISPLAY " 12 TIMESTAMP DATETIME Y TO F(3) "
DISPLAY " 13 DATETIME DATETIME Y TO F(3) "
DISPLAY " 14 BIGINT DECIMAL(19,0) "
DISPLAY " 15 TINYINT SMALLINT "
DISPLAY " 16 SMALLINT SMALLINT "
DISPLAY " 17 INTEGER INTEGER "
DISPLAY " 18 DOUBLE SMALLFLOAT "
DISPLAY " 19 REAL SMALLFLOAT "
DISPLAY " 20 FLOAT FLOAT "
DISPLAY " 21 BINARY BYTE "
DISPLAY " 22 VARBINARY BYTE "
DISPLAY " 23 LONGVARBINARY BYTE "
DISPLAY " 24 LONGVARCHAR TEXT "
DISPLAY " 25 DATETIME s TO e DATETIME s TO e "
DISPLAY " 26 INTERVAL s TO e INTERVAL s TO e "
DISPLAY " ------------------------------------------------------------------"
DISPLAY ""
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION fgldbsch_set_parameter(name, value)
DEFINE name, value STRING
CASE name
WHEN "compat" LET params.compat = value
WHEN "dbname" LET params.dbname = value
WHEN "dbdriver" LET params.dbdriver = value
WHEN "username" LET params.username = value
WHEN "userpswd" LET params.userpswd = value
WHEN "dbowner" LET params.dbowner = value
WHEN "tabname" LET params.tabname = value
WHEN "cvmeth" LET params.cvmeth = value
WHEN "casens" LET params.casens = value
WHEN "systabs" LET params.systabs = value
WHEN "verbose" LET params.verbose = value
END CASE
END FUNCTION
FUNCTION fgldbsch_get_db_type()
RETURN params.dbtype
END FUNCTION
FUNCTION _fgldbsch_get_db_type()
DEFINE dbt CHAR(3)
INITIALIZE dbt TO NULL
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT user FROM user_users WHERE username=user") THEN
LET dbt = "ORA"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT DISTINCT(@@SERVERNAME) FROM INFORMATION_SCHEMA.TABLES") THEN
LET dbt = "MSV"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT CURRENT USER FROM SYS.SYSCATALOG WHERE TNAME='SYSTABLE'") THEN
LET dbt = "ASA"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT USER FROM sysibm.systables WHERE name='SYSTABLES'") THEN
LET dbt = "DB2"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT USER FROM informix.systables WHERE tabid=1") THEN
LET dbt = "IFX"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT USER FROM pg_type WHERE typname = 'bool'") THEN
LET dbt = "PGS"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT CURDATE()") THEN
LET dbt = "MYS"
END IF
END IF
IF dbt IS NULL THEN
IF _fgldbsch_try_select("SELECT USER FROM SYSTEM.TABLE_OF_TABLES WHERE TABLE_NAME = 'TABLE_OF_TABLES'") THEN
LET dbt = "ADS"
END IF
END IF
RETURN dbt
END FUNCTION
FUNCTION _fgldbsch_try_select(stmt)
DEFINE stmt STRING
DEFINE uname CHAR(50)
WHENEVER ERROR CONTINUE
DECLARE sTSU CURSOR FROM stmt
IF sqlca.sqlcode!=0 THEN RETURN FALSE END IF
OPEN sTSU
IF sqlca.sqlcode!=0 THEN RETURN FALSE END IF
FETCH sTSU INTO uname
IF sqlca.sqlcode!=0 THEN RETURN FALSE END IF
CLOSE sTSU
IF sqlca.sqlcode!=0 THEN RETURN FALSE END IF
FREE sTSU
IF sqlca.sqlcode!=0 THEN RETURN FALSE END IF
WHENEVER ERROR STOP
RETURN TRUE
END FUNCTION
FUNCTION _fgldbsch_uplow(name)
DEFINE name STRING
CASE params.casens
WHEN "U" RETURN UPSHIFT(name)
WHEN "L" RETURN DOWNSHIFT(name)
OTHERWISE RETURN name
END CASE
END FUNCTION
FUNCTION fgldbsch_init()
LET params.systabs = "N" -- No system tables by default
LET params.casens = "L" -- lower case by default
LET params.cvmeth = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
END FUNCTION
FUNCTION fgldbsch_fini()
END FUNCTION
FUNCTION fgldbsch_connect()
DEFINE dbspec STRING
DEFINE s INTEGER
LET s = 0
WHENEVER ERROR CONTINUE
LET dbspec = params.dbname
IF params.dbdriver IS NOT NULL THEN
LET dbspec = dbspec || "+driver='"||params.dbdriver||"'"
END IF
IF params.username IS NOT NULL THEN
CONNECT TO dbspec AS "fgldbsch" USER params.username USING params.userpswd
ELSE
CONNECT TO dbspec AS "fgldbsch"
END IF
LET s = STATUS
WHENEVER ERROR STOP
IF s == 0 THEN
LET params.dbtype = _fgldbsch_get_db_type()
-- Give a chance to DDL transactions...
WHENEVER ERROR CONTINUE
SET LOCK MODE TO WAIT 5
WHENEVER ERROR STOP
END IF
RETURN s
END FUNCTION
FUNCTION fgldbsch_disconnect()
WHENEVER ERROR CONTINUE
DISCONNECT "fgldbsch"
WHENEVER ERROR STOP
RETURN STATUS
END FUNCTION
FUNCTION fgldbsch_extract()
LET current_tabname = NULL
CASE params.dbtype
WHEN "IFX" RETURN _fgldbsch_extract_ifx_start()
WHEN "ORA" RETURN _fgldbsch_extract_ora_start()
WHEN "MSV" RETURN _fgldbsch_extract_msv_start()
WHEN "DB2" RETURN _fgldbsch_extract_db2_start()
WHEN "PGS" RETURN _fgldbsch_extract_pgs_start()
WHEN "MYS" RETURN _fgldbsch_extract_mys_start()
WHEN "ADS" RETURN _fgldbsch_extract_ads_start()
END CASE
RETURN -1
END FUNCTION
FUNCTION fgldbsch_next_table()
CALL coldef.clear()
IF current_tabname IS NOT NULL THEN
CALL coldef.appendElement()
LET coldef[1].* = new_coldef.*
LET current_tabname = new_tabname
END IF
CASE params.dbtype
WHEN "IFX" RETURN _fgldbsch_extract_ifx_next()
WHEN "ORA" RETURN _fgldbsch_extract_ora_next()
WHEN "MSV" RETURN _fgldbsch_extract_msv_next()
WHEN "DB2" RETURN _fgldbsch_extract_db2_next()
WHEN "PGS" RETURN _fgldbsch_extract_pgs_next()
WHEN "MYS" RETURN _fgldbsch_extract_mys_next()
WHEN "ADS" RETURN _fgldbsch_extract_ads_next()
END CASE
RETURN -1
END FUNCTION
FUNCTION fgldbsch_get_table_name()
RETURN _fgldbsch_uplow(current_tabname)
END FUNCTION
FUNCTION fgldbsch_get_column_count()
RETURN coldef.getLength()
END FUNCTION
FUNCTION fgldbsch_get_column_info(c)
DEFINE c INTEGER
IF c<0 OR c>fgldbsch_get_column_count() THEN
RETURN NULL, NULL, NULL, -1, -1
END IF
RETURN _fgldbsch_uplow(current_tabname),
_fgldbsch_uplow(coldef[c].colname),
coldef[c].nattype,
coldef[c].ifxtype,
coldef[c].ifxleng
END FUNCTION
FUNCTION _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng)
DEFINE tabname, colname, nattype STRING
DEFINE ifxtype, ifxleng INTEGER
LET new_tabname = tabname CLIPPED
LET new_coldef.colname = colname CLIPPED
LET new_coldef.nattype = nattype CLIPPED
LET new_coldef.ifxtype = ifxtype
LET new_coldef.ifxleng = ifxleng
IF current_tabname IS NULL THEN
LET current_tabname = tabname CLIPPED
ELSE
IF tabname != current_tabname THEN
LET new_tabname = tabname CLIPPED
RETURN 1
END IF
END IF
CALL coldef.appendElement()
LET coldef[coldef.getLength()].* = new_coldef.*
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_owner_warning()
IF params.verbose = "Y" THEN
DISPLAY SFMT("WARNING: No owner specified, using %1 as default", params.username CLIPPED)
DISPLAY ""
END IF
END FUNCTION
FUNCTION _fgldbsch_dtin_qualcode(qname)
DEFINE qname STRING
CASE qname
WHEN "YEAR" RETURN 0
WHEN "MONTH" RETURN 2
WHEN "DAY" RETURN 4
WHEN "HOUR" RETURN 6
WHEN "MINUTE" RETURN 8
WHEN "SECOND" RETURN 10
WHEN "FRACTION" RETURN 12 -- As first qualifier
WHEN "FRACTION(1)" RETURN 11 -- Not used with ADS
WHEN "FRACTION(2)" RETURN 12 -- Not used with ADS
WHEN "FRACTION(3)" RETURN 13 -- Not used with ADS
WHEN "FRACTION(4)" RETURN 14 -- Not used with ADS
WHEN "FRACTION(5)" RETURN 15 -- Not used with ADS
END CASE
RETURN -1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_ifx_decimal(tn,len)
DEFINE tn STRING
DEFINE len, prec, scal SMALLINT
LET prec = len / 256
LET scal = len mod 256
IF scal == 255 THEN
RETURN SFMT("%1(%2)",tn,prec)
ELSE
RETURN SFMT("%1(%2,%3)",tn,prec,scal)
END IF
END FUNCTION
FUNCTION _fgldbsch_ifx_varchar(tn,len)
DEFINE tn STRING
DEFINE len, lmin, lmax SMALLINT
DEFINE xlen INTEGER
IF len < 0 THEN
LET xlen = len + 65536
ELSE
LET xlen = len
END IF
LET lmin = xlen / 256
LET lmax = xlen mod 256
IF lmin == 0 THEN
RETURN SFMT("%1(%2)",tn,lmax)
ELSE
RETURN SFMT("%1(%2,%3)",tn,lmax,lmin)
END IF
END FUNCTION
FUNCTION _fgldbsch_ifx_dtiq(qual,p)
DEFINE qual,p SMALLINT
CASE qual
WHEN dtiqual_year RETURN "YEAR"
WHEN dtiqual_month RETURN "MONTH"
WHEN dtiqual_day RETURN "DAY"
WHEN dtiqual_hour RETURN "HOUR"
WHEN dtiqual_minute RETURN "MINUTE"
WHEN dtiqual_second RETURN "SECOND"
END CASE
IF p==1 THEN
RETURN "FRACTION"
ELSE
CASE qual
WHEN dtiqual_frac1 RETURN "FRACTION(1)"
WHEN dtiqual_frac2 RETURN "FRACTION(2)"
WHEN dtiqual_frac3 RETURN "FRACTION(3)"
WHEN dtiqual_frac4 RETURN "FRACTION(4)"
WHEN dtiqual_frac5 RETURN "FRACTION(5)"
END CASE
END IF
END FUNCTION
FUNCTION _fgldbsch_ifx_datetime(len)
DEFINE len, q1, q2 SMALLINT
LET q1 = (len MOD 256) / 16
LET q2 = (len MOD 256) MOD 16
RETURN SFMT("DATETIME %1 TO %2", _fgldbsch_ifx_dtiq(q1,1), _fgldbsch_ifx_dtiq(q2,2))
END FUNCTION
FUNCTION _fgldbsch_ifx_interval(len)
DEFINE len, l, q1, q2 SMALLINT
LET q1 = (len MOD 256) / 16
LET q2 = (len MOD 256) MOD 16
LET l = ( len / 256 ) - ( q2 - q1 )
IF q1 < dtiqual_frac1 THEN
RETURN SFMT("INTERVAL %1(%2) TO %3", _fgldbsch_ifx_dtiq(q1,1), l, _fgldbsch_ifx_dtiq(q2,2))
ELSE
RETURN SFMT("INTERVAL %1 TO %2", _fgldbsch_ifx_dtiq(q1,1), _fgldbsch_ifx_dtiq(q2,2))
END IF
END FUNCTION
FUNCTION _fgldbsch_informix_typename(ifxtype, ifxleng, xtdtype)
DEFINE ifxtype SMALLINT
DEFINE ifxleng SMALLINT
DEFINE xtdtype INTEGER
DEFINE nattype STRING
DEFINE modv SMALLINT
LET nattype = SFMT("encoded=(%1,%2)",ifxtype,ifxleng)
LET modv = ( ifxtype MOD 256 )
CASE
WHEN modv<=16
CASE modv
WHEN 0 LET nattype = SFMT("CHAR(%1)",ifxleng)
WHEN 1 LET nattype = "SMALLINT"
WHEN 2 LET nattype = "INTEGER"
WHEN 3 LET nattype = "FLOAT"
WHEN 4 LET nattype = "SMALLFLOAT"
WHEN 5 LET nattype = _fgldbsch_ifx_decimal("DECIMAL",ifxleng)
WHEN 6 LET nattype = "SERIAL"
WHEN 7 LET nattype = "DATE"
WHEN 8 LET nattype = _fgldbsch_ifx_decimal("DECIMAL",ifxleng)
WHEN 9 LET nattype = "NULL"
WHEN 10 LET nattype = _fgldbsch_ifx_datetime(ifxleng)
WHEN 11 LET nattype = "BYTE"
WHEN 12 LET nattype = "TEXT"
WHEN 13 LET nattype = _fgldbsch_ifx_varchar("VARCHAR",ifxleng)
WHEN 14 LET nattype = _fgldbsch_ifx_interval(ifxleng)
WHEN 15 LET nattype = SFMT("NCHAR(%1)",ifxleng)
WHEN 16 LET nattype = _fgldbsch_ifx_varchar("NVARCHAR",ifxleng)
END CASE
WHEN modv=41 AND xtdtype==5 LET nattype = "BOOL"
WHEN modv=17 LET nattype = "INT8"
WHEN modv=18 LET nattype = "SERIAL8"
WHEN modv=40 AND xtdtype==1 LET nattype = "LVARCHAR"
END CASE
RETURN nattype
END FUNCTION
-- Converts special Informix database types that are not supported in 4gl...
FUNCTION _fgldbsch_convert_datatype_ifx( tabname, colname, ifxtype, ifxleng, xtdtype )
DEFINE tabname, colname CHAR(200)
DEFINE ifxtype SMALLINT
DEFINE ifxleng SMALLINT
DEFINE xtdtype INTEGER
DEFINE nattype STRING
DEFINE modv SMALLINT
DEFINE base SMALLINT
IF ifxtype>=4096 THEN -- Unsupported Informix datatype
RETURN NULL, -1, 0
END IF
LET nattype = _fgldbsch_informix_typename(ifxtype, ifxleng, xtdtype)
LET modv = ( ifxtype MOD 256 )
LET ifxtype = ( ifxtype MOD 2048 ) -- Distinct type
CASE
WHEN modv=41 AND xtdtype==5 -- BOOL
IF params.cvmeth[1,1] = "B" THEN
LET base = ifxtype / 256
LET ifxtype = ( base * 256 )
LET ifxleng = 1
IF params.compat == "Y" THEN
DISPLAY SFMT("Warning: BOOLEAN type column \"%1.%2\" converted to CHAR(1).",
tabname CLIPPED, colname CLIPPED)
END IF
ELSE
LET ifxtype = -1
END IF
WHEN modv=17 -- INT8
IF params.cvmeth[2,2] = "B" THEN
LET base = ifxtype / 256
LET ifxtype = ( base * 256 ) + 5
LET ifxleng = 4864
IF params.compat == "Y" THEN
DISPLAY SFMT("Warning: INT8 type column \"%1.%2\" converted to DECIMAL(19,0).",
tabname CLIPPED, colname CLIPPED)
END IF
ELSE
LET ifxtype = -1
END IF
WHEN modv=18 -- SERIAL8
IF params.cvmeth[3,3] = "B" THEN
LET base = ifxtype / 256
LET ifxtype = ( base * 256 ) + 5
LET ifxleng = 4864
IF params.compat == "Y" THEN
DISPLAY SFMT("Warning: SERIAL8 type column \"%1.%2\" converted to DECIMAL(19,0).",
tabname CLIPPED, colname CLIPPED)
END IF
ELSE
LET ifxtype = -1
END IF
WHEN modv=40 AND xtdtype==1 -- LVARCHAR
IF params.cvmeth[4,4] = "B" THEN
LET base = ifxtype / 256
-- Type code 201 is VARCHAR2 with size>255 in .sch!
LET ifxtype = ( base * 256 ) + 201
IF params.compat == "Y" THEN
DISPLAY SFMT("Warning: LVARCHAR type column \"%1.%2\" converted to VARCHAR2(%3).",
tabname CLIPPED, colname CLIPPED, ifxleng)
END IF
ELSE
LET ifxtype = -1
END IF
OTHERWISE
IF modv<=16 THEN
LET ifxtype = ifxtype
ELSE
LET ifxtype = -1
END IF
END CASE
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_ifx(p)
DEFINE p STRING
DEFINE s STRING
LET s = " "
IF params.tabname IS NOT NULL THEN
LET s = s, " AND ",p,".TABNAME = '",params.tabname,"'"
END IF
IF params.systabs=="N" THEN
LET s = s, " AND ",p,".TABID > 99 "
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND ",p,".OWNER='",params.dbowner,"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_ifx_start()
DEFINE stmt STRING
DEFINE tabname CHAR(200) -- Warning: Must use CHAR to support SE engines!
DEFINE hassyno INTEGER
DEFINE syncount INTEGER
DEFINE xtdtcol STRING
DEFINE rsyn RECORD
ltabname CHAR(64),
rservername CHAR(64),
dbname CHAR(64),
owner CHAR(64),
rtabname CHAR(64),
lservername CHAR(64)
END RECORD
WHENEVER ERROR CONTINUE
DROP TABLE FGLDBSCH_COLS
WHENEVER ERROR STOP
CREATE TEMP TABLE FGLDBSCH_COLS (
TABNAME CHAR(200), -- Warning: Must use CHAR to support SE engines!
COLNAME CHAR(200),
COLTYPE SMALLINT,
COLLENGTH SMALLINT,
COLNO SMALLINT,
COLEXT INTEGER
)
-- Check if synonym table exists
SELECT t.tabname INTO tabname
FROM "informix".systables t
WHERE t.tabname = "syssyntable"
LET hassyno = (SQLCA.SQLCODE==0)
-- No check if there are rows in syssyntable
IF hassyno THEN
DECLARE cifx_syssyntable CURSOR
FOR SELECT t.tabname FROM "informix".syssyntable t
OPEN cifx_syssyntable
FETCH cifx_syssyntable
LET hassyno = (SQLCA.SQLCODE==0)
FREE cifx_syssyntable
END IF
-- Check if extended types table exist (IDS)
-- The coltypes 40 and 41 and OPAQUE types (variable and fixed).
-- To detect LVARCHAR, BOOLEAN, CLOB and BLOB columns, we must
-- look in the extended_id column to get the final type!
-- Extended types are IDS specific types, defined in sysxtdtypes.
SELECT t.tabname INTO tabname
FROM "informix".systables t
WHERE t.tabname = "sysxtdtypes"
IF SQLCA.SQLCODE == 0 THEN
LET xtdtcol = " C.EXTENDED_ID"
ELSE
LET xtdtcol = " 0"
END IF
LET stmt = "INSERT INTO FGLDBSCH_COLS SELECT",
" T.TABNAME,",
" C.COLNAME,",
" C.COLTYPE,",
" C.COLLENGTH,",
" C.COLNO,",
xtdtcol,
" FROM ""informix"".SYSCOLUMNS C, ""informix"".SYSTABLES T",
" WHERE C.TABID = T.TABID",
_fgldbsch_get_selection_filter_ifx("T")
EXECUTE IMMEDIATE stmt
IF hassyno THEN
-- Local PUBLIC/PRIVATE synonyms:
-- WARNING: We do not manage owners in the schema files!
-- If no owner is specified, we extract only PUBLIC synonyms.
-- If an owner is specified, we extract PUBLIC and PRIVATE synonyms.
LET stmt =
"INSERT INTO FGLDBSCH_COLS SELECT",
" T.TABNAME,", -- Name of the synonym!
" C.COLNAME,",
" C.COLTYPE,",
" C.COLLENGTH,",
" C.COLNO,",
xtdtcol,
" FROM ""informix"".SYSCOLUMNS C, ""informix"".SYSSYNTABLE S, ""informix"".SYSTABLES T",
" WHERE S.BTABID = C.TABID",
" AND T.TABID = S.TABID",
" AND S.BTABID IS NOT NULL",
_fgldbsch_get_selection_filter_ifx("T")
IF params.dbowner IS NOT NULL THEN
LET stmt = stmt, " AND T.TABTYPE IN ('P','S')"
ELSE
LET stmt = stmt, " AND T.TABTYPE = 'S'" -- ONLY PUBLIC SYNONYMS!!!
END IF
EXECUTE IMMEDIATE stmt
END IF
IF hassyno THEN
-- Remove synonyms only exist OnLine and higher engines, which support
-- the DBSERVERNAME built-in function. So, only try to deal with
-- remote synonyms if there are any to deal with.
SELECT COUNT(*) INTO syncount FROM 'informix'.SYSSYNTABLE WHERE btabid IS NULL
IF syncount>0 THEN
LET stmt =
"SELECT T.TABNAME LTABNAME, S.SERVERNAME RSERVERNAME,",
" S.DBNAME, S.OWNER, S.TABNAME RTABNAME, DBSERVERNAME LSERVERNAME",
" FROM 'informix'.SYSTABLES T, 'informix'.SYSSYNTABLE S",
" WHERE T.TABID = S.TABID",
" AND T.TABTYPE = 'S'", -- ONLY PUBLIC SYNONYMS!!!
" AND S.BTABID IS NULL",
_fgldbsch_get_selection_filter_ifx("T")
DECLARE c_remsyn CURSOR FROM stmt
FOREACH c_remsyn INTO rsyn.*
IF rsyn.rservername IS NULL OR rsyn.rservername = ' ' THEN
LET rsyn.rservername = rsyn.lservername
END IF
LET stmt = "INSERT INTO FGLDBSCH_COLS SELECT ",
"'", rsyn.ltabname CLIPPED, "',",
" C.COLNAME, C.COLTYPE, C.COLLENGTH, C.COLNO,", xtdtcol,
" FROM ",
rsyn.dbname CLIPPED, "@", rsyn.rservername CLIPPED, ":'informix'.SYSTABLES T,",
rsyn.dbname CLIPPED, "@", rsyn.rservername CLIPPED, ":'informix'.SYSCOLUMNS C",
" WHERE C.TABID = T.Tabid AND T.TABNAME = '", rsyn.rtabname CLIPPED,
"' AND T.OWNER = '", rsyn.owner CLIPPED, "'"
EXECUTE IMMEDIATE stmt
END FOREACH
END IF
END IF
WHENEVER ERROR CONTINUE
DECLARE ctc_ifx CURSOR FOR SELECT * FROM FGLDBSCH_COLS ORDER BY 1, 5
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_ifx
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_ifx_next()
DEFINE tabname VARCHAR(200)
DEFINE colname CHAR(200)
DEFINE coltype INTEGER
DEFINE coltplen INTEGER
DEFINE colident SMALLINT
DEFINE xtdtype INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_ifx INTO
tabname,
colname,
coltype,
coltplen,
colident,
xtdtype
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_ifx
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_ifx(
tabname,
colname,
coltype,
coltplen,
xtdtype
) RETURNING
nattype,
ifxtype,
ifxleng
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_convert_datatype_ora( oratype, oraleng, oraprec, orascal, oranull )
DEFINE oratype VARCHAR(100)
DEFINE oraleng INTEGER
DEFINE oraprec INTEGER
DEFINE orascal INTEGER
DEFINE oranull CHAR(1)
DEFINE ot VARCHAR(100)
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
DEFINE nattype STRING
LET ifxtype = -1
LET ot = UPSHIFT(oratype)
LET nattype = ot
CASE
WHEN ot = "CHAR"
LET ifxtype = 0
LET ifxleng = oraleng
LET nattype = SFMT("%1(%2)",ot,oraleng)
WHEN ot = "VARCHAR"
CASE params.cvmeth[3,3]
WHEN "A"
LET ifxtype = 201
LET ifxleng = oraleng
WHEN "B"
LET ifxtype = 0
LET ifxleng = oraleng
END CASE
LET nattype = SFMT("%1(%2)",ot,oraleng)
WHEN ot = "VARCHAR2"
CASE params.cvmeth[4,4]
WHEN "A"
LET ifxtype = 201
LET ifxleng = oraleng
WHEN "B"
LET ifxtype = 0
LET ifxleng = oraleng
END CASE
LET nattype = SFMT("%1(%2)",ot,oraleng)
WHEN ot = "NCHAR"
CASE params.cvmeth[15,15]
WHEN "A"
LET ifxtype = 0
LET ifxleng = oraleng
WHEN "B"
LET ifxtype = 15
LET ifxleng = oraleng
END CASE
LET nattype = SFMT("%1(%2)",ot,oraleng)
WHEN ot = "NVARCHAR2"
CASE params.cvmeth[16,16]
WHEN "A"
LET ifxtype = 201
LET ifxleng = oraleng
WHEN "B"
LET ifxtype = 202
LET ifxleng = oraleng
END CASE
LET nattype = SFMT("%1(%2)",ot,oraleng)
WHEN ot = "NUMBER"
CASE
WHEN oraprec=5 AND orascal=0 AND params.cvmeth[6,6]='A'
LET ifxtype = 1 -- SMALLINT
LET ifxleng = 2
WHEN oraprec=10 AND orascal=0 AND params.cvmeth[7,7]='A'
LET ifxtype = 2 -- INTEGER
LET ifxleng = 4
OTHERWISE
LET ifxtype = 5 -- DECIMAL
LET ifxleng = oraprec * 256 + orascal
END CASE
CASE
WHEN oraprec IS NOT NULL AND orascal IS NOT NULL
LET nattype = SFMT("%1(%2,%3)",ot,oraprec,orascal)
WHEN oraprec IS NOT NULL
LET nattype = SFMT("%1(%2)",ot,oraprec)
OTHERWISE
LET nattype = ot
END CASE
WHEN ot = "DATE"
CASE params.cvmeth[5,5]
WHEN "A"
LET ifxtype = 7
LET ifxleng = 4
WHEN "B"
LET ifxtype = 10
LET ifxleng = 3594
END CASE
LET nattype = ot
WHEN ot[1,9] = "TIMESTAMP"
IF orascal==0 THEN -- TIMESTAMP(0) exists in Oracle!
CASE params.cvmeth[12,12]
WHEN "A"
LET ifxtype = 10
LET ifxleng = 3594
WHEN "B"
LET ifxtype = 7
LET ifxleng = 4
END CASE
ELSE
LET ifxtype = 10
CASE orascal
WHEN 1 LET ifxleng = 3851 -- (15*256)+(0*16)+11
WHEN 2 LET ifxleng = 4108 -- (16*256)+(0*16)+12
WHEN 3 LET ifxleng = 4365 -- (17*256)+(0*16)+13
WHEN 4 LET ifxleng = 4622 -- (18*256)+(0*16)+14
WHEN 5 LET ifxleng = 4879 -- (19*256)+(0*16)+15
WHEN 6 LET ifxleng = -1 -- Precision of 6 not supported!
END CASE
END IF
LET nattype = SFMT("%1(%2)",ot,orascal)
WHEN ot[1,8] = "INTERVAL"
LET ifxtype = 14
CASE oraleng
WHEN 5 -- ORACLE INTERVAL YEAR TO MONTH
LET ifxleng = ((oraprec+2)*256)+(0*16)+2
LET nattype = "INTERVAL YEAR TO MONTH"
WHEN 11 -- ORACLE INTERVAL DAY TO SECOND (= ifx FRACTION)
IF orascal<6 THEN
LET ifxleng = ((oraprec+6+orascal)*256)+(4*16)+(10+orascal)
ELSE
LET ifxtype = -1
END IF
LET nattype = "INTERVAL DAY TO FRACTION"
OTHERWISE
LET ifxtype = -1
LET nattype = NULL
END CASE
WHEN ot = "FLOAT"
CASE params.cvmeth[11,11]
WHEN "A"
LET ifxtype = 5 -- DECIMAL
LET ifxleng = oraprec * 0.30103
LET ifxleng = (ifxleng+1)*256 + 255
WHEN "B"
LET ifxtype = 3 -- FLOAT
LET ifxleng = 8
END CASE
WHEN ot = "BLOB"
LET ifxtype = 11 -- BYTE
LET ifxleng = 56
WHEN ot = "CLOB"
LET ifxtype = 12 -- TEXT
LET ifxleng = 56
END CASE
IF ifxtype>-1 AND oranull="N" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_ora(p)
DEFINE p STRING
DEFINE s STRING
LET s = " "
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(",p,".TABLE_NAME) = '",UPSHIFT(params.tabname),"'"
END IF
IF params.systabs=="N" THEN
LET s = s, " AND ",p,".OWNER <> 'SYS' AND ",p,".OWNER <> 'SYSTEM'"
END IF
IF params.dbowner IS NULL THEN
CALL _fgldbsch_owner_warning()
LET params.dbowner = params.username
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND UPPER(",p,".OWNER)='",UPSHIFT(params.dbowner),"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_ora_start()
DEFINE stmt STRING
LET stmt = "SELECT",
" C.TABLE_NAME,",
" C.COLUMN_NAME,",
" C.DATA_TYPE,",
" C.DATA_LENGTH,",
" C.DATA_PRECISION,",
" C.DATA_SCALE,",
" C.NULLABLE,",
" C.COLUMN_ID",
" FROM ALL_TAB_COLUMNS C",
" WHERE C.TABLE_NAME NOT LIKE 'BIN$%'",
_fgldbsch_get_selection_filter_ora("C"),
" ORDER BY C.TABLE_NAME, C.COLUMN_ID"
WHENEVER ERROR CONTINUE
DECLARE ctc_ora CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_ora
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_ora_next()
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE coltplen INTEGER
DEFINE coltpprc INTEGER
DEFINE coltpscl INTEGER
DEFINE colnullc CHAR(1)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_ora INTO
tabname,
colname,
coltype,
coltplen,
coltpprc,
coltpscl,
colnullc,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_ora
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_ora(
coltype,
coltplen,
coltpprc,
coltpscl,
colnullc
) RETURNING
nattype,
ifxtype,
ifxleng
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_convert_datatype_db2( db2type, db2leng, db2scal, db2null )
DEFINE db2type VARCHAR(100)
DEFINE db2leng INTEGER
DEFINE db2scal INTEGER
DEFINE db2null CHAR(1)
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
DEFINE tn STRING
LET ifxtype = -1
LET tn = UPSHIFT(db2type)
LET nattype = tn
CASE tn
WHEN "CHARACTER"
LET ifxtype = 0
LET ifxleng = db2leng
LET nattype = SFMT("%1(%2)",tn,db2leng)
WHEN "VARCHAR"
LET ifxtype = 201
LET ifxleng = db2leng
LET nattype = SFMT("%1(%2)",tn,db2leng)
WHEN "DECIMAL"
LET ifxtype = 5
LET ifxleng = db2leng * 256 + db2scal
LET nattype = SFMT("%1(%2,%3)",tn,db2leng,db2scal)
WHEN "REAL"
LET ifxtype = 4
LET ifxleng = 4
WHEN "DOUBLE"
LET ifxtype = 3
LET ifxleng = 8
WHEN "SMALLINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN "INTEGER"
LET ifxtype = 2
LET ifxleng = 4
WHEN "DATE"
LET ifxtype = 7
LET ifxleng = 4
WHEN "TIME"
LET ifxtype = 10
LET ifxleng = 1642
WHEN "TIMESTAMP"
LET ifxtype = 10
LET ifxleng = 4879
WHEN "BLOB"
LET ifxtype = 11
LET ifxleng = 56
WHEN "CLOB"
LET ifxtype = 12
LET ifxleng = 56
WHEN "GRAPHIC"
LET ifxtype = 0
LET ifxleng = db2leng
LET nattype = SFMT("%1(%2)",tn,db2leng)
WHEN "VARGRAPHIC"
LET ifxtype = 201
LET ifxleng = db2leng
LET nattype = SFMT("%1(%2)",tn,db2leng)
WHEN "XML"
LET ifxtype = 201
LET ifxleng = 16384 -- 0x4000 (see driver)
END CASE
IF ifxtype>-1 AND db2null="N" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_db2(t,c)
DEFINE t,c STRING
DEFINE s STRING
LET s = " "
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(",t,") = '",UPSHIFT(params.tabname),"'"
END IF
IF params.systabs=="N" THEN
LET s = s, " AND UPPER(",c,") <> 'SYSIBM'",
" AND UPPER(",c,") <> 'SYSCAT'",
" AND UPPER(",c,") <> 'SYSSTAT'"
END IF
IF params.dbowner IS NULL THEN
CALL _fgldbsch_owner_warning()
LET params.dbowner = params.username
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND UPPER(",c,")='",UPSHIFT(params.dbowner),"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_db2_start()
DEFINE stmt STRING
LET stmt = "SELECT",
" TBNAME,",
" NAME,",
" TYPENAME,",
" LENGTH,",
" SCALE,",
" NULLS,",
" COLNO",
" FROM SYSIBM.SYSCOLUMNS",
" WHERE 1=1",
_fgldbsch_get_selection_filter_db2("TBNAME","TBCREATOR"),
" ORDER BY TBNAME, COLNO"
WHENEVER ERROR CONTINUE
DECLARE ctc_db2 CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_db2
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_db2_next()
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE coltplen INTEGER
DEFINE coltpscl INTEGER
DEFINE colnullc CHAR(1)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_db2 INTO
tabname,
colname,
coltype,
coltplen,
coltpscl,
colnullc,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_db2
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_db2(
coltype,
coltplen,
coltpscl,
colnullc
) RETURNING
nattype,
ifxtype,
ifxleng
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_msv_is_identity( tabname, colname )
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE r INTEGER
WHENEVER ERROR CONTINUE
IF NOT s_msv_identity_prepared THEN
PREPARE s_msv_identity FROM
"SELECT CAST(c.is_identity AS INT)" ||
" FROM sys.all_objects o, sys.all_columns c" ||
" WHERE o.name = ? AND c.name = ?" ||
" AND o.object_id = c.object_id" ||
" AND o.type = 'U'"
LET s_msv_identity_prepared = (SQLCA.SQLCODE == 0)
END IF
IF s_msv_identity_prepared THEN
EXECUTE s_msv_identity USING tabname, colname INTO r
END IF
WHENEVER ERROR STOP
RETURN r
END FUNCTION
# Note1:
# When using UTF-8 in FGL applications, we recommend to use the same size
# for the N[VAR]CHAR SQL SERVER column as for the FGL variable:
# [VAR]CHAR(500) in FGL <=> N[VAR]CHAR(500) in SQL SERVER
# This is to be Informix compatible and store up to 500 ASCII chars...
# So when extracting a DB schema from SQL SERVER, N[VAR]CHAR size (in bytes)
# must be divided by two.
# Warning: We cannot use the CHARACTER_MAXIMUM_LENGTH column in the SELECT,
# because multi-byte applications (BIG5) can store MB chars in [VAR]CHAR,
# and in this case we must use CHARACTER_OCTET_LENGTH as is.
FUNCTION _fgldbsch_convert_datatype_msv( tabname, colname, msvtype, msvchrl, msvprec, msvscal, msvdtpr, msvnull )
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE msvtype VARCHAR(100)
DEFINE msvchrl INTEGER
DEFINE msvprec INTEGER
DEFINE msvscal INTEGER
DEFINE msvdtpr INTEGER
DEFINE msvnull CHAR(4)
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
LET ifxtype = -1
LET nattype = msvtype
CASE
WHEN msvtype = "CHAR"
LET ifxtype = 0
LET ifxleng = msvchrl
LET nattype = SFMT("%1(%2)",msvtype,msvchrl)
WHEN msvtype = "VARCHAR" AND msvchrl == -1 -- VARCHAR(MAX)
LET ifxtype = 12 -- TEXT
LET ifxleng = 56
LET nattype = "VARCHAR(MAX)"
WHEN msvtype = "VARCHAR" AND msvchrl > 0 -- VARCHAR(n)
CASE params.cvmeth[3,3]
WHEN "A"
LET ifxtype = 201
LET ifxleng = msvchrl
WHEN "B"
LET ifxtype = 0
LET ifxleng = msvchrl
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvchrl)
WHEN msvtype = "NCHAR"
CASE params.cvmeth[10,10]
WHEN "A"
LET ifxtype = 0
LET ifxleng = msvchrl / 2 -- See Note1
WHEN "B"
LET ifxtype = 15
LET ifxleng = msvchrl / 2 -- See Note1
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvchrl)
WHEN msvtype = "NVARCHAR" AND msvchrl == -1 -- NVARCHAR(MAX)
LET ifxtype = 12 -- TEXT
LET ifxleng = 56
LET nattype = "NVARCHAR(MAX)"
WHEN msvtype = "NVARCHAR" AND msvchrl > 0 -- NVARCHAR(n)
CASE params.cvmeth[11,11]
WHEN "A"
LET ifxtype = 201
LET ifxleng = msvchrl / 2 -- See Note1
WHEN "B"
LET ifxtype = 202
LET ifxleng = msvchrl / 2 -- See Note1
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvchrl)
WHEN msvtype = "NUMERIC"
LET ifxtype = 5
LET ifxleng = msvprec * 256 + msvscal
LET nattype = SFMT("%1(%2,%3)",msvtype,msvprec,msvscal)
WHEN msvtype = "DECIMAL"
LET ifxtype = 5
LET ifxleng = msvprec * 256 + msvscal
LET nattype = SFMT("%1(%2,%3)",msvtype,msvprec,msvscal)
WHEN msvtype = "FLOAT"
LET ifxtype = 3
LET ifxleng = 8
WHEN msvtype = "REAL"
LET ifxtype = 4
LET ifxleng = 4
WHEN msvtype = "TINYINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN msvtype = "SMALLINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN msvtype = "INT"
IF _fgldbsch_msv_is_identity( tabname, colname ) THEN
LET ifxtype = 6
ELSE
LET ifxtype = 2
END IF
LET ifxleng = 4
WHEN msvtype = "BIGINT"
LET ifxtype = 5
LET ifxleng = 19 * 256
WHEN msvtype = "SMALLDATETIME"
LET ifxtype = 7
LET ifxleng = 4
WHEN msvtype = "DATETIME"
CASE params.cvmeth[5,5]
WHEN "A"
LET ifxtype = 10
LET ifxleng = 4365
WHEN "B"
LET ifxtype = 7
LET ifxleng = 4
END CASE
WHEN msvtype = "IMAGE"
LET ifxtype = 11 -- BYTE
LET ifxleng = 56
WHEN msvtype = "TEXT"
LET ifxtype = 12 -- TEXT
LET ifxleng = 56
WHEN msvtype = "NTEXT"
LET ifxtype = 12 -- TEXT
LET ifxleng = 56
WHEN msvtype = "VARBINARY" AND msvchrl == -1 -- VARBINARY(MAX)
LET ifxtype = 11 -- BYTE
LET ifxleng = 56
LET nattype = "VARBINARY(MAX)"
WHEN msvtype = "VARBINARY" AND msvchrl > 0 -- VARBINARY(n)
LET ifxtype = 11 -- BYTE
LET ifxleng = 56
LET nattype = SFMT("%1(%2)",msvtype,msvchrl)
WHEN msvtype = "UNIQUEIDENTIFIER"
CASE params.cvmeth[21,21]
WHEN "A"
LET ifxtype = 0
LET ifxleng = 36
WHEN "B"
LET ifxtype = 201
LET ifxleng = 36
WHEN "X"
-- Column will be ignored!
LET ifxtype = -2
END CASE
WHEN msvtype = "BIT"
CASE params.cvmeth[22,22]
WHEN "A"
LET ifxtype = 1
LET ifxleng = 2
WHEN "B"
LET ifxtype = 0
LET ifxleng = 1
END CASE
WHEN msvtype = "DATE"
LET ifxtype = 7
LET ifxleng = 4
WHEN msvtype = "DATETIME2" AND msvdtpr == 0
CASE params.cvmeth[24,24]
WHEN "A"
LET ifxtype = 10
LET ifxleng = 3594 -- DATETIME YEAR TO SECOND
WHEN "B"
LET ifxtype = 7
LET ifxleng = 4
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "DATETIME2" AND msvdtpr <= 5
CASE params.cvmeth[25,25]
WHEN "A"
LET ifxtype = 10
CASE msvdtpr
WHEN 1 LET ifxleng = 3851 -- DATETIME YEAR TO FRACTION(1)
WHEN 2 LET ifxleng = 4108 -- DATETIME YEAR TO FRACTION(2)
WHEN 3 LET ifxleng = 4365 -- DATETIME YEAR TO FRACTION(3)
WHEN 4 LET ifxleng = 4622 -- DATETIME YEAR TO FRACTION(4)
WHEN 5 LET ifxleng = 4879 -- DATETIME YEAR TO FRACTION(5)
END CASE
WHEN "B"
LET ifxtype = 7
LET ifxleng = 4
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "DATETIME2" AND msvdtpr == 6
LET ifxtype = 201
LET ifxleng = 26
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "DATETIME2" AND msvdtpr == 7
LET ifxtype = 201
LET ifxleng = 27
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "TIME" AND msvdtpr == 0
LET ifxtype = 10
LET ifxleng = 1642 -- DATETIME HOUR TO SECOND
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "TIME" AND msvdtpr <= 5
LET ifxtype = 10
CASE msvdtpr
WHEN 1 LET ifxleng = 1899 -- DATETIME HOUR TO FRACTION(1)
WHEN 2 LET ifxleng = 2156 -- DATETIME HOUR TO FRACTION(2)
WHEN 3 LET ifxleng = 2413 -- DATETIME HOUR TO FRACTION(3)
WHEN 4 LET ifxleng = 2670 -- DATETIME HOUR TO FRACTION(4)
WHEN 5 LET ifxleng = 2927 -- DATETIME HOUR TO FRACTION(5)
END CASE
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "TIME" AND msvdtpr == 6
LET ifxtype = 201
LET ifxleng = 15
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
WHEN msvtype = "TIME" AND msvdtpr == 7
LET ifxtype = 201
LET ifxleng = 16
LET nattype = SFMT("%1(%2)",msvtype,msvdtpr)
END CASE
IF ifxtype>-1 AND UPSHIFT(msvnull)=="NO" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_msv()
DEFINE s STRING
LET s = " AND T.TABLE_NAME != 'dtproperties'"
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(T.TABLE_NAME) = '",UPSHIFT(params.tabname),"'"
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND UPPER(T.TABLE_SCHEMA)='",UPSHIFT(params.dbowner),"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_msv_start()
DEFINE stmt STRING
LET stmt = "SELECT",
" C.TABLE_NAME,",
" C.COLUMN_NAME,",
" UPPER(C.DATA_TYPE),",
" C.CHARACTER_OCTET_LENGTH,",
" C.NUMERIC_PRECISION,",
" C.NUMERIC_SCALE,",
" C.DATETIME_PRECISION,",
" C.IS_NULLABLE,",
" C.ORDINAL_POSITION",
" FROM INFORMATION_SCHEMA.COLUMNS C, INFORMATION_SCHEMA.TABLES T",
" WHERE T.TABLE_SCHEMA = C.TABLE_SCHEMA",
" AND T.TABLE_NAME = C.TABLE_NAME",
" AND T.TABLE_TYPE IN ( 'BASE TABLE', 'VIEW' )",
_fgldbsch_get_selection_filter_msv(),
" ORDER BY C.TABLE_NAME, C.ORDINAL_POSITION"
WHENEVER ERROR CONTINUE
DECLARE ctc_msv CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_msv
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_msv_next()
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE colcharl INTEGER
DEFINE coltpprc INTEGER
DEFINE coltpscl INTEGER
DEFINE coldtprc INTEGER
DEFINE colnullc VARCHAR(10)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_msv INTO
tabname,
colname,
coltype,
colcharl,
coltpprc,
coltpscl,
coldtprc,
colnullc,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_msv
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_msv(
tabname,
colname,
coltype,
colcharl,
coltpprc,
coltpscl,
coldtprc,
colnullc
) RETURNING
nattype,
ifxtype,
ifxleng
IF ifxtype == -2 THEN
DISPLAY SFMT("Warning: %1 column \"%2.%3\" is ignored.",
nattype CLIPPED, tabname CLIPPED, colname CLIPPED)
CONTINUE WHILE
END IF
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_convert_datatype_pgs( pgstype, pgsleng, pgstmod, pgsnull )
DEFINE pgstype VARCHAR(100)
DEFINE pgsleng INTEGER
DEFINE pgstmod INTEGER
DEFINE pgsnull CHAR(1)
DEFINE tmbase INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
DEFINE tn STRING
LET ifxtype = -1
LET tmbase = pgstmod-4 -- This is atttypmod - sizeof(int4)
LET tn = UPSHIFT(pgstype)
LET nattype = tn
CASE tn
WHEN "BOOL"
LET ifxtype = 0
LET ifxleng = 1
WHEN "BPCHAR"
LET ifxtype = 0
LET ifxleng = tmbase
LET nattype = SFMT("%1(%2)",tn,tmbase)
WHEN "VARCHAR"
LET ifxtype = 201
LET ifxleng = tmbase
LET nattype = SFMT("%1(%2)",tn,tmbase)
WHEN "NUMERIC"
LET ifxtype = 5
LET ifxleng = ( tmbase / 65536 ) * 256 + ( tmbase mod 65536 )
LET nattype = SFMT("%1(%2,%3)",tn, tmbase / 65536, tmbase mod 65536)
WHEN "FLOAT4"
LET ifxtype = 4
LET ifxleng = 4
WHEN "FLOAT8"
LET ifxtype = 3
LET ifxleng = 8
WHEN "INT2"
LET ifxtype = 1
LET ifxleng = 2
WHEN "INT4"
LET ifxtype = 2
LET ifxleng = 4
WHEN "DATE"
LET ifxtype = 7
LET ifxleng = 4
WHEN "TIME"
LET ifxtype = 10
LET ifxleng = 1642
WHEN "TIMESTAMP"
LET ifxtype = 10
LET ifxleng = 4879
WHEN "BIGINT"
LET ifxtype = 5
LET ifxleng = 19 * 256
WHEN "INT8"
LET ifxtype = 5
LET ifxleng = 19 * 256
END CASE
IF ifxtype>-1 AND pgsnull="t" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_pgs(p)
DEFINE p STRING
DEFINE s STRING
LET s = " "
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(",p,".RELNAME) = '",UPSHIFT(params.tabname),"'"
END IF
IF params.systabs=="N" THEN
LET s = s, " AND ",p,".RELNAMESPACE IN ",
" (SELECT OID FROM PG_NAMESPACE ",
" WHERE NSPNAME NOT LIKE 'pg%' ",
" AND NSPNAME <> 'information_schema')"
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND UPPER(PG_GET_USERBYID(",p,".RELOWNER))='",UPSHIFT(params.dbowner),"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_pgs_start()
DEFINE stmt STRING
LET stmt = "SELECT",
" C.OID,",
" C.RELNAME,",
" A.ATTNAME,",
" T.TYPNAME,",
" A.ATTLEN,",
" A.ATTTYPMOD,",
" A.ATTNOTNULL,",
" A.ATTNUM",
" FROM PG_CLASS C, PG_ATTRIBUTE A, PG_TYPE T",
" WHERE A.ATTRELID = C.OID",
" AND A.ATTTYPID = T.OID",
" AND ((C.RELKIND='r') OR (C.RELKIND='s') OR (C.RELKIND='v'))",
" AND (A.ATTNUM>0)",
_fgldbsch_get_selection_filter_pgs("C"),
" ORDER BY C.RELNAME, A.ATTNUM"
WHENEVER ERROR CONTINUE
DECLARE ctc_pgs CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_pgs
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_pgs_next()
DEFINE tabid INTEGER
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE coltplen INTEGER
DEFINE coltpmod INTEGER
DEFINE colnullc CHAR(1)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_pgs INTO
tabid,
tabname,
colname,
coltype,
coltplen,
coltpmod,
colnullc,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_pgs
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_pgs(
coltype,
coltplen,
coltpmod,
colnullc
) RETURNING
nattype,
ifxtype,
ifxleng
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_convert_datatype_mys( coltype, colcharl, coltpprc, coltpscl, colnullc, colextra, coltname )
DEFINE coltype VARCHAR(100)
DEFINE colcharl INTEGER
DEFINE coltpprc INTEGER
DEFINE coltpscl INTEGER
DEFINE colnullc VARCHAR(10)
DEFINE colextra VARCHAR(20)
DEFINE coltname VARCHAR(100)
DEFINE qual1 INTEGER
DEFINE qual2 INTEGER
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
LET ifxtype = -1
CASE
WHEN coltype == "CHAR"
LET ifxtype = 0
LET ifxleng = colcharl
WHEN coltype == "VARCHAR"
LET ifxtype = 201
LET ifxleng = colcharl
WHEN coltype == "DECIMAL"
LET ifxtype = 5
LET ifxleng = coltpprc * 256 + coltpscl
WHEN coltype == "FLOAT"
LET ifxtype = 4
LET ifxleng = 4
WHEN coltype == "DOUBLE"
LET ifxtype = 3
LET ifxleng = 8
WHEN coltype == "TINYINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN coltype == "SMALLINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN coltype == "MEDIUMINT"
OR coltype == "INT"
IF colextra == "auto_increment" THEN
LET ifxtype = 6
ELSE
LET ifxtype = 2
END IF
LET ifxleng = 4
WHEN coltype == "BIGINT"
LET ifxtype = 5
LET ifxleng = 19 * 256
WHEN coltype == "DATE"
LET ifxtype = 7
LET ifxleng = 4
WHEN coltype == "TIME"
LET ifxtype = 10
LET ifxleng = 1642
WHEN coltype == "DATETIME"
LET ifxtype = 10
LET ifxleng = 3594
WHEN coltype == "TIMESTAMP"
LET ifxtype = 10
LET ifxleng = 3594
WHEN coltype == "ENUM"
CASE params.cvmeth[15,15]
WHEN "A"
LET ifxtype = 201
LET ifxleng = 255
WHEN "B"
LET ifxtype = 201
LET ifxleng = 1024
END CASE
WHEN coltype == "TINYTEXT" -- 256c (2^8)
CASE params.cvmeth[16,16]
WHEN "A"
LET ifxtype = 201
LET ifxleng = 255
WHEN "B"
LET ifxtype = 12
LET ifxleng = 56
END CASE
WHEN coltype == "TEXT" -- 65536c (2^16)
CASE params.cvmeth[17,17]
WHEN "A"
LET ifxtype = 201
LET ifxleng = 65535
WHEN "B"
LET ifxtype = 12
LET ifxleng = 56
END CASE
WHEN coltype == "MEDIUMTEXT" -- 16777216c (2^24)
LET ifxtype = 12
LET ifxleng = 56
WHEN coltype == "LONGTEXT" -- 4294967296c (2^32)
LET ifxtype = 12
LET ifxleng = 56
WHEN coltype == "TINYBLOB"
OR coltype == "BLOB"
OR coltype == "MEDIUMBLOB"
OR coltype == "LONGBLOB"
OR coltype == "BINARY"
OR coltype == "VARBINARY"
LET ifxtype = 11
LET ifxleng = 56
WHEN coltype == "YEAR"
CASE params.cvmeth[26,26]
WHEN "A"
LET ifxtype = 10 -- DATETIME
LET ifxleng = 1024 -- YEAR TO YEAR
WHEN "B"
LET ifxtype = 1
LET ifxleng = 2
END CASE
WHEN coltype == "BIT"
LET ifxtype = 1
LET ifxleng = 2
END CASE
IF ifxtype>-1 AND colnullc = "NO" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN coltname, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_mys()
DEFINE s STRING
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(T.TABLE_NAME) = '",UPSHIFT(params.tabname),"'"
END IF
# Warning:
# In MySQL (6.0.4), TABLE_CATALOG is NULL: TABLE_SCHEMA is the DB name!!!
# => We must use TABLE_SCHEMA = DBNAME, and no way to filter by dbowner.
IF params.systabs=="N" THEN
LET s = s, " AND T.TABLE_SCHEMA=DATABASE()"
ELSE
LET s = s, " AND (T.TABLE_SCHEMA=DATABASE() OR T.TABLE_SCHEMA='mysql')"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_mys_start()
DEFINE stmt STRING
LET stmt = "SELECT",
" C.TABLE_NAME,",
" C.COLUMN_NAME,",
" UPPER(C.DATA_TYPE),",
" C.CHARACTER_OCTET_LENGTH,",
" C.NUMERIC_PRECISION,",
" C.NUMERIC_SCALE,",
" C.IS_NULLABLE,",
" C.EXTRA,",
-- COLUMN_TYPE is complete type name, must use substring() to not get CLOB!
" SUBSTRING(C.COLUMN_TYPE,1,100),",
" C.ORDINAL_POSITION",
" FROM INFORMATION_SCHEMA.COLUMNS C, INFORMATION_SCHEMA.TABLES T",
" WHERE T.TABLE_SCHEMA = C.TABLE_SCHEMA",
" AND T.TABLE_NAME = C.TABLE_NAME",
" AND T.TABLE_TYPE IN ( 'BASE TABLE', 'VIEW' )",
_fgldbsch_get_selection_filter_mys(),
" ORDER BY C.TABLE_NAME, C.ORDINAL_POSITION"
WHENEVER ERROR CONTINUE
DECLARE ctc_mys CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_mys
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_mys_next()
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE colcharl INTEGER
DEFINE coltpprc INTEGER
DEFINE coltpscl INTEGER
DEFINE colnullc VARCHAR(10)
DEFINE colextra VARCHAR(20)
DEFINE coltname VARCHAR(100)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_mys INTO
tabname,
colname,
coltype,
colcharl,
coltpprc,
coltpscl,
colnullc,
colextra,
coltname,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_mys
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_mys(
coltype,
colcharl,
coltpprc,
coltpscl,
colnullc,
colextra,
coltname
) RETURNING
nattype,
ifxtype,
ifxleng
IF ifxtype == -2 THEN
DISPLAY SFMT("Warning: %1 column \"%2.%3\" is ignored.",
nattype CLIPPED, tabname CLIPPED, colname CLIPPED)
CONTINUE WHILE
END IF
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION
#-------------------------------------------------------------------------------
FUNCTION _fgldbsch_ads_encode_datetime(adstype, adsdtpr, adsscal)
DEFINE adstype STRING, adsdtpr, adsscal INTEGER
DEFINE tmp STRING
DEFINE tok base.StringTokenizer
DEFINE q1, q2 STRING
DEFINE vq1, vq2, len, x SMALLINT
DEFINE code INTEGER
LET tmp = adstype.subString(10, adstype.getLength()) -- "DATETIME "
LET tok = base.StringTokenizer.create(tmp," ")
LET q1 = tok.nextToken() -- qualifier 1
IF q1 IS NULL THEN RETURN -1, 0 END IF
LET tmp = tok.nextToken() -- TO
IF tmp IS NULL THEN RETURN -1, 0 END IF
LET q2 = tok.nextToken() -- qualifier 2
IF q2 IS NULL THEN RETURN -1, 0 END IF
LET vq1 = _fgldbsch_dtin_qualcode(q1)
LET x = vq1
IF q2 == "FRACTION" THEN
LET vq2 = 10 + adsscal
IF q1 = "FRACTION" THEN
LET x = 12
END IF
ELSE
LET vq2 = _fgldbsch_dtin_qualcode(q2)
END IF
IF q1 == "YEAR" THEN LET len=4 ELSE LET len=2 END IF
LET code = ((vq2 - x + len) * 256 ) + (vq1 * 16) + vq2
RETURN 10, code
END FUNCTION
FUNCTION _fgldbsch_ads_encode_interval(adstype, adsivpr, adsscal)
DEFINE adstype STRING, adsivpr, adsscal INTEGER
DEFINE tmp STRING
DEFINE tok base.StringTokenizer
DEFINE q1, q2 STRING
DEFINE vq1, vq2, len, x SMALLINT
DEFINE code INTEGER
LET tmp = adstype.subString(10, adstype.getLength()) -- "INTERVAL "
LET tok = base.StringTokenizer.create(tmp," ")
LET q1 = tok.nextToken() -- qualifier 1
IF q1 IS NULL THEN RETURN -1, 0 END IF
LET tmp = tok.nextToken() -- TO
IF tmp IS NULL THEN RETURN -1, 0 END IF
LET q2 = tok.nextToken() -- qualifier 2
IF q2 IS NULL THEN RETURN -1, 0 END IF
LET vq1 = _fgldbsch_dtin_qualcode(q1)
LET x = vq1
IF q2 == "FRACTION" THEN
LET vq2 = 10 + adsscal
IF q1 = "FRACTION" THEN
LET x = 10 + adsivpr
END IF
ELSE
LET vq2 = _fgldbsch_dtin_qualcode(q2)
END IF
LET len = (vq2 - x + adsivpr)
LET code = (len * 256 ) + (vq1 * 16) + vq2
RETURN 14, code
END FUNCTION
FUNCTION _fgldbsch_convert_datatype_ads( adstype, adssize, adsprec, adsscal, adsdtpr, adsivpr, adsnull )
DEFINE adstype VARCHAR(100)
DEFINE adssize INTEGER
DEFINE adsprec INTEGER
DEFINE adsscal INTEGER
DEFINE adsdtpr INTEGER
DEFINE adsivpr INTEGER
DEFINE adsnull CHAR(3)
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
LET ifxtype = -1
-- ADS 3.61
CASE adsnull
WHEN '1' LET adsnull = 'YES'
WHEN '0' LET adsnull = 'NO'
END CASE
LET nattype = adstype
CASE
WHEN adstype == "MONEY"
OR adstype == "NUMERIC"
OR adstype == "DECIMAL"
LET ifxtype = 5
IF adstype == "MONEY" THEN
LET ifxtype = 8
END IF
LET ifxleng = adsprec * 256 + adsscal
CASE
WHEN adsprec IS NOT NULL AND adsscal IS NOT NULL
LET nattype = SFMT("%1(%2,%3)", adstype, adsprec, adsscal)
WHEN adsprec IS NOT NULL AND adsscal IS NOT NULL
LET nattype = SFMT("%1(%2)", adstype, adsprec)
OTHERWISE
LET nattype = adstype
END CASE
WHEN adstype == "CHAR"
LET ifxtype = 0
LET ifxleng = adssize
LET nattype = SFMT("%1(%2)", adstype, adssize)
WHEN adstype == "VARCHAR"
OR adstype == "VARCHAR2"
LET ifxtype = 201
LET ifxleng = adssize
LET nattype = SFMT("%1(%2)", adstype, adssize)
WHEN adstype == "NCHAR"
LET ifxtype = 15
LET ifxleng = adssize
LET nattype = SFMT("%1(%2)", adstype, adssize)
WHEN adstype == "NVARCHAR"
OR adstype == "NVARCHAR2"
LET ifxtype = 202
LET ifxleng = adssize
LET nattype = SFMT("%1(%2)", adstype, adssize)
WHEN adstype == "DATE"
LET ifxtype = 7
LET ifxleng = 4
WHEN adstype == "TIME"
LET ifxtype = 10
LET ifxleng = 1642
WHEN adstype == "TIMESTAMP"
OR adstype == "DATETIME"
LET ifxtype = 10
LET ifxleng = 4365
WHEN adstype == "BIGINT"
LET ifxtype = 5
LET ifxleng = 19 * 256
WHEN adstype == "TINYINT"
OR adstype == "SMALLINT"
LET ifxtype = 1
LET ifxleng = 2
WHEN adstype == "INTEGER"
LET ifxtype = 2
LET ifxleng = 4
WHEN adstype == "SERIAL"
LET ifxtype = 6
LET ifxleng = 4
WHEN adstype == "DOUBLE"
OR adstype == "REAL"
OR adstype == "SMALLFLOAT"
LET ifxtype = 4
LET ifxleng = 4
WHEN adstype == "FLOAT"
OR adstype == "DOUBLE PRECISION"
LET ifxtype = 3
LET ifxleng = 8
WHEN adstype = "BINARY"
OR adstype = "VARBINARY"
OR adstype = "LONGVARBINARY"
OR adstype = "BYTE"
LET ifxtype = 11
LET ifxleng = 56
WHEN adstype = "LONGVARCHAR"
OR adstype = "TEXT"
LET ifxtype = 12
LET ifxleng = 56
WHEN adstype MATCHES "DATETIME *"
CALL _fgldbsch_ads_encode_datetime(adstype, adsdtpr, adsscal)
RETURNING ifxtype, ifxleng
WHEN adstype MATCHES "INTERVAL *"
CALL _fgldbsch_ads_encode_interval(adstype, adsivpr, adsscal)
RETURNING ifxtype, ifxleng
END CASE
IF ifxtype>-1 AND adsnull=="NO" THEN
LET ifxtype = ifxtype + 256
END IF
RETURN nattype, ifxtype, ifxleng
END FUNCTION
FUNCTION _fgldbsch_get_selection_filter_ads(t,c)
DEFINE t,c STRING
DEFINE s STRING
LET s = " "
IF params.tabname IS NOT NULL THEN
LET s = s, " AND UPPER(",t,") = '",UPSHIFT(params.tabname),"'"
END IF
IF params.systabs=="N" THEN
LET s = s, " AND ", c, " != 'SYSTEM'"
END IF
IF params.dbowner IS NULL THEN
CALL _fgldbsch_owner_warning()
LET params.dbowner = params.username
END IF
IF params.dbowner IS NOT NULL THEN
LET s = s, " AND UPPER(",c,")='",UPSHIFT(params.dbowner),"'"
END IF
RETURN s
END FUNCTION
FUNCTION _fgldbsch_extract_ads_start()
DEFINE stmt STRING
DEFINE dum CHAR(100)
WHENEVER ERROR CONTINUE
SELECT ORIGINAL_TYPE_NAME INTO dum FROM SYSTEM.TABLE_OF_COLUMNS WHERE 1=0
WHENEVER ERROR STOP
IF sqlca.sqlcode == 100 THEN
-- Since ADS 3.80 only!
LET stmt = "SELECT",
" TABLE_NAME,",
" COLUMN_NAME,",
" ORIGINAL_TYPE_NAME,",
" CHARACTER_MAXIMUM_LENGTH,",
" NUMERIC_PRECISION,",
" NUMERIC_SCALE,",
" DATETIME_PRECISION,",
" INTERVAL_PRECISION,",
" IS_NULLABLE,",
" ORDINAL_POSITION",
" FROM INFORMATION_SCHEMA.COLUMNS",
" WHERE COLUMN_NAME NOT LIKE '$%'",
_fgldbsch_get_selection_filter_ads("TABLE_NAME","TABLE_SCHEMA"),
" ORDER BY TABLE_NAME, ORDINAL_POSITION"
ELSE
LET stmt = "SELECT",
" TABLE_NAME,",
" COLUMN_NAME,",
" TYPE_NAME,",
" COLUMN_SIZE,",
" COLUMN_SIZE,",
" DECIMAL_DIGITS,",
" -1,",
" -1,",
" NULLABLE,",
" ORDINAL_POSITION",
" FROM SYSTEM.TABLE_OF_COLUMNS",
" WHERE COLUMN_NAME NOT LIKE '$%'",
_fgldbsch_get_selection_filter_ads("TABLE_NAME","TABLE_SCHEM"),
" ORDER BY TABLE_NAME, ORDINAL_POSITION"
END IF
WHENEVER ERROR CONTINUE
DECLARE ctc_ads CURSOR FROM stmt
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
OPEN ctc_ads
IF SQLCA.SQLCODE<0 THEN RETURN SQLCA.SQLCODE END IF
WHENEVER ERROR STOP
RETURN 0
END FUNCTION
FUNCTION _fgldbsch_extract_ads_next()
DEFINE tabname VARCHAR(200)
DEFINE colname VARCHAR(200)
DEFINE coltype VARCHAR(100)
DEFINE colchsze INTEGER
DEFINE colnmpre INTEGER
DEFINE colnmscl INTEGER
DEFINE coldtpre INTEGER
DEFINE colivpre INTEGER
DEFINE colnullc CHAR(3)
DEFINE colident INTEGER
DEFINE nattype STRING
DEFINE ifxtype INTEGER
DEFINE ifxleng INTEGER
WHILE TRUE
WHENEVER ERROR CONTINUE
FETCH ctc_ads INTO
tabname,
colname,
coltype,
colchsze,
colnmpre,
colnmscl,
coldtpre,
colivpre,
colnullc,
colident
WHENEVER ERROR STOP
IF SQLCA.SQLCODE < 0 THEN RETURN SQLCA.SQLCODE END IF
IF SQLCA.SQLCODE == NOTFOUND THEN
CLOSE ctc_ads
RETURN ( coldef.getLength() > 0 )
END IF
CALL _fgldbsch_convert_datatype_ads(
coltype,
colchsze,
colnmpre,
colnmscl,
coldtpre,
colivpre,
colnullc
) RETURNING
nattype,
ifxtype,
ifxleng
IF _fgldbsch_register_column(tabname, colname, nattype, ifxtype, ifxleng) THEN
EXIT WHILE
END IF
END WHILE
RETURN 1
END FUNCTION