ecpg.sgml
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:27k
- <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@postgresql.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 almost all <Acronym>SQL</Acronym>
- statements 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
- {
- char sqlcaid[8];
- long sqlabc;
- long sqlcode;
- struct
- {
- int sqlerrml;
- char sqlerrmc[70];
- } sqlerrm;
- char sqlerrp[8];
- long sqlerrd[6];
- /* 0: empty */
- /* 1: empty */
- /* 2: number of rows processed in an INSERT, UPDATE */
- /* or DELETE statement */
- /* 3: empty */
- /* 4: empty */
- /* 5: empty */
- char sqlwarn[8];
- /* 0: set to 'W' if at least one other is 'W' */
- /* 1: if 'W' at least one character string */
- /* value was truncated when it was */
- /* stored into a host variable. */
- /* 2: empty */
- /* 3: empty */
- /* 4: empty */
- /* 5: empty */
- /* 6: empty */
- /* 7: empty */
- char sqlext[8];
- } 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 the line number
- in the source file.
- </Para>
- <Para>
- List of errors that can occur:
- <VariableList>
- <VarListEntry>
- <Term>-12, Out of memory in line %d.</Term>
- <ListItem>
- <Para>
- Does not normally occur. This is a sign that your virtual memory is
- exhausted.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-200, 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>-201, Too many arguments line %d.</Term>
- <ListItem>
- <Para>
- This means that <ProductName>Postgres</ProductName> has returned more
- arguments 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>-202, Too few arguments line %d.</Term>
- <ListItem>
- <Para>
- This means that <ProductName>Postgres</ProductName> has returned fewer
- arguments than we have
- host variables. Perhaps you have too many host variables in the
- <Command>INTO :var1,:var2</Command>-list.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-203, Too many matches line %d.</Term>
- <ListItem>
- <Para>
- This means that the query has returned several lines but the
- variables specified are no arrays. The <Command>SELECT</Command> you made
- probably was not unique.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-204, 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>-205, 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>-206, Not correctly formatted floating point type: %s line %d.</Term>
- <ListItem>
- <Para>
- This means that the host variable is of a <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>-207, Unable to convert %s to bool on line %d.</Term>
- <ListItem>
- <Para>
- This means that the host variable is of a <Type>bool</Type> type and
- the field in the <ProductName>Postgres</ProductName> database is neither 't'
- nor 'f'.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-208, Empty query line %d.</Term>
- <ListItem>
- <Para>
- <ProductName>Postgres</ProductName> returned PGRES_EMPTY_QUERY, probably
- because the query indeed was empty.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-220, No such connection %s in line %d.</Term>
- <ListItem>
- <Para>
- The program tries to access a connection that does not exist.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-221, Not connected in line %d.</Term>
- <ListItem>
- <Para>
- The program tries to access a connection that does exist but is not open.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-230, Invalid statement name %s in line %d.</Term>
- <ListItem>
- <Para>
- The statement you are trying to use has not been prepared.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-400, 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>-401, Error in transaction processing line %d. </Term>
- <ListItem>
- <Para>
- <ProductName>Postgres</ProductName> signalled to us that we cannot start,
- commit or rollback the transaction.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>-402, connect: could not open database %s.</Term>
- <ListItem>
- <Para>
- The connect to the database did not work.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>100, 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>
- </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>
- The design of <Application>ecpg</Application> follows SQL standard. So
- porting from a standard RDBMS should not be a problem. Unfortunately there
- is no such thing as a standard RDBMS. So <Application>ecpg</Application>
- also tries to understand syntax additions as long as they do not create
- conflicts with the standard.
- </Para>
- <Para>
- The following list shows all the known incompatibilities. If you find one
- not listed please notify <ULink url="mailto:meskes@postgresql.org">Michael
- Meskes</ULink>. Note, however, that we list only incompatibilities from
- a precompiler of another RDBMS to <Application>ecpg</Application> and not
- additional <Application>ecpg</Application> features that these RDBMS do not
- have.
- </Para>
- <Para>
- <VariableList>
- <VarListEntry>
- <Term>Syntax of FETCH command</Term>
- <ListItem>
- <Para>
- The standard syntax of the FETCH command is:
- </para>
- <Para>
- FETCH [direction] [amount] IN|FROM <Replaceable>cursor name</Replaceable>.
- </Para>
- <para>
- <Application>ORACLE</Application>, however, does not use the keywords IN
- resp. FROM. This feature cannot be added since it would create parsing
- conflicts.
- </Para>
- </ListItem>
- </VarListEntry>
- </VariableList>
- </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>Library functions</Term>
- <ListItem>
- <Para>
- to_date et al. do not exists. But then <ProductName>Postgres</ProductName>
- has some good conversion routines itself. So you probably won't miss these.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>Structures ans unions</Term>
- <ListItem>
- <Para>
- Structures and unions 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 allocate</Term>
- <ListItem>
- <Para>
- </Para>
- </listitem>
- </VarListEntry>
- <VarListEntry>
- <Term> exec sql deallocate</Term>
- <ListItem>
- <Para>
- </Para>
- </listitem>
- </VarListEntry>
- <VarListEntry>
- <Term> SQLSTATE</Term>
- <ListItem>
- <Para>
- </Para>
- </listitem>
- </VarListEntry>
- </VariableList>
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>message 'no data found'</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>sqlwarn[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>
- </VariableList>
- </Para>
- </sect2>
- <Sect2>
- <Title>The Preprocessor</Title>
- <Para>
- The first four lines written to the output are constant additions by ecpg.
- These are 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 intervenes and
- changes them depending on what it 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>
- In particular the definition of a structure or union also has to be listed
- inside a declare section. Otherwise <Application>ecpg</Application> cannot
- handle these types since it simply does not know the definition.
- </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>
- Not that this is NOT the same as
- <ProgramListing>
- #include <filename.h>
- </ProgramListing>
- </Para>
- <Para>
- Instead the file specified is parsed by <Application>ecpg</Application>
- itself. So the contents of the specified file is included in the resulting C
- code. This way you are able to specify EXEC SQL commands in an include file.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>Connect statement</Term>
- <ListItem>
- <Para>
- A connect statement looks like:
- <ProgramListing>
- exec sql connect to <Replaceable>connection target</Replaceable>;
- </ProgramListing>
- It creates a connection to the specified database.
- </Para>
- <Para>
- The <Replaceable>connection target</Replaceable> can be specified in the
- following ways:
- <VariableList>
- <VarListEntry>
- <Term>dbname[@server][:port][as <Replaceable>connection name</Replaceable>][user <Replaceable>user name</Replaceable>]</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>tcp:postgresql://server[:port][/dbname][as <Replaceable>connection name</Replaceable>][user <Replaceable>user name</Replaceable>]</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>unix:postgresql://server[:port][/dbname][as <Replaceable>connection name</Replaceable>][user <Replaceable>user name</Replaceable>]</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term><Replaceable>character variable</Replaceable>[as <Replaceable>connection name</Replaceable>][user <Replaceable>user name</Replaceable>]</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term><Replaceable>character string</Replaceable>[as <Replaceable>connection name</Replaceable>][<Replaceable>user</Replaceable>]</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>default</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>user</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- </VariableList>
- </Para>
- <Para>
- There are also different ways to specify the user name:
- <VariableList>
- <VarListEntry>
- <Term><Replaceable>userid</Replaceable></Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term><Replaceable>userid</Replaceable>/<Replaceable>password</Replaceable></Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term><Replaceable>userid</Replaceable> identified by <Replaceable>password</Replaceable></Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term><Replaceable>userid</Replaceable> using <Replaceable>password</Replaceable></Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- </VariableList>
- </Para>
- <Para> Finally the userid and the password. Each may be a constant text, a
- character variable or a chararcter string.
- </Para>
- </ListItem>
- </VarListEntry>
- <VarListEntry>
- <Term>Disconnect statements</Term>
- <ListItem>
- <Para>
- A disconnect statement looks loke:
- <ProgramListing>
- exec sql disconnect [<Replaceable>connection target</Replaceable>];
- </ProgramListing>
- It closes the connection to the specified database.
- </Para>
- <Para>
- The <Replaceable>connection target</Replaceable> can be specified in the
- following ways:
- <VariableList>
- <VarListEntry>
- <Term><Replaceable>connection name</Replaceable></Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>default</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>current</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- <VarListEntry>
- <Term>all</Term>
- <listitem><para></para></listitem>
- </VarListEntry>
- </VariableList>
- </Para>
- </ListItem>
- </VarListEntry>
- <!--WARNING: FROM HERE ON THE TEXT IS OUTDATED!-->
- <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>
- <!--STARTING HERE IT IS OKAY AGAIN!-->
- <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 looked for among
- the variables that were previously declared within a declare section and
- depending on the variable being 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 ten arguments:
- <SimpleList>
- <Member>The type as a special symbol.</Member>
- <Member>A pointer to the value or a pointer to the pointer.</Member>
- <Member>The size of the variable if it is a char or 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>
- <Member>The type of the indicator variable as a special symbol.</Member>
- <Member>A pointer to the value of the indicator variable or a pointer to the pointer of the indicator variable.</Member>
- <Member>0.</Member>
- <Member>Number of elements in the indicator array (for array fetches).</Member>
- <Member>The offset to the next element in the indicator array (for array fetches)</Member>
- </SimpleList>
- </Para>
- </ListItem>
- </VarListEntry>
- </VariableList>
- </Para>
- </Sect2>
- <Sect2>
- <Title>A Complete Example</Title>
- <Para>
- Here is a complete example describing the output of the preprocessor of a
- file foo.pgc:
- <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>
- /* Processed by ecpg (2.6.0) */
- /* These two include files are added by the preprocessor */
- #include <ecpgtype.h>;
- #include <ecpglib.h>;
- /* exec sql begin declare section */
- #line 1 "foo.pgc"
- int index;
- int result;
- /* exec sql end declare section */
- ...
- ECPGdo(__LINE__, NULL, "select res from mytable where index = ? ",
- ECPGt_int,&(index),1L,1L,sizeof(int),
- ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
- ECPGt_int,&(result),1L,1L,sizeof(int),
- ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
- #line 147 "foo.pgc"
- </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 will not run
- into machines with limits on the amount of variables that can be
- accepted by a vararg 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 ten 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 ten 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. To get this auto-transaction going
- the first statement or the first after statement after a commit or rollback
- always begins a transaction. To disable this feature per default use the
- '-t' option on the commandline
- </Para>
- <Para>
- To be completed: entries describing the other entries.
- </Para>
- </sect2>
- </sect1>
- </Chapter>