1% APQ-\apqversion Manual
2
3\documentclass[english,letterpaper]{book}
4\usepackage{times}
5\usepackage[T1]{fontenc}
6\usepackage[latin1]{inputenc}
7\usepackage{longtable}
8\usepackage{amsmath}
9\usepackage{amssymb}
10
11\usepackage{floatflt}
12\usepackage{fancyhdr}
13
14\pagestyle{fancy}
15
16%\lhead{}
17%\chead{}
18\rhead{}
19
20\lfoot{}
21\cfoot{\thepage}
22\rfoot{APQ \apqversion}
23
24
25\newcommand\Ref[1]{\textsection\ref{#1} (page~\pageref{#1})}
26
27\usepackage{fancyvrb}
28
29\usepackage{makeidx}
30\makeindex
31
32\IfFileExists{url.sty}{\usepackage{url}}
33                      {\newcommand{\url}{\texttt}}
34
35\makeatletter
36
37\usepackage{babel}
38\makeatother
39
40
41
42%==========%
43% HYPERREF %
44%==========%
45\usepackage[bookmarks, colorlinks, breaklinks, pdftitle={APQ User Manual},
46    pdfauthor={KOW Framework Project}]{hyperref}
47\hypersetup{
48	linkcolor=DarkSkyBlue,
49	citecolor= DarkSkyBlue,
50	filecolor= DarkSkyBlue,
51	urlcolor= DarkSkyBlue
52}
53
54
55
56%========================%
57% Listings Package Setup %
58%========================%
59\usepackage{xcolor}
60\usepackage{listings}
61\usepackage{caption}
62
63
64% COLORS (Tango)
65\definecolor{LightButter}{rgb}{0.98,0.91,0.31}
66\definecolor{LightOrange}{rgb}{0.98,0.68,0.24}
67\definecolor{LightChocolate}{rgb}{0.91,0.72,0.43}
68\definecolor{LightChameleon}{rgb}{0.54,0.88,0.20}
69\definecolor{LightSkyBlue}{rgb}{0.45,0.62,0.81}
70\definecolor{LightPlum}{rgb}{0.68,0.50,0.66}
71\definecolor{LightScarletRed}{rgb}{0.93,0.16,0.16}
72\definecolor{Butter}{rgb}{0.93,0.86,0.25}
73\definecolor{Orange}{rgb}{0.96,0.47,0.00}
74\definecolor{Chocolate}{rgb}{0.75,0.49,0.07}
75\definecolor{Chameleon}{rgb}{0.45,0.82,0.09}
76\definecolor{SkyBlue}{rgb}{0.20,0.39,0.64}
77\definecolor{Plum}{rgb}{0.46,0.31,0.48}
78\definecolor{ScarletRed}{rgb}{0.80,0.00,0.00}
79\definecolor{DarkButter}{rgb}{0.77,0.62,0.00}
80\definecolor{DarkOrange}{rgb}{0.80,0.36,0.00}
81\definecolor{DarkChocolate}{rgb}{0.56,0.35,0.01}
82\definecolor{DarkChameleon}{rgb}{0.30,0.60,0.02}
83\definecolor{DarkSkyBlue}{rgb}{0.12,0.29,0.53}
84\definecolor{DarkPlum}{rgb}{0.36,0.21,0.40}
85\definecolor{DarkScarletRed}{rgb}{0.64,0.00,0.00}
86\definecolor{Aluminium1}{rgb}{0.93,0.93,0.92}
87\definecolor{Aluminium2}{rgb}{0.82,0.84,0.81}
88\definecolor{Aluminium3}{rgb}{0.73,0.74,0.71}
89\definecolor{Aluminium4}{rgb}{0.53,0.54,0.52}
90\definecolor{Aluminium5}{rgb}{0.33,0.34,0.32}
91\definecolor{Aluminium6}{rgb}{0.18,0.20,0.21}
92
93
94
95
96\lstset{
97	keywordstyle=[1]{\color{DarkSkyBlue}},
98	keywordstyle=[2]{\color{DarkScarletRed}},
99	keywordstyle=[3]{\bfseries},
100	keywordstyle=[4]{\color{DarkPlum}},
101	keywordstyle=[5]{\color{SkyBlue}},
102	commentstyle={\color{Aluminium4}\tiny},
103	stringstyle={\color{Chocolate}},
104	tabsize=4,
105	breaklines=true,
106	basicstyle={\ttfamily\tiny},
107	xleftmargin=21pt,
108	xrightmargin=11pt,
109	frame=single,
110	rulecolor=\color{black!30},
111	captionpos=b,
112	framesep=10pt,
113	framexleftmargin=18pt,
114	numbers=none,
115	numberstyle={\tiny},
116	stepnumber=1,
117	numbersep=15pt
118}
119
120
121
122\lstdefinelanguage{Ada}{%
123	morekeywords={alfa,and,array,begin,boolean,byte,case,char,const,div,%
124	do,downto,else,end,false,file,for,function,get,goto,if,in,%
125	integer,label,maxint,mod,new,not,of,or,pack,packed,page,program,%
126	procedure,put,read,readln,real,record,repeat,reset,rewrite,set,%
127	text,then,to,true,type,unpack,until,var,while,with,write,writeln},%
128	sensitive=false,%
129	morecomment=[s]{(*}{*)},%
130	morecomment=[s]{\{}{\}},%
131	morestring=[d]{'}%
132}
133\lstdefinelanguage{SQL}{%
134	morekeywords={select,insert,table,from,into,create,delete,alfa,and,array,begin,boolean,byte,case,char,const,div,%
135	do,downto,else,end,false,file,for,function,get,goto,if,in,%
136	integer,label,maxint,mod,new,not,of,or,pack,packed,page,program,%
137	procedure,put,read,readln,real,record,repeat,reset,rewrite,set,%
138	text,then,to,true,type,unpack,until,var,while,with,write,writeln},%
139	sensitive=false,%
140	morecomment=[s]{(*}{*)},%
141	morecomment=[s]{\{}{\}},%
142	morestring=[d]{'},%
143	caption=SQL%
144}
145
146
147
148
149\lstnewenvironment{SQL}[1][]{\lstset{language=SQL,title=SQL,title=Example,#1}}{}
150
151\lstnewenvironment{Code}[1][]{\lstset{language=Ada,framerule=0pt,#1}}{}
152
153\lstnewenvironment{Example}[1][]{\lstset{language=Ada,#1}}{}
154\lstnewenvironment{NumberedExample}[1][]{\lstset{language=Ada,numbers=left,escapeinside={(*@}{@*)},#1}}{}
155\lstnewenvironment{ShellNumberedExample}[1][]{\lstset{language=sh,numbers=left,escapeinside={(*@}{@*)},#1}}{}
156\renewcommand\lstlistingname{Example}
157
158\newcommand\apqversion{3.2}
159
160
161%\DeclareCaptionFont{white}{\color{white}}
162%\DeclareCaptionFormat{listing}{\colorbox[cmyk]{0.43, 0.35, 0.35,0.01}{\parbox{\textwidth}{\hspace{15pt}#1#2#3}}}
163%\captionsetup[lstlisting]{format=listing,labelfont=white,textfont=white, singlelinecheck=false, margin=0pt, font={bf,footnotesize}}
164
165%\DefineVerbatimEnvironment{SQL}{Verbatim}%
166%   {frame=single,fontsize=\small,label={SQL},labelposition=topline}
167%\DefineVerbatimEnvironment{Code}{Verbatim}%
168%   {frame=single,fontsize=\small}
169%\DefineVerbatimEnvironment{Example}{Verbatim}%
170%   {frame=single,fontsize=\small,label={Example},labelposition=topline}
171%\DefineVerbatimEnvironment{NumberedExample}{Verbatim}%
172%   {frame=single,numbers=left,fontsize=\small,label={Example},labelposition=topline,commandchars=\\\{\}}
173
174
175%==============%
176% The document %
177%==============%
178
179
180\begin{document}
181
182\title{APQ Ada2005 Database Binding}
183\author{%
184Copyright (c) 2002-2004, Warren W. Gay VE3WWG\\%
185Copyright (c) 2007-2011, KOW Framework Project
186}
187\date{\today}
188\maketitle
189
190\tableofcontents{}
191\listoftables
192%\listoffigures
193
194\chapter{Introduction}
195
196
197\section{APQ Version \apqversion}
198
199This manual documents APQ Version \apqversion, which is released under the
200GNAT Modified GPL\index{GPL} (GNU Public License)\index{GNU Public
201License} license. This license is designed to give both the \index{distributor}
202and user the necessary freedoms to enjoy the fair use and distribution of the
203sources \index{distribution of sources} contained in this project.
204See \Ref{license} for more details.
205
206
207\section{KOW Framework}
208
209APQ is now part of the KOW Framework\index{KOW Framework}\footnote{\url{http://framework.kow.com.br}}, which provides a
210range of libraries for developing web applications in Ada 2005.\\
211
212Other library of interest in the KOW Framework is APQ Provider\footnote{\url{http://framework.kow.com.br/projects/apqprovider}},
213which provides a task-safe database connection pool for server applications. A connection pool
214removes the connecting/disconnecting overhead and guaranties your code will
215be running with a valid connection.\\
216
217APQ Provider depends on
218
219\begin{description}
220	\item [KOW Lib] provides basic logging, file system utilities, locales and so on
221	\item [KOW Config] provides an easy way for dealing with configuration files
222\end{description}
223
224while APQ doesn't depend on any KOW Framework library at all.
225
226\section{Supported Databases}
227
228The APQ binding\index{binding} was initially created to satisfy the simple need to
229allow Ada\index{Ada} programs to use a PostgreSQL\index{PostgreSQL} database. However, as open
230sourced database technologies continue to advance, the need to allow
231other databases to be used, becomes greater. Rather than write a unique
232Ada binding for each one, it was conceptualized that a common API\index{API}
233could emerge from the APQ framework\index{framework}. To this end, the APQ binding
234has been reworked rather extensively for version 2.1, to permit increasing
235levels of general support of other database technologies, including
236MySQL\index{MySQL}.\\
237
238In the fall of 2003 the foundation was laid for Sybase\index{Sybase} support in
239the unreleased APQ \apqversion software using Sybase on a trial download\index{download} basis.
240Sybase highlighted some new APQ design \index{design, APQ} wrinkles, which required a
241few new adjustments and API additions. However, this development ground
242to a halt for a spell, until September 9, 2004 when it was announced
243on www.slashdot.org\index{www.slashdot.org} that ``Sybase Releases Free Enterprise Database
244on Linux''\index{Linux}.\\
245
246\begin{quote}
247``Sybase announced today that they are releasing a free (as in
248beer) version of their flagship database for Linux. The free version
249is limited to 1 CPU, 2 GB of RAM, and 5 GB of data, which is more
250than adequate for all but the most demanding applications. This release
251provides a very attractive alternative to Microsoft SQL Server\index{Microsoft SQL Server}, and
252gives developers and DBAs an extremely powerful argument to use against
253the adoption of Microsoft-based solutions.''%
254\footnote{Posted by ``Tassach'' (tassach@rapiertech.com)}
255\end{quote}
256
257Now there was greater reason to put enterprise class database support
258into an Ada thick binding\index{thick binding} for databases. Sybase support in APQ would
259allow developers to develop real applications in using Ada, without
260trial software expiring. Once developed, these same Ada applications
261could be deployed within the enterprise and on a large scale.\\
262
263Thanks to the enterprise class database support, APQ entered the
264enterprise development world. This resulted in needing to support
265both Microsoft SQL Server\index{Microsoft SQL Server} and
266ODBC.\\
267
268This resulted in major refactoring of the code and the package apq-sybase moved
269to apq-ct\_lib. Also, APQ became FreeTDS\index{FreeTDS} compatible.
270
271\begin{table}{
272   \begin{tabular}{lcccl}
273   Database       &  As of APQ Version &  SQL   &  Blob &  Module          \\
274   \hline
275   PostgreSQL     &  1.x               &  Yes   &  Yes  &  apq-postgresql  \\
276   MySQL          &  2.x               &  Yes   &  No   &  apq-mysql       \\
277   Sybase 12.52   &  2.2               &  Yes   &  No   &  apq-ct\_lib      \\
278   SQL Server     &  3.0               &  Yes   &  No   &  apq-ct\_lib      \\
279   ODBC           & 3.2                &  Yes   &  No   &  apq-odbc
280   \end{tabular}}
281   \caption{Database Product Support}\label{t:DBSupport}
282\end{table}
283
284
285Table \ref{t:DBSupport} is further described as follows:
286
287\begin{description}
288   \item [As of APQ Version]is the version where the database was first supported.
289   \item [SQL]indicates whether the common SQL functions are supported (sans blob).
290   \item [Blob]indicates whether blob support is present.
291   \item [Module]indicates the module where the specific binding is implemented
292\end{description}
293
294As the reader can observe in the table above, the only database with blob support\index{blob support}
295so far is PostgreSQL. This is so because MySQL's blob interface is not as complete as provided by PostgreSQL.
296Where PostgreSQL provides the facility for virtually limitless sized
297blobs, a MySQL blob must fit within a ``column'', very much like
298a text field. For this reason, the facility to perform stream oriented\index{stream oriented}
299I/O is lacking on a blob in APQ for MySQL.\\
300
301Also, there han't been time or interest in developing Blob support in Sybase and SQL Server
302so far. This implementation should take quite a while to be done and for now the focus of
303the project is in providing a stable solution for database connectivity with up to date documentation.\\
304
305
306The ODBC\index{ODBC} support is considered pre-alpha, only tested on Windows platforms.
307There is no build system for it yet and for now there is no interest and continuing this as
308MySQL and PostgreSQL have proven to be stable and robust enough for all of our needs.
309
310
311\subsection{The Future of Blob Support for MySQL}
312
313Much investigation and research\index{research, APQ} is required to adequately resolve
314the blob issue in APQ. Rather than hold back the binding from general
315use, where blob functionality may have limited use anyway, it was
316decided to release APQ 2.0 with the common API for the two databases,
317and leaving the resolution of the blob API for a future release.\\
318
319If you are a developer, who hopes to write portable database\index{portable database code} code,
320then please be aware that the PostgreSQL\index{PostgreSQL} blob\index{blob} API is subject to future
321revision. Potentially, this could be fairly extensively revised, but
322every attempt will be made to leave a migration path open to the developer.
323
324
325\section{Generic Database Support}
326
327One of the main goals of the APQ version 2.0 release, was to develop
328a common API\index{API, common}, that does not discriminate based upon the database technology
329being selected. The ideal was to allow a developer to write a procedure
330that would accept a classwide\index{classwide} database objects, and perform database
331operations without needing to be concerned whether the database being
332used was PostgreSQL\index{PostgreSQL}, MySQL\index{MySQL} or Sybase\index{Sybase}.
333To a large extent, the author believes that this goal has been achieved.
334
335
336\subsection{Generic Limitations}
337
338It must be admited however, there are some areas where the database
339technologies were very different. Consequently, some exceptions and
340work-arounds will be required by the programmer. An example of this
341is that MySQL\index{MySQL} requires that all rows be fetched from a SELECT\index{SELECT} query.
342A failure to do this, corrupts the communication between the server\index{communication, server}
343and the client. Consequently, APQ works around this by defaulting
344to use the C library call mysql\_store\_result()\index{mysql\_store\_result()} instead of the alternative,
345which is mysql\_use\_result()\index{mysql\_use\_result()}. However, if the result set is large,\index{large result sets}
346then receiving all of the rows into the clients memory\index{memory, client} is not a suitable
347choice. Consequently, APQ does provide some MySQL specific ways to
348manage this setting.\\
349
350The MySQL database software also provides the special ``LIMIT n''\index{LIMIT n}
351extension, if the client program is only interested in the first n
352rows of the result. If for example, you have a price file containing
353stock price history, you may want to query the most recent price for
354it. The simplest way to do this would be to perform a SELECT\index{SELECT} on the
355table with a descending price date sort sequence (or index). But if
356you only want the first (most recent) row \index{most recent row} returned, you do not want
357to retrieve the entire price history into the memory of your client!
358This is what mysql\_store\_result()\index{mysql\_store\_result()} implies (APQ default). So the
359application programmer will need to plan for this, when MySQL is used.
360He will need to do one of the following:
361
362\begin{itemize}
363   \item Cause mysql\_use\_result() to be used instead (change the APQ default),
364         and then fetch all of the rows, one by one.
365   \item Use the MySQL ``LIMIT 1''\index{LIMIT n} SQL extension to limit the results to
366         1 row.
367\end{itemize}
368
369The problem of course, is that this type of handling must only be
370done for MySQL\index{MySQL} databases. Consequently, APQ also provides an API so
371that the application may query which database is being used.
372
373
374\section{The APQ Database Binding}
375
376This software represents a binding\index{binding to objects} to objects and procedures that
377enable the Ada2005\index{Ada2005}%
378\footnote{Hereafter, we'll just refer to the language as Ada, even though the
379version of the language implied is Ada2005.%
380} programmer to manipulate or query a relational database.\index{relational database} This document
381describes the design principles and goals\index{goals of APQ} of this APQ binding. It
382also supplies reference documentation\index{reference documentation} to the programmer, enabling
383the reader to write applications using the PostgreSQL\index{PostgreSQL}, MySQL\index{MySQL}
384or Sybase\index{Sybase}  databases,
385in the Ada programming language.\\
386
387We recomend you to use the newest GNAT distribution possible. Both FSF and Adacore's version are supported.
388APQ is currently developed under Sabayon Linux, but updated debian packages are currently available.\\
389
390The source code avoids any use of GNAT\index{GNAT} specific language extensions\index{language extensions}.
391The possible exception to this rule is that the gnatprep\index{gnatprep} tool may
392be used to precompile\index{precompile} optional support of optional databases\index{optional databases}. There
393is some C\index{C language} language source\index{source code} code used, to facilitate Ada\index{Ada} and database
394C language library linkages.
395
396\begin{table}
397   \begin{center}
398   \begin{tabular}{ll}
399   Library              &  Module         \\
400   \hline
401   libpq                &  apq-postgresql \\
402   libmysqlclient       &  apq-mysql      \\
403   OCS-12\_5 or FreeTDS &  apq-ct\_lib    \\
404   \end{tabular}
405   \end{center}
406\caption{Client Libraries}\label{t:ClientLib}
407\end{table}
408
409Table \ref{t:ClientLib}
410lists the C language libraries\index{libraries, C} that are
411used in addition to the APQ client\index{library, APQ client} library, while linking\index{linking} your
412application.\\
413
414
415GNAT specific features are avoided where possible, but as it has become the \emph{de facto}
416standard compiler for Ada we tend to use some of it's facilities.\\
417
418
419For now our code is built using gprbuild\index{gprbuild} tool (which actually should support
420non-ACT\index{non-ACT} vendors).\\
421
422GNAT\index{GNAT} specific pragma\index{pragma} statements of the form:\\
423
424\index{Linker\_Options}
425\begin{Code}
426
427   pragma Linker_Options("-lapq");
428
429\end{Code}
430
431
432were used in the past, but thanks to gprbuild they are being removed in favour of a more
433portable way for controlling the linker\index{linking}. Therefore those using non-ACT\index{non-ACT} vendor
434supplied Ada compilers\index{Ada compilers} might be able to compile and use this binding\index{binding}
435without a huge investment even if their compiler isn't supported by gprbuild.\\
436
437
438APQ has been tested in the following platforms:
439
440\begin{description}
441	\item [Windows] several versions, but for now 32bit windows only. APQ should work in 64 bit windows as well.
442	\item [Linux] both 32 and 64 bit Linux distributions, including Debian, Ubuntu, Sabayon and Gentoo linux.
443	\item [FreeBSD] even thought it hasn't been tested recently
444	\item [Open Solaris] same as FreeBSD
445\end{description}
446
447
448\subsection{General Features}
449
450This binding\index{binding} supports all of the normal database functions that a
451programmer would want to use. Additionally blob\index{blob} support
452is included%
453\footnote{For PostgreSQL only, at release 2.0.%
454}, and implemented using the Ada streams\index{streams, Ada} interface\index{interface}.
455This provides the programmer with the Ada convenience and safety of
456the streams interface\index{streams interface} when working with blobs.\\
457
458This binding includes the following general features:
459
460\begin{enumerate}
461   \item Open and Close one or more concurrent database connections\index{connections}
462   \item Create and Execute one or more concurrent SQL queries\index{queries, concurrent} on a selected
463         database connection\index{connection, database}
464   \item Begin work\index{begin work}, Commit work\index{commit work} or Rollback work\index{rollback work}
465   \item Access error message\index{error messages} text
466   \item Generic functions and procedures to support specialized application
467         types
468   \item The NULL indicator\index{NULL indicator} is supported
469   \item Blob\index{blob} support using the Ada streams\index{streams, Ada} facility
470   \item A wide range of native\index{native types} and builtin\index{builtin data types} data types are supported
471   \item Database neutral API\index{neutral API, database} is now supported for most functions
472\end{enumerate}
473
474\subsection{Binding Type}
475
476This library represents a thick Ada binding\index{thick binding} to the PostgreSQL C\index{C programmer}  programmer's
477libpq\index{libpq} library %
478\footnote{C++ programs can also make use of this library but there exists the
479library libpq++ for C++ native support.%
480}, and with version 2.0, MySQL's\index{MySQL} C programming library. As a thick
481binding, there are consequently Ada objects\index{objects, Ada} and data types that are
482tailored specifically to the Ada programmer. Some data types and objects
483exist to mirror those used in the C language, while others are provided
484to make the binding easier or safer to apply.\\
485
486A thin binding\index{thin binding} would have required the Ada programmer to be continually
487dealing with C language\index{C language data types} data type issues. Conversions to and from
488various types and pointers\index{pointers} would be necessary making the use of the
489binding rather tedious. Furthermore, the resulting Ada\index{Ada} program would
490be much harder to read and understand.\\
491
492A thick binding\index{thick binding} introduces new objects and types in order to provide
493an API to the programmer. This approach however, fully insulates the
494Ada\index{Ada} programmer from interfacing with C programs\index{C programs}, pointers\index{pointers} and strings\index{strings}.
495The design goal\index{design goal} has additionally been to keep the number of new objects
496and types to a minimum. This has been done without sacrificing convenience
497and safety\index{safety}. Readability\index{readability} of the resulting Ada\index{Ada} program was also considered
498to be important.\\
499
500The objects and data types involved in the use of this binding can
501be classified into the following main groups:
502
503\begin{enumerate}
504   \item Native\index{native data types} data types and objects
505   \item Database \index{database objects} manipulation objects
506   \item New database related objects and types for holding data
507\end{enumerate}
508
509Native data types need no explanation in this document. The database
510manipulation objects will be described in
511\Ref{Database_Objects:Section}.
512The following section will introduce the Ada types\index{Ada types} that are used to
513hold data.
514
515
516\section{Binding Data Types}
517
518The PostgreSQL\index{PostgreSQL} database supports many standard SQL\index{SQL data types} data types as well
519as a few exotic ones. This section documents the database base types\index{data types, database}
520that are supported by the Ada\index{Ada binding} binding to the database. This list is
521expected to grow with time as the Ada binding continues to mature
522in its own software development.\\
523
524The ``Data Type Name'' column in the following table refers to
525a binding type\index{binding type} if the type name is prefixed with ``APQ\_''%
526\footnote{Formerly, the PostgreSQL specific types had used a PG\_ prefix.%
527}. These data types were designed to mimic common database data types
528in use. They can be used as they are provided, or you may subtype
529from them or even derive new types from them in typical Ada\index{Ada} fashion.
530All other data types are references to native Ada data types (for
531some of these, the package where they are defined are shown in the
532``Notes'' column).\\
533
534The column labelled ``Root Type''\index{root types} documents the data type that
535the APQ\_ data type was derived\index{derived} from. Where they represent an Ada\index{subtype, Ada}
536subtype, the column ``Subtype'' indicates a ``Y''. For type
537derivations a ``N'' is shown in this column, indicating that the
538APQ\_ type \index{APQ\_ types} listed is made ``unique''.\\
539
540
541\subsection{PostgreSQL Data Types\label{PostgreSQL SQL Data Types}}
542
543The ``Notes'' column of Table \ref{t:pqtypes} provides PostgreSQL notes, package names\index{package names} and
544PostgreSQL\index{data types, PostgreSQL} data type names where the name is given in all capitals.
545
546\begin{longtable}{|l|c|c|l|}
547\hline
548Data Type Name    &  Root Type   &  Subtype  &  PostgreSQL Notes\\
549\hline \hline
550Row\_ID\_Type     &  -           &  N        &  Used for blobs and rows\\
551\hline
552String(<>)        &  -           &  -        &  Native Strings\\
553\hline
554String(a..b)      &  -           &  -        &  Fixed length strings\\
555\hline
556Unbounded\_String &  -           &  -        &  Ada.Strings.Unbounded\\
557\hline
558Bounded\_String   &  -           &  -        &  Ada.Strings.Bounded\\
559\hline
560APQ\_Smallint     &  -           &  N        &  SMALLINT\\
561\hline
562APQ\_Integer      &  -           &  N        &  INTEGER\\
563\hline
564APQ\_Bigint       &  -           &  N        &  BIGINT\\
565\hline
566APQ\_Real         &  -           &  N        &  REAL\\
567\hline
568APQ\_Double       &  -           &  N        &  DOUBLE PRECISION\\
569\hline
570APQ\_Serial       &  -           &  N        &  SERIAL\\
571\hline
572APQ\_Bigserial    &  -           &  N        &  BIGSERIAL\\
573\hline
574APQ\_Boolean      &  Boolean     &  Y        &  BOOLEAN\\
575\hline
576APQ\_Date         &  Ada.Calendar.Time & Y   &  DATE\footnote{Local timezone assumed}\\
577\hline
578APQ\_Time         &  Ada.Calendar.Day\_Duration & Y & TIME\footnote{Local timezone assumed}\\
579\hline
580APQ\_Timestamp    &  Ada.Calendar.Time & N   & TIMESTAMP\footnote{Converted into and loaded as UTC}\\
581\hline
582APQ\_Bitstring    &  -           &  N        &  BIT or BIT VARYING\\
583\hline
584Decimal\_Type     &  -           &  -        &  PostgreSQL.Decimal\\
585\hline
586range <>          &  -           &  -        &  Native Integers\\
587\hline
588delta <>          &  -           &  -        &  Native Fixed Point\\
589\hline
590digits <>         &  -           &  -        &  Native Floating Point\\
591\hline
592delta <> digits <> & -           &  -        &  Native Decimal\\
593\hline
594\caption{PostgreSQL Data Types}\label{t:pqtypes}
595\end{longtable}
596
597The data type shown as ``Decimal\_Type''\index{Decimal\_Type}
598is special, in that it is supported from a child package APQ\-.PostgreSQL\-.Decimal\index{APQ.PostgreSQL.Decimal}.
599It represents a tagged\index{tagged type} type that provides an interface to the C routines\index{C routines}
600used by the PostgreSQL database server, for arbitrary precision decimal\index{precision, arbitrary}
601values.
602
603
604\subsection{MySQL Data Types\label{MySQL Data Types}}
605
606Table \ref{t:mytypes} summarizes the MySQL\index{data types, MySQL} specific data types and the
607corresponding APQ data types.
608
609\begin{longtable}{|l|c|c|l|}
610\hline
611APQ Data Type        &  Ada Spec                   &  Subtype     &  Comments\\
612\hline
613\hline
614Row\_ID\_Type        &  unsigned 64 bits           &  N           &  For all databases\\
615\hline
616APQ\_Smallint        &  signed 16 bits             &  N           &  SMALLINT\\
617\hline
618APQ\_Integer         &  signed 32 bits             &  N           &  INTEGER\\
619\hline
620APQ\_Bigint          &  signed 64 bits             &  N           &  BIGINT\\
621\hline
622APQ\_Real            &  digits 6                   &  N           &  REAL\\
623\hline
624APQ\_Double          &  digits 15                  &  N           &  DOUBLE PRECISION\\
625\hline
626APQ\_Serial          &  range 1..2147483647        &  N           &  \emph{INTEGER}\\
627\hline
628APQ\_Bigserial       &  range 1..2{*}{*}63         &  N           &  \emph{BIGINT}\\
629\hline
630APQ\_Boolean         &  Boolean                    &  Y           &  BOOLEAN\\
631\hline
632APQ\_Date            &  Ada.Calendar.Time          &  Y           &  DATE\\
633\hline
634APQ\_Time            &  Ada.Calendar.Day\_Duration &  Y           &  TIME\\
635\hline
636APQ\_Timestamp       &  Ada.Calendar.Time          &  N           &  TIMESTAMP\\
637\hline
638APQ\_Bitstring       &  array(Positive) of APQ\_Boolean & N       &  \emph{Not in MySQL}\\
639\hline
640\caption{MySQL Data Types}\label{t:mytypes}
641\end{longtable}
642
643Notice the italicized SQL keywords\index{keywords, SQL} in the table. They identify the
644SQL keywords that differ from PostgreSQL\index{PostgreSQL}. However, the programmer
645only needs to be concerned with these SQL\index{keywords, SQL} keywords when creating new
646tables or temporary tables. For example a column of type SERIAL\index{SERIAL} in
647a PostgreSQL table, should be declared as a INTEGER\index{INTEGER} type in MySQL.
648
649
650\section{Sybase Data Types}
651
652The chart below outlines the mappings between APQ data types and Sybase
653server data types\index{data types, Sybase}. The italicized SQL keywords
654\index{keywords, SQL} in the table identify
655the keywords that differ from PostgreSQL\index{PostgreSQL}. The following notes are
656particular to Sybase\index{Sybase}:
657
658\begin{itemize}
659   \item APQ\_Bigint is not completely range compatible with Sybase's \emph{NUMERIC}
660         \index{APQ\_Bigint}\index{NUMERIC}\index{DECIMAL}
661         (or \emph{DECIMAL}) server types. APQ\_Bigint will always accept Sybase server
662         values, but the server will not be able to accept the full APQ\_Bigint range of values.
663         To comply with the database server's range,
664         the application designer should use:
665\end{itemize}
666
667\index{Sybase\_Bigint}
668\begin{Code}
669subtype Sybase_Bigint is APQ_Bigint
670   range -10**38..10**38-1;
671\end{Code}
672
673\begin{itemize}
674   \item APQ\_Bigserial\index{APQ\_Bigserial} is not supported.
675   \item APQ\_Boolean\index{APQ\_Boolean}  maps to Sybase's data type \emph{BIT.}
676   \item APQ\_Bitstring\index{APQ\_Bitstring} is not supported.
677\end{itemize}
678
679Table \ref{t:sytypes} lists the APQ types supported for Sybase.
680
681\begin{longtable}{|l|c|c|l|}
682\hline
683APQ Data Type        &  Ada Spec          &  Subtype           &  Comments\\
684\hline
685\hline
686Row\_ID\_Type        &  unsigned 64 bits  &  N                 &  For all databases\\
687\hline
688APQ\_Smallint        &  signed 16 bits    &  N                 &  SMALLINT\\
689\hline
690APQ\_Integer         &  signed 32 bits    &  N                 &  INTEGER/INT\\
691\hline
692APQ\_Bigint          &  signed 64 bits ($-10^{38}..$$10^{38}\textrm{-1}$) & N & \emph{NUMERIC/DECIMAL}\\
693\hline
694APQ\_Real            &  digits 6          &  N                 &  REAL\\
695\hline
696APQ\_Double          &  digits 15         &  N                 &  DOUBLE PRECISION\\
697\hline
698APQ\_Serial          &  range 1..2147483647 & N                &  \emph{INTEGER}\\
699\hline
700APQ\_Bigserial       &  range 1..$2^{63}$ &  N                 &  ???\\
701\hline
702APQ\_Boolean         &  Boolean           &  Y                 &  \emph{BIT}\\
703\hline
704APQ\_Date            &  Ada.Calendar.Time &  Y                 &  DATE\\
705\hline
706APQ\_Time            &  Ada.Calendar.Day\_Duration & Y         &  TIME\\
707\hline
708APQ\_Timestamp       &  Ada.Calendar.Time &  N                 &  \emph{DATETIME}\\
709\hline
710APQ\_Bitstring       &  array(Positive) of APQ\_Boolean & N    &  \emph{Not in Sybase}\\
711\hline
712\caption{Sybase Data Types}\label{t:sytypes}
713\end{longtable}
714
715
716\section{Database Objects\label{Database_Objects:Section}}
717
718Much of the binding between Ada\index{Ada} and the database server is provided
719through the use of tagged\index{tagged record} record types. Presently the APQ binding
720operates through three object types\index{object types, APQ} listed in Table \ref{t:APQObj}.
721
722\begin{table}
723   \begin{center}
724   \begin{tabular}{lll}
725   Derived From            &  Object Type       &  Purpose\\
726   \hline
727   Root\_Connection\_Type  &  Connection\_Type  & Database connection\\
728   Root\_Query\_Type       &  Query\_Type       & SQL interface\\
729   N/A                     &  Blob\_Type        & Blob operations\\
730   \end{tabular}
731   \end{center}
732   \caption{APQ Object Types}\label{t:APQObj}
733\end{table}
734
735The APQ objects from Table \ref{t:APQObj} are described more fully as follows:
736
737\begin{description}
738   \item[Connection\_Type] object is used with Query\_Type and Blob\_Type objects
739         to perform SQL queries and blob operations respectively. This object
740         maintains the connection to the database server.
741   \item[Query\_Type] objects are used with one Connection\_Type object
742         to perform SQL query operations. This object holds the text of the
743         SQL query, some query state and result information. To execute a
744         query, it must be used in conjunction with a Connection\_Type object.
745   \item[Blob\_Type] objects are used with one Connection\_Type object to
746         perform blob operations. This is currently only supported for PostgreSQL
747         by APQ. All blob operations must occur within a transaction.
748\end{description}
749
750\begin{floatingtable}{
751      \begin{tabular}{lc}
752      Object            & Finalized \\
753      \hline
754      Connection\_Type  & Yes \\
755      Query\_Type       & Yes \\
756      Blob\_Type        & No \\
757      \end{tabular}}
758\caption{Object Finalization Behavior}\label{t:Finalization}
759\end{floatingtable}
760
761Table \ref{t:Finalization} lists the three APQ objects and their finalization
762behaviour.
763While the Connection\_Type\index{Connection\_Type}
764and Query\_Type\index{Query\_Type} objects are subject to
765finalization, the Blob\_Type\index{Blob\_Type} is not.
766This is because it represents an access type to
767a Blob\_Object. This is similar in concept to an open a file, using
768the File\_Type data type. This design approach was necessary
769to support Ada\index{Ada} Streams\index{streams, Ada} oriented access for blobs.
770
771\subsection{Object Hierarchy}
772
773Before multiple database products were supported, the APQ object hierarchy\index{hierarchy}
774was simple. To provide generic level support however, there are now
775root\index{root objects} objects and derived objects\index{derived objects}. In most programming
776contexts, the application writer does not need to be concerned with this fact.
777However, if you frequently inspect the spec files\index{spec files} instead of the documentation\index{documentation},
778you must be aware that primitives\index{primitives} for a given object may be declared
779in multiple places. Examine Table \ref{t:pkghier} to review the APQ package hierarchy.
780
781\begin{table}
782   \begin{center}
783      \begin{tabular}{ll}
784         Package Name            & Description \\
785         \hline
786         APQ                     & Root objects and primitives \\
787         APQ.PostgreSQL          & Declarations and constants unique to PostgreSQL \\
788         APQ.PostgreSQL.Client   & Derived objects and added primitives \\
789         APQ.MySQL               & Declarations and constants unique to MySQL \\
790         APQ.MySQL.Client        & Derived objects and added primitives \\
791         APQ.Sybase              & Declarations and constants unique to Sybase \\
792         APQ.Sybase.Client       & Derived objects and added primitves for Sybase \\
793      \end{tabular}
794   \end{center}
795   \caption{APQ Package Hierarchy}\label{t:pkghier}
796\end{table}
797
798Table \ref{t:pkghier} illustrates that support for a given database is derived\index{derived}
799from the APQ top level\index{top level package} package. Root objects\index{root level} are declared in APQ,
800with common functionality. Some primitives must be overridden\index{overridden} by the
801derived object in database specific packages. For example, APQ.Root\_Query\_Type
802declares a primitive named Value (\emph{APQ.Value)} to return a string
803column result. If this particular method is called, the exception
804\emph{Is\_Abstract}\index{Is\_Abstract} will be raised to indicate that it must be overriden
805with code to handle the specific database being used. Normally the
806user would invoke APQ\-.MySQL\-.Client\-.Value when using the MySQL\index{MySQL} database,
807for example. The programmer normally need not be aware of these details,
808since object dispatching\index{dispatching} takes care of these details.
809
810For this reason, the APQ\-.MySQL\-.Query\_Type object for example, is
811derived from the APQ\-.Root\_Query\_Type\index{Root\_Query\_Type} object. This Query\_Type\index{Query\_Type} object
812will provide its own implementation of the Value\index{Value} function to return
813a column result, and will work as required.
814
815Consequently, when looking for primitives\index{primitives} available to the Query\_Type
816object, don't forget that many common primitives\index{common primitives} will be inherited\index{inherited}
817from the APQ\-.Root\-\_Query\-\_Type object. The same is true for Connection\-\_Type\index{Connection\_Type}
818objects. A number of common primitives are inherited from the APQ\-.Root\_Connection\_Type
819object.
820
821
822\chapter{Connecting to the Database}
823
824Before any useful work can be accomplished by a database client program,
825a connection must be established between the Ada program and the database
826server. This chapter will demonstrate how to use the APQ binding\index{binding} to
827enable a program to connect\index{connect} and disconnect\index{disconnect}
828from the database server.
829
830\section{The Connection\_Type}
831
832The Connection\_Type\index{Connection\_Type} object holds everything that is needed to maintain
833a connection\index{connection} to the database server. There are seven groups of primitive\index{primitive}
834operations for this object:
835
836\begin{enumerate}
837   \item Context\index{Context} setting operations
838   \item Connection\index{Connection} operations
839   \item Connection Information functions\index{information functions}
840   \item General Information operations
841   \item Implicit operations (Finalization\index{Finalization})
842   \item Trace Facilities\index{trace facilities}
843   \item Generic Database Operations
844\end{enumerate}
845
846\section{Context Setting Operations}\label{Context_Setting_Operations}
847
848These primitives ``configure''\index{configure} the connection\index{connection} that is
849to be made later. When the object is initially created, it is in the
850disconnected\index{disconnected state} state. While disconnected, configuration changes can be
851made in to affect the next connection attempt. With the exception of the
852database name\index{database name}, the application should not make configuration\index{configuration} changes
853while the object is in the connected state\index{connected state}.
854\footnote{This is not yet enforced by APQ.}
855
856The configuration primitives\index{primitives} are listed in Table \ref{t:ctxops}.
857\footnote{The items marked ``Root'' are primitives from APQ.Root\_Query\_Type.
858The items marked {}``Derived'' are those overrides that are declared
859on the APQ.{*}.Query\_Type object.}
860
861\begin{table}
862   \begin{center}
863      \begin{tabular}{ccll}
864      Type & Derivation & Name                  & Purpose \\
865      \hline
866      proc & Root       & Set\_Host\_Name       & Set server host name \\
867      proc & Root       & Set\_Host\_Address    & Set server host IP address \\
868      proc & Root       & Set\_Port             & Set server port number \\
869      proc & Root       & Set\_DB\_Name         & Set database name \\
870      proc & Root       & Set\_User\_Password   & Set userid and password \\
871      proc & Root       & Set\_Instance         & Set instance name to use \\
872      proc & Root       & Set\_Options          & Set userid and password \\
873      \end{tabular}
874   \end{center}
875\caption{Context Setting Primitives}\label{t:ctxops}
876\end{table}
877
878It would be nice if all database software products worked the same
879way but the reality is very different. Table \ref{t:ctxdiffs} indicates how
880the primitives apply by database product.\label{Set_Instance Support Chart}
881In the table you can see that PostgreSQL\index{PostgreSQL} and MySQL\index{MySQL} establish their
882connection by specifying the host, port and database name. Sybase
883on the other hand, specifies this information in their \emph{interface}
884file. To access the appropriate Sybase\index{Sybase interface entry} interface entry requires only
885the \emph{instance}\index{instance} information supplied by the Set\_Instance\index{Set\_Instance} call.
886
887\begin{table}
888   \begin{center}
889      \begin{tabular}{lccc}
890      Primitive            & PostgreSQL   & MySQL  & Sybase \\
891      \hline
892      Set\_Host\_Name      & Yes          & Yes    & Ignored \\
893      Set\_Host\_Address   & Yes          & Yes    & Ignored \\
894      Set\_Port            & Yes          & Yes    & Ignored \\
895      Set\_DB\_Name        & Yes          & Yes    & See Note %
896      \footnote{Set\_DB\_Name is useful after the connection is made.}\\
897      Set\_User\_Password  & Yes          & Yes    & Yes \\
898      Set\_Instance        & No           & No     & Yes \\
899      Set\_Options         & Yes          & Yes    & Yes \\
900      \end{tabular}
901   \end{center}
902\caption{Context Setting Differences}\label{t:ctxdiffs}
903\end{table}
904
905\subsection{PostgreSQL Defaults}
906
907The PostgreSQL database defines certain environment\index{environment, PostgreSQL} variables that
908can specify defaults. These and the fallback\index{fallback values} values are documented
909in Table \ref{t:pqdef}.
910
911\begin{table}
912   \begin{center}
913      \begin{tabular}{cclll}
914      Type & Derivation    & Name               & Default      & Fallback \\
915      \hline
916      proc & Root          & Set\_Host\_Name    & PGHOST       & localhost\\
917      proc & Root          & Set\_Host\_Address & PGHOST       & localhost\\
918      proc & Root          & Set\_Port          & PGPORT       & 5432\\
919      proc & Root          & Set\_DB\_Name      & PGDATABASE   & LOGNAME\\
920      proc & Root          & Set\_User\_Password &
921         \begin{tabular}{l}
922            PGUSER\\
923            PGPASSWORD\\
924         \end{tabular}
925        & LOGNAME\\
926      proc & Root          & Set\_Options       & PGOPTIONS    & ""\\
927      \end{tabular}
928   \end{center}
929   \caption{PostgreSQL Context Defaults}\label{t:pqdef}
930\end{table}
931
932The capitalized names in the table for the ``Default'' and ``Fallback''
933columns represent environment\index{environment} variable names.
934When any of the environment\index{environment variables} variables are undefined in the ``Default''
935column, the value used is determined by the ``Fallback'' value
936listed. The fallback\index{fallback} variable name LOGNAME\index{LOGNAME}
937is simply used to represent the current user's userid\index{userid}.%
938\footnote{The PostgreSQL libpq library may in fact, completely ignore the LOGNAME
939environment variable, and simply look up the userid in the /etc/password
940file.%
941} When no password\index{password} value is provided and no PGPASSWORD\index{PGPASSWORD}
942environment variable exists, then no password is assumed.
943
944
945\subsection{Procedure Set\_Host\_Name}
946
947The Set\_Host\_Name\index{Set\_Host\_Name} procedure accepts the following arguments
948
949\begin{Code}
950procedure Set_Host_Name(
951   C :         in out Connection_Type;
952   Host_Name : in     String
953);
954\end{Code}
955
956The following example configures the Connection\_Type object to connect
957to host\index{host name} ``witherspoon'':
958
959\begin{Example}
960declare
961   C : Connection_Type;
962begin
963   Set_Host_Name(C,"witherspoon");
964\end{Example}
965
966\begin{description}
967\item [Note:]Sybase ignores this API call.
968\end{description}
969
970\subsection{Procedure Set\_Host\_Address}
971
972The procedure takes two arguments, in the same fashion as Set\_Host\_Name\index{Set\_Host\_Address}:
973
974\begin{Code}
975procedure Set_Host_Address(
976   C :            in out Connection_Type;
977   Host_Address : in     String
978);
979\end{Code}
980
981The following example configures the Connection\_Type object to connect
982to IP address\index{IP address} 10.0.0.7:
983
984\begin{Example}
985declare
986   C : Connection_Type;
987begin
988   Set_Host_Address(C,"10.0.0.7");
989\end{Example}
990
991\begin{description}
992\item [Note:]Sybase ignores this API call.
993\end{description}
994
995\subsection{Procedure Set\_Port (IP)}
996
997This procedure configures the port\index{port} where the database
998server\index{server} is listening\index{listening} (when using TCP/IP\index{TCP/IP}
999as the transport\index{transport}):
1000
1001\begin{Code}
1002procedure Set_Port(
1003   C :           in out Connection_Type;
1004   Port_Number : in     Integer
1005);
1006\end{Code}
1007
1008\begin{floatingtable}{
1009   \begin{tabular}{ccc}
1010   Database                &  Default  &  Port\\
1011   \hline
1012   PostgreSQL              &  IP       &  5432\\
1013   MySQL                   &  UNIX     &  ?\\
1014   Sybase                  &  N/A      &  Ignored\\
1015   \end{tabular}}
1016   \caption{Default Database Connections}\label{t:defdb}
1017\end{floatingtable}
1018
1019Table \ref{t:defdb} shows the connection defaults by database product. Some of these
1020are influenced by APQ. For example, APQ defaults to using a TCP/IP connection for the
1021PostgreSQL standard port of 5432.
1022
1023The next example
1024shows how the port\index{port} number is configured.
1025The example configures APQ to use TCP/IP
1026port number 5432\index{port 5432} to connect to
1027a PostgreSQL database.
1028
1029\begin{Example}
1030declare
1031   C : Connection_Type;
1032begin
1033   Set_Port(C,5432);
1034\end{Example}
1035
1036\begin{description}
1037\item [Note:]Sybase ignores this API call.
1038\end{description}
1039
1040\subsection{Procedure Set\_Port (UNIX)}
1041
1042To create a local UNIX socket connection to the database, there is
1043an overloaded version of Set\_Port\index{Set\_Port} that accepts a string\index{string} parameter
1044instead of an integer\index{port, integer} port number.
1045
1046\begin{Code}
1047procedure Set_Port(
1048   C :           in out Connection_Type;
1049   Port_Number : in     String
1050);
1051\end{Code}
1052
1053Specify a null string\index{null string} for the connection\index{connection}
1054to use the local\index{local socket} UNIX\index{UNIX socket} socket default.
1055
1056This parameter has changed somewhat as PostgreSQL\index{PostgreSQL} evolves. If you
1057are experiencing trouble getting a UNIX\index{UNIX socket} socket connection to work,
1058check the database documentation for PostgreSQL carefully. The following
1059example has been tested to work on PostgreSQL version 7.3.5.
1060
1061\begin{Example}
1062declare
1063   C : Connection_Type;
1064begin
1065   Set_Port(C,"5432");
1066\end{Example}
1067
1068See the troubleshooting chapter for tips.
1069
1070\subsection{Procedure Set\_DB\_Name}
1071
1072This procedure call configures the name of the database that the server
1073is to use \emph{prior} to the connection being established. Once
1074the connection has been established, calling Set\_DB\_Name\index{Set\_DB\_Name} switches the
1075connection\index{connection} to use the named database.
1076The calling signature for this primitive is as follows:
1077
1078\begin{Code}
1079procedure Set_DB_Name(
1080   C :       in out Connection_Type;
1081   DB_Name : in     String
1082);
1083\end{Code}
1084
1085The following code fragment shows how the database name\index{database name} is configured
1086to be ``production'':
1087
1088\begin{Example}
1089declare
1090   C : Connection_Type;
1091begin
1092   Set_DB_Name(C,"production");
1093\end{Example}
1094
1095The Set\_DB\_Name \emph{always} acts as a configuration setting \emph{prior}
1096to connecting to the database server. Calling Set\_DB\_Name on a Connection\_Type\index{Connection\_Type}
1097object that has an open server connection to the database, can result
1098in hidden SQL commands for some databases.%
1099\footnote{For PostgreSQL and Sybase, a USE <database> command must be executed.%
1100} Table \ref{t:setdb} summarizes the behaviour according to database product.
1101
1102\begin{table}
1103   \begin{center}
1104      \begin{tabular}{llll}
1105      Database Vendor   &  Before Connecting &  While Connecting           &  After Connected\\
1106      \hline
1107      PostgreSQL        &  Configuration     &  uses config     &  ``USE'' Executed\\
1108      MySQL             &  Configuration     &  uses config.    &  MySQL Client Call\\
1109      Sybase            &  Pending SQL       &  ``USE'' executed   &  ``USE'' Executed\\
1110      \end{tabular}
1111   \end{center}
1112   \caption{Set\_DB\_Name Behaviour}\label{t:setdb}
1113\end{table}
1114
1115From the table you can see that PostgreSQL\index{PostgreSQL} and MySQL\index{MySQL} configure the
1116database prior to connecting\index{connecting} (connecting also establishes the database
1117to be used). When Set\_\-DB\_\-Name is called after a connection has been
1118established, the database server will switch\index{switch database} to the requested database.
1119For some databases, this happens through the native\index{native client API} client API library\index{library}
1120(MySQL), but for others, a ``USE~<database>''\index{USE database} SQL\index{SQL} command must
1121be executed (internally within APQ).
1122
1123\begin{floatingtable}{
1124   \begin{tabular}{ll}
1125   Exception Name    &  Reason\\
1126   \hline
1127   Use\_Error        &  Unsuccessful doing a ``USE <database>''\\
1128   \end{tabular}}
1129   \caption{Set\_DB\_Name Exceptions}\label{t:sdbx}
1130\end{floatingtable}
1131
1132Sybase\index{Sybase} is different again, because does not establish the database
1133at connect time\index{connect time} (Sybase will use the configured default database).
1134So a call to Set\_DB\_Name will queue a ``USE <database>''\index{USE database} SQL\index{SQL}
1135statement, to be executed by APQ, once the connection succeeds. If
1136another Set\_DB\_Name is performed while connected, new ``USE <database>''
1137SQL statements are executed on the Sybase server\index{Sybase server} connection provided.
1138
1139The exceptions listed in Table \ref{t:sdbx}\index{exception} are possible when
1140using a new database name.
1141
1142The case of the database name used is affected according to the case policy\index{case policy}
1143that is in effect for the connection\index{connection}. This is summarized in Table \ref{t:cpol}
1144for each database vendor product.
1145
1146\begin{table}
1147   \begin{center}
1148      \begin{tabular}{llll}
1149      Database Product  &  Case Policy          &  Effect on DB\_Name      &  DB Name Sensitive\\
1150      \hline
1151      PostgreSQL        &  Ignored              &  Case preserved          &  Yes\\
1152      MySQL             &  Ignored              &  Case preserved          &  Yes\\
1153      Sybase            &  Ignored              &  Case preserved          &  Yes\\
1154      \end{tabular}
1155   \end{center}
1156   \caption{Case Policy by Product}\label{t:cpol}
1157\end{table}
1158
1159\subsection{Procedure Set\_User\_Password}
1160
1161This procedure call configures both the userid\index{userid} and the password\index{password} together.
1162If there is no password, then supply the null string\index{null string}:
1163
1164\begin{Code}
1165procedure Set_User_Password(
1166   C :             in out Connection_Type;
1167   User_Name :     in     String;
1168   User_Password : in     String
1169);
1170\end{Code}
1171
1172The following code fragment illustrates how the userid and
1173password is configured:
1174
1175\begin{Example}
1176declare
1177   C :   Connection_Type;
1178begin
1179   Set_User_Password(C,"myuserid","xyzzy");
1180\end{Example}
1181
1182\subsection{Procedure Set\_Case}
1183
1184One of the goals of APQ was to make writing of portable database\index{portable database code} code
1185possible. While this isn't completely possible, the goal remains to
1186reduce database differences. Until the introduction of Sybase\index{Sybase} within
1187APQ, there was little concern for the case of SQL query\index{SQL query code} code used.
1188
1189This APQ manual has always used examples where SQL code is uppercased\index{uppercased SQL code},
1190with Ada\index{Ada} code using normal Ada2005\index{Ada2005} conventions. This helps to make the
1191SQ\index{SQL}L code standout, and separate it from the other code. Sybase introduces
1192a problem however, since the Sybase server is case sensitive\index{case sensitive} when
1193referring to tables\index{tables} and column\index{column names} names. This feature cannot be disabled
1194for a Sybase server%
1195\footnote{MySQL databases can be configured to be caseless or case sensitive.%
1196}. Since users of Sybase\index{Sybase} tend to use lowercase\index{lowercase names} names, this creates
1197a bit of a problem for portable\index{portable SQL} SQL text within APQ.
1198
1199The approach that APQ \apqversion uses for Sybase\index{Sybase} (and future databases where
1200this matters), all SQL\index{SQL} code is changed to lowercase\index{lowercase} before being
1201sent to the server. Before the reader panics thinking that this won't
1202work, it should be made clear that APQ does not change the case\index{case of SQL} of
1203any string\index{string} that is quoted\index{quoted} (using the Append\_Quoted\index{Append\_Quoted} functions for
1204example). A WHERE\index{WHERE clause} clause such as the following will preserve the text
1205within quotes\index{quotes}:
1206
1207\begin{SQL}
1208
1209   where part_no = "XZ98-307"
1210
1211\end{SQL}
1212
1213APQ keeps track of what parts of the SQL\index{SQL query} query were quoted\index{quoted} and which
1214parts were not. This is \emph{not} done by parsing\index{parsing} the SQL text. That
1215would be prone to error and would require intimate knowledge of every
1216SQL dialect supported in APQ. Instead, the string\index{string} fragments are marked
1217for ``preserve''\index{preserve case} case or ``not preserve''\index{preserved, not} as the Query\_Type\index{Query\_Type}
1218object collects text. When the full SQL text\index{SQL text} is require by a routine
1219like To\_String\index{To\_String}, then the standing case policy\index{case policy} is applied to each
1220string\index{string fragment} fragment that has ``not preserve''\index{preserved, not}.
1221
1222You can change this APQ case policy\index{case policy} for Sybase (or any other database).
1223The Set\_Case\index{Set\_Case} function gives you complete control over what the policy
1224to use for SQL case\index{SQL case}. You can choose one of the SQL\_Case\_Type\label{SQL_Case_Type Choices}
1225\index{SQL\_Case\_Type} options, which are listed in Table~\ref{t:cpolicies}.
1226
1227\begin{table}
1228   \begin{center}
1229      \begin{tabular}{ll}
1230         Case Policy    &  Description\\
1231         \hline
1232         Preserve\_Case &  Do not make any case changes to the SQL text\\
1233         Lower\_Case    &  Force unquoted SQL text to lowercase\\
1234         Upper\_Case    &  Force unquoted SQL text to uppercase\\
1235      \end{tabular}
1236   \end{center}
1237   \caption{Case Policies for SQL Text}\label{t:cpolicies}
1238\end{table}
1239
1240\begin{floatingtable}{
1241   \begin{tabular}{ll}
1242   Database       &  Default SQL Case Policy\\
1243   \hline
1244   PostgreSQL     &  Upper\_Case\\
1245   MySQL          &  Lower\_Case\\
1246   Sybase         &  Lower\_Case\\
1247   \end{tabular}}
1248\caption{Default Case Policies}\label{t:dfcpol}
1249\end{floatingtable}
1250
1251Table~\ref{t:dfcpol} summarizes the default case policies\index{case policies} used in APQ \apqversion
1252for the different database vendor products supported.
1253
1254MySQL\index{MySQL} joins Sybase\index{Sybase} in this case policy because by default, MySQL is
1255case sensitive. If you have configured your MySQL server to be case
1256insenstive, then any setting will do (Upper\_Case\index{Upper\_Case} is suggested for
1257the benefit of the trace log displays). Most users of Sybase\index{Sybase} will
1258likely prefer either the Lower\_Case\index{Lower\_Case} or Preserve\_Case\index{Preserve\_Case}
1259policies instead.
1260
1261The Set\_Case\index{Set\_Case} API procedure for the Connection\_Type object is defined
1262as follows:
1263
1264\begin{Code}
1265procedure Set_Case(
1266   C :        in out Connection_Type;
1267   SQL_Case : in     SQL_Case_Type
1268);
1269\end{Code}
1270
1271You may also use the Get\_Case\index{Get\_Case} function primitive to find out what
1272the current policy in effect is. Please note that a change in policy
1273only affects the outcome of the next call to the following
1274pimitives of the Query\_Type\index{Query\_Type} object:
1275
1276\begin{itemize}
1277   \item To\_String
1278   \item Execute
1279   \item Execute\_Checked
1280\end{itemize}
1281
1282The Set\_Case\index{Set\_Case} call will not actually change the SQL text\index{SQL text} stored within
1283the Query\_Type object. It only sets the policy\index{case policy} mode.
1284
1285The following example shows how to undo the Sybase default of lowercasing
1286the SQL text:
1287
1288\begin{Example}
1289declare
1290   C : Connection_Type;
1291   Q : Query_Type;
1292begin
1293   ...
1294   Set_Case(C,Preserve_Case);
1295   ...
1296   Append(Q,"from table Mixed_Case");
1297   Execute(Q,C); -- SQL case is preserved here
1298\end{Example}
1299
1300\subsubsection{The Viral Nature of Connection\_Type}
1301
1302Note that APQ does permit altering the case policy\index{case policy} for Query\_Type\index{Query\_Type}
1303objects in addition to the Connection\_Type\index{Connection\_Type} object being described
1304here. It should be noted however, that the setting held by the Connection\_Type
1305is viral\index{viral nature} in nature. Whenever a Query\_Type object is used in conjunction
1306with a Connection\_Type object, in a \emph{Execute}\index{Execute}
1307or \emph{Execute\_Checked}\index{Execute\_Checked}
1308call for example, the Query\_Type object will inherit the setting
1309held by the corresponding Connection\_Type object. For this reason,
1310the best application practice is to establish your application case
1311policy\index{case policy} in all Connection\_Type objects used by your application. It
1312is also best practice to use one Connection\_Type object wherever
1313possible, since many queries can share one connection\index{shared connection}.
1314
1315The only reason you should consider applying a case policy\index{case policy} directly
1316to a Query\_Object, is perhaps for application specific uses of the
1317SQL text\index{SQL text}. For example, you could build a query\index{query, build a} in a Query\_Type object,
1318set the case policy to Upper\_Case\index{Upper\_Case}, and then use the To\_String\index{To\_String} function
1319primitive to extract out the SQL text for logging\index{logging} or user display\index{display}
1320purposes. Once however the Query\_Type is used with a Connection\_Type
1321however, (in \emph{Execute}) the Connection\_Type's setting will not
1322only prevail for the primitive, but will also force the Query\_Type's
1323policy to agree upon return from the call.
1324
1325
1326\subsection{Procedure Set\_Options\label{Procedure Set_Options}}
1327
1328This procedure call permits the caller to specify any specialized
1329database server options. The options are specified in string form
1330with this API call. The specific options, and the format\index{format} of those
1331options\index{options} will vary according to the database being used. See the following
1332subsections for additional information about the database engine\index{engine, database} specifics.
1333
1334The procedure Set\_Options\index{Set\_Options} is documented as follows:
1335
1336\begin{Code}
1337procedure Set_Options(
1338   C :       in out Connection_Type;
1339   Options : in     String
1340);
1341\end{Code}
1342
1343Exceptions\index{exceptions} can be raised if the options are being set on a connection
1344that is already connected. Table \ref{t:soopts} lists the exceptions that may be
1345raised by Set\_Options.
1346
1347\begin{table}
1348   \begin{center}
1349      \begin{tabular}{ll}
1350      Exception Name    &  Reason\\
1351      \hline
1352      Failed            &  The option is either unsupported or setting was rejected\\
1353      \end{tabular}
1354   \end{center}
1355   \caption{Set\_Options Exceptions}\label{t:soopts}
1356\end{table}
1357
1358If the options are configured for an unconnected\index{unconnected} Connection\_Type
1359object, the exceptions if any, will be raised at the time of connection
1360(See the Connect primitive).
1361
1362The following PostgreSQL\index{PostgreSQL} code fragment illustrates how two options\index{options}
1363may be configured:
1364
1365\begin{Example}
1366declare
1367   C : Connection_Type;
1368begin
1369   Set_Options(C,"requiressl=1 dbname=test");
1370\end{Example}
1371
1372Note that in this example, the option string has been used to declare
1373the database name to be used. Standard values should be set through
1374the primitive functions provided (ie. use Set\_DB\_Name\index{Set\_DB\_Name} instead).
1375Otherwise, when information primitives are added, you may not get
1376correct results. Any non-standard options like the ``requiressl''\index{requiressl}
1377option, should be configured as shown in this procedure call.
1378
1379MySQL\index{MySQL} and Sybase\index{Sybase}, use a comma delimited list\index{delimited list} of options\index{options}.
1380The following example shows how to get Sybase I/O\index{statistics, Sybase I/O}
1381and time statistics\index{statistics, time} recorded in your APQ trace\index{trace log} log:
1382
1383\begin{Example}
1384declare
1385  C : Connection_Type;
1386begin
1387   Set_Options(C,"STATS_IO=TRUE,STATS_TIME=TRUE");
1388\end{Example}
1389
1390Option parsing\index{parsing} is rather limited. Everything between the '=' sign
1391and the next comma is the value for the parameter. Different database
1392products will use different parameter types\index{paramater types}. For example, MySQL\index{MySQL} will
1393use 0 to represent False\index{false}, and 1 to represent True\index{true}. For Sybase\index{Sybase}, use
1394F or False, and T or True for Boolean\index{Boolean} values.
1395
1396
1397\subsubsection{PostgreSQL Options}
1398
1399The documentation is not very clear about the format\index{format} of these options,
1400but it appears that keyword=value\index{keyword value pairs}  pairs\index{keyword=value pairs}
1401separated by \emph{spaces} for multiple options\index{options} are
1402accepted. If you must include spaces or other special characters within
1403the value component, then you must follow PostgreSQL\index{PostgreSQL} escaping rules\index{escaping rules}.
1404Refer to the database server documentation for these details.
1405
1406
1407\subsubsection{MySQL Options}
1408
1409MySQL's\index{MySQL} C interface\index{C interface} is much different than PostgreSQL's C interface
1410for options. MySQL uses an enumerated value\index{enumerated value} and argument pair\index{argument pair} when
1411setting an option\index{option}.%
1412\footnote{Although, some options do not use the argument.%
1413} To keep the APQ interface friendly and consistent, APQ will accept
1414all options and arguments in a string\index{string} form as documented in
1415\Ref{Procedure Set_Options}. However, these string options\index{string options} must be
1416processed by APQ and digested into arguments usable by the MySQL C
1417client interface. Consequently, APQ must anticipate these options
1418and the option format in advance. For these reasons, the MySQL options
1419and their arguments will be partially documented here.
1420
1421The format\index{format of option string} of the option string should be one or more option names
1422and arguments, separated by commas. Option names\index{option names} are treated as caseless\index{caseless}
1423(internally upcased\index{upcased}).
1424
1425\begin{Example}
1426
1427   Set\_Options(C,"CONNECT_TIMEOUT=3,COMPRESS,LOCAL_INFIL=1");
1428
1429\end{Example}
1430
1431Each option should be separated by a comma. APQ processes each option
1432in left to right fashion, making multiple MySQL C API calls for each
1433one. Table~\ref{t:myopts} lists the APQ supported options for MySQL.
1434
1435\begin{table}
1436   \begin{center}
1437      \begin{tabular}{lll}
1438         Option Name          &  Argument Type           &  Comments\\
1439         \hline
1440         CONNECT\_TIMEOUT     &  Unsigned                &  Seconds\\
1441         COMPRESS             &  None                    &  Compressed comm link\\
1442         NAMED\_PIPE          &  None                    &  Windows: use a named pipe\\
1443         INIT\_COMMAND        &  String                  &  Initialization command\\
1444         READ\_DEFAULT\_FILE  &  String                  &  See MySQL\\
1445         READ\_DEFAULT\_GROUP &  String                  &  See MySQL\\
1446         SET\_CHARSET\_DIR    &  String                  &  See MySQL\\
1447         SET\_CHARSET\_NAME   &  String                  &  See MySQL\\
1448         LOCAL\_INFIL         &  Boolean                 &  See MySQL\\
1449      \end{tabular}
1450   \end{center}
1451   \caption{MySQL Options}\label{t:myopts}
1452\end{table}
1453
1454It is important to observe that any option that requires an argument\index{argument, option},
1455must have one. Any argument that requires an unsigned integer\index{unsigned}, must
1456have an unsigned integer (otherwise an exception\index{exception} is raised). A MySQL\index{MySQL}
1457Boolean\index{Boolean} argument should be the value 0 or 1. At the present time,
1458APQ gathers string\index{string} data up until the next comma or the end of the
1459string. Currently an option argument string cannot contain a comma
1460character.
1461\footnote{This needs to be corrected in a future release of APQ.}
1462
1463
1464\subsubsection{Sybase Options}
1465
1466Sybase documents several options\index{options, Sybase} in their ``Open Client C Programmer's
1467Reference'' manual. All documented options are made available to
1468the APQ developer, although some options are not recommended.
1469
1470\begin{floatingtable}{
1471   \begin{tabular}{ll}
1472   Option Value   &  Meaning\\
1473   \hline
1474   TRUE           &  True\\
1475   T              &  True\\
1476   FALSE          &  False\\
1477   F              &  False\\
1478   \end{tabular}}
1479   \caption{Boolean Option Values}\label{t:boolarg}
1480\end{floatingtable}
1481
1482Each Sybase option value must conform to certain data type format\index{format, option}
1483and/or restrictions. Table~\ref{t:boolarg} lists
1484acceptable argument values for Boolean\index{Boolean} options, within APQ. The
1485case is not significant, but uppercase is recommended to make it stand out from
1486the surrounding Ada code.
1487
1488The following is an example of a Boolean option setting for the Sybase option STATS\_IO:
1489
1490\begin{Example}
1491
1492   "STATS_IO=TRUE"
1493
1494\end{Example}
1495
1496Some Sybase options require an integer\index{unsigned integer} (actually unsigned). Those
1497options listed in the option table\index{option table} as requiring an Unsigned value,
1498should be simply an unsigned value. The following is an example:
1499
1500\begin{Example}
1501
1502   "ROWCOUNT=1"
1503
1504\end{Example}
1505
1506String value arguments\index{string value arguments} are simply textual values that are placed between
1507the equal sign and the next comma (or end of string). The following
1508example illustrates:
1509
1510\begin{Example}
1511
1512   "AUTHOFF=sa"
1513
1514\end{Example}
1515
1516Some options are identified as taking ``String/NULL''. These options
1517will take normal string values or simply the word NULL\index{NULL options}. The value
1518NULL allows the system default to be used. The following is an example:
1519
1520\begin{Example}
1521
1522   "CHARSET=NULL"
1523
1524\end{Example}
1525
1526\begin{table}
1527   \begin{center}
1528      \begin{tabular}{ll}
1529         Value             &  Sybase Option\\
1530         \hline
1531         SUNDAY            &  CS\_OPT\_SUNDAY\\
1532         MONDAY            &  CS\_OPT\_MONDAY\\
1533         TUESDAY           &  CS\_OPT\_TUESDAY\\
1534         WEDNESDAY         &  CS\_OPT\_WEDNESDAY\\
1535         THURSDAY          &  CS\_OPT\_THURSDAY\\
1536         FRIDAY            &  CS\_OPT\_FRIDAY\\
1537         SATURDAY          &  CS\_OPT\_SATURDAY\\
1538      \end{tabular}
1539   \end{center}
1540   \caption{Weekday Option Argument Values}\label{t:wkday}
1541\end{table}
1542
1543The DATEFIRST option\index{DATEFIRST option} accepts an argument Weekday argument. The valid
1544range of values are listed in Table~\ref{t:wkday}.
1545
1546The following example shows how the DATEFIRST option is used:
1547
1548\begin{Example}
1549
1550   "DATEFIRST=SUNDAY"
1551
1552\end{Example}
1553
1554\begin{table}
1555   \begin{center}
1556      \begin{tabular}{ll}
1557      Value    &  Sybase Option\\
1558      \hline
1559      MDY      &  CS\_OPT\_FMTMDY\\
1560      DMY      &  CS\_OPT\_FMTDMY\\
1561      YMD      &  CS\_OPT\_FMTYMD\\
1562      YDM      &  CS\_OPT\_FMTYDM\\
1563      MYD      &  CS\_OPT\_FMTMYD\\
1564      DYM      &  CS\_OPT\_FMTDYM\\
1565      \end{tabular}
1566   \end{center}
1567   \caption{Date Format Argument Values}\label{t:dtfmt}
1568\end{table}
1569
1570One last category of Sybase option arguments is the DATEFORMAT argument\index{DATEFORMAT option}
1571type. The valid list of values for this type of argument are given in Table~\ref{t:dtfmt}.
1572
1573The following is an example of such an option:
1574
1575\begin{Example}
1576
1577   "DATEFORMAT=YMD"
1578
1579\end{Example}
1580
1581Table~\ref{t:syonames} lists all of the options that APQ is able to recognize for Sybase.
1582Each of the option names\index{option names} listed is equivalent to the
1583Sybase C macro\index{C macro, Sybase}
1584constant if the prefix CS\_OPT\_\index{CS\_OPT\_{*}} is added to the option name. Consult
1585the Sybase documentation for descriptions of the purpose of these
1586options and when to apply them.
1587
1588\begin{longtable}{lll}
1589Option Name       &  Data Type            &  Notes\\
1590\hline
1591ANSINULL          &  Boolean              &\\
1592ANSIPERM          &  Boolean              &\\
1593ARITHABORT        &  Boolean              &\\
1594ARITHIGNORE       &  Boolean              &\\
1595AUTHOFF           &  String               &\\
1596AUTHON            &  String               &\\
1597CHAINXACTS        &  Boolean              &\\
1598CHARSET           &  String/NULL          &  Use NULL for default\\
1599CURCLOSEONXACT    &  Boolean              &\\
1600DATEFIRST         &  Weekday              &\\
1601DATEFORMAT        &  YMD/MDY/etc.         &  May interfere with APQ\\
1602FIPSFLAG          &  Boolean              &\\
1603FORCEPLAN         &  Boolean              &\\
1604FORMATONLY        &  Boolean              &\\
1605GETDATA           &  Boolean              &\\
1606IDENTITYOFF       &  String               &\\
1607IDENTITYON        &  String               &\\
1608IDENTITYUPD\_OFF  &  String               &\\
1609IDENTITYUPD\_ON   &  String               &\\
1610ISOLATION         &  Unsigned             &  0, 1 or 3\\
1611NATLANG           &  String/NULL          &  Use NULL for default\\
1612NOCOUNT           &  Boolean              &\\
1613NOEXEC            &  Boolean              &\\
1614PARSEONLY         &  Boolean              &\\
1615QUOTED\_IDENT     &  Boolean              &\\
1616RESTREES          &  Boolean              &\\
1617ROWCOUNT          &  Unsigned             &\\
1618SHOWPLAN          &  Boolean              &  Use at your own risk\\
1619STATS\_IO         &  Boolean              &\\
1620STATS\_TIME       &  Boolean              &\\
1621STR\_RTRUNC       &  Boolean              &\\
1622TEXTSIZE          &  Unsigned             &\\
1623TRUNCIGNORE       &  Boolean              &\\
1624\caption{Sybase Option Names}\label{t:syonames}
1625\end{longtable}
1626
1627Keep in mind that not all option settings will be compatible for use
1628with APQ. Changing server date formats\index{date formats} to anything other than year-month-day
1629format, is likely to cause problems within APQ, for example.
1630
1631
1632\subsection{Procedure Set\_Notice\_Proc}
1633
1634The PostgreSQL\index{PostgreSQL} database
1635\footnote{The Set\_Notice\_Proc procedure is not available with MySQL.}
1636server sends notice\index{notice messages} messages back to the libpq\index{libpq} C library\index{library}, that the
1637APQ binding uses. These are received by a callback\index{callback}, after certain
1638database operations have been completed. While the messages are saved
1639in the Connection\_Type object (see also \Ref{Function Notice_Message}),
1640they overwrite each other as each new message comes in. For this reason,
1641it may be desireable for some applications to also receive a callback,
1642so that they can process the messages without losing them. The most
1643common reason to do this is to simply display them on standard error\index{standard error}.
1644
1645The callback\index{callback}\index{Set\_Notice\_Proc} procedure must be defined as follows:
1646\marginpar{The default setting for any new Connection\_Type object is No\_Notify.}
1647
1648\begin{Code}
1649procedure Notice_Callback(
1650   C :       in out Connection_Type;
1651   Message : in     String
1652);
1653\end{Code}
1654
1655The Set\_Notice\_Proc takes an argument named Notify\_Proc\index{Notify\_Proc} that is
1656of the following type:
1657
1658\begin{Code}
1659type Notify_Proc_Type is access
1660   procedure(
1661      C :       in out Connection_Type;
1662      Message : in     String
1663   );
1664\end{Code}
1665
1666Finally, the Set\_Notice\_Proc procedure has the following calling signature:
1667\marginpar{Note that the Reset or Disconnect call will clear any
1668registered Notify procedure.}
1669
1670\begin{Code}
1671procedure Set_Notice_Proc(
1672   C :           in out Connection_Type;
1673   Notify_Proc : in     Notify_Proc_Type
1674);
1675\end{Code}
1676
1677This call can be made at any time to change the Notify\index{notify procedure} procedure.
1678The object may or may not be connected\index{connected}. The new procedure takes effect
1679immediately upon return, and will be used when the object is connected.
1680The present implementation only maintains one such procedure.%
1681\footnote{Note that the replaced procedure is not returned. A future implementation
1682of APQ may address this.%
1683}
1684
1685
1686\subsubsection{Disabling Notify}
1687
1688The APQ\-.PostgreSQL\-.Client\index{APQ\-.PostgreSQL\-.Client} package
1689provides the special constant No\_Notify\index{No\_Notify}
1690for the application programmer to use. An example of disabling notification\index{disabling notification}
1691follows:
1692
1693\begin{Example}
1694declare
1695   C : Connection_Type;
1696begin
1697   ...
1698   -- Enable notify processing
1699   Set_Notify_Proc(C,My_Notify'Access);
1700   ...
1701   -- Disable notification
1702   Set_Notify_Proc(C,No_Notify);
1703\end{Example}
1704
1705\subsubsection{Using Standard\_Error\_Notify}
1706
1707During the debugging\index{debugging} phase of a database application, it may be useful
1708to simply have the notice messages\index{notice messages} printed on Standard\_Error\index{Standard\_Error}. To
1709do this, simply provide the access constant Standard\_Error\_Notify\index{Standard\_Error\_Notify}
1710as the second argument:
1711
1712\begin{Example}
1713declare
1714   C : Connection_Type;
1715begin
1716   ...
1717   -- Send notices to stderr
1718   Set_Notify_Proc(C,Standard_Error_Notify);
1719   ...
1720\end{Example}
1721
1722\section{Connection Operations}
1723
1724The APQ binding provides three primitives for connecting\index{connecting} and disconnecting\index{disconnecting}
1725from the database server. They are summarized in Table~\ref{t:conprims}.
1726
1727\begin{table}
1728   \begin{center}
1729      \begin{tabular}{lll}
1730         Type     &  Name              &  Purpose\\
1731         \hline
1732         proc     &  Connect           &  Connect to the database server\\
1733         proc     &  Disconnect        &  Disconnect from the database server\\
1734         proc     &  Reset             &  Disconnect if connected\\
1735      \end{tabular}
1736   \end{center}
1737   \caption{APQ Connection Primitives}\label{t:conprims}
1738\end{table}
1739
1740\subsection{Procedure Connect}
1741
1742This primitive initiates a connection attempt with the database server
1743as configured by the \Ref{Context_Setting_Operations} primitives.
1744If the connection succeeds, the procedure call returns\index{Connect}
1745successfully, leaving the Connection\_Type object in a connected state.
1746
1747
1748\begin{Code}
1749procedure Connect(
1750   C : in out Connection_Type
1751);
1752\end{Code}
1753
1754\begin{table}
1755   \begin{center}
1756      \begin{tabular}{ll}
1757         Exception Name       &  Reason\\
1758         \hline
1759         Not\_Connected       &  The connection attempt failed\\
1760         Already\_Connected   &  There is already a connection\\
1761         Failed               &  One or more configured options failed\\
1762         Use\_Error           &  Connection OK, but USE database failed\\
1763      \end{tabular}
1764   \end{center}
1765   \caption{Connect Exceptions}\label{t:conx}
1766\end{table}
1767
1768Table~\ref{t:conx} summarizes the exceptions that Connect may raise.
1769
1770The Already\_Connected\index{Already\_Connected} exception indicates that you need to disconnect
1771first, or use another Connection\_Type object if you are maintaining
1772multiple connections\index{connections, multiple}. Failed will be raised if a pending option setting
1773is unsupported or its setting has been rejected. The exception Use\_Error\index{Use\_Error}
1774indicates that the connection itself succeeded, but the selection
1775of the database failed. The connection will be returned in an unconnected\index{unconnected}
1776state when Use\_Error is raised.
1777
1778\begin{description}
1779   \item[PostgreSQL Note:] \index{PostgreSQL}The Connect primitive as of APQ 1.91 automatically executes a 'SET
1780      DATESTYLE TO ISO' \index{ISO}\index{DATESTYLE} command to guarantee that the APQ date routines
1781      will function correctly, even when the PGDATESTYLE\index{PGDATESTYLE} environment variable
1782      may choose something other than ISO. This implies however, that APQ
1783      applications should always format date information in the ISO format.
1784   \item[MySQL Note:]When MySQL\index{MySQL} returns dates in YYYYMMDD\index{YYYYMMDD} format, APQ
1785      will automatically make the necessary adjustment, based upon the length
1786      of the result.
1787\end{description}
1788
1789The following is an example call:
1790
1791\begin{Example}
1792declare
1793   C : Connection_Type;
1794begin
1795   ...
1796   begin
1797      Connect(C);
1798   exception
1799      when No_Connection =>
1800         -- Handle connection failure
1801      when Already_Connected =>
1802         ...; -- Indicates program logic problem
1803      when others =>
1804         raise;
1805   end;
1806\end{Example}
1807
1808\subsection{Connection Cloning\label{Connection Cloning}}
1809
1810Application writers may want additional connections cloned\index{cloning connections} from a
1811given connection. A web server may want to do this for example. This
1812could be performed by obtaining all of the connection information
1813from the given connection and then proceed to configure a new connection,
1814but this is tedious and error prone. To clone a new connection from
1815an existing connection, simply use the Connect\index{Connect} primitive with the
1816following calling signature (argument Same\_As is added):
1817
1818\begin{Code}
1819procedure Connect(
1820   C :       in out Connection_Type;
1821   Same_As : in     Connection_Type
1822);
1823\end{Code}
1824
1825This primitive configures object C to use the same parameters as object
1826Same\_As\index{Same\_As}. It then creates a connection to the database using these cloned\index{cloned}
1827parameters. The exceptions that may be raised are listed in Table~\ref{t:cclonx}.
1828
1829\begin{table}
1830   \begin{center}
1831      \begin{tabular}{ll}
1832         Exception Name       &  Reason\\
1833         \hline
1834         Not\_Connected       &  The connection attempt failed\\
1835         Already\_Connected   &  There is already a connection\\
1836      \end{tabular}
1837   \end{center}
1838   \caption{Connection Cloning Exceptions}\label{t:cclonx}
1839\end{table}
1840
1841The Not\_Connected\index{Not\_Connected} exception can be raised if the Same\_As connection
1842is not connected (it must be connected). This same exception can be
1843raised if the new connection fails (this should rarely happen unless
1844your database is suddenly taken down or a network failure occurs).
1845The Already\_Connected\index{Already\_Connected} exception is raised if \emph{C} is already
1846connected.
1847
1848\begin{description}
1849   \item[Note:] Note that the trace settings of the Same\_As object are not
1850      carried to the new object C. You must manually configure any trace
1851      settings you require in the newly connected object C.
1852\end{description}
1853
1854The following example shows how a procedure My\_Subr can clone
1855a new connection:
1856
1857\begin{Example}
1858procedure My_Subr(C : Connection_Type) is
1859   C2 : Connection_Type;
1860begin
1861   Connect(C2,C); -- Clone a connection
1862\end{Example}
1863
1864\subsection{Procedure Disconnect}
1865
1866The Disconnect\index{Disconnect} primitive closes the connection that was previously
1867established in the Connection\_Type\index{Connection\_Type} object. The Disconnect primitive
1868uses the following arguments:
1869
1870\begin{Code}
1871procedure Disconnect(
1872   C : in out Connection_Type
1873);
1874\end{Code}
1875
1876The list of possible exceptions for Disconnect are illustrated in Table~\ref{t:dconx}.
1877
1878\begin{table}
1879   \begin{center}
1880      \begin{tabular}{ll}
1881         Exception Name       &  Reason\\
1882         \hline
1883         No\_Connection       &  There is no connection to disconnect\index{No\_Connection}\\
1884      \end{tabular}
1885   \end{center}
1886   \caption{Disconnect Exceptions}\label{t:dconx}
1887\end{table}
1888
1889The following code fragment shows the procedure call in action:
1890
1891\begin{Example}
1892declare
1893   C : Connection_Type;
1894begin
1895   ...
1896   begin
1897      Disconnect(C);
1898   exception
1899      when No_Connection =>
1900         ...; -- Indicates program logic problem
1901      when others =>
1902         raise;
1903   end;
1904\end{Example}
1905
1906\subsection{Procedure Reset}
1907
1908The Reset\index{Reset} primitive is provided so that the programmer can recycle
1909the Connection\_Type object for use in a subsequent connection. Without
1910this primitive, the user would need to destroy the original and create
1911a new Connection\_Type. The Reset primitive accepts the following
1912arguments:
1913
1914\begin{Code}
1915procedure Reset(
1916   C : in out Connection_Type
1917);
1918\end{Code}
1919
1920In addition to closing the current connection, if it is open, the
1921notification procedure is also deregistered (if there was a Set\_Notify\_Proc\index{Set\_Notify\_Proc}
1922performed).
1923
1924No exceptions should occur. If there is a connection pending\index{pending connection}, it is
1925disconnected\index{disconnected}. If there is no connection pending, the call is ignored.
1926The following shows an example of its use:
1927
1928\begin{Example}
1929declare
1930   C : Connection_Type;
1931begin
1932   ...
1933   Reset(C);  -- C is now ready for re-use
1934\end{Example}
1935
1936\section{Connection Information Operations}
1937
1938A modular\index{modular software} piece of software may get handed a Connection\_Type object
1939as a parameter, and have a need to inquire about the details of the
1940provided connection. The function primitives that return information
1941about the connection are listed in Table~\ref{t:cinfp}.
1942
1943\begin{table}
1944   \begin{center}
1945      \begin{tabular}{ll}
1946         Function Name     &  Information Returned\\
1947         \hline
1948         Host\_Name        &  Host name of the connection\\
1949         Port              &  Port Number or Port Pathname\\
1950         DB\_Name          &  Database name\\
1951         User              &  User name for the database\\
1952         Password          &  Password for the database\\
1953         Instance          &  Instance name for the database\\
1954         Options           &  Database option parameters\\
1955      \end{tabular}
1956   \end{center}
1957   \caption{Connection Information Primitives}\label{t:cinfp}
1958\end{table}
1959
1960These function primitive specifications are listed below:
1961
1962\begin{Code}
1963function Host_Name(
1964   C : Connection_Type;
1965) return String;
1966\end{Code}
1967
1968\begin{Code}
1969function Port(
1970   C : Connection_Type;
1971) return String;  -- UNIX path
1972\end{Code}
1973
1974\begin{Code}
1975function Port(
1976   C : Connection_Type;
1977) return Integer; -- TCP/IP port
1978\end{Code}
1979
1980\begin{Code}
1981function DB_Name(
1982   C : Connection_Type;
1983) return String;
1984\end{Code}
1985
1986\begin{Code}
1987function User(
1988   C : Connection_Type;
1989) return String;
1990\end{Code}
1991
1992\begin{Code}
1993function Password(
1994   C : Connection_Type;
1995) return String;
1996\end{Code}
1997
1998\begin{Code}
1999function Instance(
2000   C : Connection_Type;
2001) return String;
2002\end{Code}
2003
2004\begin{Code}
2005function Options(
2006   C : Connection_Type;
2007) return String;
2008\end{Code}
2009
2010The Port\index{Port} primitive that returns a String is for use with database
2011connections using a UNIX socket\index{UNIX socket}\index{local socket}. The socket
2012pathname\index{pathname} is returned in this case.
2013\footnote{or at least a fragment of the pathname.}
2014
2015When called on Connection\_Type objects without a current connection,
2016an empty string\index{string, empty} is returned for any value that has not been configured
2017(for example if Set\-\_Host\-\_Name\index{Set\_Host\_Name} has not been called, Host\-\_Name\index{Host\_Name} will
2018return ""). If the value has been set, then that value is returned
2019as expected. Once the Connection\-\_Type object is connected to the
2020database however, the values will be values fetched from the library\index{library}
2021libpq\index{libpq} instead.
2022\footnote{Normally, these values should agree with what was configured.}
2023
2024The following code sample shows how to extract the host name\index{host name} and database
2025name for the current connection.
2026
2027\begin{Example}
2028procedure My_Code(C : in out Connection_Type) is
2029   Host_Name :     String := Host_Name(C);
2030   Database_Name : String := DB_Name(C);
2031begin
2032   ...
2033\end{Example}
2034
2035\begin{description}
2036\item [Sybase Note:]The Instance function primitive was added to APQ support Sybase.
2037   See the support level chart for Set\_Instance\index{Set\_Instance} on page \pageref{Set_Instance Support Chart}
2038   and other information primitives. Note also that setting and retrieving
2039   other parameters is possible in some cases, even though the information
2040   is ignored by Sybase.
2041\end{description}
2042
2043\section{General Information Operations}
2044
2045Due to the modular construction of software, it is sometimes necessary
2046to query an object for its present state. The primitives listed in Table~\ref{t:gifc}
2047for the Connection\_Type object are available for querying the state\index{query the state}
2048of the object. These are discussed in the next subsections.
2049
2050\begin{table}
2051   \begin{center}
2052      \begin{tabular}{lll}
2053         Type  &  Name              &  Purpose\\
2054         \hline
2055         func  &  Is\_Connected     &  Indicates connected state\\
2056         func  &  Error\_Message    &  Returns a error message text\\
2057      \end{tabular}
2058   \end{center}
2059   \caption{General Information for Connections}\label{t:gifc}
2060\end{table}
2061
2062\subsection{Function Is\_Connected}
2063
2064The Is\_Connected\index{Is\_Connected} function returns a Boolean result that indicates
2065the present state of the Connection\_Type object. The arguments are
2066as follows:
2067
2068\begin{Code}
2069function Is_Connected(
2070   C : Connection_Type
2071) return Boolean;
2072\end{Code}
2073
2074There are no exceptions raised by this primitive.
2075
2076The following example shows how to test if the object C is currently
2077supporting a connection. The example disconnects from the server,
2078if it determines that C is connected.
2079
2080\begin{Example}
2081declare
2082   C : Connection_Type;
2083begin
2084   ...
2085   if Is_Connected(C) then
2086      Disconnect(C);
2087      ...
2088\end{Example}
2089
2090\subsection{Function Error\_Message}
2091
2092The Error\_Message\index{Error\_Message} function makes it possible for the application
2093to report why the connection failed. This information is often crucial
2094to the user of a failed application. The arguments accepted are as
2095follows:
2096
2097\begin{Code}
2098function Error_Message(
2099   C : Connection_Type
2100) return String;
2101\end{Code}
2102
2103There are no exceptions raised by this function. If there is no present
2104connection or no present error to report, the null string is returned.
2105The following example shows how the connection failure is reported:
2106
2107\begin{Example}
2108with Ada.Text_IO;
2109...
2110declare
2111   use Ada.Text_IO;
2112
2113   C : Connection_Type;
2114begin
2115   ...
2116   begin
2117      Connect(C);
2118   exception
2119      when No_Connection =>
2120         Put_Line(Standard_Error,"Connection Failed!");
2121         Put_Line(Standard_Error,Error_Message(C));
2122         ...
2123      when Already_Connected =>
2124         ...;  -- Program logic error here
2125      when others =>
2126         raise;
2127   end;
2128\end{Example}
2129
2130\subsection{Function Notice\_Message\label{Function Notice_Message}}
2131
2132The C libpq\index{libpq} interface library\index{library}\footnote{The Notice\_Message function is
2133not available for MySQL.} provides the APQ binding with certain
2134notification messages\index{notification messages} during some calls, by means of a callback\index{callback}. Each
2135time one of these notifications is received from the database server,
2136the notification message is saved in the Connection\_Type object
2137(replacing any former notice message). The last notification message
2138received can be retreived using the Notice\_Message\index{Notice\_Message} function:
2139
2140\begin{Code}
2141function Notice_Message(
2142   C : Connection_Type
2143) return String;
2144\end{Code}
2145
2146No exception is raised, and the null string\index{null string} is returned if no notice
2147message has been registered.
2148
2149The following example illustrates one example of the Notice\_Message
2150function:
2151
2152\begin{Example}
2153with Ada.Text_IO;
2154...
2155declare
2156   use Ada.Text_IO;
2157
2158   C : Connection_Type;
2159begin
2160   ...
2161   declare
2162      Msg : String := Notice_Message(C);
2163   begin
2164      if Msg'Length > 0 then
2165         Put_Line(Standard_Error,Msg);
2166         ...
2167\end{Example}
2168
2169\subsection{In\_Abort\_State Function\label{In_Abort_State Function}}
2170
2171\Ref{Abort_State exception} documents the Abort\_State\index{Abort\_State}
2172exception, which is unique to PostgreSQL\index{PostgreSQL}. This exception is raised in
2173response to a status flag stored in the
2174APQ\-.PostgreSQL\-.Client\-.Connection\_Type object. When a transaction is
2175started, any SQL error\index{SQL error} will put the PostgreSQL database server into an
2176``\emph{abort state}'', where all current and future commands will be
2177ignored, for the connection \footnote{MySQL does not support this
2178concept, and so it does not go into an abort state.}. To permit the
2179application programmer to query this status, the In\_Abort\_State\index{In\_Abort\_State}
2180function can be used. It returns True, if an error has occurred within a
2181transaction, which requires a Rollback\_Work (\Ref{Begin, Commit and Rollback Work functions})
2182call to clear this state. The calling
2183requirements are summarized in the following table:
2184
2185\begin{Code}
2186function In_Abort_State(
2187   C : Connection_Type
2188) return Boolean;
2189\end{Code}
2190
2191Exceptions for In\_Abort\_State are summarized in Table~\ref{t:iasx}.
2192
2193\begin{table}
2194   \begin{center}
2195      \begin{tabular}{ll}
2196         Exception Name    &  Reason\\
2197         \hline
2198         Not\_Connected    &  There is no connection to query\\
2199      \end{tabular}
2200   \end{center}
2201   \caption{In\_Abort\_State Exceptions}\label{t:iasx}
2202\end{table}
2203
2204The following example shows how this function might be used:
2205
2206\begin{Example}
2207declare
2208   C : Connection_Type;
2209   Q : Query_Type;
2210begin
2211   ...
2212   Begin_Work(Q,C);
2213   ...
2214   Execute(Q,C);
2215   ...
2216   if In_Abort_State(C) then
2217      Rollback(Q,C);
2218      ...
2219   end if;
2220\end{Example}
2221
2222\section{Implicit Operations}
2223
2224There are a few implicit operations\index{implicit operations} that are performed that the programmer
2225should be aware of. They are:
2226
2227\begin{itemize}
2228   \item The Connection\_Type is subject to Finalization
2229   \item A default Commit/Rollback operation can occur at Finalization
2230\end{itemize}
2231
2232The programmer is encouraged to call Commit\_Work\index{Commit\_Work} or Rollback\_Work\index{Rollback\_Work}
2233explicitly, whenever possible. This way, the programmer is in complete
2234control of the transaction outcome.
2235
2236If a transaction has not been committed or rolled back, and the connected
2237Connection\_Type object is finalized\index{finalization}%
2238\footnote{Usually because the Connection\_Type object has fallen out of scope.%
2239}, then the default action for commit or rollback occurs. The default
2240for the APQ binding is to rollback the transaction, when the connection
2241is still active. If the programmer has disconnected\index{disconnected} from the database
2242prior to finalization, then no further action occurs. To change or
2243control the default action, use the Set\_Rollback\_On\_Finalize\index{Set\_Rollback\_On\_Finalize} procedure
2244described in the next section.
2245
2246
2247\subsection{Set\_Rollback\_On\_Finalize Procedure\label{Set_Rollback_On_Finalize Procedure}}
2248
2249The Set\_Rollback\_On\_Finalize primitive allows the programmer to
2250change the default action for the Connection\_Type object. The calling
2251requirements are summarized in the following table:%
2252
2253\begin{Code}
2254procedure Set_Rollback_On_Finalize(
2255   C :        in out Connection_Type;
2256   Rollback : in     Boolean
2257);
2258\end{Code}
2259
2260To change the default to COMMIT WORK\index{COMMIT WORK} when the Connection\_Type object
2261finalizes, peform the following call:
2262
2263\begin{Example}
2264declare
2265   C : Connection_Type;
2266begin
2267   Set_Rollback_On_Finalize(C,False); -- Commit on Finalize
2268\end{Example}
2269
2270\subsection{Will\_Rollback\_On\_Finalize Function\label{Will_Rollback_On_Finalize Function}}
2271
2272Programs sometimes need to inquire about the state of the Connection\_Type
2273object that they may have been passed. To inquire about the commit
2274or rollback default, the Will\_Rollback\_On\_Finalize\index{Will\_Rollback\_On\_Finalize} function can
2275be called. The following table summarizes the calling requirements:
2276
2277\begin{Code}
2278function Will_Rollback_On_Finalize(
2279   C : Connection_Type
2280) return Boolean;
2281\end{Code}
2282
2283\section{Trace Facilities\label{Trace Facilities}}
2284
2285No matter how carefully a programmer writes a new program, problems
2286develop that are often difficult to understand. Good tracing facilities\index{trace facilities}
2287allow the problem to be quickly understood and corrected.
2288
2289To gain trace support using APQ, it is only necessary to perform the
2290following steps:
2291
2292\begin{enumerate}
2293   \item Open a trace capture file with Open\_DB\_Trace
2294   \item Optionally enable/disable tracing at various points in the program
2295      with Set\_Trace%
2296      \footnote{Tracing is enabled by default after a Open\_DB\_Trace call.}
2297   \item Perform your SQL operations
2298   \item Close the trace capture file with Close\_DB\_Trace%
2299      \footnote{Or allow it to be closed when the Connection\_Type object is finalized.}
2300\end{enumerate}
2301
2302The Open\_DB\_Trace\index{Open\_DB\_Trace} procedure takes a Trace\_Mode\_Type\index{Trace\_Mode\_Type} parameter
2303that decides what trace content is being collected. The valid enumerated
2304choices are listed in Table~\ref{t:tmchoic}.
2305
2306\begin{table}
2307   \begin{center}
2308      \begin{tabular}{ll}
2309         Value           & Description\\
2310         \hline
2311         APQ.Trace\_None & Collect no trace information (no file is written/created)\\
2312         APQ.Trace\_DB   & Collect only C library trace information%
2313            \footnote{Prior to APQ 2.0, this was Trace\_libpq.}\\
2314         APQ.Trace\_APQ  & Collect only APQ SQL trace information\\
2315         APQ.Trace\_Full & Collect both database library and Trace\_APQ information\\
2316      \end{tabular}
2317   \end{center}
2318   \caption{Trace\_Mode\_Type Choices}\label{t:tmchoic}
2319\end{table}
2320
2321The Trace\_None\index{Trace\_None} value is provided so that the Open\_DB\_Trace procedure
2322does not need to be coded around if a trace variable is supplied,
2323which may or may not request tracing. Close\_DB\_Trace\index{Close\_DB\_Trace} can be called
2324on a Connection\_Type\index{Connection\_Type} for which Trace\_None is in effect, without
2325any exception being thrown (the call is ignored).
2326
2327Trace\_DB\index{Trace\_DB} provides only what the C library (libpq\index{libpq} for PostgreSQL\index{PostgreSQL})
2328provides. This may be useful to the database software maintainers,
2329if they want a trace of the activity that you are reporting problems
2330with.
2331
2332Trace\_APQ\index{Trace\_APQ} is what the author considers to be the most useful output
2333format to an APQ developer. The trace output in this mode is such
2334that the extra trace information is provided in SQL comment\index{SQL comment} form.
2335The actual queries that are executed are in their natural SQL form.
2336The captured Trace\_APQ trace then, is in a format that can be played
2337back, reproducing exactly what the application performed.%
2338\footnote{There are limitations however, since the blob functions are not traced
2339at the present release.%
2340} The full trace or portions of it then can be used to help debug SQL
2341related problems.
2342
2343The following shows a sample of what the Trace\_APQ output looks like:
2344
2345\begin{SQL}
2346-- Start of Trace, Mode=TRACE_APQ
2347-- SQL QUERY:
2348BEGIN~WORK}
2349;
2350-- Result: 'BEGIN'
2351
2352-- SQL QUERY:
2353INSERT INTO DOCUMENT
2354       (NAME,DOCDATE,BLOBID,CREATED,MODIFIED,ACCESSED)
2355VALUES ('compile.adb','2002-08-12~21:09:25',3339004,
2356        '2002-08-12~21:59:48','2002-08-12~21:09:25',
2357        '2002-08-19~22:11:36')
2358;
2359-- Result: 'INSERT 3339005 1'
2360
2361-- SQL QUERY:
2362SELECT DOCID
2363FROM DOCUMENT
2364WHERE OID = 3339005
2365;
2366-- Result: 'SELECT'
2367...
2368-- SQL QUERY:
2369COMMIT WORK
2370;
2371-- Result: 'COMMIT'
2372-- End of Trace.
2373\end{SQL}
2374
2375The following subsections describe the primitives that provide support
2376for trace facilities.
2377
2378
2379\subsection{Procedure Open\_DB\_Trace}
2380
2381To start any capture of trace\index{trace capture} information, you must specify the name
2382of the text file to be written to. The file must be writable to the
2383current process. The Connection\_Type object must be connected prior
2384to calling Open\_DB\_Trace\index{Open\_DB\_Trace}:
2385
2386\begin{Code}
2387procedure Open_DB_Trace(
2388   C :        in out Connection_Type;
2389   Filename : in     String;
2390   Mode :     in     Trace_Mode_Type := Trace_APQ
2391);
2392\end{Code}
2393
2394Table \ref{t:odbtx} lists the possible exceptions for Open\_DB\_Trace.
2395
2396\begin{table}
2397   \begin{center}
2398      \begin{tabular}{ll}
2399         Exception Name & Reason\\
2400         \hline
2401         Not\_Connected & There is no connection\\
2402         Tracing\_State & Trace is already enabled\\
2403      \end{tabular}
2404   \end{center}
2405   \caption{Open\_DB\_Trace Exceptions}\label{t:odbtx}
2406\end{table}
2407
2408Upon return from the Open\_DB\_Trace procedure, a text file will be
2409created and ready to have trace entries written to it.%
2410\footnote{Note that trace entries are buffered by C standard I/O routines, so
2411trace information may be held in memory buffers before it is flushed
2412out or closed.%
2413}
2414
2415The following example shows how a call might be coded:
2416
2417\begin{Example}
2418declare
2419   C : Connection_Type;
2420begin
2421   ...
2422   Open_DB_Trace(C,"./bugs.sql",Trace_APQ);
2423\end{Example}
2424
2425\subsection{Procedure Close\_DB\_Trace}
2426
2427Closing the tracing facility for a connection, suspends all further
2428trace writes. Once this has been done, the effect of Set\_Trace\index{Set\_Trace} is
2429superceeded, preventing any further trace information being written.
2430The calling requirements are outlined in the following table:
2431
2432\begin{Code}
2433procedure Close_DB_Trace(
2434   C : in out Connection_Type
2435);
2436\end{Code}
2437
2438If the Open\_DB\_Trace call was made with the Mode parameter set to
2439Trace\_None, then the call to Close\_DB\_Trace\index{Close\_DB\_Trace} has no effect and is
2440ignored for programmer convenience.
2441
2442No exceptions are raised.
2443
2444An example call is shown below:
2445
2446\begin{Example}
2447declare
2448   C : Connection_Type;
2449begin
2450   ...
2451   Open_DB_Trace(C,"./bugs.sql",Trace_APQ);
2452   ...
2453   Close_DB_Trace(C);
2454\end{Example}
2455
2456\subsection{Procedure Set\_Trace}
2457
2458In large applications where large numbers of SQL statements are executed,
2459it may be desirable to trace only certain parts of its execution in
2460a dynamic fashion. The Set\_Trace\index{Set\_Trace} primitive gives the programmer a
2461way to disable and re-enable tracing at strategic\index{strategic tracing} points within the
2462application. The calling requirements are summarized as follows:
2463
2464\begin{Code}
2465procedure Set_Trace(
2466   C :        in out Connection_Type;
2467   Trace_On : in     Boolean := True
2468);
2469\end{Code}
2470
2471Tracing is enabled by default, after a successful call to Open\_DB\_Trace
2472is made (unless Mode was Trace\_None\index{Trace\_None}).
2473
2474There are no exceptions raised.
2475
2476Note that it is considered safe to invoke Set\_Trace, even if a former
2477Open\_DB\_Trace call was not successfully performed, or the trace
2478mode was Trace\_None. This allows the application to retain strategic
2479Set\_Trace calls without having to remove them, when the Open\_DB\_Trace
2480call is disabled%
2481\footnote{Setting Mode to Trace\_None effectively disables the trace facility
2482without requiring any code changes.%
2483} or commented out.
2484
2485
2486\subsection{Function Is\_Trace}
2487
2488It may be helpful to the developer that is tracking down a problem
2489to know when tracing is enabled or not. The Is\_Trace\index{Is\_Trace} function returns
2490true when the trace collection file is receiving trace information.
2491The calling arguments are listed below:%
2492
2493Note that the returned value tracks the last value provided by
2494Set\_Trace, whether or not an open trace file has been created/opened.
2495
2496\begin{Code}
2497function Is_Trace(
2498   C : Connection_Type;
2499) return Boolean;
2500\end{Code}
2501
2502Note that the initial state of the Connection\_Type object is to have
2503Is\_Trace to return True. Also after a successful Open\_DB\_Trace,
2504Is\_Trace will return True.
2505
2506An example showing its use is given below:
2507
2508\begin{Example}
2509declare
2510   C : Connection_Type;
2511begin
2512   ...
2513   Open_DB_Trace(C,"./bugs.sql",Trace_APQ);
2514   ...
2515   if Is_Trace(C) then
2516      -- We are collecting trace info..
2517\end{Example}
2518
2519\section{Generic Database Operations}
2520
2521APQ 2.0 and later is designed so that all but the most specialized
2522database operations, can be performed, given only a Root\_Connection\_Type'Class\index{Root\_Connection\_Type'Class}
2523object (declared in top level package APQ). The following sections
2524describe some generic database related primitives that are necessary
2525for successful generic database support.
2526
2527
2528\subsection{Package APQ}
2529
2530Root object support\index{root object support} is provided in the package APQ\index{APQ, package}. Generic database
2531code will normally only use this package:
2532
2533\begin{Code}
2534   with APQ;
2535
2536   use APQ;  -- Optional use clause
2537\end{Code}
2538
2539The data types that will be used will be:
2540
2541\begin{itemize}
2542   \item APQ.Root\_Connection\_Type'Class
2543   \item APQ.Root\_Query\_Type'Class\index{Root\_Query\_Type'Class}
2544\end{itemize}
2545
2546The generic primitives that will be covered in the next section are:
2547
2548\begin{itemize}
2549   \item APQ.Engine\_Of
2550   \item APQ.New\_Query
2551\end{itemize}
2552
2553\subsection{Predicate Engine\_Of\label{Generic Database Engine_Of}}
2554
2555Given a Root\_Connection\_Type'Class object, generic database code
2556sometimes needs to determine which specific database is being used.
2557This allows the code to make special SQL syntax changes, depending
2558upon the technology being used (for example, MySQL\index{MySQL} permits the use
2559of a \emph{LIMIT}\index{LIMIT} keyword in queries).
2560
2561The Engine\_Of\index{Engine\_Of} primitive (dispatching) will identify the
2562database technology that is being used:
2563
2564\begin{Code}
2565type Database_Type is (
2566   Engine_PostgreSQL,
2567   Engine_MySQL,
2568   Engine_Sybase
2569);
2570
2571function Engine_Of(
2572   C : Connection_Type
2573) return Database_Type;
2574\end{Code}
2575
2576The following example code shows how to test if a PostgreSQL\index{PostgreSQL} database
2577is being used:
2578
2579\begin{Example}
2580with APQ; use APQ;
2581...
2582procedure App(C : Root_Connection_Type'Class) is
2583begin
2584   ...
2585   if Engine_Of(C) = Engine_PostgreSQL then
2586      ...
2587\end{Example}
2588
2589\subsection{Primitive New\_Query\label{Query_Type Factories}}
2590
2591Normally, an application database procedure will receive a connection
2592object as one of its input parameters. Generally, this connection
2593is established in the main program and then used by the program components
2594as required. However, to pass the parameter in a generic way (allowing
2595for polymorphism), you would declare the procedure's argument as receiving
2596data type Root\_Connection\_Type'Class.
2597
2598Within the called procedure however, you will need a Query\_Type object.
2599This too could be passed in as an argument, but this is unnecessary.
2600At other times, you may need additional Query\_Type objects for temporary
2601use. What you need is a convenient way to create a Query\_Type object
2602that matches the connection that you have received as a parameter. This
2603is done by the New\_Query function\index{New\_Query}.
2604
2605If your connection object is a:
2606
2607\begin{Code}
2608
2609   APQ.PostgreSQL.Client.Connection_Type
2610
2611\end{Code}
2612
2613object, then your application will want to create a:
2614
2615\begin{Code}
2616
2617   APQ.PostgreSQL.Client.Query_Type
2618
2619\end{Code}
2620
2621object. You want to avoid tests like:
2622
2623\begin{Example}
2624
2625if Connection is in APQ.PostgreSQL.Client.Connection_Type then
2626   ...
2627elsif Connection is in APQ.MySQL.Client.Connection_Type then
2628   ...
2629elsif Connection is in APQ.Sybase.Client.Connection_Type then
2630   ...
2631
2632\end{Example}
2633
2634The above example code would force your portable code to also ``with''\index{with}
2635the following packages:
2636
2637\begin{Example}
2638with APQ.PostgreSQL.Client;
2639with APQ.MySQL.Client;
2640...
2641\end{Example}
2642
2643which would be very inconvenient and unnecessary.
2644
2645To make portable\index{portable} database programming easier, APQ provides a dispatching\index{dispatching}
2646Query\_Type object factory primitive that can be used for this purpose.
2647For example:
2648
2649\begin{NumberedExample}
2650with APQ;
2651use APQ;
2652
2653procedure My_Generic_App(C : Root_Connection_Type'Class) is
2654   Q : Root_Query_Type'Class := New_Query(C);(*@\label{Ex:New_Query_Assgn}@*)
2655begin
2656   Prepare(Q,"SELECT NAME,INCOME");
2657   Append_Line(Q,"FROM~SALARIES");
2658\end{NumberedExample}
2659
2660The assignment to Q in line~\ref{Ex:New_Query_Assgn}, shows the
2661application of the primitive New\_Query. This dispatching
2662primitive returns the correct Query\_Type object that matches the
2663connection that was given. The primitive New\_Query is more formally
2664presented as follows:
2665
2666\begin{Code}
2667function New_Query(
2668   C : Root_Connection_Type
2669) return Root_Query_Type'Class;
2670\end{Code}
2671
2672\subsection{Query\_Type Assignment\label{Query_Type Cloning}}
2673
2674Prior to APQ version 2.0, the Query\_Type object was a \emph{limited}\index{limited tagged type}
2675tagged type. This meant that the Query\_Type object was never able
2676to be assigned to another Query\_Type object. With the need for a
2677factory\index{factory} primitive like \textbf{New\_Query} it was necessary to lift
2678that restriction (otherwise the factory was unable to return the created
2679object). So the Root\_Query\_Type and derived forms, permit assignment
2680as of APQ version 2.0 and later.
2681
2682When a Query\_Type is assigned in APQ, nothing spectacular happens.
2683In fact, the contents of the object on the right hand side are effectively
2684ignored, leaving a new object on the left side. The following example
2685shows how Q1 and Q2 are essentially the same:
2686
2687\begin{NumberedExample}
2688declare
2689   Q0 : Query_Type;
2690   Q1 : Query_Type;
2691   Q2 : Query_Type;
2692begin
2693   ...
2694   Q1 := Q0;   -- Q1 becomes initialized (Q0 ignored)(*@\label{Ex:Q1}@*)
2695   Clear(Q2);  -- Initialize Q2(*@\label{Ex:Q2}@*)
2696\end{NumberedExample}
2697
2698In this example, both Q1~(line~\ref{Ex:Q1}) and Q2~(line~\ref{Ex:Q2})
2699end up in the same state, and no state information is taken from Q0. You
2700might wonder why this would be implemented. The following example code
2701fragment illustrates why this is convenient and useful:
2702
2703\begin{NumberedExample}
2704with APQ;
2705usse APQ;
2706
2707procedure My_Generic_App(C : Root_Connection_Type'Class) is
2708   Q : Root_Query_Type'Class := New_Query(C);
2709begin
2710   Prepare(Q,"SELECT NAME, INCOME");
2711   Append(Q, "FROM~SALARIES");
2712   Execute(Q,C);
2713   ...
2714   declare
2715      Q2 : Root_Query_Type'Class := Q;(*@\label{Ex:Q_Clone}@*)
2716   begin
2717      ...
2718   end;
2719\end{NumberedExample}
2720
2721The example illustrates that the assignment (line~\ref{Ex:Q_Clone}) is
2722simply a convenient factory of its own kind. It is also likely to be
2723slightly more efficient than the New\_Query primitive on the
2724connection. Think of assignment of Query\_Type objects as cloning\index{cloning}
2725operations. The assigned object becomes a fresh initialized clone of the
2726Query\_Type object on the right hand side of the assignment.
2727
2728\chapter{SQL Query Support}
2729
2730Once a database connection has been established, the application is
2731ready to invoke operations on the database server. To ease the programmer's
2732burden in keeping track of the various components involved in these
2733transactions, the Query\_Type object is provided. The Query\_Type\index{Query\_Type}
2734object and the Connection\_Type object are used together when it comes
2735time to execute the query. Some operations require the connection
2736object, while others do not.
2737
2738There are a large number of primitives associated with the Query\_Type
2739object. Most of them are related to the large number of data types
2740that are supported. These Query\_Type primitives fall into the following
2741basic categories:
2742
2743\begin{enumerate}
2744   \item Object initialization
2745   \item SQL Query building
2746   \item SQL Execution on the Database server
2747   \item Transaction operations
2748   \item Fetch operations
2749   \item Column information functions
2750   \item Value fetching functions
2751   \item Value and Indicator fetching procedures
2752   \item Information operations
2753\end{enumerate}
2754
2755In addition to these, are a number of generic functions and procedures
2756that permit the APQ user to custom tailor the API to his own specialized
2757Ada data types. This allows applications to continue the follow the
2758healthy tradition of using strong data types. There is no need for
2759a database application to take a back seat to safety\index{safety}.
2760
2761\section{Initialization \label{SQL Initialization}}
2762
2763The Query\_Type object is initialized when the object is created.
2764However, the Query\-\_Type object can be re-used as various SQL\index{SQL}
2765operations are performed by the program. To re-use the Query\_Type
2766object, one of the primitives in Table~\ref{t:qinit} may be used to recycle it for
2767re-use.
2768
2769\begin{table}
2770   \begin{center}
2771      \begin{tabular}{lll}
2772         Type  &  Name     &  Purpose\\
2773         \hline
2774         proc  &  Clear    &  Clear object and re-initialize\\
2775         proc  &  Prepare  &  Reinitialize with start of new SQL query\\
2776      \end{tabular}
2777   \end{center}
2778   \caption{Query Initialization}\label{t:qinit}
2779\end{table}
2780
2781The Clear\index{Clear} procedure does the initialization of the Query\_Type object.
2782The Prepare primitive implicitly invokes Clear
2783\footnote{Consequently, your application need not invoke Clear() prior to calling
2784Prepare().} and additionally starts the building of an SQL query. Very short
2785SQL statements may comletely specified by the Prepare API call. Longer
2786queries can be completed with some of the other primitives to be discussed
2787in this section.
2788
2789\subsection{Procedure Clear}
2790
2791With one exception, the Clear\index{Clear} primitive completely resets the state
2792of the Query\_Type object. This function primitive serves to basic
2793purposes:
2794
2795\begin{enumerate}
2796\item Resets the object to its initial state so that it can be reused for a new query.
2797\item Releases any results of the current query (close cursors etc.)
2798\end{enumerate}
2799
2800When performed after a query has been executed, this primitive releases
2801all results from the query. For Sybase, this can include issuing a
2802cancel back to the server and flushing all pending row results that
2803have not been retrieved by the APQ client program.
2804
2805Clear accepts the Query\_Type object as its only argument:
2806
2807\begin{Code}
2808procedure Clear(
2809   Q : in out Query_Type
2810);
2811\end{Code}
2812
2813The one exception to clearing state however, is that the SQL case\index{case policy}
2814policy remains unchanged. If prior to the clear, the SQL case policy
2815is set to Preserve\_Case\index{Preserve\_Case}, it will remain so after the Clear call.
2816
2817There are no exceptions raised by this call.
2818
2819The use of the Clear primitive is recommended after all SQL processing
2820related to the query has been completed. This permits any database
2821server results to be released. Think of it as ``closing''\index{closing a query} the
2822query. Note however, that object finalization\index{finalization} will take care of this,
2823if the job is left unfinished by the programmer.
2824
2825The following example illustrates it's use:
2826
2827\begin{Example}
2828declare
2829   C : Connection_Type;
2830   Q : Query_Type;
2831begin
2832   ...
2833   Clear(Q);
2834\end{Example}
2835
2836\subsubsection{Performance Issue}
2837
2838There is one particular case where calling Clear is vitally important
2839for some database products. Let's use an example where you are fetching
2840the most recent stock price from a price history file. Here is the
2841table declaration:
2842
2843\begin{SQL}
2844CREATE TABLE PRICE_HIST (
2845   SECURITY    CHAR(10) NOT NULL,
2846   PRICE_DATE  DATE NOT NULL,
2847   PRICE       REAL,
2848   PRIMARY KEY (SECURITY,PRICE_DATE)
2849);
2850\end{SQL}
2851
2852With this table holding price history, keyed by the security name
2853and date, we can lookup the most recent price with a subroutine something
2854like the following:
2855
2856\begin{NumberedExample}
2857procedure Last_Price(
2858   C :        in out Root_Connection_Type'Class;
2859   Security : in     String;
2860   Price :       out APQ_Double
2861) is
2862   function Value is new Float_Value(APQ_Double);
2863
2864   Q : Root_Query_Type'Class := New_Query(C);(*@\label{Ex:TheQ}@*)
2865begin
2866
2867   Begin_Work(Q,C);
2868
2869   Prepare(Q,    "SELECT SECURITY,PRICE_DATE,PRICE");
2870   Append_Line(Q,"FROM PRICE_HIST");
2871   Append(Q,     "WHERE SECURITY = ");
2872   Append_Quoted(Q,C,Security,Line_Feed);
2873   Append_Line(Q,"ORDER BY SECURITY,PRICE_DATE DESC");(*@\label{Ex:OrderBy}@*)
2874
2875   if Engine_Of(C) = Engine_MySQL then
2876      Append_Line(Q,"LIMIT 1");(*@\label{Ex:Limit1}@*)
2877   end if;
2878
2879   Execute(Q,C);
2880
2881   begin
2882      Fetch(Q);
2883   exception
2884      when No_Tuple =>
2885         raise;   -- No price found!
2886   end;
2887
2888   Price := Value(Q,3);
2889   Clear(Q);\label{Ex:Clear}
2890
2891end Last_Price;
2892\end{NumberedExample}
2893
2894In this example, you can see that MySQL\index{MySQL} is covered by adding the "LIMIT 1"\index{LIMIT}
2895clause in line~\ref{Ex:Limit1}.\footnote{MySQL will limit the results to 1 row, if any.}
2896PostgreSQL\index{PostgreSQL} does not have a problem with this type of query because each row is
2897fetched on demand. Sybase\index{Sybase} however, will start returning all the rows
2898that it has available, in the order specified by the "ORDER BY"\index{ORDER BY} clause
2899(line~\ref{Ex:OrderBy}).
2900
2901Given that the routine Last\_Price only calls Fetch\index{Fetch}
2902once, there is no point in the Sybase server producing and sending
2903more row data down the connection to the APQ client program. For this
2904reason, a call to Clear\index{Clear} (line~\ref{Ex:Clear}) will send a cancel notice to the Sybase server
2905to stop producing additional rows. It will also clear out any row data on
2906the connection that has not been fetched by the client program.
2907
2908In this particular example, the Query\_Type object Q (line~\ref{Ex:TheQ}) would have been
2909finalized\index{finalized} anyway upon return from Last\_Price. Finalized Query\_Type
2910objects always perform the equivalent of a call to Clear prior to
2911releasing the object storage. However, it is important to explicitly
2912call Clear\index{Clear} if you have many other operations that follow the query
2913performed in order to allow a timely cancel if necessary and to release
2914any pending query results.
2915
2916
2917\subsection{Procedure Prepare\label{Procedure Prepare}}
2918
2919The Prepare\index{Prepare} primitive goes one step further than Clear
2920in that it readies the object for the start of an SQL\index{SQL} statement build.
2921If the query is short, this will be the only building step required.
2922As in the case of Clear, the SQL case policy\index{case policy} is unchanged however.
2923
2924The Prepare procedure takes the following arguments:
2925
2926\begin{Code}
2927procedure Prepare(
2928   Q :     in out Query_Type;
2929   SQL :   in     String;
2930   After : in     String := Line_Feed
2931);
2932\end{Code}
2933
2934The SQL argument defines the start of your SQL\index{SQL} statement. The
2935After argument may supply either the default (line feed)\index{line feed} or
2936some other text to append to the SQL text\index{SQL text}.
2937It is provided as a programmer convenience, since many times the
2938programmer will need to append a comma for example.
2939
2940There are no exceptions raised by this call.
2941
2942The following code shows an example of building a query to drop a
2943table:
2944
2945\begin{Example}
2946declare
2947   Q : Query_Type;
2948begin
2949   ...
2950   Prepare(Q,"DROP TABLE DEAD_WEIGHT");
2951\end{Example}
2952
2953\section{SQL Query Building \label{SQL Query Building}}
2954
2955The previous section primitives ``cleared'' the Query\_Type for
2956a new query. The primitives provided in this section help to build
2957a new SQL query or to continue (append to)\index{append} the one started by the
2958Prepare call in \Ref{Procedure Prepare}. The programmer may
2959start\index{start} with a Prepare call and follow it by a number of ``append''
2960calls, or call Clear and build upon an empty query\index{empty query} and skip the
2961Prepare. ``PREPARE''\index{PREPARE} however, is a traditional first step
2962in embedded SQL\index{embedded SQL} software, so this tradition comes recommended
2963by the author.
2964
2965There are two broad categories of support for creating SQL queries\index{SQL queries}.
2966They are:
2967
2968\begin{enumerate}
2969   \item Append\index{Append} a value to the SQL query
2970   \item Encode\index{Encode} a value or NULL\index{NULL}, to the SQL query.
2971\end{enumerate}
2972
2973Both of these categories append to the current query. Primitives in
2974category 2 , are prefixed with Encode and will be described
2975later in the present chapter.
2976
2977The Append category of support is useful for values that are never
2978\emph{NULL} (in SQL terms these columns that are declared as ``NOT
2979NULL''\index{NOT NULL}). The Encode category of support is provided for values in
2980your application that may be in the NULL\index{NULL} state. It is not absolutely
2981required that the Encode support be used, since it is possible for
2982the application to test for a NULL value. However, the programmer
2983will find that the Encode support provides application coding convenience
2984and economy of expression. With compact code, better readability\index{readability} and
2985safety\index{safety} is normally obtained.
2986
2987Within category 1, there are five groups of primitives%
2988\footnote{The generic procedures have been lumped in with the primitives.%
2989} that build on the present query. They are:
2990
2991\begin{enumerate}
2992   \item Append a string
2993   \item Append a string and a \emph{{}``newline''}
2994   \item Append a quoted string%
2995      \footnote{Quoted values are always spared from any automatic case conversions,
2996      if any are applied.}
2997   \item Append non string types
2998   \item Append using generic procedures for custom types
2999\end{enumerate}
3000
3001Encode\index{Encode} support on the other hand, only provides for the needs of variables
3002that must be communicated to the database server. As a result, the
3003encode procedures consist only of the following two groups:
3004
3005\begin{enumerate}
3006   \item Encode non-string\index{non-string types} types
3007   \item Encode using generic procedures for custom types\index{custom types}
3008\end{enumerate}
3009
3010Presently only the second group is provided for by the APQ binding.%
3011\footnote{The reasoning is that most of the time, the user will want to instantiate
3012the generic procedures anyway. This permits both the data type and
3013the null indicator\index{null indicator} type to be a custom application type.%
3014} A future release may expand on category 1 support.
3015
3016The append procedures (category 1) will be described first and then
3017followed by the encode procedures (category 2).
3018
3019
3020\subsection{Append SQL String}
3021
3022The Append\index{Append} procedure permits the programmer to append text to the
3023SQL query being saved in the Query\_Type object. Unlike Prepare\index{Prepare},
3024Append does not clear the object. Append continues to add
3025SQL text\index{SQL text} to the query already gathered by the object Q (below):
3026
3027\begin{Code}
3028procedure Append(
3029   Q :     in out Query_Type;
3030   SQL :   in     String;
3031   After : in     String := ""
3032);
3033\end{Code}
3034
3035\begin{Code}
3036procedure Append(
3037   Q :     in out Query_Type;
3038   SQL :   in     Ada.Strings.Unbounded.Unbounded_String;
3039   After : in     String := ""
3040);
3041\end{Code}
3042
3043There are no exceptions raised by this call.
3044
3045The following example shows how Append is used:
3046
3047\begin{Example}
3048declare
3049   Q : Query_Type;
3050begin
3051   ...
3052   Prepare(Q,"SELECT CUSTNO,CUST_NAME");
3053   Append(Q, "FROM CUSTOMER");
3054\end{Example}
3055
3056Note that the Prepare\index{Prepare} call uses a default argument After=New\_Line\index{After}\index{New\_Line},
3057while Append uses a null string\index{null string} default.
3058You can put a line break in the SQL query by supplying the
3059value New\_Line in the argument "After" if you like.
3060The following example illustrates the use of Prepare and Append:
3061
3062\begin{Example}
3063declare
3064   Q : Query_Type;
3065   Col_Name_1 : constant String := "CUSTNO";
3066   Col_Name_2 : constant String := "CUST_NAME";
3067begin
3068   ...
3069   Prepare(Q,"SELECT ");
3070   Append(Q,Col_Name_1,",");
3071   Append(Q,Col_Name_2,Line_Feed);
3072   Append(Q,"FROM CUSTOMER");
3073\end{Example}
3074
3075This example builds up the same query that the previous example did,
3076except that the column names were provided by string variables\index{string variables}.
3077
3078\subsection{Append SQL Line\label{Append SQL Line}}
3079
3080The Append\_Line\index{Append\_Line} procedure is provided for added convenience and program
3081readability\index{readability}. The same effect can be had with a string Append call,
3082using string APQ.Line\_Feed supplied as the After\index{After} argument.
3083The Append\_Line procedure has the following specification:
3084
3085\begin{Code}
3086procedure Append_Line(
3087   Q :   in out Query_Type;
3088   SQL : in     String;
3089);
3090\end{Code}
3091
3092The Append\_Line procedure is one of the few that does not sport an
3093\emph{After} argument.
3094
3095
3096\subsection{Append Quoted SQL String}
3097
3098Don't quote\index{quoted strings} your own strings at home. There are several reasons why
3099supplying your own quotes to a call to the normal Append call is a
3100bad idea:
3101
3102\begin{enumerate}
3103   \item Some characters must be encoded\index{encoded} or escaped\index{escaped}, if they occur in the string.
3104   \item SQL portability\index{portability} is enhanced, since encoding and escaping\index{escaping} varies from
3105      database vendor to vendor.
3106   \item Internationalization\index{Internationalization} chosen by the user may require different processing.
3107   \item Quoted\index{quoted strings} strings should not be changed to upper or lowercase\index{lowercase} (by APQ).
3108\end{enumerate}
3109
3110The Append\_Quoted\index{Append\_Quoted} procedure call is designed to make it easier for
3111the programmer to supply a string value that may contain special characters
3112within it. Since a string value is already supplied by APQ with outer\index{outer quotes}
3113quotes, any quote\index{quote} appearing within the string must be quoted. The
3114Append\_Quoted procedure provides the necessary outer quotes\index{quotes}
3115for the sring value and escapes\index{escapes} any special characters\index{special characters}
3116occuring within it as well.
3117
3118Another very important reason for using this API call for quoted strings
3119is that this will prevent the APQ library from changing the case of\index{case of SQL}
3120any SQL text that is created. This is true no matter what the current
3121SQL case policy\index{case policy} is (see type APQ\-.SQL\-\_Case\-\_Type on page \pageref{SQL_Case_Type Choices}).
3122Any string segment\index{string segment} that was added to the query with this API call
3123will not have its case changed when the query is executed or the text
3124of the SQL is returned in a call to the To\_String\index{To\_String} function.
3125
3126There are two Append\_Quoted procedures, which differ only in the data
3127type of the \emph{SQL} argument:
3128
3129\begin{Code}
3130procedure Append_Quoted(
3131   Q :          in out Query_Type;
3132   Connection : in out Root_Connection_Type'Class;
3133   SQL :        in     String;
3134   After :      in     String := ""
3135);
3136\end{Code}
3137
3138\begin{Code}
3139procedure Append_Quoted(
3140   Q :          in out Query_Type;
3141   Connection : in out Root_Connection_Type'Class;
3142   SQL :        in     Ada.Strings.Unbounded.Unbounded_String;
3143   After :      in     String := ""
3144);
3145\end{Code}
3146
3147Notice that this particular API call requires a connection\index{connection}. The reason
3148for this is that some databases require the server to make the appropriate
3149choices dealing with internationalized\index{internationalized} character sets\index{character sets}. The quoting\index{quoting}
3150conventions also vary from database to database, so APQ relies upon
3151the database vendor software to perform the quoting for you.
3152
3153The following example illustrates the use of this call (using the
3154String type):
3155
3156\begin{Example}
3157declare
3158   C :               Connection_Type;
3159   Q :               Query_Type;
3160   Freds_Emporium :  String := "Fred's Emporium";
3161begin
3162   ...
3163   Prepare(Q,    "SELECT COMPNO,COMPANY_NAME");
3164   Append_Line(Q,"FROM SUPPLIER");
3165   Append(Q,     "WHERE COMPANY_NAME = ");
3166   Append_Quoted(Q,C,Freds_Emporium,New_Line);
3167\end{Example}
3168
3169The effect of these calls is to build an SQL query\index{SQL} that looks as follows
3170(for PostgreSQL\index{PostgreSQL}):
3171
3172\begin{SQL}
3173SELECT COMPNO,COMPANY_NAME
3174FROM SUPPLIER
3175WHERE COMPANY_NAME = 'Fred\'s Emporium'
3176\end{SQL}
3177
3178Notice how the quote character was escaped for use by the PostgreSQL\index{PostgreSQL}
3179database server. Note also that even though the SQL case policy\index{case policy} was to
3180use Upper\_Case\index{Upper\_Case}, the case of the quoted text was preserved.
3181
3182APQ will automatically adjust the quoting conventions\index{quoting conventions} to match the
3183database being used. The same example above when used for Sybase\index{Sybase},
3184would produce the following SQL text\index{SQL text} instead:
3185
3186\begin{SQL}
3187SELECT COMPNO,COMPANY_NAME
3188FROM SUPPLIER
3189WHERE COMPANY_NAME = 'Fred''s Emporium'
3190\end{SQL}
3191
3192Sybase uses a doubled-up quote\index{doubled-up quote} instead.
3193
3194Using APQ's Append\_Quoted frees the programmer from worrying about
3195quoting conventions and guarantees that the case of the text will be
3196preserved.
3197
3198\subsection{Append Non-String Types to SQL Query}
3199
3200A fairly large set of builtin non-string\index{non-string types} data types are supported by varied
3201Append calls that differ in the second argument V. The following
3202is a list of their specifications:
3203
3204\begin{Code}
3205procedure Append(
3206   Q :     in out Query_Type;
3207   V :     in     APQ_Boolean;
3208   After : in     String := ""
3209);
3210\end{Code}
3211
3212\begin{Code}
3213procedure Append(
3214   Q :     in out Query_Type;
3215   V :     in     APQ_Date;
3216   After : in     String := ""
3217);
3218\end{Code}
3219
3220\begin{Code}
3221procedure Append(
3222   Q :     in out Query_Type;
3223   V :     in     APQ_Time;
3224   After : in     String := ""
3225);
3226\end{Code}
3227
3228\begin{Code}
3229procedure Append(
3230   Q :     in out Query_Type;
3231   V :     in     APQ_Timestamp;
3232   After : in     String := ""
3233);
3234\end{Code}
3235
3236\begin{Code}
3237procedure Append(
3238   Q :     in out Query_Type;
3239   V :     in     APQ_Bitstring;
3240   After : in     String := ""
3241);
3242\end{Code}
3243
3244\begin{Code}
3245procedure Append(
3246   Q :     in out Query_Type;
3247   V :     in     Row_ID_Type;
3248   After : in     String := ""
3249);
3250\end{Code}
3251
3252These Append\index{Append} procedure calls automatically convert\index{convert} the supplied data
3253type in argument V, internally into a string\index{string} using the To\_String\index{To\_String} function
3254appropriate to the data type. Internally, the string Append procedure
3255is then utilized to perform the remaining work. The following example
3256illustrates their use:
3257
3258\begin{Example}
3259declare
3260   Q :         Query_Type;
3261   Ship_Date : APQ_Date;
3262begin
3263   ...
3264   Prepare(Q,    "SELECT COMPNO,COMPANY_NAME,SHIP_DATE");
3265   Append_Line(Q,"FROM SUPPLIER");
3266   Append(Q,     "WHERE SHIP_DATE = ");
3267   Append(Q,Ship_Date,New_Line);
3268\end{Example}
3269
3270The example presented builds an SQL query that looks like this:
3271
3272\begin{SQL}
3273SELECT COMPNO,COMPANY_NAME,SHIP_DATE
3274FROM SUPPLIER
3275WHERE SHIP_DATE = '2002-07-21'
3276\end{SQL}
3277
3278Notice that the Append call for APQ\_Date\index{APQ\_Date} automatically supplies the
3279necessary quotes to the SQL query\index{SQL query} (if needed for the database being
3280used). All of the data types supported are molded into a format that
3281is acceptable in the native database SQL syntax\index{SQL syntax}. \\
3282
3283
3284APQ used to include the APQ\_Timezone data type. When it was updated to Ada 2005
3285this type was removed. Now APQ date and time types work as follows
3286
3287\begin{description}
3288	\item[APQ\_Date] date only, in local timezone
3289	\item[APQ\_Hour] \emph{Day\_Duration} type has no timestamp information; thus it's assumed local timezone as well
3290	\item[APQ\_Timestamp] it's converted to/from UTC when talking to the database; The \emph{Ada.Calendar.Formatting} package is used for the conversion tasks
3291\end{description}
3292
3293
3294\subsection{Generic Append SQL Procedures}
3295
3296Ada programmers often take advantage of the strong typing \index{strong typing}that
3297is available in the language. To accomodate this programming aspect,
3298generic procedures are available so that type conversions\index{type conversions}
3299are unnecessary. The following table documents the generic procedures
3300that accept one generic argument named Val\_Type and the data
3301types that they support:
3302
3303\begin{Code}
3304generic
3305   type Val_Type is new Boolean;
3306procedure Append_Boolean(
3307   Q :     in out Root_Query_Type'Class;
3308   V :     in     Val_Type;
3309   After : in     String := ""
3310);
3311\end{Code}
3312
3313\begin{Code}
3314generic
3315   type Val_Type is range <>;
3316procedure Append_Integer(
3317   Q :     in out Root_Query_Type'Class;
3318   V :     in     Val_Type;
3319   After : in     String := ""
3320);
3321\end{Code}
3322
3323\begin{Code}
3324generic
3325   type Val_Type is mod <>;
3326procedure Append_Modular(
3327   Q :     in out Root_Query_Type'Class;
3328   V :     in     Val_Type;
3329   After : in     String := ""
3330);
3331\end{Code}
3332
3333\begin{Code}
3334generic
3335   type Val_Type is digits <>;
3336procedure Append_Float(
3337   Q :     in out Root_Query_Type'Class;
3338   V :     in     Val_Type;
3339   After : in     String := ""
3340);
3341\end{Code}
3342
3343\begin{Code}
3344generic
3345   type Val_Type is delta <>;
3346procedure Append_Fixed(
3347   Q :     in out Root_Query_Type'Class;
3348   V :     in     Val_Type;
3349   After : in     String := ""
3350);
3351\end{Code}
3352
3353\begin{Code}
3354generic
3355   type Val_Type is delta <> digits <>;
3356procedure Append_Decimal(
3357   Q :     in out Root_Query_Type'Class;
3358   V :     in     Val_Type;
3359   After : in     String := ""
3360);
3361\end{Code}
3362
3363\begin{Code}
3364generic
3365   type Val_Type is new Ada.Calendar.Time;
3366procedure Append_Date(
3367   Q :     in out Root_Query_Type'Class;
3368   V :     in     Val_Type;
3369   After : in     String := ""
3370);
3371\end{Code}
3372
3373\begin{Code}
3374generic
3375   type Val_Type is new Ada.Calendar.Day_Duration;
3376procedure Append_Time(
3377   Q :     in out Root_Query_Type'Class;
3378   V :     in     Val_Type;
3379   After : in     String := ""
3380);
3381\end{Code}
3382
3383\begin{Code}
3384generic
3385   type Val_Type is new APQ_Timestamp;
3386procedure Append_Timestamp(
3387   Q :     in out Root_Query_Type'Class;
3388   V :     in     Val_Type;
3389   After : in     String := ""
3390);
3391\end{Code}
3392
3393\begin{Code}
3394generic
3395   type Val_Type is new APQ_Bitstring;
3396procedure Append_Bitstring(
3397   Q :     in out Root_Query_Type'Class;
3398   V :     in     Val_Type;
3399   After : in     String := ""
3400);
3401\end{Code}
3402
3403Each of the resulting instantiated procedures provide the following
3404calling signature:
3405
3406\begin{Code}
3407procedure Append(
3408   Q :     in out Query_Type;
3409   V :     in     Val_Type;
3410   After : in     String := ""
3411);
3412\end{Code}
3413
3414The following code fragment illustrates how these are instantiated\index{instantiated} and used:
3415
3416\begin{NumberedExample}
3417declare
3418   type Price_Type is delta 0.01 digits 12;(*@\label{Ex:TypeDef}@*)
3419   procedure Append is new Append_Decimal(Price_Type);(*@\label{Ex:Inst}@*)
3420
3421   Q :             Query_Type;
3422   Selling_Price : Price_Type;
3423begin
3424   ...
3425   Prepare(Q,"UPDATE SUPPL_ORDER");
3426   Append(Q."SET SELLING_PRICE = ");
3427   Append(Q,Selling_Price,New_Line);(*@\label{Ex:InstUse}@*)
3428   Append_Line(Q,"WHERE ...");
3429\end{NumberedExample}
3430
3431In this example, the application defines its own type Price\_Type
3432in line~\ref{Ex:TypeDef}. After instantiating the Append\_Decimal
3433generic procedure as Append\index{Append} (line~\ref{Ex:Inst}), the application is
3434free to neatly append a price value from Selling\_Price in
3435line~\ref{Ex:InstUse}, as if it were natively supported.
3436
3437
3438
3439\subsection{Generic Append of Bounded SQL Text}
3440
3441To accomodate the use of the package Ada\-.Strings\-.Bounded\index{Ada.Strings.Bounded},
3442the generic procedure Append\_Bounded\index{Append\_Bounded} was provided. Its instantiation
3443requirements differ from the preceeding ones because the instantiation
3444of the Bounded\_String\index{Bounded\_String} type must be provided to the Append\_Bounded
3445generic procedure. The generic procedure is defined as follows:
3446
3447\begin{Code}
3448generic
3449   with package P
3450      is new Ada.Strings.Bounded.Generic_Bounded_Length(<>);
3451procedure Append_Bounded(
3452   Q :     in out Query_Type;
3453   SQL :   in     P.Bounded_String;
3454   After : in     String
3455);
3456\end{Code}
3457
3458In other words, Append\_Bounded can be instantiated from any instantiation
3459of the Ada.Strings.Bounded.Generic\_Bounded\_Length package. The following
3460example makes this easier to understand:
3461
3462\begin{NumberedExample}
3463with Ada.Strings.Bounded;
3464...
3465declare
3466   package B80
3467      is new Ada.Strings.Bounded.Generic_Bounded_Length(80);
3468   package B20
3469      is new Ada.Strings.Bounded.Generic_Bounded_Length(20);
3470
3471   procedure Append is new Append_Bounded(B80);(*@\label{Ex:B80}@*)
3472   procedure Append is new Append_Bounded(B20);(*@\label{Ex:B20}@*)
3473
3474   Q :         Query_Type;
3475   Item_Code : B20;
3476   Item_Name : B80;
3477begin
3478   ...
3479   Prepare(Q,    "SELECT COUNT(*)");
3480   Append_Line(Q,"FROM ORDER");
3481   Append(Q,     "WHERE ITEM_CODE = ","'");
3482   Append(Q,Item_Code,"' AND ITEM_NAME = '");(*@\label{Ex:UseB20}@*)
3483   Append(Q,Item_Name,"'" & New_Line);(*@\label{Ex:UseB80}@*)
3484   ...
3485\end{NumberedExample}
3486
3487The example shows how two different generic procedures named Append
3488are instantiated from the Bounded\_String instantiations B80 (line~\ref{Ex:B80})
3489and B20 (line~\ref{Ex:B20}). Note that the Append\_Bounded procedure does not escape
3490special characters, nor provide the outer quotes (this is a poor example of its
3491use actually).
3492
3493The Append\index{Append} call used in line~\ref{Ex:UseB20} is the one that was
3494instantiated on line~\ref{Ex:B20}. The other Append used on
3495line~\ref{Ex:UseB80} was instantiated on line~\ref{Ex:B80}. These
3496are matched according to the normal Ada2005\index{Ada2005} argument type matching
3497rules.
3498
3499\subsection{Generic Append\_Bounded\_Quoted Procedure}
3500
3501To accomodate the quoting needs of Bounded\_Strings, the Append\_Bounded\_Quoted\index{Append\_Bounded\_Quoted}
3502generic procedure may be used:
3503
3504\begin{Code}
3505generic
3506   with package P
3507      is new Ada.Strings.Bounded.Generic_Bounded_Length(<>);
3508procedure Append_Bounded_Quoted(
3509   Q :     in out Query_Type;
3510   C :     in     Connection_Type;
3511   SQL :   in     P.Bounded_String;
3512   After : in     String
3513);
3514\end{Code}
3515
3516It is otherwise very similar to the previous Append\_Unbounded\index{Append\_Unbounded} procedure.
3517The following example illustrates a safer\index{safer} version of the prior example:
3518
3519\begin{Example}
3520with Ada.Strings.Bounded;
3521...
3522declare
3523   package B80
3524      is new Ada.Strings.Bounded.Generic_Bounded_Length(80);
3525   package B20
3526      is new Ada.Strings.Bounded.Generic_Bounded_Length(20);
3527
3528   procedure Append_Quoted is new Append_Bounded_Quoted(B80);
3529   procedure Append_Quoted is new Append_Bounded_Quoted(B20);
3530
3531   C :         Connection_Type;
3532   Q :         Query_Type;
3533   Item_Code : B20;
3534   Item_Name : B80;
3535begin
3536   ...
3537   Prepare(Q,    "SELECT COUNT(*)");
3538   Append_Line(Q,"FROM ORDER");
3539   Append(Q,     "WHERE ITEM_CODE = ");
3540   Append_Quoted(Q,C,Item_Code," AND ITEM_NAME = ");
3541   Append_Quoted(Q,C,Item_Name,New_Line);
3542   ...
3543\end{Example}
3544
3545The instantiations of Append\_Quoted\index{Append\_Quoted}%
3546\footnote{It is not necessary to instantiate these procedures as
3547Append\_Quoted, but it is recommended for readability.} here will
3548properly escape\index{escape} any special\index{special characters} characters that may appear in the program's
3549string variables Item\_Code and Item\_Name. Additionally, note that the
3550outer quotes\index{quotes} are provided automatically, easing the programmer's burden
3551in building up the SQL query. Like other Append\_Quoted API calls within
3552APQ, the case\index{case within quoted strings} within quoted strings is always preserved.
3553
3554
3555\subsection{Encoding Quoted Strings}
3556
3557While strings are well covered by the category 1 support, it is necessary
3558to encode a NULL\index{NULL} in place of a quoted string\index{quoted string},
3559when the value is null. The generic specification for
3560Encode\-\_String\-\_Quoted\index{Encode\_String\_Quoted} is as follows:
3561
3562\begin{Code}
3563generic
3564   type Ind_Type is new Boolean;
3565procedure Encode_String_Quoted(
3566   Q :          in out Root_Query_Type'Class;
3567   Connection : in     Root_Connection_Type'Class;
3568   SQL :        in     String;
3569   Indicator :  in     Ind_Type;
3570   After :      in     String := ""
3571);
3572\end{Code}
3573
3574An example of its instantiation and use is shown below:
3575
3576\begin{Example}
3577declare
3578   type Cust_Name_Ind_Type is new Boolean;
3579
3580   procedure Encode_Quoted
3581      is new Encode_String_Quoted(Cust_Name_Ind_Type);
3582
3583   Q :             Query_Type;
3584   Cust_Name :     String(1..30);
3585   Cust_Name_Ind : Cust_Name_Ind_Type; -- Indicator
3586begin
3587   ...
3588   Prepare(Q,"UPDATE CUSTOMER");
3589   Append_Line(Q,"SET CUST_NAME = ");
3590   Encode_Quoted(Q,Cust_Name,Cust_Name_Ind);
3591\end{Example}
3592
3593In this example, the String Cust\_Name is given outer quotes
3594and any special characters are escaped before the value is appended
3595to the current SQL query being collected in object Q. If however,
3596the indicator Cust\_Name\_Ind is True (indicating that the
3597value Cust\_Name should be interpreted as NULL\index{NULL}), then the string
3598``NULL'' is appended instead. When NULL is supplied, no outer
3599quotes are supplied. The following two SQL statements are possible,
3600depending upon Cust\_Name\_Ind. When the indicator is false,
3601a quoted\index{quoted value} value is supplied:
3602
3603\begin{SQL}
3604UPDATE CUSTOMER
3605SET CUST_NAME = 'Fred Willard'
3606...
3607\end{SQL}
3608
3609When the indicator is true (the value is null), the resulting query
3610becomes the following:
3611
3612\begin{SQL}
3613UPDATE CUSTOMER
3614SET CUST_NAME = NULL
3615...
3616\end{SQL}
3617
3618\subsection{Encoding Quoted Unbounded\_String}
3619
3620To provide quoting\index{quoting support} support for Unbounded\-\_Strings\index{Ada.Strings.Unbounded},
3621the Encode\-\_Bounded\-\_Quoted gen\-eric procedure is provided by APQ.
3622The specifications for this procedure is given below:
3623
3624\begin{Code}
3625generic
3626   type Ind_Type is new Boolean;
3627procedure Encode_Unbounded_Quoted(
3628   Q :          in out Root_Query_Type'Class;
3629   Connection : in     Root_Connection_Type'Class;
3630   SQL :        in     Ada.Strings.Unbounded.Unbounded_String;
3631   Indicator :  in     Ind_Type;
3632   After :      in     String := ""
3633);
3634\end{Code}
3635
3636An example of its use is illustrated as follows:
3637
3638\begin{Example}
3639declare
3640   use Ada.Strings.Bounded;
3641
3642   type Cust_Name_Ind_Type is new Boolean;
3643
3644   procedure Encode_Quoted
3645      is new Encode_Unbounded_Quoted(Cust_Name_Ind_Type);
3646
3647   C :             Connection_Type;
3648   Q :             Query_Type;
3649   Cust_Name :     Unbounded_String;
3650   Cust_Name_Ind : Cust_Name_Ind_Type;
3651begin
3652   ...
3653   Prepare(Q,"UPDATE CUSTOMER");
3654   Append_Line(Q,"SET CUST_NAME = ");
3655   Encode_Quoted(Q,C,Cust_Name,Cust_Name_Ind);
3656\end{Example}
3657
3658In this example, the Unbounded\_String Cust\_Name is given
3659outer quotes and any special characters are escaped before the value
3660is appended to the current SQL query\index{SQL query} being collected in object Q.
3661If however, the indicator\index{indicator, null} Cust\_Name\_Ind is True (indicating
3662that the value \emph{Cust\_Name} should be interpreted as NULL), then
3663the string ``NULL''\index{NULL} is appended\index{appended} instead. When NULL is supplied,
3664no outer\index{outer quotes} quotes are supplied. The following two SQL statements are
3665possible, depending upon \emph{Cust\_Name\_Ind}. When the indicator
3666is false, a quoted value\index{quoted value} is supplied:
3667
3668\begin{SQL}
3669UPDATE CUSTOMER
3670SET CUST_NAME = 'Fred Willard'
3671...
3672\end{SQL}
3673
3674When the indicator is true, the resulting query becomes the following:
3675
3676\begin{SQL}
3677UPDATE CUSTOMER
3678SET CUST_NAME = NULL
3679...
3680\end{SQL}
3681
3682\subsection{Encoding Bounded Quoted Strings}
3683
3684Bounded strings\index{bounded strings} require instantiations of
3685Ada\-.Strings\-.Bounded\-.Gen\-eric\-\_Bound\-ed\-\_Len\-gth
3686\index{Ada.Strings.Bounded}with a specific length. The instantiated
3687package\index{package} reference must be provided as an argment to the
3688Encode\-\_Bounded\-\_Quoted\index{Encode\_Bounded\_Quoted} instantiation:
3689
3690\begin{Code}
3691generic
3692   type Ind_Type is new Boolean;
3693   with package P
3694      is new Ada.Strings.Bounded.Generic_Bounded_Length(<>);
3695procedure Encode_Bounded_Quoted(
3696   Q :          in out Root_Query_Type'Class;
3697   Connection : in     Root_Connection_Type'Class;
3698   SQL :        in     P.Bounded_String;
3699   Indicator :  in     Ind_Type;
3700   After :      in     String := ""
3701);
3702\end{Code}
3703
3704An example showing its use is given below:
3705
3706\begin{Example}
3707with Ada.Strings.Bounded;
3708
3709declare
3710   package B80 is new
3711      Ada.Strings.Bounded.Generic_Bounded_Length(80);
3712
3713   type Cust_Name_Ind_Type is new Boolean;
3714
3715   procedure Encode_Quoted is new
3716      Encode_Bounded_Quoted(Cust_Name_Ind_Type,B80);
3717
3718   C :             Connection_Type;
3719   Q :             Query_Type;
3720   Cust_Name :     B80.Bounded_String;
3721   Cust_Name_Ind : Cust_Name_Ind_Type; -- Indicator
3722begin
3723   ...
3724   Prepare(Q,"UPDATE CUSTOMER");
3725   Append_Line(Q,"SET CUST_NAME = ");
3726   Encode_Quoted(Q,C,Cust_Name,Cust_Name_Ind);
3727   ...
3728\end{Example}
3729
3730In this example, the Bounded\_String Cust\_Name is given outer
3731quotes and any special characters are escaped before the value is
3732appended to the current SQL query being collected in object Q.
3733If however, the indicator\index{indicator} Cust\_Name\_Ind is True (indicating
3734that the value Cust\_Name should be interpreted as NULL), then
3735the string ``NULL''\index{NULL} is appended instead. When NULL is supplied,
3736no outer quotes are supplied. The following two SQL\index{SQL} statements are
3737possible, depending upon Cust\_Name\_Ind. When the indicator is false,
3738a quoted value\index{quoted value} is supplied:
3739
3740\begin{SQL}
3741UPDATE CUSTOMER
3742SET CUST_NAME = 'Fred Willard'
3743...
3744\end{SQL}
3745
3746When the indicator is true, the resulting query becomes the following:
3747
3748\begin{SQL}
3749UPDATE CUSTOMER
3750SET CUST_NAME = NULL
3751...
3752\end{SQL}
3753
3754\subsection{Encoding Non-String Values}
3755
3756There are a large number of generic\index{generic} encoding procedures that
3757allow encoding of non-string\index{non-string values} values into SQL queries. They are
3758listed below:
3759
3760\begin{Code}
3761generic
3762   type Val_Type is new Boolean;
3763   type Ind_Type is new Boolean;
3764procedure Encode_Boolean(
3765   Q :         in out Root_Query_Type'Class;
3766   V :         in     Val_Type;
3767   Indicator : in     Ind_Type;
3768   After :     in     String := ""
3769);
3770\end{Code}
3771
3772\begin{Code}
3773generic
3774   type Val_Type is range <>;
3775   type Ind_Type is new Boolean;
3776procedure Encode_Integer(
3777   Q :         in out Root_Query_Type'Class;
3778   V :         in     Val_Type;
3779   Indicator : in     Ind_Type;
3780   After :     in     String := ""
3781);
3782\end{Code}
3783
3784\begin{Code}
3785generic
3786   type Val_Type is mod <>;
3787   type Ind_Type is new Boolean;
3788procedure Encode_Modular(
3789   Q :         in out Root_Query_Type'Class;
3790   V :         in     Val_Type;
3791   Indicator : in     Ind_Type;
3792   After :     in     String := ""
3793);
3794\end{Code}
3795
3796\begin{Code}
3797generic
3798   type Val_Type is digits <>;
3799   type Ind_Type is new Boolean;
3800procedure Encode_Float(
3801   Q :         in out Root_Query_Type'Class;
3802   V :         in     Val_Type;
3803   Indicator : in     Ind_Type;
3804   After :     in     String := ""
3805);
3806\end{Code}
3807
3808\begin{Code}
3809generic
3810   type Val_Type is delta <>;
3811   type Ind_Type is new Boolean;
3812procedure Encode_Fixed(
3813   Q :         in out Root_Query_Type'Class;
3814   V :         in     Val_Type;
3815   Indicator : in     Ind_Type;
3816   After :     in     String := ""
3817);
3818\end{Code}
3819
3820\begin{Code}
3821generic
3822   type Val_Type is delta <> digits <>;
3823   type Ind_Type is new Boolean;
3824procedure Encode_Decimal(
3825   Q :         in out Root_Query_Type'Class;
3826   V :         in     Val_Type;
3827   Indicator : in     Ind_Type;
3828   After :     in     String := ""
3829);
3830\end{Code}
3831
3832\begin{Code}
3833generic
3834   type Val_Type is new APQ_Date;
3835   type Ind_Type is new Boolean;
3836procedure Encode_Date(
3837   Q :         in out Root_Query_Type'Class;
3838   V :         in     Val_Type;
3839   Indicator : in     Ind_Type;
3840   After :     in     String := ""
3841);
3842\end{Code}
3843
3844\begin{Code}
3845generic
3846   type Val_Type is new APQ_Time;
3847   type Ind_Type is new Boolean;
3848procedure Encode_Time(
3849   Q :         in out Root_Query_Type'Class;
3850   V :         in     Val_Type;
3851   Indicator : in     Ind_Type;
3852   After :     in     String := ""
3853);
3854\end{Code}
3855
3856\begin{Code}
3857generic
3858   type Val_Type is new APQ_Timestamp;
3859   type Ind_Type is new Boolean;
3860procedure Encode_Timestamp(
3861   Q :         in out Root_Query_Type'Class;
3862   V :         in     Val_Type;
3863   Indicator : in     Ind_Type;
3864   After :     in     String := ""
3865);
3866\end{Code}
3867
3868\begin{Code}
3869generic
3870   type Val_Type is new APQ_Bitstring;
3871   type Ind_Type is new Boolean;
3872procedure Encode_Bitstring(
3873   Q :         in out Root_Query_Type'Class;
3874   V:          in     Val_Type;
3875   Indicator : in     Ind_Type;
3876   After :     in     String := ""
3877);
3878\end{Code}
3879
3880The following example shows the application of one of these generic
3881procedures:
3882
3883\begin{Example}
3884declare
3885   type Cust_No_Type is new Integer range 1000..100_000;
3886   type Cust_Age_Type is new Integer range 0..200;
3887
3888   procedure Append is new Append_Integer(Cust_No_Type);
3889   procedure Encode is new
3890      Encode_Integer(Cust_No_Type,Boolean);
3891
3892   Q :            Query_Type;
3893   Cust_No :      Cust_No_Type;  -- Customer # NOT NULL
3894   Cust_Age :     Cust_Age_Type; -- Can be NULL
3895   Cust_Age_Ind : Boolean;       -- Indicator
3896   Cust_Name :    String(1..30); -- Customer Name NOT NULL
3897begin
3898   ...
3899   Prepare(Q,"INSERT INTO CUSTOMER (CUST_NO,AGE,CUST_NAME)");
3900   Append(Q, "VALUES ( ");
3901   Append(Q,Cust_No,",");
3902   Encode(Q,Cust_Age,Cust_Age_Ind,",");
3903   Append_Quoted(Q,Cust_Name," )" & New_Line);
3904   ...
3905\end{Example}
3906
3907From the example, if variable Cust\_Name holds the value ``Martin Mull'',
3908and Cust\_No holds 12345, two possible SQL queries are possible,
3909depending upon the value of Cust\_Age\_Ind, the null indicator\index{indicator, null}. When
3910Cust\_Age\_Ind is false (not null), then the SQL query would be formed as
3911follows:
3912
3913\begin{SQL}
3914INSERT INTO CUSTOMER (CUST_NO,AGE,CUST_NAME)
3915VALUES (12345,52,'Martin Mull')
3916\end{SQL}
3917
3918When the indicator\index{indicator} Cust\_Age\_Ind is true (representing null), then the
3919query would be constructed as follows:
3920
3921\begin{SQL}
3922INSERT INTO CUSTOMER (CUST_NO,AGE,CUST_NAME)
3923VALUES (12345,NULL,'Martin Mull')
3924\end{SQL}
3925
3926Notice how Append\index{Append} procedures are used for values that can never be
3927null (no null indicator is involved). Encode routines are only necessary
3928when a null indicator may need to be encoded into the result.
3929
3930
3931
3932
3933\section{Query Execution}
3934
3935Once the SQL query has been constructed using all of the techniques
3936described in \Ref{SQL Initialization} and \Ref{SQL Query Building},
3937you are ready to send\index{send the query} the query to the database engine\index{engine, database} to have it
3938executed. This is done with the help of the Query\_Type's primitive
3939Execute\index{Execute}. The Execute call requires the following calling arguments:
3940
3941\begin{Code}
3942procedure Execute(
3943   Query :      in out Root_Query_Type;
3944   Connection : in out Root_Connection_Type'Class
3945);
3946\end{Code}
3947
3948The Execute primitive can raise the exceptions that are listed
3949in Table~\ref{t:exx}.
3950
3951\begin{table}
3952   \begin{center}
3953      \begin{tabular}{ll}
3954         Exception Name &  Reason\\
3955         \hline
3956         Not\_Connected &  There is no connection to use\\
3957         Abort\_State   &  Transaction in {}``abort state{}``\\
3958         SQL\_Error     &  The submitted SQL query failed\\
3959         Failed         &  Hidden APQ query failure\\
3960      \end{tabular}
3961   \end{center}
3962   \caption{Execute Exceptions}\label{t:exx}
3963\end{table}
3964
3965The PostgreSQL\index{PostgreSQL} Abort\_State\index{Abort\_State}
3966exception is described in \Ref{Abort_State exception}. This exception indicates that
3967the current transaction has failed\index{failed transaction}. All other types of errors\index{errors} raise\index{raise}
3968the SQL\_Error\index{SQL\_Error} exception, unless the connection is bad. The Failed\index{Failed exception}
3969exception only occurs for some databases where a hidden\index{hidden SQL query} SQL query
3970must be performed and it unexpectedly failed.%
3971\footnote{For Sybase, APQ will do a SELECT @@identity after an INSERT query
3972is performed.%
3973}
3974
3975The use of the Execute\index{Execute} primitive is illustrated by the example \ref{Ex:Execute}
3976
3977\begin{NumberedExample}[label=Ex:Execute,caption=Executing Queries]
3978declare
3979   type Cust_No_Type is new Integer range 1000..100_000;
3980   type Birthday_Type is new APQ_Timestamp;
3981
3982   procedure Append is new Append_Integer(Cust_No_Type);
3983
3984   procedure Encode is new Encode_Integer(Cust_No_Type,Boolean);
3985   procedure Encode is new Encode_Timestamp(Birthday_Type,Boolean);
3986
3987   C            : Connection_Type;
3988   Q            : Query_Type;
3989   Cust_No      : Cust_No_Type;     -- NOT NULL
3990   Birthday     : Birthday_Type;
3991   Birthday_Ind : Boolean;          -- Indicator
3992begin
3993   -- ...
3994   -- we set the Ada variable and so on...
3995   Prepare( Q, "INSERT INTO BIRTHDAY (CUST_NO,BIRTHDAY)" );
3996   Append( Q, "VALUES (" );
3997   Append( Q, Cust_No, ",");
3998   Encode( Q, Birthday, Birthday_TZ, Birthday_Ind, ")" );
3999   Execute( Q, C ); (*@\label{Ex:Execute:Execute}@*)
4000end;
4001\end{NumberedExample}
4002
4003The example shows the Execute primitive pairing the query object Q
4004with the database connection object C at line \ref{Ex:Execute:Execute}.
4005
4006\subsection{Error Message Reporting\label{Error Message Reporting}}
4007
4008It is useful to know that your SQL query failed, but more information
4009is usually necessary. The Error\_Message\index{Error\_Message} primitive can be invoked
4010on the Query\_Type object. This function has the following calling
4011signature:
4012
4013\begin{Code}
4014function Error_Message(
4015   Query : Query_Type;
4016) return String;
4017\end{Code}
4018
4019The following example shows how this function might be used:
4020
4021\begin{Example}
4022begin
4023   ...
4024   Execute(Q,C);
4025exception
4026   when SQL_Error =>
4027      Put(Standard_Error,"SQL Error: ");
4028      Put_Line(Standard_Error,Error_Message(Q));
4029      raise;
4030   when others =>
4031      raise;
4032end
4033\end{Example}
4034
4035\subsection{Is\_Duplicate\_Key Function}
4036
4037Duplicate\index{duplicate key} key errors\index{errors} often occur while performing SQL INSERT\index{INSERT} operations
4038on a table. A duplicate key insertion\index{insertion error} error is a special case because
4039the insert operation may not be considered a failure for some applications.
4040For this reason, the Is\_Duplicate\_Key\index{Is\_Duplicate\_Key} predicate function is provided
4041for use after a SQL\_Error exception has been raised%
4042\footnote{At present, this test is implemented by calling Error\_Message and
4043looking at the message text. Future versions of the APQ binding may
4044use a more reliable indicator if the PostgreSQL libpq library provides
4045such a status indication.%
4046}. The specification is listed as follows:
4047
4048\begin{Code}
4049function Is_Duplicate_Key(
4050   Query : Query_Type
4051) return Boolean;
4052\end{Code}
4053
4054The following example reports an SQL error\index{SQL error} only if the error is not
4055a duplicate key insert problem:
4056
4057\begin{Example}
4058...
4059begin
4060   Execute(Q,C);  -- Execute an INSERT SQL statement
4061exception
4062   when SQL_Error =>
4063      if not Is_Duplicate_Key(Q) then
4064         -- Report error if not a duplicate insert
4065         Put(Standard_Error,"SQL Error: ");
4066         Put_Line(Standard_Error,Error_Message(Q));
4067         raise;
4068      else
4069         null; -- Ignore duplicate insert
4070      end;
4071end;
4072\end{Example}
4073
4074\subsection{Command\_Status Function (PostgreSQL)\label{Command_Status Function}}
4075
4076The Command\_Status\index{Command\_Status} function provides a string of status information
4077after a PostgreSQL\index{PostgreSQL} query has been executed. The results returned depends
4078upon the type of execution that was last performed. Table~\ref{t:csrv}
4079summarizes the types of return status strings available:%
4080\marginpar{This is a PostgreSQL specific function, only. Avoid its use for portability.}
4081
4082\begin{table}
4083   \begin{center}
4084      \begin{tabular}{|l|l|l|}
4085         \hline
4086         After Event    &  Result               &  Comments\\
4087         \hline
4088         CREATE ...     &  "CREATE"             &  \\
4089         BEGIN WORK     &  "BEGIN"              &  \\
4090         COMMIT WORK    &  "COMMIT"             &  \\
4091         ROLLBACK WORK  &  "ROLLBACK"           &  \\
4092         SELECT ...     &  "SELECT"             &  \\
4093         INSERT ...     &  "INSERT <OID> <\#>"  &  \# is normally 1\\
4094         \hline
4095      \end{tabular}
4096   \end{center}
4097   \caption{Command\_Status Return Values}\label{t:csrv}
4098\end{table}
4099
4100Notice that after an INSERT\index{INSERT} is performed, the returned status string
4101includes the OID\index{OID} (row ID\index{row ID}) of the new row, and the number of rows inserted
4102(normally 1). If you need to extract the OID value, see the Command\_Oid
4103function in \Ref{Command_Oid Function}.
4104
4105The calling signature of Command\_Status is:
4106
4107\begin{Code}
4108function Command_Status(
4109   Query : Query_Type
4110) return String;
4111\end{Code}
4112
4113The Command\_Status function can raise the exceptions listed in
4114Table~\ref{t:cstsx}.
4115
4116\begin{table}
4117   \begin{center}
4118      \begin{tabular}{ll}
4119         Exception Name    &  Reason\\
4120         \hline
4121         No\_Result        &  There is no result status (no execution)\\
4122      \end{tabular}
4123   \end{center}
4124   \caption{Command\_Status Exceptions}\label{t:cstsx}
4125\end{table}
4126
4127
4128\subsection{Command\_Oid Function \label{Command_Oid Function}}
4129
4130After an INSERT\index{INSERT} operation, it is often required to know the OID\index{OID} (row ID\index{row ID})
4131value for the newly created row. When using PostgreSQL, this can be
4132extracted from the Command\_Status\index{Command\_Status} return string (see
4133\Ref{Command_Status Function}), but this approach is not
4134portable to other vendor databases.
4135
4136The APQ user is encouraged to call the Command\_Oid function when
4137it is necessary to know the identity\index{identity} of the newly inserted row. This
4138function primitive hides the differences\index{differences} between the different database
4139products and makes your code more portable.
4140
4141The calling signature for Command\_Oid is as follows:
4142
4143\begin{Code}
4144function Command_Oid(
4145   Query : Query_Type
4146) return Row_ID_Type;
4147\end{Code}
4148
4149Table \ref{t:coidx} lists the exceptions that are possible for Command\_Oid.
4150
4151\begin{table}
4152   \begin{center}
4153      \begin{tabular}{ll}
4154         Exception Name    &  Reason\\
4155         \hline
4156         No\_Result        &  There is no result status (no execution)\\
4157         SQL\_Error        &  An SQL error occurred obtaining the OID\\
4158      \end{tabular}
4159   \end{center}
4160   \caption{Command\_Oid Exceptions}\label{t:coidx}
4161\end{table}
4162
4163Be aware that the exception No\_Result\index{No\_Result} can be raised for two different
4164reasons:
4165
4166\begin{itemize}
4167   \item There was no prior ``execution'' (thus no result)
4168   \item The prior execution was not an INSERT operation (hence no OID value available)
4169\end{itemize}
4170
4171APQ applications should \emph{not} be written to provoke these exceptions,
4172since different database products behave differently in this respect
4173(Sybase\index{Sybase} users will never see an exception from Command\_Oid for example).
4174The raising of either of these exceptions does however indicate that
4175there is a programming error\index{error, programming} that requires correction in the calling
4176application.
4177
4178
4179\subsubsection{Database OID (Row ID) Support}
4180
4181Some databases do not support the concept of OID\index{OID} (row ID\index{row ID}) values.
4182This creates a huge portability\index{portability} problem for the application programmer.
4183However, all databases provide some technique for identifying\index{identifying rows} rows
4184uniquely in a table. Table~\ref{t:roids} summarizes the ways that
4185APQ adapts the database server to concept of OID values:%
4186\footnote{Applications should be written to avoid row ID concepts and use key values instead.}
4187
4188\begin{table}
4189   \begin{center}
4190      \begin{tabular}{|l|l|l|l|}
4191         \hline
4192         Database          &  OID      &  How               &  How APQ Supports OID\\
4193         \hline
4194         PostgreSQL        & Yes       &  OID = Row ID      &  PostgreSQL Object ID (OID)\\
4195         MySQL             & No        &  AUTO\_INCREMENT   &  Serial value from primary key\\
4196         Sybase            & No        &  Identity column   &  SELECT @@identity\\
4197         \hline
4198      \end{tabular}
4199   \end{center}
4200   \caption{Row ID Database Support}\label{t:roids}
4201\end{table}
4202
4203
4204\subsubsection{MySQL OID (Row ID) Support}
4205
4206From the preceeding table, you can observe that MySQL\index{MySQL} does not support
4207any concept of a row ID\index{row ID} value. APQ can fake OID-like\index{OID} support, if the
4208table is defined using a primary key in the following form\index{AUTO\_INCREMENT}:
4209
4210\begin{SQL}
4211
4212   INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY
4213
4214\end{SQL}
4215
4216When a MySQL table has a primary key like the one shown, APQ is able
4217to return the created primary key value using Command\_OID\index{Command\_OID}.
4218
4219The following is an example table declaration:
4220
4221\begin{SQL}
4222CREATE TABLE ITEM_DESC (
4223   ITEM_ID     INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
4224   DESCRIPTION VARCHAR(80)
4225);
4226\end{SQL}
4227
4228\subsubsection{Sybase OID (Row ID) Support}
4229
4230Sybase\index{Sybase} does not support the concept of row ID\index{row ID} values. APQ however,
4231can provide row ID-like support if you declare your table with a primary
4232key in the following form\index{IDENTITY}:
4233
4234\begin{SQL}
4235
4236   NUMERIC IDENTITY NOT NULL PRIMARY KEY
4237
4238\end{SQL}
4239
4240For Sybase, when the APQ procedure Execute is performed, APQ will
4241check to see if the SQL query peformed was an INSERT\index{INSERT} command. If it
4242was, a hidden SQL query is performed immediately afterwards on the
4243same connection to query the identity\index{identity of a row} of the row that was created\index{@@identity}:
4244
4245\begin{SQL}
4246
4247   SELECT @@identity
4248
4249\end{SQL}
4250
4251The value returned by this hidden query will be saved as the row ID\index{row ID}
4252in the Query\-\_Type object used to perform the INSERT\index{INSERT}. A later call
4253to Command\_OID on this same Query\_Type object, will then return
4254this row identity value as a Row\_ID\_Type\index{Row\_ID\_Type}.
4255
4256The following is an example Sybase table declaration:
4257
4258\begin{SQL}
4259CREATE TABLE ITEM_DESC (
4260   ITEM_ID     NUMERIC IDENTITY NOT NULL PRIMARY KEY,
4261   DESCRIPTION VARCHAR(80)
4262);
4263\end{SQL}
4264
4265\subsubsection{Example of Command\_OID Use}
4266
4267The following example will always work for PostgreSQL\index{PostgreSQL}. It will also
4268work for MySQL\index{MySQL} and Sybase\index{Sybase}, if the primary key\index{primary key} guidelines in the prior
4269subsections were followed.
4270
4271This example shows how the INSERTed\index{INSERT} row's OID value (or primary key\index{primary key})
4272is obtained:
4273
4274\begin{Example}
4275declare
4276   C :      Connection_Type;
4277   Q :      Query_Type;
4278   Obj_Id : Row_ID_Type;
4279begin
4280   ...
4281   Prepare(Q,"INSERT INTO CUST_ORDER (CATALOG_NO,QUANTITY,...");
4282   ...
4283   Execute(Q,C);
4284   Obj_Id := Command_Oid(Q);  -- row id/identity of inserted row
4285\end{Example}
4286
4287The variable named Obj\_ID will contain the PostgreSQL\index{PostgreSQL} OID\index{OID} value of
4288the inserted row, when PostgreSQL is used. For MySQL\index{MySQL} and Sybase\index{Sybase}, the
4289variable Obj\_ID will contain the primary key value of the newly created
4290row.
4291
4292
4293\subsubsection{Generic\_Command\_Oid Function}
4294
4295To allow strong typing\index{strong typing} to be used in place of the supplied Row\_ID\_Type\index{Row\_ID\_Type}
4296type, the Generic\_Command\_Oid\index{Generic\_Command\_Oid} function can be instantiated for use
4297in the application. The instantiated function otherwise behaves identical
4298with the Command\_Oid function described on page \pageref{Command_Oid Function}.
4299The instantiation arguments for Generic\_Command\_Oid are as follows:
4300
4301\begin{Code}
4302generic
4303   type Oid_Type is new Row_ID_Type;
4304function Generic_Command_Oid(
4305   Query : Query_Type'Class
4306) return Oid_Type;
4307\end{Code}
4308
4309An instantiation example follows:
4310
4311\begin{Example}
4312declare
4313   type My_Oid_Type is new Row_ID_@Type;
4314
4315   function Command_Oid
4316      is new Generic_Command_Oid(My_Oid_Type);
4317\end{Example}
4318
4319\subsection{Error Status Reporting\label{Error Status Reporting}}
4320
4321The Result\index{Result} function primitive is documented here for completeness.
4322Applications should avoid using this function, since the values that
4323it returns are very database technology specific.
4324
4325
4326\subsubsection{Result Codes}
4327
4328The Result function primitive should be avoided in portable code. However,
4329there may be circumstances where a particular code is important to the
4330application developer.
4331
4332\begin{Code}
4333function Result(
4334   Query : Query_Type
4335) return Natural;
4336  -- Returns Result_Type'Pos()
4337\end{Code}
4338
4339The Result function returns a Natural\index{Natural} value. To obtain the Result\_Type\index{Result\_Type}
4340for the database being used, you should use;
4341
4342\begin{Example}
4343declare
4344   Q : Query_Type;
4345   R : Result_Type;
4346begin
4347   R := Result_Type'Val(Result(Q));
4348\end{Example}
4349
4350\subsubsection{Notes:}
4351
4352\begin{itemize}
4353   \item The Execute\index{Execute} primitive will throw an exception if the execution failed
4354         (the PostgreSQL Nonfatal\_Error\index{Nonfatal\_Error} case).
4355   \item For SELECT\index{SELECT} queries, the fact that no rows are returned will be identifiable upon
4356         the first FETCH\index{FETCH} operation (the PostgreSQL Empty\_Query\index{Empty\_Query}
4357         case), or upon calling End\_of\_Query\index{End\_of\_Query}.
4358   \item When rows are returned (the PostgreSQL Tuples\_OK\index{Tuples\_OK} case), the application will
4359         successfully fetch at least one row.
4360   \item For other SQL commands, successful execution is determined by Execute
4361         not throwing an exception (the PostgreSQL Command\_OK\index{Command\_OK} case).
4362\end{itemize}
4363
4364\subsubsection{PostgreSQL Result Codes}
4365
4366The PostgreSQL\index{PostgreSQL} result\index{result types} types are declared in the APQ\-.PostgreSQL package.
4367The Result\_Type values are highly PostgreSQL engine\index{engine} specific and are
4368enumerated in Table~\ref{t:pqresc}.
4369
4370\begin{longtable}{|c|c|l|}
4371\hline
4372Name              &  Value          &  Description\\
4373\hline
4374Empty\_Query      &  0              &  The query returned 0 rows of data\\
4375Command\_OK       &  1              &  The non-query statement executed successfully\\
4376Tuples\_OK        &  2              &  The SQL query returned at least 1 row of data\\
4377Copy\_Out         &  3              &  \\
4378Copy\_In          &  4              &  \\
4379Bad\_Response     &  5              &  Bad response from database server\\
4380Nonfatal\_Error   &  6              &  A non fatal error has occurred\\
4381Fata\_Error       &  7              &  A fatal error has occurred\\
4382\hline
4383\caption{PostgreSQL Result Codes}\label{t:pqresc}
4384\end{longtable}
4385
4386\begin{quote}
4387Note that the numeric values in Table~\ref{t:pqresc} are subject to change if the
4388PostgreSQL\index{PostgreSQL} database server software designers choose to do so. Use
4389the enumerated names instead.
4390\end{quote}
4391
4392\subsubsection{MySQL Result Codes}
4393
4394Result types for MySQL\index{MySQL} are declared in package APQ\-.MySQL. These are
4395generated by the APQ install process from the MySQL database
4396C macros provided. The following is the list from MySQL version 4.0.14 :
4397
4398\begin{Code}
4399type Result_Type is (
4400   CR_NO_ERROR,
4401   ER_HASHCHK,
4402   ER_NISAMCHK,
4403   ER_NO,
4404   ER_YES,
4405   ER_CANT_CREATE_FILE,
4406   ER_CANT_CREATE_TABLE,
4407   ER_CANT_CREATE_DB,
4408   ER_DB_CREATE_EXISTS,
4409   ER_DB_DROP_EXISTS,
4410   ER_DB_DROP_DELETE,
4411   ER_DB_DROP_RMDIR,
4412   ER_CANT_DELETE_FILE,
4413   ER_CANT_FIND_SYSTEM_REC,
4414   ER_CANT_GET_STAT,
4415   ER_CANT_GET_WD,
4416   ER_CANT_LOCK,
4417   ER_CANT_OPEN_FILE,
4418   ER_FILE_NOT_FOUND,
4419   ER_CANT_READ_DIR,
4420   ER_CANT_SET_WD,
4421   ER_CHECKREAD,
4422   ER_DISK_FULL,
4423   ER_DUP_KEY,
4424   ER_ERROR_ON_CLOSE,
4425   ER_ERROR_ON_READ,
4426   ER_ERROR_ON_RENAME,
4427   ER_ERROR_ON_WRITE,
4428   ER_FILE_USED,
4429   ER_FILSORT_ABORT,
4430   ER_FORM_NOT_FOUND,
4431   ER_GET_ERRNO,
4432   ER_ILLEGAL_HA,
4433   ER_KEY_NOT_FOUND,
4434   ER_NOT_FORM_FILE,
4435   ER_NOT_KEYFILE,
4436   ER_OLD_KEYFILE,
4437   ER_OPEN_AS_READONLY,
4438   ER_OUTOFMEMORY,
4439   ER_OUT_OF_SORTMEMORY,
4440   ER_UNEXPECTED_EOF,
4441   ER_CON_COUNT_ERROR,
4442   ER_OUT_OF_RESOURCES,
4443   ER_BAD_HOST_ERROR,
4444   ER_HANDSHAKE_ERROR,
4445   ER_DBACCESS_DENIED_ERROR,
4446   ER_ACCESS_DENIED_ERROR,
4447   ER_NO_DB_ERROR,
4448   ER_UNKNOWN_COM_ERROR,
4449   ER_BAD_NULL_ERROR,
4450   ER_BAD_DB_ERROR,
4451   ER_TABLE_EXISTS_ERROR,
4452   ER_BAD_TABLE_ERROR,
4453   ER_NON_UNIQ_ERROR,
4454   ER_SERVER_SHUTDOWN,
4455   ER_BAD_FIELD_ERROR,
4456   ER_WRONG_FIELD_WITH_GROUP,
4457   ER_WRONG_GROUP_FIELD,
4458   ER_WRONG_SUM_SELECT,
4459   ER_WRONG_VALUE_COUNT,
4460   ER_TOO_LONG_IDENT,
4461   ER_DUP_FIELDNAME,
4462   ER_DUP_KEYNAME,
4463   ER_DUP_ENTRY,
4464   ER_WRONG_FIELD_SPEC,
4465   ER_PARSE_ERROR,
4466   ER_EMPTY_QUERY,
4467   ER_NONUNIQ_TABLE,
4468   ER_INVALID_DEFAULT,
4469   ER_MULTIPLE_PRI_KEY,
4470   ER_TOO_MANY_KEYS,
4471   ER_TOO_MANY_KEY_PARTS,
4472   ER_TOO_LONG_KEY,
4473   ER_KEY_COLUMN_DOES_NOT_EXITS,
4474   ER_BLOB_USED_AS_KEY,
4475   ER_TOO_BIG_FIELDLENGTH,
4476   ER_WRONG_AUTO_KEY,
4477   ER_READY,
4478   ER_NORMAL_SHUTDOWN,
4479   ER_GOT_SIGNAL,
4480   ER_SHUTDOWN_COMPLETE,
4481   ER_FORCING_CLOSE,
4482   ER_IPSOCK_ERROR,
4483   ER_NO_SUCH_INDEX,
4484   ER_WRONG_FIELD_TERMINATORS,
4485   ER_BLOBS_AND_NO_TERMINATED,
4486   ER_TEXTFILE_NOT_READABLE,
4487   ER_FILE_EXISTS_ERROR,
4488   ER_LOAD_INFO,
4489   ER_ALTER_INFO,
4490   ER_WRONG_SUB_KEY,
4491   ER_CANT_REMOVE_ALL_FIELDS,
4492   ER_CANT_DROP_FIELD_OR_KEY,
4493   ER_INSERT_INFO,
4494   ER_INSERT_TABLE_USED,
4495   ER_NO_SUCH_THREAD,
4496   ER_KILL_DENIED_ERROR,
4497   ER_NO_TABLES_USED,
4498   ER_TOO_BIG_SET,
4499   ER_NO_UNIQUE_LOGFILE,
4500   ER_TABLE_NOT_LOCKED_FOR_WRITE,
4501   ER_TABLE_NOT_LOCKED,
4502   ER_BLOB_CANT_HAVE_DEFAULT,
4503   ER_WRONG_DB_NAME,
4504   ER_WRONG_TABLE_NAME,
4505   ER_TOO_BIG_SELECT,
4506   ER_UNKNOWN_ERROR,
4507   ER_UNKNOWN_PROCEDURE,
4508   ER_WRONG_PARAMCOUNT_TO_PROCEDURE,
4509   ER_WRONG_PARAMETERS_TO_PROCEDURE,
4510   ER_UNKNOWN_TABLE,
4511   ER_FIELD_SPECIFIED_TWICE,
4512   ER_INVALID_GROUP_FUNC_USE,
4513   ER_UNSUPPORTED_EXTENSION,
4514   ER_TABLE_MUST_HAVE_COLUMNS,
4515   ER_RECORD_FILE_FULL,
4516   ER_UNKNOWN_CHARACTER_SET,
4517   ER_TOO_MANY_TABLES,
4518   ER_TOO_MANY_FIELDS,
4519   ER_TOO_BIG_ROWSIZE,
4520   ER_STACK_OVERRUN,
4521   ER_WRONG_OUTER_JOIN,
4522   ER_NULL_COLUMN_IN_INDEX,
4523   ER_CANT_FIND_UDF,
4524   ER_CANT_INITIALIZE_UDF,
4525   ER_UDF_NO_PATHS,
4526   ER_UDF_EXISTS,
4527   ER_CANT_OPEN_LIBRARY,
4528   ER_CANT_FIND_DL_ENTRY,
4529   ER_FUNCTION_NOT_DEFINED,
4530   ER_HOST_IS_BLOCKED,
4531   ER_HOST_NOT_PRIVILEGED,
4532   ER_PASSWORD_ANONYMOUS_USER,
4533   ER_PASSWORD_NOT_ALLOWED,
4534   ER_PASSWORD_NO_MATCH,
4535   ER_UPDATE_INFO,
4536   ER_CANT_CREATE_THREAD,
4537   ER_WRONG_VALUE_COUNT_ON_ROW,
4538   ER_CANT_REOPEN_TABLE,
4539   ER_INVALID_USE_OF_NULL,
4540   ER_REGEXP_ERROR,
4541   ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
4542   ER_NONEXISTING_GRANT,
4543   ER_TABLEACCESS_DENIED_ERROR,
4544   ER_COLUMNACCESS_DENIED_ERROR,
4545   ER_ILLEGAL_GRANT_FOR_TABLE,
4546   ER_GRANT_WRONG_HOST_OR_USER,
4547   ER_NO_SUCH_TABLE,
4548   ER_NONEXISTING_TABLE_GRANT,
4549   ER_NOT_ALLOWED_COMMAND,
4550   ER_SYNTAX_ERROR,
4551   ER_DELAYED_CANT_CHANGE_LOCK,
4552   ER_TOO_MANY_DELAYED_THREADS,
4553   ER_ABORTING_CONNECTION,
4554   ER_NET_PACKET_TOO_LARGE,
4555   ER_NET_READ_ERROR_FROM_PIPE,
4556   ER_NET_FCNTL_ERROR,
4557   ER_NET_PACKETS_OUT_OF_ORDER,
4558   ER_NET_UNCOMPRESS_ERROR,
4559   ER_NET_READ_ERROR,
4560   ER_NET_READ_INTERRUPTED,
4561   ER_NET_ERROR_ON_WRITE,
4562   ER_NET_WRITE_INTERRUPTED,
4563   ER_TOO_LONG_STRING,
4564   ER_TABLE_CANT_HANDLE_BLOB,
4565   ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
4566   ER_DELAYED_INSERT_TABLE_LOCKED,
4567   ER_WRONG_COLUMN_NAME,
4568   ER_WRONG_KEY_COLUMN,
4569   ER_WRONG_MRG_TABLE,
4570   ER_DUP_UNIQUE,
4571   ER_BLOB_KEY_WITHOUT_LENGTH,
4572   ER_PRIMARY_CANT_HAVE_NULL,
4573   ER_TOO_MANY_ROWS,
4574   ER_REQUIRES_PRIMARY_KEY,
4575   ER_NO_RAID_COMPILED,
4576   ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
4577   ER_KEY_DOES_NOT_EXITS,
4578   ER_CHECK_NO_SUCH_TABLE,
4579   ER_CHECK_NOT_IMPLEMENTED,
4580   ER_CANT_DO_THIS_DURING_AN_TRANSACTION,
4581   ER_ERROR_DURING_COMMIT,
4582   ER_ERROR_DURING_ROLLBACK,
4583   ER_ERROR_DURING_FLUSH_LOGS,
4584   ER_ERROR_DURING_CHECKPOINT,
4585   ER_NEW_ABORTING_CONNECTION,
4586   ER_DUMP_NOT_IMPLEMENTED,
4587   ER_FLUSH_MASTER_BINLOG_CLOSED,
4588   ER_INDEX_REBUILD,
4589   ER_MASTER,
4590   ER_MASTER_NET_READ,
4591   ER_MASTER_NET_WRITE,
4592   ER_FT_MATCHING_KEY_NOT_FOUND,
4593   ER_LOCK_OR_ACTIVE_TRANSACTION,
4594   ER_UNKNOWN_SYSTEM_VARIABLE,
4595   ER_CRASHED_ON_USAGE,
4596   ER_CRASHED_ON_REPAIR,
4597   ER_WARNING_NOT_COMPLETE_ROLLBACK,
4598   ER_TRANS_CACHE_FULL,
4599   ER_SLAVE_MUST_STOP,
4600   ER_SLAVE_NOT_RUNNING,
4601   ER_BAD_SLAVE,
4602   ER_MASTER_INFO,
4603   ER_SLAVE_THREAD,
4604   ER_TOO_MANY_USER_CONNECTIONS,
4605   ER_SET_CONSTANTS_ONLY,
4606   ER_LOCK_WAIT_TIMEOUT,
4607   ER_LOCK_TABLE_FULL,
4608   ER_READ_ONLY_TRANSACTION,
4609   ER_DROP_DB_WITH_READ_LOCK,
4610   ER_CREATE_DB_WITH_READ_LOCK,
4611   ER_WRONG_ARGUMENTS,
4612   ER_NO_PERMISSION_TO_CREATE_USER,
4613   ER_UNION_TABLES_IN_DIFFERENT_DIR,
4614   ER_LOCK_DEADLOCK,
4615   ER_TABLE_CANT_HANDLE_FULLTEXT,
4616   ER_CANNOT_ADD_FOREIGN,
4617   ER_NO_REFERENCED_ROW,
4618   ER_ROW_IS_REFERENCED,
4619   ER_CONNECT_TO_MASTER,
4620   ER_QUERY_ON_MASTER,
4621   ER_ERROR_WHEN_EXECUTING_COMMAND,
4622   ER_WRONG_USAGE,
4623   ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
4624   ER_CANT_UPDATE_WITH_READLOCK,
4625   ER_MIXING_NOT_ALLOWED,
4626   ER_DUP_ARGUMENT,
4627   ER_USER_LIMIT_REACHED,
4628   ER_SPECIFIC_ACCESS_DENIED_ERROR,
4629   ER_LOCAL_VARIABLE,
4630   ER_GLOBAL_VARIABLE,
4631   ER_NO_DEFAULT,
4632   ER_WRONG_VALUE_FOR_VAR,
4633   ER_WRONG_TYPE_FOR_VAR,
4634   ER_VAR_CANT_BE_READ,
4635   ER_CANT_USE_OPTION_HERE,
4636   ER_NOT_SUPPORTED_YET,
4637   ER_MASTER_FATAL_ERROR_READING_BINLOG,
4638   ER_SLAVE_IGNORED_TABLE,
4639   CR_UNKNOWN_ERROR,
4640   CR_SOCKET_CREATE_ERROR,
4641   CR_CONNECTION_ERROR,
4642   CR_CONN_HOST_ERROR,
4643   CR_IPSOCK_ERROR,
4644   CR_UNKNOWN_HOST,
4645   CR_SERVER_GONE_ERROR,
4646   CR_VERSION_ERROR,
4647   CR_OUT_OF_MEMORY,
4648   CR_WRONG_HOST_INFO,
4649   CR_LOCALHOST_CONNECTION,
4650   CR_TCP_CONNECTION,
4651   CR_SERVER_HANDSHAKE_ERR,
4652   CR_SERVER_LOST,
4653   CR_COMMANDS_OUT_OF_SYNC,
4654   CR_NAMEDPIPE_CONNECTION,
4655   CR_NAMEDPIPEWAIT_ERROR,
4656   CR_NAMEDPIPEOPEN_ERROR,
4657   CR_NAMEDPIPESETSTATE_ERROR,
4658   CR_CANT_READ_CHARSET,
4659   CR_NET_PACKET_TOO_LARGE,
4660   CR_EMBEDDED_CONNECTION,
4661   CR_PROBE_SLAVE_STATUS,
4662   CR_PROBE_SLAVE_HOSTS,
4663   CR_PROBE_SLAVE_CONNECT,
4664   CR_PROBE_MASTER_CONNECT,
4665   CR_SSL_CONNECTION_ERROR,
4666   CR_MALFORMED_PACKET
4667);
4668\end{Code}
4669
4670\subsubsection{Sybase Result Codes}
4671
4672The Result\_Type values available from package APQ.Sybase are as follows;
4673
4674\begin{Code}
4675type Result_Type is (
4676   Execution_Failed, -- ct_results() call failed
4677   No_Results,       -- Cmd processed, but no results
4678   Row_Results,      -- Cmd processed, and row results
4679   Cursor_Results,   -- Cmd processed, and cursor row result
4680   Info_Results,     -- Cmd processed, no row data, but info
4681   Compute_Results,  -- Computed results
4682   Param_Results,    -- Parameter results
4683   Status_Results    -- Status results
4684);
4685\end{Code}
4686
4687\subsection{Generic APQ.Result\label{Generic APQ.Result}}
4688
4689To enable generic database processing, APQ version 2.0 adds a new
4690API function which is declared at the APQ\-.Root\_Query\_Type\index{APQ.Root\_Query\_Type} object
4691level. This function returns a Natural result:
4692
4693\begin{Code}
4694function Result(
4695   Query : Root_Query_Type;
4696) return Natural;
4697\end{Code}
4698
4699The value returned, represents the Result\_Type'Pos(arg)\index{Result\_Type'Pos}. In generic
4700database code, you could use this generic function to retrieve the
4701value. Later it can be turned into the appropriate Result\_Type when
4702required by doing a conversion. The following example illustrates:
4703
4704\begin{Example}
4705with APQ.MySQL.Client, APQ.PostgreSQL.Client;
4706...
4707procedure App(Q : Root_Query_Type'Class) is
4708   R :      Natural;
4709   PQ_R :   APQ.PostgreSQL.Result_Type;
4710   My_R :   APQ.MySQL.Result_Type;
4711begin
4712   ...
4713   R := APQ.Result(Q);
4714   if APQ.Engine_Of(Q) = Engine_MySQL then
4715      My_R := APQ.MySQL.Result_Type'Val(R);
4716      ...
4717   elsif APQ.Engine_Of(Q) = Engine_PostgreSQL then
4718      PQ_R := APQ.PostgreSQL.Result_Type'Val(R);
4719      ...
4720   ...
4721\end{Example}
4722
4723The code above demonstrates how generic database code is able to test
4724for specific database error codes, when required.
4725
4726
4727\subsection{Generic APQ.Engine\_Of\label{Generic APQ.Engine_Of}}
4728
4729As seen in the example of \Ref{Generic APQ.Result}, it is
4730sometimes necessary to determine in portable code, what database
4731technology is being used. Once this fact is known, the correct, more
4732specific action can be taken.  For example, the ``LIMIT n''\index{LIMIT} clause can
4733be added to MySQL\index{MySQL} queries to limit the number of returned rows for
4734greater efficiency.
4735
4736The function primitive Engine\_Of\index{Engine\_Of} can be used to determine
4737the database technology being used:
4738
4739\begin{Code}
4740type Database_Type is (
4741   Engine_PostgreSQL,
4742   Engine_MySQL,
4743   Engine_Sybase
4744);
4745
4746function Engine_Of(
4747   Query : Root_Query_Type;
4748) return Database_Type;
4749\end{Code}
4750
4751\subsection{Checked Execution}
4752
4753For many utility programs \index{utility programs}where error reporting
4754and recovery have simple requirements, a more compact and convenient
4755way to execute queries can be applied. With checked execution, the
4756query is not only executed, but any SQL errors are intercepted and
4757reported\index{reported} to Standard\_Error\index{Standard\_Error} automatically. This saves the programmer
4758effort when writing simple utility programs. Once the SQL\_Error\index{SQL\_Error} exception
4759is intercepted and reported, the exception is re-raised to leave control
4760in the caller's hands. The important thing here is that the error\index{error}
4761is caught and reported.
4762
4763The Execute\_Checked\index{Execute\_Checked} primitive has the following calling signature:
4764
4765\begin{Code}
4766procedure Execute_Checked(
4767   Query :      in out Root_Query_Type;
4768   Connection : in out Root_Connection_Type'Class;
4769   Msg :        in     String := ""
4770);
4771\end{Code}
4772
4773When the argument Msg is a non-empty\index{non-empty string} string like ``Dropping table
4774temp\_tbl'', the error message reported will be of the following
4775format:
4776
4777\begin{Example}
4778*** SQL ERROR: Dropping table temp_tbl
4779FATAL_ERROR: ERROR: Relation "temp_tbl" does not exist
4780\end{Example}
4781
4782The first line just identifies the fact that an SQL error occurred,
4783and reports the Msg text. The second line first reports Result\_Type'Image
4784of the error, and then reports the error message text as returned
4785by Error\_Message\index{Error\_Message}. In this case, the example shows that Result\_Type
4786Fatal\_Error was returned, and the error message returned from the
4787database server was ``ERROR: Relation ``temp\_tbl'' does not
4788exist''.
4789
4790When the null string\index{null string} (or the default value for
4791the parameter) is given to argument Msg, then the SQL query is dumped\index{dumped}
4792out to Standard\_Error\index{Standard\_Error} instead. This is often useful for debugging\index{debugging}
4793purposes.
4794
4795Changing the example \ref{Ex:Execute} on page \pageref{Ex:Execute}
4796slightly, we can apply the Execute\_Checked primitive in the place
4797of the Execute\index{Execute} call as shown in the example \ref{Ex:Execute_Checked}.
4798
4799\begin{NumberedExample}[label=Ex:Execute_Checked,caption=Executing Queries using Execute\_Checked]
4800declare
4801   type Cust_No_Type is new Integer range 1000..100_000;
4802   type Birthday_Type is new APQ_Timestamp;
4803
4804   procedure Append is new Append_Integer(Cust_No_Type);
4805
4806   procedure Encode is new Encode_Integer(Cust_No_Type,Boolean);
4807   procedure Encode is new Encode_Timestamp(Birthday_Type,Boolean);
4808
4809   C            : Connection_Type;
4810   Q            : Query_Type;
4811   Cust_No      : Cust_No_Type;     -- NOT NULL
4812   Birthday     : Birthday_Type;
4813   Birthday_Ind : Boolean;          -- Indicator
4814begin
4815   -- ...
4816   -- we set the Ada variable and so on...
4817   Prepare( Q, "INSERT INTO BIRTHDAY (CUST_NO,BIRTHDAY)" );
4818   Append( Q, "VALUES (" );
4819   Append( Q, Cust_No, ",");
4820   Encode( Q, Birthday, Birthday_TZ, Birthday_Ind, ")" );
4821   Execute_Checked( Q, C ); (*@\label{Ex:Execute_Checked:Execute_Checked}@*)
4822end;
4823\end{NumberedExample}
4824
4825
4826\subsection{Suppressing Checked Exceptions}
4827
4828For utility work, it is sometimes convenient to have Execute\_Checked
4829report errors, but not raise SQL\_Error\index{SQL\_Error}. This is useful when you don't
4830care about the outcome but want the error to be reported when detected.
4831The raising or not raising of SQL\_Error can be controlled for the
4832Execute\_Checked\index{Execute\_Checked} primitive by calling
4833Raise\_Exceptions\index{Raise\_Exceptions}. It has the following calling
4834requirements:
4835
4836\begin{Code}
4837procedure Raise_Exceptions(
4838   Query :    in out Query_Type;
4839   Raise_On : in     Boolean := True
4840);
4841\end{Code}
4842
4843The following example shows how exceptions can be suppressed:
4844
4845\begin{Example}
4846declare
4847   C : Connection_Type;
4848   Q : Query_Type;
4849begin
4850   ...
4851   Raise_Exceptions(Q,False); -- Suppress SQL_Error exception
4852   Execute_Checked(Q,C);      -- Report errors only
4853   Raise_Exceptions(Q,True);  -- Re-enable SQL_Error exceptions
4854\end{Example}
4855
4856\subsection{Suppressing Checked Reports}
4857
4858Occaisionally, it is useful to control whether or not reporting is
4859performed in the event of an SQL\_Error\index{SQL\_Error}. The reporting of errors can
4860be controlled by the Report\_Errors\index{Report\_Errors} primitive procedure:
4861
4862\begin{Code}
4863procedure Report_Errors(
4864   Query :     in out Query_Type;
4865   Report_On : in     Boolean := True
4866);
4867\end{Code}
4868
4869The default behaviour of a Query\_Type is to report errors and raise
4870SQL\_Error when Execute\_Checked experiences an SQL\_Error exception.
4871The reporting behaviour can be disabled\index{disable reporting} as follows:
4872
4873\begin{Example}
4874declare
4875   C :   Connection_Type;
4876   Q :   Query_Type;
4877begin
4878   ...
4879   Report_Errors(Q,False); -- Suppress error reporting
4880   Execute_Checked(Q,C);
4881\end{Example}
4882
4883Normally application programmers would not use Execute\_Checked with
4884error reporting disabled. However, it may be useful as a temporary
4885measure to cause error reporting while debugging\index{debugging} a program. Once the
4886debugging has been completed, a global Boolean\index{Boolean} value could be set
4887to false to prevent these errors from being reported.
4888
4889
4890\section{Transaction Operations}
4891
4892Database transaction\index{Transaction} operations consist of:
4893
4894\begin{itemize}
4895   \item BEGIN WORK\index{BEGIN WORK}
4896   \item COMMIT WORK\index{COMMIT WORK}
4897   \item ROLLBACK WORK\index{ROLLBACK WORK}
4898\end{itemize}
4899
4900It is possible to build your own queries to accomplish these operations
4901but the programmer is encourage to use the primitive operations below
4902instead. One reason for using the APQ provided functions is to make
4903your application portable to different databases. There are slight
4904variations on the SQL syntax\index{syntax, SQL} required for these operations. It may
4905also be possible in the future to query the state of the transaction.%
4906\footnote{It is likely that a function like an In\_Transaction function will
4907be added in the future.%
4908}
4909
4910The three primitives are named according to function \label{Begin, Commit and Rollback Work functions}
4911and are listed in Table~\ref{t:txp}.
4912
4913\begin{table}
4914   \begin{center}
4915      \begin{tabular}{ll}
4916         Primitive Name    &  SQL Function\\
4917         \hline
4918         Begin\_Work       &  BEGIN WORK\\
4919         Commit\_Work      &  COMMIT WORK\\
4920         Rollback\_Work    &  ROLLBACK WORK\\
4921      \end{tabular}
4922   \end{center}
4923   \caption{Transaction Primitives}\label{t:txp}
4924\end{table}
4925
4926The specifications of these primitives are listed below:
4927
4928\begin{Code}
4929procedure Begin_Work(
4930   Query :      in out Query_Type;
4931   Connection : in out Connection_Type'Class
4932);
4933\end{Code}
4934
4935\begin{Code}
4936procedure Commit_Work(
4937   Query :      in out Query_Type;
4938   Connection : in out Connection_Type'Class
4939);
4940\end{Code}
4941
4942\begin{Code}
4943procedure Rollback_Work(
4944   Query :      in out Query_Type;
4945   Connection : in out Connection_Type'Class
4946);
4947\end{Code}
4948
4949These primitives will raise the exceptions listed in Table~\ref{t:tranpx}.
4950
4951\begin{table}
4952   \begin{center}
4953      \begin{tabular}{ll}
4954         Exception Name    &  Reason\\
4955         \hline
4956         Not\_Connected    &  There is no connection\\
4957         Abort\_State      &  A ROLLBACK is required\\
4958         SQL\_Error        &  This should not normally occur\\
4959      \end{tabular}
4960   \end{center}
4961   \caption{Transaction Primitives Exceptions}\label{t:tranpx}
4962\end{table}
4963
4964The following simple example demonstrates the use of these primitives:
4965
4966\begin{Example}
4967declare
4968   C :   Connection_Type;
4969   Q :   Query_Type;
4970begin
4971   ...
4972   Begin_Work(Q,C);
4973   ...
4974   Commit_Work(Q,C);
4975\end{Example}
4976
4977\begin{description}
4978   \item [Note:] There is an implicit\index{implicit Clear} Clear operation before and after the
4979      execution of these operations for the Query\_Type\index{Query\_Type} object. The original
4980      fetch mode of the object is preserved after the call.
4981\end{description}
4982
4983\subsection{The PostgreSQL Abort\_State}
4984
4985The Abort\_State\index{Abort\_State} is unique to the PostgreSQL\index{PostgreSQL} database. Other databases
4986will tolerate failed steps within a transaction, but PostgreSQL will not.
4987The Abort\_State \label{Abort_State exception} exception indicates that the database
4988was in a transaction%
4989\footnote{A {}``BEGIN WORK'' statement was executed.%
4990} when a processing error occurred (like a duplicate key on insert
4991error). Once an error\index{error in transaction} is encountered within a PostgreSQL transaction,
4992the only course to recovery is by executing a ROLLBACK\index{ROLLBACK} WORK statement
4993(this is done by the Rollback\_Work\index{Rollback\_Work} call shown above). If duplicate\index{duplicate inserts}
4994inserts\index{inserts} may occur, you must test for them in advance of the INSERT\index{INSERT},
4995to avoid placing the transaction into the ``abort state''\index{abort state}. Note
4996that this PostgreSQL\index{PostgreSQL} behavior is different from other database vendor
4997offerings.
4998
4999The ``abort state''\index{abort state} itself is maintained in the Connection\_Type\index{Connection\_Type}
5000object, causing the state\index{state} to influence all Query\_Type objects using
5001the same connection. To clear the status\index{status}, you must perform a Rollback\_Work\index{Rollback\_Work}
5002call on any Query\_Type object, using the affected Connection\_Type
5003object where the status is saved.
5004
5005The Query\_Type object is used to form the SQL\index{SQL} statement and to hold
5006the result\index{result status} status. In application programming, you may want to dedicate
5007one Query\_Type object for each transaction in progress.%
5008\footnote{This will be important later, if you want to query whether or not
5009you are in a transaction.%
5010}
5011
5012\section{Fetch Operations}
5013
5014Some database operations, particularly SELECT\index{SELECT}, return
5015results. There are two fetch\index{fetch} related primitives:
5016
5017\begin{enumerate}
5018   \item Sequential\index{Sequential access} row fetch\index{fetch, sequential}
5019   \item Random\index{Random access} access row fetch\index{fetch, random}
5020\end{enumerate}
5021
5022The sequential fetch permits serial\index{serial access} access of the resulting rows (tuples\index{tuples}).
5023Random access fetching permits rapid\index{rapid access} access to particular row results.
5024
5025\subsection{Fetch Limitations\label{Fetch Limitations}}
5026
5027Some databases like PostgreSQL\index{PostgreSQL} have \emph{no} limitations\index{limitations} on how row
5028data is fetched. The fetch\index{fetch} may be sequential or random, as the application
5029requires. Some other databases however, require some planning by the
5030application programmer in this area. This distinction, and the API
5031to control this problem is new to APQ 2.0 and later, for database
5032engines\index{engines} that require it.
5033
5034For example, MySQL\index{MySQL} retrieves row data into the client program's address\index{address space}
5035space in one of two ways:
5036
5037\begin{itemize}
5038   \item one row at a time, but all rows must be fetched
5039   \item all rows are loaded into client memory\index{client memory}, for random access by the application
5040\end{itemize}
5041
5042For large result sets\index{large result sets}, fetching one row%
5043\footnote{This is done using the mysql\_use\_result() function.%
5044} at a time is very practical. However, MySQL\index{MySQL} requires that the program
5045fetch \emph{all} row data. If the result set\index{result set} is large, and only an
5046initial number of rows are required, this can be a serious performance
5047issue. This is a greater problem if the application would like to
5048cancel\index{cancel} the operation.
5049
5050When random access%
5051\footnote{This is done using the mysql\_store\_result() function.%
5052} of rows is required, MySQL\index{MySQL} requires that all row data be retrieved
5053and stored into the client program (behind the scenes). Fetching all
5054of this data into client memory\index{client memory} can be impractical for size\index{size} reasons
5055for large numbers of rows (there is an SQL work-around\index{SQL work-around} for this).
5056
5057The default APQ query mode varies according to database as listed in Table~\ref{t:fchmd}.
5058
5059\begin{table}
5060   \begin{center}
5061      \begin{tabular}{lll}
5062         Database       &  Default Mode      &  Comments\\
5063         \hline
5064         PostgreSQL     &  Random\_Fetch     &  Random or Sequential supported\\
5065         MySQL          &  Random\_Fetch     &  Watch \# of rows returned\\
5066         Sybase         &  Sequential\_Fetch &  Random\_Fetch not supported\\
5067      \end{tabular}
5068   \end{center}
5069   \caption{APQ Fetch Modes}\label{t:fchmd}
5070\end{table}
5071
5072From the table, you can see that PostgreSQL\index{PostgreSQL} has no difficulty in either
5073mode. MySQL\index{MySQL} supports both modes, but the programmer must be careful
5074about the result set size returned if Random\_Fetch mode is in use.
5075Finally, Sybase\index{Sybase} support does not support Random\_Fetch\index{Random\_Fetch} mode (Sybase
5076\emph{can} fetch rows randomly with a cursor, but only sequential
5077cursors\index{cursors} are currently supported by APQ).
5078
5079All database engines\index{engines} support sequential\index{sequential} access \- even in random\index{random}
5080access mode. Even if you are using the default or configured Random\_Fetch\index{Random\_Fetch}
5081mode, APQ will return rows sequentially unless a specific row is requested.
5082If the application programmer is using a database that is limited
5083in this way (MySQL), and has determined that fetching all results
5084into client memory is not suitable, then the mode of the Query\_Type\index{Query\_Type}
5085needs to be changed by the program to use sequential access instead.
5086See the next few sections on how to control the fetch query mode.
5087
5088If you are only planning to use PostgreSQL\index{PostgreSQL}, you can effectively ignore
5089the sections about Fetch Query modes. However, if you plan to write
5090your application in a database generic sort of way, or support MySQL\index{MySQL}
5091and/or Sybase\index{Sybase} code, then you need to plan for the fetch query modes
5092in your code.
5093
5094
5095\subsection{Fetch Query Modes\label{Fetch Query Modes}}
5096
5097Due to the performance limitations of different database engines,
5098APQ provides the application programmer a way to control the fetch\index{fetch}
5099mode used. Package APQ defines the Fetch\_Mode\_Type\index{Fetch\_Mode\_Type} for this purpose:
5100
5101\begin{Code}
5102type Fetch_Mode_Type is (
5103   Sequential_Fetch,    -- All databases
5104   Random_Fetch,        -- PostgreSQL, MySQL, not Sybase yet
5105   Cursor_For_Update,   -- Sybase
5106   Cursor_For_Read_Only -- Sybase
5107);
5108\end{Code}
5109
5110The last two modes related to cursors will be discussed separately.
5111
5112The application programmer can query the fetch mode that is in effect.
5113The Fetch\-\_Mode\index{Fetch\_Mode} function primitive returns the current state
5114of the Query\-\_Type object:
5115
5116\begin{Code}
5117function Fetch_Mode(
5118   Q : Query_Type
5119) return Fetch_Mode_Type;
5120\end{Code}
5121
5122To change the current mode in effect, use the function primitive Set\_Fetch\_Mode\index{Set\_Fetch\_Mode}:
5123
5124\begin{Code}
5125procedure Set_Fetch_Mode(
5126   Q :    in out Query_Type;
5127   Mode : in     Fetch_Mode_Type
5128);
5129\end{Code}
5130
5131The application should only change the query mode \emph{prior} to
5132the \emph{execution} of the query. When Execute\index{Execute} or Execute\_Checked\index{Execute\_Checked}
5133are called, APQ must commit to the fetch method being used. For this
5134reason, set the query mode when the Query\_Type is initially declared,
5135after a call to Reset\index{Reset} or Prepare\index{Prepare}. The mode must
5136be established prior to executing the query.
5137
5138Table \ref{t:sfmdx} lists the exceptions that may be raised by Set\_Fetch\_Mode.
5139
5140\begin{table}
5141   \begin{center}
5142      \begin{tabular}{ll}
5143         Exception Name    &  Reason\\
5144         \hline
5145         Failed            &  Query results exist - cannot change mode\\
5146      \end{tabular}
5147   \end{center}
5148   \caption{Set\_Fetch\_Mode Exceptions}\label{t:sfmdx}
5149\end{table}
5150
5151
5152\subsection{Sequential Fetch}
5153
5154The \emph{Query\_Type} object is always positioned at the first row\index{first row}
5155after the query has been executed. Sequential fetches\index{fetches} can then be
5156performed to retrieve the first row, through to the last resulting
5157row. The sequential \textbf{Fetch} primitive has the following calling
5158arguments:
5159
5160\begin{Code}
5161procedure Fetch(
5162   Q : in out Query_Type
5163);
5164\end{Code}
5165
5166A sequential fetch can always be made, whether the query object is
5167in sequential or random mode. However, be aware that some databases
5168(MySQL\index{MySQL}) require that all results be fetched when in Sequential\_Fetch\index{Sequential\_Fetch}
5169mode. The APQ default varies according to the database software being
5170used. See \Ref{Fetch Query Modes} to establish a mode explicitly.
5171
5172Table \ref{t:fchx} lists the exceptions that can be raised by Fetch.
5173
5174\begin{table}
5175   \begin{center}
5176      \begin{tabular}{ll}
5177         Exception Name    &  Reason\\
5178         \hline
5179         No\_Result        &  There was no command executed\\
5180         No\_Tuple         &  There were no result rows returned\\
5181         Not\_Supported    &  The fetch mode in effect is not supported\\
5182      \end{tabular}
5183   \end{center}
5184   \caption{Fetch Exceptions}\label{t:fchx}
5185\end{table}
5186
5187The No\_Result\index{No\_Result} exception is raised when the Query\_Type
5188object is in the wrong\index{wrong state} state. For example, if the Query\_Type
5189object is cleared, and/or an SQL query is built but not Executed,
5190then a No\_Result exception will be raised.
5191
5192The No\_Tuple\index{No\_Tuple} exception is raised to indicate that no rows
5193were available, or that there are no more rows remaining. In Sequential\_Fetch
5194mode, this indicates that there are no more rows to be returned. In
5195Random\_Fetch\index{Random\_Fetch} mode, this indicates that no rows were returned.%
5196\footnote{Note that requesting a non existant row in random fetch mode will
5197not raise an exception until a value is extracted.%
5198}
5199
5200The Not\_Supported\index{Not\_Supported} exception is also possible with APQ \apqversion
5201and later. This exception is raised to indicate that the database
5202software being used does not support the current Fetch\_Mode\index{Fetch\_Mode} that
5203is in effect.
5204
5205The following code shows a normal sequential fetch loop:\label{Sequential Fetch Example}
5206
5207\begin{Example}
5208declare
5209   C : Connection_Type;
5210   Q : Query_Type;
5211begin
5212   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5213   Append(Q, "FROM CUSTOMER");
5214   Execute(Q,C);
5215   loop
5216      begin
5217         Fetch(Q);
5218      exception
5219         when APQ.No_Tuple =>
5220            exit;
5221      end;
5222      ...
5223   end loop;
5224   Clear(Q); -- Release any query results
5225\end{Example}
5226
5227Clearing the query (or allowing it to fall out of scope) is recommended.
5228This releases\index{releases} resources\index{resources} that are
5229holding any prior query results.
5230
5231
5232\subsection{Random Fetch}
5233
5234The random fetch\index{fetch} operation requires the use of the Tuple\_Index\_Type\index{Tuple\_Index\_Type}
5235defined in the package APQ:
5236
5237\begin{Code}
5238type Tuple_Index_Type is mod 2 ** 64;
5239First_Tuple_Index : constant Tuple_Index_Type := 1;
5240\end{Code}
5241
5242The random Fetch primitive has the following calling arguments:
5243
5244\begin{Code}
5245procedure Fetch(
5246   Q :  in out Query_Type;
5247   TX : in     Tuple_Index_Type
5248);
5249\end{Code}
5250
5251Table \ref{t:rfchx} lists the possible exceptions for
5252a random Fetch call.
5253
5254\begin{table}
5255   \begin{center}
5256      \begin{tabular}{ll}
5257         Exception Name    &  Reason\\
5258         \hline
5259         No\_Result        &  There was no command executed\\
5260         No\_Tuple         &  There were no result rows returned\\
5261         Not\_Supported    &  Random access is not supported\\
5262      \end{tabular}
5263   \end{center}
5264   \caption{Random Fetch Exceptions}\label{t:rfchx}
5265\end{table}
5266
5267A random fetch example is provided below:\label{Random Fetch Example}
5268
5269\begin{Example}
5270declare
5271   C : Connection_Type;
5272   Q : Query_Type;
5273begin
5274   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5275   Append(Q, "FROM CUSTOMER");
5276   Execute(Q,C);
5277
5278   for TX in 1..Tuple_Index_Type(Tuples(Q)) loop
5279      Fetch(Q,TX);
5280      ...
5281   end loop;
5282   Clear(Q);
5283\end{Example}
5284
5285The function Tuples(Q)\index{Tuples} that was used in the \emph{for} loop, returns
5286the number of result rows for the query.%
5287\footnote{Which can be zero.%
5288} A slight modification of this loop could permit processing the rows
5289in reverse order.
5290
5291
5292\subsubsection{Notes:}
5293
5294\begin{enumerate}
5295   \item If the tuple\index{tuple} index \emph{TX} provided to Fetch is out
5296         of range for the result set, no exception will be raised. An exception
5297         \emph{will} be raised however, when the application attempts to fetch
5298         any value from that out of range row.
5299   \item Any subsequent sequential fetch operation will fetch the row following
5300         the last randomly accessed row.
5301\end{enumerate}
5302
5303\subsection{Function End\_of\_Query\label{End_of_Query}}
5304
5305To facilitate sequential
5306fetch operations, the End\_of\_Query primitive function was provided in
5307early versions of APQ. This API remains, but is considered
5308\emph{obsolete} and should be avoided. MySQL\index{MySQL} users should not use it at
5309all, due to the bug\index{bug} present in the MySQL client library. See the note
5310that follows the tables.
5311
5312\begin{quote}
5313Note: This function is depreciated. Catch the No\_Tuple exception
5314instead for greater database portability.
5315\end{quote}
5316
5317The calling requirements are summarized in the following specification:
5318
5319\begin{Code}
5320function End_of_Query(
5321   Q : Query_Type
5322) return Boolean;
5323\end{Code}
5324
5325Table \ref{t:eoqx} lists the exceptions for this function.
5326
5327\begin{table}
5328   \begin{center}
5329      \begin{tabular}{ll}
5330         Exception Name    &  Reason\\
5331         \hline
5332         No\_Result        &  There was no command executed\\
5333      \end{tabular}
5334   \end{center}
5335   \caption{End\_of\_Query Exceptions}\label{t:eoqx}
5336\end{table}
5337
5338The End\_of\_Query\index{End\_of\_Query} function returns a Boolean\index{Boolean} result:
5339
5340\begin{description}
5341   \item [False] there is at least one more result row available (not at end)
5342   \item [True] there are no more rows\index{rows} available (at end)
5343\end{description}
5344
5345\begin{quote}
5346MySQL Note:
5347The MySQL\index{MySQL} implementation of End\_Of\_Query is not a good
5348one. End\_Of\_Query\index{End\_of\_Query} should \emph{not} be used. The problem is located
5349in the MySQL C client library that comes with MySQL. The C mysql\_eof()\index{mysql\_eof()}
5350function returns false after reading the last row. It is only by fetching
5351one more row and discovering that there are no more rows, that mysql\_eof()
5352then starts to return true. In other words, it returns true, when
5353the end has already been reached. Since there is no way to work around
5354this problem in MySQL, a developer should avoid using End\_Of\_Query
5355completely.
5356\end{quote}
5357
5358Catch the exception No\_Tuple\index{No\_Tuple} instead, when fetching rows.
5359
5360
5361\subsection{Function Tuple}
5362
5363The Tuple\index{Tuple} function primitive is an information function that
5364returns the current tuple number\index{tuple number} that was last
5365fetched. If there has been no fetch yet, the No\_Tuple\index{No\_Tuple} exception
5366is raised. The calling signature is as follows:
5367
5368\begin{Code}
5369function Tuple(
5370   Q : Query_Type
5371) return Tuple_Index_Type;
5372\end{Code}
5373
5374Tuple can raise the exceptions listed in Table~\ref{t:tupx}.
5375
5376\begin{table}
5377   \begin{center}
5378      \begin{tabular}{ll}
5379         Exception Name    &  Reason\\
5380         \hline
5381         No\_Tuple         &  There was no fetch performed yet\\
5382      \end{tabular}
5383   \end{center}
5384   \caption{Tuple Exceptions}\label{t:tupx}
5385\end{table}
5386
5387The following example shows the function being used:
5388
5389\begin{Example}
5390declare
5391   C : Connection_Type;
5392   Q : Query_Type;
5393   X : Tuple_Index_Type;
5394begin
5395   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5396   Append(Q, "FROM CUSTOMER");
5397   Execute(Q,C);
5398
5399   loop
5400      begin
5401         Fetch(Q);
5402      exception
5403         when APQ.No_Tuple =>
5404            exit;
5405      end;
5406      TX := Tuple(Q); -- Get Row #
5407      ...
5408   end loop;
5409   Clear(Q);
5410\end{Example}
5411
5412\subsection{Rewind Procedure}
5413
5414Sometimes it is desireable to reprocess results sequentially. This
5415is easily accomplished with the Rewind\index{Rewind} primitive. This
5416primitive merely alters the state of the Query\_Type object such that
5417the next fetch\index{fetch} operation will start with the first row. This only
5418works when the fetch mode is Random\_Fetch\index{Random\_Fetch}.
5419
5420The calling requirements are listed as follows:
5421
5422\begin{Code}
5423procedure Rewind(
5424   Q : in out Query_Type
5425);
5426\end{Code}
5427
5428Table \ref{t:rwx} lists the possible exceptions for Rewind.
5429
5430\begin{table}
5431   \begin{center}
5432      \begin{tabular}{ll}
5433         Exception Name    &  Reason\\
5434         \hline
5435         SQL\_Error        &  The Query\_Type is not in Random\_Fetch mode\\
5436      \end{tabular}
5437   \end{center}
5438   \caption{Rewind Exceptions}\label{t:rwx}
5439\end{table}
5440
5441The following example shows the Rewind procedure being used:
5442
5443\begin{Example}
5444declare
5445   C : Connection_Type;
5446   Q : Query_Type;
5447begin
5448   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5449   Append(Q, "FROM CUSTOMER");
5450   Execute(Q,C);
5451
5452   loop
5453      begin
5454         Fetch(Q);
5455      exception
5456         when APQ.No_Tuple =>
5457            exit;
5458      end;
5459      ...
5460   end loop;
5461
5462   -- REPROCESS THE QUERY RESULTS :
5463
5464   Rewind(Q);
5465
5466   loop
5467      begin
5468         Fetch(Q);
5469      exception
5470         when APQ.No_Tuple =>
5471            exit;
5472      end;
5473      ...
5474   end loop;
5475   Clear(Q);
5476\end{Example}
5477
5478\subsection{Tuples Function}
5479
5480You have already seen this function used in the example on page
5481\pageref{Random Fetch Example}. This information function returns the
5482number of result rows that are available. It should only be called after
5483the \emph{Query\_Type} has been executed however. Otherwise the
5484No\_Result exception will be raised by Tuples\index{Tuples}.
5485
5486The calling requirement for this function is summarized as follows:
5487
5488\begin{Code}
5489function Tuples(
5490   Q : Query_Type
5491) return Tuple_Count_Type;
5492\end{Code}
5493
5494Tuples can raise the exceptions listed in Table~\ref{t:tupsx}. For an
5495example of use, see \Ref{Random Fetch Example}.
5496
5497\begin{table}
5498   \begin{center}
5499      \begin{tabular}{ll}
5500         Exception Name    &  Reason\\
5501         \hline
5502         No\_Result        &  There was no execute performed yet\\
5503      \end{tabular}
5504   \end{center}
5505   \caption{Tuples Exceptions}\label{t:tupsx}
5506\end{table}
5507
5508\subsection{Using Cursors}
5509
5510For databases supporting cursor\index{cursor} operations in their client\index{client libraries} libraries
5511(Sybase), APQ will automatically generate cursor names for each Query\_Type
5512object. The function Cursor\_Name\index{Cursor\_Name} will retrieve this for you (see
5513\Ref{Cursor_Name}).
5514
5515To perform cursor operations, there are the following general steps
5516to follow:
5517
5518\begin{enumerate}
5519   \item Set the cursor mode of the Query\_Type object.
5520   \item Prepare the SQL query to fetch rows.
5521   \item Execute the SQL query.
5522   \item Fetch a row.
5523   \item Prepare the inner SQL query using ``WHERE CURRENT OF''\index{WHERE CURRENT OF}
5524   \item Execute the inner query
5525   \item Repeat steps 4-6 as required
5526\end{enumerate}
5527
5528Describing cursor operation in APQ is probably best done with a concrete
5529example. Assume a simple SALARIES table like the one below:
5530
5531\begin{SQL}
5532CREATE TABLE SALARIES (
5533   EMPNO    INT NOT NULL PRIMARY KEY,
5534   SALARY   REAL NOT NULL
5535);
5536\end{SQL}
5537
5538Our example, will assume the following values in the table:
5539
5540\begin{SQL}
5541select * from salaries
5542go
5543empno       salary
5544----------- --------------------
5545          2         56000.000000
5546          3         82800.000000
5547          4         82500.000000
5548          5         43600.000000
5549
55504 rows affected
55511>
5552\end{SQL}
5553
5554Our application is tasked with the job of rewarding all employees
5555with salaries greater than or equal to \$50,000 with an increase of
55565\% (life is often unfair). It is possible to construct an SQL\index{SQL} statement
5557to do this without using cursors but we're going to build the shell
5558of a program that will be required to get approval from the user (using
5559a GUI\index{GUI} etc.) Getting user approval is not possible in SQL, so we need
5560to code a fetch loop and an inner query to do the update if the approval
5561is granted. This is one example of how a cursor can be useful.
5562
5563The following is a Sybase\index{Sybase} APQ program listing for the
5564update:\label{Cursor Example Program}
5565
5566\begin{Example}
5567with Ada.Text _IO;
5568with APQ.Sybase.Client;
5569use APQ, APQ.Sybase.Client, Ada.Text_IO;
5570
5571procedure Salaries is
5572   function Value is new Integer_Value(Integer);
5573   function Value is new Float_Value(APQ_Double);
5574   procedure Append is new Append_Float(APQ_Double);
5575
5576   C :      Connection_Type;
5577   Q :      Query_Type;
5578   Q2 :     Query_Type;
5579   Empno :  Integer;
5580   Salary : APQ_Double;
5581begin
5582   Set_Instance(C,"SYBIL");
5583   Set_DB_Name(C,"wwg");
5584   Set_User_Password(C,"wwg","somepw");
5585   Connect(C);
5586
5587   Begin_Work(Q,C);
5588   Set_Fetch_Mode(Q,Cursor_For_Update);
5589
5590   Prepare(Q,    "SELECT EMPNO,SALARY");
5591   Append_Line(Q,"FROM SALARIES");
5592   Execute(Q,C);
5593
5594   loop
5595      begin
5596         Fetch(Q);
5597      exception
5598         when No_Tuple =>
5599            exit;
5600      end;
5601
5602      Empno  := Value(Q,1);
5603      Salary := Value(Q,2);
5604      Put_Line("Empno=" & Empno'Img & " Salary="
5605         & Salary'Img);
5606      if Salary >= 50_000.0 then
5607         Salary := Salary * 1.05; -- 5% raise
5608
5609         Prepare(Q2,    "UPDATE SALARIES");
5610         Append(Q2,     "SET SALARY = ");
5611         Append(Q2,Salary,Line_Feed);
5612         Append_Line(Q2,"WHERE CURRENT OF " & Cursor_Name(Q));
5613         Execute(Q2,C);
5614         Clear(Q2);
5615      end if;
5616   end loop;
5617   Clear(Q);
5618
5619   Commit_Work(Q,C);
5620   Disconnect(C);
5621end Salaries;
5622\end{Example}
5623
5624The fetch mode of query object Q is set to Cursor\_For\_Update\index{Cursor\_For\_Update}. This is
5625critical for the cursor\index{cursor} operation to work (you can also use
5626Cursor\_For\_Read\_Only for non-update operations). The outer query\index{outer query} is
5627formed, which is then executed. When the program decides it wants to
5628update a particular row (here we pretend the user has approved it from
5629the terminal), we prepare and execute the inner query\index{inner query} Q2. The special
5630WHERE clause ``WHERE CURRENT OF''\index{WHERE CURRENT OF} is used, naming the cursor being
5631used from the outer query object Q. The function Cursor\_Name(Q)\index{Cursor\_Name}
5632supplies the cursor name for it. Once the inner query is processed, more
5633outer query rows can be fetched\index{fetched} and processed in like manner.
5634
5635Note that the inner query can also include DELETE\index{DELETE} ... WHERE CURRENT
5636OF\index{WHERE CURRENT OF} operations. Using a cursor\index{cursor} guarantees that when you go to delete
5637the row, that some other external process hasn't deleted it before
5638you have (this avoids experiencing an error). Similarly for updates\index{updates},
5639if the correct isolation\index{isolation level} level is used, you can be sure that the values
5640in the row have not changed by the time you perform the inner query.
5641
5642\section{Column Information Functions}
5643
5644After a query has been executed, which returns a set of rows, it is
5645sometimes necessary to obtain information\index{information, column} about the columns. Many
5646of the functions make use of the following data type:
5647
5648\begin{Code}
5649
5650	type Column_Index_Type is new Postive;
5651
5652\end{Code}
5653
5654\begin{table}
5655   \begin{center}
5656      \begin{tabular}{ll}
5657         Function Name           &  Purpose\\
5658         \hline
5659         Columns                 &  Return the \# of columns in each row\\
5660         Column\_Name            &  Return the column name for an index value\\
5661         Column\_Index           &  Return the index for a column name\\
5662         Column\_Type            &  Return type information for the column\\
5663         Is\_Null                &  Test if a column is null\\
5664      \end{tabular}
5665   \end{center}
5666   \caption{Column Information Functions}\label{t:cif}
5667\end{table}
5668
5669Table \ref{t:cif}
5670lists four column information functions that are available to the
5671application programmer.
5672All of these functions will raise the exception No\_Result\index{No\_Result}
5673if an execute has not been performed successfully on the Query\_Type
5674object.
5675
5676Note that the case of the column name returned will match the SQL
5677case policy for the connection. If the policy is Upper\_Case\index{Upper\_Case}, then
5678column names are returned in uppercase. Other possibilities follow
5679the established case policy\index{case policy}.
5680
5681
5682\subsection{Function Columns}
5683
5684The Columns primitive function returns the number of columns\index{columns}
5685available in each row of the result set. The calling arguments are
5686summarized as follows:
5687
5688\begin{Code}
5689function Columns(
5690   Q : Query_Type
5691) return Natural;
5692\end{Code}
5693
5694The Columns\index{Columns} function may raise the exceptions found in
5695Table~\ref{t:cex}.
5696
5697\begin{table}
5698   \begin{center}
5699      \begin{tabular}{ll}
5700         Exception Name    &  Reason\\
5701         \hline
5702         No\_Result        &  There was no execute performed\\
5703      \end{tabular}
5704   \end{center}
5705   \caption{Columns Exceptions}\label{t:cex}
5706\end{table}
5707
5708The following example shows the function at work:
5709
5710\begin{Example}
5711declare
5712   C : Connection_Type;
5713   Q : Query_Type;
5714begin
5715   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5716   Append(Q, "FROM CUSTOMER");
5717   Execute(Q,C);
5718
5719   loop
5720      begin
5721         Fetch(Q);
5722      exception
5723         when APQ.No_Tuple =>
5724            exit;
5725      end;
5726
5727      for CX in 1..Column_Index_Type(Columns(Q)) loop
5728         ...process each column...
5729      end loop;
5730   end loop;
5731   Clear(Q);
5732\end{Example}
5733
5734\subsection{Function Column\_Name}
5735
5736The primitive Column\_Name\index{Column\_Name} returns the name of the column for a particular
5737column index\index{column index} value. The calling requirements
5738are summarized in the following table:
5739
5740\begin{Code}
5741function Column_Name(
5742   Query : in Query_Type;
5743   Index : in Column_Index_Type
5744) return String;
5745\end{Code}
5746
5747The Column\_Name function may raise the exceptions listed in Table~\ref{t:cnx}.
5748
5749\begin{table}
5750   \begin{center}
5751      \begin{tabular}{ll}
5752         Exception Name    &  Reason\\
5753         \hline
5754         No\_Result        &  There was no execute performed\\
5755         No\_Column        &  Bad Column\_Index\_Type value\\
5756      \end{tabular}
5757   \end{center}
5758   \caption{Column\_Name Exceptions}\label{t:cnx}
5759\end{table}
5760
5761Note that the case of the column name returned will match the SQL
5762case policy for the connection. If the policy is Upper\_Case\index{Upper\_Case}, then
5763column names are returned in uppercase. Other possibilities follow
5764the established case policy\index{case policy}.
5765
5766The following example shows the function in use:
5767
5768\begin{Example}
5769declare
5770   C : Connection_Type;
5771   Q : Query_Type;
5772begin
5773   Prepare(Q, "SELECT CUST_NO,CUST_NAME");
5774   Append(Q,  "FROM CUSTOMER");
5775   Execute(Q,C);
5776
5777   loop
5778      begin
5779         Fetch(Q);
5780      exception
5781         when No_Tuple =>
5782            exit;
5783      end;
5784
5785      for CX in 1..Column_Index_Type(Columns(Q)) loop
5786         Put_Line("Column Name: " & Column_Name(Q,CX));
5787      end loop;
5788   end loop;
5789   Clear(Q);
5790\end{Example}
5791
5792\subsection{Function Column\_Index}
5793
5794If you have a column name, but want to know the column index value,
5795then the Column\_Index\index{Column\_Index} primitive function can be used. It's calling
5796requirements are as follows:
5797
5798\begin{Code}
5799function Column_Index(
5800   Query : in Query_Type;
5801   Name :  in String
5802) return Column_Index_Type;
5803\end{Code}
5804
5805The function may raise any of the exceptions listed in Table~\ref{t:cidxx}.
5806
5807\begin{table}
5808   \begin{center}
5809      \begin{tabular}{ll}
5810         Exception Name    &  Reason\\
5811         \hline
5812         No\_Result        &  There was no execute performed\\
5813         No\_Column        &  Unknown column name\\
5814      \end{tabular}
5815   \end{center}
5816   \caption{Column\_Index Exceptions}\label{t:cidxx}
5817\end{table}
5818
5819The following rather contrived example shows the Column\_Index function
5820used in the pragma\index{pragma assert} assert statement:
5821
5822\begin{NumberedExample}
5823declare
5824   C : Connection_Type;
5825   Q : Query_Type;
5826begin
5827   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
5828   Append(Q, "FROM~CUSTOMER");
5829   Execute(Q,C);
5830
5831   loop
5832      begin
5833         Fetch(Q);
5834      exception
5835         when No_Tuple =>
5836            exit;
5837      end;
5838
5839      for CX in 1..Column_Index_Type(Columns(Q)) loop
5840         declare
5841            Col_Name : String := Column_Name(Q,CX);
5842         begin
5843            Put_Line("Column Name: " & Col_Name);
5844            pragma assert(CX = Column_Index(Col_Name));(*@\label{Ex:pragma}@*)
5845         end;
5846      end loop;
5847   end loop;
5848   Clear(Q);
5849\end{NumberedExample}
5850
5851The pragma statement in line~\ref{Ex:pragma} is not necessary, but
5852was included in this example to show how the Column\_Index and the
5853Column\_Name are related.
5854
5855\subsection{Function Column\_Type}
5856
5857\index{Column\_Type}The column type information varies according to the database product
5858being used. The following subsections are specific to the APQ supported
5859database products.
5860
5861\subsubsection{PostgreSQL Type Information}
5862
5863The Column\_Type\index{Column\_Type} primitive is the beginning of type information for
5864the column. This function returns the Row\_ID\_Type\index{Row\_ID\_Type}
5865value that describes the type in the pg\_type\index{pg\_type} PostgreSQL\index{PostgreSQL} table\index{table}. See
5866the PostgreSQL database documentation for more details.
5867
5868The Column\_Type calling signature is as follows:
5869
5870\begin{Code}
5871function Column_Type(
5872   Q :  in Query_Type;
5873   CX : in Column_Index_Type
5874) return Row_ID_Type;
5875\end{Code}
5876
5877Table \ref{t:ctypx} lists the exceptions that
5878may be raised by Column\_Type.
5879
5880\begin{table}
5881   \begin{center}
5882      \begin{tabular}{ll}
5883         Exception Name    &  Reason\\
5884         \hline
5885         No\_Result        &  There was no execute performed\\
5886         No\_Column        &  Unknown column name\\
5887      \end{tabular}
5888   \end{center}
5889   \caption{Column\_Type Exceptions}\label{t:ctypx}
5890\end{table}
5891
5892\subsubsection{MySQL Type Information}
5893
5894The field\index{field types} types supported by MySQL\index{MySQL} are defined by APQ\-.MySQL\-.Field\_Type.
5895The programmer may use the Query\_Type primitive APQ\-.MySQL\-.Client\-.Column\_Type
5896to determine the column's type:
5897
5898\begin{Code}
5899function Column_Type(
5900   Q :  in Query_Type;
5901   CX : in Column_Index_Type
5902) return Field_Type;
5903\end{Code}
5904
5905At the writing of this manual, the values in Table~\ref{t:mysqlftyp}
5906are supported MySQL field (column) type names.
5907
5908\begin{table}
5909   \begin{center}
5910      \begin{tabular}{ll}
5911         Field\_Type                &  MySQL Datatype\\
5912         \hline
5913         FIELD\_TYPE\_DECIMAL       &  DECIMAL\\
5914         FIELD\_TYPE\_TINY          &  TINYINT | BOOLEAN\\
5915         FIELD\_TYPE\_SHORT         &  SMALLINT\\
5916         FIELD\_TYPE\_LONG          &  INTEGER\\
5917         FIELD\_TYPE\_FLOAT         &  FLOAT\\
5918         FIELD\_TYPE\_DOUBLE        &  DOUBLE\\
5919         FIELD\_TYPE\_NULL          &  BOOLEAN\\
5920         FIELD\_TYPE\_TIMESTAMP     &  TIMESTAMP\\
5921         FIELD\_TYPE\_LONGLONG      &  BIGINT\\
5922         FIELD\_TYPE\_INT24         &  MEDIUMINT\\
5923         FIELD\_TYPE\_DATE          &  DATE\\
5924         FIELD\_TYPE\_TIME          &  TIME\\
5925         FIELD\_TYPE\_DATETIME      &  DATETIME\\
5926         FIELD\_TYPE\_YEAR          &  YEAR\\
5927         FIELD\_TYPE\_NEWDATE       &  ?\\
5928         FIELD\_TYPE\_ENUM          &  ENUM\\
5929         FIELD\_TYPE\_SET           &  SET\\
5930         FIELD\_TYPE\_TINY\_BLOB    &  TINYTEXT | TINYBLOB\\
5931         FIELD\_TYPE\_MEDIUM\_BLOB  &  MEDIUMTEXT | MEDIUMBLOB\\
5932         FIELD\_TYPE\_LONG\_BLOB    &  LONGTEXT | LONGBLOB\\
5933         FIELD\_TYPE\_BLOB          &  TEXT | BLOB\\
5934         FIELD\_TYPE\_VAR\_STRING   &  VARCHAR(N)\\
5935         FIELD\_TYPE\_STRING        &  CHAR(N)\\
5936      \end{tabular}
5937   \end{center}
5938   \caption{MySQL Field Types}\label{t:mysqlftyp}
5939\end{table}
5940
5941APQ does not yet fully support all of MySQL data types.
5942
5943
5944\subsection*{Sybase Type Information}
5945
5946Sybase\index{Sybase} also provides type information:
5947
5948\begin{Code}
5949function Column_Type(
5950   Q :  in Query_Type;
5951   CX : in Column_Index_Type
5952) return Field_Type;
5953\end{Code}
5954
5955Sybase is capable of returning types listed in the Column\_Type column
5956of Table~\ref{t:sycoltyp}.
5957
5958\begin{table}
5959   \begin{center}
5960      \begin{tabular}{lll}
5961         Column\_Type               &  Sybase Database Type &  APQ Support\\
5962         \hline
5963         Type\_CHAR                 &  CHAR/VARCHAR         &  Yes\\
5964         Type\_BINARY               &  BINARY/VARBINARY     &  No\\
5965         Type\_LONGCHAR             &  \emph{None}          &  No\\
5966         Type\_LONGBINARY           &  \emph{None}          &  No\\
5967         Type\_TEXT                 &  TEXT                 &  Yes\\
5968         Type\_IMAGE                &  IMAGE                &  No\\
5969         Type\_TINYINT              &  TINYINT              &  Yes\\
5970         Type\_SMALLINT             &  SMALLINT             &  Yes\\
5971         Type\_INT                  &  INT/INTEGER          &  Yes\\
5972         Type\_REAL                 &  REAL                 &  Yes\\
5973         Type\_FLOAT                &  FLOAT                &  Yes\\
5974         Type\_BIT                  &  BIT                  &  Yes\\
5975         Type\_DATETIME             &  DATETIME             &  Yes\\
5976         Type\_DATETIME4            &  SMALLDATETIME        &  Yes\\
5977         Type\_MONEY                &  MONEY                &  Yes\\
5978         Type\_MONEY4               &  SMALLMONEY           &  Yes\\
5979         Type\_NUMERIC              &  NUMERIC              &  Yes\\
5980         Type\_DECIMAL              &  DECIMAL              &  Yes\\
5981         Type\_VARCHAR              &  VARCHAR              &  Yes\\
5982         Type\_VARBINARY            &  VARBINARY            &  No\\
5983         Type\_LONG                 &  LONG                 &  Yes\\
5984         Type\_SENSITIVITY          &  \emph{None}          &  No\\
5985         Type\_BOUNDARY             &  BOUNDARY             &  No\\
5986         Type\_VOID                 &  \emph{None}          &  No\\
5987         Type\_USHORT               &  USHORT               &  Yes\\
5988         Type\_UNICHAR              &  UNICHAR/UNIVARCHAR   &  No\\
5989         Type\_BLOB                 &  BLOB                 &  No\\
5990         Type\_DATE                 &  DATE                 &  Yes\\
5991      \end{tabular}
5992   \end{center}
5993   \caption{Sybase Column Types}\label{t:sycoltyp}
5994\end{table}
5995
5996
5997\subsection{Is\_Null Function}
5998
5999If a column is capable of returning a NULL\index{NULL} value, it
6000becomes necessary to test for this. The Is\_Null\index{Is\_Null} function calling
6001specification is as follows:
6002
6003\begin{Code}
6004function Is_Null(
6005   Q :  in Query_Type;
6006   CX : in Column_Index_Type
6007) return Boolean;
6008\end{Code}
6009
6010The Is\_Null function may raise the exceptions listed in Table~\ref{t:isnullx}.
6011
6012\begin{table}
6013   \begin{center}
6014      \begin{tabular}{ll}
6015         Exception Name    &  Reason\\
6016         \hline
6017         No\_Result        &  There was no execute performed\\
6018         No\_Column        &  Unknown column name\\
6019      \end{tabular}
6020   \end{center}
6021   \caption{Is\_Null Exceptions}\label{t:isnullx}
6022\end{table}
6023
6024The following example shows how to test if the CUST\_NAME column is
6025null\index{null} or not:
6026
6027\begin{Example}
6028declare
6029   C : Connection_Type;
6030   Q : Query_Type;
6031begin
6032   Prepare(Q,"SELECT CUST_NO,CUST_NAME,BIRTH_DATE");
6033   Append(Q, "FROM CUSTOMER");
6034   Execute(Q,C);
6035
6036   loop
6037      begin
6038         Fetch(Q);
6039      exception
6040         when No_Tuple =>
6041            exit;
6042      end;
6043      ...
6044
6045      if Is_Null(Q,2) then
6046         -- CUST_NAME value is null
6047      end if;
6048      ...
6049   end loop;
6050   Clear(Q);
6051\end{Example}
6052
6053\subsection{Column\_Is\_Null Generic Function}
6054
6055If you need to test for null\index{null} using strongly typed
6056indicators\index{indicators}, you may want to instantiate the
6057Column\_Is\_Null\index{Column\_Is\_Null} generic function. The generic parameters are:
6058
6059\begin{Code}
6060generic
6061   type Ind_Type is new Boolean;
6062function Column_Is_Null(
6063   Q :  in Query_Type'Class;
6064   CX : in Column_Index_Type
6065) return Ind_Type;
6066\end{Code}
6067
6068Table~\ref{t:isnullx} lists exceptions that also apply to the Column\_Is\_Null function.
6069
6070%\begin{tabular}{ll}
6071%Exception Name    &  Reason\\
6072%\hline
6073%No\_Result        &  There was no execute performed\\
6074%No\_Column        &  No column at index\\
6075%\end{tabular}
6076
6077The following example illustrates its use:
6078
6079\begin{Example}
6080declare
6081   type Cust_Name_Ind_Type is new Boolean;
6082   function Is_Null
6083       is new Column_Is_Null(Cust_Name_Ind_Type);
6084
6085   C :             Connection_Type;
6086   Q :             Query_Type;
6087   Cust_Name_Ind : Cust_Name_Ind_Type;
6088 begin
6089   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
6090   Append(Q, "FROM CUSTOMER");
6091   Execute(Q,C);
6092   loop
6093      begin
6094         Fetch(Q);
6095      exception
6096         when No_Tuple =>
6097            exit;
6098      end;
6099      Cust_Name_Ind := Is_Null(Q,2);
6100      if not Cust_Name_Ind then
6101         -- Get Cust_Name since it is not null
6102      end if;
6103   end loop;
6104   Clear(Q);
6105\end{Example}
6106
6107\section{Value Fetching Functions\label{Value Fetching Functions}}
6108
6109Once a fetch\index{fetch} operation has been performed, the application needs to
6110retrieve the values for each column from the row. The function primitive
6111Value\index{Value} assumes that the column's value is \emph{not} going
6112to be NULL\index{NULL}. If it should be null however, the exception
6113Null\_Value\index{Null\_Value} is raised. A better set of primitives should be used for
6114columns that may return NULL. See \Ref{Value and Indicator Fetch Procedures}.
6115
6116The following subsections will cover the function primitives for extracting
6117the values for builtin types\index{builtin types}.
6118
6119
6120\subsection{Function Value\label{Standard Value Functions}}
6121
6122The value for a Row\_ID\_Type\index{OID}, string, bit string or
6123Unbounded\_String\index{Unbounded\_String} can be extracted for a column
6124using the Value function primitive. This function should only used
6125for columns that cannot return a NULL \index{NULL}value.%
6126\footnote{If the value is NULL, the exception Null\_Value will be raised.%
6127} The calling requirements for these primitives are the same with
6128different return types:
6129
6130\begin{Code}
6131function Value(
6132   Query : in Query_Type;
6133   CX :    in Column_Index_Type
6134) return Row_ID_Type;
6135\end{Code}
6136
6137\begin{Code}
6138function Value(
6139   Query : in Query_Type;
6140   CX :    in Column_Index_Type
6141) return String;
6142\end{Code}
6143
6144\begin{Code}
6145function Value(
6146   Query : in Query_Type;
6147   CX :    in Column_Index_Type
6148) return Ada.Strings.Unbounded.Unbounded_String;
6149\end{Code}
6150
6151\begin{Code}
6152function Value(
6153   Query : in Query_Type;
6154   CX :    in Column_Index_Type
6155) return APQ_Bitstring;
6156\end{Code}
6157
6158Table \ref{t:valx} lists the possible exceptions for these functions.
6159
6160\begin{table}
6161   \begin{center}
6162      \begin{tabular}{ll}
6163         Exception Name    &  Reason\\
6164         \hline
6165         No\_Result        &  There was no execute performed\\
6166         No\_Column        &  No column at index\\
6167         Null\_Value       &  The column's value is NULL\\
6168      \end{tabular}
6169   \end{center}
6170   \caption{Value Exceptions}\label{t:valx}
6171\end{table}
6172
6173The following example shows how all the column values are fetched:
6174
6175\begin{Example}
6176   declare
6177     C : Connection_Type;
6178     Q : Query_Type;
6179   begin
6180     Prepare(Q,"SELECT CUST_NO,CUST_NAME");
6181     Append(Q, "FROM CUSTOMER");
6182     Execute(Q,C);
6183     loop
6184        begin
6185           Fetch(Q);
6186        exception
6187           when No_Tuple =>
6188              exit;
6189        end;
6190        for CX in 1..Column_Index_Type(Columns(Q)) loop
6191           declare
6192               Col_Value : String := Value(Q,CX);
6193           begin
6194               Put("Column");
6195               Put(Column_Index_Type'Image(CX));
6196               Put(" = '");
6197               Put(Value(Q,CX));
6198               Put_Line("'");
6199           end;
6200        end loop;
6201     end loop;
6202     Clear(Q);
6203\end{Example}
6204
6205\subsection{Null\_Oid Function\label{Null_Oid Function}}
6206
6207Since different database engines have different approaches to row
6208ID values%
6209\footnote{MySQL for example, does not return row ID values.%
6210}, it is necessary to know how to represent a null row ID\index{row ID} value in
6211the current database context. Use the Null\_Oid\index{Null\_Oid} primitive
6212to obtain that value:
6213
6214\begin{Code}
6215function Null_Oid(
6216   Query : Query_Type
6217) return Row_ID_Type;
6218\end{Code}
6219
6220\begin{floatingtable}{
6221   \begin{tabular}{lc}
6222      Database       &  Value\\
6223      \hline
6224      PostgreSQL     &  0\\
6225      MySQL          &  0\\
6226      Sybase         &  0\\
6227   \end{tabular}}
6228   \caption{Null Oid Values by Product}\label{t:nulloid}
6229\end{floatingtable}
6230
6231Using the Null\_Oid function in generic database code allows helps
6232to eliminate the need to identify the database engine being used.
6233Table~\ref{t:nulloid} lists the numeric values that represent a
6234null OID (row ID) value. The application programmer should rely
6235of the function Null\_Oid to avoid hardcoding a numeric value
6236that might change in the future.
6237
6238\subsection{Generic Value Functions}
6239
6240The Value functions documented in \Ref{Standard Value Functions}
6241were suitable for the specific data types that they supported. However,
6242Ada programmers often derive distinct new types to prevent accidental
6243mixing of values in expressions. To accomodate all of these custom
6244data types, you need to use generic functions for the purpose:
6245
6246\begin{Code}
6247generic
6248   type Val_Type is new Boolean;
6249function Boolean_Value(
6250   Query : in Query_Type'Class;
6251   CX :    in Column_Index_Type
6252) return Val_Type;
6253\end{Code}
6254
6255\begin{Code}
6256generic
6257   type Val_Type is range <>;
6258function Integer_Value(
6259   Query : in Query_Type'Class;
6260   CX :    in Column_Index_Type
6261) return Val_Type;
6262\end{Code}
6263
6264\begin{Code}
6265generic
6266   type Val_Type is mod <>;
6267function Modular_Value(
6268   Query : in Query_Type'Class;
6269   CX :    in Column_Index_Type
6270) return Val_Type;
6271\end{Code}
6272
6273\begin{Code}
6274generic
6275   type Val_Type is digits <>;
6276function Float_Value(
6277   Query : in Query_Type'Class;
6278   CX :    in Column_Index_Type
6279) return Val_Type;
6280\end{Code}
6281
6282\begin{Code}
6283generic
6284   type Val_Type is delta <>;
6285function Fixed_Value(
6286   Query : in Query_Type'Class;
6287   CX :    in Column_Index_Type
6288) return Val_Type;
6289\end{Code}
6290
6291\begin{Code}
6292generic
6293   type Val_Type is delta <> digits <>;
6294function Decimal_Value(
6295   Query : in Query_Type'Class;
6296   CX :    in Column_Index_Type
6297) return Val_Type;
6298\end{Code}
6299
6300\begin{Code}
6301generic
6302   type Val_Type is new APQ_Date;
6303function Date_Value(
6304   Query : in Query_Type'Class;
6305   CX :    in Column_Index_Type
6306) return Val_Type;
6307\end{Code}
6308
6309\begin{Code}
6310generic
6311   type Val_Type is new APQ_Time;
6312function Time_Value(
6313   Query : in Query_Type'Class;
6314   CX :    in Column_Index_Type
6315) return Val_Type;
6316\end{Code}
6317
6318\begin{Code}
6319generic
6320   type Val_Type is new Ada.Calendar.Time;
6321function Timestamp_Value(
6322   Query : in Query_Type'Class;
6323   CX :    in Column_Index_Type
6324) return Val_Type;
6325\end{Code}
6326
6327Table \ref{t:gvalx} lists the exceptions possible for these
6328instantiated routines.
6329
6330\begin{table}
6331   \begin{center}
6332      \begin{tabular}{ll}
6333         Exception Name    &  Reason\\
6334         \hline
6335         No\_Result        &  There was no execute performed\\
6336         No\_Column        &  No column at index\\
6337         Null\_Value       &  The column's value is NULL\\
6338      \end{tabular}
6339   \end{center}
6340   \caption{Generic Value Exceptions}\label{t:gvalx}
6341\end{table}
6342
6343The following example illustrates the use of the Integer\_Value and
6344Date\_Value generic functions:
6345
6346\begin{Example}
6347declare
6348   type Cust_No_Type is new APQ_Integer;
6349   type Cust_Birthday_Type is new APQ_Date;
6350   function Value is new Integer_Value(Cust_No_Type);
6351   function Value is new Date_Value(Cust_Birthday_Type);
6352   C : Connection_Type;
6353   Q : Query_Type;
6354begin
6355   Prepare(Q,"SELECT CUST_NO,CUST_NAME,BIRTH_DATE");
6356   Append(Q, "FROM CUSTOMER");
6357   Execute(Q,C);
6358   loop
6359      begin
6360         Fetch(Q);
6361      exception
6362         when No_Tuple =>
6363            exit;
6364      end;
6365      declare
6366         Cust_Name : String := Value(Q,2);
6367         Cust_No :   Cust_No_Type;
6368         Birthday :  Cust_Birthday_Type;
6369      begin
6370         Cust_No  := Value(Q,1);  -- CUST_NO is col 1
6371         Birthday := Value(Q,3);  -- BIRTH_DATE is col 3
6372         ...
6373      end;
6374   end loop;
6375   Clear(Q);
6376\end{Example}
6377
6378In the example shown, \emph{Cust\_Name} is returned by the builtin
6379function Value for String types. The variables \emph{Cust\_No} and
6380\emph{Birthday} are assigned through the generic instantiations of
6381the functions Integer\_Value\index{Integer\_Value} and Date\_Value\index{Date\_Value} respectively.
6382
6383
6384\subsection{Fixed Length String Value Procedure}
6385
6386Sometimes in an application it is desireable to work with fixed\index{fixed length} length
6387string\index{string} values. The following Value\index{Value} procedure does just this:
6388
6389\begin{Code}
6390procedure Value(
6391   Query: in     Query_Type;
6392   CX :   in     Column_Index_Type;
6393   V :       out String
6394);
6395\end{Code}
6396
6397This function raises the exceptions listed in Table~\ref{t:fxflsx}.
6398
6399\begin{table}
6400   \begin{center}
6401      \begin{tabular}{ll}
6402         Exception Name    &  Reason\\
6403         \hline
6404         No\_Result        &  There was no execute performed\\
6405         No\_Column        &  No column at index\\
6406         Null\_Value       &  The column's value is null\\
6407      \end{tabular}
6408   \end{center}
6409   \caption{Fixed Length String Value Exceptions}\label{t:fxflsx}
6410\end{table}
6411
6412The following example extracts the CUST\_NAME column result into variable
6413\emph{Cust\_Name} as a 30 byte string value:
6414
6415\begin{Example}
6416declare
6417   C :         Connection_Type;
6418   Q :         Query_Type;
6419   Cust_Name : String(1..30);
6420begin
6421   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
6422   Append(Q,"FROM CUSTOMER");
6423   Execute(Q,C);
6424   loop
6425      begin
6426         Fetch(Q);
6427      exception
6428         when No_Tuple =>
6429            exit;
6430      end;
6431      ...
6432      Value(Q,2,Cust_Name);
6433      ...
6434   end loop;
6435   Clear(Q);
6436\end{Example}
6437
6438
6439
6440\subsection{Bounded\_Value Function}
6441
6442Bounded\index{bounded strings} strings require a separate instantiation of
6443Ada\-.Strings\-.Bounded\index{Ada.Strings.Bounded} for each string length.
6444For this reason, a function supporting bounded strings must be provided
6445in generic form. The Bounded\_Value\index{Bounded\_Value} generic function accepts
6446the following generic arguments:
6447
6448\begin{Code}
6449generic
6450   with package P is new
6451      Ada.Strings.Bounded.Generic_Bounded_Length(<>);
6452function Bounded_Value(
6453   Query : in Query_Type'Class;
6454   CX :    in Column_Index_Type
6455) return P.Bounded_String;
6456\end{Code}
6457
6458\begin{table}
6459   \begin{center}
6460      \begin{tabular}{ll}
6461         Exception Name    &  Reason\\
6462         \hline
6463         No\_Result        &  There was no execute performed\\
6464         No\_Column        &  No column at index\\
6465         Null\_Value       &  The column's value is null\\
6466      \end{tabular}
6467   \end{center}
6468   \caption{Bounded\_Value Exceptions}\label{t:bvx}
6469\end{table}
6470
6471Table \ref{t:bvx} lists the exceptions possible for Bounded\_Value.
6472The example below illustrates the use of Bounded\_Value:
6473
6474\begin{Example}
6475with Ada.Strings.Bounded;
6476declare
6477   package B30 is new
6478      Ada.Strings.Bounded.Generic_Bounded_Length(30);
6479   function Value is new Bounded_Value(B30);
6480   C :         Connection_Type;
6481   Q :         Query_Type;
6482   Cust_Name : B30;
6483begin
6484   Prepare(Q,"SELECT CUST_NO,CUST_NAME,BIRTH_DATE");
6485   Append(Q, "FROM CUSTOMER");
6486   Execute(Q,C);
6487   loop
6488      begin
6489         Fetch(Q);
6490      exception
6491         when No_Tuple =>
6492      end;
6493      ...
6494      Cust_Name := Value(Q,2);
6495      ...
6496      end loop;
6497   end loop;
6498   Clear(Q);
6499\end{Example}
6500
6501\section{Value and Indicator Fetch Procedures\label{Value and Indicator Fetch Procedures}}
6502
6503The Value\index{Value} functions\index{value functions} presented in
6504\Ref{Value Fetching Functions} were useful when the returned value was
6505always going to be present. However, their use becomes clumsy and less
6506efficient if exception handlers must be used to handle the
6507NULL\index{NULL} value case. This section documents Fetch procedures to
6508return both a value and a null indicator together. With this convenience
6509comes the added responsibility of checking the null
6510indicator\index{indicator} values, that are returned.
6511
6512
6513\subsection{Char and Unbounded Fetch}
6514
6515The Char\_Fetch and Unbounded\_Fetch generic procedures
6516fetch both a string value and an indicator value. In the Char\_Fetch
6517case, the returned value is blank filled to the full size of the receiving
6518String buffer. Each of these has the following instantiation parameters:
6519
6520\begin{Code}
6521generic
6522   type Ind_Type is new Boolean;
6523procedure Char_Fetch(
6524   Query :     in     Query_Type'Class;
6525   CX :        in     Column_Index_Type;
6526   V :            out String;
6527   Indicator :    out Ind_Type
6528);
6529\end{Code}
6530
6531\begin{Code}
6532generic
6533   type Ind_Type is new Boolean;
6534procedure Unbounded_Fetch(
6535   Query :     in     Query_Type'Class;
6536   CX :        in     Column_Index_Type;
6537   V :            out Ada.Strings.Unbounded.Unbounded_String;
6538   Indicator :    out Ind_Type
6539);
6540\end{Code}
6541
6542The Unbounded\_Fetch routine may raise any of the exceptions listed in Table~\ref{t:ufx}.
6543
6544\begin{table}
6545   \begin{center}
6546      \begin{tabular}{ll}
6547         Exception Name    &  Reason\\
6548         \hline
6549         No\_Result        &  There was no execute performed\\
6550         No\_Column        &  No column at index\\
6551      \end{tabular}
6552   \end{center}
6553   \caption{Unbounded\_Fetch Exceptions}\label{t:ufx}
6554\end{table}
6555
6556The following example illustrates two different column fetch applications:
6557
6558\begin{Example}
6559with Ada.Strings.Unbounded;
6560declare
6561   type Cust_Name_Ind_Type is new Boolean;
6562   type Cust_City_Ind_Type is new Boolean;
6563   subtype Cust_Name_Type is String(1..30);
6564   subtype Cust_City_Type is
6565       Ada.Strings.Unbounded.Unbounded_String;
6566
6567   procedure Value is new
6568       Char_Fetch(Cust_Name_Ind_Type);
6569   procedure Value is new
6570       Unbounded_Fetch(Cust_City_Ind_Type);
6571
6572   C :             Connection_Type;
6573   Q :             Query_Type;
6574   Cust_Name :     Cust_Name_Type;
6575   Cust_Name_Ind : Cust_Name_Ind_Type;
6576   Cust_City :     Cust_City_Type;
6577   Cust_City_Ind : Cust_City_Ind_Type;
6578begin
6579   Prepare(Q,"SELECT CUST_NO,CUST_NAME,CITY");
6580   Append(Q, "FROM CUSTOMER");
6581   Execute(Q,C);
6582   loop
6583      begin
6584         Fetch(Q);
6585      exception
6586         when No_Tuple =>
6587      end;
6588      ...
6589      Value(Q,2,Cust_Name,Cust_Name_Ind);
6590      Value(Q,3,Cust_City,Cust_City_Ind);
6591      ...
6592   end loop;
6593   Clear(Q);
6594\end{Example}
6595
6596\subsection{Varchar\_Fetch and Bitstring\_Fetch Procedures}
6597
6598To return a varying length string\index{varying length string} requires
6599the use of a function. However, to return two values, we must resort
6600to a procedure call for the purpose. In order to return both a varying
6601length string and a null indicator, an additional return value is
6602returned that indicates the length of the string. To accomodate strongly
6603typed indicators\index{indicators}, these two procedures are provided in generic form.
6604The instantiation parameters are:
6605
6606\begin{Code}
6607generic
6608   type Ind_Type is new Boolean;
6609procedure Varchar_Fetch(
6610   Query :     in     Query_Type'Class;
6611   CX :        in     Column_Index_Type;
6612   V :            out String;
6613   Last :         out Natural;
6614   Indicator :    out Ind_Type
6615);
6616\end{Code}
6617
6618\begin{Code}
6619generic
6620   type Ind_Type is new Boolean;
6621procedure Bitstring_Fetch(
6622   Query :     in     Query_Type'Class;
6623   CX :        in     Column_Index_Type;
6624   V :            out APQ_Bitstring;
6625   Last :         out Natural;
6626   Indicator :    out Ind_Type
6627);
6628\end{Code}
6629
6630\begin{table}
6631   \begin{center}
6632      \begin{tabular}{ll}
6633         Exception Name    &  Reason\\
6634         \hline
6635         No\_Result        &  There was no execute performed\\
6636         No\_Column        &  No column at index\\
6637      \end{tabular}
6638   \end{center}
6639   \caption{Bitstring\_Fetch Exceptions}\label{t:bfx}
6640\end{table}
6641
6642Table \ref{t:bfx} lists the exceptions for Bitstring\_Fetch.
6643The next example illustrates two different column fetch applications:
6644
6645\begin{Example}
6646declare
6647   type Cust_Name_Ind_Type is new Boolean;
6648   type Cust_City_Ind_Type is new Boolean;
6649
6650   procedure Value is new
6651      Varchar_Fetch(Cust_Name_Ind_Type);
6652   procedure Value is new
6653      Varchar_Fetch(Cust_City_Ind_Type);
6654
6655   C :              Connection_Type;
6656   Q :              Query_Type;
6657   Cust_Name :      String(1..30);
6658   Cust_Name_Last : Natural;
6659   Cust_Name_Ind :  Cust_Name_Ind_Type;
6660   Cust_City :      String(1..40);
6661   Cust_City_Last : Natural;
6662   Cust_City_Ind :  Cust_City_Ind_Type;
6663begin
6664   Prepare(Q,"SELECT CUST_NO,CUST_NAME,CITY");
6665   Append(Q, "FROM CUSTOMER");
6666   Execute(Q,C);
6667   loop
6668      begin
6669         Fetch(Q);
6670      exception
6671         when No_Tuple =>
6672            exit;
6673      end;
6674      ...
6675      Value(Q,2,Cust_Name,Cust_Name_Last,Cust_Name_Ind);
6676      Value(Q,3,Cust_City,Cust_City_Last,Cust_City_Ind);
6677      ...
6678   end loop;
6679   Clear(Q);
6680\end{Example}
6681
6682After the first Value call in the example, the customer name would
6683be represented by the expression:
6684
6685\begin{Code}
6686
6687   Cust_Name(1..Cust_Name_Last)
6688
6689\end{Code}
6690
6691provided that the value Cust\_Name\_Ind was false.
6692
6693
6694\subsection{Bounded\_Fetch Procedure}
6695
6696To fetch both a Bounded\_String value and its associated null\index{null indicator} indicator,
6697you instantiate and call the Bounded\_Fetch\index{Bounded\_Fetch}. The instantiation
6698parameters are as follows:
6699
6700\begin{Code}
6701generic
6702   type Ind is new Boolean;
6703   with package P is new
6704      Ada.Strings.Bounded.Generic_Bounded_Length(<>);
6705procedure Bounded_Fetch(
6706   Query :     in     Query_Type'Class;
6707   CX :        in     Column_Index_Type;
6708   V :            out P.Bounded_String;
6709   Indicator :    out Ind);
6710\end{Code}
6711
6712\begin{table}
6713   \begin{center}
6714      \begin{tabular}{ll}
6715         Exception Name    &  Reason\\
6716         \hline
6717         No\_Result        &  There was no execute performed\\
6718         No\_Column        &  No column at index\\
6719      \end{tabular}
6720   \end{center}
6721   \caption{Bounded\_Fetch Exceptions}\label{t:bfx2}
6722\end{table}
6723
6724The Bounded\_Fetch routine may raise any of the exceptions listed in Table~\ref{t:bfx2}.
6725The example below illustrates a fetch instantiation and call:
6726
6727\begin{Example}
6728with Ada.Strings.Bounded;
6729declare
6730   package B32 is new
6731      Ada.Strings.Bounded.Generic_Bounded_Length(32);
6732   type Cust_Name_Ind_Type is new Boolean;
6733
6734   procedure Value is new
6735      Bounded_Fetch(Cust_Name_Ind_Type,B32);
6736
6737   C :              Connection_Type;
6738   Q :              Query_Type;
6739   Cust_Name :      B32;
6740   Cust_Name_Ind :  Cust_Name_Ind_Type;
6741begin
6742   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
6743   Append(Q, "FROM CUSTOMER");
6744   Execute(Q,C);
6745   loop
6746      begin
6747         Fetch(Q);
6748      exception
6749         when No_Tuple =>
6750            exit;
6751      end;
6752      ...
6753      Value(Q,2,Cust_Name,Cust_Name_Ind);
6754      ...
6755   end loop;
6756   Clear(Q);
6757\end{Example}
6758
6759\subsection{Discrete Type Fetch Procedures}
6760
6761Several of the discrete\index{discrete types} types can be grouped and documented in this
6762section. The following table indicates the generic procedure names
6763and their associated class of data type for which they are designed:
6764
6765\begin{Code}
6766generic
6767   type Val_Type is new Boolean;
6768   type Ind_Type is new Boolean;
6769procedure Boolean_Fetch(
6770   Query :     in     Root_Query_Type'Class;
6771   CX :        in     Column_Index_Type;
6772   V :            out Val_Type;
6773   Indicator :    out Ind_Type
6774);
6775\end{Code}
6776
6777\begin{Code}
6778generic
6779   type Val_Type is range <>;
6780   type Ind_Type is new Boolean;
6781procedure Integer_Fetch(
6782   Query :     in     Root_Query_Type'Class;
6783   CX :        in     Column_Index_Type;
6784   V :            out Val_Type;
6785   Indicator :    out Ind_Type
6786);
6787\end{Code}
6788
6789\begin{Code}
6790generic
6791   type Val_Type is mod <>;
6792   type Ind_Type is new Boolean;
6793procedure Modular_Fetch(
6794   Query :     in     Root_Query_Type'Class;
6795   CX :        in     Column_Index_Type;
6796   V :            out Val_Type;
6797   Indicator :    out Ind_Type
6798);
6799\end{Code}
6800
6801\begin{Code}
6802generic
6803   type Val_Type is digits <>;
6804   type Ind_Type is new Boolean;
6805procedure Float_Fetch(
6806   Query :     in     Root_Query_Type'Class;
6807   CX :        in     Column_Index_Type;
6808   V :            out Val_Type;
6809   Indicator :    out Ind_Type
6810);
6811\end{Code}
6812
6813\begin{Code}
6814generic
6815   type Val_Type is delta <>;
6816   type Ind_Type is new Boolean;
6817procedure Fixed_Fetch(
6818   Query :     in     Root_Query_Type'Class;
6819   CX :        in     Column_Index_Type;
6820   V :            out Val_Type;
6821   Indicator :    out Ind_Type
6822);
6823\end{Code}
6824
6825\begin{Code}
6826generic
6827   type Val_Type is delta <> digits <>;
6828   type Ind_Type is new Boolean;
6829procedure Decimal_Fetch(
6830   Query :     in     Root_Query_Type'Class;
6831   CX :        in     Column_Index_Type;
6832   V :            out Val_Type;
6833   Indicator :    out Ind_Type
6834);
6835\end{Code}
6836
6837\begin{Code}
6838generic
6839   type Val_Type is new Ada.Calendar.Time;
6840   type Ind_Type is new Boolean;
6841procedure Date_Fetch(
6842   Query :     in     Root_Query_Type'Class;
6843   CX :        in     Column_Index_Type;
6844   V :            out Val_Type;
6845   Indicator :    out Ind_Type
6846);
6847\end{Code}
6848
6849\begin{Code}
6850generic
6851   type Val_Type is new Ada.Calendar.Day_Duration;
6852   type Ind_Type is new Boolean;
6853procedure Time_Fetch(
6854   Query :     in     Root_Query_Type'Class;
6855   CX :        in     Column_Index_Type;
6856   V :            out Val_Type;
6857   Indicator :    out Ind_Type
6858);
6859\end{Code}
6860
6861\begin{Code}
6862generic
6863   type Val_Type is new Ada.Calendar.Time;
6864   type Ind_Type is new Boolean;
6865procedure Timestamp_Fetch(
6866   Query :     in     Root_Query_Type'Class;
6867   CX :        in     Column_Index_Type;
6868   V :            out Val_Type;
6869   Indicator :    out Ind_Type
6870);
6871\end{Code}
6872
6873\begin{table}
6874   \begin{center}
6875      \begin{tabular}{ll}
6876         Exception Name    &  Reason\\
6877         \hline
6878         No\_Result        &  There was no execute performed\\
6879         No\_Column        &  No column at index\\
6880      \end{tabular}
6881   \end{center}
6882   \caption{Timestamp\_Fetch Exceptions}\label{t:tfx2}
6883\end{table}
6884
6885The Timestamp\_Fetch exceptions are listed in Table~\ref{t:tfx2}.
6886The following example illustrates how to instantiate and call a
6887Integer\_Fetch procedure.
6888
6889\begin{Example}
6890declare
6891   type Cust_No_Type is new Integer;
6892   type Cust_No_Ind_Type is new Boolean;
6893   procedure Value is new Integer_Fetch
6894      (Cust_No_Type,Cust_No_Ind_Type);
6895   C :              Connection_Type;
6896   Q :              Query_Type;
6897   Cust_No :        Cust_No_Type;
6898   Cust_No_Ind :    Cust_No_Ind_Type;
6899begin
6900   Prepare(Q,"SELECT CUST_NO,CUST_NAME");
6901   Append(Q, "FROM CUSTOMER");
6902   Execute(Q,C);
6903   loop
6904      begin
6905         Fetch(Q);
6906      exception
6907         when No_Tuple =>
6908            exit;
6909      end;
6910      ...
6911      Value(Q,1,Cust_No,Cust_No_Ind);
6912      ...
6913   end loop;
6914   Clear(Q);
6915\end{Example}
6916
6917
6918\section{Information Functions}
6919
6920You have already seen two information functions Result\index{Result} and Error\_Message\index{Error\_Message}
6921in \Ref{Error Message Reporting} and \Ref{Error Status Reporting}.
6922Another useful Query\_Type primitive is the To\_String\index{To\_String} function. It
6923is described in the next subsection.
6924
6925
6926\subsection{The To\_String Function}
6927
6928The To\_String\index{To\_String} primitive allows the caller to retrieve the collected
6929SQL text from the Query\_Type object. The function's calling signature
6930is as follows:
6931
6932\begin{Code}
6933function To_String(
6934   Query : Query_Type
6935) return String;
6936\end{Code}
6937
6938The To\_String function returns the full text of the SQL query, including
6939newline characters.%
6940\footnote{One is included at the end of the string if it is missing.%
6941} If there has not been any SQL text\index{SQL text} collected, the
6942function returns an empty string.%
6943\footnote{In this case, no newline is provided.%
6944}
6945
6946The following example shows how a programmer can dump out the SQL\index{SQL}
6947query, but only when it fails:
6948
6949\begin{Example}
6950declare
6951   C :   Connection_Type;
6952   Q :   Query_Type;
6953begin
6954   Prepare(Q,"SELECT CUST_NO,CUST_NAME,BIRTH_DATE");
6955   Append(Q, "FROM CUSTOMER");
6956   begin
6957      Execute(Q,C);
6958   exception
6959      when SQL_Error =>
6960         Put_Line("The failed SQL Query was:");
6961         Put_Line(To_String(Q));
6962         raise;
6963      when others =>
6964         raise;
6965   end;
6966\end{Example}
6967
6968\subsection{Cursor Names\label{Cursor_Name}}
6969
6970While PostgreSQL\index{PostgreSQL} and MySQL\index{MySQL} do not yet support cursors\index{cursors} in their client
6971libraries \footnote{PostgreSQL supports server cursors, but cursor support is absent in libpq.},
6972other database products like Sybase\index{Sybase} do. Cursors allow the programmer
6973to work with the concept of a ``current row''\index{current row}. For those databases
6974that do support the use of cursors, you can retrieve the cursor name\index{cursor name}
6975with the use of the Cursor\_Name\index{Cursor\_Name} function primitive:
6976
6977\begin{Code}
6978function Cursor_Name(
6979   Query : Query_Type
6980) return String;
6981\end{Code}
6982
6983\begin{table}
6984   \begin{center}
6985      \begin{tabular}{ll}
6986         Exception Name    &  Reason\\
6987         \hline
6988         No\_Result        &  No cursor results pending\\
6989      \end{tabular}
6990   \end{center}
6991   \caption{Cursor\_Name Exceptions}\label{t:cnamx}
6992\end{table}
6993
6994The Cursor\_Name exceptions are documented in Table~\ref{t:cnamx}.
6995To use cursors within APQ, you must set the fetch mode of the Query\_Type
6996to one of the following:
6997
6998\begin{itemize}
6999   \item Cursor\_For\_Update\index{Cursor\_For\_Update}
7000   \item Cursor\_For\_Read\_Only\index{Cursor\_For\_Read\_Only}
7001\end{itemize}
7002
7003Once you have set the fetch mode to one of the cursor fetch modes
7004listed above, and you have executed the query to produce cursor results,
7005\emph{then} the call to Cursor\_Name is valid. For a description of
7006fetch query modes in \Ref{Fetch Query Modes}.
7007
7008
7009\chapter{Blob Support}
7010
7011The MySQL\index{MySQL} database provides a very different type of blob support\index{blob support}.
7012For the moment, blobs are unsupported in MySQL. Blob support is also
7013absent for Sybase\index{Sybase}. These are two areas ripe for further work in APQ.
7014
7015Blobs are supported for PostgreSQL\index{PostgreSQL} in APQ however. This provides the
7016application programmer with the ability to store large amounts of
7017information in a ``blob''\index{blob}. In many ways this resembles
7018a file\index{file}, with the exception that the contents are stored
7019in the database and is accessed by number (OID\index{OID}). The APQ
7020binding provides full PostgreSQL blob support for the Ada programmer.
7021In addition, the Ada\index{Ada} stream\index{stream} concept is employed to
7022provide reliable and Ada2005\index{Ada2005} convenient access to the blob.
7023
7024
7025\subsubsection{Endian Note:}
7026
7027The application programmer must keep in mind that any binary data
7028written to a blob, by means of the Ada stream, is not endian\index{endian} neutral.
7029This becomes a concern when a client application accesses or writes
7030to blobs stored on a database over the network, on another host. If
7031the endianess of the server and client differ, endian problems will
7032emerge.
7033
7034
7035\section{Introduction}
7036
7037Blob functions are managed primarily through the Blob\_Type\index{Blob\_Type} access
7038type.%
7039\footnote{The object itself is of type Blob\_Object. Blob\_Type is an access
7040to Blob\_Object type.%
7041} Stream I/O to and from the blob is performed using an Ada streams
7042access value.%
7043\footnote{Internally named Root\_Stream\_Access type, which is the type ''access
7044all Ada.Streams.Root\_Stream\_Type'Class''.%
7045}
7046
7047The blob support can generally be grouped into the following categories:
7048
7049\begin{itemize}
7050   \item Create, Open and Close operations
7051   \item Index setting and querying operations
7052   \item Information operations for Size and OID
7053   \item Stream accessor\index{stream accessor} function
7054   \item Blob destruction\index{blob destruction}
7055   \item File and Blob operations
7056\end{itemize}
7057
7058The following sections will document the blob support using these
7059groupings.
7060
7061
7062\section{Blob Memory Leak Prevention}
7063
7064\index{memory leak prevention}It is extremely important that the
7065programmer realize that the Blob\_Type data type is an access type.%
7066\footnote{This design choice was necessary to accomodate Ada stream oriented
7067I/O.%
7068} Additionally this access\index{access value} value is a pointer\index{pointer} to a dynamically\index{dynamic} allocated
7069tagged\index{tagged} record (type Blob\_Object). For this reason, the programmer
7070must take great care to ``close'' the Blob\_Type before discarding
7071the Blob\_Type value, when it goes out of scope. Failure to close
7072a Blob\_Type value, will result in a memory leak\index{memory leak} and cause subsequent
7073database performance issues. Use the Blob\_Type value as if it were
7074an open file that needs closing.
7075
7076The following example represents a ``Blob\_Type leak'':
7077
7078\begin{Example}
7079declare
7080   C :   aliased Connection_Type;
7081   B :   Blob_Type;
7082begin
7083   ...
7084   B := Blob_Create(C'Access);
7085   ...
7086end;
7087\end{Example}
7088
7089The example above is bad because a ``blob leak''\index{blob leak}
7090occurs when the ``end'' statement is reached.%
7091\footnote{It should also be noted that after creating a blob in the database,
7092the application must save the OID value for the blob somewhere. Otherwise,
7093you will have a blob in the database that will never be accessed!%
7094} The variable \emph{C} finalizes itself OK because it is a controled
7095object.%
7096\footnote{Both Connection\_Type and Query\_Type objects are controlled records
7097with finalization.%
7098} However, B is an access type, pointing to a Blob\_Object record.
7099When variable B falls out of scope, only the pointer value
7100in B is lost. The object it pointed to has not been released!
7101
7102The following example code is better:
7103
7104\begin{Example}
7105declare
7106   C :   aliased Connection_Type;
7107   B :   Blob_Type;
7108begin
7109   ...
7110   B := Blob_Create(C'Access);
7111   ...
7112   Blob_Close(B);
7113end;
7114\end{Example}
7115
7116The call to Blob\_Close\index{Blob\_Close} insures that the memory associated with the
7117opened blob is released, before the value \emph{B} falls out of scope.%
7118\footnote{Note that Close does not destroy the blob in the database.%
7119} However, if there is a chance that an exception may be raised, you
7120may still be vulnerable to leaks. The following example covers all
7121of the bases:
7122
7123\begin{Example}
7124declare
7125   C :   aliased Connection_Type;
7126   B :   Blob_Type;
7127begin
7128   ...
7129   B := Blob_Create(C'Access);
7130   ...
7131   Blob_Close(B);
7132exception
7133   when others =>
7134      if B /= null then
7135         Blob_Close(B);
7136      end if;
7137      ...recovery steps...
7138end;
7139\end{Example}
7140
7141While the recovery steps have been left to the reader's imagination
7142in the example above, the exception is caught and the value for variable
7143\emph{B} is tested. Only if \emph{B} is not null, should the Blob\_Close
7144procedure call made. Only you can prevent blob memory leaks!
7145
7146
7147\section{Create, Open and Close of Blobs}
7148
7149The most basic operations possible in an Ada program using blobs are:
7150
7151\begin{itemize}
7152   \item Creating a new blob in the database (Blob\_Create)
7153   \item Opening an existing blob in the database (Blob\_Open)
7154   \item Flushing buffered writes to the database (Blob\_Flush)
7155   \item Closing a blob (Blob\_Close)
7156\end{itemize}
7157
7158The following subsections will explain how to perform these operations
7159in detail.
7160
7161
7162\subsection{Blob\_Create Procedure}
7163
7164Before the application can open an existing blob\index{opening a blob},
7165there must be some way to create a blob\index{creating a blob}. The
7166Blob\_Create\index{Blob\_Create} function does just this with the following calling signature:%
7167\marginpar{Note: Blob operations must be performed within the context of a transaction.%
7168}
7169
7170\begin{Code}
7171function Blob_Create(
7172   DB :       access Connection_Type;
7173   Buf_Size : in     Natural := Buf_Size_Default
7174) return Blob_Type;
7175\end{Code}
7176
7177The returned value is a Blob\_Type that is capable of being used to
7178read and/or write a blob. The blob is positioned at index position
71791 (the beginning). See \Ref{Blob OID Function} for information
7180about how to determine the created blob's OID\index{OID}.
7181
7182Starting with APQ version 1.2, all blob I/O is buffered if the Buf\_Size
7183argument is supplied with a value greater than zero, or is not supplied
7184such that the default value applies. Table~\ref{t:bcbsgx} summarizes
7185the Buf\_Size\index{Buf\_Size} argument behaviour. The exceptions
7186are listed in Table~\ref{t:blbcx}.
7187
7188\begin{table}
7189   \begin{center}
7190      \begin{tabular}{lll}
7191         Buf\_Size Value                        &  Description          &  Performance\\
7192         \hline
7193         0                                      &  Unbuffered blob I/O  &  Very poor\\
7194         0 < Buf\_Size < 1024                   &  Buffered             &  Poor\\
7195         1024 <= Buf\_Size < Buf\_Size\_Default & Buffered blob I/O     &  Better\\
7196         Buf\_Size\_Default                     &  Buffered: 5120 bytes &  Very good\\
7197      \end{tabular}
7198   \end{center}
7199   \caption{Blob\_Create Buf\_Size Guidelines}\label{t:bcbsgx}
7200\end{table}
7201
7202\begin{table}
7203   \begin{center}
7204      \begin{tabular}{ll}
7205         Exception Name    &  Reason\\
7206         \hline
7207         Blob\_Error       &  There was no blob created\\
7208      \end{tabular}
7209   \end{center}
7210   \caption{Blob\_Create Exceptions}\label{t:blbcx}
7211\end{table}
7212
7213Possible reasons for a Blob\_Error\index{Blob\_Error} exception to be raised would include:
7214
7215\begin{itemize}
7216   \item bad database connection object%
7217      \footnote{Or the database connection object went out of scope.}
7218   \item a database error occurred (no more blob space?)
7219\end{itemize}
7220
7221The following example shows how a new blob can be created:
7222
7223\begin{Example}
7224declare
7225   C :   aliased Connection_Type;
7226   B :   Blob_Type;
7227begin
7228   ...
7229   B := Blob_Create(C'Access);
7230   ...
7231   Blob_Close(B);
7232end;
7233\end{Example}
7234
7235\subsubsection{Note:}
7236
7237The argument DB in the call to the Blob\_Create\index{Blob\_Create}, is an access
7238to Connection\_Type argument. You must guarantee that the Connection\_Type
7239object does not finalize before the created blob has been closed.
7240
7241
7242\subsection{Blob\_Open Function\label{Blob_Open Function}}
7243
7244To open an existing blob\index{existing blob}, you must know the OID\index{OID} of the blob in the
7245database. This is normally a value that is stored in a database column
7246somewhere. See \Ref{Blob OID Function} for information on
7247how to determine the OID of a created blob.%
7248\marginpar{Note: Blob operations must be performed within the context of a transaction.%
7249}
7250
7251Blobs can be opened for various types of access:
7252
7253\begin{description}
7254   \item [Read\index{Read}] for readonly access to the blob contents
7255   \item [Write\index{Write}] for writing to the blob
7256   \item [Read\_Write\index{Write}] for both reading and writing of the blob
7257\end{description}
7258
7259The Blob\_Open\index{Blob\_Open} function has the following specification:
7260
7261\begin{Code}
7262type Mode_Type is (
7263   Write,
7264   Read,
7265   Read_Write
7266);
7267
7268function Blob_Open(
7269   DB :       access Connection_Type;
7270   Oid :      in     Row_ID_Type;
7271   Mode :     in     Mode_Type;
7272   Buf_Size : in     Natural := Buf_Size_Default
7273) return Blob_Type;
7274\end{Code}
7275
7276The returned value is a Blob\_Type that is accessable according to
7277the Mode selected. The blob is positioned\index{blob position} at index value 1
7278(the beginning).
7279
7280Starting with APQ version 1.2, all blob I/O is buffered\index{buffered blob I/O} if the Buf\_Size
7281argument is supplied with a value greater than zero, or is not supplied
7282such that the default value applies. Refer to Table~\ref{t:bcbsgx} for guidance on
7283the value to use for Buf\_Size. The exceptions are documented
7284in Table~\ref{t:bopnx}.
7285
7286\begin{table}
7287   \begin{center}
7288      \begin{tabular}{ll}
7289         Exception Name    &  Reason\\
7290         \hline
7291         Blob\_Error       &  There was no blob opened\\
7292      \end{tabular}
7293   \end{center}
7294   \caption{Blob\_Open Exceptions}\label{t:bopnx}
7295\end{table}
7296
7297Possible reasons for a Blob\_Error exception to be raised would include:
7298
7299\begin{itemize}
7300   \item bad database connection object
7301   \item the Oid value supplied is not known by the database
7302   \item a database error occurred
7303\end{itemize}
7304
7305The following example shows how blob 73763 can be opened for reading:
7306
7307\label{Example-code-with-OID-73763}
7308\begin{Example}
7309declare
7310   C :   aliased Connection_Type;
7311   B :   Blob_Type;
7312   OID : Row_ID_Type := 73763;
7313begin
7314   ...
7315   B := Blob_Open(C'Access,OID,Read);
7316   ...
7317   Blob_Close(B);
7318exception
7319   when others =>
7320      if B /= null then
7321         Blob_Close(B);
7322      end if;
7323      raise;
7324end;
7325\end{Example}
7326
7327\subsubsection{Note:}
7328
7329The argument DB in the call to the Blob\_Open, is an access
7330to Connection\_Type argument. You must guarantee that the Connection\_Type
7331object does not finalize\index{finalize} before the opened blob has been closed.
7332
7333
7334\subsubsection{Generic\_Blob\_Open Function}
7335
7336To allow the application programmer to use strong types in place of
7337the supplied Row\_ID\_Type\index{Row\_ID\_Type} type, a generic procedure for opening blobs
7338is also provided. The instantiated function behaves exactly as described
7339for Blob\_Open\index{Open\_Blob} on page \pageref{Blob_Open Function}. The instantiation
7340arguments for Generic\_Blob\_Open\index{Generic\_Blob\_Open} are:
7341
7342\begin{Code}
7343type Mode_Type is (
7344   Write,
7345   Read,
7346   Read_Write
7347);
7348
7349generic
7350   type Oid_Type is new Row_ID_Type;
7351function Generic_Blob_Open(
7352   DB :       access Connection_Type;
7353   Oid :      in     Oid_Type;
7354   Mode :     in     Mode_Type;
7355   Buf_Size : in     Natural := Buf_Size_Default
7356) return Blob_Type;
7357\end{Code}
7358
7359The following example shows how to instantiate the function:
7360
7361\begin{Example}
7362declare
7363type My_Oid_Type is new Row_ID_Type;
7364function Blob_Open is new
7365   Generic_Blob_Open(My_Oid_Type);
7366\end{Example}
7367
7368\subsection{Blob\_Flush Procedure}
7369
7370\index{Blob\_Flush}When you are using buffered\index{buffered blob I/O} blob I/O%
7371\footnote{Buffered blob I/O is the default for performance reasons.%
7372} and your application has performed one or more writes to the blob,
7373you may need to be certain that all of the buffered data is physically
7374written out to the database. For example, you may have a timing\index{timing} opportunity
7375to perform this expensive operation while the user is waiting for
7376something else to occur. Buffer flushes\index{flush} are automatically performed
7377when the blob is closed or due to changes made by the Blob\_Set\_Index\index{Blob\_Set\_Index}
7378operation. To give the application programmer control over the timing
7379of the physical write to the database, the Blob\_Flush\index{Blob\_Flush} procedure can
7380be used.%
7381\marginpar{Blob\_Flush calls are ignored when unbuffered blob I/O is being used.
7382This makes it easy for the application to choose buffered or unbuffered
7383operation without source code changes.}
7384
7385The Blob\_Flush procedure has the specification below. Table~\ref{tblbflx} lists the exceptions.
7386
7387\begin{Code}
7388procedure Blob_Flush(Blob : Blob_Type);
7389\end{Code}
7390
7391\begin{table}
7392   \begin{center}
7393      \begin{tabular}{ll}
7394         Exception Name       &  Reason\\
7395         \hline
7396         Blob\_Error          &  The blob is not open\\
7397      \end{tabular}
7398   \end{center}
7399   \caption{Blob\_Flush Exceptions}\label{t:blbflx}
7400\end{table}
7401
7402
7403\subsection{Blob\_Close Procedure}
7404
7405When the programmer no longer requires access to a open/created blob,
7406the procedure Blob\_Close\index{Blob\_Close} should be called. Since an open blob depends
7407upon a hidden access value that points back to the Connection\_Type
7408object, the programmer should call Blob\_Close as soon as is practical.
7409This reduces the possibility of error that will occur if the Connection\_Type
7410object is finalized too soon.
7411
7412The Blob\_Close procedure has the following specification. Exceptions are
7413listed in Table~\ref{t:bclsx}.
7414
7415\begin{Code}
7416procedure Blob_Close(Blob : in out Blob_Type);
7417\end{Code}
7418
7419\begin{table}
7420   \begin{center}
7421      \begin{tabular}{ll}
7422         Exception Name    &  Reason\\
7423         \hline
7424         Blob\_Error       &  The blob is not open\\
7425      \end{tabular}
7426   \end{center}
7427   \caption{Blob\_Close Exceptions}\label{t:bclsx}
7428\end{table}
7429
7430Normally the Blob\_Error\index{Blob\_Error} exception will indicate an attempt to close
7431a blob that is not open. However, it is possible that the database
7432engine may experience a problem that will raise the same exception.
7433
7434The procedure Blob\_Close will also null out the the Blob\_Type value
7435that was passed in. This is done to eliminate any accidental access
7436to a Blob\_Object that no longer exists.
7437
7438
7439\section{Index Setting Operations}
7440
7441Like a file, a blob's ``position''\index{position of a blob} can be changed and queried.
7442The index\index{index} operations require the use of two types defined for the
7443purpose. They are:
7444
7445\begin{Code}
7446
7447   type Blob_Count is new
7448      Ada.Streams.Stream_Element_Offset
7449      range 0..Ada.Streams.Stream_Element_Offset'Last;
7450
7451\end{Code}
7452
7453\begin{Code}
7454
7455   subtype Blob_Offset is
7456      Blob_Count range 1..Blob_Count'Last;
7457
7458\end{Code}
7459
7460The type Blob\_Count\index{Blob\_Count} is used where there is a count involved
7461(which may require the value zero). The type Blob\_Offset\index{Blob\_Offset} is
7462used whenever a blob offset is used, since it starts at the value
74631.
7464
7465The next subsections describe facilities for performing blob indexing
7466operations.
7467
7468
7469\subsection{Blob\_Set\_Index Procedure}
7470
7471The Blob\_Set\_Index\index{Blob\_Set\_Index} procedure is used when the caller needs to seek
7472to a new position within the opened blob. See \Ref{Blob Size Function}
7473if you need to know the size of the blob.
7474
7475The calling requirements for Blob\_Set\_Index are summarized below
7476(exceptions in Table~\ref{t:blbsxx}).
7477
7478\begin{Code}
7479procedure Blob_Set_Index (
7480   Blob : in Blob_Type;
7481   To :   in Blob_Offset
7482);
7483\end{Code}
7484
7485\begin{table}
7486   \begin{center}
7487      \begin{tabular}{ll}
7488         Exception Name    &  Reason\\
7489         \hline
7490         Blob\_Error       &  Not open or seek failed\\
7491      \end{tabular}
7492   \end{center}
7493   \caption{Blob\_Set\_Index Exceptions}\label{t:blbsxx}
7494\end{table}
7495
7496The following example shows how to seek to the end of the blob:
7497
7498\begin{Example}
7499declare
7500   C :        aliased Connection_Type;
7501   B :        Blob_Type;
7502   B_Size :   Blob_Count;
7503   End_Blob : Blob_Index;
7504begin
7505   ...
7506   B_Size := Blob_Size(B);
7507   if B_Size > 0 then
7508      End_Blob := B_Size;
7509      Blob_Set_Index(B,End_Blob);
7510   ...
7511\end{Example}
7512
7513\section{Blob\_Index Function}
7514
7515Applications sometimes need to query where they are positioned in
7516the blob. The Blob\_Index\index{Blob\_Index} function returns the current Blob\_Offset\index{Blob\_Offset}
7517position\index{position} information. The specification is shown below,
7518while the exceptions are listed in Table~\ref{t:blbxx}.
7519
7520\begin{Code}
7521function Blob_Index(
7522   Blob : in Blob_Type
7523) return Blob_Offset;
7524\end{Code}
7525
7526\begin{table}
7527   \begin{center}
7528      \begin{tabular}{ll}
7529         Exception Name    &  Reason\\
7530         \hline
7531         Blob\_Error       &  Not open\\
7532      \end{tabular}
7533   \end{center}
7534   \caption{Blob\_Index Exceptions}\label{t:blbxx}
7535\end{table}
7536
7537The following example code determines where in the presently opened
7538blob the blob position index is:
7539
7540\begin{Example}
7541declare
7542   C :        aliased Connection_Type;
7543   B :        Blob_Type;
7544   Pos_Blob : Blob_Index;
7545begin
7546   ...
7547   Pos_Blob := Blob_Index(B);
7548\end{Example}
7549
7550\section{Information Functions}
7551
7552The following subsections describe information gathering functions.
7553They provide the programmer a way to obtain size\index{size} and identification\index{identification}
7554information.
7555
7556\subsection{Blob Size Function\label{Blob Size Function}}
7557
7558To determine the present size\index{blob size} of a blob, the Blob\_Size\index{Blob\_Size}
7559function can be used. Table~\ref{t:blbszx} documents the exceptions while the specification
7560is listed as follows:
7561
7562\begin{Code}
7563function Blob_Size(
7564   Blob : in Blob_Type
7565) return Blob_Count;
7566\end{Code}
7567
7568\begin{table}
7569   \begin{center}
7570      \begin{tabular}{ll}
7571         Exception Name    &  Reason\\
7572         \hline
7573         Blob\_Error       &  Not open\\
7574      \end{tabular}
7575   \end{center}
7576   \caption{Blob\_Size Exceptions}\label{t:blbszx}
7577\end{table}
7578
7579Notice that the return type Blob\_Count\index{Blob\_Count} does permit the value zero
7580to be returned (blob is empty).
7581
7582The following example code determines the size of the presently opened
7583blob:
7584
7585\begin{Example}
7586declare
7587   C :	       aliased Connection_Type;
7588   B :	       Blob_Type;
7589   Blob_Size : Blob_Count;
7590begin
7591   ...
7592   Blob_Size := Blob_Size(B);
7593\end{Example}
7594
7595\subsection{Blob\_OID Function\label{Blob OID Function}}
7596
7597After a blob is created, it is very necessary to determine the OID\index{OID}
7598for the blob. The Blob\_Oid function may be called after Blob\_Create\index{Blob\_Create}
7599or Blob\_Open\index{Blob\_Open} to obtain OID information.
7600Table~\ref{t:blboidx} lists the exceptions and the specification is
7601shown below:
7602
7603\begin{Code}
7604function Blob_Oid(
7605   Blob : in Blob_Type
7606) return Row_ID_Type;
7607\end{Code}
7608
7609\begin{table}
7610   \begin{center}
7611      \begin{tabular}{ll}
7612         Exception Name    &  Reason\\
7613         \hline
7614         Blob\_Error       &  Not open\\
7615      \end{tabular}
7616   \end{center}
7617   \caption{Blob\_OID Exceptions}\label{t:blboidx}
7618\end{table}
7619
7620The following example code determines the OID\index{OID} value for the newly
7621created blob\index{blob}:
7622
7623\begin{Example}
7624declare
7625   C :         aliased Connection_Type;
7626   B :         Blob_Type;
7627   Blob_OID :  Row_ID_Type;
7628begin
7629   ...
7630   B        := Blob_Create(C'Access);
7631   Blob_OID := Blob_Oid(B);
7632\end{Example}
7633
7634\subsubsection{Generic\_Blob\_Oid Function}
7635
7636To use a strongly typed version of the Blob\_Oid\index{Blob\_Oid} function, the application
7637programmer can instantiate from Generic\_Blob\_Oid. The instantiated
7638function otherwise behaves exactly as the Blob\_Oid function on page
7639\pageref{Blob OID Function}. The instantiation parameters for Generic\_Blob\_Oid\index{Generic\_Blob\_Oid}
7640are:
7641
7642\begin{Code}
7643generic
7644   type Oid_Type is new Row_ID_Type;
7645function Generic_Blob_Oid(
7646   Blob : in Blob_Type
7647) return Oid_Type;
7648\end{Code}
7649
7650The following example shows how to instantiate the function:
7651
7652\begin{Example}
7653declare
7654   type My_Oid_Type is new Row_ID_Type;
7655   function Blob_Oid is new Generic_Blob_Oid(My_Oid_Type);
7656\end{Example}
7657
7658\subsection{End\_Of\_Blob Function}
7659
7660The End\_Of\_Blob\index{End\_Of\_Blob} function can be used by programs that sequentially
7661read through a blob. The calling signature for this function is given
7662below:%
7663\marginpar{Note that this function results in poor performance if the buffer
7664size is set to zero (unbuffered) in the opening Blob\_Open/Blob\_Create
7665calls.%
7666}
7667
7668\begin{Code}
7669function End_of_Blob(
7670   Blob : in Blob_Type
7671) return Boolean;
7672\end{Code}
7673
7674The return value is True if the current position in the blob is at
7675the end of the blob. Otherwise the value False is returned. Table~\ref{teoblbx}
7676lists the possible exceptions.
7677
7678\begin{table}
7679   \begin{center}
7680      \begin{tabular}{ll}
7681         Exception Name    &  Reason\\
7682         \hline
7683         Blob\_Error       &  Not open\\
7684      \end{tabular}
7685   \end{center}
7686   \caption{End\_of\_Blob Exceptions}\label{t:eoblbx}
7687\end{table}
7688
7689The following example code reads a series of strings from the blob,
7690using the End\_Of\_Blob function:
7691
7692\begin{Example}
7693declare
7694   C : aliased Connection_Type;
7695   B : Blob_Type;
7696begin
7697   ...
7698   B := Blob_Open(...);
7699   declare
7700      S : Root_Stream_Access := Blob_Stream(B);
7701   begin
7702      while not End_Of_Blob(B) loop
7703         declare
7704            Line : String := String'Input(S);
7705         begin
7706            Put_Line(Line);
7707         end;
7708      end loop;
7709   end;
7710   Blob_Close(B);
7711\end{Example}
7712
7713\section{Stream Access}
7714
7715In order for an Ada program to perform stream I/O\index{stream I/O}
7716on a blob, you must obtain a useable stream pointer\index{stream pointer}.
7717The APQ binding defines a type named Root\_Stream\_Access\index{Root\_Stream\_Access} for
7718this purpose. It is defined as follows:
7719
7720\begin{Code}
7721
7722   type Root_Stream_Access is access all
7723      Ada.Streams.Root_Stream_Type'Class;
7724
7725\end{Code}
7726
7727The function Blob\_Stream\index{Blob\_Stream} returns this stream pointer to the caller.
7728Use of this returned pointer makes it possible to use the native Ada\index{Ada}
7729stream\index{stream I/O} I/O facilities. The function Blob\_Stream is
7730specified below while Table~\ref{t:blbstrx} documents the exceptions
7731possible.
7732
7733\begin{Code}
7734function Blob_Stream(
7735   Blob : in Blob_Type
7736) return Root_Stream_Access;
7737\end{Code}
7738
7739\begin{table}
7740   \begin{center}
7741      \begin{tabular}{ll}
7742         Exception Name    &  Reason\\
7743         \hline
7744         Blob\_Error       &  Not open\\
7745      \end{tabular}
7746   \end{center}
7747   \caption{Blob\_Stream Exceptions}\label{t:blbstrx}
7748\end{table}
7749
7750The following example shows how a blob is created, a stream access
7751value is obtained, and a APQ\_Timestamp\index{APQ\_Timestamp} value is written to the new
7752blob:
7753
7754\begin{Example}
7755declare
7756   C :         aliased Connection_Type;
7757   B :         Blob_Type;
7758   Str :       Root_Stream_Access;
7759   Some_Date : APQ_Timestamp;
7760begin
7761   ...
7762   B   := Blob_Create(C'Access);
7763   declare
7764      Str : Root_Stream_Access := Blob_Stream(B);
7765   begin
7766      APQ_Timestamp'Write(Str,Some_Date);
7767      ...
7768   end;
7769   Blob_Close(B);
7770end;
7771\end{Example}
7772
7773Notice in this example, that the declaration and the existance of
7774the stream pointer Str was restricted as much as possible.
7775While not strictly necessary, there are good reasons for following
7776this practice. See the special following note for the details.
7777
7778
7779\subsubsection{Note:}
7780
7781The programmer does not have to worry about ``closing'' or freeing\index{freeing}
7782the returned stream pointer (Str in the example). It can be
7783nulled or left to fall out of scope. Only the type Blob\_Type
7784must be ``closed'' by calling Blob\_Close\index{Blob\_Close}.
7785
7786The programmer must however be careful to never use the stream\index{stream pointer} pointer
7787after the blob has been closed, or after the connection object has
7788been closed or finalized\index{finalized}. The stream pointer should be nulled\index{nulled} when
7789it has outlived its usefulness, or allowed to fall out of scope.
7790
7791
7792\section{Blob Destruction}
7793
7794To release a blob\index{releasing a blob}, you must use the Blob\_Unlink\index{Blob\_Unlink}
7795procedure call. Table~\ref{t:blbunlkx} lists the exceptions while the specification
7796is shown below:
7797
7798\begin{Code}
7799procedure Blob_Unlink(
7800   DB :  in Connection_Type;
7801   Oid : in Row_ID_Type
7802);
7803\end{Code}
7804
7805\begin{table}
7806   \begin{center}
7807      \begin{tabular}{ll}
7808         Exception Name    &  Reason\\
7809         \hline
7810         Blob\_Error       &  No such Oid\\
7811      \end{tabular}
7812   \end{center}
7813   \caption{Blob\_Unlink Exceptions}\label{t:blbunlkx}
7814\end{table}
7815
7816The following code releases the blob referenced in the example on
7817page \pageref{Example-code-with-OID-73763}.
7818
7819\begin{Example}
7820declare
7821   C :   aliased Connection_Type;
7822   Oid : Row_ID_Type := 73763;
7823begin
7824   ...
7825   Blob_Unlink(C,Oid);
7826\end{Example}
7827
7828\subsubsection{Generic\_Blob\_Unlink Procedure}
7829
7830To use a strongly typed version of the Blob\_Unlink procedure, the
7831application programmer can instantiate from Generic\_Blob\_Unlink\index{Generic\_Blob\_Unlink}.
7832The instantiated function otherwise behaves exactly as the Blob\_Unlink
7833function. The instantiation parameters for Generic\_Blob\_Unlink are:
7834
7835\begin{Code}
7836generic
7837   type Oid_Type is new Row_ID_Type;
7838procedure Generic_Blob_Unlink(
7839   DB :  in Connection_Type;
7840   Oid : in Oid_Type
7841);
7842\end{Code}
7843
7844The following example shows how to instantiate the function:
7845
7846\begin{Example}
7847declare
7848   type My_Oid_Type is new Row_ID_Type;
7849   procedure Blob_Unlink is new
7850      Generic_Blob_Unlink(My_Oid_Type);
7851\end{Example}
7852
7853\section{File and Blob Operations}
7854
7855Blobs are very similar to files\index{files}. It should be no surprise
7856then that sometimes a file is imported\index{imported} into a blob,
7857or exported\index{exported} from a blob.
7858
7859A file is imported into a blob with the Blob\_Import\index{Blob\_Import} call:
7860
7861\begin{Code}
7862procedure Blob_Import(
7863   DB :       in     Connection_Type;
7864   Pathname : in     String;
7865   Oid :         out Row_ID_Type
7866);
7867\end{Code}
7868
7869Blob\_Import returns the Oid of the newly created blob, that now contains
7870a copy of the file specified by the Pathname argument.
7871
7872A blob's contents can be written out (exported) to a file with a call
7873to Blob\_Export\index{Blob\_Export}:
7874
7875\begin{Code}
7876procedure Blob_Export(
7877   DB :       in Connection_Type;
7878   Oid :      in Row_ID_Type;
7879   Pathname : in String
7880);
7881\end{Code}
7882
7883After a successful return from Blob\_Export, the file named by the
7884Pathname argument, contains a copy of the specified blob.
7885If any error in these import/export operations occur, the
7886exceptions listed in Table~\ref{t:blbxpx} occur.
7887
7888\begin{table}
7889   \begin{center}
7890      \begin{tabular}{ll}
7891         Exception Name       &  Reason\\
7892         \hline
7893         Blob\_Error          &  Import/export failed\\
7894      \end{tabular}
7895   \end{center}
7896   \caption{Blob\_Export Exceptions}\label{t:blbxpx}
7897\end{table}
7898
7899Note that Blob\_Import creates a new blob if necessary. Blob\_Export
7900creates a new file if necessary.
7901
7902
7903\subsubsection{Generic\_Blob\_Import and Generic\_Blob\_Export Procedures}
7904
7905To use strongly typed versions of the Blob\_Import and Blob\_Export,
7906the application programmer can instantiate from Generic\_Blob\_Import\index{Generic\_Blob\_Import}
7907and Generic\_Blob\_Export\index{Generic\_Blob\_Export} respectively. The instantiated procedure
7908otherwise behaves exactly as the Blob\_Import or Blob\_Export function.
7909The instantiation parameters for Generic\_Blob\_Import or Generic\_Blob\_Export
7910are:
7911
7912\begin{Code}
7913generic
7914   type Oid_Type is new Row_ID_Type;
7915procedure Generic_Blob_Import(
7916   DB :       in     Connection_Type;
7917   Pathname : in     String;
7918   Oid :         out Oid_Type
7919);
7920\end{Code}
7921
7922\begin{Code}
7923generic
7924   type Oid_Type is new Row_ID_Type;
7925procedure Generic_Blob_Export(
7926   DB :       in     Connection_Type;
7927   Oid :      in     Oid_Type;
7928   Pathname : in     String
7929);
7930\end{Code}
7931
7932The following example shows how to instantiate the function:
7933
7934\begin{Example}
7935declare
7936   type My_Oid_Type is new Row_ID_Type;
7937   procedure Blob_Import is new
7938      Generic_Blob_Import(My_Oid_Type);
7939\end{Example}
7940
7941
7942\chapter{Utility Functions} % Chapter 5
7943
7944\section{To\_String Support}
7945
7946To ease the job for programming, a number of builtin To\_String\index{To\_String} functions
7947are provided to allow conversion from the data type to its string
7948representation. The following To\_String functions are available with
7949the following builtin types (only one function requires a second argument):
7950
7951\begin{Code}
7952function To_String(
7953   V : APQ_Boolean
7954) return String;
7955\end{Code}
7956
7957\begin{Code}
7958function To_String(
7959   V : APQ_Date
7960) return String;
7961\end{Code}
7962
7963\begin{Code}
7964function To_String(
7965   V : APQ_Time
7966) return String;
7967\end{Code}
7968
7969\begin{Code}
7970function To_String(
7971   V : APQ_Timestamp
7972) return String;
7973\end{Code}
7974
7975\begin{Code}
7976function To_String(
7977   V : APQ_Bitstring
7978) return String;
7979\end{Code}
7980
7981The following illustrates one example:
7982
7983\begin{Example}
7984declare
7985   Ship_Date : APQ_Date;
7986begin
7987   Put({
7988   Put_Line(To_String(Ship_Date));
7989\end{Example}
7990
7991\section{Generic To\_String Support}
7992
7993Programs that make use of distinct types will require the use of generic
7994functions to perform To\_String\index{generic To\_String} conversions. The following generic
7995functions are available for instantiation:
7996
7997\begin{Code}
7998generic
7999   type Val_Type is new Boolean;
8000function Boolean_String(
8001   V : Val_Type
8002) return String;
8003\end{Code}
8004
8005\begin{Code}
8006generic
8007   type Val_Type is range <>;
8008function Integer_String(
8009   V : Val_Type
8010) return String;
8011\end{Code}
8012
8013\begin{Code}
8014generic
8015   type Val_Type is mod <>;
8016function Modular_String(
8017   V : Val_Type
8018) return String;
8019\end{Code}
8020
8021\begin{Code}
8022generic
8023   type Val_Type is delta <>;
8024function Fixed_String(
8025   V : Val_Type
8026) return String;
8027\end{Code}
8028
8029\begin{Code}
8030generic
8031   type Val_Type is digits <>;
8032function Float_String(
8033   V : Val_Type
8034) return String;
8035\end{Code}
8036
8037\begin{Code}
8038generic
8039   type Val_Type is delta <> digits <>;
8040function Decimal_String(
8041   V : Val_Type
8042) return String;
8043\end{Code}
8044
8045\begin{Code}
8046generic
8047   type Val_Type is new Ada.Calendar.Time;
8048function Date_String(
8049   V : Val_Type
8050) return String;
8051\end{Code}
8052
8053\begin{Code}
8054generic
8055   type Val_Type is new Ada.Calendar.Day_Duration;
8056function Time_String(
8057   V : Val_Type
8058) return String;
8059\end{Code}
8060
8061\begin{Code}
8062generic
8063   type Val_Type is new Ada.Calendar.Time;
8064function Timestamp_String(
8065   V : Val_Type
8066) return String;
8067\end{Code}
8068
8069The following example illustrates their use:
8070
8071\begin{Example}
8072declare
8073   type My_Date_Type is new APQ_Timestamp;
8074
8075   function To_String is new
8076      Timestamp_String(My_Date_Type);
8077
8078   Execution_Date : My_Date_Type;
8079begin
8080   ...
8081   Put("Program Execution Date: ");
8082   Put_Line(To_String(Execution_Date));
8083\end{Example}
8084
8085\section{Conversion Generic Functions}
8086
8087Sometimes a programmer must convert from a text format string into
8088another data type for manipulation. Several generic conversion \index{conversion functions} functions are
8089provided for the purpose (exceptions listed in Table~\ref{t:cvtx}):
8090
8091\begin{Code}
8092generic
8093   type Val_Type is new Boolean;
8094function Convert_To_Boolean(
8095   S : String
8096) return Val_Type;
8097\end{Code}
8098
8099\begin{Code}
8100generic
8101   type Val_Type is new Ada.Calendar.Time;
8102function Convert_To_Date(
8103   S : String
8104) return Val_Type; -- YYYY-MM-DD format
8105\end{Code}
8106
8107\begin{Code}
8108generic
8109   type Val_Type is new Ada.Calendar.Day_Duration;
8110function Convert_To_Time(
8111   S : String
8112) return Val_Type; -- HH:MM:SS format
8113\end{Code}
8114
8115
8116\begin{Code}
8117generic
8118   type Val_Type is new Ada.Calendar.Time;
8119function Convert_To_Timestamp(
8120   S : String;
8121   TZ: Ada.Calendar.Time_Zones.Time_Offset := 0
8122) return Val_Type; -- HH:MM:SS format
8123\end{Code}
8124
8125
8126As for time and timestamp conversions, these are generic implementations that in fact uses
8127the ones provided by the \emph{Ada.Calendar.Formatting} package. They are provided to enforce
8128strong typing whenever desired and also for backwards compatibility.\\
8129
8130\textbf{Convert\_to\_Date} was removed to enforce the use of Timestamps.
8131
8132\begin{table}
8133   \begin{center}
8134      \begin{tabular}{ll}
8135         Exception Name    &  Reason\\
8136         \hline
8137         Invalid\_Format   &  The input value was not a proper value for the type\\
8138      \end{tabular}
8139   \end{center}
8140   \caption{Conversion Exceptions}\label{t:cvtx}
8141\end{table}
8142
8143The following example illustrates some converions:
8144
8145\begin{Example}
8146declare
8147   type Bool is new APQ_Boolean;
8148   type Birth_Date_Type is new APQ_Date;
8149   function To_Boolean is new Convert_To_Boolean(Bool);
8150   function To_Date is new Convert_To_Date(Birth_Date_Type);
8151   My_Bool : Bool;
8152   Elvis :   Birth_Date_Type;
8153begin
8154   ...
8155   My_Bool := To_Boolean("T"); -- valid values are 1/t/true and 0/f/false
8156   Elvis   := To_Timestamp("1957-01-08 00:00:00"); -- UTC
8157\end{Example}
8158
8159\section{The Convert\_Date\_and\_Time Generic Function}
8160
8161Sometimes the programmer needs the convenience of putting separate
8162date and time values together into a returned timestamp\index{timestamp}
8163value. For example the date of birth may be stored in one database
8164column\index{column}, while the time of birth is stored in another.
8165It may be necessary to work with a timestamp value instead, that contains
8166both of these components. To permit the use of strongly typed values\index{strongly typed values},
8167a generic function is provided for this purpose.
8168
8169The generic specification for Convert\_Date\_and\_Time\index{Convert\_Date\_and\_Time} is:
8170
8171\begin{Code}
8172generic
8173   type Date_Type is new Ada.Calendar.Time;
8174   type Time_Type is new Ada.Calendar.Day_Duration;
8175   type Result_Type is new Ada.Calendar.Time;
8176function Convert_Date_and_Time(
8177   DT : Date_Type;
8178   TM : Time_Type
8179) return Result_Type;
8180\end{Code}
8181
8182The following example shows how to apply this function:
8183
8184\begin{Example}
8185declare
8186   type My_Date_Type is new APQ_Date;
8187   type My_Time_Type is new APQ_Time;
8188   type My_Timestamp_Type is new APQ_Timestamp;
8189   function To_Timestamp is new
8190      Convert_Date_and_Time(
8191         Date_Type => My_Date_Type,
8192         Time_Time => My_Time_Type,
8193         Result_Type => My_Timestamp_Type);
8194   Some_Date :      My_Date_Type;
8195   Some_Time :      My_Time_Type;
8196   Some_Timestamp : My_Timestamp_Type;
8197begin
8198   ...
8199   Some_Timestamp := To_Timestamp(Some_Date,Some_Time);
8200\end{Example}
8201
8202
8203\chapter{Calendar Functions}
8204
8205There is frequently the need in applications to separate out the hour\index{hour},
8206minute\index{minute} and second\index{second} from a time\index{time}
8207value. To make this easier, and to permit the continued use of strong
8208typing, the following generic functions are available:%
8209\footnote{It could be argued that these generic functions do not go the full
8210generic distance, because the return value types are standard types
8211only (types Hour\_Number, Minute\_Number and Second\_Number).%
8212}
8213
8214\begin{Code}
8215generic
8216   type Time_Type is new Ada.Calendar.Day_Duration;
8217function Generic_Hour(
8218   TM : Time_Type
8219) return Hour_Number;
8220-- local time zone is assumed
8221\end{Code}
8222
8223\begin{Code}
8224generic
8225   type Time_Type is new Ada.Calendar.Day_Duration;
8226function Generic_Minute(
8227   TM : Time_Type
8228) return Minute_Number;
8229\end{Code}
8230
8231\begin{Code}
8232generic
8233   type Time_Type is new Ada.Calendar.Day_Duration;
8234function Generic_Second(
8235   TM : Time_Type
8236) return Second_Number;
8237\end{Code}
8238
8239The following example shows how to apply this procedure:
8240
8241\begin{Example}
8242declare
8243   type Evt_Time_Type is new Ada.Calendar.Day_Duration;
8244   function Hour is new Generic_Hour(Evt_Time_Type);
8245   function Minute is new Generic_Minute(Evt_Time_Type);
8246   Evt_Time : Evt_Time_Type;
8247   HH :       Hour_Number;
8248   MM :       Minute_Number;
8249begin
8250   ...
8251   HH := Hour(Evt_Time);
8252   MM := Minute(Evt_Time);
8253\end{Example}
8254
8255
8256Notice these generic functions are designed torward the \emph{Day\_Duration} type and thus there is
8257no conflict with the ones available at \emph{Ada.Calendar.Formatting} standard package.
8258
8259\chapter{Decimal Support}
8260
8261In order to support accurate number calculations, particularly for
8262financial work, the package APQ\-.PostgreSQL\-.Decimal\index{APQ.PostgreSQL.Decimal}
8263is available for the programmer to use. This package is based upon
8264the C source\index{C source} code extracted out of the PostgreSQL server.%
8265\footnote{Portions copyright (c) 1996-2001, The PostgreSQL Global Development
8266Group, and portions copyright (c) 1994, The Regents of the University
8267of California.%
8268} The decimal support\index{decimal support} is \emph{not} a floating
8269point\index{floating point} package, but does support approximately
82701,000 digits worth of accuracy\index{accuracy}. Note that this is currently PostgreSQL\index{PostgreSQL}
8271specific code, and as such, it has not been reworked for general use
8272in databases like MySQL\index{MySQL}.
8273
8274
8275\section{Introduction}
8276
8277The APQ\-.PostgreSQL\-.Decimal package is a binding to the extracted server
8278decimal code. This gives the Ada programmer access to the same numeric
8279support\index{numeric support} as used by the database engine to
8280sum columns etc. Because it is decimal\index{decimal} based, you will not have to
8281worry about representation issues for values like 0.3,%
8282\footnote{In binary floating point, the value 0.3 must be represented as 0.29999
8283repeat.} allowing for accurate sums and hash total calculations.
8284
8285
8286\begin{quote}
8287Special Note: The APQ\-.PostgreSQL\-.Decimal package is still under development,
8288and is subject to change. One of the most serious limitations at present
8289is the fact that assignment clobbers any prior concept of precision\index{precision}
8290and scale\index{scale} for the variable being assigned to. To overcome this, it
8291is possible that a future implementation of this package may provide
8292task safe storage to preserve the variable's precision and scale.
8293This can be done by saving the variable's precision and scale in task
8294safe storage at finalization time. When the Adjust primitive is later
8295called, the saved precision and scale can be restored and followed
8296by a call to the Constrain()\index{Constrain} function. This will implicitly keep the
8297variable within its configured precision and scale parameters.
8298\end{quote}
8299
8300
8301\section{Decimal Exceptions}
8302
8303The APQ\-.PostgreSQL\-.Decimal binding can raise any of the exceptions
8304listed in Table~\ref{t:decx}.
8305
8306\begin{table}
8307   \begin{center}
8308      \begin{tabular}{ll}
8309         Exception Name    &  Reason\\
8310         \hline
8311         Decimal\_NaN      &  The value is ``Not a Number{}`` (or NULL)\\
8312         Decimal\_Format   &  Input does not represent a decimal number\\
8313         Decimal\_Overflow &  Value over/under-flowed\\
8314         Undefined\_Result &  Computation does not have a defined result\\
8315         Divide\_By\_Zero  &  An attempt to divide by zero occurred\\
8316      \end{tabular}
8317   \end{center}
8318   \caption{Decimal Exceptions}\label{t:decx}
8319\end{table}
8320
8321\section{``Not a Number'' Operations}
8322
8323A new Decimal\_Type\index{Decimal\_Type} value is initialized to NaN\index{NaN} (Not a
8324Number). This is a special status for the value, which can be assigned
8325to other Decimal\_Type values. When this status is detected in an
8326expression where a computation is being performed, the exception
8327Decimal\_NaN\index{Decimal\_NaN exception} is raised to indicate that no
8328valid result can be determined.
8329
8330
8331\section{The Decimal\_Type Type}
8332
8333Decimal values are manipulated in a type, which is defined in terms
8334of a tagged\index{tagged} controlled\index{controlled} record:
8335
8336\begin{Code}
8337
8338   type Decimal_Type is new
8339      Ada.Finalization.Controlled with private;
8340
8341\end{Code}
8342
8343These values are further defined by the following additional two attributes:
8344
8345\begin{description}
8346   \item [Precision] specifies the precision of the decimal variable
8347   \item [Scale] specifies the scale of the decimal variable
8348\end{description}
8349
8350\section{Is\_NaN Function}
8351
8352To test if a value is ``Not a Number'', the Is\_NaN\index{Is\_NaN} function can
8353be used:
8354
8355\begin{Code}
8356function Is_Nan(
8357   DT : Decimal_Type
8358) return Boolean;
8359\end{Code}
8360
8361The following example shows how to apply the function:
8362
8363\begin{Example}
8364declare
8365   D : Decimal_Type;
8366begin
8367   if Is_NaN(D) then
8368   Put_Line("D is NaN!");
8369   ...
8370\end{Example}
8371
8372\section{Convert Procedure}
8373
8374To import\index{import} a large decimal value from a String, the programmer may
8375invoke the Convert\index{Convert} procedure:
8376
8377\begin{Code}
8378procedure Convert(
8379   DT :        in out Decimal_Type;
8380   S :         in     String;
8381   Precision : in     Precision_Type := 0;
8382   Scale :     in     Scale_Type := 2
8383);
8384\end{Code}
8385
8386The arguments \emph{Precision} and \emph{Scale} arguments can be omitted
8387if you can accept the default values of 0 and 2 for the precision
8388and scale respectively. When \emph{Precision} is given as zero, the
8389value has no defined precision, and may grow to whatever size is necessary
8390to carry the result.%
8391\footnote{The source code indicates that the maximum precision is approximately
83921,000 decimal digits.}
8393
8394The following example shows how to initialize a Decimal\_Type from
8395a string:
8396
8397\begin{Example}
8398declare
8399   D : Decimal_Type;
8400begin
8401   Convert(D,"12345.6789",0,4);
8402\end{Example}
8403
8404\section{To\_String Function}
8405
8406To make a Decimal\_Type value printable, you can call upon the To\_String\index{To\_String}
8407function:
8408
8409\begin{Code}
8410function To_String(
8411   DT : Decimal_Type
8412) return String;
8413\end{Code}
8414
8415The To\_String will return the string ``NULL''\index{NULL} if the value is
8416in the ``Not a Number'' state.
8417
8418The following example shows how to use it in a Put\_Line call:
8419
8420\begin{Example}
8421declare
8422   D : Decimal_Type;
8423begin
8424   ...
8425   Put_Line("D := " & To_String(D));
8426\end{Example}
8427
8428\section{Constrain Function}
8429
8430Sometimes it is desireable to constrain\index{constraining values}
8431a result to a particular precision and scale, while watching for overflows.
8432The Constrain function takes an input value, and returns a new value
8433with the values constrained to the given precision and scale\index{Constrain}:
8434
8435\begin{Code}
8436function Constrain(
8437   DT :        in Decimal_Type;
8438   Precision : in Precision_Type;
8439   Scale :     in Scale_Type
8440) return Decimal_Type;
8441\end{Code}
8442
8443The returned value is rounded (if necessary) to accomodate the \emph{Scale}\index{scale}
8444argument. The result must fit within the precision\index{precision} given by the \emph{Precision}
8445argument. The following example illustrates how the function is used:
8446
8447\begin{Example}
8448declare
8449   A : Decimal_Type;
8450   B : Decimal_Type;
8451begin
8452   A := ...some calculation...;
8453   B := Constrain(A,10,2);  -- Precision 10, Scale 2
8454\end{Example}
8455
8456\section{Expression Operations}
8457
8458The Decimal\_Type values can be both assigned and computed with the
8459normal set of operators\index{operators} as shown in Table~\ref{t:decopr}.
8460
8461\begin{table}
8462   \begin{center}
8463      \begin{tabular}{|c|c|}
8464         \hline
8465         Operator             &  Description\\
8466         \hline
8467         +                    &  Add\\
8468         -                    &  Subtract\\
8469         {*}                  &  Multiply\\
8470         /                    &  Divide\\
8471         unary -              &  Negate\\
8472         =                    &  Equal\\
8473         <                    &  Less than\\
8474         <=                   &  Less than or equal\\
8475         >                    &  Greater than\\
8476         >=                   &  Greater than or equal\\
8477         \hline
8478      \end{tabular}
8479   \end{center}
8480   \caption{Decimal Operators}\label{t:decopr}
8481\end{table}
8482
8483The following code fragment shows some Decimal\_Type expressions\index{expressions}
8484at work:
8485
8486\begin{Example}
8487declare
8488   Watts_per_Hp : Decimal_Type;
8489   Watts :        Decimal_Type;
8490   Volts :        Decimal_Type;
8491   Amperes :      Decimal_Type;
8492   Hp :           Decimal_Type;
8493begin
8494   Convert(Watts_per_Hp,"745.577",0,3); -- Watts/HP
8495   Convert(Volts,"120.0",0,1);
8496   Convert(Amperes,"7.0",0,1);
8497   Watts := Volts * Amperes;       -- # of Watts
8498   Hp := Watts / Watts_per_Hp;     -- # of Horsepower
8499\end{Example}
8500
8501\section{Minimum and Maximum Values}
8502
8503The Min\_Value\index{Min\_Value} and Max\_Value\index{Max\_Value} functions are available to the programmer
8504to conveniently return the minimum\index{minimum} or maximum\index{maximum}
8505value of a pair, respectively. These functions share the following
8506common calling signature:
8507
8508\begin{Code}
8509function Min_Value(
8510   Left, Right : Decimal_Type
8511) return Decimal_Type;
8512\end{Code}
8513
8514\begin{Code}
8515function Max_Value(
8516   Left, Right : Decimal_Type
8517) return Decimal_Type;
8518\end{Code}
8519
8520The following example illustrates its use:
8521
8522\begin{Example}
8523declare
8524   A, B :     Decimal_Type;
8525   Smallest : Decimal_Type;
8526begin
8527   Smallest := Min_Value(A,B);
8528\end{Example}
8529
8530\section{Abs\_Value, Sign, Ceil and Floor Functions}
8531
8532The functions in the following table are documented in this section\index{Abs\_Value}\index{Sign}\index{Ceil}
8533\index{Floor}:
8534
8535\begin{Code}
8536function Abs_Value(
8537   DT : Decimal_Type
8538) return Decimal_Type;
8539\end{Code}
8540
8541\begin{Code}
8542function Sign(
8543   DT : Decimal_Type
8544) return Decimal_Type;
8545\end{Code}
8546
8547\begin{Code}
8548function Ceil(
8549   DT : Decimal_Type
8550) return Decimal_Type;
8551\end{Code}
8552
8553\begin{Code}
8554function Floor(
8555   DT : Decimal_Type
8556) return Decimal_Type;
8557\end{Code}
8558
8559The following example illustrates its use:
8560
8561\begin{Example}
8562declare
8563   A, B :    Decimal_Type;
8564   Pos_Val : Decimal_Type;
8565begin
8566   Pos_Val := Abs_Value(A,B);
8567\end{Example}
8568
8569\section{Sqrt, Exp, Ln and Log10 Functions}
8570
8571The functions in the following table are documented in this section%
8572\index{Sqrt}\index{Exp}\index{Ln}\index{Log10}:
8573
8574\begin{Code}
8575function Sqrt(
8576   X : Decimal_Type
8577) return Decimal_Type;
8578\end{Code}
8579
8580\begin{Code}
8581function Exp(
8582   X : Decimal_Type
8583) return Decimal_Type;
8584\end{Code}
8585
8586\begin{Code}
8587function Ln(
8588   X : Decimal_Type
8589) return Decimal_Type;
8590\end{Code}
8591
8592\begin{Code}
8593function Log10(
8594   X : Decimal_Type
8595) return Decimal_Type;
8596\end{Code}
8597
8598The following example illustrates its use:
8599
8600\begin{Example}
8601declare
8602   X :   Decimal_Type;
8603   L10 : Decimal_Type;
8604begin
8605   L10 := Log10(X);
8606\end{Example}
8607
8608\section{The Log Function}
8609
8610The Log\index{Log} function permits the caller to evaluate a logrithm $\log$
8611$_{\textrm{base}}$ x . It has the following calling requirements:
8612
8613\begin{Code}
8614function Log(
8615   X, Base : Decimal_Type
8616) return Decimal_Type;
8617\end{Code}
8618
8619The following example illustrates its use:
8620
8621\begin{Example}
8622declare
8623   X :    Decimal_Type;
8624   Base : Decimal_Type;
8625   L :    Decimal_Type;
8626begin
8627   L := Log(X,Base);
8628\end{Example}
8629
8630\section{The Power Function}
8631
8632The Power\index{Power} function permits the caller to evaluate the expression x$^{\textrm{y}}$.
8633The function accepts the following calling arguments:
8634
8635\begin{Code}
8636function Power(
8637   X, Y : Decimal_Type
8638) return Decimal_Type;
8639\end{Code}
8640
8641The following example assigns to \emph{P}, the value x$^{\textrm{y}}$.
8642
8643\begin{Example}
8644declare
8645   X : Decimal_Type;
8646   Y : Decimal_Type;
8647   P : Decimal_Type;
8648begin
8649   P := Power(X,Y);
8650\end{Example}
8651
8652\section{The Round and Trunc Functions}
8653
8654To round\index{round} or truncate\index{truncate} a Decimal\_Type
8655value, the application designer may call the Round\index{Round} and Trunc\index{Trunc} functions
8656respectively. They both accept the following calling arguments:
8657
8658\begin{Code}
8659function Round(
8660   DT :    in Decimal_Type;
8661   Scale : in Scale_Type
8662) return Decimal_Type;
8663\end{Code}
8664
8665\begin{Code}
8666function Trunc(
8667   DT :    in Decimal_Type;
8668   Scale : in Scale_Type
8669) return Decimal_Type;
8670\end{Code}
8671
8672The following example assigns to \emph{R}, the rounded value of \emph{X},
8673to 2 decimal places:
8674
8675\begin{Example}
8676declare
8677   X : Decimal_Type;
8678   R : Decimal_Type;
8679begin
8680   R := Round(X,2);
8681\end{Example}
8682
8683\section{Builtin Decimal\_Type Constants}
8684
8685The builtin decimal constants\index{decimal constants} are defined
8686as the following functions%
8687\index{Zero}\index{One}\index{Two}\index{Ten}\index{NaN}:
8688
8689\begin{Code}
8690
8691   function Zero return Decimal_Type;
8692   function One return Decimal_Type;
8693   function Two return Decimal_Type;
8694   function Ten return Decimal_Type;
8695   function NaN return Decimal_Type;
8696
8697\end{Code}
8698
8699The NaN function can be used to put a value into a ``Not a Number''
8700state. This doubles as setting the value to NULL\index{NULL}, for SQL query use.
8701
8702
8703\section{Using Decimal\_Types with Query\_Type}
8704
8705Creating SQL\index{SQL} queries using the Decimal\_Type\index{Decimal\_Type} and retrieving values
8706from SQL queries has been made easy for the application programmer.
8707The NaN\index{NaN} state is used to represent a NULL\index{NULL} value. This eliminates the
8708need for the application programmer to define indicator values.
8709
8710The Append procedure allows the programmer to build SQL queries with
8711Decimal\_Type values. The Value\index{Value} function, permits the programmer to
8712retrieve a column value into a Decimal\_Type variable (with or without
8713a NULL\index{NULL} value).
8714
8715
8716\subsection{Using Decimal\_Type with Append}
8717
8718The Append procedure has the following specification:
8719
8720\begin{Code}
8721procedure Append(
8722   Query : in out PostgreSQL.Client.Query_Type;
8723   DT :    in     Decimal_Type'Class;
8724   After : in     String := ""
8725);
8726\end{Code}
8727
8728\subsection{Fetching Decimal\_Type Values}
8729
8730A decimal value may be retrieved from a SQL query, using the Value
8731function:
8732
8733\begin{Code}
8734function Value(
8735   Query : in PostgreSQL.Client.Query_Type;
8736   CX :    in Column_Index_Type
8737) return Decimal_Type;
8738\end{Code}
8739
8740If the returned value for the column is NULL\index{NULL}, the value
8741returned will be in the NaN state. The following example illustrates
8742how to apply the Value\index{Value} function:
8743
8744\begin{Example}
8745declare
8746   C : Connection_Type;
8747   Q : Query_Type;
8748   D : Decimal_Type := NaN;
8749begin
8750   ...
8751   Prepare(Q,  "SELECT QTY, ...");
8752   Append_Line("FROM ORDERS");
8753   Execute(Q,C);
8754   while not End_of_Query loop
8755      Fetch(Q);
8756      D := Value(Q,1);  -- Fetch Decimal_Type
8757   end loop;
8758   Clear(Q);
8759\end{Example}
8760
8761\chapter{Generic Database Programming}
8762
8763With APQ 2.0, the support of the MySQL database becomes available.
8764The future may allow APQ to support even more database technologies.
8765With this in mind, it becomes very desireable in some circumstances
8766to write applications in a database neutral way. Within this documentation,
8767we will use the term ``Generic Database Programming'' to describe
8768portable\index{portable} database code.
8769
8770This chapter is about programming for databases generically. Given
8771that APQ is built using object oriented techniques (tagged\index{tagged} Ada2005\index{Ada2005} records),
8772it should be possible to leverage this in a way to write application
8773procedures once, and enjoy the flexibility of choosing or changing
8774the database technology used later. \Ref{Generic APQ.Result}
8775identified one aspect of generic database processing.
8776
8777
8778\section{Generic Connections}
8779
8780For most routine database work, the only object that needs to be defined
8781up front, is the database connection. In APQ version \apqversion and later,
8782there are three concrete choices:
8783
8784\begin{enumerate}
8785   \item APQ.PostgreSQL.Client.Connection\_Type
8786   \item APQ.MySQL.Client.Connection\_Type
8787   \item APQ.Sybase.Client.Connection\_Type
8788\end{enumerate}
8789
8790Once the high level layer of the application chooses one of these
8791connection objects, and establishes a connection with the database,
8792the connection object may be passed around as parameters to procedures.
8793The recommended generic way to do this, is to pass the connection
8794as a APQ\-.Root\_Connection\_Type\-'Class\index{Root\_Connection\_Type'Class} parameter. See the following
8795example:
8796
8797\begin{Example}
8798procedure MyApp(C : in out APQ.Root_Connection_Type'Class) is
8799begin
8800   ...
8801\end{Example}
8802
8803The classwide parameter then permits any database connection object
8804to be passed as a parameter. The classwide attribute causes all operations
8805performed upon that object to be dispatching calls. By dispatching
8806on the object's primitives, you ensure that database specific operations
8807are carried out according to the type of database being used.
8808
8809
8810\section{Database Specific Code}
8811
8812Due to the wide differences that sometimes exist between database
8813engines\index{engines}, it is sometimes necessary to take different course of action,
8814depending upon the database being used. For example, PostgreSQL\index{PostgreSQL} allows
8815a varchar(256)\index{varchar} column to be defined, where MySQL\index{MySQL} is limited to varchar(255)
8816instead.%
8817\footnote{MySQL requires you declare the type as TEXT if you need more than
8818255 characters.%
8819}
8820
8821To determine the database being used, use the Engine\_Of\index{Engine\_Of}
8822predicate\index{predicate} function. This primitive exists on both the Root\_Connection\_Type\index{Root\_Connection\_Type}
8823and Root\_Query\_Type objects. \Ref{Generic Database Engine_Of}
8824and \Ref{Generic APQ.Engine_Of} describe functions and examples for
8825this purpose.
8826
8827Obviously, if you are only given a Root\_Connection\_Type'Class connection
8828argument to use, you cannot know in advance which Query\_Type\index{Query\_Type} object
8829to use. Make use of the New\_Query\index{New\_Query} factory\index{factory} function to create
8830one (See \Ref{Query_Type Factories}) or use cloning\index{cloning}
8831(\Ref{Query_Type Cloning}) if you have an existing Query\_Type object
8832available.
8833
8834
8835\subsection{Row ID Values}\label{Portability Note for Row ID Values}
8836
8837When designing a new system, it is important to plan for the use of
8838row ID\index{row ID} values. MySQL\index{MySQL} does not support them at all, while PostgreSQL\index{PostgreSQL}
8839encourages their use.%
8840\footnote{For example, a blob is identified by a Oid value, which is basically
8841a row ID.%
8842} MySQL encourages the use of serial values instead, which is a good
8843practice. For generic database programming you must plan for these
8844differences to reduce the amount of specialized code. For more information
8845about obtaining row ID values, see the \Ref{Command_Oid Function},
8846and \Ref{Portability Note for Row ID Values} for portability\index{portability}
8847notes.
8848
8849Additionally, the assumptions about what constitutes a null row ID\index{null row ID}
8850must be scrutinized. Since different databases use different values
8851to represent ``no row'', you should make careful use of the APQ
8852Null\_Oid\index{Null\_Oid} function, rather than depend upon a particular
8853constant. See \Ref{Null_Oid Function} for information about
8854that.
8855
8856
8857\section{Data Types}
8858
8859When writing generic database code it is important to choose your
8860datatypes\index{datatypes} very carefully.\\
8861
8862A problem exists with PostgreSQL bit string types (APQ\_Bitstring\index{APQ\_Bitstring}).
8863MySQL and Sybase do not support them. So if you want to write portable
8864code, stick to simple data types in your application. \\
8865
8866When you must make use of special database types, be prepared to specialize
8867the code somewhat, depending upon the database being used.\\
8868
8869
8870The APQ\_Timezone data type was removed in favour of a more portable way of dealing
8871with timestamps now Ada 2005 supports time zone information.
8872
8873
8874\subsection{Column Types}
8875
8876Another area that is important to consider is the database column
8877\index{column types} types that are chosen for tables. Comparing the table in
8878\Ref{PostgreSQL SQL Data Types} and \Ref{MySQL Data Types}, the
8879reader can see that most columns can be declared in SQL using the
8880same column type declarations. However, there are some important differences.
8881For example, a SERIAL\index{SERIAL} column in PostgreSQL must be declared as an
8882INTEGER\index{INTEGER} type when using MySQL. For most applications, this is not
8883too much of an issue, because applications usually don't create and
8884drop tables. However, this can be an issue with temporary tables.\\
8885
8886
8887Also it's better to assure the table structure is expecting timestamp values
8888set in UTC in order not to mess things around when updating or moving your
8889server to another time zone.\\
8890
8891
8892
8893\section{Pulling it All Together}
8894
8895This section will examine a fairly trivial example of a generic database
8896procedure. It will make one exception for MySQL\index{MySQL}, so that the reader
8897will know how to work with database engine\index{engine} differences. Ideally, you
8898would want to avoid differences, where possible.
8899
8900The example is a real world example. A procedure is required to fetch
8901the most recent stock price available on file, for a given security
8902(by ticker symbol). While there may be a price for the security on
8903the given day, if there is not one listed, the procedure is expected
8904to fall back to the most recent price available. The table being consulted,
8905is defined as follows:\label{PRICE_HIST Table Definition}
8906
8907\begin{SQL}
8908CREATE TABLE PRICE_HIST (
8909    SECURITY   CHAR(10) NOT NULL,
8910    PRICE_DATE DATE NOT NULL,
8911    PRICE      REAL NOT NULL,
8912    PRIMARY KEY(SECURITY,PRICE_DATE)
8913);
8914\end{SQL}
8915
8916Here is the package spec for the Prices module, which makes the procedure
8917Last\_Price available for use:
8918
8919\begin{Example}
8920with APQ;
8921use APQ;
8922
8923package Prices is
8924
8925   procedure Last_Price(
8926      C :       in out Root_Connection_Type'Class;
8927      Security : in     String;
8928      Price :       out APQ_Double
8929   );
8930
8931end Prices;
8932\end{Example}
8933
8934Given any database connection, and a ticker symbol provided in argument
8935Security, the procedure Last\_Price is expected to lookup the most
8936recent stock price in the PRICE\_HIST table and return that price
8937in the Price argument. Here is the body of the package, written to
8938work with any database:
8939
8940\begin{NumberedExample}
8941package body Prices is
8942   procedure Last_Price(
8943      C :        in out Root_Connection_Type'Class;(*@\label{Ex:RootConn}@*)
8944      Security : in     String;
8945      Price :       out APQ_Double
8946   ) is
8947      function Value is new Float_Value(APQ_Double);
8948
8949      Q : Root_Query_Type'Class := New_Query(C);(*@\label{Ex:QFact}@*)
8950   begin
8951
8952      Prepare(Q,     "SELECT SECURITY,PRICE_DATE,PRICE");
8953      Append_Line(Q, "FROM PRICE_HIST");
8954      Append(Q,      "WHERE SECURITY = ");
8955      Append_Quoted(Q,C,Security,Line_Feed);
8956      Append_Line(Q, "ORDER BY SECURITY,PRICE_DATE DESC");(*@\label{Ex:OrBy}@*)
8957
8958      if Engine_Of(C) = Engine_MySQL then(*@\label{Ex:EngOf}@*)
8959         Append_Line(Q,"LIMIT 1");(*@\label{Ex:Limit1_Again}@*)
8960      end if;
8961
8962      Execute(Q,C);
8963
8964      begin
8965         Fetch(Q);
8966      exception
8967          when No_Tuple =>
8968             raise;    -- Indicates no price
8969      end;
8970
8971      Price := Value(Q,3);
8972
8973   end Last_Price;
8974
8975end Prices;
8976\end{NumberedExample}
8977
8978A few notes are in order here: The spec already with's and uses the
8979package APQ. So it is not repeated in the body of the package. The
8980Last\_Price procedure takes a Root\_Connection\_Type'Class
8981(line~\ref{Ex:RootConn} connection object type, so it can be supplied
8982with a MySQL or PostgreSQL database connection\index{connection} (Connection\_Type).
8983
8984The New\_Query factory\index{factory} function (line~\ref{Ex:QFact}) is used to create
8985the correct Query\_Type object necessary to match the connection. It is
8986used to form and execute the query. The Prepare, Append\_line,
8987Append\_Quoted calls build up an SQL query, and then the type of the
8988database is queried by calling Engine\_Of (line \ref{Ex:EngOf}). If the
8989database being used is a MySQL database, the query is optimized
8990\footnote{One could also argue that it is {}``fixed'' here, since MySQL
8991insists that all row results of a query be fetched.} so that only one
8992row is returned by use of the extended SQL ``LIMIT 1''\index{LIMIT} clause
8993(line~\ref{Ex:Limit1_Again}).
8994
8995Note that the ``ORDER BY''\index{ORDER BY} clause in line~\ref{Ex:OrBy} requires that
8996the sort order be descending (most recent dates first). Given that the
8997``ORDER BY'' clause specifies indexed columns, this retrieval should
8998be quick since a reverse index retrieval is possible (if the database
8999cannot do this, you should create a new index or fix the primary key to
9000be descending).
9001
9002Since we are only interested in the most recent price (ie. one price),
9003only one Fetch call is made. This is not a problem for PostgreSQL,
9004but it is for MySQL if there there are more than one row (see
9005\Ref{Fetch Limitations} to find out why). If the database is MySQL
9006the problem is addressed by adding to the query a MySQL extended clause
9007``LIMIT 1''\index{LIMIT}, to limit the results to one row (line~\ref{Ex:Limit1_Again}).
9008
9009The price is then fetched from column 3 (PRICE) and the procedure
9010returns. If no rows are returned, we simply raise the APQ.No\_Tuple
9011exception here to keep the example simple. A finished application
9012would handle this in a more elegant way perhaps.
9013
9014The important thing to recognize here is that there is nothing specific
9015to the type of database being used in this Prices package, except
9016for the MySQL work-around. The only APQ package being used is the
9017top level package APQ, and the root types for connection and query
9018types.
9019
9020Here is a PostgreSQL main program:
9021
9022\begin{Example}
9023with Ada.Text_IO;
9024with APQ.
9025with Prices;
9026
9027use APQ, Prices, APQ.
9028
9029procedure Price_PG is
9030   C : Connection_Type;
9031   P : APQ_Double;
9032begin
9033
9034   Set_DB_Name(C,"investments");
9035   Connect(C);
9036
9037   Last_Price(C,"RHAT",P);
9038   Put_Line("RHAT $" & APQ_Double'Image(P));
9039
9040   Disconnect(C);
9041
9042end Price_PG;
9043\end{Example}
9044
9045Please notice the following points about the main program:
9046
9047\begin{enumerate}
9048   \item The database specific package is with'ed as APQ.PostgreSQL.Client
9049         here to choose the database connection being used.
9050   \item The Connection\_Type object is declared in APQ.PostgreSQL.Client and
9051         derives from APQ.Root\_Connection\_Type.
9052   \item The database is chosen and a connection is established.
9053         \item The Last\_Price procedure is called, providing only the connection
9054         and the security's ticker symbol that the price is being sought for.
9055   \item The returned price P is then printed (albeit crudely)
9056   \item The application disconnects from the server and exits.
9057\end{enumerate}
9058
9059The same main program using MySQL looks like this:
9060
9061\begin{Example}
9062with Ada.Text_IO;
9063with APQ.
9064with Prices;
9065
9066use APQ, Prices, APQ.
9067
9068procedure Price_My is
9069   C : Connection_Type;
9070   P : APQ_Double;
9071begin
9072
9073   Set_DB_Name(C,"investments");
9074   Connect(C);
9075
9076   Last_Price(C,"RHAT",P);
9077   Put_Line("RHAT $" & APQ_Double'Image(P));
9078
9079   Disconnect(C);
9080
9081end Price_My;
9082\end{Example}
9083
9084The only difference between this MySQL\index{MySQL} main program and the prior
9085PostgreSQL\index{PostgreSQL} main program, is the name of the package used (APQ\-.MySQL\-.Client).
9086APQ truly is the closest thing to database independance!
9087
9088
9089\section{Miscellaneous Portability Issues}
9090
9091There are a number of other database portability issues that should
9092be born in mind. An incomplete list has begun in this document below:
9093
9094\begin{itemize}
9095   \item temporary tables creation
9096   \item SELECT ... INTO TABLE ...
9097\end{itemize}
9098
9099This list will grow with submissions and experience.
9100\footnote{Contributions are welcome.}
9101
9102
9103\subsection{Temporary Tables\label{Creating Temp Tables}}
9104
9105Many databases allow the SQL programmer to create a temporary\index{temporary tables} table
9106prior to its use in the application. This temporary table is only
9107visible to the user of the established database connection. When the
9108database connection is closed or disconnected, the temporary table
9109is automatically discarded and its space recycled by the database
9110engine.
9111
9112The difficulty that a generic database programmer needs to be aware
9113of is that some databases work differently. Normally, an application
9114would perform something like the following to create a temporary table
9115in the database session that required it:
9116
9117\begin{SQL}
9118CREATE TEMP TABLE INTERMED_RESULTS (
9119   SECURITY  CHAR(10) NOT NULL,
9120   HOLDINGS  BIGINT NOT NULL
9121);
9122\end{SQL}
9123
9124Subsequent to the successful creation\index{create temp table} of this temporary table, the
9125application would populate it and use it as necessary. The application
9126may even create indexes on the table after the table is populated,
9127to help performance in later stages of the table's use.
9128
9129While this works for PostgreSQL\index{PostgreSQL} and MySQL\index{MySQL}, the generic programmer
9130should be aware that this will not work on an Oracle\index{Oracle} database (when
9131APQ gets there some day). Oracle permits the same syntax, but operates
9132differently: Oracle only permits one CREATE TEMP TABLE\index{CREATE TEMP TABLE} operation to
9133be performed, in the same way that a permanent table is created. Once
9134created, the user implicitly gets access to the table upon demand.
9135Upon the first reference to the temporary table in a particular session,
9136you get a temporary table created, which is empty. You then populate
9137and use that temporary table without ever having to create it within
9138that particular session. When the session is over, the table's contents
9139are discarded.
9140
9141So how do you plan for this? If the Engine\_Of\index{Engine\_Of} function
9142indicates Engine\_Oracle\index{Engine\_Oracle}, you must \emph{not} create the
9143temporary table during your database session. This will be done when
9144the permanent tables are created.%
9145\footnote{In many respects, this is perhaps the best time to declare and plan
9146for a temporary table.%
9147} For other database engines, you should create the temporary table
9148when you are about to use them in your application.
9149
9150Perhaps the most sensible thing for temporary tables is to isolate
9151much of that work to stored\index{stored procedures} procedures. Your program can then just
9152invoke the stored procedure in a portable fashion.
9153
9154
9155\subsubsection{Indexes on Temporary Tables}
9156
9157There is an additional piece of advice to consider when creating indexes
9158for temporary tables. For performance reasons, it is often best to
9159populate the temp table with no indexes\index{indexes} created. After the table has
9160been populated, indexes can then be efficiently added and dropped
9161as the needs arise.
9162
9163In the Oracle case, these indexes are likely to be predefined as is
9164the declaration of the temporary table itself. So when creating indexes
9165for temporary tables, you should also probably test for Oracle in
9166the generic code. When using Oracle, you probably do \emph{not} want
9167to create or drop the index\index{index, create/drop}, as it will probably affect all users
9168of that temporary table definition.%
9169\footnote{The author has not verified this point, but the reader is encouraged
9170to do so.%
9171}
9172
9173\subsection{SELECT ... INTO TABLE}
9174
9175A number of database engines support a SQL syntax along the lines
9176of:
9177
9178\label{SelectIntoTempTable}
9179\begin{SQL}
9180SELECT *
9181FROM MY_TABLE
9182WHERE ...
9183INTO TEMP TABLE TEMP123
9184\end{SQL}
9185
9186The above SQL code performs the usual SELECT\index{SELECT INTO TEMP}, but places its results
9187into a temporary table named TEMP123. \footnote{One application
9188framework that the author is familiar with used a suffix of ``123'' to
9189denote the name of a temporary table.} Alternatively, databases will
9190also often permit:
9191
9192\begin{SQL}
9193SELECT *
9194FROM MY_TABLE
9195WHERE ...
9196INTO TABLE RESULTS
9197\end{SQL}
9198
9199This query places the results into a permanent table named RESULTS
9200(note that the keyword TEMP was dropped).
9201
9202Both of these operations are very convenient for processing intermediate
9203results. However, database engines vary in their support. Neither
9204of these formats are supported by PostgreSQL or MySQL, but they are
9205supported by INFORMIX.
9206
9207The SQL-99\index{SQL-99} way to perform this operation is specified as follows:
9208
9209\begin{SQL}
9210INSERT INTO RESULTS
9211SELECT *
9212FROM MY_TABLE
9213WHERE ...
9214\end{SQL}
9215
9216This syntax is supported by both PostgreSQL\index{PostgreSQL} and MySQL\index{MySQL} for permanent
9217tables.
9218
9219There is no provision currently to create a temporary table on the
9220fly with syntax shown on page \pageref{SelectIntoTempTable}
9221using PostgreSQL or MySQL. So even SQL-99 syntax won't help you there.
9222You can only create a temporary table, and then use the INSERT INTO\index{INSERT INTO}
9223... SELECT syntax after the temporary table is created. But don't
9224forget the limitation in \Ref{Creating Temp Tables}.
9225
9226
9227\chapter{Troubleshooting}
9228
9229There are several problems\index{problems} that can crop up in applications using
9230the APQ Binding. These problems usually fall into one of the following
9231categories:
9232
9233\begin{itemize}
9234   \item PostgreSQL database server ``personality''
9235   \item The PostgreSQL libpq C library interface
9236   \item The MySQL client library
9237   \item Sybase libraries and/or interfaces file
9238   \item The APQ binding itself
9239\end{itemize}
9240
9241The APQ Binding attempts to insulate the user as much as is practical
9242from the client library issues and the database server. However, some
9243issues still manage to poke through. This chapter is an attempt to
9244provide some useful advice for those people that are encountering
9245unexpected behaviour, using the APQ Binding.
9246
9247
9248\section{General Problems}
9249
9250The following subsections provide general troubleshooting help with
9251APQ binding issues.
9252
9253
9254\subsection{Missing Rows After Inserts (PostgreSQL)}
9255
9256The first step in identifying whether this section applies or not,
9257is to ask:
9258
9259\begin{itemize}
9260   \item is a transaction\index{transaction} processing being used?
9261   \item or, is a transaction pending when it shouldn't be?
9262\end{itemize}
9263
9264If the second bullet applies to you, then you need to correct the
9265logic in your program (but read on to find out why).
9266
9267On the other hand, if you are purposely using transactions (first
9268case) and you are losing\index{losing rows} inserted row information, then it is likely
9269that you are suffering from an aborted transaction in PostgreSQL\index{PostgreSQL} (this
9270is PostgreSQL specific). It might also represent an APQ binding bug\index{bug},
9271but check first to make sure that you have not put PostgreSQL into
9272an ``abort state''\index{abort state} (ie. in a snit). This is unusal database behavior,
9273but the PostgreSQL group seems to be proud of it.
9274
9275The APQ Binding should prevent aborted\index{aborted transactions} transactions from being left
9276unnoticed.%
9277\footnote{If however, the Abort\_State\index{Abort\_State} exception is never being raised, then
9278it is possible you have a PostgreSQL porting issue. If the PostgreSQL
9279notice message format changes, the APQ binding code will fail to recognize
9280the notification of an ``abort state'' from the database server.%
9281} When the database server notificaties the APQ binding that an {}``abort
9282state'' has been entered%
9283\footnote{After a duplicate key on insert error, for example.%
9284}, any further attempts to execute SQL queries or COMMIT WORK\index{COMMIT WORK} on that
9285connection, will raise the Abort\_State exception for PostgreSQL (see
9286also \Ref{In_Abort_State Function} and \Ref{Abort_State exception}).
9287
9288One common reason this happens is when an application inserts\index{insert of rows} rows
9289into a table, and intercepts the SQL\_Error\index{SQL\_Error} exception. This exception
9290is caught because the application writer wants to ignore the insert
9291on a duplicate\index{duplicate key insert} key error. The difficulty here is that the PostgreSQL
9292database engine will enter an ``abort state'' after the failed
9293INSERT\index{INSERT} operation, regardless of how the application handles the exception.
9294The only recourse to recovery at this point is to rollback the transaction
9295with a call to Rollback\_Work (\Ref{Begin, Commit and Rollback Work functions}).
9296
9297This brings up a question about the APQ Binding. Why doesn't the APQ
9298binding raise Abort\_State immediately after the failed INSERT\index{INSERT} operation
9299within a transaction? There are two reasons:
9300
9301\begin{enumerate}
9302   \item The ``Abort State'' notice is provided to the APQ binding in the
9303         form of a callback.
9304   \item Processing SQL\_Error exception within a transaction implies an aborted
9305         transaction (for PostgreSQL only).
9306\end{enumerate}
9307
9308Notices are received by the APQ binding by registering a callback
9309with the database server. As a result, it is not always possible to
9310know about the ``abort state''\index{abort state} when it might be critical to the
9311application. Even if the information is available, this may not always
9312be so in future versions of PostgreSQL\index{PostgreSQL} (timing may change).
9313
9314The very fact that you've started a transaction with Begin\_Work and
9315you have encountered an SQL\_Error exception should tell you that
9316you must Rollback\_Work and recover (remember this is only for PostgreSQL).
9317So as the developer, you should be thinking:
9318
9319$Abort\, State=Begin\, Work+SQL\, Error$
9320
9321The APQ binding has been designed to avoid several SQL statements
9322from being executed and being ignored because the database server
9323is in this ``Abort State''. This is why the Execute and Commit\_Work
9324calls check for this and raise the Abort\_State\index{Abort\_State} exception. However,
9325the best advice is to not rely on this mechanism when programming
9326the logic of your application.
9327
9328
9329\subsection{Missing Time Data (Or Time is 00:00:00)}
9330
9331You build a query to insert or update a row with date and time\index{time} information,
9332but only the date\index{date} is getting stored in the database. The time component
9333always reads midnight\index{midnight} (00:00:00). Or perhaps you provide a date and
9334timestamp as part of a WHERE\index{WHERE clause} clause, but it fails because only the
9335date value is being put into the query (the time component always
9336shows as midnight). You print out the variables using To\_String and
9337they show the correct values, as follows:
9338
9339\begin{Example}
9340declare
9341   type My_Date_Type is new APQ_Timestamp;
9342   My_Date : My_Date_Type;
9343begin
9344   ...
9345   Put_Line(
9346      "My_Date='"
9347      & To_String(APQ_Timestamp(My_Date))
9348      & "'"
9349   );
9350\end{Example}
9351
9352The above symptoms are the result of a common problem. This human
9353error is easy to make and is due to choosing the incorrect generic
9354procedure. Look for a generic instantiation statement like the following:
9355
9356\begin{Code}
9357
9358   procedure Append
9359      is new Append_Date(My_Date_Type);
9360
9361\end{Code}
9362
9363If your data type My\_Date\_Type holds time information, then
9364it is likely that you meant to code the following instead:
9365
9366\begin{Code}
9367
9368   procedure~Append
9369      is new Append_Timestamp(My_Date_Type);
9370
9371\end{Code}
9372
9373The error was choosing generic procedure Append\_Date\index{Append\_Date} over the correct
9374Append\_Timestamp\index{Append\_Timestamp} routine.
9375
9376A similar mistake can be made choosing between Encode\_Date\index{Encode\_Date} and Encode\_Timestamp\index{Encode\_Timestamp}
9377generic procedures. So watch for these subtle differences!
9378
9379
9380\subsection{Exception No\_Tuple}
9381
9382If you are having the exception No\_Tuple\index{No\_Tuple} being raised when you don't
9383think it should be, then check to see if the following apply:
9384
9385\begin{itemize}
9386   \item Are you using MySQL\index{MySQL}?
9387   \item Do you use the End\_of\_Query\index{End\_of\_Query} function calls?
9388\end{itemize}
9389
9390If you do, then you need to look for any code calling End\_of\_Query,
9391particularly loops:
9392
9393\begin{Example}
9394   while not End_of_Query(Q) loop
9395      Fetch(Q);
9396      ...
9397   end loop;
9398\end{Example}
9399
9400This type of code works well for PostgreSQL\index{PostgreSQL}, but may be problematic
9401with some other databases (MySQL has a problem with this). Restructure
9402your code to eliminate the calls to End\_of\_Query (this call is now
9403considered \emph{obsolete} within APQ). \Ref{End_of_Query}
9404describes the problem in greater detail. Restructure the loop to something
9405like the following:
9406
9407\begin{Example}
9408loop
9409   begin
9410      Fetch(Q);
9411   exception
9412      when No_Tuple =>
9413         exit;
9414   end;
9415   ...
9416end loop;
9417\end{Example}
9418
9419\subsection{Null Values}
9420
9421If you are using Sybase\index{Sybase} and experiencing a problem where you are receiving
9422a Null\_Value\index{Null\_Value} exception when there should be a value, then check to
9423make sure that you have called Fetch\index{Fetch}. MySQL and PostgreSQL will raise
9424No\_Result\index{No\_Result} when this happens. Sybase however, will appear to APQ as
9425holding row results (which it might be), but APQ will not realize
9426that Fetch has not yet been called. The Sybase library will then return
9427a NULL\index{NULL} value if an attempt to get a column value is made, without
9428a prior call to Fetch.
9429
9430Forgetting to call Fetch is easy to do when you code a SELECT\index{SELECT} to return
9431one row with the help of a primary key reference in a WHERE\index{WHERE clause} clause.
9432Since you are expecting one row to be returned, you will not code
9433it as part of a traditional loop. So it is human nature to forget
9434to code the call to Fetch after the Execute call. The following example
9435might be typical of this:
9436
9437\begin{Example}
9438   Prepare(Sy_Q,     "SELECT PUB_ID,PUB_NAME,CITY,STATE");
9439   Append_Line(Sy_Q, "FROM PUBLISHERS");
9440   Append(Sy_Q,      "WHERE PUB_ID = ");
9441   Append_Quoted(Sy_Q,Sy_C,Pub_Id);
9442   Execute(Sy_Q,Sy_C);
9443   Fetch(Sy_Q);      -- Easy to forget
9444\end{Example}
9445
9446\subsection{Database Client Problems}
9447
9448If problems with the database engine begin to occur after a particular
9449query, look for the following:
9450
9451\begin{itemize}
9452   \item Are you using MySQL\index{MySQL}?
9453   \item Are your doing a SELECT\index{SELECT}, or otherwise returning row results?
9454   \item Is your Query\_Type object in Sequential\_Fetch mode?
9455   \item Is your code fetching all row data?
9456\end{itemize}
9457
9458This problem may occur with MySQL\index{MySQL}, since the client library for MySQL
9459requires that all row result data be fetched. Failure to fetch all
9460rows may cause a backlog in communication with the database server
9461and cause strange behaviour or errors. Check the Query\_Type fetch
9462mode.
9463
9464
9465\subsection{Client Performance or Memory Problems}
9466
9467Check to see if the following apply:
9468
9469\begin{itemize}
9470   \item Are you using MySQL\index{MySQL}?
9471   \item Are you doing a SELECT\index{SELECT} or otherwise returning large row sets?
9472   \item Is your Query\_Type object in Random\_Fetch\index{Random\_Fetch} mode?
9473\end{itemize}
9474
9475If the above are true, then it is possible you have formed a query
9476that has generated a large row set. Since the default for the MySQL
9477Query\_Type object is for Random\_Fetch mode, the APQ library calls
9478upon mysql\_store\_result() to fetch all of the result set into the
9479client's memory for random access. For reasonable sized sets of rows,
9480this works well, but for larger results, this can be very expensive
9481and may run your application out of memory.
9482
9483Consider the PRICE\_HIST table like the one discussed on page \pageref{PRICE_HIST Table Definition}.
9484For MySQL, if you fail to include the LIMIT 1 clause, and your Query\_Type
9485object uses the default Random\_Fetch mode, you could easily find
9486your application selecting the entire history of one security into
9487your application client memory! If you have several years of price
9488history for that security, your application may be destined to run
9489out of memory the first time that query is run.
9490
9491When using the MySQL database, you must consider the following:
9492
9493\begin{itemize}
9494   \item MySQL fetches in Random\_Fetch mode must guarantee a \emph{reasonably
9495         small result set} (use the LIMIT clause if necessary).
9496   \item MySQL fetches in Sequential\_Fetch mode must fetch \emph{all} row
9497         data
9498\end{itemize}
9499
9500Unless otherwise noted, you probably do not need to be concerned about
9501this. PostgreSQL\index{PostgreSQL} for example, does not require all row data to be
9502fetched. However, if there are ways to restrict the row set, this
9503may improve database server performance.
9504
9505
9506\subsection{Can't Find Existing Table Names}
9507
9508Some databases use caseless\index{caseless} references to database objects, while
9509others are case\index{case sensitive} sensitive (MySQL can be either). If you are using
9510MySQL and experiencing problems, one solution is to configure the MySQL parameter:
9511
9512\begin{Code}
9513
9514   [mysqld]
9515   set-variable = lower_case_table_names=1
9516
9517\end{Code}
9518
9519By default, MySQL distinguishes
9520between table names PRICE\_HIST, Price\_Hist, and price\_hist for
9521example. Setting the parameter true (1), causes all table names
9522to be lowercased (effectively caseless)\index{caseless table names}.
9523
9524The another approach is to check the SQL case policy\index{case policy} being used. APQ
9525can work with MySQL in Lower\_Case, Upper\_Case or Preserve\_Case
9526mode. The last choice only makes sense of course, if the SQL text
9527in the program is correct.
9528
9529The suggested approach is to configure lower\_case\_table\_names=1
9530(as shown above) and to Set\_Case(C,Upper\_Case). Uppercase\index{uppercase} is easier
9531to read in the trace logs, since the SQL stands out from the other trace
9532information.
9533
9534If you are using Sybase\index{Sybase}, you cannot change the server. This means
9535that either a Upper\_Case or Lower\_Case policy has to work for you,
9536or you have to use exact case\index{exact case} for SQL code in the Ada code. It is
9537possible to use a Lower\_Case policy most of the time, and make exceptions
9538where they are required. The following shows how to make exceptions
9539for a table name only:
9540
9541\begin{Example}
9542declare
9543   C : Connection_Type;
9544   Q : Query_Type;
9545begin
9546   Prepare(Q,"SELECT DESCRIPTION");
9547   Append(Q,"FROM ");
9548   Set_Case(Q,Preserve_Case);
9549   Append(Q,"Part_Info",Line_Feed);
9550   Set_Case(Q,Lower_Case);
9551   Append_Line(Q,"WHERE ...");
9552   ...
9553   Execute(Q,C);
9554\end{Example}
9555
9556In the example presented, the case policy\index{case policy} was changed temporarily
9557while building the query. Here the table name Part\_Info will have
9558its case preserved, even though it is not a quoted string\index{quoted string}. The example
9559assumes here that the normal policy is Lower\_Case.
9560
9561Note however, that any case policy change in the Query\_Type object
9562is lost once Execute is called. An example will clarify this. Assume
9563from our example above, two things:
9564
9565\begin{enumerate}
9566   \item The case policy in effect in the connection object C, is Lower\_Case
9567         (all SQL text is lowercased except where case must be preserved).
9568   \item Assume that the second Set\_Case(Q,Lower\_Case) call in the example
9569         code was commented out (the policy for Q is left at Preserve\_Case)
9570\end{enumerate}
9571
9572If the above two assumptions are true, then upon return from the Execute(Q,C)
9573call, the Query\_Type object would now hold the case policy of Lower\_Case
9574(this came from Connection\_Type). Even after you call Clear, or Prepare
9575and start a new query, this is the SQL case policy that is now in
9576effect for Q.
9577
9578
9579\section{Blob Related Problems}
9580
9581Blob operations on a database can be tricky to get right. The following
9582subsections provide some assistance with blob related issues.
9583
9584
9585\section{Blob\_Create and Blob\_Open Fails}
9586
9587You have written what seems like a simple piece of code that creates
9588a blob, and then writes some data to it. It couldn't possibly fail
9589on paper, but it does when you run it. Or you are wondering why that
9590Blob\_Open\index{Blob\_Open failures} call keeps failing, because you are certain that the OID
9591of that blob surely does exist. These are both symptoms of the same
9592problem!
9593
9594\begin{quote}
9595   \emph{``All blob operations in PostgreSQL must be performed within
9596      a transaction''}
9597\end{quote}
9598
9599Repeat it to yourself again. It is too easy to forget this fact!
9600
9601Unless you have started a transaction on the connection that you are
9602using, \emph{all blob operations will fail}. They will only succeed within
9603a transaction\index{transaction}. Furthermore, make certain your application commits\index{commit}
9604the changes to your blob, after they have been performed successfully.
9605Otherwise your application may fall prey to the default actions of
9606PostgreSQL, which may be to rollback\index{rollback} your changes.%
9607\footnote{Check your PostgreSQL documentation to determine what the default
9608transaction action is for your version of PostgreSQL database.}
9609
9610
9611\section{Blob I/O Buffering Bugs Suspected}
9612
9613If you have good reason to believe that the APQ binding software%
9614\footnote{Only APQ versions 1.2 and later have buffered blob I/O.%
9615} has a bug\index{bug} in its buffered\index{buffered blob I/O} blob I/O, you can disable blob I/O buffering.
9616This is done by specifying a value of zero for the Buf\_Size argument
9617in the Blob\_Open and/or Blob\_Create calls that you are troubleshooting.
9618Be prepared to accept a large degradation in performance when specifying
9619unbuffered I/O this way. The performance\index{performance} is especially poor when array
9620I/O is performed.
9621
9622Another possibility might be that you need to call upon Blob\_Flush\index{Blob\_Flush}
9623at strategic points in your application. While the buffering algorithms
9624used are such that you should not need to worry about this, it is
9625worth investigating when problems exist.
9626
9627Note also that multiple write access to the same blob is definitely
9628\emph{not} supported by APQ.
9629
9630
9631\section{Transaction Problems}
9632
9633The following subsections deal with transaction problems that may
9634occur with application termination.
9635
9636
9637\subsection{Abnormal Termination of Transactions}
9638
9639The APQ binding is designed to commit or rollback a transaction when the
9640Connection\_Type object finalizes. The default behavior of the
9641Connection\_Type is to ROLLBACK WORK\index{ROLLBACK WORK}, when the object finalizes\index{finalizes}%
9642\footnote{Provided that the Connection\_Type object is connected to the
9643database at the time of finalization.}. Consequently, if your program
9644raises an uncaught exception (perhaps Program\_Error or
9645Constraint\_Error), the Connection\_Type object will finalize\index{finalize} and
9646rollback\index{rollback} the transaction on you. \footnote{Unless you have changed the
9647default setting for the object. } If this is undesired behaviour, then
9648check out the Set\_Rollback\_On\_Finalize primitive in section
9649\Ref{Set_Rollback_On_Finalize Procedure}.
9650
9651
9652\subsection{Aborted Applications}
9653
9654The APQ binding can only perform the default COMMIT/ROLLBACK action
9655(see \Ref{Set_Rollback_On_Finalize Procedure}) if the Connection\_Type
9656object is permitted to have its Finalize\index{finalize} primitive called. If the
9657process under UNIX for example, is terminated with a signal (by the
9658kill(1)\index{kill(1) command} command), the objects within your application may not experience
9659a Finalize call, because normal Ada shutdown procedures were not invoked.%
9660\footnote{There are Ada2005 ways to deal with UNIX signals, which permit an orderly
9661Ada shutdown of your application. However, a kill -9 prevents any
9662action at all from being performed by the application!%
9663} If this is the reason for your problem, then you have two courses
9664of action:
9665
9666\begin{itemize}
9667   \item Commit/Rollback explicitly in the program (prior to receiving a signal)
9668   \item Avoid signalling the application
9669   \item Add signal\index{signal handling} handling capability to your Ada application, to permit
9670         an orderly application shutdown
9671   \item Not use kill -9, which prevents any application recovery or notification
9672\end{itemize}
9673
9674The choice is generally up to the application designer. Whenever possible
9675however, where it is important, the application should perform its
9676own explicit commit or rollback operation.
9677
9678Note however, that if the Connection\_Type object is not permitted
9679to finalize\index{finalize} successfully on its own, the database software itself
9680has default procedures for dealing with disconnected sessions. Some
9681databases will rollback transactions if the socket/pipe connection
9682to the server is disconnected. Others will commit. You'll need to
9683check your server documentation and configuration to sort that one
9684out.
9685
9686
9687\section{SQL Problems\label{SQL Problems}}
9688
9689If you are experiencing SQL problems that you don't understand, the
9690quickest way to inspect what is really going on is to use the APQ
9691trace\index{trace facility} facility. The documentation for the SQL trace facility is given
9692in \Ref{Trace Facilities}. So RTFM.
9693
9694
9695\subsection{Tracing SQL}
9696
9697Where your Connection\_Type connects to the database, add a call to
9698Open\_DB\_Trace as follows:
9699
9700\begin{Example}
9701declare
9702   C : Connection_Type;
9703begin
9704   ...
9705   Connect(C);
9706   Open_DB_Trace(C,"trace_file.txt",Trace_APQ);
9707\end{Example}
9708
9709Without adding another line of code, every SQL interaction will be
9710captured to trace\_file.txt, which you can inspect when the application
9711completes.%
9712\footnote{Note however that the tracing facilities are not task (thread) safe.
9713If your application uses tasking, then disable tracing in the tasks
9714or avoid using APQ in more than one task.%
9715}
9716
9717
9718\subsection{Too Much Trace Output}
9719
9720If your application performs so many SQL operations that the trace
9721file becomes too large, then disable\index{disable tracing} the tracing until you get to
9722a strategic point in the program:
9723
9724\begin{Example}
9725declare
9726   C : Connection_Type;
9727begin
9728   ...
9729   Connect(C);
9730   Open_DB_Trace(C,"trace_file.txt",Trace_APQ);
9731   Set_Trace(C,False);  -- Disable trace for now..
9732   ...
9733   Set_Trace(C,True);   -- Start tracing now
9734\end{Example}
9735
9736The overhead of the Set\_Trace primitive is light, unless you have
9737selected Trace\_libpq or Trace\_Full (these add the overhead of invoking
9738libpq functions PQtrace() and PQuntrace()). Light overhead permits
9739you to use Set\_Trace within a loop without severe penalty, to gather
9740only the information you need.
9741
9742
9743\subsection{Captured SQL Looks OK}
9744
9745If the SQL code captured in \Ref{SQL Problems} looks OK,
9746but the database engine is still reporting a problem, then try the
9747following:
9748
9749\begin{enumerate}
9750   \item Create a capture file using Trace\_APQ (or use the current one you
9751         have).
9752   \item Edit (cut) out the portion of the SQL queries in the capture file
9753         that you are having difficulty with.
9754   \item Use the database interactive SQL command (psql for PostgreSQL) and
9755         replay the extracted problem SQL queries.
9756   \item Edit SQL query and repeat step \#3 as necessary until you discover
9757         your error.
9758\end{enumerate}
9759
9760This allows you to experiment with the SQL text as your applicaton
9761created it. Once you achieve success with psql, you can then go back
9762and correct your application to form the query correctly.
9763
9764
9765\subsection{You Want to Report a Problem to PostgreSQL}
9766
9767If you want to report a trace file in terms that the PostgreSQL people
9768understand, simply choose the Trace\_libpq trace mode when creating
9769a trace file. Then send them the trace file with a description of
9770the problem.
9771
9772
9773\subsection{Missing Trace Information}
9774
9775The trace information is collected at the Connection\_Type object
9776level. Check to see if you have more than one Connection\_Type object
9777involved. If so, make sure you set the appropriate trace settings\index{trace settings}
9778on the connections that you want to collect trace information for.
9779Different instances of a Connection\_Type object should write its
9780traces to different files.
9781
9782Note also, that when a Connection\_Type object finalizes\index{finalizes}, its trace
9783file is closed.
9784
9785
9786\section{Cursor Related Problems}
9787
9788To use a cursor\index{cursor} you generally need an SQL phrase of the form\index{WHERE CURRENT OF}:
9789
9790\begin{SQL}
9791
9792   WHERE CURRENT OF <Cursor_Name>
9793
9794\end{SQL}
9795
9796Obviously, the APQ function primitive Cursor\_Name\index{Cursor\_Name} is expected to
9797provide this name. But does this function primitive seem to raise
9798the exception \emph{No\_Results}\index{No\_Results} for you? If so, you've probably supplied
9799the wrong Query\_Type object to the function Cursor\_Name.
9800
9801Review the test program on page \pageref{Cursor Example Program},
9802where you see the statement:
9803
9804\begin{Example}
9805
9806   Append_Line(Q2,"WHERE CURRENT OF " & Cursor_Name(Q));
9807
9808\end{Example}
9809
9810There are two Query\_Type objects being used:
9811
9812\begin{enumerate}
9813   \item Q for the cursor fetch (outer query)
9814   \item Q2 for the inner SQL query (the UPDATE)
9815\end{enumerate}
9816
9817When coding this statement, it is very easy to type Q2 for Cursor\_Name
9818argument, instead of Q.%
9819\footnote{The author made this very mistake the first time the example program
9820was written.%
9821} However, the cursor name is only available for the outer query\index{outer query} (the
9822one with the cursor and cursor results). So be certain to carefully
9823distinguish between the inner and outer query objects.
9824
9825
9826\section{Connection Related Problems}
9827
9828If you are experiencing trouble establishing a connection to the database
9829itself, then there are a number of environment\index{environment} related issues.
9830
9831
9832\subsection{PostgreSQL Connections}
9833
9834A number of environment variables affect a PostgreSQL database connection:%
9835\footnote{Check your PostgreSQL documentation for the final word on this subject.%
9836}
9837
9838\begin{description}
9839   \item [PGHOST]Host name of the database server
9840   \item [PGPORT]IP port number or UNIX socket pathname of the database server
9841   \item [PGDATABASE]Database name within the database server
9842   \item [PGUSER]Database user name
9843   \item [PGPASSWORD]Database password
9844   \item [PGREALM]Kerberos realm for the database server
9845   \item [PGOPTIONS]Database server options
9846\end{description}
9847
9848Any of these connection mode parameters that are not configured in
9849the application are defaulted to the ones defined by the above environment
9850variables. If you are experiencing trouble, make certain that your
9851variables are \emph{exported}\index{exported variables}. In many shells, like the Bourne\index{Bourne shell} and
9852Korn\index{Korn shell} shells,%
9853\footnote{I won't encourage anyone here to use the csh.%
9854} this is done as follows (for the PGHOST\index{PGHOST} variable):
9855
9856\begin{Example}
9857
9858   export PGHOST
9859
9860\end{Example}
9861
9862Some shells, like the Korn shell and the GNU bash\index{bash shell, GNU} shell, allow multiple
9863variable names to be listed at once:
9864
9865\begin{Example}
9866
9867   export PGHOST PGPORT PGDATABASE PGUSER
9868
9869\end{Example}
9870
9871Once you have the environment configured correctly, you should be
9872able to access the database with the PostgreSQL psql\index{psql} command. If the
9873psql%
9874\footnote{Do a ``man psql'' for details about the psql client command.%
9875} command still fails, then you may need to revisit your environment
9876variable settings or possibly even the database server configuration.%
9877\footnote{Check the security aspects of your connection first.%
9878}
9879
9880
9881\subsubsection{PostgreSQL UNIX (Local) Connections}
9882
9883The way that the local socket\index{local socket} is specified for PostgreSQL seems to
9884have changed with its different releases. Make sure you choose the
9885correct Set\_Port\index{Set\_Port} procedure to specify the local UNIX socket. Use
9886the Set\_Port that accepts a string argument. The string indicates
9887that a local UNIX connection is required. PostgreSQL 7.3.5 and later
9888(unless it has changed again), requires only the ``number'' to
9889specify the local socket. For example, if you ``netstat -na'' command
9890shows the following:\footnote{The output lines have had the RefCnt
9891and Flags columns removed to allow the lines to fit the space
9892available.}
9893
9894\begin{ShellNumberedExample}
9895$ netstat -na --unix
9896Active UNIX domain sockets (servers and established)
9897Proto  Type    State         I-Node Path
9898unix   DGRAM                 2086   /dev/log
9899unix   STREAM  LISTENING     2937   /var/run/mysqld/mysqld.sock
9900unix   STREAM  LISTENING     2942   /tmp/.s.PGSQL.5432(*@\label{Ex:5432}@*)
9901unix   STREAM  CONNECTED     3363
9902unix   STREAM  CONNECTED     3362
9903unix   DGRAM                 3138
9904...
9905\end{ShellNumberedExample}
9906
9907From this display, you can see that a database connection is available
9908with UNIX\index{UNIX socket} socket /tmp/.s.PGSQL.5432 (line~\ref{Ex:5432}). For Set\_Port, you only need
9909to supply the last numerical part, namely ``5432'' (which happens
9910to match the default IP port number). So to specify a UNIX socket
9911connection for this, you would code:
9912
9913\begin{Example}
9914
9915   Set_Port(C,"5432");
9916
9917\end{Example}
9918
9919Note especially, that the number must be in a \emph{string} to cause
9920a UNIX\index{UNIX socket} local\index{local socket} socket to be used. If you specify an integer costant,
9921a TCP/IP\index{TCP/IP socket} socket will be used, which uses the IP port number you specified.
9922
9923
9924\subsection{MySQL Connections}
9925
9926APQ does not currently look for environment variables for MySQL.\footnote{although changes to MySQL are possible}
9927If you suspect environmental influences, check the MySQL C client library
9928documentation for conditions where the environment may be consulted.
9929
9930A successful MySQL connection must have:
9931
9932\begin{enumerate}
9933   \item A designated host name or address for the database server\index{host name}
9934   \item A port number\index{port number}
9935   \item Userid\index{userid} and password\index{password} (or ``'')
9936   \item Options (only if necessary)\index{options}
9937\end{enumerate}
9938
9939Any supplied instance information is ignored.
9940
9941
9942\subsection{Sybase Connections}
9943
9944APQ itself does not currently look for environment variables for Sybase\index{Sybase}.
9945The Sybase client libraries \emph{probably} do, if the variables exist.
9946Check the Sybase documentation (\emph{todo: check documentation for
9947influencing environment variables that are believed to exist}).
9948
9949A successful Sybase connection must have:
9950
9951\begin{enumerate}
9952   \item A designated instance name (Set\_Instance)\index{Set\_Instance}
9953   \item A userid\index{userid} and password\index{password} (or {}``'')
9954   \item Options (only if necessary)\index{options}
9955\end{enumerate}
9956
9957Sybase ignores the host name/address and port information. The database
9958name is only important once the connection has been established. See
9959the Sybase specific notes about Set\_DB\_Name in \Ref{Context_Setting_Operations}.
9960
9961The instance\index{instance name} name must exist in the local hosts \emph{interfaces}
9962file. In most cases this file can be found in /opt/sybase/interfaces
9963(\$SYBASE/interfaces) on UNIX platforms or possibly C:\textbackslash{}opt\textbackslash{}sybase\textbackslash{}ini\textbackslash{}sql.ini
9964(\%SYBASE\%\textbackslash{}ini\textbackslash{}sql.ini) on windows
9965(depending upon where it was installed). There may be exceptions to
9966this rule in more advanced Sybase configurations.
9967
9968
9969\subsection{Sybase Disconnect Problems}
9970
9971If you experience a APQ.Not\_Connected\index{Not\_Connected} exception
9972in one of the following scenarios:
9973
9974\begin{itemize}
9975   \item When the Connection\_Type object is finalized\index{finalized}
9976   \item When Disconnect is called on the Connection\_Type object
9977\end{itemize}
9978
9979then look for Query\_Type objects that are still hanging onto query
9980results. This most often happens in a program where the Connection\_Type
9981object and Query\_Type objects are declared together and the Connection\_Type
9982object finalizes\index{finalizes} first. The solution is to either arrange it so that
9983all Query\_Type objects finalize first, or clear the query results
9984explicitly by calling Clear, prior to disconnecting or finalizing
9985the connection. For example if Q is the Query\_Type object and C the
9986connection, then the following sequence will ensure that the disconnect
9987(or finalize) will always succeed\index{Clear}:
9988
9989\begin{Example}
9990
9991   Clear(Q);      -- Release query results
9992
9993   Disconnect(C); -- Disconnect (or finalize)
9994
9995\end{Example}
9996
9997\subsection{Sybase Options}
9998
9999APQ permits the application developer to set various Sybase\index{Options} server
10000options. Some of these are known to create problems for APQ. Rather
10001than dictate policy for the developer, APQ gives you full access to
10002the Sybase options. Clearly some options should be avoided when using
10003APQ.
10004
10005One such option is the following:
10006
10007\begin{Example}
10008
10009   Set_Options(C,"SHOWPLAN=TRUE"); -- CS_OPT_SHOWPLAN
10010
10011\end{Example}
10012
10013This option setting seems to do something strange to the underlying
10014Sybase connection after it is set. APQ has been observed raising Program\_Error\index{Program\_Error}
10015when other exceptions were supposed to have been raised. Unless you
10016know what you are doing, you seem to be well advised to stay clear
10017of this option when using APQ for Sybase.
10018
10019The developer should also avoid using any Sybase options that change
10020the way the date is formatted. APQ functions look for dates to be
10021in a specific format so that they can be converted into APQ data types.
10022
10023
10024\subsection{Connection Cloning Problems}
10025
10026If the original Connection\_Type object connects OK, but the Connect
10027clone\index{clone} call fails, then it could be that the network has gone bad since
10028the original connection was made. If exceptions other than Not\_Connected
10029are being raised, then check that:
10030
10031\begin{itemize}
10032   \item Make sure the parameters are in the correct order in the Connect call.
10033   \item Make certain that the connected object, is indeed connected.
10034   \item Make certain that the new object is not already connected.
10035   \item Make sure you haven't exceeded the number of allowed database server
10036         connections
10037\end{itemize}
10038
10039\subsection{Connection Tracing}
10040
10041Problem: Your first Connection\_Type object is tracing to a file successfully,
10042but the cloned\index{cloned} Connection\_Type object is not.
10043
10044Reason: Cloned connections do not have the trace\index{cloned trace} file parameters cloned.
10045This was a compromise to make APQ more portable to other platforms
10046that may not share files well.
10047
10048Solution: Configure the cloned connection to trace to a file separate
10049from the original connection, after the clone operation is complete.
10050
10051
10052\appendix
10053\chapter{PostgreSQL Credits}
10054
10055\section*{PostgreSQL Decimal C Sources}
10056
10057PostgreSQL Database Management System (formerly known as Postgres,
10058then as Postgres95)
10059
10060\begin{itemize}
10061\item Portions Copyright (c) 1996-2001, The PostgreSQL Global Development
10062Group
10063\item Portions Copyright (c) 1994, The Regents of the University of California
10064\end{itemize}
10065Permission to use, copy, modify, and distribute this software and
10066its documentation for any purpose, without fee, and without a written
10067agreement is hereby granted, provided that the above copyright notice
10068and this paragraph and the following two paragraphs appear in all
10069copies.
10070
10071IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
10072FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
10073INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND
10074ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
10075OF THE POSSIBILITY OF SUCH DAMAGE.
10076
10077THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
10078INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10079AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
10080IS ON AN ``AS IS'' BASIS, AND THE UNIVERSITY OF CALIFORNIA
10081HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
10082OR MODIFICATIONS.
10083
10084
10085\section*{Modification Notice}
10086
10087The numeric C routines required extensive interface modifications
10088for use in this APQ Binding. These modified C sources were extracted
10089from the PostgreSQL server project. No guarantee is made with regard
10090to the quality of these modifications.
10091
10092
10093\section*{Contributor Notice}
10094
10095In no event shall the author or contributors to the APQ Binding be
10096liable to any party for any cause that the modified PostgreSQL software
10097may cause or contribute to.
10098
10099
10100\chapter{APQ License}
10101\label{license}
10102
10103
10104\section*{Scope of the APQ Binding License}
10105
10106The {}``APQ Binding'' license covers those software modules not
10107provided by or extracted from the PostgreSQL database software (such
10108as the Decimal C source modules). The APQ license does not cover database
10109products themselves that APQ binds to.
10110
10111
10112\section*{APQ Binding License}
10113
10114The APQ Binding used to be covered under a dual-license arrangement. This
10115was reflected in the file name COPYING. The following two licenses
10116were available:
10117
10118\begin{enumerate}
10119   \item The Ada Community License (ACL).
10120   \item The GNU Public License 2 (GPL2)
10121\end{enumerate}
10122
10123This dual-license arrangement was to allow use of the package both with GPL programs
10124and non GPL programs. This can be achieved by using a single license now, and thus APQ
10125has changed it's license to MGPL.
10126
10127Please see pages \pageref{gmgpl} and \pageref{gpl} for more information.
10128
10129
10130\section*{Patents}
10131
10132The author is not aware of any patent infringements made by
10133the APQ software. However the author makes \emph{absolutely no warrante}
10134about any possible patent infringements.
10135
10136You are encouraged to lobby against any kind of software patents, since
10137software patents today do not serve the public's best interest.
10138Companies and individuals are using software patents to
10139legally extort from other companies and individuals. This is not in
10140the spirit of the original patent legislation and works against
10141all reasonable public interests.
10142
10143\chapter{GNAT Modified GPL}
10144\label{gmgpl}
10145
10146
10147\begin{quote}
10148This program is free software; you can redistribute it and/or
10149modify it under the terms of the GNU General Public License as
10150published by the Free Software Foundation; either version 2 of the
10151License, or (at your option) any later version.
10152
10153This program is distributed in the hope that it will be useful,
10154but WITHOUT ANY WARRANTY; without even the implied warranty of
10155MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10156General Public License for more details.
10157
10158You should have received a copy of the GNU General Public License
10159along with this program; if not, write to the Free Software
10160Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1016102111-1307, USA.
10162
10163As a special exception, if other files instantiate generics from
10164this unit, or you link this unit with other files to produce an
10165executable, this unit does not by itself cause the resulting
10166executable to be covered by the GNU General Public License. This
10167exception does not however invalidate any other reasons why the
10168executable file might be covered by the GNU Public License.
10169\end{quote}
10170
10171\chapter{GNU Public License}
10172\label{gpl}
10173
10174\section*{GNU GENERAL PUBLIC LICENSE Version 2, June 1991}
10175
10176\begin{quote}
10177Copyright (C) 1989, 1991 Free Software Foundation,
10178
10179Inc. 59 Temple Place, Suite 330, Boston,
10180
10181MA 02111-1307 USA
10182
10183Everyone is permitted to copy and distribute verbatim copies of this
10184license document, but changing it is not allowed.
10185\end{quote}
10186
10187\subsection*{Preamble}
10188
10189The licenses for most software are designed to take away your freedom
10190to share and change it. By contrast, the GNU General Public License
10191is intended to guarantee your freedom to share and change free software--to
10192make sure the software is free for all its users. This General Public
10193License applies to most of the Free Software Foundation's software
10194and to any other program whose authors commit to using it. (Some other
10195Free Software Foundation software is covered by the GNU Library General
10196Public License instead.) You can apply it to your programs, too.
10197
10198When we speak of free software, we are referring to freedom, not price.
10199Our General Public Licenses are designed to make sure that you have
10200the freedom to distribute copies of free software (and charge for
10201this service if you wish), that you receive source code or can get
10202it if you want it, that you can change the software or use pieces
10203of it in new free programs; and that you know you can do these things.
10204
10205To protect your rights, we need to make restrictions that forbid anyone
10206to deny you these rights or to ask you to surrender the rights. These
10207restrictions translate to certain responsibilities for you if you
10208distribute copies of the software, or if you modify it.
10209
10210For example, if you distribute copies of such a program, whether gratis
10211or for a fee, you must give the recipients all the rights that you
10212have. You must make sure that they, too, receive or can get the source
10213code. And you must show them these terms so they know their rights.
10214
10215We protect your rights with two steps:
10216
10217\begin{enumerate}
10218   \item copyright the software, and
10219   \item offer you this license which gives you legal permission to copy, distribute
10220      and/or modify the software.
10221\end{enumerate}
10222
10223Also, for each author's protection and ours, we want to make certain
10224that everyone understands that there is no warranty for this free
10225software. If the software is modified by someone else and passed on,
10226we want its recipients to know that what they have is not the original,
10227so that any problems introduced by others will not reflect on the
10228original authors' reputations.
10229
10230Finally, any free program is threatened constantly by software patents.
10231We wish to avoid the danger that redistributors of a free program
10232will individually obtain patent licenses, in effect making the program
10233proprietary. To prevent this, we have made it clear that any patent
10234must be licensed for everyone's free use or not licensed at all.
10235
10236The precise terms and conditions for copying, distribution and modification
10237follow.
10238
10239
10240\section*{GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
10241AND MODIFICATION}
10242
10243
10244\paragraph{0. This License applies to any program or other work which contains
10245a notice placed by the copyright holder saying it may be distributed
10246under the terms of this General Public License. The ``Program'',
10247below, refers to any such program or work, and a ``work based
10248on the Program'' means either the Program or any derivative
10249work under copyright law: that is to say, a work containing the Program
10250or a portion of it, either verbatim or with modifications and/or translated
10251into another language. (Hereinafter, translation is included without
10252limitation in the term ``modification''.) Each licensee
10253is addressed as ``you''.}
10254
10255
10256\paragraph{Activities other than copying, distribution and modification are
10257not covered by this License; they are outside its scope. The act of
10258running the Program is not restricted, and the output from the Program
10259is covered only if its contents constitute a work based on the Program
10260(independent of having been made by running the Program). Whether
10261that is true depends on what the Program does.}
10262
10263
10264\paragraph{1. You may copy and distribute verbatim copies of the Program's source
10265code as you receive it, in any medium, provided that you conspicuously
10266and appropriately publish on each copy an appropriate copyright notice
10267and disclaimer of warranty; keep intact all the notices that refer
10268to this License and to the absence of any warranty; and give any other
10269recipients of the Program a copy of this License along with the Program.}
10270
10271
10272\paragraph{You may charge a fee for the physical act of transferring a copy,
10273and you may at your option offer warranty protection in exchange for
10274a fee.}
10275
10276
10277\paragraph{2. You may modify your copy or copies of the Program or any portion
10278of it, thus forming a work based on the Program, and copy and distribute
10279such modifications or work under the terms of Section 1 above, provided
10280that you also meet all of these conditions:}
10281
10282
10283\subparagraph*{a) You must cause the modified files to carry prominent notices stating
10284that you changed the files and the date of any change.}
10285
10286
10287\subparagraph*{b) You must cause any work that you distribute or publish, that in
10288whole or in part contains or is derived from the Program or any part
10289thereof, to be licensed as a whole at no charge to all third parties
10290under the terms of this License.}
10291
10292
10293\subparagraph{c) If the modified program normally reads commands interactively
10294when run, you must cause it, when started running for such interactive
10295use in the most ordinary way, to print or display an announcement
10296including an appropriate copyright notice and a notice that there
10297is no warranty (or else, saying that you provide a warranty) and that
10298users may redistribute the program under these conditions, and telling
10299the user how to view a copy of this License. (Exception: if the Program
10300itself is interactive but does not normally print such an announcement,
10301your work based on the Program is not required to print an announcement.) }
10302
10303
10304\paragraph{These requirements apply to the modified work as a whole. If identifiable
10305sections of that work are not derived from the Program, and can be
10306reasonably considered independent and separate works in themselves,
10307then this License, and its terms, do not apply to those sections when
10308you distribute them as separate works. But when you distribute the
10309same sections as part of a whole which is a work based on the Program,
10310the distribution of the whole must be on the terms of this License,
10311whose permissions for other licensees extend to the entire whole,
10312and thus to each and every part regardless of who wrote it.}
10313
10314
10315\paragraph{Thus, it is not the intent of this section to claim rights or contest
10316your rights to work written entirely by you; rather, the intent is
10317to exercise the right to control the distribution of derivative or
10318collective works based on the Program.}
10319
10320
10321\paragraph{In addition, mere aggregation of another work not based on the Program
10322with the Program (or with a work based on the Program) on a volume
10323of a storage or distribution medium does not bring the other work
10324under the scope of this License.}
10325
10326
10327\paragraph*{3. You may copy and distribute the Program (or a work based on it,
10328under Section 2) in object code or executable form under the terms
10329of Sections 1 and 2 above provided that you also do one of the following:}
10330
10331
10332\subparagraph*{a) Accompany it with the complete corresponding machine-readable
10333source code, which must be distributed under the terms of Sections
103341 and 2 above on a medium customarily used for software interchange;
10335or,}
10336
10337
10338\subparagraph{b) Accompany it with a written offer, valid for at least three years,
10339to give any third party, for a charge no more than your cost of physically
10340performing source distribution, a complete machine-readable copy of
10341the corresponding source code, to be distributed under the terms of
10342Sections 1 and 2 above on a medium customarily used for software interchange;
10343or,}
10344
10345
10346\subparagraph{c) Accompany it with the information you received as to the offer
10347to distribute corresponding source code. (This alternative is allowed
10348only for noncommercial distribution and only if you received the program
10349in object code or executable form with such an offer, in accord with
10350Subsection b above.)}
10351
10352
10353\paragraph{The source code for a work means the preferred form of the work for
10354making modifications to it. For an executable work, complete source
10355code means all the source code for all modules it contains, plus any
10356associated interface definition files, plus the scripts used to control
10357compilation and installation of the executable. However, as a special
10358exception, the source code distributed need not include anything that
10359is normally distributed (in either source or binary form) with the
10360major components (compiler, kernel, and so on) of the operating system
10361on which the executable runs, unless that component itself accompanies
10362the executable.}
10363
10364
10365\paragraph{If distribution of executable or object code is made by offering
10366access to copy from a designated place, then offering equivalent access
10367to copy the source code from the same place counts as distribution
10368of the source code, even though third parties are not compelled to
10369copy the source along with the object code. ~4. You may not copy,
10370modify, sublicense, or distribute the Program except as expressly
10371provided under this License. Any attempt otherwise to copy, modify,
10372sublicense or distribute the Program is void, and will automatically
10373terminate your rights under this License. However, parties who have
10374received copies, or rights, from you under this License will not have
10375their licenses terminated so long as such parties remain in full compliance.}
10376
10377
10378\paragraph*{5. You are not required to accept this License, since you have not
10379signed it. However, nothing else grants you permission to modify or
10380distribute the Program or its derivative works. These actions are
10381prohibited by law if you do not accept this License. Therefore, by
10382modifying or distributing the Program (or any work based on the Program),
10383you indicate your acceptance of this License to do so, and all its
10384terms and conditions for copying, distributing or modifying the Program
10385or works based on it.}
10386
10387
10388\paragraph{6. Each time you redistribute the Program (or any work based on the
10389Program), the recipient automatically receives a license from the
10390original licensor to copy, distribute or modify the Program subject
10391to these terms and conditions. You may not impose any further restrictions
10392on the recipients' exercise of the rights granted herein. You are
10393not responsible for enforcing compliance by third parties to this
10394License.}
10395
10396
10397\paragraph{7. If, as a consequence of a court judgment or allegation of patent
10398infringement or for any other reason (not limited to patent issues),
10399conditions are imposed on you (whether by court order, agreement or
10400otherwise) that contradict the conditions of this License, they do
10401not excuse you from the conditions of this License. If you cannot
10402distribute so as to satisfy simultaneously your obligations under
10403this License and any other pertinent obligations, then as a consequence
10404you may not distribute the Program at all. For example, if a patent
10405license would not permit royalty-free redistribution of the Program
10406by all those who receive copies directly or indirectly through you,
10407then the only way you could satisfy both it and this License would
10408be to refrain entirely from distribution of the Program.}
10409
10410
10411\paragraph{If any portion of this section is held invalid or unenforceable under
10412any particular circumstance, the balance of the section is intended
10413to apply and the section as a whole is intended to apply in other
10414circumstances.}
10415
10416
10417\paragraph{It is not the purpose of this section to induce you to infringe any
10418patents or other property right claims or to contest validity of any
10419such claims; this section has the sole purpose of protecting the integrity
10420of the free software distribution system, which is implemented by
10421public license practices. Many people have made generous contributions
10422to the wide range of software distributed through that system in reliance
10423on consistent application of that system; it is up to the author/donor
10424to decide if he or she is willing to distribute software through any
10425other system and a licensee cannot impose that choice.}
10426
10427
10428\paragraph{This section is intended to make thoroughly clear what is believed
10429to be a consequence of the rest of this License. ~8. If the distribution
10430and/or use of the Program is restricted in certain countries either
10431by patents or by copyrighted interfaces, the original copyright holder
10432who places the Program under this License may add an explicit geographical
10433distribution limitation excluding those countries, so that distribution
10434is permitted only in or among countries not thus excluded. In such
10435case, this License incorporates the limitation as if written in the
10436body of this License.}
10437
10438
10439\paragraph{9. The Free Software Foundation may publish revised and/or new versions
10440of the General Public License from time to time. Such new versions
10441will be similar in spirit to the present version, but may differ in
10442detail to address new problems or concerns.}
10443
10444
10445\paragraph{Each version is given a distinguishing version number. If the Program
10446specifies a version number of this License which applies to it and
10447``any later version'', you have the option of following
10448the terms and conditions either of that version or of any later version
10449published by the Free Software Foundation. If the Program does not
10450specify a version number of this License, you may choose any version
10451ever published by the Free Software Foundation.}
10452
10453
10454\paragraph{10. If you wish to incorporate parts of the Program into other free
10455programs whose distribution conditions are different, write to the
10456author to ask for permission. For software which is copyrighted by
10457the Free Software Foundation, write to the Free Software Foundation;
10458we sometimes make exceptions for this. Our decision will be guided
10459by the two goals of preserving the free status of all derivatives
10460of our free software and of promoting the sharing and reuse of software
10461generally.}
10462
10463
10464\subsection*{NO WARRANTY}
10465
10466
10467\paragraph{11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
10468FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
10469WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
10470PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY
10471OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED
10472TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
10473PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
10474PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
10475THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.}
10476
10477
10478\paragraph{12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
10479WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
10480AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
10481FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
10482DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING
10483BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
10484OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
10485TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
10486PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.}
10487
10488
10489\paragraph{END OF TERMS AND CONDITIONS}
10490
10491
10492
10493\chapter{Credits}
10494
10495This appendix documents the contributors to the ``APQ Binding''
10496that are separate from the PostgreSQL project.
10497
10498
10499\section*{Authors}
10500
10501\begin{itemize}
10502\item Warren W. Gay VE3WWG
10503	\begin{itemize}
10504		\item 29 Glen Park Road, St. Catharines, Ontario
10505		\item Canada L2N 3E3
10506		\item ve3wwg@cogeco.ca
10507	\end{itemize}
10508	\item Marcelo Cora\c ca de Freitas <marcelo@kow.com.br>
10509	\item Daniel Norte de Moraes <danielcheagle@gmail.com>
10510\end{itemize}
10511
10512
10513\section*{Contributions}
10514
10515\subsection*{Source Code Modifications}
10516
10517Some people has contributed to the 3.0 release:
10518\begin{itemize}
10519	\item Alex Abate Biral <abiral@ydeasolutions.com.br>
10520		\begin{itemize}
10521			\item Most notably implemented the ODBC support which is not yet complete
10522		\end{itemize}
10523\end{itemize}
10524
10525\subsection*{Bug Reports}
10526
10527\begin{itemize}
10528\item There appears to be a problem with win32 releases using PostgreSQL
105297.2.1, where specifying the database server by IP \# creates a problem.
10530The problem is believed to be in libpq.dll. (September 22, 2004: this
10531problem is believed to be fixed in more current releases of PostgreSQL).
10532\item Jeffrey R. Carter, Chief Software Engineer from Singo Solution, Inc.,
10533who contributed with bug fixes in 2007 for the apq-postgresql module.
10534\end{itemize}
10535
10536
10537\subsection*{Bug Report/Fix Contributions}
10538
10539\begin{itemize}
10540\item Charles Darcy <charlie@mullum.com.au>, November 23, 2002
10541\item Jesse Lang <jesse@solidrockdata.com>, March 2008
10542\end{itemize}
10543
10544\chapter{History}
10545
10546
10547\section*{APQ 1.0}
10548
10549First released August 3, 2002, under the Ada Community License (ACL).
10550
10551
10552\section*{APQ 1.1}
10553
10554Second release August 4, 2002, but under the dual ACL and GPL2%
10555\footnote{GNU Public License 2%
10556} license. This license change was suggested by Florian Weimer.
10557
10558
10559\section*{APQ 1.2}
10560
10561\begin{itemize}
10562   \item Added function End\_Of\_Blob to streamline sequential processing.
10563   \item Added buffered blob I/O for higher performance.
10564   \item Added procedure Blob\_Flush to force unwritten blob data to the database
10565         server.
10566   \item Blob\_Create has new optional Buf\_Size argument.
10567   \item Blob\_Open has new optional Buf\_Size argument.
10568   \item Fixed Blob\_Create to release the created blob, if the blob cannot
10569         be opened. This most often happens when the caller is attempting to
10570         create a blob, outside of a transaction.
10571\end{itemize}
10572
10573\section*{APQ 1.3}
10574
10575\begin{itemize}
10576   \item Removed some debug Put\_Line statements that should have been removed
10577         in 1.2.
10578   \item Added a few pragma Inline statements to the spec PostgreSQL.Client
10579\end{itemize}
10580
10581\section*{APQ 1.4}
10582
10583\begin{itemize}
10584   \item Added Generic\_Command\_Oid for strong PG\_Oid type use
10585   \item Added Generic\_Blob\_Open for strong PG\_Oid type use
10586   \item Added Generic\_Blob\_Oid function for strong PG\_Oid type use
10587   \item Added Generic\_Blob\_Unlink for strong PG\_Oid type use
10588   \item Added Generic\_Blob\_Import and Generic\_Blob\_Export for strong PG\_Oid
10589         type use
10590\end{itemize}
10591
10592\section*{APQ 1.5}
10593
10594\begin{itemize}
10595   \item Bug fix: Append\_Time, Append\_Date and Append\_Timestamp now emit
10596         the surrounding single quote characters around the value to satisfy
10597         the SQL syntax required by the database server.
10598   \item Troubleshooting help added to this manual for {}``Missing Time Data
10599         (Or Time is 00:00:00)''.
10600\end{itemize}
10601
10602\section*{APQ 1.6}
10603
10604\begin{itemize}
10605   \item Added Set\_Rollback\_On\_Finalize controlling primitive for Connection\_Type.
10606   \item Added Will\_Rollback\_On\_Finalize function for Connection\_Type for
10607         inquiry.
10608   \item Expanded manual and added transaction problem help to the Troubleshooting
10609         chapter.
10610\end{itemize}
10611
10612\section*{APQ 1.7}
10613
10614\begin{itemize}
10615   \item Open\_DB\_Trace and Close\_DB\_Trace procedures added.
10616   \item Set\_Trace procedure added to enable and disable tracing.
10617   \item Is\_Trace function added to query the tracing state.
10618\end{itemize}
10619
10620\section*{APQ 1.8}
10621
10622\begin{itemize}
10623   \item Connection information functions like Host\_Name and Port were added.
10624   \item A connection cloning primitive was added.
10625\end{itemize}
10626
10627\section*{APQ 1.9}
10628
10629\begin{itemize}
10630   \item A compiler work-around was provided. Some versions of GNAT would not
10631         compile the APQ source code, because certain instantiations of Ada.Text\_IO.Integer\_IO
10632         were producing duplicate symbol errors in the assembler phase of the
10633         compile. This problem was absent in gnat 3.13p compiles, but have
10634         shown up in gcc-3.1.1 and probably in gnat 3.14p and later releases.
10635         The instantiation names INTIO were made unique within the source code
10636         to avoid this problem.
10637\end{itemize}
10638
10639\section*{APQ 1.91}
10640
10641\begin{itemize}
10642   \item The PostgreSQL Connect call now performs an automatic {}``SET DATESTYLE
10643         TO ISO'' command prior to returning from a successful connect. This
10644         is necessary to guarantee that ISO date format is returned from the
10645         database engine and recognized from the engine. This guarantees that
10646         APQ correctly handles dates, even when the user has specified a PGDATESTYLE
10647         environment variable value that is different than ISO.
10648         \item Fixed bug in Host\_Name function. It was returning a null string when
10649         a host name was set in the Connection\_Type object.
10650   \item Win32 apq-1.91 source release (subdirectory win32) and apq-1.91-win32-2.7.1
10651         binary release created.
10652\end{itemize}
10653
10654\section*{APQ 1.92}
10655
10656\begin{itemize}
10657   \item Fixed bug for floating point and fixed point types (was rounding the
10658         value to the nearest integer, due to the fact that the Ada.Text\_IO.Float\_IO.Put
10659         call was receiving the argument Aft => 0). Omitting the Aft parameter
10660         causes the value to be formatted as required for the SQL floating/fixed
10661         point type. The bug was reported by Charles Darcy <charlie@mullum.com.au>.
10662\end{itemize}
10663
10664\section*{APQ 1.93}
10665
10666\begin{itemize}
10667   \item Modified the Ada2005 package hierarchy to insert a top level package
10668         named APQ. Hence package PostgreSQL now becomes APQ.PostgreSQL. This
10669         is an interim release, which will pave the way to future support of
10670         other database products such as MySQL.
10671\end{itemize}
10672
10673\section*{APQ 2.0}
10674
10675\begin{itemize}
10676   \item MySQL support added. This was made possible by the package restructuring
10677         done in the interim release APQ 1.93.
10678   \item Generic database programming support added. Special generic services
10679         like Engine\_Of, New\_Query etc. were added to make this possible.
10680         A heavy reliance is made upon object inheritance and polymorphism
10681         to make this work.
10682   \item A new example subdirectory eg2 was added. The programs in this subdirectory
10683         show the original example program, but done in a database generic
10684         way. The test program can be compiled and run for both PostgreSQL
10685         and MySQL databases.
10686   \item PG\_Oid is now named APQ\_Row\_ID and is 64 bits unsigned integer.
10687   \item Null\_Oid() function added for generic database support (and much
10688         more).
10689   \item Engine\_Of() function added for generic database support.
10690   \item Exception {}``Failed'' was added to handle some general failures.
10691   \item Fetch\_Mode() and Set\_Fetch\_Mode() were added to accommodate MySQL
10692         limitations.
10693   \item Documentation went through some restructuring to accomodate two databases,
10694         and their differences.
10695\end{itemize}
10696
10697\section*{APQ 2.1}
10698
10699\begin{itemize}
10700   \item This was the win32 port.
10701   \item See win32.pdf for instructions for building APQ on a win32 platform.
10702   \item win32\_test.adb program was added to the distribution to allow testing
10703         of APQ in the windows environment.
10704\end{itemize}
10705
10706\section*{APQ 2.2}
10707
10708\begin{itemize}
10709   \item PostgreSQL now defaults to Set\_Port(C,5432), which is an TCP/IP connection
10710         for port 5432.
10711   \item APQ now uses Ada.Exceptions.Raise\_Exception in many places to provide
10712         more information. For example if a Value() function raises a Constraint\_Error,
10713         it now indicates in the message which column \# the error occurred
10714         for (where Value takes a Column\_Index\_Type argument). The informative
10715         message makes it easier to debug a new APQ application.
10716   \item Documentation added for Set\_Port for UNIX socket connections.
10717   \item The primitives Begin\_Work, Commit\_Work and Rollback\_Work now include
10718         an implicit call to Clear before and after the Query\_Type's object's
10719         use. This is necessary in some cases to clean up results and to put
10720         the object into the right state (Sybase made this necessary). The
10721         fetch mode of the Query\_Type object is preserved, even though it
10722         may be changed to something else while being used.
10723   \item The Set\_DB\_Name now works differently for PostgreSQL, if the connection
10724         has already been established. In the past, APQ (for PostgreSQL) simply
10725         took note of the new database name, but did nothing with it. This
10726         was inconsitent behavior compared to the fact that APQ\-.MySQL\-.Client\-.Set\_DB\_Name()
10727         would make a database switch on the connected connection. Now this
10728         behaviour is harmonized, by having the PostgreSQL version perform
10729         a hidden {}``USE <database>'' SQL query to make it happen.
10730   \item When a APQ\-.MySQL\-.Set\_DB\_Name(C) fails on a connected C, the exception
10731         raised is now APQ.Use\_Error instead of APQ.Failed. This helps to
10732         distinguish the difference between a successful connection and failed
10733         database change.
10734   \item Sybase always connects to the server's configured default database
10735         for the user. To make APQ.Sybase consistent with other supported databases,
10736         any Set\_DB\_Name(C) on connection C prior to the connection, now
10737         queues up a ``USE <database>'' query to be performed, once the
10738         connection is successful (effectively making it appear the same in
10739         APQ). Any call to Set\_DB\_Name(C) while C is connected, will result
10740         in another ``USE <database>'' SQL query being performed behind
10741         the scenes.
10742   \item Fixed bug in APQ\-.MySQL\-.Client\-.Reset so that the Connection\_Type object
10743         was properly reset for re-use.
10744   \item APQ.Sybase.Client support was added
10745   \item Set\_Instance and Instance functions were added to permit specification
10746         of Sybase instances.
10747   \item Fetch modes Cursor\_For\_Update and Cursor\_For\_Read\_Only were added
10748         for Sybase cursor support.
10749   \item Function Cursor\_Name was added for Sybase cursor support.
10750   \item Functions Set\_Case and Case were added to deal with Sybase's case
10751         sensitivity for database agnostic code.
10752   \item Fixed MySQL encoding of APQ\_Boolean types. Now sends 1 or 0, for
10753         True or False respectively (MySQL uses bit or tinyint to represent
10754         boolean values).
10755   \item Fixed MySQL decoding of date/time types (MySQL provides YYYYMMDDHHMMSS
10756         instead of YYYY-MM-DD HH:MM:SS, which APQ expected).
10757   \item APQ.PostgreSQL.Client.Value now trims trailing blanks returned for
10758         string values. This helps the returned values to be consistent across
10759         all database vendor products (MySQL always trims the trailing blanks).
10760\end{itemize}
10761
10762\section*{APQ 3.0}
10763\begin{itemize}
10764	\item New build system.
10765	\item GPR file support
10766	\item APQ was divided into sub projects:
10767		\begin{itemize}
10768			\item \textbf{apq} the core APQ classes
10769			\item \textbf{apq-ct\_lib} ct\_lib backend support (MySQL Server and Sybase)
10770			\item \textbf{apq-mysql} MySQL backend support
10771			\item \textbf{apq-odbc} ODBC support
10772			\item \textbf{apq-postgresql} PostgreSQL backend support
10773		\end{itemize}
10774	\item Microsoft SQL Server and ODBC Support
10775	\item Can be built with FreeTDS and Sybase's ct\_lib
10776	\item New single license in favour of the old dual-license
10777	\item some bug fixes
10778\end{itemize}
10779
10780\section*{APQ 3.1}
10781
10782\begin{itemize}
10783	\item Some minor PostgreSQL bug fixes
10784	\item Support to PostgreSQL SSL connections
10785\end{itemize}
10786
10787\section*{APQ 3.2}
10788
10789\begin{itemize}
10790	\item Moved on to gprbuild
10791	\item Removed Pragma Linker\_Options from the code
10792	\item APQ\_Timestamp in UTC
10793	\item Support Ada2005's Ada.Calendar.Time\_Zones package
10794\end{itemize}
10795
10796
10797\printindex
10798\end{document}
10799