Skip to content

Appendix B. Porting Pro*C Applications to APRE#

Refer to this appendix when converting an application that was written using Oracle Pro*C/C++ so that it can be compiled using the Altibase C/C++ Precompiler.

Datatypes#

This section describes the Oracle data types and the corresponding data types of Altibase.

ODBC SQL data type Oracle Altibase Remarks
SQL_CHAR CHAR CHAR 1-32000 length
SQL_TIMESTAMP DATE DATE
SQL_LONGVARCHAR LONG BLOB Up to 2147483647bytes
SQL_INTEGER INT INTEGER
SQL_FLOAT NUMBER NUMBER
SQL_DECIMAL NUMBER(P) NUMBER(P) 1-38
SQL_DECIMAL NUMBER(P,S) NUMBER(P,S) precision : 1-38 scale : -84 - 126
SQL_BINARY RAW HSS_BYTES 1-32000
SQL_VARCHAR VARCHAR VARCHAR max 32000 bytes
SQL_VARCHAR VARCHAR2 VARCHAR max 32000 bytes

Embedded Functions#

Like Oracle, Altibase provides numeric functions, date functions, string functions, data type conversion functions, and other built-in functions. This section explains which Altibase functions should be used in place of corresponding Oracle functions.

The name, purpose, and method of use of each built-in function of Altibase is similar to its counterpart in Oracle.

The following built-in functions are supported in Altibase:

  • Numeric Functions:
    ABS, ACOS, ASIN, ATAN, ATAN2, CEIL, COS, COSH, EXP, FLOOR, ISNUMERIC, LN, LOG, MOD, POWER, RANDOM, ROUND, SIGN, SIN, SINH, SQRT, TAN, TANH, TRUNC, BITTAND, BITOR, BITXOR, BITNOT
  • Aggregate Functions:
    AVG, COUNT, GROUP_CONCAT, LISTAGG, MAX, MIN, PERCENTILE_CONT, PERCENTILE_DISC, STATS_ONE_WAY_ANOVA, STDDEV, STDDEV_POP, STDDEV_SAMP, SUM, VARIANCE, VAR_POP, VAR_SAMP
  • Character Functions:
    ASCII, CHAR_LENGTH, CHOSUNG, CHR, CONCAT, DIGITS, INITCAP, INSTR, INSTRB, POSITION, LOWER, LPAD, LTRIM, NCHR, OCTET_LENGTH, PKCS7PAD16, PKCS7UNPAD16, RANDOM_STRING, REGEXP_COUNT, REGEXP_INSTR, REGEXP_SUBSTR, REPLACE2, REVERSE_STR, RPAD, RTRIM, SIZEOF, SUBSTR, TRANSLATE, TRIM, UPPER, REPLICATE, REVERSE_STR, STUFF, UPPER
  • Date/time Functions:
    ADD_MONTHS, CURRENT_DATE, CURRENT_TIMESTAMP, CONV_TIMEZONE, DATEADD, DATEDIFF, DATENAME, DB_TIMEZONE, EXTRACT, LAST_DAY, MONTHS_BETWEEN, ROUND, NEXT_DAY, SESSION_TIMEZONE, SYSDATE, SYSTIMESTAMP, TRUNC, UNIX_DATE, UNIX_TIMESTAMP
  • Data Type Conversion Functions:
    ASCIISTR, BIN_TO_NUM, CONVERT, DATE_TO_UNIX, HEX_ENCODE, HEX_DECODE, HEX_TO_NUM, OCT_TO_NUM, TO_BIN, TO_CHAR, TO_DATE, TO_HEX, TO_NCHAR, TO_NUMBER, TO_OCT, TO_RAW, UNISTR, UNIX_TO_DATE
  • Encryption Functions:
    AESDECRYPT, AESENCRYPT, DESENCRYPT, DESDECRYPT, TDESDECRYPT/TRIPLE_DESDECRYPT,TDESENCRYPT/TRIPLE_DESENCRYPT
  • Window Functions: AVG, COUNT, LISTAGG, MAX, MIN, PERCENTILE_CONT, AVG, COUNT, LISTAGG, MAX, MIN, PERCENTILE_CONT, PERCENTILE_DISC, STDDEV, SUM, VARIANCE, GROUP_CONCAT, RANK, DENSE_RANK, ROW_NUMBER, LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE
  • Miscellaneous Functions:
    BINARY_LENGTH, CASE2, CASE_WHEN, COALESCE, DECODE, DIGEST, DUMP, GREATEST, GROUPING, GROUPING_ID, HOST_NAME, LEAST, LNNVL, NULLIF, NVL, NVL2, RAW_SIZEOF, RAW_CONCAT, ROWNUM, NVL, NVL2, SENDMSG, SUBRAW, SYS_CONNECT_BY_PATH, USER_ID, USER_NAME, SESSION_ID

For more information, please refer to the SQL Reference.

Managing Database Connections#

This chapter describes the differences in the database connection and disconnection methods between Oracle and Altibase.

Connecting to a Database#

The command that is used to establish a default connection is the same in Oracle and Altibase. Oracle and Altibase are also similar in that multiple connections can be established if names are assigned to individual connections, and in that connection options can be set using the USING clause.

Connect Statement#

  • Oracle

    EXEC SQL CONNECT {:user IDENTIFIED BY :oldpswd :usr_psw } 
    [[ AT { dbname | :host_variable }] USING :connect_string ];
    
  • Altibase

     EXEC SQL [AT {conn_name | :conn_name}] 
    CONNECT <:user> IDENTIFIED BY <:passwd>
     [USING <:conn_opt>[,<:conn_opt2>]];
    

Establishing the Default Connection#

  • Oracle

    char *username = "SCOTT";
    char *password = "TIGER";
    char *connstr = "ORA817";
    EXEC SQL WHENEVER SQLERROR
    .
    .
    .
    EXEC SQL CONNECT :username IDENTIFIED BY :password 
    USING :connstr;
    
  • Altibase

    strcpy(username, "SYS");
    strcpy(password, "MANAGER");
    strcpy(connstr,"DSN=192.168.1.2;PORTNO=20310;CONNTYPE=3");
    EXEC SQL CONNECT :username IDENTIFIED BY :password 
    USING :connstr;
    
  • If the USING clause is not specified, the application will attempt to connect to an Altibase database on the same system.

Establishing a Named Connection#

  • Oracle

    char *username = "SCOTT";
    char *password = "TIGER";
    char *connstr = "ORA817";
    EXEC SQL WHENEVER SQLERROR 
    .
    .
    .
    EXEC SQL CONNECT :username IDENTIFIED BY :password
    AT :db_name USING :connstr;
    
  • Altibase

    strcpy(user2, "ALTIBASE");
    strcpy(passwd2, "ALTIBASE");
    strcpy(conn_name, "CONN2");
    strcpy(connstr,"DSN=192.168.1.12;PORTNO=20310;CONNTYPE=1");
    EXEC SQL AT :conn_name CONNECT :user2 IDENTIFIED BY :passwd2
    USING :connstr;
    

Disconnecting from a Database#

In Oracle, the EXEC SQL ROLLBACK WORK RELEASE statement is used to roll back any pending transactions and disconnect from the database in a single line of code.

This statement is also supported in Altibase.

Disconnect Statement#

  • Oracle

    EXEC SQL COMMIT WORK RELEASE;
    
    or
    EXEC SQL ROLLBACK  WORK RELEASE;
    

  • Altibase

    EXEC SQL COMMIT WORK RELEASE;
    
    or
    EXEC SQL ROLLBACK  WORK RELEASE;
    

Host Variables#

This section describes the differences between the host variables used with Oracle Pro*C and those used with the Altibase C/C++ Precompiler.

Host Variable Compatibility#

Oracle Altibase Remarks
Database Column type Host Variable C type Database Column type Host Variable C type
CHAR char CHAR char/char[2] single character
VARCHAR2(X) VARCHAR(X) VARCHAR[X] VARCHAR VARCHAR n-byte variable-length character array
CHAR[X] char[x] CHAR[X] char[x] n-byte character array
NUMBER int NUMBER/ INTEGER int/ APRE _INT integer
NUMBER(P,S) short int long float double NUMBER(P,S) short int/APRE_INTEGER long float double small integer integer large integer float-point number double-precision floating-point number
DATE char[n] varchar[n] DATE char[n] varchar[n] n >= 20

Host Variable Declaration Section#

The statements used to delimit the host variable declaration section are the same in Altibase and Oracle.

  • Oracle

    EXEC SQL BEGIN DECLARE SECTION;
    /* Host variable declaration */
    EXEC SQL END DECLARE SECTION;
    
  • Altibase

    EXEC SQL BEGIN DECLARE SECTION;
    /* Host variable declaration */
    EXEC SQL END DECLARE SECTION;
    

Using Embedded SQL Statements#

This section compares the use of basic SQL statements (SELECT, UPDATE, INSERT, DELETE), cursor control SQL statements and dynamic SQL statements in Oracle Pro*C and the Altibase C/C++ Precompiler

Basic DML Statements#

Basic DML statements, for example the SELECT, INSERT, UPDATE, and DELETE statements, are executed the same way (i.e. using EXEC SQL) in both Oracle and Altibase.

Cursor Control SQL Statements#

The fundamental method of declaring cursors is the same in Oracle and Altibase. They only differ in that Oracle supports the declaration of cursor variables in the host variable declaration section, just like host variables, whereas Altibase does not.

Cursor Declaration#

  • Oracle

    EXEC SQL DECLARE cur_emp CURSOR FOR 
    SELECT ename, job, sal 
    FROM emp;
    
  • Altibase

    EXEC SQL DECLARE cur_emp CURSOR FOR
    SELECT ename, job, sal 
    FROM emp;
    

Cursor Open and Fetch#

The methods used to open cursors and fetch records are the same in Altibase and Oracle.

However, the error code types and values differ between the two products, which means that error-handling code written inside the FETCH statement will need to be changed. The support for the use of the WHENEVER statement to handle runtime errors (e.g. EXEC SQL WHENEVER NOT FOUND DO BREAK;) is the same in Altibase as it is in Oracle.

  • Oracle

    EXEC SQL OPEN cur_emp;
    if(sqlca.sqlcode != SQL_OK ) {
    fprintf(stderr, "OPEN CSR ERROR%d\n",sqlca.sqlcode);
       close_db();
       exit(0);
    }
    for(;;)
    {
    EXEC SQL FETCH cur_emp 
     INTO :emp_name, :job_title, :salary;    
       switch(sqlca.sqlcode)
       {
            case 0:
                    printf("emp_name : %s\n", emp_name);
                    continue;
            case 1403:      /* Not Found Data */
                    break;
            default :
                    fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
                    close_db();
                    exit(0);
       }
    }
    
  • Altibase

    EXEC SQL OPEN cur_emp;
    if(sqlca.sqlcode != SQL_SUCCESS ) {
        fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
        close_db();
        exit(0);
    }
    for(;;)
    {
        EXEC SQL  FETCH  cur_emp INTO :emp_name, :job_title, :salary;    
        switch(sqlca.sqlcode)
        {
            case SQL_SUCCESS:
                    printf("emp_name : %s\n", emp_name);
                    continue;
            case SQL_NO_DATA:      /* Not Found Data */
                    break;
            default :
                    fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
                    close_db();
                    exit(0);
        }
    }
    

Closing Cursors#

The use of the CLOSE statement to close a cursor is the same in both Oracle Pro*C and APRE.

  • Oracle

    EXEC SQL CLOSE cur_emp;
    
  • Altibase

    EXEC SQL CLOSE cur_emp;
    

Dynamic SQL Statements#

Altibase supports Oracle Dynamic SQL Methods 1, 2, 3, and 4.

In Oracle, both the syntax ":v[1...n]" and the question mark ("?") can be used as parameter markers within embedded SQL statements. Altibase only supports the use of the question mark ("?").

Method 1#

  • Oracle

    char dynstmt1[80];    
    strcpy(dynstmt1, "DROP TABLE EMP" );
    EXEC SQL EXECUTE IMMEDIATE :dynstmt1;
    
  • Altibase

    EXEC SQL BEGIN DECLARE SECTION;
    char dynstmt1[80];
    EXEC SQL END DECLARE SECTION;    
    strcpy(dynstmt1, "DROP TABLE EMP" );
    EXEC SQL EXECUTE IMMEDIATE :dynstmt1;
    

Method 2#

  • Oralce

    int emp_number;
    char delete_stmt[120];
    .
    .
    .
    strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = :v1");
    EXEC SQL PREPARE sql_stmt FROM :delete_stmt;
    emp_number = 10;
    EXEC SQL EXECUTE sql_stmt USING :emp_number;
    
  • Altibase

    EXEC SQL BEGIN DECLARE SECTION;
    int emp_number;
    char delete_stmt[120];
    EXEC SQL END DECLARE SECTION;
    .
    .
    .
    strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = ?");
    
    EXEC SQL PREPARE sql_stmt FROM :delete_stmt;
    emp_number = 10;
    
    EXEC SQL EXECUTE sql_stmt USING :emp_number;
    

Method 3#

  • Oracle

    char sql_query[80];
    int  deptno = 10;
    char ename[10];
    strcpy(sql_query,"SELECT ename FROM emp WHERE deptno > :v1");
    EXEC SQL PREPARE S FROM : sql_query;
    EXEC SQL DECLARE C CURSOR FOR S;
    EXEC SQL OPEN C USING :deptno;
    for (;;)
    {
        EXEC SQL FETCH C INTO :ename;
        .
        .
        .
    }
    
  • Altibase

    EXEC SQL BEGIN DECLARE SECTION;
    char sql_query[80];
    int  deptno = 10;
    char ename[10];
    EXEC SQL END DECLARE SECTION;
    strcpy(sql_query,"SELECT ename FROM emp WHERE deptno > ? ");
    EXEC SQL PREPARE S FROM : sql_query;
    EXEC SQL DECLARE C CURSOR FOR S;
    EXEC SQL OPEN C USING :deptno;
    for (;;)
    {
        EXEC SQL FETCH C INTO :ename;
        .
        .
        .
    }
    

Method 4#

  • Oracle

    #define MAX_COLUMN_SIZE 30
    
    char name[10];
    int number;
    
    short ind_number;
    
    char *sql_stmt = "INSERT INTO emp (empno, ename) VALUES(:e, :n);
    SQLDA *binda;
    .
    .
    .
    binda = SQLSQLDAAlloc(SQL_SINGLE_RCTX, MAX_COLUMN_SIZE, 10, 10);
    binda->N = MAX_COLUMN_SIZE;
    
    EXEC SQL PREPARE stmt FROM :sql_stmt;
    EXEC SQL DESCRIBE BIND VARIABLES FOR stmt INTO binda;
    binda->N = binda->F;
    
    binda->V[0] = (char*)&number;
    binda->L[0] = (long)sizeof(int);
    binda->T[0] = 3;
    binda->I[0] = &ind_number;
    
    binda->V[1] = (char*) name;
    binda->L[1] = (long) 10;
    binda->T[1] = 1;
    binda->I[1] = (short*)0;
    .
    .
    .
    number = 1024;
    strcpy(name, "ALLISON");
    ind_number = 0;
    
    EXECUTE stmt USING DESCRIPTOR binda;
    
  • Altibase

    #define MAX_COLUMN_SIZE 30
    
    EXEC SQL BEGIN DECLARE SECTION;
    char *sql_stmt = "INSERT INTO emp VALUES(?,?)";
    SQLDA *binda;
    EXEC SQL END DECLARE SECTION;
    
    int number;
    char name[10];
    
    short ind_name;
    
    binda = (SQLDA*) SQLSQLDAAlloc( MAX_COLUMN_SIZE );
    
    EXEC SQL PREPARE stmt FROM :sql_stmt;
    
    EXEC SQL DESCRIBE BIND VARIABLES FOR stmt INTO :binda;
    binda->N = binda->F;
    
    binda->V[0] = (char*)&number;
    binda->L[0] = sizeof(int);
    bidna->T[0] = SQLDA_TYPE_SINT;
    binda->I[0] = NULL;
    
    binda->V[1] = (char*)name;
    binda->L[1] = 10;
    binda->T[1] = SQLDA_TYPE_CHAR;
    binda->I[1] = (short*)&ind_name;
    
    number = 1024;
    strcpy(name, "ALLISON");
    ind_name = strlen(name);
    
    EXEC SQL EXECUTE stmt USING DESCRIPTOR :binda;
    

Execution Results and Status Codes#

This section will explain the differences between Oracle and Altibase in the use of the SQLSTATE, SQLCODE and SQLCA variables to handle runtime errors.

SQLCA#

SQLCA is a structure in which information about the results of execution of embedded SQL statements is saved. In Altibase, the supported elements of the structure are sqlcode, sqlerrm.sqlerrmc, sqlerrm.sqlerrml, sqlerrd[2] and sqlerrd[3]. Other SQLCA elements, such as sqlwarn, are implemented only in the Oracle SQLCA structure, and are not supported for use in Altibase.

SQLCA Declaration#

  • Oracle

    EXEC SQL INCLUDE SQLCA;
    
    or
    #include <sqlca.h>
    

  • Altibase
    In APRE, this structure is defined by default, and does not have to be explicitly declared.

sqlca.sqlcode Status#

  • Oracle

    Status Code Description
    0 Success
    >0 No rows returned
    <0 database, system, network , application error
  • Altibase

    Status Code Description
    SQL_SUCCESS Success
    SQL_SUCCESS_WITH_INFO
    SQL_NO_DATA No rows returned
    SQL_ERROR
    SQL_INVALID_HANDLE

sqlca.sqlerrm#

sqlerrmc and sqlerrml are implemented identically in Oracle and Altibase.

sqlca.sqlerrd[2]#

  • Oracle
    This element indicates the number of records that were affected by an INSERT, UPDATE, DELETE, or SELECT INTO operation. This number is cumulative.

  • Altibase
    Unlike Oracle, in Altibase the number stored in this element is not cumulative. When an INSERT, UPDATE, or DELETE operation is performed, this element indicates the number of records that were affected. When a SELECT or FETCH statement is executed using an array-type output host variable, this element indicates the number of records that were returned.

SQLSTATE#

SQLSTATE is used to store a status code, which is used to determine the kind of error or exception that has occurred.

Declaration and Use of SQLSTATE#

  • Oracle
    In Oracle, SQLSTATE must be declared and the MODE=ANSI precompiler option must be specified when precompiling.

    char SQLSTATE[6];
    
  • Altibase
    Can be used without declaration.

SQLSTATE Status Codes#

The values of the SQLSTATE status codes and their meanings in Oracle differ from the ODBC standard. Therefore, it will be necessary to appropriately convert SQLSTATE status codes to the ODBC equivalents with reference to Chapter 7: Status Codes and the ODBC code table.

SQLCODE#

SQLCODE is used to store error codes after the execution of an embedded SQL statement.

Declaring and Using SQLCODE#

  • Oracle
    In Oracle, SQLCODE must be declared and the MODE=ANSI precompiler option must be specified when precompiling.

    long SQLCODE;
    
  • Altibase
    Can be used without declaration

SQLCODE Status Code Values#

  • Oracle
    The SQLCODE status codes are the same as for sqlca.sqlcode.

  • Altibase

    Status Code Description
    0 Upon successful execution of the embedded SQL statement, that is, when the value of sqlca.sqlcode is SQL_SUCCESS
    1 When the embedded SQL statement is executed successfully but a warning is detected, at which time the value of sqlca.sqlcode is SQL_SUCCESS_WITH_INFO
    100 hen no records were returned as the result of execution of a SELECT or FETCH statement, that is, when the value of sqlca.sqlcode is SQL_NO_DATA
    -1 When an error occurred during the execution of an embedded SQL statement, but there is no error code corresponding to the error. At this time, the value of sqlca.sqlcode is SQL_ERROR.
    -2 WWhen an attempt was made to execute an embedded SQL statement without first establishing a database connection, that is, when the value of sqlca.sqlcode is SQL_INVALID_HANDLE
    • The presence of any value other than the values listed above in SQLCODE is an error message indicating the occurrence of an error in the corresponding SQL statement.

Commit Mode#

This section explains the differences between Altibase and Oracle related to the commit mode, including the default commit mode, how to change the commit mode, and how to commit transactions.

Default Commit Mode#

Oracle Altibase
Non-Autocommit mode Autocommit mode

Changing the Commit Mode#

  • Oracle

    EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE
    
    or
    EXEC SQL ALTER SESSION SET AUTOCOMMIT = FALSE
    

  • Altibase

    EXEC SQL AUTOCOMMIT ON
    
    or
    EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE
    
    or
    EXEC SQL ALTER SESSION SET AUTOCOMMIT = FALSE
    

Explicit Commit#

  • Oracle

    EXEC SQL COMMIT;
    
    or
    EXEC SQL COMMIT WORK;
    

  • Altibase

    EXEC SQL COMMIT;
    

Sample Programs#

The following sample source code contains examples of the points described above.

Oracle#

#include <stdio.h>
#include <stdlib.h>

EXEC SQL include sqlca.h;

EXEC SQL BEGIN DECLARE SECTION;
char    emp_name[21];
char    job_title[21];
int     salary;
int     emp_number;
EXEC SQL END DECLARE SECTION;

char uid[10] = "SCOTT";
char pwd[10] = "TIGER";

int main(void)
{
  int  dynamic_emp_number;
  char dynamic_stmt[120];

  EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
  if ( sqlca.sqlcode != 0 ) {
       fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  /* INSERT */
  /* value setting */
  emp_number = 10;
  strcpy(emp_name,  "oracle1");
  strcpy(job_title, "oracle dba1");
  salary    = 10000;

  /* INSERT  DML */
  EXEC SQL INSERT INTO emp (empno, ename, job, sal) 
                  VALUES (:emp_number, :emp_name, :job_title, :salary);
  if ( sqlca.sqlcode != 0 ) {
       fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  emp_number = 20;
  strcpy(emp_name,  "oracle2");
  strcpy(job_title, "oracle dba2");
  salary    = 10000;

  EXEC SQL INSERT INTO emp (empno, ename, job, sal) 
                  VALUES (:emp_number, :emp_name, :job_title, :salary);

  if ( sqlca.sqlcode != 0 ) {
       fprintf(stderr, "Insert Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  /* SELECT DML */
  emp_number = 10;
  EXEC SQL SELECT ename, job, sal INTO :emp_name, :job_title, :salary
           FROM emp
           WHERE empno = :emp_number;
  if ( sqlca.sqlcode != 0 ) {
       fprintf(stderr, "Select Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }
  printf(" SELECT result : ename=[%s], job=[%s], sal=[%d]\n", 
                            emp_name, job_title, salary);

  /* UPDATE DML */
  emp_number = 10;
  salary     = 2000;  
  EXEC SQL UPDATE emp SET sal = :salary WHERE empno = :emp_number;
  if ( sqlca.sqlcode != 0 ) {
       fprintf(stderr, "Update Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  /* Cursor  Create */
  EXEC SQL DECLARE cur_emp CURSOR FOR
                   SELECT ename, job, sal FROM   emp;

  /* Cursor Open */
  EXEC SQL  OPEN  cur_emp;
  if(sqlca.sqlcode != 0 ) {
       fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
       exit(-1);
  }

  /* Fetch Cursor */ 
  for(;;)
  {
     EXEC SQL  FETCH  cur_emp INTO :emp_name, :job_title, :salary;

     switch(sqlca.sqlcode)
     {
        case 0:
                printf("Fetch Result : emp_name[%s], job[%s], sal=[%d]\n", 
                                        emp_name, job_title, salary );
                continue;
        case 1403:      /* Not Found Data */
                break;
        default :
                fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
                exit(-1);
     }
     break;
   }

  /* Cursor Close */
  EXEC SQL CLOSE cur_emp; 

  /* Dynamic SQL */
  strcpy(dynamic_stmt, "DELETE FROM EMP WHERE EMPNO = :v1");
  EXEC SQL PREPARE sql_stmt FROM :dynamic_stmt;
  dynamic_emp_number = 10;
  EXEC SQL EXECUTE sql_stmt USING :dynamic_emp_number;

  /* Disconnect */
  EXEC SQL COMMIT WORK RELEASE;

  exit(0);
}

Altibase#

#include <stdio.h>
#include <stdlib.h>

EXEC SQL BEGIN DECLARE SECTION;
char    emp_name[21];
char    job_title[21];
int     salary;
int     emp_number;
char    uid[10];
char    pwd[10];
char    dynamic_stmt[120];
int     dynamic_emp_number;
EXEC SQL END DECLARE SECTION;

int main(void)
{
  strcpy(uid, "SYS" );
  strcpy(pwd, "MANAGER");

  EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
  if ( sqlca.sqlcode != SQL_SUCCESS ) {
       fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  /* INSERT */
  /* value setting */
  emp_number = 10;
  strcpy(emp_name,  "altibase1");
  strcpy(job_title, "dba1");
  salary    = 10000;
  /* INSERT  DML */
  EXEC SQL INSERT INTO emp (empno, ename, job, sal) 
                  VALUES (:emp_number, :emp_name, :job_title, :salary);
  if ( sqlca.sqlcode != SQL_SUCCESS ) {
       fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  emp_number = 20;
  strcpy(emp_name,  "altibase2");
  strcpy(job_title, "dba2");
  salary    = 20000;
  EXEC SQL INSERT INTO emp (empno, ename, job, sal) 
                  VALUES (:emp_number, :emp_name, :job_title, :salary);


  /* SELECT DML */
  emp_number = 10;
  EXEC SQL SELECT ename, job, sal INTO :emp_name, :job_title, :salary
           FROM emp
           WHERE empno = :emp_number;
  if ( sqlca.sqlcode != SQL_SUCCESS ) {
       fprintf(stderr, "Select Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }
  printf(" SELECT result : ename=[%s], job=[%s], sal=[%d]\n", 
                            emp_name, job_title, salary);

  /* UPDATE DML */
  emp_number = 10;
  salary     = 2000;  
  EXEC SQL UPDATE emp SET sal = :salary WHERE empno = :emp_number;
  if ( sqlca.sqlcode != SQL_SUCCESS ) {
       fprintf(stderr, "Update Error : [%d]!!!", sqlca.sqlcode);
       exit(-1);
  }

  /* Cursor  Create */
  EXEC SQL DECLARE cur_emp CURSOR FOR
                   SELECT ename, job, sal FROM   emp;

  /* Cursor Open */
  EXEC SQL  OPEN  cur_emp;
  if(sqlca.sqlcode != SQL_SUCCESS ) {
       fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
       exit(-1);
  }

  /* Fetch Cursor */ 
  for(;;)
  {
     EXEC SQL  FETCH  cur_emp INTO :emp_name, :job_title, :salary;

     switch(sqlca.sqlcode)
     {
        case SQL_SUCCESS:
                printf("Fetch Result : emp_name[%s], job[%s], sal=[%d]\n", 
                                        emp_name, job_title, salary );
                continue;
        case SQL_NO_DATA:      /* Not Found Data */
                break;
        default :
                fprintf(stderr, "FETCH CSR ERROR %d %s\n",
                            sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
                exit(-1);
     }
     break;
   }

  /* Cursor Close */
  EXEC SQL CLOSE cur_emp;


  /* Dynamic SQL */
  strcpy(dynamic_stmt, "DELETE FROM EMP WHERE EMPNO = ?");

  EXEC SQL PREPARE sql_stmt FROM :dynamic_stmt;
  dynamic_emp_number = 10;

  EXEC SQL EXECUTE sql_stmt USING :dynamic_emp_number;


  /* Disconnect */
  EXEC SQL DISCONNECT;

exit(0);
}