home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / sql / sqlspc.int < prev    next >
Encoding:
Text File  |  1988-05-03  |  42.3 KB  |  786 lines

  1.                                   ADA/SQL+:
  2.                   A STANDARD, PORTABLE ADA-DBMS INTERFACE++
  3.  
  4.  
  5.  
  6.                   Fred J. Friedman* - Bill R. Brykczynski**
  7.  
  8.  
  9.        *RACOM Computer Professionals, P.O. Box 576, Annandale, VA 22003
  10.  
  11. **Institute for Defense Analyses, 1801 N. Beauregard St., Alexandria, VA 22311
  12.  
  13.  
  14.  
  15. +  Ada  is a registered trademark of the U.S.  Government (Ada  Joint  Program
  16. Office).
  17.  
  18. ++  The work reported in this document was conducted as part of Institute  for
  19. Defense Analyses Project T-4-206 under Contract No.  MDA-903-84-C-0031 for the
  20. Department  of Defense.   The publication of this paper does not indicate  en-
  21. dorsement  by  the Department of Defense or IDA,  nor should the  contents  be
  22. construed as reflecting the official positions of those organizations.
  23.  
  24.  
  25.  
  26.                                    ABSTRACT
  27.  
  28. A  standard relational database interface for the Ada programming language  is
  29. presented.   By accessing databases through this standard interface,  Ada pro-
  30. grams may be written in a consistent and transportable fashion,  regardless of
  31. which  underlying database management system (DBMS) ultimately provides actual
  32. database support.   The Data Definition Language (DDL) serves three  purposes,
  33. with  all transformations automated to ensure consistency across uses:  (1) it
  34. is  standard  Ada,  so that data types defined therein may be  "with'ed"  into
  35. application  programs,  (2) it may be transformed into the DDL required by  an
  36. underlying  DBMS  to define an application's database,  and  (3)  it  contains
  37. augmented  information that enables it to be used to generate test data.   The
  38. Data Manipulation Language (DML), while being standard Ada, is also as similar
  39. to SQL as permitted by Ada syntax, to provide all the power and flexibility of
  40. the language proposed as the ANSI relational standard.   Major portions of the
  41. system described have actually been implemented on a prototype basis to  prove
  42. the feasibility of the approach.
  43.  
  44.  
  45.                                ACKNOWLEDGMENTS
  46.  
  47. The authors thank Col. William A. Whitaker, of the WIS JPMO, for providing the
  48. ideas  and encouragement that led this work to fruition.   The  driving  force
  49. behind  our  efforts  has been his guidance that "it can all be done  in  Ada"
  50. providing you "use the full power of Ada".   We also thank Maj.  Terry  Court-
  51. wright,  also  of the WIS JPMO,  and Dr.  John Salasin,  of the Institute  for
  52. Defense Analyses, for their fine technical direction and management support of
  53. this  effort,  ensuring that the authors had all the facilities and  resources
  54. necessary to reach a successful conclusion.
  55.  
  56.  
  57.                                  INTRODUCTION
  58.  
  59.      The  United States Department of Defense initiative  towards  programming
  60. language  standardization with Ada [1] shows great promise.   High-level plan-
  61. ners realize,  however, that standards must go beyond the basic language defi-
  62. nition in order to reduce the cost and time required for software  development
  63. and maintenance.   The standards and software developed under this effort have
  64. addressed the area of interfacing with database management systems (DBMS).   A
  65. standard DBMS interface for Ada has been developed,  consisting of both a data
  66. definition language (DDL) and a data manipulation language (DML).  Use of this
  67. standard within application programs will permit them to operate transportably
  68. with any of a variety of commercial, off the shelf (COTS) DBMSs.  In addition,
  69. tools have been developed to assist in the implementation of the standard with
  70. a new COTS DBMS, and to automatically generate test data for use during system
  71. checkout and tuning phases.
  72.  
  73.      The standard DBMS interface,  Ada/SQL,  adheres to the current version of
  74. the  proposed ANSI standard for SQL [2] as much as possible.   The  underlying
  75. DBMS need not,  however,  conform to the SQL standard; the Ada/SQL environment
  76. translates  between the standard Ada/SQL interface and that of the  underlying
  77. DBMS.
  78.  
  79.  
  80.                   COMPONENTS OF A DATABASE MANAGEMENT SYSTEM
  81.  
  82.      Every  database management system provides two main language  components,
  83. one  for data definition and one for data manipulation.   The data  definition
  84. language has traditionally been used for the one-time function of creating new
  85. databases,  and  perhaps  for modifying existing databases where such  actions
  86. were permitted.  With its definitions of tables and columns (in the relational
  87. data model),  it is used not only to define the structure of the database, but
  88. also to maintain the consistency of that structure and its contents.  It seems
  89. reasonable  to  also import the data definitions into programs  accessing  the
  90. database,  to  maintain consistency between their program variable  types  and
  91. those within the database.   This has,  however,  been implemented by very few
  92. relational  DBMSs,  undoubtedly  because the languages to which  they  provide
  93. interfaces are not strongly typed.
  94.  
  95.      Virtually  all relational database management systems provide two flavors
  96. of data manipulation language,  one available for program use of data and  one
  97. for interactive use.   It is desirable,  and most DBMSs have,  in fact, imple-
  98. mented this, that the programming language interface should be as close to the
  99. interactive interface as possible.   Programmers will very often desire to use
  100. the  interactive  interface to experiment with various data manipulation  com-
  101. mands  during  the design phases,  and to set/modify data values  for  testing
  102. programs during later development phases.   The selection of SQL as the  stan-
  103. dard  DML maximizes the number of existing DBMSs with which this desired simi-
  104. larity  between  the programming language and interactive  interfaces  can  be
  105. achieved.
  106.  
  107.  
  108.                        THE STANDARD ADA DBMS INTERFACE
  109.  
  110.      The  Ada/SQL standard Ada DBMS interface provides these two major compon-
  111. ents, a DDL and a DML, required of any database management system.
  112.  
  113.      The  DDL  is  not,  of course,  used directly to define the  contents  of
  114. databases, since it is not the DDL of any existing database management system.
  115. It is,  however, designed to be translatable into the DDLs required by typical
  116. COTS  DBMSs.   Any database schema written using the standard DDL will be  in-
  117. stantly and automatically transportable to any DBMS, providing a DDL generator
  118. is  available for the target DBMS.   Several such DDL generators have  already
  119. been written, and tools have been developed to streamline their development.
  120.  
  121.      The  second goal for a DDL mentioned above,  that of using it  to  define
  122. program data types consistent with database data types,  is achieved by having
  123. the  Ada/SQL  DDL  be standard Ada,  compiled by any validated  Ada  compiler.
  124. Application  programs  can therefore simply "with" a DDL package in  order  to
  125. immediately and consistently have all database data types defined for them.
  126.  
  127.      The DDL is also used for a third purpose,  that of automatically generat-
  128. ing  test  data  for populating databases during the program  checkout  phase.
  129. Automatically  generated test data,  in large quantities,  is also useful  for
  130. determining the performance of new DBMSs,  schemas,  and/or programs.  Certain
  131. constructs  have  been  built into the DDL to enable it to be  used  for  this
  132. purpose,  particularly to ensure that the test data generated is meaningful in
  133. terms of the application.
  134.  
  135.      The Ada/SQL standard data manipulation language is,  as noted above, SQL,
  136. or as close to it as is possible within the constraints of Ada syntax.   Since
  137. the DML is also Ada, it may be used directly within programs that are compiled
  138. by any validated Ada compiler.   In order to make this possible, functions are
  139. defined  to  build  data structures that are then used to  translate  the  SQL
  140. operations  into  the commands required by the underlying COTS  DBMS  actually
  141. storing  the database.   A mini-DBMS that uses these data structures has  been
  142. implemented,  in  order to show how they may be used to process the SQL  func-
  143. tions of SELECT, UPDATE, INSERT, and  DELETE.
  144.  
  145.  
  146.                        PORTABLE APPLICATIONS AND TOOLS
  147.  
  148.      Ada/SQL is more than just an interface specification;  it includes a  set
  149. of tools for implementing the interface with an underlying DBMS.   The way all
  150. these components fit together is shown in Figure 1.   As can be seen, applica-
  151. tion  DDL  and programs are totally transportable across  underlying  database
  152. management  systems.   This  portability  is created by tools  that  translate
  153. between the Ada/SQL standard protocols and those required by a specific under-
  154. lying DBMS.  These tools must obviously have some components that are specific
  155. to the underlying DBMS,  but they are designed such that much of their code is
  156. also transportable across DBMSs.
  157.  
  158.      The  DDL for a database application is written as one or more  Ada  pack-
  159. ages.  Application programs may "with" these packages to define the data types
  160. they will need to access the database.  A DDL generator program reads the text
  161. of  the  standard DDL to generate the DDL required to define  the  application
  162. database to the underlying DBMS.
  163.  
  164.      Once  the  database has been defined,  the application programs  may  use
  165. Ada/SQL statements to process the data stored therein.   These statements  are
  166. actually Ada subprograms which build data structures descriptive of the opera-
  167. tion performed, and/or cause execution of the operation.  Procedures executing
  168. Ada/SQL  operations  can be viewed as part of a DML converter  package,  which
  169. converts the Ada/SQL operations into the instructions required by the specific
  170. underlying  DBMS,  thereby  causing the operations to actually  be  performed.
  171. Parts  of the DML converter are transportable;  the bulk of  it  is,  however,
  172. dependent on the underlying DBMS.
  173.  
  174.      The  Ada/SQL data manipulation language includes references to table  and
  175. column names defined by the data definition language.   A SQL function genera-
  176. tor  reads the DDL and defines the necessary overloaded functions to implement
  177. these  name references.   Data types for strong typing of database  operations
  178. are  also automatically defined.   The output of the SQL  function  generator,
  179. which  consists largely of instantiations of generic functions,  is  "with'ed"
  180. into  application programs to make the functions and data types defined  visi-
  181. ble.   The data types and table/column names are independent of the underlying
  182. DBMS, so the SQL function generator is totally transportable.
  183.  
  184.      The  standard DDL package may also be read as text by a test data genera-
  185. tor tool.  The test data generator uses the augmented database descriptions of
  186. the DDL to generate meaningful test data for the application programs.   Since
  187. the test data generator uses  Ada/SQL statements  to load the database,  it is
  188. totally transportable.   Output can also be targeted for bulk load of a  data-
  189. base,  if  warranted  by the data volumes and processing  speed.   As  already
  190. noted,  large volumes of test data can also be used to derive performance fig-
  191. ures for new DBMSs, schemas, and/or programs.
  192.  
  193.      The  DDL generator,  SQL function generator,  and test data generator all
  194. read the Ada/SQL DDL.   Code to read the DDL and build descriptive data struc-
  195. tures  can  be  shared by all three components.   The prototype  was  in  fact
  196. implemented in this fashion, where code written for the SQL function generator
  197. was reused to write DDL generators for two different underlyings  DBMSs.   The
  198. test data generator has not yet been prototyped.
  199.  
  200.  
  201.                        REQUIREMENTS FOR DATA DEFINITION
  202.  
  203.      The  main  purpose of a relational data definition language is to  define
  204. the tables that will be present within a database.   Each table is named,  and
  205. consists of one or more named columns.  Each column has a particular data type
  206. for  values that may be assigned to it.   Unique keys for tables may  also  be
  207. specified,  as this can be used both for consistency checking and for perform-
  208. ance improvement.   The Ada/SQL standard DDL includes provision for specifying
  209. all  the above items,  as well as privilege and view definition (these  latter
  210. functions are not discussed here).
  211.  
  212.  
  213.                   CONCERNS OF AUTOMATIC TEST DATA GENERATION
  214.  
  215.      Additional  information  beyond  that of a typical DDL  is  required  for
  216. automatic  generation  of meaningful test data.   Column data  types  are,  of
  217. course, still required, but are now used to actively guide the data generated.
  218. In this regard, it is useful to know when the domain of one column is a subset
  219. of the domain of another.   For example, EMPLOYEE and MANAGER columns may both
  220. be of type EMPLOYEE_NAME (a strongly typed version of STRING),  but test  data
  221. should  be generated such that all MANAGERs are EMPLOYEEs,  but only some  EM-
  222. PLOYEEs are MANAGERs.
  223.  
  224.      Likewise, knowledge of key uniqueness is required to determine whether or
  225. not  duplicate  values should be generated for columns.   In  addition,  which
  226. columns  may be used for joins between tables must be known,  so  that  corre-
  227. sponding  data can be generated for join columns.   The type of join for  each
  228. pair  of columns must also be known;  whether the join is one-to-one,  one-to-
  229. many, or many-to-many.
  230.  
  231.  
  232.                        FEATURES OF THE STANDARD ADA DDL
  233.  
  234.      The Ada/SQL standard DDL upholds the Ada philosophy of strong typing,  by
  235. using Ada data types to also indicate database data types.   Since the DDL  is
  236. legal  Ada  that is "with'ed" into application programs,  this naturally  also
  237. determines the corresponding program data types.  Strong typing also indicates
  238. which columns may be joined to which others,  since join operations will  only
  239. make  sense between columns of the same data type.   A typical DBMS might only
  240. support one variety of STRING type,  but the Ada/SQL DDL,  Ada programs  using
  241. it, and the test data generator will have the benefit of knowing about EMPLOY-
  242. EE_NAMEs,  HOME_ADDRESSes,  etc.   Strong  typing will prevent a program  from
  243. comparing  an  EMPLOYEE_NAME to a HOME_ADDRESS,  and the test  data  generator
  244. will, of course, also generate different data for each type of column.
  245.  
  246.      The Ada subtype mechanism provides a convenient technique for determining
  247. how data is to be subsetted for automatic generation.   Expanding the EMPLOYEE
  248. and MANAGER example above, the Ada DDL statement
  249.  
  250.   subtype MANAGER_NAME is EMPLOYEE_NAME;
  251.  
  252. makes it obvious that MANAGERs are a subset of EMPLOYEEs.  The EMPLOYEE column
  253. would  then be of subtype EMPLOYEE_NAME,  while the MANAGER column would be of
  254. subtype MANAGER_NAME.
  255.  
  256.      Type  and subtype names may be suffixed with "_NOT_NULL" or  "_NOT_NULL_-
  257. UNIQUE"  to indicate that columns of those types should have  the  appropriate
  258. SQL  constraints.   The  test data generator will generate data in  accordance
  259. with these constraints.  For example, a column of type EMPLOYEE_NAME_NOT_NULL-
  260. _UNIQUE  might be a key for an employee roster,  and the test  data  generator
  261. would not generate any duplicate values for that column.
  262.  
  263.      As  noted above,  column types determine which columns may be joined  to-
  264. gether.   Thus,  a  column  of subtype EMPLOYEE_NAME may be joined to  one  of
  265. subtype MANAGER_NAME,  because both columns are of the same type,  although of
  266. different subtypes.   The uniqueness constraints given by the type and subtype
  267. definitions determine the type of join performed,  and hence the nature of the
  268. test data generated.   Joins between two unique columns are one-to-one,  those
  269. between  one unique and one non-unique column are one-to-many (the "one"  side
  270. is  obviously on the unique column),  and joins between two non-unique columns
  271. are many-to-many.
  272.  
  273.      Subsetting, as indicated by subtype, determines whether a join will match
  274. all  values  in a column or whether some values will  not  have  corresponding
  275. matches  in  the other join column.   There are three possibilities:  (1)  all
  276. values in each join column have corresponding value(s) in the other,  (2)  one
  277. join  column has values that are a subset of the other,  and (3) although some
  278. values  in  each join column overlap,  both columns have values that  are  not
  279. present  in  the other.   The Ada DDL instructing the test data  generator  to
  280. produce data appropriate for each of these three cases is as follows:
  281.  
  282. (1) -- no special DDL required,
  283.     -- both columns of subtype A
  284.  
  285. (2) subtype B is A;
  286.     -- subset column of subtype B,
  287.     -- other column of subtype A
  288.  
  289. (3) subtype A is COMMON_TYPE;
  290.     subtype B is COMMON_TYPE;
  291.     -- one column of subtype A,
  292.     -- other of subtype B
  293.  
  294. Two  subtypes,  one derived directly from the other and with  names  differing
  295. only  in the "_NOT_NULL" or "_NOT_NULL_UNIQUE" suffixes,  will not be  subset,
  296. and  are considered by the test data generator to be the same subtype for  all
  297. purposes  except uniqueness and the null value possibility.   Thus,  given the
  298. following DDL:
  299.  
  300.   type EMPLOYEE_NAME is new STRING(1..20);
  301.   subtype EMPLOYEE_NAME_NOT_NULL_UNIQUE is EMPLOYEE_NAME;
  302.   subtype MANAGER_NAME is EMPLOYEE_NAME_NOT_NULL_UNIQUE;
  303.  
  304. Columns  of subtype EMPLOYEE_NAME and EMPLOYEE_NAME_NOT_NULL_UNIQUE will  have
  305. the  same range of values generated for them,  except that null and  duplicate
  306. values will be generated for EMPLOYEE_NAME columns but not for EMPLOYEE_NAME_-
  307. NOT_NULL_UNIQUE columns.   Only a subset of these values will be generated for
  308. columns  of subtype MANAGER_NAME.   The MANAGER_NAME subtype does not  inherit
  309. the unique or null constraints from EMPLOYEE_NAME_NOT_NULL_UNIQUE;  the actual
  310. subtype  name  must include the suffix in order for the constraints to  apply.
  311. The declaration for MANAGER_NAME is therefore equivalent,  for test data gene-
  312. ration purposes, to the following declaration
  313.  
  314.   subtype MANAGER_NAME is EMPLOYEE_NAME;
  315.  
  316.      Database  rows are indicated by Ada records in the Ada/SQL standard  DDL,
  317. which is a most natural notation.  Database columns are therefore represented,
  318. more or less, by the components of the Ada records.  Ada records may, however,
  319. have  components which are themselves records,  and most DBMSs do not  support
  320. this subrecord concept.  When encountering a subrecord, the DDL generator will
  321. expand it into its components,  as many levels down as necessary,  to  produce
  322. the  non-composite column descriptions required by the DDL of the target DBMS.
  323. Subrecords may be used advantageously in two ways: (1) they provide handy data
  324. types for items which are almost always processed together,  such as  latitude
  325. and  longitude,  and  (2) they may be used to indicate uniqueness  constraints
  326. over  groups of columns (composite keys),  even though each individual  column
  327. within the group may not have unique values.
  328.  
  329.  
  330.                            THE STANDARD DDL IS ADA
  331.  
  332.      Figure  2 shows a sample database specification in the  standard  Ada/SQL
  333. DDL.   The tables defined are a small part of an illustrative database used in
  334. [3].   As already stated, Ada record types are used to indicate the columns of
  335. database  tables,  as  well  as programming language subrecords  within  those
  336. columns.  The PARCELS and PARCEL_ACCOUNTS record types define database tables,
  337. since  they  are not used as subrecords of any other records.   On  the  other
  338. hand,  the PARCEL_TRANSACTION_KEY record is used as a subrecord within another
  339. record, so the DDL generator will not produce a database table for it.
  340.  
  341.      PARCEL_TRANSACTION_KEY_NOT_NULL_UNIQUE  is  used to  designate  a  unique
  342. composite  key (group of columns indicated by a subrecord) within the PARCEL_-
  343. ACCOUNTS table.  Another use of subtyping to indicate uniqueness is illustrat-
  344. ed  by the ASSESSOR_PARCEL_NUMBER_NOT_NULL_UNIQUE subtype.   The example  does
  345. not include a use of subtyping to show subsetting for test data generation.
  346.  
  347.      In the example,  all type definitions used for the database are  included
  348. within a single package.   This is not necessary; packages of type definitions
  349. may  be "with'ed" into database definitions,  as into any Ada  packages.   The
  350. Ada/SQL  DDL  also  includes a facility for combining table  definitions  from
  351. several  packages  into a single database schema.   Database  definitions  may
  352. therefore be organized in logical,  modular fashion.  Defining logically sepa-
  353. rate parts of a database in separate packages may reduce the number of  appli-
  354. cation  program  recompilations  required by changes to the  data  definition,
  355. since  only users of the affected packages must be  adjusted.   Each  separate
  356. package may also be viewed as a subschema, defining and enabling operations on
  357. only  a  portion of the database.   Views and privileges may also be  used  to
  358. define  subschemas  and protections for different classes of users of a  data-
  359. base.
  360.  
  361.  
  362.                      THE STANDARD ADA DML LOOKS LIKE SQL
  363.  
  364.      Several representative statements from the Ada/SQL standard data  manipu-
  365. lation  language  are  shown in Figure 3.   All examples except the  last  are
  366. recodings of SQL statements used in [3].   As part of developing the DML,  all
  367. the  functions necessary to process every example in the book were  coded  and
  368. executed,  as  verification of the versatility and completeness of the Ada/SQL
  369. DML.
  370.  
  371.      It is surprising how close we can come to SQL using Ada syntax (remember,
  372. these  examples  are excerpts from actual programs that may be compiled  by  a
  373. validated Ada compiler and then executed),  but certain minor concessions did,
  374. of  course,  have  to be made due to the natures of the  two  languages.   For
  375. example,  the SQL keywords SELECT and DECLARE are also reserved words in  Ada,
  376. so  the corresponding Ada/SQL subprograms are called SELEC and  DECLAR.   And,
  377. the arguments to the subprograms must have parentheses surrounding them (open-
  378. ing on line 1 and closing on line 9,  for example), whereas no parentheses are
  379. used  in  SQL.   The same naturally holds true for arguments  to  INSERT_INTO,
  380. UPDATE,  and  DELETE_FROM.   The necessity to join separate words with  under-
  381. scores  to make them single identifiers in Ada is also apparent in CURSOR_FOR,
  382. GROUP_BY, ORDER_BY, INSERT_INTO, and DELETE_FROM.
  383.  
  384.      Lists  of  items  in SQL are separated by commas,  in  Ada/SQL  they  are
  385. separated  by  ampersands,  since the ampersand can be overloaded  as  an  Ada
  386. function  whereas the comma cannot be.   Examples of such lists can be seen in
  387. the following clauses:  SELECT (line 2),  FROM (line 3),  GROUP BY (no example
  388. shown),  ORDER  BY (no example shown),  and the INSERT INTO column list  (line
  389. 22).   For INSERT INTO value lists (line 24) the "and" operator is used as the
  390. connective.  STRINGs would often be used as values, and using ampersands would
  391. have  required redefining the array catenation operator,  which is often  used
  392. with  STRINGs.   UPDATE  SET clauses (lines 27 and 28) are also  separated  by
  393. "and",  in order to achieve the correct precedence between clauses.   "<="  is
  394. used within each clause to indicate assignment of a value to a column,  and an
  395. operator  of lower precedence (i.e.,  not ampersand) must therefore be used to
  396. separate clauses.
  397.  
  398.      The various SQL clauses become subprogram parameters in  Ada/SQL.   Thus,
  399. the  clause  names  must be followed by the Ada parameter  association  symbol
  400. "=>", and the clauses must be separated by commas.
  401.  
  402.      Perhaps  the greatest concession in Ada/SQL was required by the  restric-
  403. tions on overloading the Ada equality and inequality operators ("=" and "/=").
  404. Ada/SQL functions return data structures,  but these Ada operators can only be
  405. overloaded to return BOOLEAN,  with operands of the same type.   Hence,  it is
  406. necessary for Ada/SQL to write "A=B" as EQ(A,B).  This is required for compar-
  407. ison operators (see,  for example,  lines 4 and 5) and is the reason that "<="
  408. is used instead of "=" for setting UPDATE values (lines 27 and 28).  Other SQL
  409. comparison and arithmetic operators that can be redefined in Ada are expressed
  410. in their natural fashion, however (line 8 shows an example of the greater than
  411. operator).   SQL functions translate directly to Ada (see, for example, SUM on
  412. lines  2 and 8),  but infix operators that have no equivalent in Ada  must  be
  413. written as Ada prefix functions (e.g., LIKE on line 6).
  414.  
  415.      Several  other  minor concessions were also required.   For  example,  an
  416. asterisk cannot stand by itself in Ada, as in "SELECT *" or "COUNT(*)", so the
  417. asterisk  is  instead made into a character  literal  (line  15).   Also,  Ada
  418. strings  are delimited by double quotes instead of the single quotes (apostro-
  419. phes) used by SQL.
  420.  
  421.      Even with all these concessions the similarity between SQL and Ada/SQL is
  422. remarkable.   This is because the Ada language provides many features that can
  423. be exploited for Ada/SQL.  Already noted were the use of subprogram and param-
  424. eter names for SQL clause names,  the direct translation of SQL functions such
  425. as  SUM into corresponding Ada functions,  and the redefinition of  arithmetic
  426. and comparison operators other than equality and inequality.  The redefinition
  427. of operators also applies to the boolean operators of "and",  "or", and "not",
  428. so  that predicates can be joined in their most natural fashion.   The use  of
  429. functions  for Ada/SQL operators and SELECT statements allows nested  queries,
  430. as with the EXISTS example beginning on line 11.
  431.  
  432.      Database  table and column names are also functions (defined by  the  SQL
  433. function  generator from the DDL),  overloaded to return objects of the appro-
  434. priate type depending on the context in which they are used.   The Ada  record
  435. component  selection  operator  (period) corresponds precisely  with  the  SQL
  436. column  selection operator,  so qualified columns can be directly indicated in
  437. Ada (see, for example, line 17.  PARCELS.APN is a column name qualified with a
  438. table  name.   The  notation KEY.APN selects the KEY column  in  the  PARCEL_-
  439. ACCOUNTS table by SQL semantics, then the APN subcolumn by Ada semantics.)
  440.  
  441.  
  442.                  THE DML AND DDL ARE TIED TOGETHER BY ADA/SQL
  443.  
  444.      The examples thus far did not include the use of program variables within
  445. SQL statements,  but that is very straightforward.   Any constant in the exam-
  446. ples  can  obviously  be replaced with a program variable;  it  is  merely  an
  447. argument  to a subprogram.   In short,  program variables may be used anywhere
  448. they are semantically meaningful.   There is no need (and no  possibility,  in
  449. fact)  to differentiate program variables from database columns with a  prefix
  450. such as the colon used by SQL.   Of course,  this does mean that program vari-
  451. ables  may  not have the same names as database tables or  columns,  but  this
  452. should  not be a major problem.   If record program variables are defined  for
  453. each table in the database,  using the types declared in the standard Ada DDL,
  454. then the record component names will be the same as the database column names.
  455. Continuing with the road association example,  the program/PDL shown in Figure
  456. 4  illustrates the naturalness of this approach and the tie-in between the DDL
  457. and the DML.
  458.  
  459.      The  ROAD_ASSOCIATION_SCHEMA package "with'ed" on line 1 is the  standard
  460. Ada  DDL  already discussed,  defining record types for the  road  association
  461. database.   The ROAD_ASSOCIATION package on line 2 contains the definitions of
  462. all  Ada/SQL  functions (table and column names,  and overloaded functions  on
  463. unique  data types) for the road association database.   It  is  automatically
  464. generated  from  the standard Ada DDL by the SQL function  generator.   A  use
  465. clause is not used for ROAD_ASSOCIATION_SCHEMA,  defining record types, but is
  466. used for ROAD_ASSOCIATION, defining table names, because the automatic genera-
  467. tion  procedures  cause table names to be homographs of database  record  type
  468. names.   Table  names  are used in all Ada/SQL operations,  while record  type
  469. names are used only in declarations.   Since the former use is expected to  be
  470. more  frequent than the latter,  table names are made directly visible,  while
  471. the  record  type names are visible only  by  selection.   The  SQL_OPERATIONS
  472. package  on line 3 contains the standard Ada/SQL subprograms,  such as  SELEC,
  473. and  operators  not  dependent on data types,  such as the AND used  to  build
  474. search conditions.
  475.  
  476.      Line 6 shows how the standard DDL may be used within a program.  PARCELS,
  477. in the ROAD_ASSOCIATION_SCHEMA package,  is a definition of a record type used
  478. within  the database.   The CURRENT_PARCEL object of that type is the  logical
  479. choice into which to retrieve tuples from the corresponding table.  The CURSOR
  480. declared  on  line 7 is used with the DML to fetch successive  tuples  from  a
  481. retrieved table.   The exact fetch mechanism used is not shown here; it paral-
  482. lels the SQL FETCH-INTO operation.
  483.  
  484.      Procedure SHOW_PARCELS_ON_ROAD asks the user to select a road (the PDL on
  485. line 9),  queries the database for information on parcels on the selected road
  486. (the query is set up by the Ada/SQL on lines 10-13),  and displays information
  487. on  all parcels on the selected road (the PDL on lines 14-15 would turn into a
  488. loop in the actual code).   Within the Ada/SQL query,  PARCELS is the name  of
  489. the  database  table generated from the PARCELS record type definition in  the
  490. DDL.  PARCELS.ROAD is the ROAD column in the PARCELS database table; CURRENT_-
  491. PARCEL.ROAD is the ROAD component in the CURRENT_PARCEL program  object.   The
  492. way  in  which  the functions and other declarations are set  up  causes  this
  493. distinction to be automatically maintained by the Ada compiler.
  494.  
  495.  
  496.                           ADA/SQL DML IMPLEMENTATION
  497.  
  498.      The preceding discussion of Ada/SQL DML examples presented details of the
  499. strategy for implementing the SQL language within pure Ada code.  This section
  500. concisely recapitulates the major ideas discussed.
  501.  
  502.      Subprograms  are  defined for the basic SQL statements,  such as  SELECT.
  503. The parameters of these subprograms are given the same names as the SQL clause
  504. keywords,  so  that named parameter associations use the SQL clause  keywords.
  505. Functions are also defined for those SQL operations,  such as the AND used  to
  506. build search conditions, that do not depend on database-unique data types.
  507.  
  508.      Operations,  such  as EQ,  that must be defined on user data  types,  are
  509. defined  generically.   The SQL function generator automatically generates in-
  510. stantiations  of these functions based on the data types declared  within  the
  511. standard Ada DDL.
  512.  
  513.      The  SQL  function generator also writes functions (most are generic  in-
  514. stantiations) corresponding to database table names and column  names.   These
  515. functions are overloaded based on the type of result returned; the Ada compil-
  516. er  selects the correct version based on context.   For example,  a table name
  517. function  returns  a very simple data structure (an indication  of  the  table
  518. name) when used within a FROM list.   When used to qualify a column,  however,
  519. as with PARCELS.APN, the table name function (PARCELS in this case) returns an
  520. access  value designating a record object.   The record object has one  appro-
  521. priately  named  component for each column in the corresponding  table.   Each
  522. component (such as APN) is a data structure describing both the table name and
  523. the column name.   The SQL function generator is totally transportable,  since
  524. all the functions it produces are independent of the underlying DBMS.
  525.  
  526.  
  527.                  COMPILE-TIME CHECKING OF OPERATOR FUNCTIONS
  528.  
  529.      Writing SQL within Ada enables the Ada compiler to perform type  checking
  530. on  database  columns just as it does on program  variables.   This  naturally
  531. improves the reliability and maintainability of the resultant programs.
  532.  
  533.      Using  the  road association example again,  the Ada compiler  would  not
  534. permit a programmer to say
  535.  
  536.   EQ(PARCELS.ROAD,"I don't know")
  537.  
  538. for  example.   PARCELS.ROAD returns a data structure describing the  database
  539. column  selected.   The  type of this data structure is derived from the  base
  540. type  of all such data structures,  specifically to correspond to the type  of
  541. the column.  Since the PARCELS.ROAD column is of type ROAD_DESIGNATOR, the SQL
  542. function generator might produce
  543.  
  544.   type ROAD_DESIGNATOR_COLUMN is new COLUMN;
  545.  
  546. Code  would then be generated to instantiate the EQ function,  as well as  all
  547. other  appropriate  ones,  to allow comparisons between database  columns  and
  548. program variables of type ROAD_DESIGNATOR:
  549.  
  550.   function EQ is new BINARY_OPERATOR(O_EQ,
  551.    ROAD_DESIGNATOR_COLUMN,ROAD_DESIGNATOR_COLUMN);
  552.  
  553.   function EQ is new BINARY_OPERATOR(O_EQ,
  554.    ROAD_DESIGNATOR_COLUMN,ROAD_DESIGNATOR);
  555.  
  556.   function EQ is new BINARY_OPERATOR(O_EQ,
  557.    ROAD_DESIGNATOR,ROAD_DESIGNATOR_COLUMN);
  558.  
  559. BINARY_OPERATOR  is a generic function for defining (not surprisingly)  binary
  560. operators.   Its  first argument is an opcode (an enumeration type  indicating
  561. the type of operation performed) to be placed into the data structure returned
  562. by  the operator function.   The next two arguments are the types of the  left
  563. and right operands,  respectively, of the binary operator.  (This also applies
  564. to the two parameters,  in order,  of an operator,  such as EQ,  which must be
  565. written using Ada prefix function notation.)  The first instantiation  enables
  566. programs to compare two database columns of type ROAD_DESIGNATOR,  which would
  567. most  likely  be used for joining tables.   The remaining  two  instantiations
  568. enable  programs to compare database columns with program objects and literals
  569. of  type  ROAD_DESIGNATOR.   As a convenience,  either order of  the  database
  570. column and the program object is permitted.   As can be seen,  there is no  EQ
  571. function  defined  for comparing ROAD_DESIGNATOR_COLUMNs with string  objects,
  572. which  is why the Ada compiler would not permit the erroneous statement  noted
  573. above.
  574.  
  575.      Another  function  of operators such as EQ is to  convert  their  program
  576. object  operand (if any) to an internal representation that is independent  of
  577. any user-defined data types.   This is required so that the underlying Ada/SQL
  578. routines  can operate on data types known to them;  they do not know about any
  579. user-defined  data  types.   (The underlying routines are independent  of  any
  580. specific database content.)  The conversion is simple for  integer,  real,  or
  581. string  types -- values are just converted to the appropriate predefined type.
  582. Enumeration,  array,  and  record types require data structures  to  represent
  583. values.
  584.  
  585.      Much compile-time checking of SQL syntax is also provided by appropriate-
  586. ly defining the Ada/SQL operators.   If, for example, the EQ operator returned
  587. a result of type SEARCH_CONDITION, then the AND operator would be defined only
  588. for  objects of type SEARCH_CONDITION.   (Other definitions of "and" are  pro-
  589. vided  for use within insert value lists and update set clauses,  but they are
  590. not germaine to this discussion.)  This would make a use such as
  591.  
  592.   WHERE => EQ(..) AND EQ(..)
  593.  
  594. legal, while
  595.  
  596.   WHERE => "hello" AND "goodbye"
  597.  
  598. would be rejected by the compiler.
  599.  
  600.      Similar  syntax  checking is applicable to lists  of  items.   A  typical
  601. example  is  the GROUP BY clause,  which requires lists of column  names.   By
  602. defining the ampersand operator correctly, the compiler will accept
  603.  
  604.   GROUP_BY => ROAD & OWNER
  605.  
  606. but will reject
  607.  
  608.   GROUP_BY => ROAD & 7
  609.  
  610.  
  611.                                    SUMMARY
  612.  
  613.      There  are  several  objectives that are important for  an  Ada  database
  614. interface.   The  interface should be portable by virtue of database  indepen-
  615. dence,  so  that  application programs using the interface can be run  on  any
  616. computer system using any underlying DBMS.   Details of using a specific  DBMS
  617. should be the concern of the interface implementation,  not of the application
  618. programs.   The  interface should be written using pure Ada,  in line with the
  619. philosophy of not subsetting or extending the language.  It should be designed
  620. so that the resulting code satisfies the readability,  reliability,  and main-
  621. tainability objectives of Ada itself.
  622.  
  623.      Ada/SQL clearly satisfies these objectives.   It also provides the  addi-
  624. tional advantage of being compatible with the SQL language,  which is not only
  625. the  most  widely used relational database language,  but which has also  been
  626. proposed as the ANSI standard language for relational databases.
  627.  
  628.  
  629.                                   REFERENCES
  630.  
  631. [1] Military Standard: Ada Programming Language, ANSI/MIL-STD-1815A, 1983.
  632.  
  633. [2] Draft  Proposed American National Standard:  Database Language  SQL.   New
  634.     York, NY: American National Standards Institute, Inc., 1985.
  635.  
  636. [3] C.J. Date, Database: A Primer.  Reading, MA: Addison-Wesley, 1983.
  637.  
  638. ------------------------------------------------------------------------------
  639.  
  640.       +--------------------------------------------------+
  641.       |                       with                       |
  642.       |                                                 \|/
  643.     +-+-----+   * Legend in block     +-------+    +-----------+
  644.    /       +--+   to right:          / SQL   /     |Application|  Totally
  645.   /  DDL  /   |   SQL Function +--->/ Func  +----->|Program    |  Portable
  646.  /       +--+ |   Instan-      |   / Inst  / with  |           |  Applications
  647. +-----+-+   | |   tiations     |  +-------+        +-----+-----+
  648.       |     | |                |                         |
  649. - - - | - - | | Data  - - - -  |  - - - - - - - - - - -  |  - - - - - - - - -
  650.       |     | |                |                         |
  651.  Data |     | |  +-----------+ |  +-----------+          | Call
  652.       |     | |  | SQL       +-+  | Test      |          |        Totally
  653.       |     | +->| Function  |    | Data      |          |        Portable
  654.      \|/     \   | Generator | +->| Generator |         \|/       Tools
  655. +-----------+ \  +-----------+ |  +-----+-----+    +-----------+
  656. | DDL       |  +---------------+        |          | DML       |
  657. | Generator | -      Data       - - - - +--------->| Converter |  - - - - - -
  658. |           |                              Call    |           |
  659. +-----+-----+                                      +-----+-----+
  660.       |                                                  |        DBMS-
  661.       |                                                  |        Specific
  662.       |                                                  |        Tools
  663.       |                                                  |
  664.       |                                                  |
  665. - - - | - - - - - - - - - - - - - - - - - - - - - - - -  |  - - - - - - - - -
  666.       |                                                  |
  667.      \|/                                                \|/
  668.   COTS DBMS                                          COTS DBMS    COTS DBMS
  669.      DDL                                             DML Calls
  670.  
  671.  
  672.                     Figure 1.  Ada/SQL Portability Design
  673.  
  674. ------------------------------------------------------------------------------
  675.  
  676.  1.package ROAD_ASSOCIATION_SCHEMA is
  677.  2.
  678.  3.  type ASSESSOR_PARCEL_NUMBER is new STRING(1..9);
  679.  4.  subtype ASSESSOR_PARCEL_NUMBER_NOT_NULL_UNIQUE
  680.  5.   is ASSESSOR_PARCEL_NUMBER;
  681.  6.
  682.  7.  type ROAD_DESIGNATOR is (REDWOOD, CREEK, MILL);
  683.  8.  type OWNER_NAME is new STRING(1..20);
  684.  9.  type IMPROVED_FLAG is (Y,N);
  685. 10.  type ENTRY_NUMBER is range 1 .. 99999;
  686. 11.  type MONEY is delta 0.01 range -99_999.99 .. 99_999.99;
  687. 12.  type CALENDAR_DATE is new STRING(1..6);
  688. 13.  type TRANSACTION_DESCRIPTION is new STRING(1..20);
  689. 14.  type TRANSACTION_TYPE is (CHARGE, CREDIT);
  690. 15.
  691. 16.  type PARCEL_TRANSACTION_KEY is
  692. 17.    record
  693. 18.      APN    : ASSESSOR_PARCEL_NUMBER;
  694. 19.      EN_TRY : ENTRY_NUMBER;
  695. 20.    end record;
  696. 21.
  697. 22.  subtype PARCEL_TRANSACTION_KEY_NOT_NULL_UNIQUE
  698. 23.   is PARCEL_TRANSACTION_KEY;
  699. 24.
  700. 25.  type PARCELS is
  701. 26.    record
  702. 27.      APN        : ASSESSOR_PARCEL_NUMBER_NOT_NULL_UNIQUE;
  703. 28.      ROAD       : ROAD_DESIGNATOR;
  704. 29.      OWNER      : OWNER_NAME;
  705. 30.      IMPROVED   : IMPROVED_FLAG;
  706. 31.      LAST_ENTRY : ENTRY_NUMBER;
  707. 32.      BALANCE    : MONEY;
  708. 33.    end record;
  709. 34.
  710. 35.  type PARCEL_ACCOUNTS is
  711. 36.    record
  712. 37.      KEY         : PARCEL_TRANSACTION_KEY_NOT_NULL_UNIQUE;
  713. 38.      DATE        : CALENDAR_DATE;
  714. 39.      DESCRIPTION : TRANSACTION_DESCRIPTION;
  715. 40.      TY_PE       : TRANSACTION_TYPE;
  716. 41.      AMOUNT      : MONEY;
  717. 42.      BALANCE     : MONEY;
  718. 43.    end record;
  719. 44.  .
  720. 45.   .
  721. 46.    .
  722. 47.end ROAD_ASSOCIATION_SCHEMA;
  723.  
  724.  
  725.                       Figure 2.  The Standard DDL is Ada
  726.  
  727. ------------------------------------------------------------------------------
  728.  
  729.  1. DECLAR ( CURSOR , CURSOR_FOR =>
  730.  2.   SELEC   ( PARCELS.OWNER & SUM(PARCEL_ACCOUNTS.AMOUNT),
  731.  3.   FROM   => PARCELS & PARCEL_ACCOUNTS,
  732.  4.   WHERE  => EQ(PARCELS.APN,PARCEL_ACCOUNTS.KEY.APN)
  733.  5.   AND       EQ(PARCEL_ACCOUNTS.TY_PE,CREDIT)
  734.  6.   AND       LIKE(PARCEL_ACCOUNTS.DATE,"82%"),
  735.  7.   GROUP_BY  => PARCELS.OWNER,
  736.  8.   HAVING    => SUM(PARCEL_ACCOUNTS.AMOUNT) > 500.00,
  737.  9.   ORDER_BY  => PARCELS.OWNER ) );
  738. 10.
  739. 11. DECLAR ( CURSOR , CURSOR_FOR =>
  740. 12.   SELEC  ( APN & OWNER,
  741. 13.   FROM  => PARCELS,
  742. 14.   WHERE => EXISTS
  743. 15.          ( SELEC  ( '*',
  744. 16.            FROM  => PARCEL_ACCOUNTS,
  745. 17.            WHERE => EQ(KEY.APN,PARCELS.APN)
  746. 18.            AND      EQ(TY_PE,CREDIT)
  747. 19.            AND      AMOUNT > 499.99 ) ) ) );
  748. 20.
  749. 21. INSERT_INTO ( PARCELS
  750. 22.  ( APN & ROAD & OWNER & IMPROVED & LAST_ENTRY & BALANCE ),
  751. 23. VALUES
  752. 24.  ( "93-282-55" and CREEK and "I.J.KING" and Y and 1 and 120.00 ) );
  753. 25.
  754. 26. UPDATE ( PARCELS,
  755. 27. SET   => LAST_ENTRY <= 24
  756. 28.      and BALANCE    <= 0.00 ,
  757. 29. WHERE => EQ(APN,"93-282-55") );
  758. 30.
  759. 31. DELETE_FROM ( PARCEL_ACCOUNTS,
  760. 32.      WHERE => DATE < "84" );
  761.  
  762.  
  763.                 Figure 3. The Standard Ada DML Looks Like SQL
  764.  
  765. ------------------------------------------------------------------------------
  766.  
  767.  1. with ROAD_ASSOCIATION_SCHEMA;
  768.  2. with ROAD_ASSOCIATION; use ROAD_ASSOCIATION;
  769.  3. with SQL_OPERATIONS; use SQL_OPERATIONS;
  770.  4.
  771.  5. procedure SHOW_PARCELS_ON_ROAD is
  772.  6.   CURRENT_PARCEL : ROAD_ASSOCIATION_SCHEMA.PARCELS;
  773.  7.   CURSOR         : CURSOR_NAME;
  774.  8. begin
  775.  9.   read CURRENT_PARCEL.ROAD from user
  776. 10.   DECLAR ( CURSOR , CURSOR_FOR =>
  777. 11.     SELEC  ( '*',
  778. 12.     FROM  => PARCELS,
  779. 13.     WHERE => EQ(PARCELS.ROAD,CURRENT_PARCEL.ROAD) ) );
  780. 14.   fetch successive database records into CURRENT_PARCEL, displaying
  781. 15.    information on parcels on the selected road to the user
  782. 16. end SHOW_PARCELS_ON_ROAD;
  783.  
  784.  
  785.                  Figure 4. Relation of DDL and DML in Ada/SQL
  786.