/******************************************************************************
**
** Source File Name = trigsql.sqc 1.4
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1995, 1999
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**
** PURPOSE : an example of using advanced SQL statements, to show the
** use of TRIGGERs within a database.
** New tables are created for this example.
** (currentquote, quotehistory)
**
** STRUCTURES USED :
** sqlca
** sqlda
**
** APIs USED :
**
** FUNCTIONS DECLARED :
** 'C' COMPILER LIBRARY :
** stdio.h - printf
** string.h - strncpy
**
** OTHER :
** external : [in the file util.c]
** check_error : Checks for SQLCODE error, and prints out any
** related information available.
**
** EXTERNAL DEPENDANCIES :
** - Ensure existence of database for precompile purposes.
** - Precompile with the SQL precompiler (PREP in DB2)
** - Bind to a database (BIND in DB2)
** - Compile and link with the IBM Cset++ compiler (AIX and OS/2)
** or the Microsoft Visual C++ compiler (Windows)
** or the compiler supported on your platform.
**
** For more information about these samples see the README file.
**
** For more information on programming in C, see the:
** - "Programming in C and C++" section of the Application Development Guide
** For more information on Building C Applications, see the:
** - "Building C Applications" section of the Application Building Guide.
**
** For more information on the SQL language see the SQL Reference.
**
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlda.h>
#include "util.h"
#ifdef DB268K
/* Need to include ASLM for 68K applications */
#include <LibraryManager.h>
#endif
EXEC SQL INCLUDE SQLCA;
#define CHECKERR(CE_STR) if (check_error(CE_STR, &sqlca)!=0) return 1;
int output_statement (char *);
int main(int argc, char *argv[]) {
EXEC SQL BEGIN DECLARE SECTION;
char userid[9];
char passwd[19];
char st[80];
char st2[80];
char symbol[3];
double currquote;
struct cs {
short length;
char name[15];
} currstatus;
char timestamp[26];
EXEC SQL END DECLARE SECTION;
double quoteupdates[6] = {68.25, 68.75, 68.5, 68.5, 68.62, 68};
short idx;
#ifdef DB268K
/* Before making any API calls for 68K environment,
need to initial the Library Manager */
InitLibraryManager(0,kCurrentZone,kNormalMemory);
atexit(CleanupLibraryManager);
#endif
printf( "\nSample C program: TRIGSQL\n");
if (argc == 1) {
EXEC SQL CONNECT TO sample; /* :rk.5:erk. */
CHECKERR ("CONNECT TO SAMPLE"); /* :rk.6:erk. */
}
else if (argc == 3) {
strcpy (userid, argv[1]);
strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd; /* :rk.5:erk. */
CHECKERR ("CONNECT TO SAMPLE"); /* :rk.6:erk. */
}
else {
printf ("\nUSAGE: trigsql [userid passwd]\n\n");
return 1;
} /* endif */
EXEC SQL DROP TABLE currentquote;
EXEC SQL DROP TABLE quotehistory;
EXEC SQL DROP TRIGGER stock_status;
EXEC SQL DROP TRIGGER record_history;
EXEC SQL CREATE TABLE currentquote (symbol CHAR(3) NOT NULL,
quote DECIMAL(6,2),
status VARCHAR(8));
CHECKERR ("CREATE TABLE CURRENTQUOTE");
EXEC SQL CREATE TABLE quotehistory (symbol CHAR(3) NOT NULL,
quote DECIMAL(6,2), timestamp TIMESTAMP);
CHECKERR ("CREATE TABLE QUOTEHISTORY");
strcpy (st, "INSERT INTO currentquote VALUES ('IBM', 68.5, NULL)");
EXEC SQL EXECUTE IMMEDIATE :st;
CHECKERR ("INSERT INTO CURRENTQUOTE");
EXEC SQL CREATE TRIGGER STOCK_STATUS
NO CASCADE BEFORE UPDATE OF QUOTE ON CURRENTQUOTE
REFERENCING NEW AS NEWQUOTE OLD AS OLDQUOTE
FOR EACH ROW MODE DB2SQL
SET NEWQUOTE.STATUS =
CASE
WHEN NEWQUOTE.QUOTE >=
(SELECT MAX(QUOTE) FROM QUOTEHISTORY
WHERE SYMBOL = NEWQUOTE.SYMBOL
AND YEAR(TIMESTAMP) = YEAR(CURRENT DATE) )
THEN 'High'
WHEN NEWQUOTE.QUOTE <=
(SELECT MIN(QUOTE) FROM QUOTEHISTORY
WHERE SYMBOL = NEWQUOTE.SYMBOL
AND YEAR(TIMESTAMP) = YEAR(CURRENT DATE) )
THEN 'Low'
WHEN NEWQUOTE.QUOTE > OLDQUOTE.QUOTE
THEN 'Rising'
WHEN NEWQUOTE.QUOTE < OLDQUOTE.QUOTE
THEN 'Dropping'
WHEN NEWQUOTE.QUOTE = OLDQUOTE.QUOTE
THEN 'Steady'
END;
CHECKERR ("CREATE TRIGGER STOCK_STATUS");
EXEC SQL CREATE TRIGGER RECORD_HISTORY
AFTER UPDATE OF QUOTE ON CURRENTQUOTE
REFERENCING NEW AS NEWQUOTE
FOR EACH ROW MODE DB2SQL
INSERT INTO QUOTEHISTORY
VALUES (NEWQUOTE.SYMBOL,NEWQUOTE.QUOTE,CURRENT TIMESTAMP);
CHECKERR ("CREATE TRIGGER RECORD_HISTORY");
strcpy (st, "UPDATE currentquote SET quote=? WHERE symbol='IBM'");
strcpy (st2, "SELECT * FROM currentquote");
EXEC SQL PREPARE QUPDATE FROM :st;
for (idx=0; idx < 6; idx++) {
currquote = quoteupdates[idx];
EXEC SQL EXECUTE QUPDATE USING :currquote;
EXEC SQL PREPARE S1 FROM :st2;
EXEC SQL DECLARE C1 CURSOR FOR S1;
EXEC SQL OPEN C1;
EXEC SQL FETCH C1 INTO :symbol, :currquote, :currstatus;
EXEC SQL CLOSE C1;
printf ("%3.3s %10.2f %.*s\n", symbol, currquote, currstatus.length,
currstatus.name);
} /* endfor */
printf ("\nContents of the 'quotehistory' table after updates\n");
strcpy (st, "SELECT * FROM quotehistory");
EXEC SQL PREPARE S2 FROM :st;
EXEC SQL DECLARE C2 CURSOR FOR S2;
EXEC SQL OPEN C2;
do {
EXEC SQL FETCH C2 INTO :symbol, :currquote, :timestamp;
if (SQLCODE != 0) break;
printf ("%3.3s %10.2f %s\n", symbol, currquote, timestamp);
} while ( 1 );
EXEC SQL CLOSE C2;
/* Drop the tables and triggers */
EXEC SQL DROP TABLE currentquote;
CHECKERR("DROP TABLE currentquote");
EXEC SQL DROP TABLE quotehistory;
CHECKERR("DROP quotehistory");
EXEC SQL DROP TRIGGER stock_status;
CHECKERR("DROP TRIGGER stock_status");
EXEC SQL DROP TRIGGER record_history;
CHECKERR("DROP TRIGGER record_history");
EXEC SQL CONNECT RESET;
CHECKERR ("CONNECT RESET");
return 0;
}