a75f2d21a8
of Norm's Modular Style Sheets and jade/docbook. From Vince Vielhaber <vev@michvhf.com>.
927 lines
23 KiB
Text
927 lines
23 KiB
Text
<Chapter Id="ecpg">
|
||
<DocInfo>
|
||
<AuthorGroup>
|
||
<Author>
|
||
<FirstName>Linux</FirstName>
|
||
<Surname>Tolke</Surname>
|
||
</Author>
|
||
<Author>
|
||
<FirstName>Michael</FirstName>
|
||
<Surname>Meskes</Surname>
|
||
</Author>
|
||
</AuthorGroup>
|
||
<Copyright>
|
||
<Year>1996-1997</Year>
|
||
<Holder>Linus Tolke</Holder>
|
||
</Copyright>
|
||
<Copyright>
|
||
<Year>1998</Year>
|
||
<Holder>Michael Meskes</Holder>
|
||
</Copyright>
|
||
<Date>Transcribed 1998-02-12</Date>
|
||
</DocInfo>
|
||
|
||
<Title><Application>ecpg</Application> - Embedded <Acronym>SQL</Acronym>
|
||
in <Acronym>C</Acronym></Title>
|
||
|
||
<Para>
|
||
This describes an embedded <Acronym>SQL</Acronym> in <Acronym>C</Acronym>
|
||
package for <ProductName>Postgres</ProductName>.
|
||
|
||
It is written by <ULink url="mailto:linus@epact.se">Linus Tolke</ULink>
|
||
and <ULink url="mailto:meskes@debian.org">Michael Meskes</ULink>.
|
||
|
||
<Note>
|
||
<Para>
|
||
Permission is granted to copy and use in the same way as you are allowed
|
||
to copy and use the rest of the <ProductName>PostgreSQL</ProductName>.
|
||
</Para>
|
||
</Note>
|
||
</para>
|
||
<Sect1>
|
||
<Title>Why Embedded <Acronym>SQL</Acronym>?</Title>
|
||
|
||
<Para>
|
||
Embedded <Acronym>SQL</Acronym> has some small advantages over other ways
|
||
to handle <Acronym>SQL</Acronym>
|
||
queries. It takes care of all the tedious moving of information to and
|
||
from variables in your <Acronym>C</Acronym> program.
|
||
Many <Acronym>RDBMS</Acronym> packages
|
||
support this embedded language.
|
||
</Para>
|
||
|
||
<Para> There is an ANSI-standard describing how the embedded language should
|
||
work. <Application>ecpg</Application> was designed to meet this standard
|
||
as much as possible. So it is
|
||
possible to port programs with embedded <Acronym>SQL</Acronym> written for
|
||
other <Acronym>RDBMS</Acronym> packages to
|
||
<ProductName>Postgres</ProductName> and thus promoting the spirit of free
|
||
software.
|
||
</Para>
|
||
</sect1>
|
||
<Sect1>
|
||
<Title>The Concept</Title>
|
||
|
||
<Para>
|
||
You write your program in <Acronym>C</Acronym> with some
|
||
special <Acronym>SQL</Acronym> things.
|
||
For declaring variables that can be used in
|
||
<Acronym>SQL</Acronym> statements you need to
|
||
put them in a special declare section.
|
||
You use a special syntax for the <Acronym>SQL</Acronym> queries.
|
||
</Para>
|
||
|
||
<Para>
|
||
Before compiling you run the file through
|
||
the embedded <Acronym>SQL</Acronym> <Acronym>C</Acronym>
|
||
preprocessor and it converts the <Acronym>SQL</Acronym> statements you used
|
||
to function
|
||
calls with the variables used as arguments. Both variables that are used
|
||
as input to the <Acronym>SQL</Acronym> statements and variables that will
|
||
contain the
|
||
result are passed.
|
||
</Para>
|
||
|
||
<Para>
|
||
Then you compile and at link time you link with a special library that
|
||
contains the functions used. These functions (actually it is mostly one
|
||
single function) fetches the information from the arguments, performs
|
||
the <Acronym>SQL</Acronym> query using the ordinary interface
|
||
(<FileName>libpq</FileName>) and puts back
|
||
the result in the arguments dedicated for output.
|
||
</Para>
|
||
|
||
<Para>
|
||
Then you run your program and when the control arrives to
|
||
the <Acronym>SQL</Acronym>
|
||
statement the <Acronym>SQL</Acronym> statement is performed against
|
||
the database and you
|
||
can continue with the result.
|
||
</Para>
|
||
</sect1>
|
||
|
||
<Sect1>
|
||
<Title>How To Use <Application>egpc</Application></Title>
|
||
|
||
<Para>
|
||
This section describes how to use the <Application>egpc</Application> tool.
|
||
</Para>
|
||
|
||
<Sect2>
|
||
<Title>Preprocessor</title>
|
||
|
||
<Para>
|
||
The preprocessor is called <Application>ecpg</Application>.
|
||
After installation it resides in
|
||
the <ProductName>Postgres</ProductName> <FileName>bin/</FileName> directory.
|
||
</Para>
|
||
</sect2>
|
||
<Sect2>
|
||
<Title>Library</title>
|
||
|
||
<Para>
|
||
The <Application>ecpg</Application> library is called
|
||
<FileName>libecpg.a</FileName> or
|
||
<FileName>libecpg.so</FileName>. Additionally, the library
|
||
uses the <FileName>libpq</FileName> library for communication to the
|
||
<ProductName>Postgres</ProductName> server so you will
|
||
have to link your program with <Parameter>-lecpg -lpq</Parameter>.
|
||
</Para>
|
||
|
||
<Para>
|
||
The library has some methods that are "hidden" but that could prove very
|
||
useful sometime.
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<function>ECPGdebug(int <replaceable class="parameter">on</replaceable>, FILE *<replaceable class="parameter">stream</replaceable>)</function>
|
||
turns on debug logging if called with the first argument non-zero.
|
||
Debug logging is done on <replaceable class="parameter">stream</replaceable>.
|
||
Most <Acronym>SQL</Acronym> statement logs its arguments and result.
|
||
</Para>
|
||
|
||
<Para>
|
||
The most important one (<Function>ECPGdo</Function>)
|
||
that is called on all <Acronym>SQL</Acronym>
|
||
statements except <Command>EXEC SQL COMMIT</Command>,
|
||
<Command>EXEC SQL ROLLBACK</Command>,
|
||
<Command>EXEC SQL CONNECT</Command> logs both its expanded string,
|
||
i.e. the string
|
||
with all the input variables inserted, and the result from the
|
||
<ProductName>Postgres</ProductName> server.
|
||
This can be very useful when searching for errors
|
||
in your <Acronym>SQL</Acronym> statements.
|
||
</Para>
|
||
</ListItem>
|
||
|
||
<listitem>
|
||
<para>
|
||
<function>ECPGstatus()</function>
|
||
This method returns TRUE if we are connected to a database and FALSE if not.
|
||
</Para>
|
||
</ListItem>
|
||
</itemizedlist>
|
||
</Para>
|
||
</sect2>
|
||
|
||
<Sect2>
|
||
<Title>Error handling</title>
|
||
|
||
<Para>
|
||
To be able to detect errors from the <ProductName>Postgres</ProductName>
|
||
server you include a line like
|
||
<ProgramListing>
|
||
exec sql include sqlca;
|
||
</ProgramListing>
|
||
in the include section of your file. This will define a struct and a
|
||
variable with the name <Parameter>sqlca</Parameter> as following:
|
||
<ProgramListing>
|
||
struct sqlca {
|
||
int sqlcode;
|
||
struct {
|
||
int sqlerrml;
|
||
char sqlerrmc[1000];
|
||
} sqlerrm;
|
||
} sqlca;
|
||
</ProgramListing>
|
||
</Para>
|
||
|
||
<Para>
|
||
If an error occured in the last <Acronym>SQL</Acronym> statement
|
||
then <Parameter>sqlca.sqlcode</Parameter>
|
||
will be non-zero. If <Parameter>sqlca.sqlcode</Parameter> is less that 0
|
||
then this is
|
||
some kind of serious error, like the database definition does not match
|
||
the query given. If it is bigger than 0 then this is a normal error like
|
||
the table did not contain the requested row.
|
||
</Para>
|
||
|
||
<Para>
|
||
sqlca.sqlerrm.sqlerrmc will contain a string that describes the error.
|
||
The string ends with <Quote>line 23.</Quote> where the line is the line number
|
||
in the source file (actually the file generated by the preprocessor but
|
||
I hope I can fix this to be the line number in the input file.)
|
||
</Para>
|
||
|
||
<Para>
|
||
List of errors that can occur:
|
||
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term>-1, Unsupported type %s on line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Does not normally occur. This is a sign that the preprocessor has
|
||
generated something that the library does not know about. Perhaps you
|
||
are running incompatible versions of the preprocessor and the library.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Too many arguments line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
The preprocessor has goofed up and generated some incorrect code.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Too few arguments line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
The preprocessor has goofed up and generated some incorrect code.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Error starting transaction line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
<ProductName>Postgres</ProductName> signalled to us that we cannot open
|
||
the connection.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Postgres error: %s line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Some <ProductName>Postgres</ProductName> error.
|
||
The message contains the error message from the
|
||
<ProductName>Postgres</ProductName> backend.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>1, Data not found line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This is a "normal" error that tells you that what you are quering cannot
|
||
be found or we have gone through the cursor.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, To many matches line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that the query has returned several lines.
|
||
The <Command>SELECT</Command> you made probably was not unique.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Not correctly formatted int type: %s line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that the host variable is of an <Type>int</Type> type and the field
|
||
in the <ProductName>Postgres</ProductName> database is of another type and
|
||
contains a value that cannot be interpreted as an <Type>int</Type>.
|
||
The library uses <Function>strtol</Function>
|
||
for this conversion.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Not correctly formatted unsigned type: %s line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that the host variable is of an <Type>unsigned int</Type> type and
|
||
the field in the <ProductName>Postgres</ProductName> database is of another
|
||
type and contains a
|
||
value that cannot be interpreted as an <Type>unsigned int</Type>. The library
|
||
uses <Function>strtoul</Function> for this conversion.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Not correctly formatted floating point type: %s line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that the host variable is of an <Type>float</Type> type and
|
||
the field in the <ProductName>Postgres</ProductName> database is of another
|
||
type and contains a
|
||
value that cannot be interpreted as an <Type>float</Type>. The library
|
||
uses <Function>strtod</Function> for this conversion.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Too few arguments line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that <ProductName>Postgres</ProductName> has returned more records
|
||
than we have
|
||
matching variables. Perhaps you have forgotten a couple of the host
|
||
variables in the <Command>INTO :var1,:var2</Command>-list.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Too many arguments line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that <ProductName>Postgres</ProductName> has returned fewer records
|
||
than we have
|
||
host variables. Perhaps you have to many host variables in the
|
||
<Command>INTO :var1,:var2</Command>-list.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Empty query line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
<ProductName>Postgres</ProductName> returned PGRES_EMPTY_QUERY.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Error: %s line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This means that <ProductName>Postgres</ProductName> returned on of the errors
|
||
PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR or PGRES_BAD_RESPONSE. Which one
|
||
and why is explained in the message.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Postgres error line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
<ProductName>Postgres</ProductName> returns something that the library does
|
||
not know how to
|
||
handle. This is probably because the version of
|
||
<ProductName>Postgres</ProductName> does not
|
||
match the version of the <Application>ecpg</Application> library.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Error committing line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Error during <Command>COMMIT</Command>. <Command>EXEC SQL COMMIT</Command>
|
||
is translated to an
|
||
<Command>end</Command> operation in <ProductName>Postgres</ProductName>
|
||
and that is the operation that could
|
||
not be performed.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, Error rolling back line %d.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Error during <Command>ROLLBACK</Command>.
|
||
<Command>EXEC SQL ROLLBACK</Command> is translated to
|
||
an <Command>abort</Command> operation in <ProductName>Postgres</ProductName>
|
||
and that is the operation that
|
||
could not be performed.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>-1, ECPGconnect: could not open database %s.</Term>
|
||
<ListItem>
|
||
<Para>
|
||
The connect to the database did not work.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
</Sect2>
|
||
</sect1>
|
||
|
||
<Sect1>
|
||
<Title>Limitations</Title>
|
||
|
||
<Para>
|
||
What will never be included and why or what cannot be done with this
|
||
concept.
|
||
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term>oracles single tasking possibility</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Oracle version 7.0 on AIX 3 uses the OS-supported locks on the shared
|
||
memory segments and allows the application designer to link an
|
||
application in a so called single tasking way. Instead of starting one
|
||
client process per application process both the database part and the
|
||
application part is run in the same process. In later versions of oracle
|
||
this is no longer supported.
|
||
</Para>
|
||
|
||
<Para>
|
||
This would require a total redesign of the <ProductName>Postgres</ProductName> access model and
|
||
that effort can not justify the performance gained.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
</sect1>
|
||
|
||
<Sect1>
|
||
<Title>Porting From Other <Acronym>RDBMS</Acronym> Packages</Title>
|
||
|
||
<Para>
|
||
To be written by someone who knows the different
|
||
<Acronym>RDBMS</Acronym> packages and who
|
||
actually does port something...
|
||
</Para>
|
||
</sect1>
|
||
|
||
<Sect1>
|
||
<Title>Installation</Title>
|
||
|
||
<Para>
|
||
Since version 0.5 <Application>ecpg</Application> is distributed
|
||
together with <ProductName>Postgres</ProductName>. So you
|
||
should get your precompiler, libraries and header files compiled and
|
||
installed by default as a part of your installation.
|
||
</Para>
|
||
</sect1>
|
||
|
||
<Sect1>
|
||
<Title>For the Developer</Title>
|
||
|
||
<Para>
|
||
This section is for those who want to develop the
|
||
<Application>ecpg</Application> interface. It
|
||
describes how the things work. The ambition is to make this section
|
||
contain things for those that want to have a look inside and the section
|
||
on How to use it should be enough for all normal questions.
|
||
|
||
So, read this before looking at the internals of the
|
||
<Application>ecpg</Application>. If
|
||
you are not interested in how it really works, skip this section.
|
||
</Para>
|
||
|
||
<Sect2>
|
||
<Title>ToDo List</Title>
|
||
|
||
<Para>
|
||
This version the preprocessor has some flaws:
|
||
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term>no restriction to strings only</Term>
|
||
<ListItem>
|
||
<Para>
|
||
The PQ interface, and most of all the PQexec function, that is used by
|
||
the <Application>ecpg</Application> relies on that the request is built
|
||
up as a string. In some
|
||
cases, like when the data contains the null character, this will be a
|
||
serious problem.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>error codes</Term>
|
||
<ListItem>
|
||
<Para>
|
||
There should be different error numbers for the different errors instead
|
||
of just -1 for them all.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>library functions</Term>
|
||
<ListItem>
|
||
<Para>
|
||
to_date et al.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>records</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Records or structures have to be defined in the declare section.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>missing statements</Term>
|
||
<ListItem>
|
||
<Para>
|
||
The following statements are not implemented thus far:
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term> exec sql type</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term> exec sql prepare</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term> exec sql allocate</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term> exec sql free</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term> exec sql whenever sqlwarning</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term> SQLSTATE</Term>
|
||
<ListItem>
|
||
<Para>
|
||
</Para>
|
||
</listitem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>message <20>no data found<6E></Term>
|
||
<ListItem>
|
||
<Para>
|
||
The error message for "no data" in an exec sql insert select from statement
|
||
has to be 100.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>sqlwanr[6]</Term>
|
||
<ListItem>
|
||
<Para>
|
||
sqlwarn[6] should be 'W' if the PRECISION or SCALE value specified in a SET
|
||
DESCRIPTOR statement will be ignored.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
<VarListEntry>
|
||
<Term>conversion of scripts</Term>
|
||
<ListItem>
|
||
<Para>
|
||
To set up a database you need a few scripts with table definitions and
|
||
other configuration parameters. If you have these scripts for an old
|
||
database you would like to just apply them to get a
|
||
<ProductName>Postgres</ProductName> database that works in the same way.
|
||
</Para>
|
||
|
||
<Para>
|
||
To set up a database you need a few scripts with table definitions and
|
||
The functionality could be accomplished with some conversion scripts.
|
||
Speed will never be accomplished in this way. To do this you need a
|
||
bigger insight in the database construction and the use of the database
|
||
than could be realised in a script.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
</sect2>
|
||
|
||
<Sect2>
|
||
<Title>The Preprocessor</Title>
|
||
|
||
<Para>
|
||
First four lines are written to the output. Two comments and two include
|
||
lines necessary for the interface to the library.
|
||
</Para>
|
||
|
||
<Para>
|
||
Then the preprocessor works in one pass only reading the input file and
|
||
writing to the output as it goes along. Normally it just echoes
|
||
everything to the output without looking at it further.
|
||
</Para>
|
||
|
||
<Para>
|
||
When it comes to an <Command>EXEC SQL</Command> statements it interviens and
|
||
changes them depending on what iit is.
|
||
The <Command>EXEC SQL</Command> statement can be one of these:
|
||
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term>Declare sections</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Declare sections begins with
|
||
<ProgramListing>
|
||
exec sql begin declare section;
|
||
</ProgramListing>
|
||
and ends with
|
||
<ProgramListing>
|
||
exec sql end declare section;
|
||
</ProgramListing>
|
||
In the section only variable declarations are allowed. Every variable
|
||
declare within this section is also entered in a list of variables
|
||
indexed on their name together with the corresponding type.
|
||
</Para>
|
||
|
||
<Para>
|
||
The declaration is echoed to the file to make the variable a normal
|
||
C-variable also.
|
||
</Para>
|
||
|
||
<Para>
|
||
The special types VARCHAR and VARCHAR2 are converted into a named struct
|
||
for every variable. A declaration like:
|
||
<ProgramListing>
|
||
VARCHAR var[180];
|
||
</ProgramListing>
|
||
is converted into
|
||
<ProgramListing>
|
||
struct varchar_var { int len; char arr[180]; } var;
|
||
</ProgramListing>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Include statements</Term>
|
||
<ListItem>
|
||
<Para>
|
||
An include statement looks like:
|
||
<ProgramListing>
|
||
exec sql include filename;
|
||
</ProgramListing>
|
||
It is converted into
|
||
<ProgramListing>
|
||
#include <filename.h>
|
||
</ProgramListing>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Connect statement</Term>
|
||
<ListItem>
|
||
<Para>
|
||
A connect statement looks like:
|
||
<ProgramListing>
|
||
exec sql connect '<Replaceable>database</Replaceable>';
|
||
</ProgramListing>
|
||
That statement is converted into
|
||
<ProgramListing>
|
||
ECPGconnect("<Replaceable>database</Replaceable>");
|
||
</ProgramListing>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Open cursor statement</Term>
|
||
<ListItem>
|
||
<Para>
|
||
An open cursor statement looks like:
|
||
<ProgramListing>
|
||
exec sql open <Replaceable>cursor</Replaceable>;
|
||
</ProgramListing>
|
||
and is ignore and not copied from the output.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Commit statement</Term>
|
||
<ListItem>
|
||
<Para>
|
||
A commit statement looks like
|
||
<ProgramListing>
|
||
exec sql commit;
|
||
</ProgramListing>
|
||
and is translated on the output to
|
||
<ProgramListing>
|
||
ECPGcommit(__LINE__);
|
||
</ProgramListing>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Rollback statement</Term>
|
||
<ListItem>
|
||
<Para>
|
||
A rollback statement looks like
|
||
<ProgramListing>
|
||
exec sql rollback;
|
||
</ProgramListing>
|
||
and is translated on the output to
|
||
<ProgramListing>
|
||
ECPGrollback(__LINE__);
|
||
</ProgramListing>
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Other statements</Term>
|
||
<ListItem>
|
||
<Para>
|
||
Other <Acronym>SQL</Acronym> statements are other statements that start with
|
||
<Command>exec sql</Command> and ends with <Command>;</Command>.
|
||
Everything inbetween is treated
|
||
as an <Acronym>SQL</Acronym> statement and parsed for variable substitution.
|
||
</Para>
|
||
|
||
<Para>
|
||
Variable substitution occur when a symbol starts with a colon
|
||
(<Command>:</Command>).
|
||
Then a variable with that name is found among the variables
|
||
that were previously declared within a declare section and depending on
|
||
whether or not the <Acronym>SQL</Acronym> statements knows it to be
|
||
a variable for input or
|
||
output the pointers to the variables are written to the output to allow
|
||
for access by the function.
|
||
</Para>
|
||
|
||
<Para>
|
||
For every variable that is part of the <Acronym>SQL</Acronym> request
|
||
the function gets another five arguments:
|
||
|
||
<SimpleList>
|
||
<Member>The type as a special symbol</Member>
|
||
<Member>A pointer to the value</Member>
|
||
<Member>The size of the variable if it is a varchar</Member>
|
||
<Member>Number of elements in the array (for array fetches)</Member>
|
||
<Member>The offset to the next element in the array (for array fetches)</Member>
|
||
</SimpleList>
|
||
</Para>
|
||
|
||
<Para>
|
||
Since the array fetches are not implemented yet the two last arguments
|
||
are not really important. They could perhaps have been left out.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
</Sect2>
|
||
|
||
<Sect2>
|
||
<Title>A Complete Example</Title>
|
||
|
||
<Para>
|
||
Here is a complete example describing the output of the preprocessor:
|
||
<ProgramListing>
|
||
exec sql begin declare section;
|
||
int index;
|
||
int result;
|
||
exec sql end declare section;
|
||
...
|
||
exec sql select res into :result from mytable where index = :index;
|
||
</ProgramListing>
|
||
is translated into:
|
||
<ProgramListing>
|
||
/* These two include files are added by the preprocessor */
|
||
#include <ecpgtype.h>
|
||
#include <ecpglib.h>
|
||
/* exec sql begin declare section */
|
||
|
||
int index;
|
||
int result;
|
||
/* exec sql end declare section */
|
||
|
||
...
|
||
ECPGdo(__LINE__, "select res from mytable where index = ;;",
|
||
ECPGt_int,&index,0,0,sizeof(int),
|
||
ECPGt_EOIT,
|
||
ECPGt_int,&result,0,0,sizeof(int),
|
||
ECPGt_EORT );
|
||
</ProgramListing>
|
||
(the indentation in this manual is added for readability and not
|
||
something that the preprocessor can do.)
|
||
</Para>
|
||
</sect2>
|
||
|
||
<Sect2>
|
||
<Title>The Library</Title>
|
||
|
||
<Para>
|
||
The most important function in the library is the <Function>ECPGdo</Function>
|
||
function. It takes a variable amount of arguments. Hopefully we wont run
|
||
into machines with limits on the amount of variables that can be
|
||
accepted by a varchar function. This could easily add up to 50 or so
|
||
arguments.
|
||
</Para>
|
||
|
||
<Para>
|
||
The arguments are:
|
||
|
||
<VariableList>
|
||
<VarListEntry>
|
||
<Term>A line number</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This is a line number for the original line used in error messages only.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>A string</Term>
|
||
<ListItem>
|
||
<Para>
|
||
This is the <Acronym>SQL</Acronym> request that is to be issued.
|
||
This request is modified
|
||
by the input variables, i.e. the variables that where not known at
|
||
compile time but are to be entered in the request. Where the variables
|
||
should go the string contains <Quote>;</Quote>.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Input variables</Term>
|
||
<ListItem>
|
||
<Para>
|
||
As described in the section about the preprocessor every input variable
|
||
gets five arguments.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>ECPGt_EOIT</Term>
|
||
<ListItem>
|
||
<Para>
|
||
An enum telling that there are no more input variables.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>Output variables</Term>
|
||
<ListItem>
|
||
<Para>
|
||
As described in the section about the preprocessor every input variable
|
||
gets five arguments. These variables are filled by the function.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
|
||
<VarListEntry>
|
||
<Term>ECPGt_EORT</Term>
|
||
<ListItem>
|
||
<Para>
|
||
An enum telling that there are no more variables.
|
||
</Para>
|
||
</ListItem>
|
||
</VarListEntry>
|
||
</VariableList>
|
||
</Para>
|
||
|
||
<Para>
|
||
All the <Acronym>SQL</Acronym> statements are performed in one transaction
|
||
unless you issue
|
||
a commit transaction. This works so that the first transaction or the
|
||
first after a commit or rollback always begins a transaction.
|
||
</Para>
|
||
|
||
<Para>
|
||
To be completed: entries describing the other entries.
|
||
</Para>
|
||
</sect2>
|
||
</sect1>
|
||
</Chapter>
|