Aa@YHH $ d    dFootnote TableFootnote**. . / - .\[0 \yTOCHeadingLusardi closecursor cursor_name database_nameYi]YZ[\Y [!<$lastpagenum><$monthname> <$daynum>, <$year>"<$monthnum>/<$daynum>/<$shortyear>;<$monthname> <$daynum>, <$year> <$hour>:<$minute00> <$ampm>"<$monthnum>/<$daynum>/<$shortyear><$monthname> <$daynum>, <$year>"<$monthnum>/<$daynum>/<$shortyear> <$fullfilename>  <$filename>  <$paratext[Title]>B$  <$paratext[Heading]>  <$curpagenum>  <$marker1>i <$marker2>A (Continued)Pagepage<$pagenum>Heading & Page <$paratext> on page<$pagenum>See Heading & Page%See <$paratext> on page<$pagenum>. Table & Page7Table<$paranumonly>, <$paratext>, on page<$pagenum>o+ (Sheet <$tblsheetnum> of <$tblsheetcount>) wwxx[yyyzzHe{{dA ||uAreAmAK[JKatpaaathnIynu1. >I" 10. /PnumJyeaa;Ime>2. , ar> R$miR$amR"Rm>/I/<$3. aIme>4. , ar>D$moI$da5. ora>R$fuRe>R$fiR  RateR>B$I$pa6. dia Ipag 9.  E$maaEker Eed)NEagem>Edin <E> T$pa 9.1. SeEdina%SeEtexIge 11. E TaIe77. raaly>`texOagem>oE(ShsheE <$QounEEwEyEZzQQA |EeEZEEEEZEEI8. a >R RPRJRaIa2.ar> a$mia$ama"Jm>/K/<$a aDI5.>$fue>$fi  ate>B$$pa di EaE   N E EETEaEI11 Tae7 ra !"#$%&'()*+,-./0123456`8T 9.2. E:`C`DEaFRGRHRIRJKaLaMaNaOaPJQKRaSTUVWXYZ[\]^_`abcdefg h i j k lmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456`8T:`C`DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./012345678<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab d e f g hijklmnopqrtuvwxyz {!|"}#~$%&'()*+,-./012345678<=>?@ABCDEFGHIJKLMNOPQRSu0duw|dv}}H$ wxu H$ UU` Hz xwyu Hz UU` H$ yxzu H$ UU` Hz zy{u Hz UU` HH{z|u HH` HH|{u HH` HH}v HH3UU`} UU` UU`printf("here we go\n"); *UU`3printf("selection criteria: image_type = 'v'\n"); 6UU`| BUU`while (sqlca.sqlcode == 0) { NUU`EXEC SQL FETCH gcursor ZUU`INTO :span, :time; fUU` UrUU`zif (sqlca.sqlcode < 0) { H~UU`#clean_up("FETCH \"gcursor\"");; UUUU` } else { UU`#if (sqlca.sqlcode != NOT_FOUND) { UU`-printf("time: %s span: %s\n", time, span); zUU`} UU` } ƪUU`} ҪUU` ުUU`  ꪗUU`!EXEC SQL CLOSE gcursor; UU`"EXEC SQL DISCONNECT; UU`# UU`$ exit(0); UU`% &UU`&} 2UU`' >UU`(clean_up(stmt) UUJUU`) char *stmt; VUU`*{ bUU`+") EXEC SQL BEGIN DECLARE SECTION; senUU`, ichar *err_stmt = stmt; zUU`- char errmsg[101]; whUU`. =EXEC SQL END DECLARE SECTION; UU`/so UU`0,EXEC SQL INQUIRE_SQL (:errmsg = ERRORTEXT); UUU`1z;fprintf(stderr, "Aborting because of error in %s:\n%s\n", n_uUU`2err_stmt, errmsg); ªUU`3seEXEC SQL DISCONNECT; ΪUU`4de exit(-1); ڪUU`5UU} `6me s`8, 2Embedded SQL example: (Dynamic Select Statements)  :ZIn this example the database used is SOI_DSDS_V2. The function Read_Stmt reads the select %:or[statements from standard input and processes them and the Execute_Select function opens up ex3:UU^cursors necessary to fetch the rows from the database. Finally the functions Print_Header and A:)YPrint_Row process the rows fetched and print them as the standard output. Once again the CO:UU^structures used in this example are specific to INGRES. While the same concept can be used to ]@: D]run this program against a different database vendor product, modifications need to be made. Rk`C UxUU`D(s#include useUU`E%s#include 2d~ DH3K ^~ exH RH R5Footnoted8mpHH HH}ba.d `e G4) References to database objects such as columns, tables, views etc. st" roVThe structures used in Dynamic SQL program by different database vendors has not been 0he`standardized yet. Hence respective documentations need to be referenced while writing a dynamic oc>@ed SQL program. X`tpSample Programs Cp UUYThe following are the sample nondynamic and dynamic SQL programs written in C and INGRES d~:VRelease 6.2. These sample programs are taken from the SOI-DSDS Prototype Version1 and @ Version2. `D5Embedded SQL example: (Nondynamic select statements) u XIn this example columns span and time are selected from the table ap in the SOI_DSDS_V1 ex@ database. 䪪UU`#include UU`mp#include UU` UU`}:/* sets up areas for SQL return values, messages, etc. */ UU`chEXEC SQL INCLUDE SQLCA; e UU`EXEC SQL INCLUDE SQLDA; se,UU`ro m8UU`ba/* SQL error code */ DUU`he#define NOT_FOUND 100 PUU`en i\UU`ermain() le hUU`oc{ tUU`SQ/* local SQL variables */ UU`am EXEC SQL BEGIN DECLARE SECTION; owUU` nchar dbname[50]; UU`ttchar time[50]; dUU`:char span[1]; eseUU`reEXEC SQL END DECLARE SECTION; UU` ȪUU`ioK/* the cursor is a pointer to a table to hold the results of the query */ ) uԪUU`$EXEC SQL DECLARE gcursor CURSOR FOR e કUU`thSELECT span, time _DS쪔UU` FROM ap aUU`UUWHERE image_type='v'; .h>UU` pUU`.hstrcpy(dbname, "SOI_DSDS_V1"); UU`et p(UU`urEXEC SQL CONNECT :dbname; 4UU`chif (sqlca.sqlcode < 0) { e@UU`#fprintf(stderr, "Connect error"); UULUU`  exit(-1); /*XUU`  } dUU` #dEXEC SQL OPEN gcursor; pUU` if (sqlca.sqlcode < 0) { |UU` occlean_up("OPEN \"gcursor\""); l SdamREHH cHH}r 60]UU`F :UU`GseEXEC SQL INCLUDE SQLCA; SUU`HTIEXEC SQL INCLUDE SQLDA; *UU`Iio *6UU`JpoUU``4void Print_Row(); /*print select row values*/ ELJUU`avoid Print_Error(); DAVUU`bst5char *Read_Stmt(); /*read stmts from terminal*/ bUU`c#d,char *Alloc_Mem(); /*allocate Memory*/ chnUU`dZE zUU`elimain() */ UU`ft { UU`g !EXEC SQL BEGIN DECLARE SECTION; UU`hII char dbname[DBNAME_MAX+1]; inUU`i aEXEC SQL END DECLARE SECTION; esuUU`jfo hªUU`kctC/* The dbname can be made dynamic by reading it from stdinput and ުΪUU`li"** copying into dbname variable. ڪUU`ms_*/ 0]檂UU`n strcpy(dbname, "SOI_DSDS_V2"); UU`o UU`p REXEC SQL CONNECT :dbname; `] UU`qldif (sqlca.sqlcode < 0) { ~UU`r^$fprintf(stderr, "Connect error"); "}UU`s P exit(-1); .|UU`tol} ead:{UU`uUU `FzUU`vowRun_Monitor(); seRyUU`wEL&EXEC SQL WHENEVER SQLERROR CONTINUE; ^xUU`xb(printf("SQL:EXITING MONITOR PROG.\n"); fjwUU`yEXEC SQL ROLLBACK; *vvUU`z/*EXEC SQL DISCONNECT; uUU`{ }/*main*/ dfgHH IOHH[D6MAUU`|UU iUU`}D void Run_Monitor() UU`~ h{ *UU`/!EXEC SQL BEGIN DECLARE SECTION; 6UU`dichar stmt_buf[STMT_MAX+1]; "*BUU`amEXEC SQL END DECLARE SECTION; *NUU`n ZUU`"Sint stmt_num; fUU` int rows; RrUU`T  n~UU`UUInit_Sqlda(DEF_ELEMS); deUU`UU rUU`de!for (stmt_num = 1;; stmt_num++) UUU`1){ .|UU`}7if (Read_Stmt(stmt_num, stmt_buf, STMT_MAX) == NULL) nitUU`UU break; ƪUU`QL OҪUU`; EXEC SQL WHENEVER SQLERROR GOTO Stmt_Err; ުUU`C  ꪗUU`: /*Prepare and describe the stmt. If sqlda is too small UU`+then allocate a new one and redescribe*/ gUU`'EXEC SQL PREPARE stmt FROM :stmt_buf; UU`%EXEC SQL DESCRIBE stmt INTO :sqlda; UUU`_M!if (sqlda->sqld > sqlda->sqln){ &UU`/Init_Sqlda(sqlda->sqld); TIO2UU`&EXEC SQL DESCRIBE stmt INTO :sqlda; >UU`am} EC JUU`CT ;VUU`if (sqlda->sqld == 0){ "SbUU P /*this is not a UUnUU@ELselect stmt*/ zUU`EXEC SQL EXECUTE stmt; tUU`rows = sqlca.sqlerrd[2]; .|UU`}>} else { /*this is a select*/ UU`rows = Execute_Select();  OUU`} UU`L printf("[%d row(s)]\n", rows); ªUU`C continue; UUΪUU`pa Stmt_Err: be ڪUU` i&EXEC SQL WHENEVER SQLERROR CONTINUE; 檂UU`e Print_Error(); gUU`}/*for each stmt*/ mtUU`}/*Run_Monitor*/  UU`BE m~UU`void Init_Sqlda(num_elems) >sq"}UU` int num_elems; /.|UU`da{ :{UU`UU if (sqlda) ECFzUU` Ifree((char *)sqlda); `RyUU` U^xUU`2sqlda = (IISQLDA *) Alloc_Mem(IISQDA_HEAD_SIZE + jwUU` ,(num_elems*IISQDA_VAR_SIZE), "new SQLDA"); vvUU`t sqlda->sqln = num_elems; uUU`}/*Init_Sqlda*/ ECdqlHH }HHhi6 sUU`UU UU`cuint Execute_Select() UU` { *UU`p int rows; w(s6UU`Print_Header(); cBUU`,EXEC SQL WHENEVER SQLERROR GOTO Close_Csr; iNUU`ER LZUU`EXEC SQL OPEN csr; ntfUU`  rows = 0; }rUU`mtwhile (sqlca.sqlcode == 0){ n~UU`UU.EXEC SQL FETCH csr USING DESCRIPTOR :sqlda; UU`}if(sqlca.sqlcode == 0){ UU`UU rows++; :{UU`iPrint_Row(); UU`ee} r *UU` }/*while there are more rows*/ ƪUU`A Close_Csr: ISҪUU`wif (sqlca.sqlcode < 0) emުUU`, Print_Error(); vꪗUU`s&EXEC SQL WHENEVER SQLERROR CONTINUE; UU`a*EXEC SQL CLOSE csr; UU`}/*Execute_Select*/ UU` UU`void Print_Header() &UU`{ 2UU`  inti; >UU`SeIISQLVAR *sqv; JUU`int base_type; VUU`intres_cur_size; bUU`E nUU`RO6for (res_cur_size = 0, i = 0; i < sqlda->sqld; i++){ zUU`L sqv = &sqlda->sqlvar[i]; UU 7printf("[%d] %.*s ", i+1, sqv->sqlname.sqlnamel, sqv-UUUU@QL>sqlname.sqlnamec); IPUU` UUU`ca3/*find the base type of the result non-nullable*/ UU`$if ((base_type = sqv->sqltype) <0) }ªUU`base_type = -base_type; e rΪUU`UU ڪUU`IS7 /*make different datatypes into int, float or char*/ UU檂UU`Erswitch (base_type){ UU`ENcase IISQ_INT_TYPE: UU`E!res_cur_size += sizeof(long);  UU`Sesqv->sqllen = sizeof(long); ~UU`vo break; "}UU`UU .|UU`UU :{UU`case IISQ_MNY_TYPE: AR FzUU`if (sqv->sqltype <0) asRyUU`UU"sqv->sqltype = -IISQ_FLT_TYPE; ^xUU` else UUjwUU`s_!sqv->sqltype = IISQ_FLT_TYPE; dvvUU`UU#res_cur_size += sizeof(double); uUU`!sqv->sqllen = sizeof(double); sdUUnaHH HH t6ulUU` break; UU`se pUU`<0 }*UU`case IISQ_FLT_TYPE: pe;6UU`#res_cur_size += sizeof(double); e dBUU` i!sqv->sqllen = sizeof(double); NUU`tc bZUU` UfUU`IIcase IISQ_DTE_TYPE: UUrUU`ursqv->sqllen = DATE_SIZE; ~UU`qv qUU`); UU`vocase IISQ_CHA_TYPE: `UU`UUcase IISQ_VCH_TYPE: `UU`_M#res_cur_size +=sqv->sqllen + 1; if UU`asif (res_cur_size % 2) vƪUU`FLres_cur_size ++; ҪUU`wif (sqv->sqltype <0) sqުUU`YP"sqv->sqltype = -IISQ_CHA_TYPE; ꪗUU`ub  else uUU`!sqv->sqltype = IISQ_CHA_TYPE; UU` break; UU`} /*switch*/ UU` &UU`if (sqv->sqltype <0) 6ul2UU`"res_cur_size += sizeof(short); >UU`<0}/*for each column */ JUU`E: ;VUU`printf("\n\n"); =bUU` d nUU`C /* So far printed all column headers and converted data types to `zUU`UUA** one of int, char or float. Now allocate single result buffer qUU`C** and point all result column data areas into it. If we have old UU` E:A** result data area and it is not large enough then free it and UU` iz6** allocate a new one. Otherwise reuse the last one. UU` */ UUUU` ur zªUU` UUBif (res_buf.res_length >0 && res_buf.res_length sqld; i++) { uUU`ltsqv = &sqlda->sqlvar[i]; e edUU aHH oHHUU6urUU` $if((base_type = sqv->sqltype) <0) s_UU`s_base_type = -base_type; TYUU`es t*UU` :sqv->sqldata = (char *)&res_buf.res_data[res_cur_size]; 6UU`!; res_cur_size += sqv->sqllen; */BUU`" NUU`# A#if (base_type == IISQ_CHA_TYPE){ torZUU`$*res_cur_size++; /*add one for null*/ fUU`%es:if (res_cur_size % 2) /*round off to even boundary*/ rUU`&res_cur_size++; um~UU`'es} drUU`(mn zUU`)inif (sqv->sqltype <0) { UUU *insqv->sqlind = (short eaUU@*#*)&res_buf.res_data[res_cur_size]; vvUU`+f"res_cur_size += sizeof(short); ƪUU`,u } else { ltҪUU`-sqsqv->sqlind = (short *)0; ުUU`.} ꪗUU`/}/*for each column*/ UU`0}/*Print_Header*/ UU`1 UU`2(( eUU`3pevoid Print_Row() U&UU`4ty{ 2UU`5 inti; >UU`6UU2IISQLVAR *sqv;/*pointer to 'sqlvar' */ JUU`7intbase_type; VUU`8v- lbUU`UU4 /* for each column print column number and data. ISnUU`** null columns print as n/a ++;zUU`ul*/ UU`<$for (i = 0; i sqld; i++) { o UU`=sqv = &sqlda->sqlvar[i]; _siUU`>UUprintf("[%d] ", i+1); UUU`?'if(sqv->sqlind && *sqv->sqlind <0) { UU`@printf("N/A "); eaªUU`A } else { resΪUU`B];)/* find the base type of the result*/ =ڪUU`C&if ((base_type = sqv->sqltype) <0) 檂UU`Dqvbase_type = -base_type; UU`E UU`F}switch (base_type) {  UU`Gricase IISQ_INT_TYPE: ~UU`HUU(printf("%d ", (long *)sqv->sqldata); nt"}UU`IUU break; .|UU`J i:{UU`KUUcase IISQ_FLT_TYPE: *FzUU`Lo *printf("%f ", (double *)sqv->sqldata); RyUU`MUU break; ^xUU`NUU jwUU`On  nvvUU`Pd case IISQ_CHA_TYPE: uUU`Qs (printf("%s ", (char *)sqv->sqldata); d io ddaHH +1HH & -> UT UT`Introduction to Embedded SQL A!`UU Overview 9 XThe Structured Query Language(SQL) was originally developed by IBM in the mid-1970s for _tG) btheir prototype relational database called System-R. In 1979 Oracle Corp. first introduced SQL to UtyVthe commercial market. Since then it has been very widely used by relational database c@->Mmanagement system (RDBMS) users and it was adopted as ANSI standard in 1986. U}`II What is SQL *`o VSQL is a set of statements to access an RDBMS. SQL is divided into three components:  O1) Data Manipulation Language(DML) commands like Inserts, Updates, Deletes and s @ (Selects to manipulate data. `M2) Data Dictionary Language(DDL) commands like Create, Drop and Alter table. `O3) Data Control Language(DCL) commands like Grant, Commit, Lock, Rollback etc. UT `InNIn general DCL and DDL commands are used by the Database Administrator (DBA). %`ueNeed for an extension to SQL = n bSQL is nonprocedural since it processes sets of records rather than one record at a time. This is Krscparticularly useful while manipulating sets of records at a time. However in most applications the sedYabaneed to access a set of records and perform more sophisticated operations on them than the basic 8gTones allowed by SQL arises. Hence the extension to SQL in the form of embedding SQL S.u@ntVstatements within procedural programming languages like C, FORTRAN. PASCAL, ADA, etc. `s,What is Embedded SQL  ct]Embedded SQL is set of SQL statements placed within an application program written in a host er Xlanguage. In the application program, SQL statements can be freely intermixed with host ocUTZlanguage statements. All the SQL statements begin with keywords EXEC SQL and end with the ^SQL statement terminator. This allows the precompiler to translate all EXEC SQL statements to rd[DBMS calls recognized by the host language compiler. For example, a select statement in an ani@ec+embedded SQL program would look like this: theUU`# EXEC SQL SELECT * FROM TABLE; an`hi" Advantages of using Embedded SQL 7`@Embedded SQL allows all SQL statements including the following: n Q in]1) Manipulate data dictionary structures like tables and views. That is, tables or views can N_@. Ube created or dropped, and also grant or revoke access to tables and views to users. fy acY2) Manipulate data by using Select, Insert, Update and Delete statements on the database ad cd HH laHHbeth@ atables. h "`K3)Retrieval of status information by using SQL Communication Area (SQLCA). EXE< o Z4) Perform database management activities like grants, revokes and integrities on tables, J@anAcopy data from one table to another, or one database to another. :d`N5) Use it in distributed database system to access data from other databases. ~ L _6) Finally, regular activities like running reports daily etc. can be performed as batch jobs, @ul by using embedded SQL programs. e `ThGeneral Syntax vie ZIn general we can embed SQL statements in the host language program anywhere we need; but Ywe need to include declaration of host language variables before we can access them. The a@Kfollowing is the basic outline of how an embedded SQL program should look: laUU`% begin program -- host language code  UU` EXEC SQL INCLUDE SQLCA; )"UU`s ! EXEC SQL BEGIN DECLARE SECTION; i:UU`XE declare host variables here RUU`nt EXEC SQL END DECLARE SECTION; andjUU`bl" EXEC SQL WHENEVER SQLERROR STOP; UU`an! EXEC SQL CONNECT database_name; :UU`: EXEC SQL SELECT columns into local variables from table; UU`.  EXEC SQL DISCONNECT; ʪUU`ac end program u`y Cursors e   jbThe above syntax is very basic and it will suffice if the DML statement like SELECT will retrieve  aand manipulate only one record at a time. However we need the ability to retrieve and manipulate we[sets of records from the database. For that purpose we use CURSORS. A cursor is like a row %owamarker for a database result table. Once a cursor is declared and opened it can be moved forward n3an`through the set, pointing to each individual row in turn. When the cursor moves to the row, the DEA_data in that row can be transferred to host variables and processed using the embedded SQL and ON;O@Ehost language statements. Following is the syntax for using cursors: hUU`am) begin program -- host language code cUU`va EXEC SQL INCLUDE SQLCA; d;  eHH CuHHntveUU`ll! EXEC SQL BEGIN DECLARE SECTION; SUU`e  declare host variables here 6UU`rd EXEC SQL END DECLARE SECTION; bilNUU`d " EXEC SQL WHENEVER SQLERROR STOP; fUU` t! EXEC SQL CONNECT database_name; e~UU` i) EXEC SQL DECLARE cursor_name CURSOR FOR rUU`su& SELECT column1, column2 COLUMN2 ... UU`ov  FROM table ƪUU`th WHERE conditions... ުUU` EXEC SQL OPEN cursor_name; veUU`DE/ EXEC SQL WHENEVER NOT FOUND GOTO closecursor; nsfUU`ab$ loop while more rows to be fetched QL&UU`2 EXEC SQL FETCH cursor_name into local variables; >UU`cu! here manipulate local variables bVUU`st end loop nUU` closecursor: UU` EXEC SQL CLOSE cursor_name; UU` EXEC SQL DISCONNECT; UU` end program ` Dynamic SQL   EXSo far we have seen that the SQL statements are hardcoded in the host language program. C `However, situations may arise where we may not know the selection criteria beforehand. In those NNZcases it is useful to know that we can use Dynamic SQL and build more versatile programs. LERTypically Dynamic SQL program can be used when one of the following is unknown at @itprecompile time: U9`L 71) Text of the SQL statement (commands, clauses, etc.) VERS`os 2) The number of host variables lm`s #3) The datatypes of host variables 2 EdalUUH$  arH$ UUUU`rs Hz  LOHz C SCUUhUU#ESQLY11Z[5/6/92\ `HH HHtear` h Hqv? ^~ HzHzn Single LineherH'~itFootnote ulo andHvDf ^~ HHa Double LineQL H ~e  Double Lineemest H ~3) Single Line2 Eal HZ~ TableFootnoteUEGX-Rb ^~ EPoEPoO TableFootnoteHH SCHH692UU`R break; UU`S}/*switch*/ UU`T }/*else*/ *UU`Uv}/*for each column*/ 6UU`Vprintf("\n"); LinBUU`W}/*Print_Row*/ itNUU`X oZUU`Y fUU`Zulvoid Print_Error() rUU`[{ ~UU`\!EXEC SQL BEGIN DECLARE SECTION; oUU`]char error_buf[150]; UU`^EXEC SQL END DECLARE SECTION; UU`_ UU``/EXEC SQL INQUIRE_SQL(:error_buf = ERRORTEXT); UU`a4printf("\n Sql Error:\n %s\n", error_buf); ƪUU`bSi}/*Print_Error*/ ҪUU`d ުUU`e.char *Read_Stmt(stmt_num, stmt_buf, stmt_max) ꪗUU`fint stmt_num; UU`gX-char stmt_buf; ~UU`hint stmt_max; UU`i{ UU`j#char input_buf[INPUT_SIZE +1]; &UU`k7char *icp; /*scan input buffer*/ wit2UU`lUU:char *ocp; /*scan output stmt_buf*/ >UU`mUUAint in_string; /*for string handling*/ tJUU`nprintf("%3d >", stmt_num); VUU`ovo*ocp = stmt_buf; bUU`pin_string = 0; \nUU`qGI7while (fgets(input_buf, INPUT_SIZE, stdin) != NULL) { _buzUU rUU@for (icp = input_buf; *icp && ((ocp - stmt_buf) <=stmt_max)); UU@r icp++) { UU`t_b;/* not in string -- check for delimiters and new line */ or:UU`uer+ if ( !in_string) { rorUU`vdif (*icp == ';') { UU`wtm*ocp = '\0'; ufªUU`xreturn stmt_buf; _nΪUU`yg} else if (*icp == '\n') { ڪUU`zst*ocp++ = ' '; U檂UU`{&break; /*read next line*/ UU`|} else if (*icp == '\'') { UU`}ca n UU`~/*entering string*/ ~UU` in_string++; ut"}UU`} m.|UU` *ocp++ = *icp; :{UU`g "} else { /*inside a string*/ FzUU`t_if (*icp == '\n') { voRyUU`; -break; /*new line in srting is ignored*/ ^xUU`le} else if (*icp == '\'') { dinjwUU`.if (*(icp+1) == '\'') /*escaped quote?*/ vvUU`*ocp++ = *icp++; uUU`+)} dngrsHH uHHin-orUU`d*ocp++ = *icp; UU`w}/*if instring*/ ufUU`} /*for all char in buffer*/ *UU` e 6UU`{ "if (ocp - stmt_buf >=stmt_max) { BUU`{8/*if statement is too large ignore it and try again*/ |NUU  (<printf("Sql error: Maximum stmt length (%d) exceeded.\n", /ZUU@ stmt_max); `fUU`++4printf("%3d> ", stmt_num); /*reprompt the user*/ rUU`{ocp = stmt_buf; ~UU`dein_string = 0; UU`f } else { UU UU>printf("---->"); /*break on new-line - print UU@ continue sign*/ \'UU`UU} UU`==#}/*while reading from std input*/ UUƪUU`+ return NULL; ҪUU`}/*Read_Stmt*/ ުUU`ng ꪗUU`rs(char *Alloc_Mem(mem_size, error_string) UU`intmem_size; UU`char*error_string; UU`w{ UU`uf char *mem; &UU` cmem = malloc(mem_size); 2UU` if (mem) "i>UU`>=return mem; JUU`/*print error and rollback*/ e iVUU`|>printf("Sql Fatal Error: Cannot allocate %s (%d bytes).\n", bUU`/error_string, mem_size); );nUU`:printf("Any pending updates are being rolled back.\n"); zUU`{'EXEC SQL WHENEVER SQLERROR CONTINUE; UU`EXEC SQL ROLLBACK; sUU`EXEC SQL DISCONNECT; UU`k exit(-1); prUU`}/*Alloc_Mem*/ gn*`Acknowledgement:  wh\Thanks to Vicki Johnson for her initial version of the Nondynamic Embedded SQL example. It ea@Gserved as a very useful working example for adding more options later. ing` References m_s`UU*1) ORACLE Precompilers Programmer's Guide 1`*2) Ingres Reference Guide to Embedded SQL K`oc+3) SQL Language Reference Manual -- ORACLE "ie`>=4) Ingres/SQL Reference Manual `an75) The Database Experts' Guide to SQL by Frank Lusardi 1 anduteLeftdRightsind~ Referenceddad\nddv Cdd sdECddprd lld d =L00$ @=e Indentvef> ` CellHeadingrf?E SQLFootnotef@T ExHeadingtBodyfA  TableFootnotefBT  TableTitleT:Table : fCPTitleBody fD  6HBody0$ @E IndentfF  CellHeadingtfG CellBodyfHT  TableTitleT:Table : fIQ Heading2. lBody@J Ti  oHeader@K   yFooterfM InCellBody0$ @N  CeeIndent0$ @O lBo~IndentfPTHeadingnBody0$ @Q HeZIndent0$ @R Indent o fSQ Heading2. Body fTQ Heading3 .. Body fYQ Heading3 .. nBody0$ @Z [Indentf\ 6HeHdyBodyf` nde6HBody fa  6HBodyfy 6HBodyf Y6kBodyf 6lBodyf 6lBodyf lBodyf 6cBodyf y6dBodyf 6ZBodyf 6HBodyf kBodyf 6HBodyf 6HBodyf 6YyBodyf 6HBodyf 6HBodyf 6HdyBodyf 6$HdyBodyf 66HldyBodyf 6@Bodyf ?HBody   Emphasis   Subscript  Superscript dy    ;eujeThinfMediumgDoublehThicky@i Very Thin eeeeeeeeegHHFGFHFGFHFGFHFGFHFGFFormat A efeeeeefHHFGFHFGFHFGFmHFGFHFGFFormat B-=.-SuCommentCourier HelveticaTimesrRegularRomanMediumBold RegularItalico:9/,P;.+q-kIbjdUW?noL}T R$dߙu4ѕI~ #Y2,(pB$Fi,tͨ{:$ )b x&>gQGnxGGPaPo*] z N5V44i"*fC