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