Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
efc3a25b
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,发现更多精彩内容 >>
提交
efc3a25b
编写于
6月 21, 2003
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update libpq to make new features of FE/BE protocol available to
client applications. Some editorial work on libpq.sgml, too.
上级
b8d601e7
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
2524 addition
and
832 deletion
+2524
-832
doc/src/sgml/libpq.sgml
doc/src/sgml/libpq.sgml
+1184
-462
doc/src/sgml/lobj.sgml
doc/src/sgml/lobj.sgml
+16
-2
src/interfaces/libpq/blibpqdll.def
src/interfaces/libpq/blibpqdll.def
+28
-1
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-connect.c
+92
-14
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/fe-exec.c
+598
-184
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/fe-misc.c
+14
-22
src/interfaces/libpq/fe-protocol2.c
src/interfaces/libpq/fe-protocol2.c
+183
-11
src/interfaces/libpq/fe-protocol3.c
src/interfaces/libpq/fe-protocol3.c
+266
-74
src/interfaces/libpq/libpq-fe.h
src/interfaces/libpq/libpq-fe.h
+80
-26
src/interfaces/libpq/libpq-int.h
src/interfaces/libpq/libpq-int.h
+49
-35
src/interfaces/libpq/libpqdll.def
src/interfaces/libpq/libpqdll.def
+14
-1
未找到文件。
doc/src/sgml/libpq.sgml
浏览文件 @
efc3a25b
此差异已折叠。
点击以展开。
doc/src/sgml/lobj.sgml
浏览文件 @
efc3a25b
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.2
8 2003/03/13 01:30:28 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.2
9 2003/06/21 21:51:33 tgl
Exp $
-->
-->
<chapter id="largeObjects">
<chapter id="largeObjects">
...
@@ -181,7 +181,8 @@ int lo_open(PGconn *conn, Oid lobjId, int mode);
...
@@ -181,7 +181,8 @@ int lo_open(PGconn *conn, Oid lobjId, int mode);
<function>lo_open</function> returns a large object descriptor
<function>lo_open</function> returns a large object descriptor
for later use in <function>lo_read</function>, <function>lo_write</function>,
for later use in <function>lo_read</function>, <function>lo_write</function>,
<function>lo_lseek</function>, <function>lo_tell</function>, and
<function>lo_lseek</function>, <function>lo_tell</function>, and
<function>lo_close</function>.
<function>lo_close</function>. The descriptor is only valid for
the duration of the current transaction.
</para>
</para>
</sect2>
</sect2>
...
@@ -256,6 +257,11 @@ int lo_close(PGconn *conn, int fd);
...
@@ -256,6 +257,11 @@ int lo_close(PGconn *conn, int fd);
<function>lo_open</function>. On success, <function>lo_close</function>
<function>lo_open</function>. On success, <function>lo_close</function>
returns zero. On error, the return value is negative.
returns zero. On error, the return value is negative.
</para>
</para>
<para>
Any large object descriptors that remain open at the end of a
transaction will be closed automatically.
</para>
</sect2>
</sect2>
<sect2>
<sect2>
...
@@ -296,6 +302,14 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
...
@@ -296,6 +302,14 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
WHERE name = 'beautiful image';
WHERE name = 'beautiful image';
</programlisting>
</programlisting>
</para>
</para>
<para>
These functions read and write files in the server's filesystem, using the
permissions of the database's owning user. Therefore, their use is restricted
to superusers. (In contrast, the client-side import and export functions
read and write files in the client's filesystem, using the permissions of
the client program. Their use is not restricted.)
</para>
</sect1>
</sect1>
<sect1 id="lo-examplesect">
<sect1 id="lo-examplesect">
...
...
src/interfaces/libpq/blibpqdll.def
浏览文件 @
efc3a25b
...
@@ -97,6 +97,20 @@ EXPORTS
...
@@ -97,6 +97,20 @@ EXPORTS
_pg_utf_mblen @ 93
_pg_utf_mblen @ 93
_PQunescapeBytea @ 94
_PQunescapeBytea @ 94
_PQfreemem @ 95
_PQfreemem @ 95
_PQtransactionStatus @ 96
_PQparameterStatus @ 97
_PQprotocolVersion @ 98
_PQsetErrorVerbosity @ 99
_PQsetNoticeReceiver @ 100
_PQexecParams @ 101
_PQsendQueryParams @ 102
_PQputCopyData @ 103
_PQputCopyEnd @ 104
_PQgetCopyData @ 105
_PQresultErrorField @ 106
_PQftable @ 107
_PQftablecol @ 108
_PQfformat @ 109
; Aliases for MS compatible names
; Aliases for MS compatible names
PQconnectdb = _PQconnectdb
PQconnectdb = _PQconnectdb
...
@@ -194,4 +208,17 @@ EXPORTS
...
@@ -194,4 +208,17 @@ EXPORTS
pg_utf_mblen = _pg_utf_mblen
pg_utf_mblen = _pg_utf_mblen
PQunescapeBytea = _PQunescapeBytea
PQunescapeBytea = _PQunescapeBytea
PQfreemem = _PQfreemem
PQfreemem = _PQfreemem
PQtransactionStatus = _PQtransactionStatus
PQparameterStatus = _PQparameterStatus
PQprotocolVersion = _PQprotocolVersion
PQsetErrorVerbosity = _PQsetErrorVerbosity
PQsetNoticeReceiver = _PQsetNoticeReceiver
PQexecParams = _PQexecParams
PQsendQueryParams = _PQsendQueryParams
PQputCopyData = _PQputCopyData
PQputCopyEnd = _PQputCopyEnd
PQgetCopyData = _PQgetCopyData
PQresultErrorField = _PQresultErrorField
PQftable = _PQftable
PQftablecol = _PQftablecol
PQfformat = _PQfformat
src/interfaces/libpq/fe-connect.c
浏览文件 @
efc3a25b
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.2
49 2003/06/20 04:09:12
tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.2
50 2003/06/21 21:51:33
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -176,6 +176,7 @@ static PQconninfoOption *conninfo_parse(const char *conninfo,
...
@@ -176,6 +176,7 @@ static PQconninfoOption *conninfo_parse(const char *conninfo,
PQExpBuffer
errorMessage
);
PQExpBuffer
errorMessage
);
static
char
*
conninfo_getval
(
PQconninfoOption
*
connOptions
,
static
char
*
conninfo_getval
(
PQconninfoOption
*
connOptions
,
const
char
*
keyword
);
const
char
*
keyword
);
static
void
defaultNoticeReceiver
(
void
*
arg
,
const
PGresult
*
res
);
static
void
defaultNoticeProcessor
(
void
*
arg
,
const
char
*
message
);
static
void
defaultNoticeProcessor
(
void
*
arg
,
const
char
*
message
);
static
int
parseServiceInfo
(
PQconninfoOption
*
options
,
static
int
parseServiceInfo
(
PQconninfoOption
*
options
,
PQExpBuffer
errorMessage
);
PQExpBuffer
errorMessage
);
...
@@ -1804,11 +1805,14 @@ makeEmptyPGconn(void)
...
@@ -1804,11 +1805,14 @@ makeEmptyPGconn(void)
/* Zero all pointers and booleans */
/* Zero all pointers and booleans */
MemSet
((
char
*
)
conn
,
0
,
sizeof
(
PGconn
));
MemSet
((
char
*
)
conn
,
0
,
sizeof
(
PGconn
));
conn
->
noticeHook
=
defaultNoticeProcessor
;
conn
->
noticeHooks
.
noticeRec
=
defaultNoticeReceiver
;
conn
->
noticeHooks
.
noticeProc
=
defaultNoticeProcessor
;
conn
->
status
=
CONNECTION_BAD
;
conn
->
status
=
CONNECTION_BAD
;
conn
->
asyncStatus
=
PGASYNC_IDLE
;
conn
->
asyncStatus
=
PGASYNC_IDLE
;
conn
->
xactStatus
=
PQTRANS_IDLE
;
conn
->
setenv_state
=
SETENV_STATE_IDLE
;
conn
->
setenv_state
=
SETENV_STATE_IDLE
;
conn
->
client_encoding
=
PG_SQL_ASCII
;
conn
->
client_encoding
=
PG_SQL_ASCII
;
conn
->
verbosity
=
PQERRORS_DEFAULT
;
conn
->
notifyList
=
DLNewList
();
conn
->
notifyList
=
DLNewList
();
conn
->
sock
=
-
1
;
conn
->
sock
=
-
1
;
#ifdef USE_SSL
#ifdef USE_SSL
...
@@ -1850,7 +1854,6 @@ makeEmptyPGconn(void)
...
@@ -1850,7 +1854,6 @@ makeEmptyPGconn(void)
/*
/*
* freePGconn
* freePGconn
* - free the PGconn data structure
* - free the PGconn data structure
*
*/
*/
static
void
static
void
freePGconn
(
PGconn
*
conn
)
freePGconn
(
PGconn
*
conn
)
...
@@ -1899,9 +1902,9 @@ freePGconn(PGconn *conn)
...
@@ -1899,9 +1902,9 @@ freePGconn(PGconn *conn)
}
}
/*
/*
closePGconn
*
closePGconn
- properly close a connection to the backend
*
- properly close a connection to the backend
*/
*/
static
void
static
void
closePGconn
(
PGconn
*
conn
)
closePGconn
(
PGconn
*
conn
)
{
{
...
@@ -2662,6 +2665,41 @@ PQstatus(const PGconn *conn)
...
@@ -2662,6 +2665,41 @@ PQstatus(const PGconn *conn)
return
conn
->
status
;
return
conn
->
status
;
}
}
PGTransactionStatusType
PQtransactionStatus
(
const
PGconn
*
conn
)
{
if
(
!
conn
||
conn
->
status
!=
CONNECTION_OK
)
return
PQTRANS_UNKNOWN
;
if
(
conn
->
asyncStatus
!=
PGASYNC_IDLE
)
return
PQTRANS_ACTIVE
;
return
conn
->
xactStatus
;
}
const
char
*
PQparameterStatus
(
const
PGconn
*
conn
,
const
char
*
paramName
)
{
const
pgParameterStatus
*
pstatus
;
if
(
!
conn
||
!
paramName
)
return
NULL
;
for
(
pstatus
=
conn
->
pstatus
;
pstatus
!=
NULL
;
pstatus
=
pstatus
->
next
)
{
if
(
strcmp
(
pstatus
->
name
,
paramName
)
==
0
)
return
pstatus
->
value
;
}
return
NULL
;
}
int
PQprotocolVersion
(
const
PGconn
*
conn
)
{
if
(
!
conn
)
return
0
;
if
(
conn
->
status
==
CONNECTION_BAD
)
return
0
;
return
PG_PROTOCOL_MAJOR
(
conn
->
pversion
);
}
char
*
char
*
PQerrorMessage
(
const
PGconn
*
conn
)
PQerrorMessage
(
const
PGconn
*
conn
)
{
{
...
@@ -2731,11 +2769,22 @@ PQsetClientEncoding(PGconn *conn, const char *encoding)
...
@@ -2731,11 +2769,22 @@ PQsetClientEncoding(PGconn *conn, const char *encoding)
return
(
status
);
return
(
status
);
}
}
PGVerbosity
PQsetErrorVerbosity
(
PGconn
*
conn
,
PGVerbosity
verbosity
)
{
PGVerbosity
old
;
if
(
!
conn
)
return
PQERRORS_DEFAULT
;
old
=
conn
->
verbosity
;
conn
->
verbosity
=
verbosity
;
return
old
;
}
void
void
PQtrace
(
PGconn
*
conn
,
FILE
*
debug_port
)
PQtrace
(
PGconn
*
conn
,
FILE
*
debug_port
)
{
{
if
(
conn
==
NULL
||
if
(
conn
==
NULL
)
conn
->
status
==
CONNECTION_BAD
)
return
;
return
;
PQuntrace
(
conn
);
PQuntrace
(
conn
);
conn
->
Pfdebug
=
debug_port
;
conn
->
Pfdebug
=
debug_port
;
...
@@ -2744,7 +2793,6 @@ PQtrace(PGconn *conn, FILE *debug_port)
...
@@ -2744,7 +2793,6 @@ PQtrace(PGconn *conn, FILE *debug_port)
void
void
PQuntrace
(
PGconn
*
conn
)
PQuntrace
(
PGconn
*
conn
)
{
{
/* note: better allow untrace even when connection bad */
if
(
conn
==
NULL
)
if
(
conn
==
NULL
)
return
;
return
;
if
(
conn
->
Pfdebug
)
if
(
conn
->
Pfdebug
)
...
@@ -2754,6 +2802,23 @@ PQuntrace(PGconn *conn)
...
@@ -2754,6 +2802,23 @@ PQuntrace(PGconn *conn)
}
}
}
}
PQnoticeReceiver
PQsetNoticeReceiver
(
PGconn
*
conn
,
PQnoticeReceiver
proc
,
void
*
arg
)
{
PQnoticeReceiver
old
;
if
(
conn
==
NULL
)
return
NULL
;
old
=
conn
->
noticeHooks
.
noticeRec
;
if
(
proc
)
{
conn
->
noticeHooks
.
noticeRec
=
proc
;
conn
->
noticeHooks
.
noticeRecArg
=
arg
;
}
return
old
;
}
PQnoticeProcessor
PQnoticeProcessor
PQsetNoticeProcessor
(
PGconn
*
conn
,
PQnoticeProcessor
proc
,
void
*
arg
)
PQsetNoticeProcessor
(
PGconn
*
conn
,
PQnoticeProcessor
proc
,
void
*
arg
)
{
{
...
@@ -2762,22 +2827,35 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
...
@@ -2762,22 +2827,35 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
if
(
conn
==
NULL
)
if
(
conn
==
NULL
)
return
NULL
;
return
NULL
;
old
=
conn
->
noticeHook
;
old
=
conn
->
noticeHook
s
.
noticeProc
;
if
(
proc
)
if
(
proc
)
{
{
conn
->
noticeHook
=
proc
;
conn
->
noticeHook
s
.
noticeProc
=
proc
;
conn
->
noticeArg
=
arg
;
conn
->
notice
Hooks
.
noticeProc
Arg
=
arg
;
}
}
return
old
;
return
old
;
}
}
/*
/*
* The default notice/error message processor just prints the
* The default notice message receiver just gets the standard notice text
* and sends it to the notice processor. This two-level setup exists
* mostly for backwards compatibility; perhaps we should deprecate use of
* PQsetNoticeProcessor?
*/
static
void
defaultNoticeReceiver
(
void
*
arg
,
const
PGresult
*
res
)
{
(
void
)
arg
;
/* not used */
(
*
res
->
noticeHooks
.
noticeProc
)
(
res
->
noticeHooks
.
noticeProcArg
,
PQresultErrorMessage
(
res
));
}
/*
* The default notice message processor just prints the
* message on stderr. Applications can override this if they
* message on stderr. Applications can override this if they
* want the messages to go elsewhere (a window, for example).
* want the messages to go elsewhere (a window, for example).
* Note that simply discarding notices is probably a bad idea.
* Note that simply discarding notices is probably a bad idea.
*/
*/
static
void
static
void
defaultNoticeProcessor
(
void
*
arg
,
const
char
*
message
)
defaultNoticeProcessor
(
void
*
arg
,
const
char
*
message
)
{
{
...
...
src/interfaces/libpq/fe-exec.c
浏览文件 @
efc3a25b
此差异已折叠。
点击以展开。
src/interfaces/libpq/fe-misc.c
浏览文件 @
efc3a25b
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.9
6 2003/06/14 17:49:54 momjian
Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.9
7 2003/06/21 21:51:34 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -197,7 +197,7 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
...
@@ -197,7 +197,7 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
}
}
/*
/*
* p
g
GetInt
* p
q
GetInt
* read a 2 or 4 byte integer and convert from network byte order
* read a 2 or 4 byte integer and convert from network byte order
* to local byte order
* to local byte order
*/
*/
...
@@ -226,7 +226,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
...
@@ -226,7 +226,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
break
;
break
;
default:
default:
snprintf
(
noticeBuf
,
sizeof
(
noticeBuf
),
snprintf
(
noticeBuf
,
sizeof
(
noticeBuf
),
libpq_gettext
(
"integer of size %lu not supported by pqGetInt
\n
"
),
libpq_gettext
(
"integer of size %lu not supported by pqGetInt"
),
(
unsigned
long
)
bytes
);
(
unsigned
long
)
bytes
);
PGDONOTICE
(
conn
,
noticeBuf
);
PGDONOTICE
(
conn
,
noticeBuf
);
return
EOF
;
return
EOF
;
...
@@ -239,7 +239,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
...
@@ -239,7 +239,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
}
}
/*
/*
* p
g
PutInt
* p
q
PutInt
* write an integer of 2 or 4 bytes, converting from host byte order
* write an integer of 2 or 4 bytes, converting from host byte order
* to network byte order.
* to network byte order.
*/
*/
...
@@ -264,7 +264,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
...
@@ -264,7 +264,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
break
;
break
;
default:
default:
snprintf
(
noticeBuf
,
sizeof
(
noticeBuf
),
snprintf
(
noticeBuf
,
sizeof
(
noticeBuf
),
libpq_gettext
(
"integer of size %lu not supported by pqPutInt
\n
"
),
libpq_gettext
(
"integer of size %lu not supported by pqPutInt"
),
(
unsigned
long
)
bytes
);
(
unsigned
long
)
bytes
);
PGDONOTICE
(
conn
,
noticeBuf
);
PGDONOTICE
(
conn
,
noticeBuf
);
return
EOF
;
return
EOF
;
...
@@ -282,7 +282,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
...
@@ -282,7 +282,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
*
*
* Returns 0 on success, EOF if failed to enlarge buffer
* Returns 0 on success, EOF if failed to enlarge buffer
*/
*/
static
int
int
pqCheckOutBufferSpace
(
int
bytes_needed
,
PGconn
*
conn
)
pqCheckOutBufferSpace
(
int
bytes_needed
,
PGconn
*
conn
)
{
{
int
newsize
=
conn
->
outBufSize
;
int
newsize
=
conn
->
outBufSize
;
...
@@ -748,7 +748,7 @@ pqSendSome(PGconn *conn, int len)
...
@@ -748,7 +748,7 @@ pqSendSome(PGconn *conn, int len)
if
(
sent
<
0
)
if
(
sent
<
0
)
{
{
/*
/*
* Anything except EAGAIN
or EWOULDBLOCK
is trouble. If it's
* Anything except EAGAIN
/EWOULDBLOCK/EINTR
is trouble. If it's
* EPIPE or ECONNRESET, assume we've lost the backend
* EPIPE or ECONNRESET, assume we've lost the backend
* connection permanently.
* connection permanently.
*/
*/
...
@@ -804,25 +804,17 @@ pqSendSome(PGconn *conn, int len)
...
@@ -804,25 +804,17 @@ pqSendSome(PGconn *conn, int len)
if
(
len
>
0
)
if
(
len
>
0
)
{
{
/* We didn't send it all, wait till we can send more */
/*
/*
* if the socket is in non-blocking mode we may need to abort
* We didn't send it all, wait till we can send more.
* here and return 1 to indicate that data is still pending.
*
* If the connection is in non-blocking mode we don't wait,
* but return 1 to indicate that data is still pending.
*/
*/
#ifdef USE_SSL
if
(
pqIsnonblocking
(
conn
))
/* can't do anything for our SSL users yet */
if
(
conn
->
ssl
==
NULL
)
{
{
#endif
result
=
1
;
if
(
pqIsnonblocking
(
conn
))
break
;
{
result
=
1
;
break
;
}
#ifdef USE_SSL
}
}
#endif
if
(
pqWait
(
FALSE
,
TRUE
,
conn
))
if
(
pqWait
(
FALSE
,
TRUE
,
conn
))
{
{
...
...
src/interfaces/libpq/fe-protocol2.c
浏览文件 @
efc3a25b
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.
1 2003/06/08 17:43:00
tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.
2 2003/06/21 21:51:34
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -38,6 +38,7 @@
...
@@ -38,6 +38,7 @@
static
int
getRowDescriptions
(
PGconn
*
conn
);
static
int
getRowDescriptions
(
PGconn
*
conn
);
static
int
getAnotherTuple
(
PGconn
*
conn
,
bool
binary
);
static
int
getAnotherTuple
(
PGconn
*
conn
,
bool
binary
);
static
int
pqGetErrorNotice2
(
PGconn
*
conn
,
bool
isError
);
static
int
pqGetErrorNotice2
(
PGconn
*
conn
,
bool
isError
);
static
void
checkXactStatus
(
PGconn
*
conn
,
const
char
*
cmdTag
);
static
int
getNotify
(
PGconn
*
conn
);
static
int
getNotify
(
PGconn
*
conn
);
...
@@ -312,7 +313,7 @@ pqSetenvPoll(PGconn *conn)
...
@@ -312,7 +313,7 @@ pqSetenvPoll(PGconn *conn)
val
);
val
);
else
else
{
{
val
=
pqGetP
arameterStatus
(
conn
,
"server_encoding"
);
val
=
PQp
arameterStatus
(
conn
,
"server_encoding"
);
if
(
val
&&
*
val
)
if
(
val
&&
*
val
)
pqSaveParameterStatus
(
conn
,
"client_encoding"
,
pqSaveParameterStatus
(
conn
,
"client_encoding"
,
val
);
val
);
...
@@ -424,7 +425,7 @@ pqParseInput2(PGconn *conn)
...
@@ -424,7 +425,7 @@ pqParseInput2(PGconn *conn)
else
else
{
{
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
libpq_gettext
(
"message type 0x%02x arrived from server while idle
\n
"
),
libpq_gettext
(
"message type 0x%02x arrived from server while idle"
),
id
);
id
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
/* Discard the unexpected message; good idea?? */
/* Discard the unexpected message; good idea?? */
...
@@ -447,6 +448,7 @@ pqParseInput2(PGconn *conn)
...
@@ -447,6 +448,7 @@ pqParseInput2(PGconn *conn)
PGRES_COMMAND_OK
);
PGRES_COMMAND_OK
);
strncpy
(
conn
->
result
->
cmdStatus
,
conn
->
workBuffer
.
data
,
strncpy
(
conn
->
result
->
cmdStatus
,
conn
->
workBuffer
.
data
,
CMDSTATUS_LEN
);
CMDSTATUS_LEN
);
checkXactStatus
(
conn
,
conn
->
workBuffer
.
data
);
conn
->
asyncStatus
=
PGASYNC_READY
;
conn
->
asyncStatus
=
PGASYNC_READY
;
break
;
break
;
case
'E'
:
/* error return */
case
'E'
:
/* error return */
...
@@ -464,7 +466,7 @@ pqParseInput2(PGconn *conn)
...
@@ -464,7 +466,7 @@ pqParseInput2(PGconn *conn)
if
(
id
!=
'\0'
)
if
(
id
!=
'\0'
)
{
{
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
libpq_gettext
(
"unexpected character %c following empty query response (
\"
I
\"
message)
\n
"
),
libpq_gettext
(
"unexpected character %c following empty query response (
\"
I
\"
message)"
),
id
);
id
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
}
}
...
@@ -521,7 +523,7 @@ pqParseInput2(PGconn *conn)
...
@@ -521,7 +523,7 @@ pqParseInput2(PGconn *conn)
else
else
{
{
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
libpq_gettext
(
"server sent data (
\"
D
\"
message) without prior row description (
\"
T
\"
message)
\n
"
));
libpq_gettext
(
"server sent data (
\"
D
\"
message) without prior row description (
\"
T
\"
message)"
));
PGDONOTICE
(
conn
,
noticeWorkspace
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
/* Discard the unexpected message; good idea?? */
/* Discard the unexpected message; good idea?? */
conn
->
inStart
=
conn
->
inEnd
;
conn
->
inStart
=
conn
->
inEnd
;
...
@@ -538,7 +540,7 @@ pqParseInput2(PGconn *conn)
...
@@ -538,7 +540,7 @@ pqParseInput2(PGconn *conn)
else
else
{
{
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
libpq_gettext
(
"server sent binary data (
\"
B
\"
message) without prior row description (
\"
T
\"
message)
\n
"
));
libpq_gettext
(
"server sent binary data (
\"
B
\"
message) without prior row description (
\"
T
\"
message)"
));
PGDONOTICE
(
conn
,
noticeWorkspace
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
/* Discard the unexpected message; good idea?? */
/* Discard the unexpected message; good idea?? */
conn
->
inStart
=
conn
->
inEnd
;
conn
->
inStart
=
conn
->
inEnd
;
...
@@ -628,6 +630,9 @@ getRowDescriptions(PGconn *conn)
...
@@ -628,6 +630,9 @@ getRowDescriptions(PGconn *conn)
result
->
attDescs
[
i
].
name
=
pqResultStrdup
(
result
,
result
->
attDescs
[
i
].
name
=
pqResultStrdup
(
result
,
conn
->
workBuffer
.
data
);
conn
->
workBuffer
.
data
);
result
->
attDescs
[
i
].
tableid
=
0
;
result
->
attDescs
[
i
].
columnid
=
0
;
result
->
attDescs
[
i
].
format
=
0
;
result
->
attDescs
[
i
].
typid
=
typid
;
result
->
attDescs
[
i
].
typid
=
typid
;
result
->
attDescs
[
i
].
typlen
=
typlen
;
result
->
attDescs
[
i
].
typlen
=
typlen
;
result
->
attDescs
[
i
].
atttypmod
=
atttypmod
;
result
->
attDescs
[
i
].
atttypmod
=
atttypmod
;
...
@@ -674,6 +679,15 @@ getAnotherTuple(PGconn *conn, bool binary)
...
@@ -674,6 +679,15 @@ getAnotherTuple(PGconn *conn, bool binary)
if
(
conn
->
curTuple
==
NULL
)
if
(
conn
->
curTuple
==
NULL
)
goto
outOfMemory
;
goto
outOfMemory
;
MemSet
((
char
*
)
conn
->
curTuple
,
0
,
nfields
*
sizeof
(
PGresAttValue
));
MemSet
((
char
*
)
conn
->
curTuple
,
0
,
nfields
*
sizeof
(
PGresAttValue
));
/*
* If it's binary, fix the column format indicators. We assume
* the backend will consistently send either B or D, not a mix.
*/
if
(
binary
)
{
for
(
i
=
0
;
i
<
nfields
;
i
++
)
result
->
attDescs
[
i
].
format
=
1
;
}
}
}
tup
=
conn
->
curTuple
;
tup
=
conn
->
curTuple
;
...
@@ -778,6 +792,8 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
...
@@ -778,6 +792,8 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
{
{
PGresult
*
res
;
PGresult
*
res
;
PQExpBufferData
workBuf
;
PQExpBufferData
workBuf
;
char
*
startp
;
char
*
splitp
;
/*
/*
* Since the message might be pretty long, we create a temporary
* Since the message might be pretty long, we create a temporary
...
@@ -800,19 +816,63 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
...
@@ -800,19 +816,63 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
res
->
resultStatus
=
isError
?
PGRES_FATAL_ERROR
:
PGRES_NONFATAL_ERROR
;
res
->
resultStatus
=
isError
?
PGRES_FATAL_ERROR
:
PGRES_NONFATAL_ERROR
;
res
->
errMsg
=
pqResultStrdup
(
res
,
workBuf
.
data
);
res
->
errMsg
=
pqResultStrdup
(
res
,
workBuf
.
data
);
/*
* Break the message into fields. We can't do very much here, but we
* can split the severity code off, and remove trailing newlines. Also,
* we use the heuristic that the primary message extends only to the
* first newline --- anything after that is detail message. (In some
* cases it'd be better classed as hint, but we can hardly be expected
* to guess that here.)
*/
while
(
workBuf
.
len
>
0
&&
workBuf
.
data
[
workBuf
.
len
-
1
]
==
'\n'
)
workBuf
.
data
[
--
workBuf
.
len
]
=
'\0'
;
splitp
=
strstr
(
workBuf
.
data
,
": "
);
if
(
splitp
)
{
/* what comes before the colon is severity */
*
splitp
=
'\0'
;
pqSaveMessageField
(
res
,
'S'
,
workBuf
.
data
);
startp
=
splitp
+
3
;
}
else
{
/* can't find a colon? oh well... */
startp
=
workBuf
.
data
;
}
splitp
=
strchr
(
startp
,
'\n'
);
if
(
splitp
)
{
/* what comes before the newline is primary message */
*
splitp
++
=
'\0'
;
pqSaveMessageField
(
res
,
'M'
,
startp
);
/* the rest is detail; strip any leading whitespace */
while
(
*
splitp
&&
isspace
((
unsigned
char
)
*
splitp
))
splitp
++
;
pqSaveMessageField
(
res
,
'D'
,
splitp
);
}
else
{
/* single-line message, so all primary */
pqSaveMessageField
(
res
,
'M'
,
startp
);
}
/*
/*
* Either save error as current async result, or just emit the notice.
* Either save error as current async result, or just emit the notice.
* Also, if it's an error and we were in a transaction block, assume
* the server has now gone to error-in-transaction state.
*/
*/
if
(
isError
)
if
(
isError
)
{
{
pqClearAsyncResult
(
conn
);
pqClearAsyncResult
(
conn
);
conn
->
result
=
res
;
conn
->
result
=
res
;
resetPQExpBuffer
(
&
conn
->
errorMessage
);
resetPQExpBuffer
(
&
conn
->
errorMessage
);
appendPQExpBufferStr
(
&
conn
->
errorMessage
,
workBuf
.
data
);
appendPQExpBufferStr
(
&
conn
->
errorMessage
,
res
->
errMsg
);
if
(
conn
->
xactStatus
==
PQTRANS_INTRANS
)
conn
->
xactStatus
=
PQTRANS_INERROR
;
}
}
else
else
{
{
PGDONOTICE
(
conn
,
workBuf
.
data
);
(
*
res
->
noticeHooks
.
noticeRec
)
(
res
->
noticeHooks
.
noticeRecArg
,
res
);
PQclear
(
res
);
PQclear
(
res
);
}
}
...
@@ -820,6 +880,37 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
...
@@ -820,6 +880,37 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
return
0
;
return
0
;
}
}
/*
* checkXactStatus - attempt to track transaction-block status of server
*
* This is called each time we receive a command-complete message. By
* watching for messages from BEGIN/COMMIT/ROLLBACK commands, we can do
* a passable job of tracking the server's xact status. BUT: this does
* not work at all on 7.3 servers with AUTOCOMMIT OFF. (Man, was that
* feature ever a mistake.) Caveat user.
*
* The tags known here are all those used as far back as 7.0; is it worth
* adding those from even-older servers?
*/
static
void
checkXactStatus
(
PGconn
*
conn
,
const
char
*
cmdTag
)
{
if
(
strcmp
(
cmdTag
,
"BEGIN"
)
==
0
)
conn
->
xactStatus
=
PQTRANS_INTRANS
;
else
if
(
strcmp
(
cmdTag
,
"COMMIT"
)
==
0
)
conn
->
xactStatus
=
PQTRANS_IDLE
;
else
if
(
strcmp
(
cmdTag
,
"ROLLBACK"
)
==
0
)
conn
->
xactStatus
=
PQTRANS_IDLE
;
else
if
(
strcmp
(
cmdTag
,
"START TRANSACTION"
)
==
0
)
/* 7.3 only */
conn
->
xactStatus
=
PQTRANS_INTRANS
;
/*
* Normally we get into INERROR state by detecting an Error message.
* However, if we see one of these tags then we know for sure the
* server is in abort state ...
*/
else
if
(
strcmp
(
cmdTag
,
"*ABORT STATE*"
)
==
0
)
/* pre-7.3 only */
conn
->
xactStatus
=
PQTRANS_INERROR
;
}
/*
/*
* Attempt to read a Notify response message.
* Attempt to read a Notify response message.
...
@@ -832,6 +923,7 @@ static int
...
@@ -832,6 +923,7 @@ static int
getNotify
(
PGconn
*
conn
)
getNotify
(
PGconn
*
conn
)
{
{
int
be_pid
;
int
be_pid
;
int
nmlen
;
PGnotify
*
newNotify
;
PGnotify
*
newNotify
;
if
(
pqGetInt
(
&
be_pid
,
4
,
conn
))
if
(
pqGetInt
(
&
be_pid
,
4
,
conn
))
...
@@ -844,12 +936,14 @@ getNotify(PGconn *conn)
...
@@ -844,12 +936,14 @@ getNotify(PGconn *conn)
* can all be freed at once. We don't use NAMEDATALEN because we
* can all be freed at once. We don't use NAMEDATALEN because we
* don't want to tie this interface to a specific server name length.
* don't want to tie this interface to a specific server name length.
*/
*/
n
ewNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
)
+
n
mlen
=
strlen
(
conn
->
workBuffer
.
data
);
strlen
(
conn
->
workBuffer
.
data
)
+
1
);
newNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
)
+
nmlen
+
1
);
if
(
newNotify
)
if
(
newNotify
)
{
{
newNotify
->
relname
=
(
char
*
)
newNotify
+
sizeof
(
PGnotify
);
newNotify
->
relname
=
(
char
*
)
newNotify
+
sizeof
(
PGnotify
);
strcpy
(
newNotify
->
relname
,
conn
->
workBuffer
.
data
);
strcpy
(
newNotify
->
relname
,
conn
->
workBuffer
.
data
);
/* fake up an empty-string extra field */
newNotify
->
extra
=
newNotify
->
relname
+
nmlen
;
newNotify
->
be_pid
=
be_pid
;
newNotify
->
be_pid
=
be_pid
;
DLAddTail
(
conn
->
notifyList
,
DLNewElem
(
newNotify
));
DLAddTail
(
conn
->
notifyList
,
DLNewElem
(
newNotify
));
}
}
...
@@ -858,6 +952,84 @@ getNotify(PGconn *conn)
...
@@ -858,6 +952,84 @@ getNotify(PGconn *conn)
}
}
/*
* PQgetCopyData - read a row of data from the backend during COPY OUT
*
* If successful, sets *buffer to point to a malloc'd row of data, and
* returns row length (always > 0) as result.
* Returns 0 if no row available yet (only possible if async is true),
* -1 if end of copy (consult PQgetResult), or -2 if error (consult
* PQerrorMessage).
*/
int
pqGetCopyData2
(
PGconn
*
conn
,
char
**
buffer
,
int
async
)
{
bool
found
;
int
msgLength
;
for
(;;)
{
/*
* Do we have a complete line of data?
*/
conn
->
inCursor
=
conn
->
inStart
;
found
=
false
;
while
(
conn
->
inCursor
<
conn
->
inEnd
)
{
char
c
=
conn
->
inBuffer
[
conn
->
inCursor
++
];
if
(
c
==
'\n'
)
{
found
=
true
;
break
;
}
}
if
(
!
found
)
goto
nodata
;
msgLength
=
conn
->
inCursor
-
conn
->
inStart
;
/*
* If it's the end-of-data marker, consume it, exit COPY_OUT mode,
* and let caller read status with PQgetResult().
*/
if
(
msgLength
==
3
&&
strncmp
(
&
conn
->
inBuffer
[
conn
->
inStart
],
"
\\
.
\n
"
,
3
)
==
0
)
{
conn
->
inStart
=
conn
->
inCursor
;
conn
->
asyncStatus
=
PGASYNC_BUSY
;
return
-
1
;
}
/*
* Pass the line back to the caller.
*/
*
buffer
=
(
char
*
)
malloc
(
msgLength
+
1
);
if
(
*
buffer
==
NULL
)
{
printfPQExpBuffer
(
&
conn
->
errorMessage
,
libpq_gettext
(
"out of memory
\n
"
));
return
-
2
;
}
memcpy
(
*
buffer
,
&
conn
->
inBuffer
[
conn
->
inStart
],
msgLength
);
(
*
buffer
)[
msgLength
]
=
'\0'
;
/* Add terminating null */
/* Mark message consumed */
conn
->
inStart
=
conn
->
inCursor
;
return
msgLength
;
nodata:
/* Don't block if async read requested */
if
(
async
)
return
0
;
/* Need to load more data */
if
(
pqWait
(
TRUE
,
FALSE
,
conn
)
||
pqReadData
(
conn
)
<
0
)
return
-
2
;
}
}
/*
/*
* PQgetline - gets a newline-terminated string from the backend.
* PQgetline - gets a newline-terminated string from the backend.
*
*
...
@@ -1020,7 +1192,7 @@ pqEndcopy2(PGconn *conn)
...
@@ -1020,7 +1192,7 @@ pqEndcopy2(PGconn *conn)
if
(
conn
->
errorMessage
.
len
>
0
)
if
(
conn
->
errorMessage
.
len
>
0
)
PGDONOTICE
(
conn
,
conn
->
errorMessage
.
data
);
PGDONOTICE
(
conn
,
conn
->
errorMessage
.
data
);
PGDONOTICE
(
conn
,
libpq_gettext
(
"lost synchronization with server, resetting connection
\n
"
));
PGDONOTICE
(
conn
,
libpq_gettext
(
"lost synchronization with server, resetting connection"
));
/*
/*
* Users doing non-blocking connections need to handle the reset
* Users doing non-blocking connections need to handle the reset
...
...
src/interfaces/libpq/fe-protocol3.c
浏览文件 @
efc3a25b
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.
1 2003/06/08 17:43:00
tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.
2 2003/06/21 21:51:34
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -40,6 +40,8 @@ static int getRowDescriptions(PGconn *conn);
...
@@ -40,6 +40,8 @@ static int getRowDescriptions(PGconn *conn);
static
int
getAnotherTuple
(
PGconn
*
conn
,
int
msgLength
);
static
int
getAnotherTuple
(
PGconn
*
conn
,
int
msgLength
);
static
int
getParameterStatus
(
PGconn
*
conn
);
static
int
getParameterStatus
(
PGconn
*
conn
);
static
int
getNotify
(
PGconn
*
conn
);
static
int
getNotify
(
PGconn
*
conn
);
static
int
getCopyStart
(
PGconn
*
conn
,
ExecStatusType
copytype
);
static
int
getReadyForQuery
(
PGconn
*
conn
);
static
int
build_startup_packet
(
const
PGconn
*
conn
,
char
*
packet
,
static
int
build_startup_packet
(
const
PGconn
*
conn
,
char
*
packet
,
const
PQEnvironmentOption
*
options
);
const
PQEnvironmentOption
*
options
);
...
@@ -171,7 +173,7 @@ pqParseInput3(PGconn *conn)
...
@@ -171,7 +173,7 @@ pqParseInput3(PGconn *conn)
else
else
{
{
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
snprintf
(
noticeWorkspace
,
sizeof
(
noticeWorkspace
),
libpq_gettext
(
"message type 0x%02x arrived from server while idle
\n
"
),
libpq_gettext
(
"message type 0x%02x arrived from server while idle"
),
id
);
id
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
PGDONOTICE
(
conn
,
noticeWorkspace
);
/* Discard the unexpected message */
/* Discard the unexpected message */
...
@@ -201,7 +203,7 @@ pqParseInput3(PGconn *conn)
...
@@ -201,7 +203,7 @@ pqParseInput3(PGconn *conn)
conn
->
asyncStatus
=
PGASYNC_READY
;
conn
->
asyncStatus
=
PGASYNC_READY
;
break
;
break
;
case
'Z'
:
/* backend is ready for new query */
case
'Z'
:
/* backend is ready for new query */
if
(
pqGetc
(
&
conn
->
xact_status
,
conn
))
if
(
getReadyForQuery
(
conn
))
return
;
return
;
conn
->
asyncStatus
=
PGASYNC_IDLE
;
conn
->
asyncStatus
=
PGASYNC_IDLE
;
break
;
break
;
...
@@ -211,6 +213,11 @@ pqParseInput3(PGconn *conn)
...
@@ -211,6 +213,11 @@ pqParseInput3(PGconn *conn)
PGRES_EMPTY_QUERY
);
PGRES_EMPTY_QUERY
);
conn
->
asyncStatus
=
PGASYNC_READY
;
conn
->
asyncStatus
=
PGASYNC_READY
;
break
;
break
;
case
'1'
:
/* Parse Complete */
case
'2'
:
/* Bind Complete */
case
'3'
:
/* Close Complete */
/* Nothing to do for these message types */
break
;
case
'S'
:
/* parameter status */
case
'S'
:
/* parameter status */
if
(
getParameterStatus
(
conn
))
if
(
getParameterStatus
(
conn
))
return
;
return
;
...
@@ -276,17 +283,13 @@ pqParseInput3(PGconn *conn)
...
@@ -276,17 +283,13 @@ pqParseInput3(PGconn *conn)
}
}
break
;
break
;
case
'G'
:
/* Start Copy In */
case
'G'
:
/* Start Copy In */
if
(
pqGetc
(
&
conn
->
copy_is_binary
,
conn
))
if
(
getCopyStart
(
conn
,
PGRES_COPY_IN
))
return
;
return
;
/* XXX we currently ignore the rest of the message */
conn
->
inCursor
=
conn
->
inStart
+
5
+
msgLength
;
conn
->
asyncStatus
=
PGASYNC_COPY_IN
;
conn
->
asyncStatus
=
PGASYNC_COPY_IN
;
break
;
break
;
case
'H'
:
/* Start Copy Out */
case
'H'
:
/* Start Copy Out */
if
(
pqGetc
(
&
conn
->
copy_is_binary
,
conn
))
if
(
getCopyStart
(
conn
,
PGRES_COPY_OUT
))
return
;
return
;
/* XXX we currently ignore the rest of the message */
conn
->
inCursor
=
conn
->
inStart
+
5
+
msgLength
;
conn
->
asyncStatus
=
PGASYNC_COPY_OUT
;
conn
->
asyncStatus
=
PGASYNC_COPY_OUT
;
conn
->
copy_already_done
=
0
;
conn
->
copy_already_done
=
0
;
break
;
break
;
...
@@ -398,6 +401,9 @@ getRowDescriptions(PGconn *conn)
...
@@ -398,6 +401,9 @@ getRowDescriptions(PGconn *conn)
MemSet
((
char
*
)
result
->
attDescs
,
0
,
nfields
*
sizeof
(
PGresAttDesc
));
MemSet
((
char
*
)
result
->
attDescs
,
0
,
nfields
*
sizeof
(
PGresAttDesc
));
}
}
/* result->binary is true only if ALL columns are binary */
result
->
binary
=
(
nfields
>
0
)
?
1
:
0
;
/* get type info */
/* get type info */
for
(
i
=
0
;
i
<
nfields
;
i
++
)
for
(
i
=
0
;
i
<
nfields
;
i
++
)
{
{
...
@@ -430,10 +436,15 @@ getRowDescriptions(PGconn *conn)
...
@@ -430,10 +436,15 @@ getRowDescriptions(PGconn *conn)
result
->
attDescs
[
i
].
name
=
pqResultStrdup
(
result
,
result
->
attDescs
[
i
].
name
=
pqResultStrdup
(
result
,
conn
->
workBuffer
.
data
);
conn
->
workBuffer
.
data
);
result
->
attDescs
[
i
].
tableid
=
tableid
;
result
->
attDescs
[
i
].
columnid
=
columnid
;
result
->
attDescs
[
i
].
format
=
format
;
result
->
attDescs
[
i
].
typid
=
typid
;
result
->
attDescs
[
i
].
typid
=
typid
;
result
->
attDescs
[
i
].
typlen
=
typlen
;
result
->
attDescs
[
i
].
typlen
=
typlen
;
result
->
attDescs
[
i
].
atttypmod
=
atttypmod
;
result
->
attDescs
[
i
].
atttypmod
=
atttypmod
;
/* XXX todo: save tableid/columnid, format too */
if
(
format
!=
1
)
result
->
binary
=
0
;
}
}
/* Success! */
/* Success! */
...
@@ -503,7 +514,9 @@ getAnotherTuple(PGconn *conn, int msgLength)
...
@@ -503,7 +514,9 @@ getAnotherTuple(PGconn *conn, int msgLength)
vlen
=
0
;
vlen
=
0
;
if
(
tup
[
i
].
value
==
NULL
)
if
(
tup
[
i
].
value
==
NULL
)
{
{
tup
[
i
].
value
=
(
char
*
)
pqResultAlloc
(
result
,
vlen
+
1
,
false
);
bool
isbinary
=
(
result
->
attDescs
[
i
].
format
!=
0
);
tup
[
i
].
value
=
(
char
*
)
pqResultAlloc
(
result
,
vlen
+
1
,
isbinary
);
if
(
tup
[
i
].
value
==
NULL
)
if
(
tup
[
i
].
value
==
NULL
)
goto
outOfMemory
;
goto
outOfMemory
;
}
}
...
@@ -553,6 +566,7 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
...
@@ -553,6 +566,7 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
PGresult
*
res
;
PGresult
*
res
;
PQExpBufferData
workBuf
;
PQExpBufferData
workBuf
;
char
id
;
char
id
;
const
char
*
val
;
/*
/*
* Make a PGresult to hold the accumulated fields. We temporarily
* Make a PGresult to hold the accumulated fields. We temporarily
...
@@ -580,68 +594,63 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
...
@@ -580,68 +594,63 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
break
;
/* terminator found */
break
;
/* terminator found */
if
(
pqGets
(
&
workBuf
,
conn
))
if
(
pqGets
(
&
workBuf
,
conn
))
goto
fail
;
goto
fail
;
switch
(
id
)
pqSaveMessageField
(
res
,
id
,
workBuf
.
data
);
{
case
'S'
:
res
->
errSeverity
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'C'
:
res
->
errCode
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'M'
:
res
->
errPrimary
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'D'
:
res
->
errDetail
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'H'
:
res
->
errHint
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'P'
:
res
->
errPosition
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'W'
:
res
->
errContext
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'F'
:
res
->
errFilename
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'L'
:
res
->
errLineno
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
case
'R'
:
res
->
errFuncname
=
pqResultStrdup
(
res
,
workBuf
.
data
);
break
;
default:
/* silently ignore any other field type */
break
;
}
}
}
/*
/*
* Now build the "overall" error message for PQresultErrorMessage.
* Now build the "overall" error message for PQresultErrorMessage.
*
* XXX this should be configurable somehow.
*/
*/
resetPQExpBuffer
(
&
workBuf
);
resetPQExpBuffer
(
&
workBuf
);
if
(
res
->
errSeverity
)
val
=
PQresultErrorField
(
res
,
'S'
);
/* Severity */
appendPQExpBuffer
(
&
workBuf
,
"%s: "
,
res
->
errSeverity
);
if
(
val
)
if
(
res
->
errPrimary
)
appendPQExpBuffer
(
&
workBuf
,
"%s: "
,
val
);
appendPQExpBufferStr
(
&
workBuf
,
res
->
errPrimary
);
if
(
conn
->
verbosity
==
PQERRORS_VERBOSE
)
/* translator: %s represents a digit string */
{
if
(
res
->
errPosition
)
val
=
PQresultErrorField
(
res
,
'C'
);
/* SQLSTATE Code */
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
" at character %s"
),
if
(
val
)
res
->
errPosition
);
appendPQExpBuffer
(
&
workBuf
,
"%s: "
,
val
);
}
val
=
PQresultErrorField
(
res
,
'M'
);
/* Primary message */
if
(
val
)
appendPQExpBufferStr
(
&
workBuf
,
val
);
val
=
PQresultErrorField
(
res
,
'P'
);
/* Position */
if
(
val
)
{
/* translator: %s represents a digit string */
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
" at character %s"
),
val
);
}
appendPQExpBufferChar
(
&
workBuf
,
'\n'
);
appendPQExpBufferChar
(
&
workBuf
,
'\n'
);
if
(
res
->
errDetail
)
if
(
conn
->
verbosity
!=
PQERRORS_TERSE
)
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"DETAIL: %s
\n
"
),
{
res
->
errDetail
);
val
=
PQresultErrorField
(
res
,
'D'
);
/* Detail */
if
(
res
->
errHint
)
if
(
val
)
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"HINT: %s
\n
"
),
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"DETAIL: %s
\n
"
),
val
);
res
->
errHint
);
val
=
PQresultErrorField
(
res
,
'H'
);
/* Hint */
if
(
res
->
errContext
)
if
(
val
)
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"CONTEXT: %s
\n
"
),
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"HINT: %s
\n
"
),
val
);
res
->
errContext
);
val
=
PQresultErrorField
(
res
,
'W'
);
/* Where */
if
(
val
)
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"CONTEXT: %s
\n
"
),
val
);
}
if
(
conn
->
verbosity
==
PQERRORS_VERBOSE
)
{
const
char
*
valf
;
const
char
*
vall
;
valf
=
PQresultErrorField
(
res
,
'F'
);
/* File */
vall
=
PQresultErrorField
(
res
,
'L'
);
/* Line */
val
=
PQresultErrorField
(
res
,
'R'
);
/* Routine */
if
(
val
||
valf
||
vall
)
{
appendPQExpBufferStr
(
&
workBuf
,
libpq_gettext
(
"LOCATION: "
));
if
(
val
)
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"%s, "
),
val
);
if
(
valf
&&
vall
)
/* unlikely we'd have just one */
appendPQExpBuffer
(
&
workBuf
,
libpq_gettext
(
"%s:%s"
),
valf
,
vall
);
appendPQExpBufferChar
(
&
workBuf
,
'\n'
);
}
}
/*
/*
* Either save error as current async result, or just emit the notice.
* Either save error as current async result, or just emit the notice.
...
@@ -656,7 +665,9 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
...
@@ -656,7 +665,9 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
}
}
else
else
{
{
PGDONOTICE
(
conn
,
workBuf
.
data
);
/* We can cheat a little here and not copy the message. */
res
->
errMsg
=
workBuf
.
data
;
(
*
res
->
noticeHooks
.
noticeRec
)
(
res
->
noticeHooks
.
noticeRecArg
,
res
);
PQclear
(
res
);
PQclear
(
res
);
}
}
...
@@ -710,35 +721,216 @@ static int
...
@@ -710,35 +721,216 @@ static int
getNotify
(
PGconn
*
conn
)
getNotify
(
PGconn
*
conn
)
{
{
int
be_pid
;
int
be_pid
;
char
*
svname
;
int
nmlen
;
int
extralen
;
PGnotify
*
newNotify
;
PGnotify
*
newNotify
;
if
(
pqGetInt
(
&
be_pid
,
4
,
conn
))
if
(
pqGetInt
(
&
be_pid
,
4
,
conn
))
return
EOF
;
return
EOF
;
if
(
pqGets
(
&
conn
->
workBuffer
,
conn
))
if
(
pqGets
(
&
conn
->
workBuffer
,
conn
))
return
EOF
;
return
EOF
;
/* must save name while getting extra string */
svname
=
strdup
(
conn
->
workBuffer
.
data
);
if
(
!
svname
)
return
EOF
;
if
(
pqGets
(
&
conn
->
workBuffer
,
conn
))
{
free
(
svname
);
return
EOF
;
}
/*
/*
* Store the
relation name
right after the PQnotify structure so it
* Store the
strings
right after the PQnotify structure so it
* can all be freed at once. We don't use NAMEDATALEN because we
* can all be freed at once. We don't use NAMEDATALEN because we
* don't want to tie this interface to a specific server name length.
* don't want to tie this interface to a specific server name length.
*/
*/
newNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
)
+
nmlen
=
strlen
(
svname
);
strlen
(
conn
->
workBuffer
.
data
)
+
1
);
extralen
=
strlen
(
conn
->
workBuffer
.
data
);
newNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
)
+
nmlen
+
extralen
+
2
);
if
(
newNotify
)
if
(
newNotify
)
{
{
newNotify
->
relname
=
(
char
*
)
newNotify
+
sizeof
(
PGnotify
);
newNotify
->
relname
=
(
char
*
)
newNotify
+
sizeof
(
PGnotify
);
strcpy
(
newNotify
->
relname
,
conn
->
workBuffer
.
data
);
strcpy
(
newNotify
->
relname
,
svname
);
newNotify
->
extra
=
newNotify
->
relname
+
nmlen
+
1
;
strcpy
(
newNotify
->
extra
,
conn
->
workBuffer
.
data
);
newNotify
->
be_pid
=
be_pid
;
newNotify
->
be_pid
=
be_pid
;
DLAddTail
(
conn
->
notifyList
,
DLNewElem
(
newNotify
));
DLAddTail
(
conn
->
notifyList
,
DLNewElem
(
newNotify
));
}
}
/* Swallow extra string (not presently used) */
free
(
svname
);
if
(
pqGets
(
&
conn
->
workBuffer
,
conn
))
return
0
;
}
/*
* getCopyStart - process CopyInResponse or CopyOutResponse message
*
* parseInput already read the message type and length.
*/
static
int
getCopyStart
(
PGconn
*
conn
,
ExecStatusType
copytype
)
{
PGresult
*
result
;
int
nfields
;
int
i
;
result
=
PQmakeEmptyPGresult
(
conn
,
copytype
);
if
(
pqGetc
(
&
conn
->
copy_is_binary
,
conn
))
{
PQclear
(
result
);
return
EOF
;
return
EOF
;
}
result
->
binary
=
conn
->
copy_is_binary
;
/* the next two bytes are the number of fields */
if
(
pqGetInt
(
&
(
result
->
numAttributes
),
2
,
conn
))
{
PQclear
(
result
);
return
EOF
;
}
nfields
=
result
->
numAttributes
;
/* allocate space for the attribute descriptors */
if
(
nfields
>
0
)
{
result
->
attDescs
=
(
PGresAttDesc
*
)
pqResultAlloc
(
result
,
nfields
*
sizeof
(
PGresAttDesc
),
TRUE
);
MemSet
((
char
*
)
result
->
attDescs
,
0
,
nfields
*
sizeof
(
PGresAttDesc
));
}
for
(
i
=
0
;
i
<
nfields
;
i
++
)
{
int
format
;
if
(
pqGetInt
(
&
format
,
2
,
conn
))
{
PQclear
(
result
);
return
EOF
;
}
/*
* Since pqGetInt treats 2-byte integers as unsigned, we need to
* coerce these results to signed form.
*/
format
=
(
int
)
((
int16
)
format
);
result
->
attDescs
[
i
].
format
=
format
;
}
/* Success! */
conn
->
result
=
result
;
return
0
;
return
0
;
}
}
/*
* getReadyForQuery - process ReadyForQuery message
*/
static
int
getReadyForQuery
(
PGconn
*
conn
)
{
char
xact_status
;
if
(
pqGetc
(
&
xact_status
,
conn
))
return
EOF
;
switch
(
xact_status
)
{
case
'I'
:
conn
->
xactStatus
=
PQTRANS_IDLE
;
break
;
case
'T'
:
conn
->
xactStatus
=
PQTRANS_INTRANS
;
break
;
case
'E'
:
conn
->
xactStatus
=
PQTRANS_INERROR
;
break
;
default:
conn
->
xactStatus
=
PQTRANS_UNKNOWN
;
break
;
}
return
0
;
}
/*
* PQgetCopyData - read a row of data from the backend during COPY OUT
*
* If successful, sets *buffer to point to a malloc'd row of data, and
* returns row length (always > 0) as result.
* Returns 0 if no row available yet (only possible if async is true),
* -1 if end of copy (consult PQgetResult), or -2 if error (consult
* PQerrorMessage).
*/
int
pqGetCopyData3
(
PGconn
*
conn
,
char
**
buffer
,
int
async
)
{
char
id
;
int
msgLength
;
int
avail
;
for
(;;)
{
/*
* Do we have the next input message? To make life simpler for async
* callers, we keep returning 0 until the next message is fully
* available, even if it is not Copy Data.
*/
conn
->
inCursor
=
conn
->
inStart
;
if
(
pqGetc
(
&
id
,
conn
))
goto
nodata
;
if
(
pqGetInt
(
&
msgLength
,
4
,
conn
))
goto
nodata
;
avail
=
conn
->
inEnd
-
conn
->
inCursor
;
if
(
avail
<
msgLength
-
4
)
goto
nodata
;
/*
* If it's anything except Copy Data, exit COPY_OUT mode and let
* caller read status with PQgetResult(). The normal case is that
* it's Copy Done, but we let parseInput read that.
*/
if
(
id
!=
'd'
)
{
conn
->
asyncStatus
=
PGASYNC_BUSY
;
return
-
1
;
}
/*
* Drop zero-length messages (shouldn't happen anyway). Otherwise
* pass the data back to the caller.
*/
msgLength
-=
4
;
if
(
msgLength
>
0
)
{
*
buffer
=
(
char
*
)
malloc
(
msgLength
+
1
);
if
(
*
buffer
==
NULL
)
{
printfPQExpBuffer
(
&
conn
->
errorMessage
,
libpq_gettext
(
"out of memory
\n
"
));
return
-
2
;
}
memcpy
(
*
buffer
,
&
conn
->
inBuffer
[
conn
->
inCursor
],
msgLength
);
(
*
buffer
)[
msgLength
]
=
'\0'
;
/* Add terminating null */
/* Mark message consumed */
conn
->
inStart
=
conn
->
inCursor
+
msgLength
;
return
msgLength
;
}
/* Empty, so drop it and loop around for another */
conn
->
inStart
=
conn
->
inCursor
;
continue
;
nodata:
/* Don't block if async read requested */
if
(
async
)
return
0
;
/* Need to load more data */
if
(
pqWait
(
TRUE
,
FALSE
,
conn
)
||
pqReadData
(
conn
)
<
0
)
return
-
2
;
}
}
/*
/*
* PQgetline - gets a newline-terminated string from the backend.
* PQgetline - gets a newline-terminated string from the backend.
...
@@ -1108,7 +1300,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
...
@@ -1108,7 +1300,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
continue
;
continue
;
break
;
break
;
case
'Z'
:
/* backend is ready for new query */
case
'Z'
:
/* backend is ready for new query */
if
(
pqGetc
(
&
conn
->
xact_status
,
conn
))
if
(
getReadyForQuery
(
conn
))
continue
;
continue
;
/* consume the message and exit */
/* consume the message and exit */
conn
->
inStart
+=
5
+
msgLength
;
conn
->
inStart
+=
5
+
msgLength
;
...
...
src/interfaces/libpq/libpq-fe.h
浏览文件 @
efc3a25b
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Id: libpq-fe.h,v 1.9
3 2003/06/08 17:43:00
tgl Exp $
* $Id: libpq-fe.h,v 1.9
4 2003/06/21 21:51:34
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -88,6 +88,22 @@ typedef enum
...
@@ -88,6 +88,22 @@ typedef enum
PGRES_FATAL_ERROR
/* query failed */
PGRES_FATAL_ERROR
/* query failed */
}
ExecStatusType
;
}
ExecStatusType
;
typedef
enum
{
PQTRANS_IDLE
,
/* connection idle */
PQTRANS_ACTIVE
,
/* command in progress */
PQTRANS_INTRANS
,
/* idle, within transaction block */
PQTRANS_INERROR
,
/* idle, within failed transaction */
PQTRANS_UNKNOWN
/* cannot determine status */
}
PGTransactionStatusType
;
typedef
enum
{
PQERRORS_TERSE
,
/* single-line error messages */
PQERRORS_DEFAULT
,
/* recommended style */
PQERRORS_VERBOSE
/* all the facts, ma'am */
}
PGVerbosity
;
/* PGconn encapsulates a connection to the backend.
/* PGconn encapsulates a connection to the backend.
* The contents of this struct are not supposed to be known to applications.
* The contents of this struct are not supposed to be known to applications.
*/
*/
...
@@ -108,12 +124,13 @@ typedef struct pg_result PGresult;
...
@@ -108,12 +124,13 @@ typedef struct pg_result PGresult;
*/
*/
typedef
struct
pgNotify
typedef
struct
pgNotify
{
{
char
*
relname
;
/* name of relation containing data */
char
*
relname
;
/* notification condition name */
int
be_pid
;
/* process id of backend */
int
be_pid
;
/* process ID of server process */
char
*
extra
;
/* notification parameter */
}
PGnotify
;
}
PGnotify
;
/*
PQnoticeProcessor is the function type for the notice-message callback.
/*
Function types for notice-handling callbacks */
*/
typedef
void
(
*
PQnoticeReceiver
)
(
void
*
arg
,
const
PGresult
*
res
);
typedef
void
(
*
PQnoticeProcessor
)
(
void
*
arg
,
const
char
*
message
);
typedef
void
(
*
PQnoticeProcessor
)
(
void
*
arg
,
const
char
*
message
);
/* Print options for PQprint() */
/* Print options for PQprint() */
...
@@ -227,6 +244,10 @@ extern char *PQport(const PGconn *conn);
...
@@ -227,6 +244,10 @@ extern char *PQport(const PGconn *conn);
extern
char
*
PQtty
(
const
PGconn
*
conn
);
extern
char
*
PQtty
(
const
PGconn
*
conn
);
extern
char
*
PQoptions
(
const
PGconn
*
conn
);
extern
char
*
PQoptions
(
const
PGconn
*
conn
);
extern
ConnStatusType
PQstatus
(
const
PGconn
*
conn
);
extern
ConnStatusType
PQstatus
(
const
PGconn
*
conn
);
extern
PGTransactionStatusType
PQtransactionStatus
(
const
PGconn
*
conn
);
extern
const
char
*
PQparameterStatus
(
const
PGconn
*
conn
,
const
char
*
paramName
);
extern
int
PQprotocolVersion
(
const
PGconn
*
conn
);
extern
char
*
PQerrorMessage
(
const
PGconn
*
conn
);
extern
char
*
PQerrorMessage
(
const
PGconn
*
conn
);
extern
int
PQsocket
(
const
PGconn
*
conn
);
extern
int
PQsocket
(
const
PGconn
*
conn
);
extern
int
PQbackendPID
(
const
PGconn
*
conn
);
extern
int
PQbackendPID
(
const
PGconn
*
conn
);
...
@@ -238,42 +259,58 @@ extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
...
@@ -238,42 +259,58 @@ extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
extern
SSL
*
PQgetssl
(
PGconn
*
conn
);
extern
SSL
*
PQgetssl
(
PGconn
*
conn
);
#endif
#endif
/* Set verbosity for PQerrorMessage and PQresultErrorMessage */
extern
PGVerbosity
PQsetErrorVerbosity
(
PGconn
*
conn
,
PGVerbosity
verbosity
);
/* Enable/disable tracing */
/* Enable/disable tracing */
extern
void
PQtrace
(
PGconn
*
conn
,
FILE
*
debug_port
);
extern
void
PQtrace
(
PGconn
*
conn
,
FILE
*
debug_port
);
extern
void
PQuntrace
(
PGconn
*
conn
);
extern
void
PQuntrace
(
PGconn
*
conn
);
/* Override default notice processor */
/* Override default notice handling routines */
extern
PQnoticeReceiver
PQsetNoticeReceiver
(
PGconn
*
conn
,
PQnoticeReceiver
proc
,
void
*
arg
);
extern
PQnoticeProcessor
PQsetNoticeProcessor
(
PGconn
*
conn
,
extern
PQnoticeProcessor
PQsetNoticeProcessor
(
PGconn
*
conn
,
PQnoticeProcessor
proc
,
PQnoticeProcessor
proc
,
void
*
arg
);
void
*
arg
);
/* === in fe-exec.c === */
/* === in fe-exec.c === */
/* Quoting strings before inclusion in queries. */
extern
size_t
PQescapeString
(
char
*
to
,
const
char
*
from
,
size_t
length
);
extern
unsigned
char
*
PQescapeBytea
(
const
unsigned
char
*
bintext
,
size_t
binlen
,
size_t
*
bytealen
);
extern
unsigned
char
*
PQunescapeBytea
(
const
unsigned
char
*
strtext
,
size_t
*
retbuflen
);
extern
void
PQfreemem
(
void
*
ptr
);
/* Simple synchronous query */
/* Simple synchronous query */
extern
PGresult
*
PQexec
(
PGconn
*
conn
,
const
char
*
query
);
extern
PGresult
*
PQexec
(
PGconn
*
conn
,
const
char
*
query
);
extern
PGnotify
*
PQnotifies
(
PGconn
*
conn
);
extern
PGresult
*
PQexecParams
(
PGconn
*
conn
,
/* Exists for backward compatibility. bjm 2003-03-24 */
const
char
*
command
,
#define PQfreeNotify(ptr) PQfreemem(ptr)
int
nParams
,
const
Oid
*
paramTypes
,
const
char
*
const
*
paramValues
,
const
int
*
paramLengths
,
const
int
*
paramFormats
,
int
resultFormat
);
/* Interface for multiple-result or asynchronous queries */
/* Interface for multiple-result or asynchronous queries */
extern
int
PQsendQuery
(
PGconn
*
conn
,
const
char
*
query
);
extern
int
PQsendQuery
(
PGconn
*
conn
,
const
char
*
query
);
extern
int
PQsendQueryParams
(
PGconn
*
conn
,
const
char
*
command
,
int
nParams
,
const
Oid
*
paramTypes
,
const
char
*
const
*
paramValues
,
const
int
*
paramLengths
,
const
int
*
paramFormats
,
int
resultFormat
);
extern
PGresult
*
PQgetResult
(
PGconn
*
conn
);
extern
PGresult
*
PQgetResult
(
PGconn
*
conn
);
/* Routines for managing an asynchronous query */
/* Routines for managing an asynchronous query */
extern
int
PQisBusy
(
PGconn
*
conn
);
extern
int
PQisBusy
(
PGconn
*
conn
);
extern
int
PQconsumeInput
(
PGconn
*
conn
);
extern
int
PQconsumeInput
(
PGconn
*
conn
);
/* LISTEN/NOTIFY support */
extern
PGnotify
*
PQnotifies
(
PGconn
*
conn
);
/* Routines for copy in/out */
/* Routines for copy in/out */
extern
int
PQputCopyData
(
PGconn
*
conn
,
const
char
*
buffer
,
int
nbytes
);
extern
int
PQputCopyEnd
(
PGconn
*
conn
,
const
char
*
errormsg
);
extern
int
PQgetCopyData
(
PGconn
*
conn
,
char
**
buffer
,
int
async
);
/* Deprecated routines for copy in/out */
extern
int
PQgetline
(
PGconn
*
conn
,
char
*
string
,
int
length
);
extern
int
PQgetline
(
PGconn
*
conn
,
char
*
string
,
int
length
);
extern
int
PQputline
(
PGconn
*
conn
,
const
char
*
string
);
extern
int
PQputline
(
PGconn
*
conn
,
const
char
*
string
);
extern
int
PQgetlineAsync
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
extern
int
PQgetlineAsync
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
...
@@ -303,11 +340,15 @@ extern PGresult *PQfn(PGconn *conn,
...
@@ -303,11 +340,15 @@ extern PGresult *PQfn(PGconn *conn,
extern
ExecStatusType
PQresultStatus
(
const
PGresult
*
res
);
extern
ExecStatusType
PQresultStatus
(
const
PGresult
*
res
);
extern
char
*
PQresStatus
(
ExecStatusType
status
);
extern
char
*
PQresStatus
(
ExecStatusType
status
);
extern
char
*
PQresultErrorMessage
(
const
PGresult
*
res
);
extern
char
*
PQresultErrorMessage
(
const
PGresult
*
res
);
extern
char
*
PQresultErrorField
(
const
PGresult
*
res
,
int
fieldcode
);
extern
int
PQntuples
(
const
PGresult
*
res
);
extern
int
PQntuples
(
const
PGresult
*
res
);
extern
int
PQnfields
(
const
PGresult
*
res
);
extern
int
PQnfields
(
const
PGresult
*
res
);
extern
int
PQbinaryTuples
(
const
PGresult
*
res
);
extern
int
PQbinaryTuples
(
const
PGresult
*
res
);
extern
char
*
PQfname
(
const
PGresult
*
res
,
int
field_num
);
extern
char
*
PQfname
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfnumber
(
const
PGresult
*
res
,
const
char
*
field_name
);
extern
int
PQfnumber
(
const
PGresult
*
res
,
const
char
*
field_name
);
extern
Oid
PQftable
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQftablecol
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfformat
(
const
PGresult
*
res
,
int
field_num
);
extern
Oid
PQftype
(
const
PGresult
*
res
,
int
field_num
);
extern
Oid
PQftype
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfsize
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfsize
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfmod
(
const
PGresult
*
res
,
int
field_num
);
extern
int
PQfmod
(
const
PGresult
*
res
,
int
field_num
);
...
@@ -322,6 +363,12 @@ extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
...
@@ -322,6 +363,12 @@ extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
/* Delete a PGresult */
/* Delete a PGresult */
extern
void
PQclear
(
PGresult
*
res
);
extern
void
PQclear
(
PGresult
*
res
);
/* For freeing other alloc'd results, such as PGnotify structs */
extern
void
PQfreemem
(
void
*
ptr
);
/* Exists for backward compatibility. bjm 2003-03-24 */
#define PQfreeNotify(ptr) PQfreemem(ptr)
/*
/*
* Make an empty PGresult with given status (some apps find this
* Make an empty PGresult with given status (some apps find this
* useful). If conn is not NULL and status indicates an error, the
* useful). If conn is not NULL and status indicates an error, the
...
@@ -329,26 +376,33 @@ extern void PQclear(PGresult *res);
...
@@ -329,26 +376,33 @@ extern void PQclear(PGresult *res);
*/
*/
extern
PGresult
*
PQmakeEmptyPGresult
(
PGconn
*
conn
,
ExecStatusType
status
);
extern
PGresult
*
PQmakeEmptyPGresult
(
PGconn
*
conn
,
ExecStatusType
status
);
/* Quoting strings before inclusion in queries. */
extern
size_t
PQescapeString
(
char
*
to
,
const
char
*
from
,
size_t
length
);
extern
unsigned
char
*
PQescapeBytea
(
const
unsigned
char
*
bintext
,
size_t
binlen
,
size_t
*
bytealen
);
extern
unsigned
char
*
PQunescapeBytea
(
const
unsigned
char
*
strtext
,
size_t
*
retbuflen
);
/* === in fe-print.c === */
/* === in fe-print.c === */
extern
void
extern
void
PQprint
(
FILE
*
fout
,
/* output stream */
PQprint
(
FILE
*
fout
,
/* output stream */
const
PGresult
*
res
,
const
PGresult
*
res
,
const
PQprintOpt
*
ps
);
/* option structure */
const
PQprintOpt
*
ps
);
/* option structure */
/*
/*
* really old printing routines
* really old printing routines
*/
*/
extern
void
extern
void
PQdisplayTuples
(
const
PGresult
*
res
,
PQdisplayTuples
(
const
PGresult
*
res
,
FILE
*
fp
,
/* where to send the output */
FILE
*
fp
,
/* where to send the output */
int
fillAlign
,
/* pad the fields with spaces */
int
fillAlign
,
/* pad the fields with spaces */
const
char
*
fieldSep
,
/* field separator */
const
char
*
fieldSep
,
/* field separator */
int
printHeader
,
/* display headers? */
int
printHeader
,
/* display headers? */
int
quiet
);
int
quiet
);
extern
void
extern
void
PQprintTuples
(
const
PGresult
*
res
,
PQprintTuples
(
const
PGresult
*
res
,
FILE
*
fout
,
/* output stream */
FILE
*
fout
,
/* output stream */
int
printAttName
,
/* print attribute names */
int
printAttName
,
/* print attribute names */
int
terseOutput
,
/* delimiter bars */
int
terseOutput
,
/* delimiter bars */
...
...
src/interfaces/libpq/libpq-int.h
浏览文件 @
efc3a25b
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Id: libpq-int.h,v 1.7
4 2003/06/14 17:49:54 momjian
Exp $
* $Id: libpq-int.h,v 1.7
5 2003/06/21 21:51:34 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -20,6 +20,9 @@
...
@@ -20,6 +20,9 @@
#ifndef LIBPQ_INT_H
#ifndef LIBPQ_INT_H
#define LIBPQ_INT_H
#define LIBPQ_INT_H
/* We assume libpq-fe.h has already been included. */
#include "postgres_fe.h"
#include <time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/types.h>
#ifndef WIN32
#ifndef WIN32
...
@@ -28,13 +31,10 @@
...
@@ -28,13 +31,10 @@
#if defined(WIN32) && (!defined(ssize_t))
#if defined(WIN32) && (!defined(ssize_t))
typedef
int
ssize_t
;
/* ssize_t doesn't exist in VC (atleast
typedef
int
ssize_t
;
/* ssize_t doesn't exist in VC (at
least
* not VC6) */
* not VC6) */
#endif
#endif
/* We assume libpq-fe.h has already been included. */
#include "postgres_fe.h"
/* include stuff common to fe and be */
/* include stuff common to fe and be */
#include "getaddrinfo.h"
#include "getaddrinfo.h"
#include "libpq/pqcomm.h"
#include "libpq/pqcomm.h"
...
@@ -78,7 +78,10 @@ union pgresult_data
...
@@ -78,7 +78,10 @@ union pgresult_data
typedef
struct
pgresAttDesc
typedef
struct
pgresAttDesc
{
{
char
*
name
;
/* type name */
char
*
name
;
/* column name */
Oid
tableid
;
/* source table, if known */
int
columnid
;
/* source column, if known */
int
format
;
/* format code for value (text/binary) */
Oid
typid
;
/* type id */
Oid
typid
;
/* type id */
int
typlen
;
/* type size */
int
typlen
;
/* type size */
int
atttypmod
;
/* type-specific modifier info */
int
atttypmod
;
/* type-specific modifier info */
...
@@ -91,7 +94,7 @@ typedef struct pgresAttDesc
...
@@ -91,7 +94,7 @@ typedef struct pgresAttDesc
*
*
* The value pointer always points to a null-terminated area; we add a
* The value pointer always points to a null-terminated area; we add a
* null (zero) byte after whatever the backend sends us. This is only
* null (zero) byte after whatever the backend sends us. This is only
* particularly useful for text
tupl
es ... with a binary value, the
* particularly useful for text
valu
es ... with a binary value, the
* value might have embedded nulls, so the application can't use C string
* value might have embedded nulls, so the application can't use C string
* operators on it. But we add a null anyway for consistency.
* operators on it. But we add a null anyway for consistency.
* Note that the value itself does not contain a length word.
* Note that the value itself does not contain a length word.
...
@@ -111,6 +114,23 @@ typedef struct pgresAttValue
...
@@ -111,6 +114,23 @@ typedef struct pgresAttValue
* byte */
* byte */
}
PGresAttValue
;
}
PGresAttValue
;
/* Typedef for message-field list entries */
typedef
struct
pgMessageField
{
struct
pgMessageField
*
next
;
/* list link */
char
code
;
/* field code */
char
contents
[
1
];
/* field value (VARIABLE LENGTH) */
}
PGMessageField
;
/* Fields needed for notice handling */
typedef
struct
{
PQnoticeReceiver
noticeRec
;
/* notice message receiver */
void
*
noticeRecArg
;
PQnoticeProcessor
noticeProc
;
/* notice message processor */
void
*
noticeProcArg
;
}
PGNoticeHooks
;
struct
pg_result
struct
pg_result
{
{
int
ntups
;
int
ntups
;
...
@@ -118,10 +138,10 @@ struct pg_result
...
@@ -118,10 +138,10 @@ struct pg_result
PGresAttDesc
*
attDescs
;
PGresAttDesc
*
attDescs
;
PGresAttValue
**
tuples
;
/* each PGresTuple is an array of
PGresAttValue
**
tuples
;
/* each PGresTuple is an array of
* PGresAttValue's */
* PGresAttValue's */
int
tupArrSize
;
/*
size of tuples array allocated
*/
int
tupArrSize
;
/*
allocated size of tuples array
*/
ExecStatusType
resultStatus
;
ExecStatusType
resultStatus
;
char
cmdStatus
[
CMDSTATUS_LEN
];
/* cmd status from the
char
cmdStatus
[
CMDSTATUS_LEN
];
/* cmd status from the
*
last
query */
* query */
int
binary
;
/* binary tuple values if binary == 1,
int
binary
;
/* binary tuple values if binary == 1,
* otherwise text */
* otherwise text */
...
@@ -129,35 +149,23 @@ struct pg_result
...
@@ -129,35 +149,23 @@ struct pg_result
* These fields are copied from the originating PGconn, so that
* These fields are copied from the originating PGconn, so that
* operations on the PGresult don't have to reference the PGconn.
* operations on the PGresult don't have to reference the PGconn.
*/
*/
PQnoticeProcessor
noticeHook
;
/* notice/error message processor */
PGNoticeHooks
noticeHooks
;
void
*
noticeArg
;
int
client_encoding
;
/* encoding id */
int
client_encoding
;
/* encoding id */
/*
/*
* Error information (all NULL if not an error result). errMsg is the
* Error information (all NULL if not an error result). errMsg is the
* "overall" error message returned by PQresultErrorMessage. If we
* "overall" error message returned by PQresultErrorMessage. If we
* got a field-ized error from the server then the additional fields
* have per-field info then it is stored in a linked list.
* may be set.
*/
*/
char
*
errMsg
;
/* error message, or NULL if no error */
char
*
errMsg
;
/* error message, or NULL if no error */
PGMessageField
*
errFields
;
/* message broken into fields */
char
*
errSeverity
;
/* severity code */
char
*
errCode
;
/* SQLSTATE code */
char
*
errPrimary
;
/* primary message text */
char
*
errDetail
;
/* detail text */
char
*
errHint
;
/* hint text */
char
*
errPosition
;
/* cursor position */
char
*
errContext
;
/* location information */
char
*
errFilename
;
/* source-code file name */
char
*
errLineno
;
/* source-code line number */
char
*
errFuncname
;
/* source-code function name */
/* All NULL attributes in the query result point to this null string */
/* All NULL attributes in the query result point to this null string */
char
null_field
[
1
];
char
null_field
[
1
];
/*
/*
* Space management information. Note that attDescs and err
Msg, if
* Space management information. Note that attDescs and err
or stuff,
* not null, point into allocated blocks. But tuples points to a
*
if
not null, point into allocated blocks. But tuples points to a
* separately malloc'd block, so that we can realloc it.
* separately malloc'd block, so that we can realloc it.
*/
*/
PGresult_data
*
curBlock
;
/* most recently allocated block */
PGresult_data
*
curBlock
;
/* most recently allocated block */
...
@@ -245,18 +253,18 @@ struct pg_conn
...
@@ -245,18 +253,18 @@ struct pg_conn
/* Optional file to write trace info to */
/* Optional file to write trace info to */
FILE
*
Pfdebug
;
FILE
*
Pfdebug
;
/* Callback procedure for notice/error message processing */
/* Callback procedures for notice message processing */
PQnoticeProcessor
noticeHook
;
PGNoticeHooks
noticeHooks
;
void
*
noticeArg
;
/* Status indicators */
/* Status indicators */
ConnStatusType
status
;
ConnStatusType
status
;
PGAsyncStatusType
asyncStatus
;
PGAsyncStatusType
asyncStatus
;
char
xact_status
;
/* status flag from latest ReadyForQuery */
PGTransactionStatusType
xactStatus
;
char
copy_is_binary
;
/* 1 = copy binary, 0 = copy text */
/* note: xactStatus never changes to ACTIVE */
int
copy_already_done
;
/* # bytes already returned in COPY OUT */
int
nonblocking
;
/* whether this connection is using a
int
nonblocking
;
/* whether this connection is using a
* blocking socket to the backend or not */
* blocking socket to the backend or not */
char
copy_is_binary
;
/* 1 = copy binary, 0 = copy text */
int
copy_already_done
;
/* # bytes already returned in COPY OUT */
Dllist
*
notifyList
;
/* Notify msgs not yet handed to
Dllist
*
notifyList
;
/* Notify msgs not yet handed to
* application */
* application */
...
@@ -281,6 +289,7 @@ struct pg_conn
...
@@ -281,6 +289,7 @@ struct pg_conn
char
cryptSalt
[
2
];
/* password salt received from backend */
char
cryptSalt
[
2
];
/* password salt received from backend */
pgParameterStatus
*
pstatus
;
/* ParameterStatus data */
pgParameterStatus
*
pstatus
;
/* ParameterStatus data */
int
client_encoding
;
/* encoding id */
int
client_encoding
;
/* encoding id */
PGVerbosity
verbosity
;
/* error/notice message verbosity */
PGlobjfuncs
*
lobjfuncs
;
/* private state for large-object access
PGlobjfuncs
*
lobjfuncs
;
/* private state for large-object access
* fns */
* fns */
...
@@ -351,10 +360,12 @@ extern char *pqResultStrdup(PGresult *res, const char *str);
...
@@ -351,10 +360,12 @@ extern char *pqResultStrdup(PGresult *res, const char *str);
extern
void
pqClearAsyncResult
(
PGconn
*
conn
);
extern
void
pqClearAsyncResult
(
PGconn
*
conn
);
extern
void
pqSaveErrorResult
(
PGconn
*
conn
);
extern
void
pqSaveErrorResult
(
PGconn
*
conn
);
extern
PGresult
*
pqPrepareAsyncResult
(
PGconn
*
conn
);
extern
PGresult
*
pqPrepareAsyncResult
(
PGconn
*
conn
);
extern
void
pqInternalNotice
(
const
PGNoticeHooks
*
hooks
,
const
char
*
msgtext
);
extern
int
pqAddTuple
(
PGresult
*
res
,
PGresAttValue
*
tup
);
extern
int
pqAddTuple
(
PGresult
*
res
,
PGresAttValue
*
tup
);
extern
void
pqSaveMessageField
(
PGresult
*
res
,
char
code
,
const
char
*
value
);
extern
void
pqSaveParameterStatus
(
PGconn
*
conn
,
const
char
*
name
,
extern
void
pqSaveParameterStatus
(
PGconn
*
conn
,
const
char
*
name
,
const
char
*
value
);
const
char
*
value
);
extern
const
char
*
pqGetParameterStatus
(
PGconn
*
conn
,
const
char
*
name
);
extern
void
pqHandleSendFailure
(
PGconn
*
conn
);
extern
void
pqHandleSendFailure
(
PGconn
*
conn
);
/* === in fe-protocol2.c === */
/* === in fe-protocol2.c === */
...
@@ -364,6 +375,7 @@ extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
...
@@ -364,6 +375,7 @@ extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
extern
char
*
pqBuildStartupPacket2
(
PGconn
*
conn
,
int
*
packetlen
,
extern
char
*
pqBuildStartupPacket2
(
PGconn
*
conn
,
int
*
packetlen
,
const
PQEnvironmentOption
*
options
);
const
PQEnvironmentOption
*
options
);
extern
void
pqParseInput2
(
PGconn
*
conn
);
extern
void
pqParseInput2
(
PGconn
*
conn
);
extern
int
pqGetCopyData2
(
PGconn
*
conn
,
char
**
buffer
,
int
async
);
extern
int
pqGetline2
(
PGconn
*
conn
,
char
*
s
,
int
maxlen
);
extern
int
pqGetline2
(
PGconn
*
conn
,
char
*
s
,
int
maxlen
);
extern
int
pqGetlineAsync2
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
extern
int
pqGetlineAsync2
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
extern
int
pqEndcopy2
(
PGconn
*
conn
);
extern
int
pqEndcopy2
(
PGconn
*
conn
);
...
@@ -378,6 +390,7 @@ extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
...
@@ -378,6 +390,7 @@ extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
const
PQEnvironmentOption
*
options
);
const
PQEnvironmentOption
*
options
);
extern
void
pqParseInput3
(
PGconn
*
conn
);
extern
void
pqParseInput3
(
PGconn
*
conn
);
extern
int
pqGetErrorNotice3
(
PGconn
*
conn
,
bool
isError
);
extern
int
pqGetErrorNotice3
(
PGconn
*
conn
,
bool
isError
);
extern
int
pqGetCopyData3
(
PGconn
*
conn
,
char
**
buffer
,
int
async
);
extern
int
pqGetline3
(
PGconn
*
conn
,
char
*
s
,
int
maxlen
);
extern
int
pqGetline3
(
PGconn
*
conn
,
char
*
s
,
int
maxlen
);
extern
int
pqGetlineAsync3
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
extern
int
pqGetlineAsync3
(
PGconn
*
conn
,
char
*
buffer
,
int
bufsize
);
extern
int
pqEndcopy3
(
PGconn
*
conn
);
extern
int
pqEndcopy3
(
PGconn
*
conn
);
...
@@ -393,6 +406,7 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
...
@@ -393,6 +406,7 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
* for Get, EOF merely means the buffer is exhausted, not that there is
* for Get, EOF merely means the buffer is exhausted, not that there is
* necessarily any error.
* necessarily any error.
*/
*/
extern
int
pqCheckOutBufferSpace
(
int
bytes_needed
,
PGconn
*
conn
);
extern
int
pqCheckInBufferSpace
(
int
bytes_needed
,
PGconn
*
conn
);
extern
int
pqCheckInBufferSpace
(
int
bytes_needed
,
PGconn
*
conn
);
extern
int
pqGetc
(
char
*
result
,
PGconn
*
conn
);
extern
int
pqGetc
(
char
*
result
,
PGconn
*
conn
);
extern
int
pqPutc
(
char
c
,
PGconn
*
conn
);
extern
int
pqPutc
(
char
c
,
PGconn
*
conn
);
...
@@ -423,10 +437,10 @@ extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
...
@@ -423,10 +437,10 @@ extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
/* Note: PGDONOTICE macro will work if applied to either PGconn or PGresult */
/* Note: PGDONOTICE macro will work if applied to either PGconn or PGresult */
#define PGDONOTICE(conn,message) \
#define PGDONOTICE(conn,message) \
((*(conn)->noticeHook) ((conn)->noticeArg, (message)
))
pqInternalNotice(&(conn)->noticeHooks, (message
))
/*
/*
* this is so that we can check i
s
a connection is non-blocking internally
* this is so that we can check i
f
a connection is non-blocking internally
* without the overhead of a function call
* without the overhead of a function call
*/
*/
#define pqIsnonblocking(conn) ((conn)->nonblocking)
#define pqIsnonblocking(conn) ((conn)->nonblocking)
...
...
src/interfaces/libpq/libpqdll.def
浏览文件 @
efc3a25b
...
@@ -97,4 +97,17 @@ EXPORTS
...
@@ -97,4 +97,17 @@ EXPORTS
pg_utf_mblen @ 93
pg_utf_mblen @ 93
PQunescapeBytea @ 94
PQunescapeBytea @ 94
PQfreemem @ 95
PQfreemem @ 95
PQtransactionStatus @ 96
PQparameterStatus @ 97
PQprotocolVersion @ 98
PQsetErrorVerbosity @ 99
PQsetNoticeReceiver @ 100
PQexecParams @ 101
PQsendQueryParams @ 102
PQputCopyData @ 103
PQputCopyEnd @ 104
PQgetCopyData @ 105
PQresultErrorField @ 106
PQftable @ 107
PQftablecol @ 108
PQfformat @ 109
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录