Guide to the dispcat_pic.ec File

=======================================================================
1. /*
2.    * dispcat_pic.ec *
3.The following program prompts the user for a catalog number,
4. selects the cat_picture column, if it is not null, from the
5. catalog table of the demonstration database and saves the
6. image into a .gif file.
7. */
8. #include <stdio.h>
9. #include <ctype.h>
10. EXEC SQL include sqltypes;
11. EXEC SQL include locator;
12. #define WARNNOTIFY      1
13.#define NOWARNNOTIFY    0
14. #define LCASE(c) (isupper(c) ? tolower(c) : (c))
15. #define BUFFSZ 256
16. extern errno;
17. EXEC SQL BEGIN DECLARE SECTION;
18.     mlong cat_num;
19.     ifx_loc_t cat_descr;
20.     ifx_loc_t cat_picture;
21. EXEC SQL END DECLARE SECTION;
22. char cpfl[18];  /* file to which the .gif will be copied */
=======================================================================

Lines 8 - 11

The #include <stdio.h> statement includes the stdio.h header file from the /usr/include directory on UNIX™ and from the include subdirectory for Microsoft™ Visual C++ on Windows™. The stdio.h file enables dispcat_pic to use the standard C I/O library. The program also includes the header files sqltypes.h and locator.h (lines 10 and 11). The locator.h file contains the definition of the locator structure and the constants that you need to work with this structure.

Lines 12 - 16

Use the WARNNOTIFY and NOWARNNOTIFY constants (lines 12 and 13) with the exp_chk2() exception-handling function. Calls to exp_chk2() specify one of these constants as the second argument to indicate whether to display SQLSTATE and SQLCODE information for warnings (WARNNOTIFY or NOWARNNOTIFY). See lines 171 - 177 for more information about the exp_chk2() function.

The program uses BUFFSZ (line 15) to specify the size of arrays that store input from the user. Line 16 defines errno, an external integer where system calls store an error number.

Lines 17 - 21

These lines define global host variables needed for the program. The cat_num variable holds the catalog_num column value of the catalog table. Lines 19 and 20 specify the locator structure as the data type for host variables that receive data for the cat_descr and cat_picture simple-large-object columns of the catalog table. The locator structure is the host variable for a simple-large-object column that is retrieved from or stored to the database. The locator structure has a ifx_loc_t typedef. The program uses the locator structure to specify simple-large-object size and location.

Line 22

Line 22 defines a single global C variable. The cpfl character array stores the name of a file. This named file is the location for the simple-large-object .gif image of cat_picture that the database server writes.

=======================================================================
23. main(argc, argv)
24. mint argc;
25. char *argv[];
26. {
27.       char ans[BUFFSZ];
28.       int4 ret, exp_chk2();
29.       char db_msg[ BUFFSZ + 1 ];
30.     EXEC SQL BEGIN DECLARE SECTION;
31.         char db_name[20];
32.         char description[16];
33.     EXEC SQL END DECLARE SECTION;
=======================================================================

Lines 23 - 26

The main() function is the point at which program execution begins. The first argument, argc, is an integer that gives the number of arguments submitted on the command line. The second argument, argv[], is a pointer to an array of character strings that contain the command-line arguments. The dispcat_pic program expects only the argv[1] argument, which is optional, to specify the name of the database to access. If argv[1] is not present, the program opens the stores7 database.

Lines 27 - 29

Lines 27 - 29 define the C variables that are local in scope to the main() function. The ans[BUFFSZ] array is the buffer that receives input from the user, namely the catalog number for the associated cat_picture column. Line 28 defines a 4-byte integer (ret) for the value that exp_chk2() returns and declares exp_chk2() as a function that returns a long. The db_msg[BUFFSZ + 1] character array holds the form of the CONNECT statement used to open the database. If an error occurs while the CONNECT executes, the string in db_msg is passed into the exp_chk2() function to identify the cause of the error.

Lines 30 - 33

Lines 30 - 33 define the host variables that are local to the main() function. A host variable receives data that is fetched from a table and supplies data that is written to a table. The db_name[20] character array is a host variable that stores the database name if the user specifies one on the command line. The description variable holds the value that the user entered, which is to be stored in the column of the stock table.

=======================================================================
34.        printf("DISPCAT_PIC Sample ESQL Program running.\n\n");
35.     if (argc > 2)           /* correct no. of args? */
36.         {
37.         printf("\nUsage: %s [database]\nIncorrect no. of 
    argument(s)\n",
38.             argv[0]);
39.         printf("DISPCAT_PIC Sample Program over.\n\n");
40.         exit(1);
41.         }
42.     strcpy(db_name, "stores7");
43.     if(argc == 2)
44.         strcpy(db_name, argv[1]);
45.     EXEC SQL connect to :db_name;
46.     sprintf(db_msg,"CONNECT TO %s",db_name);
47.     if(exp_chk2(db_msg, NOWARNNOTIFY) < 0)
48.         {
49.         printf("DISPCAT_PIC Sample Program over.\n\n");
50.         exit(1);
51.         }
52.     if(sqlca.sqlwarn.sqlwarn3 != 'W')
53.         {
54.         printf("\nThis program does not work with Informix SE. ");
55.         EXEC SQL disconnect current;
56.         printf("\nDISPCAT_PIC Sample Program over.\n\n");
57.         exit(1);
58.         }
59.     printf("Connected to %s\n", db_name);
60.    ++argv;
=======================================================================

Lines 34 - 51

These lines interpret the command-line arguments and open the database. Line 35 checks whether more than two arguments are entered on the command line. If so, dispcat_pic displays a message to show the arguments that it expects and then it terminates. Line 42 assigns the default database name of stores7 to the db_name host variable. The program opens this database if the user does not enter a command-line argument.

The program then tests whether the number of command-line arguments is equal to 2. If so, dispcat_pic assumes that the second argument, argv[1], is the name of the database that the user wants to open. Line 44 uses the strcpy() function to copy the name of the database from the argv[1] command line into the db_name host variable. The program then executes the CONNECT statement (line 45) to establish a connection to the default database server and open the specified database (in db_name).

The program reproduces the CONNECT statement in the db_msg[] array (line 46). It does so for the sake of the exp_chk2() call on line 47, which takes as its argument the name of a statement. Line 47 calls the exp_chk2() function to check on the outcome. This call to exp_chk2() specifies the NOWARNNOTIFY argument to prevent the display of warnings that CONNECT generates.

Lines 52 - 60

After CONNECT successfully opens the database, it stores information about the database server in the sqlca.sqlwarn array. Because the dispcat_pic program handles simple-large-object data types that are not supported on older version of the server, line 52 checks the type of database server. If the sqlwarn3 element of sqlca.sqlwarn is set to W, the database server is the program continues. Otherwise, the program notifies the user that it cannot continue and exits. The program has established the validity of the database server and now displays the name of the database that is opened (line 59).

=======================================================================
61.  while(1)
62.      {
63.      printf("\nEnter catalog number: "); /* prompt for cat. 
                                          * number */
64.      if(!getans(ans, 6))
65.          continue;
66.      printf("\n");
67.      if(rstol(ans, &cat_num))    /* cat_num string to long */
68.          {
69.          printf("** Cannot convert catalog number '%s' to long 
    integer\n",
               ans);
70.          EXEC SQL disconnect current;
71.          printf("\nDISPCAT_PIC Sample Program over.\n\n");
72.          exit(1);
73.          }
74.      ret=sprintf(cpfl, "pic_%s.gif", ans);
75.      /*
76.       *  Prepare locator structure for select of cat_descr
77.       */
78.      cat_descr.loc_loctype = LOCMEMORY;  /* set for 'in memory' */
79.     cat_descr.loc_bufsize = -1;         /* let db get buffer */
80.      cat_descr.loc_mflags = 0;   /* clear memory-deallocation 
                                  * feature */
81.      cat_descr.loc_oflags = 0;           /* clear loc_oflags */
82.      /*
83.       *  Prepare locator structure for select of cat_picture
84.       */
85.      cat_picture.loc_loctype = LOCFNAME;   /* type = named file */
86.      cat_picture.loc_fname = cpfl;       /* supply file name */
87.      cat_picture.loc_oflags = LOC_WONLY; /* file-open mode = write 
                                          */
88.      cat_picture.loc_size = -1;  /* size = size of file */    
=======================================================================

Lines 61 - 74

The while(1) on line 61 begins the main processing loop in dispcat_pic. Line 63 prompts the user to enter a catalog number for the cat_picture column that the user wants to see. Line 64 calls getans() to receive the catalog number that the user inputs. The arguments for getans() are the address in which the input is stored, ans[], and the maximum length of the input that is expected, including the null terminator. If the input is unacceptable, getans() returns 0 and line 65 returns control to the while at the top of the loop in line 61, which causes the prompt for the catalog number to be displayed again. For a more detailed explanation of getans(), see ids_esqlc_0234.html#ids_esqlc_0234. Line 67 calls the library function rstol() to convert the character input string to a long data type to match the data type of the catalog_num column. If rstol() returns a nonzero value, the conversion fails and lines 69 - 72 display a message to the user, close the connection, and exit. Line 74 creates the name of the .gif file to which the program writes the simple-large-object image. The file name consists of the constant pic_, the catalog number that the user entered, and the extension .gif. The file is created in the directory from which the program is run.

Lines 75 - 81

These lines define the simple-large-object location for the TEXT cat_descr column of the catalog table, as follows:
  • Line 78 sets loc_loctype in the cat_descr locator structure to LOCMEMORY to tell to select the data for cat_descr into memory.
  • Line 79 sets loc_bufsize to -1 so that allocates a memory buffer to receive the data for cat_descr.
  • Line 80 sets loc_mflags to 0 to disable the memory-deallocation feature (see Line 149) of .

If the select is successful, returns the address of the allocated buffer in loc_buffer. Line 81 sets the loc_oflags file-open mode flags to 0 because the program retrieves the simple-large-object information into memory rather than a file.

Lines 82 - 88

These lines prepare the locator structure to retrieve the BYTE column cat_picture of the catalog table. Line 85 moves LOCFNAME to loc_loctype to tell to locate the data for cat_descr in a named file. Line 86 moves the address of the cpfl file name into loc_fname. Line 87 moves the LOC_WONLY value into the loc_oflags file-open mode flags to tell to open the file in write-only mode. Finally, line 88 sets loc_size to -1 to tell to send the BYTE data in a single transfer rather than break the value into smaller pieces and use multiple transfers.

=======================================================================
89.     /* Look up catalog number */
90.     EXEC SQL select description, catalog_num, cat_descr, cat_picture
91.         into :description, :cat_num, :cat_descr, :cat_picture
92.         from stock, catalog
93.         where catalog_num = :cat_num and
94.         catalog.stock_num = stock.stock_num and
95.         catalog.manu_code = stock.manu_code;
96.     if((ret = exp_chk2("SELECT", WARNNOTIFY)) == 100) /* if not 
                                                       * found */
97.         {
98.         printf("** Catalog number %ld not found in ", cat_num);
99.         printf("catalog table.\n");
100.         printf("\t OR item not found in stock table.\n");
101.         if(!more_to_do())
102.             break;
103.         continue;
104.         }
105.      if (ret < 0)
106.         {
107.         EXEC SQL disconnect current;
108.         printf("\nDISPCAT_PIC Sample Program over.\n\n");
109.         exit(1);
110.         }
111.     if(cat_picture.loc_indicator == -1)
112.         printf("\tNo picture available for catalog number %ld\n\n",
113.                 cat_num);
114.     else
115.         {
116.         printf("Stock Item for %ld: %s\n", cat_num, description);
117.         printf("\nThe cat_picture column has been written to the 
     file:
118.            %s\n",    cpfl);
119.         printf("Use an image display tool or a Web browser ");
120.         printf("to open %s for viewing.\n\n", cpfl);
121        }
122.     prdesc();       /* display catalog.cat_descr */
=======================================================================

Lines 89 - 95

These lines define a SELECT statement to retrieve the catalog_num, cat_descr, and cat_picture columns from the catalog table and the description column from the stock table for the catalog number that the user entered. The INTO clause of the SELECT statement identifies the host variables that contain the selected values. The two ifx_loc_t host variables, cat_descr and cat_picture, are listed in this clause for the TEXT and BYTE values.

Lines 96 - 104

The exp_chk2() function checks whether the SELECT statement was able to find the stock_num and manu_code for the selected row in the catalog table and in the stock table. The catalog table does not contain a row that does not have a corresponding row in the stock table. Lines 98 - 103 handle a NOT FOUND condition. If the exp_chk2() function returns 100, the row was not found; lines 98 - 100 display a message to that effect. The more_to_do() function (line 101) asks whether the user wants to continue. If the user answers n for no, a break terminates the main processing loop and control transfers to line 131 to close the database before the program terminates.

Lines 105 - 110

If a runtime error occurs during the select, the program closes the current connection, notifies the user, and exits with a status of 1.

Lines 111 - 113

If cat_picture.loc_indicator contains-1 (line 111), the cat_picture column contains a null and the program informs the user (line 112). Execution then continues to line 113 to display the other returned column values.

Lines 114 - 122

These lines display the other columns that the SELECT statement returned. Line 116 displays the catalog number that is being processed and the description column from the stock table. Line 122 calls prdesc() to display the cat_descr column. For a detailed description of prdesc(), see Guide to the prdesc.c file.

=======================================================================
123.   if(!more_to_do())   /* More to do? */
124.     break;      /* no, terminate loop */ 
125.      /* If user chooses to display more catalog rows, enable the
126.       * memory-deallocation feature so that ESQL/C deallocates old
127.       * cat_desc buffer before it allocates a new one.
128.       */
129.     cat_descr.loc_mflags = 0;   /* clear memory-deallocation feature 
                               */
130.     }
131.     EXEC SQL disconnect current;
132.     printf("\nDISPCAT_PIC Sample Program over.\n\n");
133.     } /* end main */      
134.     /* prdesc() prints cat_desc for a row in the catalog table */
135.     #include "prdesc.c"
=======================================================================

Lines 123 - 130

The more_to_do() function then asks whether the user wants to enter more catalog numbers. If not, more_to_do() returns 0 and the program performs a break to terminate the main processing loop, close the database, and terminate the program.

The closing brace on line 130 terminates the main processing loop, which began with the while(1) on line 61. If the user wants to enter another catalog number, control returns to line 61.

Line 131 - 133

When a break statement (line 124) terminates the main processing loop that the while(1) on line 61 began, control transfers to line 131, which closes the database and the connection to the default database server. The closing brace on line 133 terminates the main() function on line 23 and terminates the program.

Lines 134 and 135

Several of the simple-large-object demonstration programs call the prdesc() function. To avoid having the function in each program, the function is put in its own source file. Each program that calls prdesc() includes the prdesc.c source file. Since prdesc() does not contain any statements, the program can include it with the C #include preprocessor statement (instead of the include directive). For a description of this function, see Guide to the prdesc.c file.

=======================================================================
136. /*
137.  * The inpfuncs.c file contains the following functions used in this
138.  * program:
139.  *    more_to_do() - asks the user to enter 'y' or 'n' to indicate 
140.  *                  whether to run the main program loop again.
141.  *
142.  *    getans(ans, len) - accepts user input, up to 'len' number of
143.  *               characters and puts it in 'ans'
144.  */
145. #include "inpfuncs.c"
146. /*
147.  * The exp_chk.ec file contains the exception handling functions to
148.  * check the SQLSTATE status variable to see if an error has 
     occurred 
149.  * following an SQL statement. If a warning or an error has
150.  * occurred, exp_chk2() executes the GET DIAGNOSTICS statement and 
151.  * displays the detail for each exception that is returned.
152.  */
153. EXEC SQL include exp_chk.ec;
=======================================================================

Lines 136 and 145

Several of the demonstration programs also call the more_to_do() and getans() functions. These functions are also broken out into a separate C source file and included in the appropriate demonstration program. Neither of these functions contain , so the program can use the C #include preprocessor statement to include the files. For a description of these functions, see ids_esqlc_0234.html#ids_esqlc_0234.

Line 146 - 153

The exp_chk2() function examines the SQLSTATE status variable to determine the outcome of an SQL statement. Because many demonstration programs use exception checking, the exp_chk2() function and its supporting functions are broken out into a separate exp_chk.ec source file. The dispcat_pic program must use the include directive to include this file because the exception-handling functions use statements. For a description of the exp_chk.ec source file, see Guide to the exp_chk.ec file.
Tip: In a production environment, functions such as prdesc(), more_to_do(), getans(), and exp_chk2() would be put into C libraries and included on the command line of the program at compile time.