In Section 36.3 you saw how you can execute SQL statements from an embedded SQL program. Some of those statements only used fixed values and did not provide a way to insert user-supplied values into statements or have the program process the values returned by the query. Those kinds of statements are not really useful in real applications. This section explains in detail how you can pass data between your C program and the embedded SQL statements using a simple mechanism called host variables. In an embedded SQL program we consider the SQL statements to be guests in the C program code which is the host language. Therefore the variables of the C program are called host variables.
Another way to exchange values between PostgreSQL backends and ECPG applications is the use of SQL descriptors, described in Section 36.7.
Passing data between the C program and the SQL statements is particularly simple in embedded SQL. Instead of having the program paste the data into the statement, which entails various complications, such as properly quoting the value, you can simply write the name of a C variable into the SQL statement, prefixed by a colon. For example:
EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
This statement refers to two C variables named v1
and v2
and also uses a regular SQL string literal, to illustrate that you are not restricted to use one kind of data or the other.
This style of inserting C variables in SQL statements works anywhere a value expression is expected in an SQL statement.
To pass data from the program to the database, for example as parameters in a query, or to pass data from the database back to the program, the C variables that are intended to contain this data need to be declared in specially marked sections, so the embedded SQL preprocessor is made aware of them.
This section starts with:
EXEC SQL BEGIN DECLARE SECTION;
and ends with:
EXEC SQL END DECLARE SECTION;
Between those lines, there must be normal C variable declarations, such as:
int x = 4; char foo[16], bar[16];
As you can see, you can optionally assign an initial value to the variable. The variable's scope is determined by the location of its declaring section within the program. You can also declare variables with the following syntax which implicitly creates a declare section:
EXEC SQL int i = 4;
You can have as many declare sections in a program as you like.
The declarations are also echoed to the output file as normal C variables, so there's no need to declare them again. Variables that are not intended to be used in SQL commands can be declared normally outside these special sections.
The definition of a structure or union also must be listed inside a DECLARE
section. Otherwise the preprocessor cannot handle these types since it does not know the definition.
Now you should be able to pass data generated by your program into an SQL command. But how do you retrieve the results of a query? For that purpose, embedded SQL provides special variants of the usual commands SELECT
and FETCH
. These commands have a special INTO
clause that specifies which host variables the retrieved values are to be stored in. SELECT
is used for a query that returns only single row, and FETCH
is used for a query that returns multiple rows, using a cursor.
Here is an example:
/* * assume this table: * CREATE TABLE test1 (a int, b varchar(50)); */ EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT a, b INTO :v1, :v2 FROM test;
So the INTO
clause appears between the select list and the FROM
clause. The number of elements in the select list and the list after INTO
(also called the target list) must be equal.
Here is an example using the command FETCH
:
EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test; ... do { ... EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2; ... } while (...);
Here the INTO
clause appears after all the normal clauses.
When ECPG applications exchange values between the PostgreSQL server and the C application, such as when retrieving query results from the server or executing SQL statements with input parameters, the values need to be converted between PostgreSQL data types and host language variable types (C language data types, concretely). One of the main points of ECPG is that it takes care of this automatically in most cases.
In this respect, there are two kinds of data types: Some simple PostgreSQL data types, such as integer
and text
, can be read and written by the application directly. Other PostgreSQL data types, such as timestamp
and numeric
can only be accessed through special library functions; see Section 36.4.4.2.
Table 36.1 shows which PostgreSQL data types correspond to which C data types. When you wish to send or receive a value of a given PostgreSQL data type, you should declare a C variable of the corresponding C data type in the declare section.
Table 36.1. Mapping Between PostgreSQL Data Types and C Variable Types
PostgreSQL data type | Host variable type |
---|---|
smallint |
short |
integer |
int |
bigint |
long long int |
decimal |
decimal [a] |
numeric |
numeric [a] |
real |
float |
double precision |
double |
smallserial |
short |
serial |
int |
bigserial |
long long int |
oid |
unsigned int |
character( , varchar( , text |
char[ , VARCHAR[ [b] |
name |
char[NAMEDATALEN] |
timestamp |
timestamp [a] |
interval |
interval |