From 8155dfdc6effb35fb85e105d713fd589803a4089 Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Wed, 26 May 2010 13:56:18 +0000 Subject: [PATCH] 1. Use poll() instead of select() when it's available. 2. Take comments or line comments in a query into account. 3. Fix a crash bug on authentication failures. --- configure.ac | 2 +- connection.c | 3 +++ convert.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- socket.c | 40 +++++++++++++++++++++++++++++++--------- socket.h | 3 +++ statement.c | 18 ++++++++++++------ version.h | 2 +- 7 files changed, 93 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index dbca4a7..425bcb8 100644 --- a/configure.ac +++ b/configure.ac @@ -274,7 +274,7 @@ AC_C_CONST # 7. Functions, global variables AC_FUNC_STRERROR_R -AC_CHECK_FUNCS(strtoul strtoll strlcpy) +AC_CHECK_FUNCS(strtoul strtoll strlcat strlcpy poll) if test x"$enable_unicode" = xyes; then AC_CHECK_FUNCS(iswascii) diff --git a/connection.c b/connection.c index 924632d..47eef47 100644 --- a/connection.c +++ b/connection.c @@ -457,6 +457,9 @@ static void CC_endup_authentication(ConnectionClass *self) { SocketClass *sock = CC_get_socket(self); + + if (!sock) + return; #ifdef USE_SSPI if (0 != self->auth_svcs) { diff --git a/convert.c b/convert.c index 5fac790..8faea54 100644 --- a/convert.c +++ b/convert.c @@ -1655,9 +1655,9 @@ typedef struct _QueryParse { ssize_t taglen; char token_save[64]; int token_len; - BOOL prev_token_end; + char prev_token_end, in_line_comment; size_t declare_pos; - UInt4 flags; + UInt4 flags, comment_level; encoded_str encstr; } QueryParse; @@ -1676,8 +1676,10 @@ QP_initialize(QueryParse *q, const StatementClass *stmt) q->token_save[0] = '\0'; q->token_len = 0; q->prev_token_end = TRUE; + q->in_line_comment = FALSE; q->declare_pos = 0; q->flags = 0; + q->comment_level = 0; make_encoded_str(&q->encstr, SC_get_conn(stmt), q->statement); return q->stmt_len; @@ -3052,6 +3054,34 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb) CVT_APPEND_CHAR(qb, oldchar); return SQL_SUCCESS; } + else if (qp->comment_level > 0) /* comment_level check */ + { + if ('/' == oldchar && + '*' == F_OldPtr(qp)[1]) + { + qp->comment_level++; + CVT_APPEND_CHAR(qb, oldchar); + F_OldNext(qp); + oldchar = F_OldChar(qp); + } + else if ('*' == oldchar && + '/' == F_OldPtr(qp)[1]) + { + qp->comment_level--; + CVT_APPEND_CHAR(qb, oldchar); + F_OldNext(qp); + oldchar = F_OldChar(qp); + } + CVT_APPEND_CHAR(qb, oldchar); + return SQL_SUCCESS; + } + else if (qp->in_line_comment) /* line comment check */ + { + if (PG_LINEFEED == oldchar) + qp->in_line_comment = FALSE; + CVT_APPEND_CHAR(qb, oldchar); + return SQL_SUCCESS; + } /* * From here we are guranteed to be in neither a literal_escape, @@ -3173,6 +3203,16 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb) if (!qp->in_literal) qp->in_identifier = TRUE; } + else if ('/' == oldchar && + '*' == F_OldPtr(qp)[1]) + { + qp->comment_level++; + } + else if ('-' == oldchar && + '-' == F_OldPtr(qp)[1]) + { + qp->in_line_comment = TRUE; + } else if (oldchar == ';') { /* diff --git a/socket.c b/socket.c index f5d17b5..0319128 100644 --- a/socket.c +++ b/socket.c @@ -350,8 +350,13 @@ retry: if (connect(self->socket, (struct sockaddr *) &(self->sadr_area), self->sadr_len) < 0) { int ret, optval; + int wait_sec = 0; +#ifdef HAVE_POLL + struct pollfd fds; +#else fd_set fds, except_fds; struct timeval tm; +#endif /* HAVE_POLL */ socklen_t optlen = sizeof(optval); time_t t_now, t_finish = 0; BOOL tm_exp = FALSE; @@ -377,15 +382,23 @@ retry: { t_now = time(NULL); t_finish = t_now + timeout; - tm.tv_sec = timeout; - tm.tv_usec = 0; + wait_sec = timeout; } do { +#ifdef HAVE_POLL + fds.fd = self->socket; + fds.events = POLLOUT; + fds.revents = 0; + ret = poll(&fds, 1, timeout > 0 ? wait_sec * 1000 : -1); +#else + tm.tv_sec = wait_sec; + tm.tv_usec = 0; FD_ZERO(&fds); FD_ZERO(&except_fds); FD_SET(self->socket, &fds); FD_SET(self->socket, &except_fds); ret = select((int) self->socket + 1, NULL, &fds, &except_fds, timeout > 0 ? &tm : NULL); +#endif /* HAVE_POLL */ gerrno = SOCK_ERRNO; if (0 < ret) break; @@ -398,10 +411,7 @@ retry: if (t_now = time(NULL), t_now >= t_finish) tm_exp = TRUE; else - { - tm.tv_sec = (long) (t_finish - t_now); - tm.tv_usec = 0; - } + wait_sec = t_finish - t_now; } } while (!tm_exp); if (tm_exp) @@ -475,8 +485,12 @@ cleanup: static int SOCK_wait_for_ready(SocketClass *sock, BOOL output, int retry_count) { int ret, gerrno; +#ifdef HAVE_POLL + struct pollfd fds; +#else fd_set fds, except_fds; struct timeval tm; +#endif /* HAVE_POLL */ BOOL no_timeout = TRUE; if (0 == retry_count) @@ -488,6 +502,13 @@ static int SOCK_wait_for_ready(SocketClass *sock, BOOL output, int retry_count) no_timeout = TRUE; #endif /* USE_SSL */ do { +#ifdef HAVE_POLL + fds.fd = sock->socket; + fds.events = output ? POLLOUT : POLLIN; + fds.revents = 0; + ret = poll(&fds, 1, no_timeout ? -1 : retry_count * 1000); +mylog("!!! poll ret=%d revents=%x\n", ret, fds.revents); +#else FD_ZERO(&fds); FD_ZERO(&except_fds); FD_SET(sock->socket, &fds); @@ -498,6 +519,7 @@ static int SOCK_wait_for_ready(SocketClass *sock, BOOL output, int retry_count) tm.tv_usec = 0; } ret = select((int) sock->socket + 1, output ? NULL : &fds, output ? &fds : NULL, &except_fds, no_timeout ? NULL : &tm); +#endif /* HAVE_POLL */ gerrno = SOCK_ERRNO; } while (ret < 0 && EINTR == gerrno); if (retry_count < 0) @@ -916,13 +938,13 @@ inolog("ECONNRESET\n"); { if (!maybeEOF) { - int nbytes = SOCK_wait_for_ready(self, FALSE, 0); - if (nbytes > 0) + int nready = SOCK_wait_for_ready(self, FALSE, 0); + if (nready > 0) { maybeEOF = TRUE; goto retry; } - else if (0 == nbytes) + else if (0 == nready) maybeEOF = TRUE; } if (maybeEOF) diff --git a/socket.h b/socket.h index 1559968..8c3ba14 100644 --- a/socket.h +++ b/socket.h @@ -21,6 +21,9 @@ #ifndef WIN32 #define WSAAPI +#ifdef HAVE_POLL +#include +#endif /* HAVE_POLL */ #include #include #include diff --git a/statement.c b/statement.c index a670e05..d4a0513 100644 --- a/statement.c +++ b/statement.c @@ -867,8 +867,8 @@ SC_scanQueryAndCountParams(const char *query, const ConnectionClass *conn, char tchar, bchar, escape_in_literal = '\0'; char in_literal = FALSE, in_identifier = FALSE, in_dollar_quote = FALSE, in_escape = FALSE, - in_line_comment = FALSE, in_comment = FALSE, - del_found = FALSE; + in_line_comment = FALSE, del_found = FALSE; + int comment_level = 0; po_ind_t multi = FALSE; SQLSMALLINT num_p; encoded_str encstr; @@ -932,13 +932,19 @@ SC_scanQueryAndCountParams(const char *query, const ConnectionClass *conn, if (PG_LINEFEED == tchar) in_line_comment = FALSE; } - else if (in_comment) + else if (comment_level > 0) { - if ('*' == tchar && '/' == sptr[1]) + if ('/' == tchar && '*' == sptr[1]) { encoded_nextchar(&encstr); sptr++; - in_comment = FALSE; + comment_level++; + } + else if ('*' == tchar && '/' == sptr[1]) + { + encoded_nextchar(&encstr); + sptr++; + comment_level--; } } else @@ -998,7 +1004,7 @@ SC_scanQueryAndCountParams(const char *query, const ConnectionClass *conn, { encoded_nextchar(&encstr); sptr++; - in_comment = TRUE; + comment_level++; } } if (!isspace(tchar)) diff --git a/version.h b/version.h index 24f48fc..c3526b6 100644 --- a/version.h +++ b/version.h @@ -12,6 +12,6 @@ #define POSTGRESDRIVERVERSION "08.04.0201" #define POSTGRES_RESOURCE_VERSION "08.04.0201\0" #define PG_DRVFILE_VERSION 8,4,02,01 -#define PG_BUILD_VERSION "201002070002" +#define PG_BUILD_VERSION "201005260001" #endif -- 2.39.5