Re: Split-up ECPG patches
| От | Boszormenyi Zoltan |
|---|---|
| Тема | Re: Split-up ECPG patches |
| Дата | |
| Msg-id | 4A770C7B.1060404@cybertec.at обсуждение исходный текст |
| Ответ на | Split-up ECPG patches (Böszörményi Zoltán <zb@cybertec.at>) |
| Ответы |
Re: Split-up ECPG patches
Re: Split-up ECPG patches Re: Split-up ECPG patches |
| Список | pgsql-hackers |
Hi,
new versions attached, updated to apply to the current CVS cleanly.
Changes:
- we fixed the case in the dynamic cursor support when
the cursor was declared in a way that the query contained
a WHERE clause, using host variables as parameters.
(leftover bug from our first, non-public, non-parser-only attempt)
- sqlda support:
- sqlda.c now indicates license
- #defines inside #if 0 ... #endif are now omitted from sqltypes.h
(both per comments from Jaime Casanova)
- describe support: there's no separate ECPGdescribe2() now
(as per comment from Michael Meskes, debatable)
- string support: I am doing much less now unconditionally,
most of the parser changes (e.g. introducing STRING_P)
were unnecessary to make it working.
- added to the list my second attempt at fixing struct variable
in INTO list in Informix-mode. This fix (or the real one if
this is not the right approach) should be backpatched,
because the bug is real.
Best regards,
Zoltán Böszörményi
Böszörményi Zoltán írta:
> Hi,
>
> as asked by Michael Meskes, I have split up our ECPG patchset:
> 1. dynamic cursorname (DECLARE :cursorname ..., etc)
> 2. SQLDA support in Informix compat mode (C structure used for
> descriptor and data query)
> 3. DESCRIBE OUTPUT support for named and sqlda descriptors
> 4. "string" pseudo-type in Informix compat mode
>
> Best regards,
> Zoltán Böszörményi
>
> ------------------------------------------------------------------------
>
>
--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/
diff -dcrpN pgsql85dev.0orig/src/backend/parser/gram.y pgsql85dev.1dyncursor/src/backend/parser/gram.y
*** pgsql85dev.0orig/src/backend/parser/gram.y 2009-08-03 10:38:28.000000000 +0200
--- pgsql85dev.1dyncursor/src/backend/parser/gram.y 2009-08-03 15:09:45.000000000 +0200
*************** static TypeName *TableFuncTypeName(List
*** 253,259 ****
%type <str> relation_name copy_file_name
database_name access_method_clause access_method attr_name
! index_name name file_name cluster_index_specification
%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
opt_class opt_validator validator_clause
--- 253,259 ----
%type <str> relation_name copy_file_name
database_name access_method_clause access_method attr_name
! index_name name cursor_name file_name cluster_index_specification
%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
opt_class opt_validator validator_clause
*************** reloption_elem:
*** 1915,1921 ****
*****************************************************************************/
ClosePortalStmt:
! CLOSE name
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2;
--- 1915,1921 ----
*****************************************************************************/
ClosePortalStmt:
! CLOSE cursor_name
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2;
*************** comment_text:
*** 4082,4095 ****
*
*****************************************************************************/
! FetchStmt: FETCH fetch_direction from_in name
{
FetchStmt *n = (FetchStmt *) $2;
n->portalname = $4;
n->ismove = FALSE;
$$ = (Node *)n;
}
! | FETCH name
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
--- 4082,4113 ----
*
*****************************************************************************/
! FetchStmt: FETCH BACKWARD from_in cursor_name
! {
! FetchStmt *n = makeNode(FetchStmt);
! n->portalname = $4;
! n->ismove = FALSE;
! n->direction = FETCH_BACKWARD;
! n->howMany = 1;
! $$ = (Node *)n;
! }
! | FETCH FORWARD from_in cursor_name
! {
! FetchStmt *n = makeNode(FetchStmt);
! n->portalname = $4;
! n->ismove = FALSE;
! n->direction = FETCH_FORWARD;
! n->howMany = 1;
! $$ = (Node *)n;
! }
! | FETCH fetch_direction from_in cursor_name
{
FetchStmt *n = (FetchStmt *) $2;
n->portalname = $4;
n->ismove = FALSE;
$$ = (Node *)n;
}
! | FETCH cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
*************** FetchStmt: FETCH fetch_direction from_in
*** 4098,4111 ****
n->ismove = FALSE;
$$ = (Node *)n;
}
! | MOVE fetch_direction from_in name
{
FetchStmt *n = (FetchStmt *) $2;
n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n;
}
! | MOVE name
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
--- 4116,4147 ----
n->ismove = FALSE;
$$ = (Node *)n;
}
! | MOVE BACKWARD from_in cursor_name
! {
! FetchStmt *n = makeNode(FetchStmt);
! n->portalname = $4;
! n->ismove = TRUE;
! n->direction = FETCH_BACKWARD;
! n->howMany = 1;
! $$ = (Node *)n;
! }
! | MOVE FORWARD from_in cursor_name
! {
! FetchStmt *n = makeNode(FetchStmt);
! n->portalname = $4;
! n->ismove = TRUE;
! n->direction = FETCH_FORWARD;
! n->howMany = 1;
! $$ = (Node *)n;
! }
! | MOVE fetch_direction from_in cursor_name
{
FetchStmt *n = (FetchStmt *) $2;
n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n;
}
! | MOVE cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
*************** fetch_direction:
*** 4180,4192 ****
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | FORWARD
- {
- FetchStmt *n = makeNode(FetchStmt);
- n->direction = FETCH_FORWARD;
- n->howMany = 1;
- $$ = (Node *)n;
- }
| FORWARD SignedIconst
{
FetchStmt *n = makeNode(FetchStmt);
--- 4216,4221 ----
*************** fetch_direction:
*** 4201,4213 ****
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | BACKWARD
- {
- FetchStmt *n = makeNode(FetchStmt);
- n->direction = FETCH_BACKWARD;
- n->howMany = 1;
- $$ = (Node *)n;
- }
| BACKWARD SignedIconst
{
FetchStmt *n = makeNode(FetchStmt);
--- 4230,4235 ----
*************** set_target_list:
*** 6847,6853 ****
* CURSOR STATEMENTS
*
*****************************************************************************/
! DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
{
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
n->portalname = $2;
--- 6869,6875 ----
* CURSOR STATEMENTS
*
*****************************************************************************/
! DeclareCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt
{
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
n->portalname = $2;
*************** DeclareCursorStmt: DECLARE name cursor_o
*** 6858,6863 ****
--- 6880,6888 ----
}
;
+ cursor_name: name { $$ = $1; }
+ ;
+
cursor_options: /*EMPTY*/ { $$ = 0; }
| cursor_options NO SCROLL { $$ = $1 | CURSOR_OPT_NO_SCROLL; }
| cursor_options SCROLL { $$ = $1 | CURSOR_OPT_SCROLL; }
diff -dcrpN pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.addons
pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.addons 2009-01-30 17:28:46.000000000 +0100
--- pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.addons 2009-08-03 15:09:45.000000000 +0200
*************** ECPG: fetch_directionBACKWARDSignedIcons
*** 221,226 ****
--- 221,235 ----
free($2);
$2 = make_str("$0");
}
+ ECPG: cursor_namename rule
+ | char_civar
+ {
+ char *curname = mm_alloc(strlen($1) + 2);
+ sprintf(curname, ":%s", $1);
+ free($1);
+ $1 = curname;
+ $$ = $1;
+ }
ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
{
$$.name = $2;
*************** ECPG: PrepareStmtPREPAREprepared_namepre
*** 235,243 ****
}
ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
{ $$ = $2; }
! ECPG: DeclareCursorStmtDECLAREnamecursor_optionsCURSORopt_holdFORSelectStmt block
{
struct cursor *ptr, *this;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
--- 244,253 ----
}
ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
{ $$ = $2; }
! ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
{
struct cursor *ptr, *this;
+ char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
*************** ECPG: DeclareCursorStmtDECLAREnamecursor
*** 251,257 ****
this->name = $2;
this->connection = connection;
this->opened = false;
! this->command = cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"),
$7);
this->argsinsert = argsinsert;
this->argsresult = argsresult;
argsinsert = argsresult = NULL;
--- 261,267 ----
this->name = $2;
this->connection = connection;
this->opened = false;
! this->command = cat_str(7, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for"),
$7);
this->argsinsert = argsinsert;
this->argsresult = argsresult;
argsinsert = argsresult = NULL;
*************** ECPG: DeclareCursorStmtDECLAREnamecursor
*** 262,267 ****
--- 272,282 ----
else
$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
}
+ ECPG: ClosePortalStmtCLOSEcursor_name block
+ {
+ char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
+ $$ = cat2_str(make_str("close"), cursor_marker);
+ }
ECPG: opt_hold block
{
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
*************** ECPG: VariableShowStmtSHOWALL block
*** 326,371 ****
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
$$ = EMPTY;
}
! ECPG: FetchStmtFETCHfetch_directionfrom_inname block
{
add_additional_variables($4, false);
! $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
}
! ECPG: FetchStmtFETCHname block
{
add_additional_variables($2, false);
! $$ = cat_str(2, make_str("fetch"), $2);
}
! ECPG: FetchStmtMOVEname rule
! | FETCH fetch_direction from_in name ecpg_into
{
add_additional_variables($4, false);
! $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
}
! | FETCH fetch_direction name ecpg_into
{
add_additional_variables($3, false);
! $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
}
! | FETCH from_in name ecpg_into
{
add_additional_variables($3, false);
! $$ = cat_str(3, make_str("fetch"), $2, $3);
}
! | FETCH name ecpg_into
{
add_additional_variables($2, false);
! $$ = cat2_str(make_str("fetch"), $2);
}
! | FETCH fetch_direction name
{
add_additional_variables($3, false);
! $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
}
! | FETCH from_in name
{
add_additional_variables($3, false);
! $$ = cat_str(3, make_str("fetch"), $2, $3);
}
ECPG: SpecialRuleRelationOLD addon
if (!QueryIsRule)
--- 341,442 ----
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
$$ = EMPTY;
}
! ECPG: FetchStmtFETCHBACKWARDfrom_incursor_name block
{
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
! $$ = cat_str(3, make_str("fetch backward"), $3, cursor_marker);
}
! ECPG: FetchStmtFETCHFORWARDfrom_incursor_name block
{
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+ add_additional_variables($4, false);
+ $$ = cat_str(3, make_str("fetch forward"), $3, cursor_marker);
+ }
+ ECPG: FetchStmtFETCHfetch_directionfrom_incursor_name block
+ {
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+ add_additional_variables($4, false);
+ $$ = cat_str(4, make_str("fetch"), $2, $3, cursor_marker);
+ }
+ ECPG: FetchStmtFETCHcursor_name block
+ {
+ char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
add_additional_variables($2, false);
! $$ = cat_str(2, make_str("fetch"), cursor_marker);
}
! ECPG: FetchStmtMOVEcursor_name rule
! | FETCH BACKWARD from_in cursor_name ecpg_into
{
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
! $$ = cat_str(3, make_str("fetch backward"), $3, cursor_marker);
}
! | FETCH FORWARD from_in cursor_name ecpg_into
{
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+ add_additional_variables($4, false);
+ $$ = cat_str(3, make_str("fetch forward"), $3, cursor_marker);
+ }
+ | FETCH fetch_direction from_in cursor_name ecpg_into
+ {
+ char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+ add_additional_variables($4, false);
+ $$ = cat_str(4, make_str("fetch"), $2, $3, cursor_marker);
+ }
+ | FETCH BACKWARD cursor_name ecpg_into
+ {
+ char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
! $$ = cat2_str(make_str("fetch backward from"), cursor_marker);
}
! | FETCH FORWARD cursor_name ecpg_into
{
+ char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
! $$ = cat2_str(make_str("fetch forward from"), cursor_marker);
}
! | FETCH fetch_direction cursor_name ecpg_into
! {
! char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
! add_additional_variables($3, false);
! $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), cursor_marker);
! }
! | FETCH from_in cursor_name ecpg_into
! {
! char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
! add_additional_variables($3, false);
! $$ = cat_str(3, make_str("fetch"), $2, cursor_marker);
! }
! | FETCH cursor_name ecpg_into
{
+ char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
add_additional_variables($2, false);
! $$ = cat2_str(make_str("fetch"), cursor_marker);
}
! | FETCH BACKWARD cursor_name
{
+ char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
! $$ = cat2_str(make_str("fetch backward from"), cursor_marker);
}
! | FETCH FORWARD cursor_name
{
+ char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
! $$ = cat2_str(make_str("fetch forward from"), cursor_marker);
! }
! | FETCH fetch_direction cursor_name
! {
! char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
! add_additional_variables($3, false);
! $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), cursor_marker);
! }
! | FETCH from_in cursor_name
! {
! char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
! add_additional_variables($3, false);
! $$ = cat_str(3, make_str("fetch"), $2, cursor_marker);
}
ECPG: SpecialRuleRelationOLD addon
if (!QueryIsRule)
diff -dcrpN pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.trailer 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 15:09:45.000000000 +0200
*************** prepared_name: name {
*** 284,292 ****
* Declare a prepared cursor. The syntax is different from the standard
* declare statement, so we create a new rule.
*/
! ECPGCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
{
struct cursor *ptr, *this;
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
--- 284,293 ----
* Declare a prepared cursor. The syntax is different from the standard
* declare statement, so we create a new rule.
*/
! ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
{
struct cursor *ptr, *this;
+ char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
*************** ECPGCursorStmt: DECLARE name cursor_opt
*** 303,309 ****
this->next = cur;
this->name = $2;
this->connection = connection;
! this->command = cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for
$1"));
this->argsresult = NULL;
thisquery->type = &ecpg_query;
--- 304,310 ----
this->next = cur;
this->name = $2;
this->connection = connection;
! this->command = cat_str(6, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for
$1"));
this->argsresult = NULL;
thisquery->type = &ecpg_query;
*************** ECPGCursorStmt: DECLARE name cursor_opt
*** 313,318 ****
--- 314,325 ----
sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
this->argsinsert = NULL;
+ if ($2[0] == ':')
+ {
+ struct variable *var = find_variable($2 + 1);
+ remove_variable_from_list(&argsinsert, var);
+ add_variable_to_head(&(this->argsinsert), var, &no_indicator);
+ }
add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
cur = this;
*************** ECPGFree: SQL_FREE name { $$ = $2; }
*** 944,950 ****
/*
* open is an open cursor, at the moment this has to be removed
*/
! ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; }
| ecpg_using { $$ = $1; }
--- 951,966 ----
/*
* open is an open cursor, at the moment this has to be removed
*/
! ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
! {
! if ($2[0] == ':')
! {
! struct variable *var = find_variable($2 + 1);
! remove_variable_from_list(&argsinsert, var);
! }
! $$ = $2;
! }
! ;
opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; }
| ecpg_using { $$ = $1; }
*************** civarind: cvariable indicator
*** 1768,1773 ****
--- 1784,1796 ----
}
;
+ char_civar: char_variable
+ {
+ add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
+ $$ = $1;
+ }
+ ;
+
civar: cvariable
{
add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
diff -dcrpN pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.type
pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql85dev.0orig/src/interfaces/ecpg/preproc/ecpg.type 2008-11-14 11:03:33.000000000 +0100
--- pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.type 2009-08-03 15:09:45.000000000 +0200
***************
*** 43,48 ****
--- 43,49 ----
%type <str> c_term
%type <str> c_thing
%type <str> char_variable
+ %type <str> char_civar
%type <str> civar
%type <str> civarind
%type <str> ColLabel
diff -dcrpN pgsql85dev.0orig/src/interfaces/ecpg/preproc/extern.h
pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/extern.h
*** pgsql85dev.0orig/src/interfaces/ecpg/preproc/extern.h 2009-07-17 07:50:56.000000000 +0200
--- pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/extern.h 2009-08-03 15:09:45.000000000 +0200
*************** extern struct descriptor *lookup_descrip
*** 91,96 ****
--- 91,97 ----
extern struct variable *descriptor_variable(const char *name, int input);
extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
+ extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
extern void dump_variables(struct arguments *, int);
extern struct typedefs *get_typedef(char *);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
diff -dcrpN pgsql85dev.0orig/src/interfaces/ecpg/preproc/variable.c
pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/variable.c
*** pgsql85dev.0orig/src/interfaces/ecpg/preproc/variable.c 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/variable.c 2009-08-03 15:09:45.000000000 +0200
*************** add_variable_to_tail(struct arguments **
*** 401,406 ****
--- 401,430 ----
*list = new;
}
+ void
+ remove_variable_from_list(struct arguments ** list, struct variable * var)
+ {
+ struct arguments *p, *prev = NULL;
+ bool found = false;
+
+ for (p = *list; p; p = p->next)
+ {
+ if (p->variable == var)
+ {
+ found = true;
+ break;
+ }
+ prev = p;
+ }
+ if (found)
+ {
+ if (prev)
+ prev->next = p->next;
+ else
+ *list = p->next;
+ }
+ }
+
/* Dump out a list of all the variable on this list.
This is a recursive function that works from the end of the list and
deletes the list as we go on.
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/execute.c
pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/execute.c 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c 2009-08-03 16:36:23.000000000 +0200
***************
*** 25,30 ****
--- 25,31 ----
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
+ #include "sqlda.h"
#include "sql3types.h"
#include "pgtypes_numeric.h"
#include "pgtypes_date.h"
*************** ecpg_store_input(const int lineno, const
*** 1031,1036 ****
--- 1032,1038 ----
break;
case ECPGt_descriptor:
+ case ECPGt_sqlda:
break;
default:
*************** ecpg_execute(struct statement * stmt)
*** 1170,1175 ****
--- 1172,1233 ----
if (desc->count == desc_counter)
desc_counter = 0;
}
+ else if (var->type == ECPGt_sqlda)
+ {
+ pg_sqlda_t **_sqlda = (pg_sqlda_t **)var->pointer;
+ pg_sqlda_t *sqlda = *_sqlda;
+ struct variable desc_inlist;
+ int i;
+
+ if (sqlda == NULL)
+ return false;
+
+ desc_counter++;
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ if (i + 1 == desc_counter)
+ {
+ desc_inlist.type = ecpg_sqlda_type(sqlda->sqlvar[i].sqltype);
+ desc_inlist.value = sqlda->sqlvar[i].sqldata;
+ desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
+ switch (desc_inlist.type)
+ {
+ case ECPGt_char:
+ case ECPGt_varchar:
+ desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
+ break;
+ default:
+ desc_inlist.varcharsize = 0;
+ break;
+ }
+ desc_inlist.arrsize = 1;
+ desc_inlist.offset = 0;
+ if (sqlda->sqlvar[i].sqlind)
+ {
+ desc_inlist.ind_type = ECPGt_short;
+ /* ECPG expects indicator value < 0 */
+ if (*(sqlda->sqlvar[i].sqlind))
+ *(sqlda->sqlvar[i].sqlind) = -1;
+ desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
+ desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
+ desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
+ desc_inlist.ind_offset = 0;
+ }
+ else
+ {
+ desc_inlist.ind_type = ECPGt_NO_INDICATOR;
+ desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
+ desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
+ }
+ if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
+ return false;
+
+ break;
+ }
+ }
+ if (sqlda->sqld == desc_counter)
+ desc_counter = 0;
+ }
else
{
if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
*************** ecpg_execute(struct statement * stmt)
*** 1351,1356 ****
--- 1409,1435 ----
}
var = var->next;
}
+ else if (var != NULL && var->type == ECPGt_sqlda)
+ {
+ pg_sqlda_t **_sqlda = (pg_sqlda_t **)var->pointer;
+ pg_sqlda_t *sqlda = *_sqlda;
+
+ if (!sqlda)
+ {
+ sqlda = ecpg_build_sqlda_for_PGresult(stmt->lineno, results);
+ if (!sqlda)
+ status = false;
+ else
+ *_sqlda = sqlda;
+ }
+ else if (!ecpg_compare_sqlda_with_PGresult(sqlda, results))
+ status = false;
+
+ if (status == true)
+ ecpg_set_sqlda_from_PGresult(stmt->lineno, _sqlda, results);
+
+ var = var->next;
+ }
else
for (act_field = 0; act_field < nfields && status; act_field++)
{
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/extern.h
pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/extern.h
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/extern.h 2009-05-25 12:08:48.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/extern.h 2009-08-03 15:25:02.000000000 +0200
***************
*** 6,11 ****
--- 6,12 ----
#include "postgres_fe.h"
#include "libpq-fe.h"
#include "sqlca.h"
+ #include "sqlda.h"
#include "ecpg_config.h"
#ifndef CHAR_BIT
#include <limits.h>
*************** bool ecpg_init(const struct connection
*** 129,134 ****
--- 130,137 ----
char *ecpg_strdup(const char *, int);
const char *ecpg_type_name(enum ECPGttype);
int ecpg_dynamic_type(Oid);
+ int ecpg_sqlda_type(int);
+ int ecpg_to_sqlda_type(Oid);
void ecpg_free_auto_mem(void);
void ecpg_clear_auto_mem(void);
*************** void ecpg_log(const char *format,...);
*** 149,154 ****
--- 152,161 ----
bool ecpg_auto_prepare(int, const char *, const int, char **, const char *);
void ecpg_init_sqlca(struct sqlca_t * sqlca);
+ pg_sqlda_t *ecpg_build_sqlda_for_PGresult(int, PGresult *);
+ bool ecpg_compare_sqlda_with_PGresult(pg_sqlda_t *sqlda, const PGresult *results);
+ void ecpg_set_sqlda_from_PGresult(int, pg_sqlda_t **, const PGresult *);
+
/* SQLSTATE values generated or processed by ecpglib (intentionally
* not exported -- users should refer to the codes directly) */
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/Makefile
pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/Makefile
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/Makefile 2009-07-13 11:16:41.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/Makefile 2009-08-03 15:25:02.000000000 +0200
*************** override CFLAGS += $(PTHREAD_CFLAGS)
*** 24,30 ****
# Need to recompile any libpgport object files
LIBS := $(filter-out -lpgport, $(LIBS))
! OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
connect.o misc.o path.o pgstrcasecmp.o \
$(filter snprintf.o strlcpy.o, $(LIBOBJS))
--- 24,30 ----
# Need to recompile any libpgport object files
LIBS := $(filter-out -lpgport, $(LIBS))
! OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
connect.o misc.o path.o pgstrcasecmp.o \
$(filter snprintf.o strlcpy.o, $(LIBOBJS))
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/sqlda.c
pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/sqlda.c
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/sqlda.c 1970-01-01 01:00:00.000000000 +0100
--- pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/sqlda.c 2009-08-03 16:34:12.000000000 +0200
***************
*** 0 ****
--- 1,272 ----
+ /*
+ * Crude SQLDA support routines
+ * Only supports fetching 1 record at a time
+ *
+ * The allocated memory area pointed by an sqlda pointer
+ * contains both the metadata and the data, so freeing up
+ * is a simple free(sqlda) as expected by the ESQL/C examples.
+ *
+ * (C) 2009 Cybertec GmbH
+ * Zoltán Böszörményi <zb@cybertec.at>
+ * Hans-Jürgen Schönig <hs@cybertec.at>
+ * Placed under the same license as PostgreSQL.
+ */
+
+ #define POSTGRES_ECPG_INTERNAL
+ #include "postgres_fe.h"
+ #include "pg_type.h"
+
+ #include <inttypes.h>
+ #include <dlfcn.h>
+
+ #include "ecpg-pthread-win32.h"
+ #include "decimal.h"
+ #include "ecpgtype.h"
+ #include "ecpglib.h"
+ #include "ecpgerrno.h"
+ #include "extern.h"
+ #include "sqlca.h"
+ #include "sqlda.h"
+ #include "sqltypes.h"
+
+ /*
+ * Build pg_sqlda_t (metadata only) from PGresult
+ */
+ pg_sqlda_t *
+ ecpg_build_sqlda_for_PGresult(int line, PGresult *res)
+ {
+ pg_sqlda_t *sqlda;
+ pg_sqlvar_t*sqlvar;
+ char *fname;
+ long size;
+ int i;
+
+ size = sizeof(pg_sqlda_t) + PQnfields(res) * sizeof(pg_sqlvar_t);
+ for (i = 0; i < PQnfields(res); i++)
+ size += strlen(PQfname(res, i)) + 1;
+ /* round allocated size up to the next multiple of 8 */
+ if (size % 8)
+ size += 8 - (size % 8);
+
+ sqlda = (pg_sqlda_t *)ecpg_alloc(size, line);
+ if (!sqlda)
+ {
+ ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
+ return NULL;
+ }
+ memset(sqlda, 0, size);
+ sqlvar = (pg_sqlvar_t *)(sqlda + 1);
+ fname = (char *)(sqlvar + PQnfields(res));
+
+ sqlda->sqld = PQnfields(res);
+ sqlda->desc_occ = size; /* cheat here, keep the full allocated size */
+ sqlda->sqlvar = sqlvar;
+
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ sqlda->sqlvar[i].sqltype = ecpg_to_sqlda_type(PQftype(res, i));
+ strcpy(fname, PQfname(res, i));
+ sqlda->sqlvar[i].sqlname = fname;
+ fname += strlen(sqlda->sqlvar[i].sqlname) + 1;
+ sqlda->sqlvar[i].sqlformat = (char *)(long)PQfformat(res, i);
+ sqlda->sqlvar[i].sqlxid = PQftype(res, i);
+ sqlda->sqlvar[i].sqltypelen = PQfsize(res, i);
+ }
+
+ return sqlda;
+ }
+
+ /*
+ * Check whether the supplied sqlda and PGresult
+ * both has the same metadata
+ */
+ bool
+ ecpg_compare_sqlda_with_PGresult(pg_sqlda_t *sqlda, const PGresult *res)
+ {
+ int i;
+
+ if (sqlda->sqld != PQnfields(res))
+ return false;
+
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ if (sqlda->sqlvar[i].sqltype != ecpg_dynamic_type(PQftype(res, i)))
+ return false;
+ if (strcmp(sqlda->sqlvar[i].sqlname, PQfname(res, i)))
+ return false;
+ if (sqlda->sqlvar[i].sqlformat != (char *)(long)PQfformat(res, i))
+ return false;
+ if (sqlda->sqlvar[i].sqlxid != PQftype(res, i))
+ return false;
+ if (sqlda->sqlvar[i].sqltypelen != PQfsize(res, i))
+ return false;
+ }
+
+ return true;
+ }
+
+ static long
+ ecpg_sqlda_size_round_align(long size, int alignment, int round)
+ {
+ if (size % alignment)
+ size += alignment - (size % alignment);
+ size += round;
+ return size;
+ }
+
+ static long
+ ecpg_sqlda_size_align(long size, int alignment)
+ {
+ if (size % alignment)
+ size += alignment - (size % alignment);
+ return size;
+ }
+
+ /*
+ * Sets values from PGresult.
+ * Reallocates the memory area pointed by *_sqlda if needed
+ */
+ void
+ ecpg_set_sqlda_from_PGresult(int lineno, pg_sqlda_t **_sqlda, const PGresult *res)
+ {
+ pg_sqlda_t *sqlda = (*_sqlda);
+ int i;
+ long size;
+ static int2 value_is_null = 1;
+ static int2 value_is_not_null = 0;
+
+ /* Compute new structure size for allocation */
+ size = sizeof(pg_sqlda_t) + sqlda->sqld * sizeof(pg_sqlvar_t);
+ for (i = 0; i < PQnfields(res); i++)
+ size += strlen(PQfname(res, i)) + 1;
+
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ switch (sqlda->sqlvar[i].sqltype)
+ {
+ case SQLSMINT:
+ size = ecpg_sqlda_size_round_align(size, sizeof(short), sizeof(short));
+ break;
+ case SQLINT:
+ case SQLSERIAL:
+ size = ecpg_sqlda_size_round_align(size, sizeof(int), sizeof(int));
+ break;
+ case SQLFLOAT:
+ size = ecpg_sqlda_size_round_align(size, sizeof(double), sizeof(double));
+ break;
+ case SQLSMFLOAT:
+ size = ecpg_sqlda_size_round_align(size, sizeof(float), sizeof(float));
+ break;
+ case SQLDECIMAL:
+ size = ecpg_sqlda_size_round_align(size, sizeof(int), sizeof(decimal));
+ break;
+ case SQLINT8:
+ case SQLSERIAL8:
+ size = ecpg_sqlda_size_round_align(size, sizeof(int64_t), sizeof(int64_t));
+ break;
+
+ /*
+ * These types will be passed as character strings
+ * until we know what to do with them.
+ */
+ case SQLCHAR:
+ case SQLTEXT:
+ case SQLVCHAR:
+ case SQLNCHAR:
+ case SQLNVCHAR:
+ case SQLMONEY:
+ case SQLDATE:
+ case SQLDTIME:
+ case SQLINTERVAL:
+ default:
+ break;
+ }
+ }
+
+ if (sqlda->desc_occ < size)
+ {
+ sqlda = realloc(sqlda, size);
+ *_sqlda = sqlda;
+ sqlda->desc_occ = size;
+ }
+
+ /*
+ * Set sqlvar[i]->sqldata pointers and convert values to correct format
+ */
+ size = sizeof(pg_sqlda_t) + sqlda->sqld * sizeof(pg_sqlvar_t);
+ for (i = 0; i < PQnfields(res); i++)
+ size += strlen(PQfname(res, i)) + 1;
+
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ switch (sqlda->sqlvar[i].sqltype)
+ {
+ case SQLSMINT:
+ size = ecpg_sqlda_size_align(size, sizeof(short));
+ sscanf(PQgetvalue(res, 0, i), "%hd", (short *)((char *)sqlda + size));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+ size += sizeof(short);
+ break;
+ case SQLINT:
+ case SQLSERIAL:
+ size = ecpg_sqlda_size_align(size, sizeof(int));
+ sscanf(PQgetvalue(res, 0, i), "%d", (int *)((char *)sqlda + size));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+ size += sizeof(int);
+ break;
+ case SQLFLOAT:
+ size = ecpg_sqlda_size_align(size, sizeof(double));
+ sscanf(PQgetvalue(res, 0, i), "%lf", (double *)((char *)sqlda + size));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+ size += sizeof(double);
+ break;
+ case SQLSMFLOAT:
+ size = ecpg_sqlda_size_align(size, sizeof(float));
+ sscanf(PQgetvalue(res, 0, i), "%f", (float *)((char *)sqlda + size));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+ size += sizeof(float);
+ break;
+ case SQLDECIMAL:
+ {
+ size = ecpg_sqlda_size_align(size, sizeof(int));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+
+ ecpg_get_data(res, 0, i, lineno,
+ ECPGt_decimal, ECPGt_NO_INDICATOR,
+ sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
+ ECPG_ARRAY_NONE, ECPG_COMPAT_INFORMIX, false);
+
+ size += sizeof(decimal);
+ break;
+ }
+ case SQLINT8:
+ case SQLSERIAL8:
+ size = ecpg_sqlda_size_align(size, sizeof(int64_t));
+ sscanf(PQgetvalue(res, 0, i), "%" PRId64, (int64_t *)((char *)sqlda + size));
+ sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+ size += sizeof(int64_t);
+ break;
+
+ /*
+ * These types will be passed as character strings until
+ * it's known what to do with them. We use sqlvar->sqldata
+ * in all cases regardless of length, don't care about
+ * sqlvar->sqlilongdata.
+ */
+ case SQLCHAR:
+ case SQLTEXT:
+ case SQLVCHAR:
+ case SQLNCHAR:
+ case SQLNVCHAR:
+ case SQLMONEY:
+ case SQLDATE:
+ case SQLDTIME:
+ case SQLINTERVAL:
+ default:
+ sqlda->sqlvar[i].sqldata = PQgetvalue(res, 0, i);
+ break;
+ }
+
+ sqlda->sqlvar[i].sqlind = PQgetisnull(res, 0, i) ? &value_is_null : &value_is_not_null;
+ }
+ }
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/typename.c
pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/typename.c
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/ecpglib/typename.c 2007-11-15 22:14:45.000000000 +0100
--- pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/typename.c 2009-08-03 16:38:16.000000000 +0200
***************
*** 7,12 ****
--- 7,13 ----
#include "ecpgtype.h"
#include "ecpglib.h"
#include "extern.h"
+ #include "sqltypes.h"
#include "sql3types.h"
#include "pg_type.h"
*************** ecpg_dynamic_type(Oid type)
*** 99,101 ****
--- 100,189 ----
return -(int) type;
}
}
+
+ int
+ ecpg_sqlda_type(int type)
+ {
+ switch (type)
+ {
+ case SQLCHAR:
+ case SQLNCHAR:
+ return ECPGt_char;
+ case SQLSMINT:
+ return ECPGt_short;
+ case SQLINT:
+ return ECPGt_int;
+ case SQLFLOAT:
+ return ECPGt_double;
+ case SQLSMFLOAT:
+ return ECPGt_float;
+ case SQLDECIMAL:
+ return ECPGt_decimal;
+ case SQLSERIAL:
+ return ECPGt_int;
+ case SQLDATE:
+ return ECPGt_date;
+ #if 0
+ case SQLMONEY:
+ return ???;
+ case SQLNULL:
+ return ???;
+ #endif
+ case SQLDTIME:
+ return ECPGt_timestamp;
+ #if 0
+ case SQLBYTES:
+ return ???;
+ #endif
+ case SQLTEXT:
+ return ECPGt_char;
+ case SQLVCHAR:
+ case SQLNVCHAR:
+ return ECPGt_varchar;
+ case SQLINTERVAL:
+ return ECPGt_interval;
+ case SQLINT8:
+ case SQLSERIAL8:
+ return ECPGt_long_long;
+ default:
+ return (-type);
+ }
+ }
+
+ int
+ ecpg_to_sqlda_type(Oid type)
+ {
+ switch (type)
+ {
+ case CHAROID:
+ case BPCHAROID:
+ return SQLCHAR;
+ case INT2OID:
+ return SQLSMINT;
+ case INT4OID:
+ return SQLINT;
+ case FLOAT8OID:
+ return SQLFLOAT;
+ case FLOAT4OID:
+ return SQLSMFLOAT;
+ case NUMERICOID:
+ return SQLDECIMAL;
+ case DATEOID:
+ return SQLDATE;
+ case CASHOID:
+ return SQLMONEY;
+ case TIMESTAMPOID:
+ case TIMESTAMPTZOID:
+ return SQLDTIME;
+ case TEXTOID:
+ return SQLTEXT;
+ case VARCHAROID:
+ return SQLVCHAR;
+ case INTERVALOID:
+ return SQLINTERVAL;
+ case INT8OID:
+ return SQLINT8;
+ default:
+ return (-type);
+ }
+ }
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/include/ecpgtype.h
pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpgtype.h
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/include/ecpgtype.h 2007-08-14 12:01:52.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpgtype.h 2009-08-03 15:25:02.000000000 +0200
*************** enum ECPGttype
*** 61,67 ****
ECPGt_const, /* a constant is needed sometimes */
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
! ECPGt_NO_INDICATOR /* no indicator */
};
/* descriptor items */
--- 61,68 ----
ECPGt_const, /* a constant is needed sometimes */
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
! ECPGt_NO_INDICATOR, /* no indicator */
! ECPGt_sqlda /* INFORMIX-compatible sqlda_t descriptor */
};
/* descriptor items */
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/include/sqlda.h
pgsql85dev.2sqlda/src/interfaces/ecpg/include/sqlda.h
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/include/sqlda.h 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/include/sqlda.h 2009-08-03 15:25:02.000000000 +0200
***************
*** 1,3 ****
--- 1,74 ----
/*
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda.h,v 1.4 2009/06/11 14:49:13 momjian Exp $
*/
+
+ #ifndef POSTGRES_SQLDA_H
+ #define POSTGRES_SQLDA_H
+
+ /* Define Informix "standard" types */
+ #ifndef C_H
+ typedef int int4;
+ typedef short int2;
+ #endif
+ typedef char int1;
+
+ typedef int mint;
+ typedef long mlong;
+
+ typedef short MSHORT;
+ typedef char MCHAR;
+
+ typedef unsigned int uint4;
+ typedef unsigned short uint2;
+ typedef unsigned char uint1;
+
+ typedef unsigned int muint;
+ typedef unsigned long mulong;
+
+ typedef unsigned short MUSHORT;
+ typedef unsigned char MUCHAR;
+
+ #define MI_INT_SIZE (sizeof(int) * 8)
+ #define MI_LONG_SIZE (sizeof(long) * 8)
+ #define MI_PTR_SIZE (sizeof(char *) * 8)
+
+ typedef struct sqlvar_struct
+ {
+ int2 sqltype; /* variable type */
+ int4 sqllen; /* length in bytes */
+ char *sqldata; /* pointer to data */
+ int2 *sqlind; /* pointer to indicator */
+ char *sqlname; /* variable name */
+ char *sqlformat; /* reserved for future use */
+ int2 sqlitype; /* ind variable type */
+ int2 sqlilen; /* ind length in bytes */
+ char *sqlidata; /* ind data pointer */
+ int4 sqlxid; /* extended id type */
+ char *sqltypename; /* extended type name */
+ int2 sqltypelen; /* length of extended type name */
+ int2 sqlownerlen; /* length of owner name */
+ int2 sqlsourcetype; /* source type for distinct of built-ins */
+ char *sqlownername; /* owner name */
+ int4 sqlsourceid; /* extended id of source type */
+
+ /*
+ * sqlilongdata is new. It supports data that exceeds the 32k
+ * limit. sqlilen and sqlidata are for backward compatibility
+ * and they have maximum value of <32K.
+ */
+ char *sqlilongdata; /* for data field beyond 32K */
+ int4 sqlflags; /* for internal use only */
+ void *sqlreserved; /* reserved for future use */
+ } pg_sqlvar_t;
+
+ typedef struct sqlda
+ {
+ int2 sqld;
+ pg_sqlvar_t *sqlvar;
+ char desc_name[19]; /* descriptor name */
+ int2 desc_occ; /* size of sqlda structure */
+ struct sqlda *desc_next; /* pointer to next sqlda struct */
+ void *reserved; /* reserved for future use */
+ } pg_sqlda_t;
+
+ #endif /* POSTGRES_SQLDA_H */
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/include/sqltypes.h
pgsql85dev.2sqlda/src/interfaces/ecpg/include/sqltypes.h
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/include/sqltypes.h 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/include/sqltypes.h 2009-08-03 16:39:30.000000000 +0200
***************
*** 30,33 ****
--- 30,55 ----
#define CLVCHARPTRTYPE 124
#define CTYPEMAX 25
+ /*
+ * Values used in sqlda->sqlvar[i]->sqltype
+ */
+ #define SQLCHAR 0
+ #define SQLSMINT 1
+ #define SQLINT 2
+ #define SQLFLOAT 3
+ #define SQLSMFLOAT 4
+ #define SQLDECIMAL 5
+ #define SQLSERIAL 6
+ #define SQLDATE 7
+ #define SQLMONEY 8
+ #define SQLDTIME 10
+ #define SQLBYTES 11
+ #define SQLTEXT 12
+ #define SQLVCHAR 13
+ #define SQLINTERVAL 14
+ #define SQLNCHAR 15
+ #define SQLNVCHAR 16
+ #define SQLINT8 17
+ #define SQLSERIAL8 18
+
#endif /* ndef ECPG_SQLTYPES_H */
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/descriptor.c
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/descriptor.c
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/descriptor.c 2009-01-30 17:28:46.000000000 +0100
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/descriptor.c 2009-08-03 15:25:02.000000000 +0200
*************** descriptor_variable(const char *name, in
*** 326,328 ****
--- 326,347 ----
strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
return (struct variable *) & varspace[input];
}
+
+ struct variable *
+ sqlda_variable(const char *name)
+ {
+ struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
+
+ p->name = mm_strdup(name);
+ p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
+ p->type->type = ECPGt_sqlda;
+ p->type->size = NULL;
+ p->type->struct_sizeof = NULL;
+ p->type->u.element = NULL;
+ p->type->lineno = 0;
+ p->brace_level = 0;
+ p->next = NULL;
+
+ return p;
+ }
+
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.addons
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.addons 2009-08-03 15:09:45.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons 2009-08-03 15:25:02.000000000 +0200
*************** ECPG: FetchStmtFETCHcursor_name block
*** 366,414 ****
$$ = cat_str(2, make_str("fetch"), cursor_marker);
}
ECPG: FetchStmtMOVEcursor_name rule
! | FETCH BACKWARD from_in cursor_name ecpg_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(3, make_str("fetch backward"), $3, cursor_marker);
}
! | FETCH FORWARD from_in cursor_name ecpg_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(3, make_str("fetch forward"), $3, cursor_marker);
}
! | FETCH fetch_direction from_in cursor_name ecpg_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(4, make_str("fetch"), $2, $3, cursor_marker);
}
! | FETCH BACKWARD cursor_name ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat2_str(make_str("fetch backward from"), cursor_marker);
}
! | FETCH FORWARD cursor_name ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat2_str(make_str("fetch forward from"), cursor_marker);
}
! | FETCH fetch_direction cursor_name ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), cursor_marker);
}
! | FETCH from_in cursor_name ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(3, make_str("fetch"), $2, cursor_marker);
}
! | FETCH cursor_name ecpg_into
{
char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
add_additional_variables($2, false);
--- 366,414 ----
$$ = cat_str(2, make_str("fetch"), cursor_marker);
}
ECPG: FetchStmtMOVEcursor_name rule
! | FETCH BACKWARD from_in cursor_name ecpg_fetch_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(3, make_str("fetch backward"), $3, cursor_marker);
}
! | FETCH FORWARD from_in cursor_name ecpg_fetch_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(3, make_str("fetch forward"), $3, cursor_marker);
}
! | FETCH fetch_direction from_in cursor_name ecpg_fetch_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(4, make_str("fetch"), $2, $3, cursor_marker);
}
! | FETCH BACKWARD cursor_name ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat2_str(make_str("fetch backward from"), cursor_marker);
}
! | FETCH FORWARD cursor_name ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat2_str(make_str("fetch forward from"), cursor_marker);
}
! | FETCH fetch_direction cursor_name ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), cursor_marker);
}
! | FETCH from_in cursor_name ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(3, make_str("fetch"), $2, cursor_marker);
}
! | FETCH cursor_name ecpg_fetch_into
{
char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
add_additional_variables($2, false);
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 15:09:45.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 15:25:02.000000000 +0200
*************** ecpg_using: USING using_list { $$ = EMP
*** 972,990 ****
using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
! add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
$$ = EMPTY;
}
;
into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
! add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
$$ = EMPTY;
}
;
! opt_sql: /*EMPTY*/ | SQL_SQL;
using_list: UsingValue | UsingValue ',' using_list;
--- 972,1020 ----
using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
! if (strlen($2) || !(INFORMIX_MODE))
! add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
! else
! {
! if ($4[0] == '\"')
! {
! char *pos;
!
! $4[0] = ' ';
! for (pos = $4; *pos; pos++)
! if (*pos == '\"')
! *pos = ' ';
! }
! add_variable_to_head(&argsinsert, sqlda_variable($4), &no_indicator);
! }
$$ = EMPTY;
}
;
into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
! if (strlen($2) || !(INFORMIX_MODE))
! add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
! else
! {
! if ($4[0] == '\"')
! {
! char *pos;
!
! $4[0] = ' ';
! for (pos = $4; *pos; pos++)
! if (*pos == '\"')
! *pos = ' ';
! }
! add_variable_to_head(&argsresult, sqlda_variable($4), &no_indicator);
! }
$$ = EMPTY;
}
;
! opt_sql: /*EMPTY*/ { $$ = EMPTY; }
! | SQL_SQL { $$ = make_str("sql"); }
! ;
using_list: UsingValue | UsingValue ',' using_list;
*************** ecpg_into: INTO into_list { $$ = EMPTY;
*** 2006,2011 ****
--- 2036,2056 ----
| into_descriptor { $$ = $1; }
;
+ ecpg_fetch_into: ecpg_into { $$ = $1; }
+ | using_descriptor
+ {
+ struct variable *var;
+
+ if (!INFORMIX_MODE)
+ mmerror(PARSE_ERROR, ET_ERROR, "Not in Informix compatibility mode");
+
+ var = argsinsert->variable;
+ remove_variable_from_list(&argsinsert, var);
+ add_variable_to_head(&argsresult, var, &no_indicator);
+ $$ = $1;
+ }
+ ;
+
%%
void base_yyerror(const char *error)
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.type
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/ecpg.type 2009-08-03 15:09:45.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type 2009-08-03 15:25:02.000000000 +0200
***************
*** 61,66 ****
--- 61,67 ----
%type <str> ecpg_ident
%type <str> ecpg_interval
%type <str> ecpg_into
+ %type <str> ecpg_fetch_into
%type <str> ecpg_param
%type <str> ecpg_sconst
%type <str> ecpg_using
***************
*** 85,90 ****
--- 86,92 ----
%type <str> opt_reference
%type <str> opt_scale
%type <str> opt_server
+ %type <str> opt_sql
%type <str> opt_user
%type <str> opt_opt_value
%type <str> ora_user
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/extern.h
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/extern.h
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/extern.h 2009-08-03 15:09:45.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/extern.h 2009-08-03 15:25:02.000000000 +0200
*************** extern void add_descriptor(char *, char
*** 89,94 ****
--- 89,95 ----
extern void drop_descriptor(char *, char *);
extern struct descriptor *lookup_descriptor(char *, char *);
extern struct variable *descriptor_variable(const char *name, int input);
+ extern struct variable *sqlda_variable(const char *name);
extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
diff -dcrpN pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/type.c
pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/type.c
*** pgsql85dev.1dyncursor/src/interfaces/ecpg/preproc/type.c 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/type.c 2009-08-03 15:25:02.000000000 +0200
*************** ECPGdump_a_simple(FILE *o, const char *n
*** 325,330 ****
--- 325,332 ----
else if (type == ECPGt_descriptor)
/* remember that name here already contains quotes (if needed) */
fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name);
+ else if (type == ECPGt_sqlda)
+ fprintf(o, "\n\tECPGt_sqlda, &%s, 0L, 0L, 0L, ", name);
else
{
char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/descriptor.c
pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/descriptor.c 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c 2009-08-03 15:41:17.000000000 +0200
***************
*** 13,18 ****
--- 13,19 ----
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
+ #include "sqlda.h"
#include "sql3types.h"
static void descriptor_free(struct descriptor * desc);
*************** get_char_item(int lineno, void *var, enu
*** 225,230 ****
--- 226,237 ----
return (true);
}
+ #define RETURN_IF_NO_DATA if (ntuples < 1) \
+ { \
+ ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
+ return (false); \
+ }
+
bool
ECPGget_desc(int lineno, const char *desc_name, int index,...)
{
*************** ECPGget_desc(int lineno, const char *des
*** 243,253 ****
return (false);
ntuples = PQntuples(ECPGresult);
- if (ntuples < 1)
- {
- ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
- return (false);
- }
if (index < 1 || index > PQnfields(ECPGresult))
{
--- 250,255 ----
*************** ECPGget_desc(int lineno, const char *des
*** 282,287 ****
--- 284,290 ----
switch (type)
{
case (ECPGd_indicator):
+ RETURN_IF_NO_DATA;
data_var.ind_type = vartype;
data_var.ind_pointer = var;
data_var.ind_varcharsize = varcharsize;
*************** ECPGget_desc(int lineno, const char *des
*** 294,299 ****
--- 297,303 ----
break;
case ECPGd_data:
+ RETURN_IF_NO_DATA;
data_var.type = vartype;
data_var.pointer = var;
data_var.varcharsize = varcharsize;
*************** ECPGget_desc(int lineno, const char *des
*** 376,381 ****
--- 380,386 ----
case ECPGd_ret_length:
case ECPGd_ret_octet:
+ RETURN_IF_NO_DATA;
/*
* this is like ECPGstore_result
*/
*************** ECPGget_desc(int lineno, const char *des
*** 479,484 ****
--- 484,490 ----
sqlca->sqlerrd[2] = ntuples;
return (true);
}
+ #undef RETURN_IF_NO_DATA
bool
ECPGset_desc_header(int lineno, const char *desc_name, int count)
*************** ecpg_find_desc(int line, const char *nam
*** 721,729 ****
return NULL; /* not found */
}
bool
! ECPGdescribe(int line, bool input, const char *statement,...)
{
! ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);
! return false;
}
--- 727,840 ----
return NULL; /* not found */
}
+ static pg_sqlda_t*
+ build_sqlda(int lineno, bool input, const char *connection_name, const char *stmt_name)
+ {
+ struct connection *con;
+ PGresult *res;
+ pg_sqlda_t *sqlda = NULL;
+
+ con = ecpg_get_connection(connection_name);
+ res = PQdescribePrepared(con->connection, stmt_name);
+ if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_INFORMIX))
+ return NULL;
+
+ sqlda = ecpg_build_sqlda_for_PGresult(lineno, res);
+
+ PQclear(res);
+ return sqlda;
+ }
+
bool
! ECPGdescribe(int line, bool input, const char *connection_name, const char *stmt_name, ...)
{
! bool ret = false;
! va_list args;
!
! /* DESCRIBE INPUT is not yet supported */
! if (input)
! return false;
!
! va_start(args, stmt_name);
!
! for (;;)
! {
! enum ECPGttype type, dummy_type;
! void *ptr, *dummy_ptr;
! long dummy;
!
! /* variable type */
! type = va_arg(args, enum ECPGttype);
!
! if (type == ECPGt_EORT)
! break;
!
! /* rest of variable parameters*/
! ptr = va_arg(args, void *);
! dummy = va_arg(args, long);
! dummy = va_arg(args, long);
! dummy = va_arg(args, long);
!
! /* variable indicator */
! dummy_type = va_arg(args, enum ECPGttype);
! dummy_ptr = va_arg(args, void *);
! dummy = va_arg(args, long);
! dummy = va_arg(args, long);
! dummy = va_arg(args, long);
!
! switch (type)
! {
! case ECPGt_descriptor:
! {
! char *name = ptr;
! struct connection *con = ecpg_get_connection(connection_name);
! struct descriptor *desc = ecpg_find_desc(line, name);
! PGresult *res;
! ExecStatusType ret;
!
! if (con == NULL)
! break;
! if (desc == NULL)
! break;
!
! res = PQdescribePrepared(con->connection, stmt_name);
! ret = PQresultStatus(res);
! if (ecpg_check_PQresult(res, line, con->connection, ECPG_COMPAT_PGSQL))
! {
! if (desc->result != NULL)
! PQclear(desc->result);
! desc->result = res;
! ret = true;
! }
! break;
! }
! case ECPGt_sqlda:
! {
! pg_sqlda_t **sqlda_ptr = ptr;
! pg_sqlda_t *sqlda_new;
!
! sqlda_new = build_sqlda(line, input, connection_name, stmt_name);
! if (sqlda_new)
! {
! #if 0
! /*
! * We should free the old pointer but we can't be sure
! * if the pointer is valid. Only the calling application can.
! */
! pg_sqlda_t *sqlda_old = *sqlda_ptr;
! if (sqlda_old)
! free(sqlda_old);
! #endif
! *sqlda_ptr = sqlda_new;
! ret = true;
! }
! break;
! }
! default:
! /* nothing else may come */
! ;
! }
! }
!
! return ret;
}
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c
pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql85dev.2sqlda/src/interfaces/ecpg/ecpglib/execute.c 2009-08-03 16:36:23.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c 2009-08-03 16:37:09.000000000 +0200
*************** ecpg_store_input(const int lineno, const
*** 1032,1037 ****
--- 1032,1039 ----
break;
case ECPGt_descriptor:
+ break;
+
case ECPGt_sqlda:
break;
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpglib.h
pgsql85dev.3describe/src/interfaces/ecpg/include/ecpglib.h
*** pgsql85dev.2sqlda/src/interfaces/ecpg/include/ecpglib.h 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/include/ecpglib.h 2009-08-03 16:10:33.000000000 +0200
*************** bool ECPGset_desc(int, const char *, in
*** 83,89 ****
void ECPGset_noind_null(enum ECPGttype, void *);
bool ECPGis_noind_null(enum ECPGttype, void *);
! bool ECPGdescribe(int, bool, const char *,...);
/* dynamic result allocation */
void ECPGfree_auto_mem(void);
--- 83,89 ----
void ECPGset_noind_null(enum ECPGttype, void *);
bool ECPGis_noind_null(enum ECPGttype, void *);
! bool ECPGdescribe(int, bool, const char *, const char *, ...);
/* dynamic result allocation */
void ECPGfree_auto_mem(void);
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons
pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.addons 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons 2009-08-03 15:37:11.000000000 +0200
*************** ECPG: VariableShowStmtSHOWALL block
*** 341,347 ****
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
$$ = EMPTY;
}
! ECPG: FetchStmtFETCHBACKWARDfrom_incursor_name block
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
--- 341,347 ----
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
$$ = EMPTY;
}
! ECPG: FetchStmtFETCHBACKWARDfrom_incursor_name block
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 15:28:36.000000000 +0200
*************** ECPGCursorStmt: DECLARE cursor_name cur
*** 321,327 ****
add_variable_to_head(&(this->argsinsert), var, &no_indicator);
}
add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
-
cur = this;
$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
--- 321,326 ----
*************** into_descriptor: INTO opt_sql SQL_DESCRI
*** 1012,1017 ****
--- 1011,1023 ----
}
;
+ into_sqlda: INTO name
+ {
+ add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator);
+ $$ = EMPTY;
+ }
+ ;
+
opt_sql: /*EMPTY*/ { $$ = EMPTY; }
| SQL_SQL { $$ = make_str("sql"); }
;
*************** ECPGDescribe: SQL_DESCRIBE INPUT_P name
*** 1047,1068 ****
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
| SQL_DESCRIBE opt_output name using_descriptor
{
const char *con = connection ? connection : "NULL";
! mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
| SQL_DESCRIBE opt_output name into_descriptor
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
! sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
;
--- 1053,1085 ----
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! $$ = (char *) mm_alloc(sizeof("1, , \"\"") + strlen(con) + strlen($3));
! sprintf($$, "1, %s, \"%s\"", con, $3);
}
| SQL_DESCRIBE opt_output name using_descriptor
{
const char *con = connection ? connection : "NULL";
! $$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
! sprintf($$, "0, %s, \"%s\"", con, $3);
}
| SQL_DESCRIBE opt_output name into_descriptor
{
const char *con = connection ? connection : "NULL";
+ $$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
+ sprintf($$, "0, %s, \"%s\"", con, $3);
+ }
+ | SQL_DESCRIBE INPUT_P name into_sqlda
+ {
+ const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
! $$ = (char *) mm_alloc(sizeof("1, , \"\"") + strlen(con) + strlen($3));
! sprintf($$, "1, %s, \"%s\"", con, $3);
! }
! | SQL_DESCRIBE opt_output name into_sqlda
! {
! const char *con = connection ? connection : "NULL";
! $$ = (char *) mm_alloc(sizeof("0, , \"\"") + strlen(con) + strlen($3));
! sprintf($$, "0, %s, \"%s\"", con, $3);
}
;
diff -dcrpN pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type
pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql85dev.2sqlda/src/interfaces/ecpg/preproc/ecpg.type 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.type 2009-08-03 15:28:36.000000000 +0200
***************
*** 72,77 ****
--- 72,78 ----
%type <str> execute_rest
%type <str> indicator
%type <str> into_descriptor
+ %type <str> into_sqlda
%type <str> Iresult
%type <str> on_off
%type <str> opt_bit_field
***************
*** 86,92 ****
%type <str> opt_reference
%type <str> opt_scale
%type <str> opt_server
! %type <str> opt_sql
%type <str> opt_user
%type <str> opt_opt_value
%type <str> ora_user
--- 87,93 ----
%type <str> opt_reference
%type <str> opt_scale
%type <str> opt_server
! %type <str> opt_sql
%type <str> opt_user
%type <str> opt_opt_value
%type <str> ora_user
diff -dcrpN pgsql85dev.3describe/doc/src/sgml/ecpg.sgml pgsql85dev.4string/doc/src/sgml/ecpg.sgml
*** pgsql85dev.3describe/doc/src/sgml/ecpg.sgml 2009-07-13 11:16:15.000000000 +0200
--- pgsql85dev.4string/doc/src/sgml/ecpg.sgml 2009-08-03 18:03:36.000000000 +0200
*************** void PGTYPESdecimal_free(decimal *var);
*** 2418,2423 ****
--- 2418,2428 ----
know about ranges like for example <literal>YEAR TO MINUTE</> so you won't
find support in ecpg for that either.
</para>
+ <para>
+ The Informix-special "string" pseudo-type for storing right-trimmed character string data is now
+ supported in Informix-mode without using <literal>typedef</literal>. In fact, in Informix-mode,
+ ECPG refuses to process source files that contain <literal>typedef sometype string;</literal>
+ </para>
<sect2>
<title>Additional embedded SQL statements</title>
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c
pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c 2009-01-16 11:45:04.000000000 +0100
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c 2009-08-03 17:01:19.000000000 +0200
*************** ecpg_get_data(const PGresult *results, i
*** 138,143 ****
--- 138,144 ----
case ECPGt_char:
case ECPGt_unsigned_char:
case ECPGt_varchar:
+ case ECPGt_string:
break;
default:
*************** ecpg_get_data(const PGresult *results, i
*** 389,394 ****
--- 390,396 ----
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
if (pval)
{
if (varcharsize == 0 || varcharsize > size)
*************** ecpg_get_data(const PGresult *results, i
*** 426,431 ****
--- 428,454 ----
sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
}
}
+ /* Do the rtrim() */
+ if (type == ECPGt_string)
+ {
+ char *str = (char *) ((long) var + offset * act_tuple);
+ char *last;
+ int len = strlen(str);
+
+ last = str + len;
+ while (last > str)
+ {
+ if (*last == '\0')
+ last--;
+ else if (*last == ' ')
+ {
+ *last = '\0';
+ last--;
+ }
+ else
+ break;
+ }
+ }
pval += size;
}
break;
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c
pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c 2009-08-03 15:41:17.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c 2009-08-03 17:01:19.000000000 +0200
*************** get_char_item(int lineno, void *var, enu
*** 201,206 ****
--- 201,207 ----
{
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
strncpy((char *) var, value, varcharsize);
break;
case ECPGt_varchar:
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c
pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c 2009-08-03 16:37:09.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c 2009-08-03 17:01:19.000000000 +0200
*************** ecpg_store_result(const PGresult *result
*** 360,365 ****
--- 360,366 ----
{
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
if (!var->varcharsize && !var->arrsize)
{
/* special mode for handling char**foo=0 */
*************** ecpg_store_result(const PGresult *result
*** 419,425 ****
/* fill the variable with the tuple(s) */
if (!var->varcharsize && !var->arrsize &&
! (var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
{
/* special mode for handling char**foo=0 */
--- 420,426 ----
/* fill the variable with the tuple(s) */
if (!var->varcharsize && !var->arrsize &&
! (var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
{
/* special mode for handling char**foo=0 */
*************** ecpg_store_input(const int lineno, const
*** 758,763 ****
--- 759,765 ----
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
{
/* set slen to string length if type is char * */
int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int)
var->varcharsize;
*************** ecpg_execute(struct statement * stmt)
*** 1196,1201 ****
--- 1198,1204 ----
{
case ECPGt_char:
case ECPGt_varchar:
+ case ECPGt_string:
desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
break;
default:
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c
pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c 2009-08-03 17:01:19.000000000 +0200
*************** ECPGset_noind_null(enum ECPGttype type,
*** 295,300 ****
--- 295,301 ----
{
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
*((char *) ptr) = '\0';
break;
case ECPGt_short:
*************** ECPGis_noind_null(enum ECPGttype type, v
*** 361,366 ****
--- 362,368 ----
{
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
if (*((char *) ptr) == '\0')
return true;
break;
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c
pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c 2009-08-03 15:28:36.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c 2009-08-03 17:01:19.000000000 +0200
*************** ecpg_type_name(enum ECPGttype typ)
*** 20,25 ****
--- 20,26 ----
switch (typ)
{
case ECPGt_char:
+ case ECPGt_string:
return "char";
case ECPGt_unsigned_char:
return "unsigned char";
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h
pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h
*** pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h 2009-08-03 17:01:19.000000000 +0200
*************** enum ECPGttype
*** 62,68 ****
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR, /* no indicator */
! ECPGt_sqlda /* INFORMIX-compatible sqlda_t descriptor */
};
/* descriptor items */
--- 62,69 ----
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR, /* no indicator */
! ECPGt_sqlda, /* INFORMIX-compatible sqlda_t descriptor */
! ECPGt_string /* trimmed (char *) type */
};
/* descriptor items */
*************** enum ECPGdtype
*** 87,93 ****
ECPGd_cardinality
};
! #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_interval)
/* we also have to handle different statement types */
enum ECPG_statement_type
--- 88,94 ----
ECPGd_cardinality
};
! #define IS_SIMPLE_TYPE(type) (((type) >= ECPGt_char && (type) <= ECPGt_interval) || ((type) == ECPGt_string))
/* we also have to handle different statement types */
enum ECPG_statement_type
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header
pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header 2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header 2009-08-03 18:02:40.000000000 +0200
*************** adjust_informix(struct arguments *list)
*** 256,267 ****
original_var = ptr->variable->name;
sprintf(temp, "%d))", ecpg_informix_var);
! if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char &&
ptr->variable->type->type!= ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
{
ptr->variable = new_variable(cat_str(4, make_str("("),
mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)),make_str(" *)(ECPG_informix_get_var("),
mm_strdup(temp)),ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"),
ptr->variable->type->u.element->lineno),ptr->variable->type->size), 0);
sprintf(temp, "%d, (", ecpg_informix_var++);
}
! else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char ||
ptr->variable->type->type== ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
{
ptr->variable = new_variable(cat_str(4, make_str("("),
mm_strdup(ecpg_type_name(ptr->variable->type->type)),make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)),
ECPGmake_simple_type(ptr->variable->type->type,ptr->variable->type->size, ptr->variable->type->lineno), 0);
sprintf(temp, "%d, (", ecpg_informix_var++);
--- 256,267 ----
original_var = ptr->variable->name;
sprintf(temp, "%d))", ecpg_informix_var);
! if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char &&
ptr->variable->type->type!= ECPGt_unsigned_char && ptr->variable->type->type != ECPGt_string) &&
atoi(ptr->variable->type->size)> 1)
{
ptr->variable = new_variable(cat_str(4, make_str("("),
mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)),make_str(" *)(ECPG_informix_get_var("),
mm_strdup(temp)),ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"),
ptr->variable->type->u.element->lineno),ptr->variable->type->size), 0);
sprintf(temp, "%d, (", ecpg_informix_var++);
}
! else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char ||
ptr->variable->type->type== ECPGt_unsigned_char || ptr->variable->type->type == ECPGt_string) &&
atoi(ptr->variable->type->size)> 1)
{
ptr->variable = new_variable(cat_str(4, make_str("("),
mm_strdup(ecpg_type_name(ptr->variable->type->type)),make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)),
ECPGmake_simple_type(ptr->variable->type->type,ptr->variable->type->size, ptr->variable->type->lineno), 0);
sprintf(temp, "%d, (", ecpg_informix_var++);
*************** add_typedef(char *name, char * dimension
*** 343,348 ****
--- 343,350 ----
type_enum == ECPGt_union) &&
initializer == 1)
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
+ else if (INFORMIX_MODE && strcmp(name, "string") == 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "type name \"string\" is reserved in Informix mode");
else
{
for (ptr = types; ptr != NULL; ptr = ptr->next)
*************** add_typedef(char *name, char * dimension
*** 371,376 ****
--- 373,379 ----
if (type_enum != ECPGt_varchar &&
type_enum != ECPGt_char &&
type_enum != ECPGt_unsigned_char &&
+ type_enum != ECPGt_string &&
atoi(this->type->type_index) >= 0)
mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 16:42:28.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer 2009-08-03 17:11:57.000000000 +0200
*************** char_variable: cvariable
*** 213,218 ****
--- 213,219 ----
{
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
$$ = $1;
break;
case ECPGt_varchar:
*************** var_type: simple_type
*** 597,614 ****
else
{
/* this is for typedef'ed types */
! struct typedefs *this = get_typedef($1);
! $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
! $$.type_enum = this->type->type_enum;
! $$.type_dimension = this->type->type_dimension;
! $$.type_index = this->type->type_index;
! if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
! $$.type_sizeof = this->type->type_sizeof;
! else
! $$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
! struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
}
| s_struct_union_symbol
--- 598,632 ----
else
{
/* this is for typedef'ed types */
! struct typedefs *this = get_typedef($1, FALSE);
! if (this == NULL)
! {
! if ((strcmp($1, "string") == 0) && INFORMIX_MODE)
! {
! $$.type_enum = ECPGt_string;
! $$.type_str = make_str("char");
! $$.type_dimension = make_str("-1");
! $$.type_index = make_str("-1");
! $$.type_sizeof = NULL;
! }
! else
! /* Emit the same error as get_typedef() */
! mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", $1);
! }
! else
! {
! $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
! $$.type_enum = this->type->type_enum;
! $$.type_dimension = this->type->type_dimension;
! $$.type_index = this->type->type_index;
! if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
! $$.type_sizeof = this->type->type_sizeof;
! else
! $$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
! struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
! }
}
}
| s_struct_union_symbol
*************** var_type: simple_type
*** 624,630 ****
{
/* No */
! this = get_typedef(name);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
--- 642,648 ----
{
/* No */
! this = get_typedef(name, TRUE);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
*************** variable: opt_pointer ECPGColLabel opt_a
*** 856,861 ****
--- 874,880 ----
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
if (atoi(dimension) == -1)
{
int i = strlen($5);
*************** ECPGVar: SQL_VAR
*** 1333,1338 ****
--- 1352,1358 ----
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
if (atoi(dimension) == -1)
type = ECPGmake_simple_type($5.type_enum, length, 0);
else
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h
pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h 2009-08-03 17:01:19.000000000 +0200
*************** extern void add_variable_to_head(struct
*** 94,100 ****
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
extern void dump_variables(struct arguments *, int);
! extern struct typedefs *get_typedef(char *);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
extern void reset_variables(void);
extern void check_indicator(struct ECPGtype *);
--- 94,100 ----
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
extern void dump_variables(struct arguments *, int);
! extern struct typedefs *get_typedef(char *, int);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
extern void reset_variables(void);
extern void check_indicator(struct ECPGtype *);
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c
pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c 2009-08-03 15:25:02.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c 2009-08-03 17:01:19.000000000 +0200
*************** get_type(enum ECPGttype type)
*** 200,205 ****
--- 200,208 ----
case ECPGt_timestamp:
return ("ECPGt_timestamp");
break;
+ case ECPGt_string:
+ return ("ECPGt_string");
+ break;
default:
mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type);
}
*************** ECPGdump_a_simple(FILE *o, const char *n
*** 368,373 ****
--- 371,377 ----
case ECPGt_char:
case ECPGt_unsigned_char:
case ECPGt_char_variable:
+ case ECPGt_string:
/*
* we have to use the pointer except for arrays with given
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c
pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c 2009-08-03 15:09:45.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c 2009-08-03 17:01:19.000000000 +0200
*************** check_indicator(struct ECPGtype * var)
*** 486,497 ****
}
struct typedefs *
! get_typedef(char *name)
{
struct typedefs *this;
for (this = types; this && strcmp(this->name, name); this = this->next);
! if (!this)
mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name);
return (this);
--- 486,497 ----
}
struct typedefs *
! get_typedef(char *name, int error)
{
struct typedefs *this;
for (this = types; this && strcmp(this->name, name); this = this->next);
! if (!this && error)
mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name);
return (this);
*************** adjust_array(enum ECPGttype type_enum, c
*** 524,530 ****
"multilevel pointers (more than 2 levels) are not supported; found %d
levels",pointer_len),
pointer_len);
! if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
--- 524,530 ----
"multilevel pointers (more than 2 levels) are not supported; found %d
levels",pointer_len),
pointer_len);
! if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
*************** adjust_array(enum ECPGttype type_enum, c
*** 563,568 ****
--- 563,569 ----
break;
case ECPGt_char:
case ECPGt_unsigned_char:
+ case ECPGt_string:
/* char ** */
if (pointer_len == 2)
{
diff -dcrpN pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header
pgsql85dev.5struct/src/interfaces/ecpg/preproc/ecpg.header
*** pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header 2009-07-15 11:19:06.000000000 +0200
--- pgsql85dev.5struct/src/interfaces/ecpg/preproc/ecpg.header 2009-07-31 11:38:50.000000000 +0200
*************** adjust_informix(struct arguments *list)
*** 266,271 ****
--- 266,273 ----
ptr->variable = new_variable(cat_str(4, make_str("("),
mm_strdup(ecpg_type_name(ptr->variable->type->type)),make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)),
ECPGmake_simple_type(ptr->variable->type->type,ptr->variable->type->size, ptr->variable->type->lineno), 0);
sprintf(temp, "%d, (", ecpg_informix_var++);
}
+ else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union)
+ continue;
else
{
ptr->variable = new_variable(cat_str(4, make_str("*("),
mm_strdup(ecpg_type_name(ptr->variable->type->type)),make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)),
ECPGmake_simple_type(ptr->variable->type->type,ptr->variable->type->size, ptr->variable->type->lineno), 0);
В списке pgsql-hackers по дате отправления: