Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
b3b35e98
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b3b35e98
编写于
2月 17, 2000
作者:
M
Michael Meskes
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
*** empty log message ***
上级
3ca3bb7d
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
855 addition
and
753 deletion
+855
-753
src/interfaces/ecpg/TODO
src/interfaces/ecpg/TODO
+3
-2
src/interfaces/ecpg/lib/README.dynSQL
src/interfaces/ecpg/lib/README.dynSQL
+20
-0
src/interfaces/ecpg/lib/dynamic.c
src/interfaces/ecpg/lib/dynamic.c
+1
-16
src/interfaces/ecpg/preproc/Makefile
src/interfaces/ecpg/preproc/Makefile
+1
-2
src/interfaces/ecpg/preproc/descriptor.c
src/interfaces/ecpg/preproc/descriptor.c
+400
-0
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/ecpg.c
+4
-0
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/extern.h
+23
-3
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/preproc.y
+37
-724
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/type.c
+1
-0
src/interfaces/ecpg/preproc/variable.c
src/interfaces/ecpg/preproc/variable.c
+358
-0
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/Makefile
+1
-1
src/interfaces/ecpg/test/dyntest.pgc
src/interfaces/ecpg/test/dyntest.pgc
+2
-2
src/interfaces/ecpg/test/test4.pgc
src/interfaces/ecpg/test/test4.pgc
+4
-3
未找到文件。
src/interfaces/ecpg/TODO
浏览文件 @
b3b35e98
...
...
@@ -23,8 +23,9 @@ indicator-error?
Add a semantic check level, e.g. check if a table really exists.
It would be nice if there was a alternative library using SPI functions
instead of libpq so we can write backend functions using ecpg.
Missing statements:
- exec sql ifdef
- exec sql allocate
- exec sql deallocate
- SQLSTATE
src/interfaces/ecpg/lib/README.dynSQL
0 → 100644
浏览文件 @
b3b35e98
descriptor statements have the following shortcomings
- up to now the only reasonable statement is
FETCH ... INTO SQL DESCRIPTOR <name>
no input variables allowed!
Reason: to fully support dynamic SQL the frontend/backend communication
should change to recognize input parameters.
Since this is not likely to happen in the near future and you
can cover the same functionality with the existing infrastructure
I'll leave the work to someone else.
- string buffer overflow does not always generate warnings
(beware: terminating 0 may be missing because strncpy is used)
:var=data sets sqlwarn accordingly (but not indicator)
- char variables pointing to NULL are not allocated on demand
- string truncation does not show up in indicator
src/interfaces/ecpg/lib/dynamic.c
浏览文件 @
b3b35e98
...
...
@@ -2,26 +2,11 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.
1 2000/02/16 16:18:12
meskes Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.
2 2000/02/17 19:48:41
meskes Exp $
*/
/* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include <libpq-fe.h>
#include <libpq/pqcomm.h>
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>
#endif
#include <sql3types.h>
static
struct
descriptor
...
...
src/interfaces/ecpg/preproc/Makefile
浏览文件 @
b3b35e98
...
...
@@ -10,8 +10,7 @@ CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DINCLUDE_PATH
=
\"
$(HEADERDIR)
\"
-g
OBJ
=
preproc.o pgc.o type.o ecpg.o ecpg_keywords.o
\
keywords.o c_keywords.o ../lib/typename.o
#../../../backend/parser/scansup.o
keywords.o c_keywords.o ../lib/typename.o descriptor.o variable.o
all
::
ecpg
...
...
src/interfaces/ecpg/preproc/descriptor.c
0 → 100644
浏览文件 @
b3b35e98
/*
* functions needed for descriptor handling
*/
#include "postgres.h"
#include "extern.h"
/*
* assignment handling function (descriptor)
*/
struct
assignment
*
assignments
;
void
push_assignment
(
char
*
var
,
char
*
value
)
{
struct
assignment
*
new
=
(
struct
assignment
*
)
mm_alloc
(
sizeof
(
struct
assignment
));
new
->
next
=
assignments
;
new
->
variable
=
mm_alloc
(
strlen
(
var
)
+
1
);
strcpy
(
new
->
variable
,
var
);
new
->
value
=
mm_alloc
(
strlen
(
value
)
+
1
);
strcpy
(
new
->
value
,
value
);
assignments
=
new
;
}
static
void
drop_assignments
(
void
)
{
while
(
assignments
)
{
struct
assignment
*
old_head
=
assignments
;
assignments
=
old_head
->
next
;
free
(
old_head
->
variable
);
free
(
old_head
->
value
);
free
(
old_head
);
}
}
/* XXX: these should be more accurate (consider ECPGdump_a_* ) */
static
void
ECPGnumeric_lvalue
(
FILE
*
f
,
char
*
name
)
{
const
struct
variable
*
v
=
find_variable
(
name
);
switch
(
v
->
type
->
typ
)
{
case
ECPGt_short
:
case
ECPGt_int
:
case
ECPGt_long
:
case
ECPGt_unsigned_short
:
case
ECPGt_unsigned_int
:
case
ECPGt_unsigned_long
:
fputs
(
name
,
yyout
);
break
;
default:
snprintf
(
errortext
,
sizeof
errortext
,
"variable %s: numeric type needed"
,
name
);
mmerror
(
ET_ERROR
,
errortext
);
break
;
}
}
static
void
ECPGstring_buffer
(
FILE
*
f
,
char
*
name
)
{
const
struct
variable
*
v
=
find_variable
(
name
);
switch
(
v
->
type
->
typ
)
{
case
ECPGt_varchar
:
fprintf
(
yyout
,
"%s.arr"
,
name
);
break
;
case
ECPGt_char
:
case
ECPGt_unsigned_char
:
fputs
(
name
,
yyout
);
break
;
default:
snprintf
(
errortext
,
sizeof
errortext
,
"variable %s: character type needed"
,
name
);
mmerror
(
ET_ERROR
,
errortext
);
break
;
}
}
static
void
ECPGstring_length
(
FILE
*
f
,
char
*
name
)
{
const
struct
variable
*
v
=
find_variable
(
name
);
switch
(
v
->
type
->
typ
)
{
case
ECPGt_varchar
:
case
ECPGt_char
:
case
ECPGt_unsigned_char
:
if
(
!
v
->
type
->
size
)
{
snprintf
(
errortext
,
sizeof
errortext
,
"zero length char variable %s for assignment"
,
v
->
name
);
mmerror
(
ET_ERROR
,
errortext
);
}
fprintf
(
yyout
,
"%ld"
,
v
->
type
->
size
);
break
;
default:
snprintf
(
errortext
,
sizeof
errortext
,
"variable %s: character type needed"
,
name
);
mmerror
(
ET_ERROR
,
errortext
);
break
;
}
}
static
void
ECPGdata_assignment
(
char
*
variable
,
char
*
index_plus_1
)
{
const
struct
variable
*
v
=
find_variable
(
variable
);
fprintf
(
yyout
,
"
\t\t\t
if (!PQgetisnull(ECPGresult,0,(%s)-1))
\n
"
,
index_plus_1
);
switch
(
v
->
type
->
typ
)
{
case
ECPGt_short
:
case
ECPGt_int
:
/* use the same conversion as ecpglib does */
case
ECPGt_long
:
fprintf
(
yyout
,
"
\t\t\t\t
%s=strtol(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);
\n
"
,
variable
,
index_plus_1
);
break
;
case
ECPGt_unsigned_short
:
case
ECPGt_unsigned_int
:
case
ECPGt_unsigned_long
:
fprintf
(
yyout
,
"
\t\t\t\t
%s=strtoul(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);
\n
"
,
variable
,
index_plus_1
);
break
;
case
ECPGt_float
:
case
ECPGt_double
:
fprintf
(
yyout
,
"
\t\t\t\t
%s=strtod(PQgetvalue(ECPGresult,0,(%s)-1),NULL);
\n
"
,
variable
,
index_plus_1
);
break
;
case
ECPGt_bool
:
fprintf
(
yyout
,
"
\t\t\t\t
%s=PQgetvalue(ECPGresult,0,(%s)-1)[0]=='t';
\n
"
,
variable
,
index_plus_1
);
break
;
case
ECPGt_varchar
:
fprintf
(
yyout
,
"
\t\t\t
{
\t
strncpy(%s.arr,PQgetvalue(ECPGresult,0,(%s)-1),%ld);
\n
"
,
variable
,
index_plus_1
,
v
->
type
->
size
);
fprintf
(
yyout
,
"
\t\t\t\t
%s.len=strlen(PQgetvalue(ECPGresult,0,(%s)-1)
\n
"
,
variable
,
index_plus_1
);
fprintf
(
yyout
,
"
\t\t\t\t
if (%s.len>%ld) { %s.len=%ld; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }
\n
"
,
variable
,
v
->
type
->
size
,
variable
,
v
->
type
->
size
);
fputs
(
"
\t\t\t
}
\n
"
,
yyout
);
break
;
case
ECPGt_char
:
case
ECPGt_unsigned_char
:
if
(
!
v
->
type
->
size
)
{
snprintf
(
errortext
,
sizeof
errortext
,
"zero length char variable %s for DATA assignment"
,
v
->
name
);
mmerror
(
ET_ERROR
,
errortext
);
}
fprintf
(
yyout
,
"
\t\t\t
{
\t
strncpy(%s,PQgetvalue(ECPGresult,0,(%s)-1),%ld);
\n
"
,
variable
,
index_plus_1
,
v
->
type
->
size
);
fprintf
(
yyout
,
"
\t\t\t\t
if (strlen(PQgetvalue(ECPGresult,0,(%s)-1))>=%ld)
\n
"
"
\t\t\t\t
{ %s[%ld]=0; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }
\n
"
,
index_plus_1
,
v
->
type
->
size
,
variable
,
v
->
type
->
size
-
1
);
fputs
(
"
\t\t\t
}
\n
"
,
yyout
);
break
;
default:
snprintf
(
errortext
,
sizeof
errortext
,
"unknown variable type %d for DATA assignment"
,
v
->
type
->
typ
);
mmerror
(
ET_ERROR
,
errortext
);
break
;
}
}
void
output_get_descr_header
(
char
*
desc_name
)
{
struct
assignment
*
results
;
fprintf
(
yyout
,
"{
\t
PGresult *ECPGresult=ECPGresultByDescriptor(%d,
\"
%s
\"
);
\n
"
,
yylineno
,
desc_name
);
fputs
(
"
\t
if (ECPGresult)
\n\t
{"
,
yyout
);
for
(
results
=
assignments
;
results
!=
NULL
;
results
=
results
->
next
)
{
if
(
!
strcasecmp
(
results
->
value
,
"count"
))
{
fputs
(
"
\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fputs
(
"=PQnfields(ECPGresult);
\n
"
,
yyout
);
}
else
{
snprintf
(
errortext
,
sizeof
errortext
,
"unknown descriptor header item '%s'"
,
results
->
value
);
mmerror
(
ET_WARN
,
errortext
);
}
}
drop_assignments
();
fputs
(
"}"
,
yyout
);
whenever_action
(
2
|
1
);
}
void
output_get_descr
(
char
*
desc_name
)
{
struct
assignment
*
results
;
int
flags
=
0
;
const
int
DATA_SEEN
=
1
;
const
int
INDICATOR_SEEN
=
2
;
fprintf
(
yyout
,
"{
\t
PGresult *ECPGresult=ECPGresultByDescriptor(%d,
\"
%s
\"
);
\n
"
,
yylineno
,
desc_name
);
fputs
(
"
\t
if (ECPGresult)
\n\t
{"
,
yyout
);
fprintf
(
yyout
,
"
\t
if (PQntuples(ECPGresult)<1) ECPGraise(%d,ECPG_NOT_FOUND);
\n
"
,
yylineno
);
fprintf
(
yyout
,
"
\t\t
else if (%s<1 || %s>PQnfields(ECPGresult))
\n
"
"
\t\t\t
ECPGraise(%d,ECPG_INVALID_DESCRIPTOR_INDEX);
\n
"
,
descriptor_index
,
descriptor_index
,
yylineno
);
fputs
(
"
\t\t
else
\n\t\t
{
\n
"
,
yyout
);
for
(
results
=
assignments
;
results
!=
NULL
;
results
=
results
->
next
)
{
if
(
!
strcasecmp
(
results
->
value
,
"type"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=ECPGDynamicType(PQftype(ECPGresult,(%s)-1));
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"datetime_interval_code"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=ECPGDynamicType_DDT(PQftype(ECPGresult,(%s)-1));
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"length"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=PQfmod(ECPGresult,(%s)-1)-VARHDRSZ;
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"octet_length"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=PQfsize(ECPGresult,(%s)-1);
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"returned_length"
)
||
!
strcasecmp
(
results
->
value
,
"returned_octet_length"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=PQgetlength(ECPGresult,0,(%s)-1);
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"precision"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=PQfmod(ECPGresult,(%s)-1)>>16;
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"scale"
))
{
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=(PQfmod(ECPGresult,(%s)-1)-VARHDRSZ)&0xffff;
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"nullable"
))
{
mmerror
(
ET_WARN
,
"nullable is always 1"
);
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=1;
\n
"
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"key_member"
))
{
mmerror
(
ET_WARN
,
"key_member is always 0"
);
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=0;
\n
"
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"name"
))
{
fputs
(
"
\t\t\t
strncpy("
,
yyout
);
ECPGstring_buffer
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
",PQfname(ECPGresult,(%s)-1),"
,
descriptor_index
);
ECPGstring_length
(
yyout
,
results
->
variable
);
fputs
(
");
\n
"
,
yyout
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"indicator"
))
{
flags
|=
INDICATOR_SEEN
;
fputs
(
"
\t\t\t
"
,
yyout
);
ECPGnumeric_lvalue
(
yyout
,
results
->
variable
);
fprintf
(
yyout
,
"=-PQgetisnull(ECPGresult,0,(%s)-1);
\n
"
,
descriptor_index
);
}
else
if
(
!
strcasecmp
(
results
->
value
,
"data"
))
{
flags
|=
DATA_SEEN
;
ECPGdata_assignment
(
results
->
variable
,
descriptor_index
);
}
else
{
snprintf
(
errortext
,
sizeof
errortext
,
"unknown descriptor header item '%s'"
,
results
->
value
);
mmerror
(
ET_WARN
,
errortext
);
}
}
if
(
flags
==
DATA_SEEN
)
/* no indicator */
{
fprintf
(
yyout
,
"
\t\t\t
if (PQgetisnull(ECPGresult,0,(%s)-1))
\n
"
"
\t\t\t\t
ECPGraise(%d,ECPG_MISSING_INDICATOR);
\n
"
,
descriptor_index
,
yylineno
);
}
drop_assignments
();
fputs
(
"
\t\t
}
\n\t
}
\n
"
,
yyout
);
whenever_action
(
2
|
1
);
}
/*
* descriptor name lookup
*/
static
struct
descriptor
*
descriptors
;
void
add_descriptor
(
char
*
name
,
char
*
connection
)
{
struct
descriptor
*
new
=
(
struct
descriptor
*
)
mm_alloc
(
sizeof
(
struct
descriptor
));
new
->
next
=
descriptors
;
new
->
name
=
mm_alloc
(
strlen
(
name
)
+
1
);
strcpy
(
new
->
name
,
name
);
if
(
connection
)
{
new
->
connection
=
mm_alloc
(
strlen
(
connection
)
+
1
);
strcpy
(
new
->
connection
,
connection
);
}
else
new
->
connection
=
connection
;
descriptors
=
new
;
}
void
drop_descriptor
(
char
*
name
,
char
*
connection
)
{
struct
descriptor
*
i
;
struct
descriptor
**
lastptr
=&
descriptors
;
for
(
i
=
descriptors
;
i
;
lastptr
=&
i
->
next
,
i
=
i
->
next
)
{
if
(
!
strcmp
(
name
,
i
->
name
))
{
if
((
!
connection
&&
!
i
->
connection
)
||
(
connection
&&
i
->
connection
&&
!
strcmp
(
connection
,
i
->
connection
)))
{
*
lastptr
=
i
->
next
;
if
(
i
->
connection
)
free
(
i
->
connection
);
free
(
i
->
name
);
free
(
i
);
return
;
}
}
}
snprintf
(
errortext
,
sizeof
errortext
,
"unknown descriptor %s"
,
name
);
mmerror
(
ET_WARN
,
errortext
);
}
struct
descriptor
*
lookup_descriptor
(
char
*
name
,
char
*
connection
)
{
struct
descriptor
*
i
;
for
(
i
=
descriptors
;
i
;
i
=
i
->
next
)
{
if
(
!
strcmp
(
name
,
i
->
name
))
{
if
((
!
connection
&&
!
i
->
connection
)
||
(
connection
&&
i
->
connection
&&
!
strcmp
(
connection
,
i
->
connection
)))
{
return
i
;
}
}
}
snprintf
(
errortext
,
sizeof
errortext
,
"unknown descriptor %s"
,
name
);
mmerror
(
ET_WARN
,
errortext
);
return
NULL
;
}
void
output_statement_desc
(
char
*
stmt
,
int
mode
)
{
int
i
,
j
=
strlen
(
stmt
);
fprintf
(
yyout
,
"{ ECPGdo_descriptor(__LINE__, %s,
\"
%s
\"
,
\"
"
,
connection
?
connection
:
"NULL"
,
descriptor_name
);
/* do this char by char as we have to filter '\"' */
for
(
i
=
0
;
i
<
j
;
i
++
)
{
if
(
stmt
[
i
]
!=
'\"'
)
fputc
(
stmt
[
i
],
yyout
);
else
fputs
(
"
\\\"
"
,
yyout
);
}
fputs
(
"
\"
);"
,
yyout
);
mode
|=
2
;
whenever_action
(
mode
);
free
(
stmt
);
if
(
connection
!=
NULL
)
free
(
connection
);
free
(
descriptor_name
);
}
src/interfaces/ecpg/preproc/ecpg.c
浏览文件 @
b3b35e98
...
...
@@ -241,6 +241,10 @@ main(int argc, char *const argv[])
/* and structure member lists */
memset
(
struct_member_list
,
0
,
sizeof
(
struct_member_list
));
/* finally the actual connection */
connection
=
NULL
;
/* initialize lex */
lex_init
();
...
...
src/interfaces/ecpg/preproc/extern.h
浏览文件 @
b3b35e98
...
...
@@ -18,6 +18,9 @@ extern int yylineno,
yyleng
;
extern
FILE
*
yyin
,
*
yyout
;
extern
char
*
descriptor_index
;
extern
char
*
descriptor_name
;
extern
char
*
connection
;
extern
struct
_include_path
*
include_paths
;
extern
struct
cursor
*
cur
;
...
...
@@ -42,9 +45,26 @@ extern void yyerror(char *);
extern
void
*
mm_alloc
(
size_t
),
*
mm_realloc
(
void
*
,
size_t
);
extern
char
*
mm_strdup
(
const
char
*
);
extern
void
mmerror
(
enum
errortype
,
char
*
);
ScanKeyword
*
ScanECPGKeywordLookup
(
char
*
);
ScanKeyword
*
ScanCKeywordLookup
(
char
*
);
extern
ScanKeyword
*
ScanECPGKeywordLookup
(
char
*
);
extern
ScanKeyword
*
ScanCKeywordLookup
(
char
*
);
extern
void
output_get_descr_header
(
char
*
);
extern
void
output_get_descr
(
char
*
);
extern
void
push_assignment
(
char
*
,
char
*
);
extern
struct
variable
*
find_variable
(
char
*
);
extern
void
whenever_action
(
int
);
extern
void
add_descriptor
(
char
*
,
char
*
);
extern
void
drop_descriptor
(
char
*
,
char
*
);
extern
struct
descriptor
*
lookup_descriptor
(
char
*
,
char
*
);
extern
void
output_statement_desc
(
char
*
,
int
);
extern
void
add_variable
(
struct
arguments
**
,
struct
variable
*
,
struct
variable
*
);
extern
void
dump_variables
(
struct
arguments
*
,
int
);
extern
struct
typedefs
*
get_typedef
(
char
*
);
extern
void
adjust_array
(
enum
ECPGttype
,
int
*
,
int
*
,
int
,
int
,
bool
);
extern
void
reset_variables
(
void
);
extern
void
check_indicator
(
struct
ECPGtype
*
);
extern
void
remove_variables
(
int
);
extern
struct
variable
*
new_variable
(
const
char
*
,
struct
ECPGtype
*
);
/* return codes */
#define OK 0
...
...
src/interfaces/ecpg/preproc/preproc.y
浏览文件 @
b3b35e98
此差异已折叠。
点击以展开。
src/interfaces/ecpg/preproc/type.c
浏览文件 @
b3b35e98
...
...
@@ -2,6 +2,7 @@
#include <string.h>
#include <stdlib.h>
#include "postgres.h"
#include "extern.h"
/* malloc + error check */
...
...
src/interfaces/ecpg/preproc/variable.c
0 → 100644
浏览文件 @
b3b35e98
#include "postgres.h"
#include "extern.h"
struct
variable
*
allvariables
=
NULL
;
struct
variable
*
new_variable
(
const
char
*
name
,
struct
ECPGtype
*
type
)
{
struct
variable
*
p
=
(
struct
variable
*
)
mm_alloc
(
sizeof
(
struct
variable
));
p
->
name
=
mm_strdup
(
name
);
p
->
type
=
type
;
p
->
brace_level
=
braces_open
;
p
->
next
=
allvariables
;
allvariables
=
p
;
return
(
p
);
}
static
struct
variable
*
find_struct_member
(
char
*
name
,
char
*
str
,
struct
ECPGstruct_member
*
members
)
{
char
*
next
=
strchr
(
++
str
,
'.'
),
c
=
'\0'
;
if
(
next
!=
NULL
)
{
c
=
*
next
;
*
next
=
'\0'
;
}
for
(;
members
;
members
=
members
->
next
)
{
if
(
strcmp
(
members
->
name
,
str
)
==
0
)
{
if
(
c
==
'\0'
)
{
/* found the end */
switch
(
members
->
typ
->
typ
)
{
case
ECPGt_array
:
return
(
new_variable
(
name
,
ECPGmake_array_type
(
members
->
typ
->
u
.
element
,
members
->
typ
->
size
)));
case
ECPGt_struct
:
case
ECPGt_union
:
return
(
new_variable
(
name
,
ECPGmake_struct_type
(
members
->
typ
->
u
.
members
,
members
->
typ
->
typ
)));
default:
return
(
new_variable
(
name
,
ECPGmake_simple_type
(
members
->
typ
->
typ
,
members
->
typ
->
size
)));
}
}
else
{
*
next
=
c
;
if
(
c
==
'-'
)
{
next
++
;
return
(
find_struct_member
(
name
,
next
,
members
->
typ
->
u
.
element
->
u
.
members
));
}
else
return
(
find_struct_member
(
name
,
next
,
members
->
typ
->
u
.
members
));
}
}
}
return
(
NULL
);
}
static
struct
variable
*
find_struct
(
char
*
name
,
char
*
next
)
{
struct
variable
*
p
;
char
c
=
*
next
;
/* first get the mother structure entry */
*
next
=
'\0'
;
p
=
find_variable
(
name
);
if
(
c
==
'-'
)
{
if
(
p
->
type
->
typ
!=
ECPGt_struct
&&
p
->
type
->
typ
!=
ECPGt_union
)
{
sprintf
(
errortext
,
"variable %s is not a pointer"
,
name
);
mmerror
(
ET_FATAL
,
errortext
);
}
if
(
p
->
type
->
u
.
element
->
typ
!=
ECPGt_struct
&&
p
->
type
->
u
.
element
->
typ
!=
ECPGt_union
)
{
sprintf
(
errortext
,
"variable %s is not a pointer to a structure or a union"
,
name
);
mmerror
(
ET_FATAL
,
errortext
);
}
/* restore the name, we will need it later on */
*
next
=
c
;
next
++
;
return
find_struct_member
(
name
,
next
,
p
->
type
->
u
.
element
->
u
.
members
);
}
else
{
if
(
p
->
type
->
typ
!=
ECPGt_struct
&&
p
->
type
->
typ
!=
ECPGt_union
)
{
sprintf
(
errortext
,
"variable %s is neither a structure nor a union"
,
name
);
mmerror
(
ET_FATAL
,
errortext
);
}
/* restore the name, we will need it later on */
*
next
=
c
;
return
find_struct_member
(
name
,
next
,
p
->
type
->
u
.
members
);
}
}
static
struct
variable
*
find_simple
(
char
*
name
)
{
struct
variable
*
p
;
for
(
p
=
allvariables
;
p
;
p
=
p
->
next
)
{
if
(
strcmp
(
p
->
name
,
name
)
==
0
)
return
p
;
}
return
(
NULL
);
}
/* Note that this function will end the program in case of an unknown */
/* variable */
struct
variable
*
find_variable
(
char
*
name
)
{
char
*
next
;
struct
variable
*
p
;
if
((
next
=
strchr
(
name
,
'.'
))
!=
NULL
)
p
=
find_struct
(
name
,
next
);
else
if
((
next
=
strstr
(
name
,
"->"
))
!=
NULL
)
p
=
find_struct
(
name
,
next
);
else
p
=
find_simple
(
name
);
if
(
p
==
NULL
)
{
sprintf
(
errortext
,
"The variable %s is not declared"
,
name
);
mmerror
(
ET_FATAL
,
errortext
);
}
return
(
p
);
}
void
remove_variables
(
int
brace_level
)
{
struct
variable
*
p
,
*
prev
;
for
(
p
=
prev
=
allvariables
;
p
;
p
=
p
?
p
->
next
:
NULL
)
{
if
(
p
->
brace_level
>=
brace_level
)
{
/* remove it */
if
(
p
==
allvariables
)
prev
=
allvariables
=
p
->
next
;
else
prev
->
next
=
p
->
next
;
ECPGfree_type
(
p
->
type
);
free
(
p
->
name
);
free
(
p
);
p
=
prev
;
}
else
prev
=
p
;
}
}
/*
* Here are the variables that need to be handled on every request.
* These are of two kinds: input and output.
* I will make two lists for them.
*/
struct
arguments
*
argsinsert
=
NULL
;
struct
arguments
*
argsresult
=
NULL
;
void
reset_variables
(
void
)
{
argsinsert
=
NULL
;
argsresult
=
NULL
;
}
/* Add a variable to a request. */
void
add_variable
(
struct
arguments
**
list
,
struct
variable
*
var
,
struct
variable
*
ind
)
{
struct
arguments
*
p
=
(
struct
arguments
*
)
mm_alloc
(
sizeof
(
struct
arguments
));
p
->
variable
=
var
;
p
->
indicator
=
ind
;
p
->
next
=
*
list
;
*
list
=
p
;
}
/* 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.
*/
void
dump_variables
(
struct
arguments
*
list
,
int
mode
)
{
if
(
list
==
NULL
)
{
return
;
}
/* The list is build up from the beginning so lets first dump the
end of the list:
*/
dump_variables
(
list
->
next
,
mode
);
/* Then the current element and its indicator */
ECPGdump_a_type
(
yyout
,
list
->
variable
->
name
,
list
->
variable
->
type
,
(
list
->
indicator
->
type
->
typ
!=
ECPGt_NO_INDICATOR
)
?
list
->
indicator
->
name
:
NULL
,
(
list
->
indicator
->
type
->
typ
!=
ECPGt_NO_INDICATOR
)
?
list
->
indicator
->
type
:
NULL
,
NULL
,
NULL
);
/* Then release the list element. */
if
(
mode
!=
0
)
free
(
list
);
}
void
check_indicator
(
struct
ECPGtype
*
var
)
{
/* make sure this is a valid indicator variable */
switch
(
var
->
typ
)
{
struct
ECPGstruct_member
*
p
;
case
ECPGt_short
:
case
ECPGt_int
:
case
ECPGt_long
:
case
ECPGt_unsigned_short
:
case
ECPGt_unsigned_int
:
case
ECPGt_unsigned_long
:
break
;
case
ECPGt_struct
:
case
ECPGt_union
:
for
(
p
=
var
->
u
.
members
;
p
;
p
=
p
->
next
)
check_indicator
(
p
->
typ
);
break
;
case
ECPGt_array
:
check_indicator
(
var
->
u
.
element
);
break
;
default:
mmerror
(
ET_ERROR
,
"indicator variable must be integer type"
);
break
;
}
}
struct
typedefs
*
get_typedef
(
char
*
name
)
{
struct
typedefs
*
this
;
for
(
this
=
types
;
this
&&
strcmp
(
this
->
name
,
name
);
this
=
this
->
next
);
if
(
!
this
)
{
sprintf
(
errortext
,
"invalid datatype '%s'"
,
name
);
mmerror
(
ET_FATAL
,
errortext
);
}
return
(
this
);
}
void
adjust_array
(
enum
ECPGttype
type_enum
,
int
*
dimension
,
int
*
length
,
int
type_dimension
,
int
type_index
,
bool
pointer
)
{
if
(
type_index
>=
0
)
{
if
(
*
length
>=
0
)
mmerror
(
ET_FATAL
,
"No multi-dimensional array support"
);
*
length
=
type_index
;
}
if
(
type_dimension
>=
0
)
{
if
(
*
dimension
>=
0
&&
*
length
>=
0
)
mmerror
(
ET_FATAL
,
"No multi-dimensional array support"
);
if
(
*
dimension
>=
0
)
*
length
=
*
dimension
;
*
dimension
=
type_dimension
;
}
if
(
*
length
>=
0
&&
*
dimension
>=
0
&&
pointer
)
mmerror
(
ET_FATAL
,
"No multi-dimensional array support"
);
switch
(
type_enum
)
{
case
ECPGt_struct
:
case
ECPGt_union
:
/* pointer has to get dimension 0 */
if
(
pointer
)
{
*
length
=
*
dimension
;
*
dimension
=
0
;
}
if
(
*
length
>=
0
)
mmerror
(
ET_FATAL
,
"No multi-dimensional array support for structures"
);
break
;
case
ECPGt_varchar
:
/* pointer has to get dimension 0 */
if
(
pointer
)
*
dimension
=
0
;
/* one index is the string length */
if
(
*
length
<
0
)
{
*
length
=
*
dimension
;
*
dimension
=
-
1
;
}
break
;
case
ECPGt_char
:
case
ECPGt_unsigned_char
:
/* pointer has to get length 0 */
if
(
pointer
)
*
length
=
0
;
/* one index is the string length */
if
(
*
length
<
0
)
{
*
length
=
(
*
dimension
<
0
)
?
1
:
*
dimension
;
*
dimension
=
-
1
;
}
break
;
default:
/* a pointer has dimension = 0 */
if
(
pointer
)
{
*
length
=
*
dimension
;
*
dimension
=
0
;
}
if
(
*
length
>=
0
)
mmerror
(
ET_FATAL
,
"No multi-dimensional array support for simple data types"
);
break
;
}
}
src/interfaces/ecpg/test/Makefile
浏览文件 @
b3b35e98
...
...
@@ -27,4 +27,4 @@ stp.so: stp.c
clean
:
-
/bin/rm test1 test2 test3 test4 test5 perftest
*
.c log stp.o stp.so
-
/bin/rm test1 test2 test3 test4 test5 perftest
*
.c log stp.o stp.so
dyntest
src/interfaces/ecpg/test/dyntest.pgc
浏览文件 @
b3b35e98
...
...
@@ -2,7 +2,7 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.
1 2000/02/16 16:18:29
meskes Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.
2 2000/02/17 19:48:58
meskes Exp $
*/
#include <stdio.h>
...
...
@@ -37,7 +37,7 @@ int main(int argc,char **argv)
exec sql allocate descriptor MYDESC;
exec sql connect to
test
;
exec sql connect to
mm
;
exec sql prepare MYQUERY from :QUERY;
exec sql declare MYCURS cursor for MYQUERY;
...
...
src/interfaces/ecpg/test/test4.pgc
浏览文件 @
b3b35e98
...
...
@@ -43,12 +43,13 @@ EXEC SQL END DECLARE SECTION;
printf("Found f=%f\n", f);
EXEC SQL SELECT
i
INTO :
i
EXEC SQL SELECT
a
INTO :
a
FROM test
WHERE f = :f;
printf("Found i=%d\n", i);
for (i = 0; i < 10; i++)
printf("Found a[%d] = %d\n", i, a[i]);
EXEC SQL DROP TABLE test;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录