1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>34.7. Using Descriptor Areas</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="ecpg-pgtypes.html" title="34.6. pgtypes Library" /><link rel="next" href="ecpg-errors.html" title="34.8. Error Handling" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">34.7. Using Descriptor Areas</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="ecpg-pgtypes.html" title="34.6. pgtypes Library">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="ecpg.html" title="Chapter 34. ECPG — Embedded SQL in C">Up</a></td><th width="60%" align="center">Chapter 34. <span class="application">ECPG</span> — Embedded <acronym class="acronym">SQL</acronym> in C</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="ecpg-errors.html" title="34.8. Error Handling">Next</a></td></tr></table><hr /></div><div class="sect1" id="ECPG-DESCRIPTORS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">34.7. Using Descriptor Areas <a href="#ECPG-DESCRIPTORS" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="ecpg-descriptors.html#ECPG-NAMED-DESCRIPTORS">34.7.1. Named SQL Descriptor Areas</a></span></dt><dt><span class="sect2"><a href="ecpg-descriptors.html#ECPG-SQLDA-DESCRIPTORS">34.7.2. SQLDA Descriptor Areas</a></span></dt></dl></div><p>
3 An SQL descriptor area is a more sophisticated method for processing
4 the result of a <code class="command">SELECT</code>, <code class="command">FETCH</code> or
5 a <code class="command">DESCRIBE</code> statement. An SQL descriptor area groups
6 the data of one row of data together with metadata items into one
7 data structure. The metadata is particularly useful when executing
8 dynamic SQL statements, where the nature of the result columns might
9 not be known ahead of time. PostgreSQL provides two ways to use
10 Descriptor Areas: the named SQL Descriptor Areas and the C-structure
12 </p><div class="sect2" id="ECPG-NAMED-DESCRIPTORS"><div class="titlepage"><div><div><h3 class="title">34.7.1. Named SQL Descriptor Areas <a href="#ECPG-NAMED-DESCRIPTORS" class="id_link">#</a></h3></div></div></div><p>
13 A named SQL descriptor area consists of a header, which contains
14 information concerning the entire descriptor, and one or more item
15 descriptor areas, which basically each describe one column in the
18 Before you can use an SQL descriptor area, you need to allocate one:
19 </p><pre class="programlisting">
20 EXEC SQL ALLOCATE DESCRIPTOR <em class="replaceable"><code>identifier</code></em>;
22 The identifier serves as the <span class="quote">“<span class="quote">variable name</span>”</span> of the
24 When you don't need the descriptor anymore, you should deallocate
26 </p><pre class="programlisting">
27 EXEC SQL DEALLOCATE DESCRIPTOR <em class="replaceable"><code>identifier</code></em>;
30 To use a descriptor area, specify it as the storage target in an
31 <code class="literal">INTO</code> clause, instead of listing host variables:
32 </p><pre class="programlisting">
33 EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc;
35 If the result set is empty, the Descriptor Area will still contain
36 the metadata from the query, i.e., the field names.
38 For not yet executed prepared queries, the <code class="command">DESCRIBE</code>
39 statement can be used to get the metadata of the result set:
40 </p><pre class="programlisting">
41 EXEC SQL BEGIN DECLARE SECTION;
42 char *sql_stmt = "SELECT * FROM table1";
43 EXEC SQL END DECLARE SECTION;
45 EXEC SQL PREPARE stmt1 FROM :sql_stmt;
46 EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc;
49 Before PostgreSQL 9.0, the <code class="literal">SQL</code> keyword was optional,
50 so using <code class="literal">DESCRIPTOR</code> and <code class="literal">SQL DESCRIPTOR</code>
51 produced named SQL Descriptor Areas. Now it is mandatory, omitting
52 the <code class="literal">SQL</code> keyword produces SQLDA Descriptor Areas,
53 see <a class="xref" href="ecpg-descriptors.html#ECPG-SQLDA-DESCRIPTORS" title="34.7.2. SQLDA Descriptor Areas">Section 34.7.2</a>.
55 In <code class="command">DESCRIBE</code> and <code class="command">FETCH</code> statements,
56 the <code class="literal">INTO</code> and <code class="literal">USING</code> keywords can be
57 used to similarly: they produce the result set and the metadata in a
60 Now how do you get the data out of the descriptor area? You can
61 think of the descriptor area as a structure with named fields. To
62 retrieve the value of a field from the header and store it into a
63 host variable, use the following command:
64 </p><pre class="programlisting">
65 EXEC SQL GET DESCRIPTOR <em class="replaceable"><code>name</code></em> :<em class="replaceable"><code>hostvar</code></em> = <em class="replaceable"><code>field</code></em>;
67 Currently, there is only one header field defined:
68 <em class="replaceable"><code>COUNT</code></em>, which tells how many item
69 descriptor areas exist (that is, how many columns are contained in
70 the result). The host variable needs to be of an integer type. To
71 get a field from the item descriptor area, use the following
73 </p><pre class="programlisting">
74 EXEC SQL GET DESCRIPTOR <em class="replaceable"><code>name</code></em> VALUE <em class="replaceable"><code>num</code></em> :<em class="replaceable"><code>hostvar</code></em> = <em class="replaceable"><code>field</code></em>;
76 <em class="replaceable"><code>num</code></em> can be a literal integer or a host
77 variable containing an integer. Possible fields are:
79 </p><div class="variablelist"><dl class="variablelist"><dt id="ECPG-NAMED-DESCRIPTORS-CARDINALITY"><span class="term"><code class="literal">CARDINALITY</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-CARDINALITY" class="id_link">#</a></dt><dd><p>
80 number of rows in the result set
81 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-DATA"><span class="term"><code class="literal">DATA</code></span> <a href="#ECPG-NAMED-DESCRIPTORS-DATA" class="id_link">#</a></dt><dd><p>
82 actual data item (therefore, the data type of this field
84 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-DATETIME-INTERVAL-CODE"><span class="term"><code class="literal">DATETIME_INTERVAL_CODE</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-DATETIME-INTERVAL-CODE" class="id_link">#</a></dt><dd><p>
85 When <code class="literal">TYPE</code> is <code class="literal">9</code>,
86 <code class="literal">DATETIME_INTERVAL_CODE</code> will have a value of
87 <code class="literal">1</code> for <code class="literal">DATE</code>,
88 <code class="literal">2</code> for <code class="literal">TIME</code>,
89 <code class="literal">3</code> for <code class="literal">TIMESTAMP</code>,
90 <code class="literal">4</code> for <code class="literal">TIME WITH TIME ZONE</code>, or
91 <code class="literal">5</code> for <code class="literal">TIMESTAMP WITH TIME ZONE</code>.
92 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-DATETIME-INTERVAL-PRECISION"><span class="term"><code class="literal">DATETIME_INTERVAL_PRECISION</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-DATETIME-INTERVAL-PRECISION" class="id_link">#</a></dt><dd><p>
94 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-INDICATOR"><span class="term"><code class="literal">INDICATOR</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-INDICATOR" class="id_link">#</a></dt><dd><p>
95 the indicator (indicating a null value or a value truncation)
96 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-KEY-MEMBER"><span class="term"><code class="literal">KEY_MEMBER</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-KEY-MEMBER" class="id_link">#</a></dt><dd><p>
98 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-LENGTH"><span class="term"><code class="literal">LENGTH</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-LENGTH" class="id_link">#</a></dt><dd><p>
99 length of the datum in characters
100 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-NAME"><span class="term"><code class="literal">NAME</code> (string)</span> <a href="#ECPG-NAMED-DESCRIPTORS-NAME" class="id_link">#</a></dt><dd><p>
102 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-NULLABLE"><span class="term"><code class="literal">NULLABLE</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-NULLABLE" class="id_link">#</a></dt><dd><p>
104 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-OCTET-LENGTH"><span class="term"><code class="literal">OCTET_LENGTH</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-OCTET-LENGTH" class="id_link">#</a></dt><dd><p>
105 length of the character representation of the datum in bytes
106 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-PRECISION"><span class="term"><code class="literal">PRECISION</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-PRECISION" class="id_link">#</a></dt><dd><p>
107 precision (for type <code class="type">numeric</code>)
108 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-RETURNED-LENGTH"><span class="term"><code class="literal">RETURNED_LENGTH</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-RETURNED-LENGTH" class="id_link">#</a></dt><dd><p>
109 length of the datum in characters
110 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-RETURNED-OCTET-LENGTH"><span class="term"><code class="literal">RETURNED_OCTET_LENGTH</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-RETURNED-OCTET-LENGTH" class="id_link">#</a></dt><dd><p>
111 length of the character representation of the datum in bytes
112 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-SCALE"><span class="term"><code class="literal">SCALE</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-SCALE" class="id_link">#</a></dt><dd><p>
113 scale (for type <code class="type">numeric</code>)
114 </p></dd><dt id="ECPG-NAMED-DESCRIPTORS-TYPE"><span class="term"><code class="literal">TYPE</code> (integer)</span> <a href="#ECPG-NAMED-DESCRIPTORS-TYPE" class="id_link">#</a></dt><dd><p>
115 numeric code of the data type of the column
116 </p></dd></dl></div><p>
118 In <code class="command">EXECUTE</code>, <code class="command">DECLARE</code> and <code class="command">OPEN</code>
119 statements, the effect of the <code class="literal">INTO</code> and <code class="literal">USING</code>
120 keywords are different. A Descriptor Area can also be manually built to
121 provide the input parameters for a query or a cursor and
122 <code class="literal">USING SQL DESCRIPTOR <em class="replaceable"><code>name</code></em></code>
123 is the way to pass the input parameters into a parameterized query. The statement
124 to build a named SQL Descriptor Area is below:
125 </p><pre class="programlisting">
126 EXEC SQL SET DESCRIPTOR <em class="replaceable"><code>name</code></em> VALUE <em class="replaceable"><code>num</code></em> <em class="replaceable"><code>field</code></em> = :<em class="replaceable"><code>hostvar</code></em>;
129 PostgreSQL supports retrieving more that one record in one <code class="command">FETCH</code>
130 statement and storing the data in host variables in this case assumes that the
131 variable is an array. E.g.:
132 </p><pre class="programlisting">
133 EXEC SQL BEGIN DECLARE SECTION;
135 EXEC SQL END DECLARE SECTION;
137 EXEC SQL FETCH 5 FROM mycursor INTO SQL DESCRIPTOR mydesc;
139 EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA;
142 </p></div><div class="sect2" id="ECPG-SQLDA-DESCRIPTORS"><div class="titlepage"><div><div><h3 class="title">34.7.2. SQLDA Descriptor Areas <a href="#ECPG-SQLDA-DESCRIPTORS" class="id_link">#</a></h3></div></div></div><p>
143 An SQLDA Descriptor Area is a C language structure which can be also used
144 to get the result set and the metadata of a query. One structure stores one
145 record from the result set.
146 </p><pre class="programlisting">
147 EXEC SQL include sqlda.h;
150 EXEC SQL FETCH 3 FROM mycursor INTO DESCRIPTOR mysqlda;
152 Note that the <code class="literal">SQL</code> keyword is omitted. The paragraphs about
153 the use cases of the <code class="literal">INTO</code> and <code class="literal">USING</code>
154 keywords in <a class="xref" href="ecpg-descriptors.html#ECPG-NAMED-DESCRIPTORS" title="34.7.1. Named SQL Descriptor Areas">Section 34.7.1</a> also apply here with an addition.
155 In a <code class="command">DESCRIBE</code> statement the <code class="literal">DESCRIPTOR</code>
156 keyword can be completely omitted if the <code class="literal">INTO</code> keyword is used:
157 </p><pre class="programlisting">
158 EXEC SQL DESCRIBE prepared_statement INTO mysqlda;
160 </p><div class="procedure"><p>
161 The general flow of a program that uses SQLDA is:
162 </p><ol class="procedure" type="1"><li class="step"><p>Prepare a query, and declare a cursor for it.</p></li><li class="step"><p>Declare an SQLDA for the result rows.</p></li><li class="step"><p>Declare an SQLDA for the input parameters, and initialize them (memory allocation, parameter settings).</p></li><li class="step"><p>Open a cursor with the input SQLDA.</p></li><li class="step"><p>Fetch rows from the cursor, and store them into an output SQLDA.</p></li><li class="step"><p>Read values from the output SQLDA into the host variables (with conversion if necessary).</p></li><li class="step"><p>Close the cursor.</p></li><li class="step"><p>Free the memory area allocated for the input SQLDA.</p></li></ol></div><div class="sect3" id="ECPG-SQLDA-DESCRIPTORS-SQLDA"><div class="titlepage"><div><div><h4 class="title">34.7.2.1. SQLDA Data Structure <a href="#ECPG-SQLDA-DESCRIPTORS-SQLDA" class="id_link">#</a></h4></div></div></div><p>
163 SQLDA uses three data structure
164 types: <code class="type">sqlda_t</code>, <code class="type">sqlvar_t</code>,
165 and <code class="type">struct sqlname</code>.
166 </p><div class="tip"><h3 class="title">Tip</h3><p>
167 PostgreSQL's SQLDA has a similar data structure to the one in
168 IBM DB2 Universal Database, so some technical information on
169 DB2's SQLDA could help understanding PostgreSQL's one better.
170 </p></div><div class="sect4" id="ECPG-SQLDA-SQLDA"><div class="titlepage"><div><div><h5 class="title">34.7.2.1.1. sqlda_t Structure <a href="#ECPG-SQLDA-SQLDA" class="id_link">#</a></h5></div></div></div><p>
171 The structure type <code class="type">sqlda_t</code> is the type of the
172 actual SQLDA. It holds one record. And two or
173 more <code class="type">sqlda_t</code> structures can be connected in a
174 linked list with the pointer in
175 the <code class="structfield">desc_next</code> field, thus
176 representing an ordered collection of rows. So, when two or
177 more rows are fetched, the application can read them by
178 following the <code class="structfield">desc_next</code> pointer in
179 each <code class="type">sqlda_t</code> node.
181 The definition of <code class="type">sqlda_t</code> is:
182 </p><pre class="programlisting">
189 struct sqlda_struct *desc_next;
190 struct sqlvar_struct sqlvar[1];
193 typedef struct sqlda_struct sqlda_t;
196 The meaning of the fields is:
198 </p><div class="variablelist"><dl class="variablelist"><dt id="ECPG-SQLDA-SQLDA-SQLDAID"><span class="term"><code class="literal">sqldaid</code></span> <a href="#ECPG-SQLDA-SQLDA-SQLDAID" class="id_link">#</a></dt><dd><p>
199 It contains the literal string <code class="literal">"SQLDA "</code>.
200 </p></dd><dt id="ECPG-SQLDA-SQLDA-SQLDABC"><span class="term"><code class="literal">sqldabc</code></span> <a href="#ECPG-SQLDA-SQLDA-SQLDABC" class="id_link">#</a></dt><dd><p>
201 It contains the size of the allocated space in bytes.
202 </p></dd><dt id="ECPG-SQLDA-SQLDA-SQLN"><span class="term"><code class="literal">sqln</code></span> <a href="#ECPG-SQLDA-SQLDA-SQLN" class="id_link">#</a></dt><dd><p>
203 It contains the number of input parameters for a parameterized query in
204 case it's passed into <code class="command">OPEN</code>, <code class="command">DECLARE</code> or
205 <code class="command">EXECUTE</code> statements using the <code class="literal">USING</code>
206 keyword. In case it's used as output of <code class="command">SELECT</code>,
207 <code class="command">EXECUTE</code> or <code class="command">FETCH</code> statements,
208 its value is the same as <code class="literal">sqld</code>
210 </p></dd><dt id="ECPG-SQLDA-SQLDA-SQLD"><span class="term"><code class="literal">sqld</code></span> <a href="#ECPG-SQLDA-SQLDA-SQLD" class="id_link">#</a></dt><dd><p>
211 It contains the number of fields in a result set.
212 </p></dd><dt id="ECPG-SQLDA-SQLDA-DESC-NEXT"><span class="term"><code class="literal">desc_next</code></span> <a href="#ECPG-SQLDA-SQLDA-DESC-NEXT" class="id_link">#</a></dt><dd><p>
213 If the query returns more than one record, multiple linked
214 SQLDA structures are returned, and <code class="literal">desc_next</code> holds
215 a pointer to the next entry in the list.
216 </p></dd><dt id="ECPG-SQLDA-SQLDA-SQLVAR"><span class="term"><code class="literal">sqlvar</code></span> <a href="#ECPG-SQLDA-SQLDA-SQLVAR" class="id_link">#</a></dt><dd><p>
217 This is the array of the columns in the result set.
218 </p></dd></dl></div><p>
219 </p></div><div class="sect4" id="ECPG-SQLDA-SQLVAR"><div class="titlepage"><div><div><h5 class="title">34.7.2.1.2. sqlvar_t Structure <a href="#ECPG-SQLDA-SQLVAR" class="id_link">#</a></h5></div></div></div><p>
220 The structure type <code class="type">sqlvar_t</code> holds a column value
221 and metadata such as type and length. The definition of the type
224 </p><pre class="programlisting">
231 struct sqlname sqlname;
234 typedef struct sqlvar_struct sqlvar_t;
237 The meaning of the fields is:
239 </p><div class="variablelist"><dl class="variablelist"><dt id="ECPG-SQLDA-SQLVAR-SQLTYPE"><span class="term"><code class="literal">sqltype</code></span> <a href="#ECPG-SQLDA-SQLVAR-SQLTYPE" class="id_link">#</a></dt><dd><p>
240 Contains the type identifier of the field. For values,
241 see <code class="literal">enum ECPGttype</code> in <code class="literal">ecpgtype.h</code>.
242 </p></dd><dt id="ECPG-SQLDA-SQLVAR-SQLLEN"><span class="term"><code class="literal">sqllen</code></span> <a href="#ECPG-SQLDA-SQLVAR-SQLLEN" class="id_link">#</a></dt><dd><p>
243 Contains the binary length of the field. e.g., 4 bytes for <code class="type">ECPGt_int</code>.
244 </p></dd><dt id="ECPG-SQLDA-SQLVAR-SQLDATA"><span class="term"><code class="literal">sqldata</code></span> <a href="#ECPG-SQLDA-SQLVAR-SQLDATA" class="id_link">#</a></dt><dd><p>
245 Points to the data. The format of the data is described
246 in <a class="xref" href="ecpg-variables.html#ECPG-VARIABLES-TYPE-MAPPING" title="34.4.4. Type Mapping">Section 34.4.4</a>.
247 </p></dd><dt id="ECPG-SQLDA-SQLVAR-SQLIND"><span class="term"><code class="literal">sqlind</code></span> <a href="#ECPG-SQLDA-SQLVAR-SQLIND" class="id_link">#</a></dt><dd><p>
248 Points to the null indicator. 0 means not null, -1 means
250 </p></dd><dt id="ECPG-SQLDA-SQLVAR-SQLNAME"><span class="term"><code class="literal">sqlname</code></span> <a href="#ECPG-SQLDA-SQLVAR-SQLNAME" class="id_link">#</a></dt><dd><p>
251 The name of the field.
252 </p></dd></dl></div><p>
253 </p></div><div class="sect4" id="ECPG-SQLDA-SQLNAME"><div class="titlepage"><div><div><h5 class="title">34.7.2.1.3. struct sqlname Structure <a href="#ECPG-SQLDA-SQLNAME" class="id_link">#</a></h5></div></div></div><p>
254 A <code class="type">struct sqlname</code> structure holds a column name. It
255 is used as a member of the <code class="type">sqlvar_t</code> structure. The
256 definition of the structure is:
257 </p><pre class="programlisting">
258 #define NAMEDATALEN 64
263 char data[NAMEDATALEN];
266 The meaning of the fields is:
267 </p><div class="variablelist"><dl class="variablelist"><dt id="ECPG-SQLDA-SQLNAME-LENGTH"><span class="term"><code class="literal">length</code></span> <a href="#ECPG-SQLDA-SQLNAME-LENGTH" class="id_link">#</a></dt><dd><p>
268 Contains the length of the field name.
269 </p></dd><dt id="ECPG-SQLDA-SQLNAME-DATA"><span class="term"><code class="literal">data</code></span> <a href="#ECPG-SQLDA-SQLNAME-DATA" class="id_link">#</a></dt><dd><p>
270 Contains the actual field name.
271 </p></dd></dl></div><p>
272 </p></div></div><div class="sect3" id="ECPG-SQLDA-OUTPUT"><div class="titlepage"><div><div><h4 class="title">34.7.2.2. Retrieving a Result Set Using an SQLDA <a href="#ECPG-SQLDA-OUTPUT" class="id_link">#</a></h4></div></div></div><div class="procedure"><p>
273 The general steps to retrieve a query result set through an
275 </p><ol class="procedure" type="1"><li class="step"><p>Declare an <code class="type">sqlda_t</code> structure to receive the result set.</p></li><li class="step"><p>Execute <code class="command">FETCH</code>/<code class="command">EXECUTE</code>/<code class="command">DESCRIBE</code> commands to process a query specifying the declared SQLDA.</p></li><li class="step"><p>Check the number of records in the result set by looking at <code class="structfield">sqln</code>, a member of the <code class="type">sqlda_t</code> structure.</p></li><li class="step"><p>Get the values of each column from <code class="literal">sqlvar[0]</code>, <code class="literal">sqlvar[1]</code>, etc., members of the <code class="type">sqlda_t</code> structure.</p></li><li class="step"><p>Go to next row (<code class="type">sqlda_t</code> structure) by following the <code class="structfield">desc_next</code> pointer, a member of the <code class="type">sqlda_t</code> structure.</p></li><li class="step"><p>Repeat above as you need.</p></li></ol></div><p>
276 Here is an example retrieving a result set through an SQLDA.
278 First, declare a <code class="type">sqlda_t</code> structure to receive the result set.
279 </p><pre class="programlisting">
283 Next, specify the SQLDA in a command. This is
284 a <code class="command">FETCH</code> command example.
285 </p><pre class="programlisting">
286 EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1;
289 Run a loop following the linked list to retrieve the rows.
290 </p><pre class="programlisting">
293 for (cur_sqlda = sqlda1;
295 cur_sqlda = cur_sqlda->desc_next)
301 Inside the loop, run another loop to retrieve each column data
302 (<code class="type">sqlvar_t</code> structure) of the row.
303 </p><pre class="programlisting">
304 for (i = 0; i < cur_sqlda->sqld; i++)
306 sqlvar_t v = cur_sqlda->sqlvar[i];
307 char *sqldata = v.sqldata;
308 short sqllen = v.sqllen;
313 To get a column value, check the <code class="structfield">sqltype</code> value,
314 a member of the <code class="type">sqlvar_t</code> structure. Then, switch
315 to an appropriate way, depending on the column type, to copy
316 data from the <code class="structfield">sqlvar</code> field to a host variable.
317 </p><pre class="programlisting">
323 memset(&var_buf, 0, sizeof(var_buf));
324 memcpy(&var_buf, sqldata, (sizeof(var_buf) <= sqllen ? sizeof(var_buf) - 1 : sqllen));
327 case ECPGt_int: /* integer */
328 memcpy(&intval, sqldata, sqllen);
329 snprintf(var_buf, sizeof(var_buf), "%d", intval);
335 </p></div><div class="sect3" id="ECPG-SQLDA-INPUT"><div class="titlepage"><div><div><h4 class="title">34.7.2.3. Passing Query Parameters Using an SQLDA <a href="#ECPG-SQLDA-INPUT" class="id_link">#</a></h4></div></div></div><div class="procedure"><p>
336 The general steps to use an SQLDA to pass input
337 parameters to a prepared query are:
338 </p><ol class="procedure" type="1"><li class="step"><p>Create a prepared query (prepared statement)</p></li><li class="step"><p>Declare an sqlda_t structure as an input SQLDA.</p></li><li class="step"><p>Allocate memory area (as sqlda_t structure) for the input SQLDA.</p></li><li class="step"><p>Set (copy) input values in the allocated memory.</p></li><li class="step"><p>Open a cursor with specifying the input SQLDA.</p></li></ol></div><p>
341 First, create a prepared statement.
342 </p><pre class="programlisting">
343 EXEC SQL BEGIN DECLARE SECTION;
344 char query[1024] = "SELECT d.oid, * FROM pg_database d, pg_stat_database s WHERE d.oid = s.datid AND (d.datname = ? OR d.oid = ?)";
345 EXEC SQL END DECLARE SECTION;
347 EXEC SQL PREPARE stmt1 FROM :query;
350 Next, allocate memory for an SQLDA, and set the number of input
351 parameters in <code class="structfield">sqln</code>, a member variable of
352 the <code class="type">sqlda_t</code> structure. When two or more input
353 parameters are required for the prepared query, the application
354 has to allocate additional memory space which is calculated by
355 (nr. of params - 1) * sizeof(sqlvar_t). The example shown here
356 allocates memory space for two input parameters.
357 </p><pre class="programlisting">
360 sqlda2 = (sqlda_t *) malloc(sizeof(sqlda_t) + sizeof(sqlvar_t));
361 memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t));
363 sqlda2->sqln = 2; /* number of input variables */
366 After memory allocation, store the parameter values into the
367 <code class="literal">sqlvar[]</code> array. (This is same array used for
368 retrieving column values when the SQLDA is receiving a result
369 set.) In this example, the input parameters
370 are <code class="literal">"postgres"</code>, having a string type,
371 and <code class="literal">1</code>, having an integer type.
372 </p><pre class="programlisting">
373 sqlda2->sqlvar[0].sqltype = ECPGt_char;
374 sqlda2->sqlvar[0].sqldata = "postgres";
375 sqlda2->sqlvar[0].sqllen = 8;
378 sqlda2->sqlvar[1].sqltype = ECPGt_int;
379 sqlda2->sqlvar[1].sqldata = (char *) &intval;
380 sqlda2->sqlvar[1].sqllen = sizeof(intval);
383 By opening a cursor and specifying the SQLDA that was set up
384 beforehand, the input parameters are passed to the prepared
386 </p><pre class="programlisting">
387 EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2;
390 Finally, after using input SQLDAs, the allocated memory space
391 must be freed explicitly, unlike SQLDAs used for receiving query
393 </p><pre class="programlisting">
396 </p></div><div class="sect3" id="ECPG-SQLDA-EXAMPLE"><div class="titlepage"><div><div><h4 class="title">34.7.2.4. A Sample Application Using SQLDA <a href="#ECPG-SQLDA-EXAMPLE" class="id_link">#</a></h4></div></div></div><p>
397 Here is an example program, which describes how to fetch access
398 statistics of the databases, specified by the input parameters,
399 from the system catalogs.
401 This application joins two system tables, pg_database and
402 pg_stat_database on the database OID, and also fetches and shows
403 the database statistics which are retrieved by two input
404 parameters (a database <code class="literal">postgres</code>, and OID <code class="literal">1</code>).
406 First, declare an SQLDA for input and an SQLDA for output.
407 </p><pre class="programlisting">
408 EXEC SQL include sqlda.h;
410 sqlda_t *sqlda1; /* an output descriptor */
411 sqlda_t *sqlda2; /* an input descriptor */
414 Next, connect to the database, prepare a statement, and declare a
415 cursor for the prepared statement.
416 </p><pre class="programlisting">
420 EXEC SQL BEGIN DECLARE SECTION;
421 char query[1024] = "SELECT d.oid,* FROM pg_database d, pg_stat_database s WHERE d.oid=s.datid AND ( d.datname=? OR d.oid=? )";
422 EXEC SQL END DECLARE SECTION;
424 EXEC SQL CONNECT TO testdb AS con1 USER testuser;
425 EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
427 EXEC SQL PREPARE stmt1 FROM :query;
428 EXEC SQL DECLARE cur1 CURSOR FOR stmt1;
431 Next, put some values in the input SQLDA for the input
432 parameters. Allocate memory for the input SQLDA, and set the
433 number of input parameters to <code class="literal">sqln</code>. Store
434 type, value, and value length into <code class="literal">sqltype</code>,
435 <code class="literal">sqldata</code>, and <code class="literal">sqllen</code> in the
436 <code class="literal">sqlvar</code> structure.
438 </p><pre class="programlisting">
439 /* Create SQLDA structure for input parameters. */
440 sqlda2 = (sqlda_t *) malloc(sizeof(sqlda_t) + sizeof(sqlvar_t));
441 memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t));
442 sqlda2->sqln = 2; /* number of input variables */
444 sqlda2->sqlvar[0].sqltype = ECPGt_char;
445 sqlda2->sqlvar[0].sqldata = "postgres";
446 sqlda2->sqlvar[0].sqllen = 8;
449 sqlda2->sqlvar[1].sqltype = ECPGt_int;
450 sqlda2->sqlvar[1].sqldata = (char *)&intval;
451 sqlda2->sqlvar[1].sqllen = sizeof(intval);
454 After setting up the input SQLDA, open a cursor with the input
457 </p><pre class="programlisting">
458 /* Open a cursor with input parameters. */
459 EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2;
462 Fetch rows into the output SQLDA from the opened cursor.
463 (Generally, you have to call <code class="command">FETCH</code> repeatedly
464 in the loop, to fetch all rows in the result set.)
465 </p><pre class="programlisting">
470 /* Assign descriptor to the cursor */
471 EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1;
474 Next, retrieve the fetched records from the SQLDA, by following
475 the linked list of the <code class="type">sqlda_t</code> structure.
476 </p><pre class="programlisting">
477 for (cur_sqlda = sqlda1 ;
479 cur_sqlda = cur_sqlda->desc_next)
484 Read each columns in the first record. The number of columns is
485 stored in <code class="structfield">sqld</code>, the actual data of the first
486 column is stored in <code class="literal">sqlvar[0]</code>, both members of
487 the <code class="type">sqlda_t</code> structure.
489 </p><pre class="programlisting">
490 /* Print every column in a row. */
491 for (i = 0; i < sqlda1->sqld; i++)
493 sqlvar_t v = sqlda1->sqlvar[i];
494 char *sqldata = v.sqldata;
495 short sqllen = v.sqllen;
497 strncpy(name_buf, v.sqlname.data, v.sqlname.length);
498 name_buf[v.sqlname.length] = '\0';
501 Now, the column data is stored in the variable <code class="varname">v</code>.
502 Copy every datum into host variables, looking
503 at <code class="literal">v.sqltype</code> for the type of the column.
504 </p><pre class="programlisting">
508 unsigned long long int longlongval;
511 memset(&var_buf, 0, sizeof(var_buf));
512 memcpy(&var_buf, sqldata, (sizeof(var_buf) <= sqllen ? sizeof(var_buf)-1 : sqllen));
515 case ECPGt_int: /* integer */
516 memcpy(&intval, sqldata, sqllen);
517 snprintf(var_buf, sizeof(var_buf), "%d", intval);
526 printf("%s = %s (type: %d)\n", name_buf, var_buf, v.sqltype);
530 Close the cursor after processing all of records, and disconnect
532 </p><pre class="programlisting">
536 EXEC SQL DISCONNECT ALL;
539 The whole program is shown
540 in <a class="xref" href="ecpg-descriptors.html#ECPG-SQLDA-EXAMPLE-EXAMPLE" title="Example 34.1. Example SQLDA Program">Example 34.1</a>.
541 </p><div class="example" id="ECPG-SQLDA-EXAMPLE-EXAMPLE"><p class="title"><strong>Example 34.1. Example SQLDA Program</strong></p><div class="example-contents"><pre class="programlisting">
542 #include <stdlib.h>
543 #include <string.h>
544 #include <stdlib.h>
545 #include <stdio.h>
546 #include <unistd.h>
548 EXEC SQL include sqlda.h;
550 sqlda_t *sqlda1; /* descriptor for output */
551 sqlda_t *sqlda2; /* descriptor for input */
553 EXEC SQL WHENEVER NOT FOUND DO BREAK;
554 EXEC SQL WHENEVER SQLERROR STOP;
559 EXEC SQL BEGIN DECLARE SECTION;
560 char query[1024] = "SELECT d.oid,* FROM pg_database d, pg_stat_database s WHERE d.oid=s.datid AND ( d.datname=? OR d.oid=? )";
563 unsigned long long int longlongval;
564 EXEC SQL END DECLARE SECTION;
566 EXEC SQL CONNECT TO uptimedb AS con1 USER uptime;
567 EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
569 EXEC SQL PREPARE stmt1 FROM :query;
570 EXEC SQL DECLARE cur1 CURSOR FOR stmt1;
572 /* Create an SQLDA structure for an input parameter */
573 sqlda2 = (sqlda_t *)malloc(sizeof(sqlda_t) + sizeof(sqlvar_t));
574 memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t));
575 sqlda2->sqln = 2; /* a number of input variables */
577 sqlda2->sqlvar[0].sqltype = ECPGt_char;
578 sqlda2->sqlvar[0].sqldata = "postgres";
579 sqlda2->sqlvar[0].sqllen = 8;
582 sqlda2->sqlvar[1].sqltype = ECPGt_int;
583 sqlda2->sqlvar[1].sqldata = (char *) &intval;
584 sqlda2->sqlvar[1].sqllen = sizeof(intval);
586 /* Open a cursor with input parameters. */
587 EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2;
593 /* Assign descriptor to the cursor */
594 EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1;
596 for (cur_sqlda = sqlda1 ;
598 cur_sqlda = cur_sqlda->desc_next)
604 /* Print every column in a row. */
605 for (i=0 ; i<cur_sqlda->sqld ; i++)
607 sqlvar_t v = cur_sqlda->sqlvar[i];
608 char *sqldata = v.sqldata;
609 short sqllen = v.sqllen;
611 strncpy(name_buf, v.sqlname.data, v.sqlname.length);
612 name_buf[v.sqlname.length] = '\0';
617 memset(&var_buf, 0, sizeof(var_buf));
618 memcpy(&var_buf, sqldata, (sizeof(var_buf)<=sqllen ? sizeof(var_buf)-1 : sqllen) );
621 case ECPGt_int: /* integer */
622 memcpy(&intval, sqldata, sqllen);
623 snprintf(var_buf, sizeof(var_buf), "%d", intval);
626 case ECPGt_long_long: /* bigint */
627 memcpy(&longlongval, sqldata, sqllen);
628 snprintf(var_buf, sizeof(var_buf), "%lld", longlongval);
634 memset(var_buf, 0, sizeof(var_buf));
635 for (i = 0; i < sqllen; i++)
638 snprintf(tmpbuf, sizeof(tmpbuf), "%02x ", (unsigned char) sqldata[i]);
639 strncat(var_buf, tmpbuf, sizeof(var_buf));
645 printf("%s = %s (type: %d)\n", name_buf, var_buf, v.sqltype);
655 EXEC SQL DISCONNECT ALL;
660 The output of this example should look something like the
661 following (some numbers will vary).
662 </p><pre class="screen">
664 datname = template1 (type: 1)
665 datdba = 10 (type: 1)
666 encoding = 0 (type: 5)
667 datistemplate = t (type: 1)
668 datallowconn = t (type: 1)
669 dathasloginevt = f (type: 1)
670 datconnlimit = -1 (type: 5)
671 datfrozenxid = 379 (type: 1)
672 dattablespace = 1663 (type: 1)
673 datconfig = (type: 1)
674 datacl = {=c/uptime,uptime=CTc/uptime} (type: 1)
676 datname = template1 (type: 1)
677 numbackends = 0 (type: 5)
678 xact_commit = 113606 (type: 9)
679 xact_rollback = 0 (type: 9)
680 blks_read = 130 (type: 9)
681 blks_hit = 7341714 (type: 9)
682 tup_returned = 38262679 (type: 9)
683 tup_fetched = 1836281 (type: 9)
684 tup_inserted = 0 (type: 9)
685 tup_updated = 0 (type: 9)
686 tup_deleted = 0 (type: 9)
688 oid = 11511 (type: 1)
689 datname = postgres (type: 1)
690 datdba = 10 (type: 1)
691 encoding = 0 (type: 5)
692 datistemplate = f (type: 1)
693 datallowconn = t (type: 1)
694 dathasloginevt = f (type: 1)
695 datconnlimit = -1 (type: 5)
696 datfrozenxid = 379 (type: 1)
697 dattablespace = 1663 (type: 1)
698 datconfig = (type: 1)
700 datid = 11511 (type: 1)
701 datname = postgres (type: 1)
702 numbackends = 0 (type: 5)
703 xact_commit = 221069 (type: 9)
704 xact_rollback = 18 (type: 9)
705 blks_read = 1176 (type: 9)
706 blks_hit = 13943750 (type: 9)
707 tup_returned = 77410091 (type: 9)
708 tup_fetched = 3253694 (type: 9)
709 tup_inserted = 0 (type: 9)
710 tup_updated = 0 (type: 9)
711 tup_deleted = 0 (type: 9)
712 </pre></div></div><br class="example-break" /></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ecpg-pgtypes.html" title="34.6. pgtypes Library">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ecpg.html" title="Chapter 34. ECPG — Embedded SQL in C">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ecpg-errors.html" title="34.8. Error Handling">Next</a></td></tr><tr><td width="40%" align="left" valign="top">34.6. pgtypes Library </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 34.8. Error Handling</td></tr></table></div></body></html>