Just Logic/SQL Relational Database Management System

C program example using Just Logic/SQL Precompiler


Home | Product Description | Technical Features | Client-Server option | How to interface with a Web Server | How to Order

/
   precompiler demonstration program
   ----------- ------------- -------

   Creates ABC Auto Part Company demo database.
*/

#include 
#include 
#include 
#include 
#include 

EXEC SQL BEGIN DECLARE SECTION;

int      table_count;

int      part_no;

char     part_name[21];

long     quantity;

short    quantity_null_indicator;

char     customer_id[11];

char     customer_name[21];

short    name_null_indicator;

char     customer_address[21];

short    address_null_indicator;

char     sql_statement_text[150];

EXEC SQL END DECLARE SECTION;



EXEC SQL DECLARE  part_cursor CURSOR FOR

         select   part_no, name, quantity

         from     part;



EXEC SQL DECLARE  part_list_cursor CURSOR FOR

         select   part_no, name, quantity

         from     part

         order by part_no;



EXEC SQL DECLARE  customer_id_list_cursor CURSOR FOR

         select   customer_id, name, address

         from     customer

         order by customer_id;



EXEC SQL DECLARE  customer_name_list_cursor CURSOR FOR

         select   name, customer_id, address

         from     customer

         order by name;



EXEC SQL DECLARE  sql_update_statement STATEMENT;



struct sqlda *sqlda;

int          sqlda_size;

int          number_of_columns;

int          column;

char         *dummy;



FILE     *file;

int      record_qty, record_no;



#ifdef NO_PROTO

void display_customers_by_id ();

void display_customers_by_name ();

void display_parts ();

void display_parts_with_variable_select ();

#else

void display_customers_by_id ();

void display_customers_by_name ();

void display_parts ();

void display_parts_with_variable_select (char *title, char *sql_statement);

#endif





EXEC SQL WHENEVER SQLERROR GOTO sqlerror_label;

EXEC SQL WHENEVER NOT FOUND GOTO not_found_label;

EXEC SQL WHENEVER SQLWARNING GOTO sqlwarning_label;



int main ()

{

   printf ("\n********************************START OF DEMO********************************\n\n");



   printf ("\n");

   printf ("This program creates the ABC Auto Part Company demo database.\n");

   printf ("The database contains:\n");

   printf ("    a short customer table,\n");

   printf ("    a simple part table,\n");

   printf ("    a shipment table,\n");

   printf ("    a shipment item table.\n");

   printf ("The database name is \"abc\".\n");

   printf ("The program shows different ways of inserting, updating and\n");

   printf ("selecting data from the database.\n\n");



   /*-------------------------------------------------------------------*/



   /*

      initialize database management system

      This is not necessary when there is no sql command executed before

      connecting to database with the dbms_connect_database function.

      It is needed here because we create the database first.

   */



  /*-------------------------------------------------------------------*/



   /* drop and re-create database */

   EXEC SQL WHENEVER SQLERROR CONTINUE;

   printf ("Dropping \"abc\" database.");

   EXEC SQL drop database abc;

   printf (" -- done\n");

   printf ("Creating database.\n");

   printf ("If this is your first database, it may take a few seconds.\n");

   EXEC SQL create database abc;

   EXEC SQL WHENEVER SQLERROR GOTO sqlerror_label;



   /*-------------------------------------------------------------------*/



   /* open database */

   printf ("Opening \"abc\" database.");

   if (DBMS_connect_database ("abc", "", 0))

   {  printf ("\"abc\" database cannot be opened.");

      return (1);

   }

	printf (" -- done\n");



   /*-------------------------------------------------------------------*/





   /* create tables */



   /* create "part" table */

   printf ("Creating \"part\" table.");

   EXEC SQL create table part (part_no  smallint not null,

                               name     asciz (21),

                               quantity integer);

   EXEC SQL commit;

   printf (" -- done\n");



   /* create "customer" table */

   printf ("Creating \"customer\" table.");

   EXEC SQL create table customer (customer_id asciz (11) not null,

                                   name        asciz (21) not null,

                                   address     asciz (21) );

	EXEC SQL commit;

   printf (" -- done\n");



   /* create "shipment" table */

   printf ("Creating \"shipment\" table.");

   EXEC SQL create table shipment (shipment_no integer not null,

                                   customer_id asciz (11) not null,

                                   date        asciz ( 9));

   EXEC SQL commit;

   printf (" -- done\n");



   /* create "shipment item" table */

   printf ("Creating \"shipment_item\" table.");

   EXEC SQL create table shipment_item (shipment_no integer  not null,

                                        part_no     smallint not null,

                                        quantity    integer);

   EXEC SQL commit;

   printf (" -- done\n");



   /* count number of tables created */

	table_count = 9999;

   EXEC SQL select count(*)

            into   :table_count

            from   rdbms_table

            where  database_name = 'abc'

            and    owner = 'user';

   printf ("%d user tables in database.\n", table_count);



   /*-------------------------------------------------------------------*/



   /* create indexes on tables */

   printf ("Creating index on \"part\".");

   EXEC SQL create unique index part_ix on part (part_no);

   EXEC SQL commit;

   printf (" -- done\n");

   printf ("Creating index on \"customer\".");

   EXEC SQL create unique index customer_ix on customer (customer_id);

   EXEC SQL commit;

   printf (" -- done\n");

   printf ("Creating indexes on \"shipment\".");

	EXEC SQL create unique index shipment_ix1 on shipment (shipment_no);

   EXEC SQL commit;

   EXEC SQL create index shipment_ix2 on shipment (customer_id);

   EXEC SQL commit;

   printf (" -- done\n");

   printf ("Creating indexes on \"shipment_item\".");

   EXEC SQL create unique index shipment_item_ix1 on shipment_item (shipment_no, part_no);

   EXEC SQL commit;

   EXEC SQL create index shipment_item_ix2 on shipment_item (part_no);

   EXEC SQL commit;

   printf (" -- done\n");



   /*-------------------------------------------------------------------*/



   /* insert parts in 3 different ways */



   /* 1 - create some parts with predefined values */

   printf ("Inserting parts with predefined values.");

   EXEC SQL insert into part (part_no, name, quantity)

            values (1010, 'starter', 52);

	EXEC SQL insert into part (part_no, name, quantity)

            values (1021, 'alternator', 95);

   EXEC SQL commit;

   printf (" -- done\n");



   /*

      2 - create more parts by reading an external file

          and using internal variables

   */



   printf ("Inserting parts from \"part.da1\".");



   /* open data file */

   if ((file = fopen ("part.da1", "r")) == NULL )

   {  printf ("\a\nUnable to open \"parts.da1\" file.\n");

      EXEC SQL WHENEVER SQLERROR CONTINUE;

      EXEC SQL disconnect database;

      return (1);

   }



	rewind (file);

   /* read list size and data, the '~' is used as a delimiter */

   fscanf (file, "%i\n", &record_qty);



   /* read part table data from file */

   /* see scanf() "C" function reference for the meaning of %[^|] */

   for (record_no = 0; record_no < record_qty; record_no++)

   {

      /* read part number, name and quantity */

      fscanf (file, "%i|", &part_no);

      fscanf (file, "%[^|]|", part_name);

      fscanf (file, "%i\n", &quantity);



      /* insert into part table */

      EXEC SQL insert into part (part_no, name, quantity)

               values (:part_no, :part_name, :quantity);

   }



   EXEC SQL commit;

   fclose (file);

	printf (" -- done\n");



   /*

      3 - create even more parts by having the dbms itself read an

          external file

   */

   printf ("Inserting parts from \"part.da2\".");

   EXEC SQL insert into part (part_no, name, quantity)

            from file 'part.da2' (integer, character, integer);

   EXEC SQL commit;

   printf (" -- done\n");



   /*-------------------------------------------------------------------*/



   /* create customers */

   printf ("Inserting customers from \"customer.dat\".");

   EXEC SQL insert into customer (customer_id, name, address)

            from file 'customer.dat' (character, character, character);

   EXEC SQL commit;

   printf (" -- done\n");



   /*-------------------------------------------------------------------*/



   /* create shipments */

   printf ("Inserting shipments from \"shipment.dat\".");

   EXEC SQL insert into shipment (shipment_no, customer_id, date)

            from file 'shipment.dat' (integer, character, character);

   EXEC SQL commit;

   printf (" -- done\n");



   /*-------------------------------------------------------------------*/



   /* create shipment items */

   printf ("Inserting shipment items from \"ship_it.dat\".");

   EXEC SQL insert into shipment_item (shipment_no, part_no, quantity)

            from file 'ship_it.dat' (integer, integer, integer);

   EXEC SQL commit;

   printf (" -- done\n");



   /*-------------------------------------------------------------------*/





   /*-------------------------------------------------------------------*/



   /* Update some customer addresses in four different ways */



   /* 1 - update customer address by using a simple SQL sql_update_statement */



   /* Let's update Gerry Goodhand's address. */

   printf ("Updating Gerry Goodhand's address.");

   EXEC SQL update customer

            set address = '104 Bellevue Dr.'

            where customer_id = 'GOO1072 ';

   printf (" -- done\n");



   /* 2 - update customer address from data in internal variables */



   /* Let's update Helen Vincent's address. */

   printf ("Updating Helen Vincent address.");

   strcpy (customer_address, "412 Alvarado Ave.");

	strcpy (customer_id, "VIN0781C");

   EXEC SQL update customer

            set address = :customer_address

            where customer_id = :customer_id;

   printf (" -- done\n");



   /* 3 - update customer address from a statement in an internal variable */



   /* Let's update Acme's address */

   printf ("Updating Acme's address.");

   strcpy (sql_statement_text, "update customer set address = '5137 42nd St.' where customer_id = 'ACM0588B'");

   EXEC SQL PREPARE sql_update_statement FROM :sql_statement_text;

   EXEC SQL EXECUTE sql_update_statement;

   printf (" -- done\n");



   /* 4 - combine the two previous examples */



   /* Let's update T&J Motor's address */

   printf ("Updating T&J Motor's address.");

   strcpy (sql_statement_text, "update customer set address = ?s where customer_id = ?s");

	strcpy (customer_address, "915 Lawrence St.");

   strcpy (customer_id, "TJX0983S");

   EXEC SQL PREPARE sql_update_statement FROM :sql_statement_text;

   EXEC SQL EXECUTE sql_update_statement USING :customer_address, :customer_id;

   printf (" -- done\n");



   /* Let's also update Alan Teng's address with the same prepared sql_update_statement */

   printf ("Updating Alan Teng's address.");

   strcpy (customer_address, "303 Eastwood Road");

   strcpy (customer_id, "TEN0289C");

   EXEC SQL EXECUTE sql_update_statement USING :customer_address, :customer_id;

   printf (" -- done\n");



   /* commit changes */

   EXEC SQL commit;

   printf ("Changes commited.\n");





   /*-------------------------------------------------------------------*/



	/* Update a part quantity by using internal variables. */

   /* Reduce spark plugs stock by 50. */

   printf ("Reducing spark plugs stock.");

   part_no = 9104;

   quantity = -50;

   EXEC SQL update part

            set quantity = quantity + :quantity

            where part_no = :part_no;

   EXEC SQL commit;

   printf (" -- done\n");



   display_parts_with_variable_select

      ("spark plugs list:",

       "select part_no, name, quantity from part where part_no = 9104");



   display_parts_with_variable_select

      ("list 1 of parts having less than 10 items:",

       "select part_no, name, quantity from part where quantity < 10");



   /*-------------------------------------------------------------------*/



      /* Simulate stock reception (by updating quantities at random) */

   /* This is done to demonstrate how to update rows within a select loop */



   printf ("Updating part quantities.");



   EXEC SQL WHENEVER SQLERROR GOTO end_of_parts;

   EXEC SQL WHENEVER SQLWARNING CONTINUE;



   /* initialize random generator used in this example */

   srand (2);



   /* do select loop */

   EXEC SQL OPEN part_cursor;

   EXEC SQL WHENEVER NOT FOUND GOTO end_of_parts;

   for (;;)

   {  EXEC SQL FETCH part_cursor into :part_no,

                                      :part_name :name_null_indicator,

                                      :quantity :quantity_null_indicator;

      /* update quantities only when they are not null */

		if (quantity_null_indicator != -1)

      {  /* update quantity */

         /* A typical program would have a more complex logic to calculate

            the new quantity. For this example, we simply use a random

            number generator. (Refer to your C compiler's manual for

            "srand" and "rand" functions).

         */

         /* This "update" statement updates the last part's row that has

				been read.

         */

         quantity += rand() % 10;

         EXEC SQL update part

                  set quantity = :quantity

                  where current of part_cursor;

      }

   }

end_of_parts:



   EXEC SQL WHENEVER SQLERROR CONTINUE;

   EXEC SQL CLOSE part_cursor;



   EXEC SQL commit;



   printf (" -- done\n");



   display_parts_with_variable_select

      ("list 2 of parts having less than 10 items:",

       "select part_no, name, quantity from part where quantity < 10");



   /*-------------------------------------------------------------------*/



   /* goto end of demo */



   goto end;



   /* error messages */



sqlerror_label:

   printf ("\nerror number %li found\n", SQLCODE);

   printf ("%s\n", (char *) DBMS_read_error (-SQLCODE, RETURN_ERROR, NULL));

	goto end;



sqlwarning_label:

   printf ("\nwarning number %li found\n", SQLCODE);

   goto end;



not_found_label:

   printf ("\nrow not found");



end:

   /* disconnect from database */

   printf ("Disconnecting database.");

   EXEC SQL WHENEVER SQLERROR CONTINUE;

   EXEC SQL disconnect database;

   printf (" -- done\n");



	printf ("\nYou can use the ISQL ABC command at the SHELL prompt\n");

   printf ("to examine and update the ABC database.\n");



   printf ("\n*********************************END OF DEMO*********************************\n");



   return (0);

}



void display_customers_by_id ()

{

   /*

      Display customer table sorted by customer id.

	*/





   printf ("\n");

   printf ("customers list, sorted by customer id.\n");

   printf ("--------------------------------------\n\n");

   printf ("id:        name:                address:\n");

   printf ("---------- -------------------- --------------------\n");



   EXEC SQL WHENEVER SQLERROR GOTO end_of_customers;

   EXEC SQL WHENEVER SQLWARNING CONTINUE;

   EXEC SQL WHENEVER NOT FOUND GOTO end_of_customers;



   EXEC SQL OPEN customer_id_list_cursor;

   for (;;)

   {  EXEC SQL FETCH customer_id_list_cursor into :customer_id,

                                                  :customer_name,

                                                  :customer_address :address_null_indicator;

      /* print id */

      printf ("%-10.10s", customer_id);



      /* print name */

      printf (" %-20.20s", customer_name);



      /* print address */

      if (address_null_indicator == -1)

         printf (" n/a\n");

      else

      printf (" %-20.20s\n", customer_address);

   }

end_of_customers:



	printf ("----------------------------------------------------\n");



   EXEC SQL WHENEVER SQLERROR CONTINUE;

   EXEC SQL CLOSE customer_id_list_cursor;



   printf ("Hit RETURN to continue.\n");

   getchar ();

   printf ("\n");

}



void display_customers_by_name ()
{
   /*
      Display customer table, sorted by name.
   */

   printf ("\n");
   printf ("customers list, sorted by name\n");
   printf ("------------------------------\n\n");
   printf ("name:                id:        address:\n");
	printf ("-------------------- ---------- --------------------\n");

   EXEC SQL WHENEVER SQLERROR CONTINUE;
   EXEC SQL WHENEVER SQLWARNING CONTINUE;
   EXEC SQL WHENEVER NOT FOUND CONTINUE;

   EXEC SQL OPEN customer_name_list_cursor;
   for (;;)
	{  EXEC SQL FETCH customer_name_list_cursor into :customer_name,
                                                    :customer_id,
                                                    :customer_address :address_null_indicator;
      if (   (SQLCODE < 0)       /* test error */
          || (SQLCODE == SQLEND) /* test end of query */ )
         break;

      /* print name */
      printf ( "%-20.20s", customer_name);

      /* print id */
      printf (" %-10.10s", customer_id);

      /* print address */
      if (address_null_indicator == -1)
         printf (" n/a\n");
      else
      printf (" %-20.20s\n", customer_address);
   }

	printf ("----------------------------------------------------\n");
   EXEC SQL WHENEVER SQLERROR CONTINUE;
   EXEC SQL CLOSE customer_name_list_cursor;

   printf ("Hit RETURN to continue.\n");
   getchar ();
   printf ("\n");
}

void display_parts ()

{

   /* Display part table */

	/* When value is null, indicate that value is not available. */



   EXEC SQL WHENEVER SQLERROR GOTO end_of_parts;

   EXEC SQL WHENEVER SQLWARNING CONTINUE;



   printf ("\n");

   printf ("part list, sorted by number\n");

   printf ("---------------------------\n\n");

	printf ("number: name:                quantity:\n");

   printf ("------- -------------------- ---------\n");



   EXEC SQL OPEN part_list_cursor;

   EXEC SQL WHENEVER NOT FOUND GOTO end_of_parts;

   for (;;)

   {  EXEC SQL FETCH part_list_cursor into :part_no,

                                           :part_name :name_null_indicator,

                                           :quantity :quantity_null_indicator;

		printf ("%6.6hi", part_no);

      if (name_null_indicator == -1)

         printf ("                   n/a");

		else

         printf ("  %-20.20s", part_name);

      if (quantity_null_indicator == -1)

         printf ("     n/a");

      else

         printf ("   %5d", quantity);

      printf ("\n");

   }

end_of_parts:



   printf ("--------------------------------------\n");

   EXEC SQL WHENEVER SQLERROR CONTINUE;

   EXEC SQL CLOSE part_list_cursor;



   printf ("Hit RETURN to continue.\n");

   getchar ();

   printf ("\n");

}



#ifdef NO_PROTO

void display_parts_with_variable_select (title, sql_statement)

char *title;

char *sql_statement;

#else

void display_parts_with_variable_select (char *title, char *sql_statement)

#endif



{   /*

      Displays parts, using a variable sql statement.

      This is an example of a fixed column list dynamic select, which means

      that the columns selected are known at compile time, but the sql

      statement itself is known only at execution time.

      For a variable list dynamic select, see program "dyn_sql.sqc".

   */



   int i;



   /*

      function parameter can't be in a "sql declare section",

      so we create a copy

   */

   EXEC SQL BEGIN DECLARE SECTION;

   char *sql_statement2 = sql_statement;

   EXEC SQL END DECLARE SECTION;



	EXEC SQL DECLARE dynamic_select_part_statement STATEMENT;

   EXEC SQL DECLARE dynamic_select_part_cursor    CURSOR FOR

						  dynamic_select_part_statement;



   EXEC SQL WHENEVER SQLERROR GOTO end_of_parts;

   EXEC SQL WHENEVER SQLWARNING CONTINUE;



   printf ("\n");

   printf ("%s\n", title);

   for (i = strlen (title); i; i--)

      printf ("-");

   printf ("\n\n");

   printf ("number: name:                quantity:\n");

   printf ("------- -------------------- ---------\n");



   EXEC SQL PREPARE dynamic_select_part_statement FROM :sql_statement2;

   EXEC SQL OPEN dynamic_select_part_cursor;

   EXEC SQL WHENEVER NOT FOUND GOTO end_of_parts;

   for (;;)

   {  EXEC SQL FETCH dynamic_select_part_cursor

							into :part_no,

                          :part_name :name_null_indicator,

                          :quantity :quantity_null_indicator;

      printf ("%6.6hi", part_no);

      if (name_null_indicator == -1)

         printf ("                   n/a");

      else

         printf ("  %-20.20s", part_name);

      if (quantity_null_indicator == -1)

         printf ("     n/a");

      else

         printf ("   %5d", quantity);

      printf ("\n");

   }

end_of_parts:



   printf ("--------------------------------------\n");

   EXEC SQL WHENEVER SQLERROR CONTINUE;

   EXEC SQL CLOSE dynamic_select_part_cursor;



   printf ("Hit RETURN to continue.\n");

   getchar ();

}


Top
Up

Just Logic Technologies Inc.
P.O. Box 63050
40 Commerce St.,
Nun's Island, Qc, H3E 1V6
Canada

email: 71563.3370@CompuServe.com

Last modification: 4/96