From 74a0003fea4087de8e9f03b6f828c45d255bcd4a Mon Sep 17 00:00:00 2001 From: MDC Service Date: Mon, 23 May 2022 11:17:34 +0200 Subject: initial check in firmware files --- software/michi_funcs/SimplePgSQL_cpp.old | 900 +++++++++++++++++++++++++++++++ 1 file changed, 900 insertions(+) create mode 100644 software/michi_funcs/SimplePgSQL_cpp.old (limited to 'software/michi_funcs/SimplePgSQL_cpp.old') diff --git a/software/michi_funcs/SimplePgSQL_cpp.old b/software/michi_funcs/SimplePgSQL_cpp.old new file mode 100644 index 0000000..0e76e0a --- /dev/null +++ b/software/michi_funcs/SimplePgSQL_cpp.old @@ -0,0 +1,900 @@ +/* + SimplePgSQL.c - Lightweight PostgreSQL connector for Arduino + Copyright (C) Bohdan R. Rau 2016 + + SimplePgSQL is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + SimplePgSQL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with SimplePgSQL. If not, write to: + The Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor + Boston, MA 02110-1301, USA. + */ +#include +//#include "esp_eth.h" +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_netif.h" +#include "lwip/err.h" +#include "lwip/sockets.h" + + +#include "SimplePgSQL.h" + +#define AUTH_REQ_OK 0 /* User is authenticated */ +#define AUTH_REQ_PASSWORD 3 /* Password */ +#define PGTAG "PGSQL" +static const char EM_OOM[] = "Out of mem"; +static const char EM_READ[] = "Backend read err"; +static const char EM_WRITE[] = "Backend write err"; +static const char EM_CONN[] = "Cannot conn 2 srv"; +static const char EM_SYNC[] = "Backend out of sync"; +static const char EM_INTR[] = "Internal err"; +static const char EM_UAUTH[] = "auth method !sptd"; +static const char EM_BIN[] = "Bin fmt !sptd"; +static const char EM_EXEC[] = "Previ exe !finished"; +static const char EM_PASSWD[] = "Pwd req"; +static const char EM_EMPTY[] = "empty qry"; +static const char EM_FORMAT[] = "Illegal chr fmt"; + +PGconnection::PGconnection(const int flags, const unsigned char *Buffer, const int bufSize) { + conn_status = CONNECTION_NEEDED; + _passwd = NULL; + _user = NULL; + _buffer = (char *) Buffer; + _bufSize = bufSize; + bufPos = 0; + result_status=0; + _available=0; + _nfields=0; + _ntuples=0; + _flags=0; +} + +int PGconnection::PGsetDbLogin(const char *ServerIP, int ServerPort, const char *dbName, const char *dbUser, const char *dbPasswd, const char *dbCharset) { + + char *startpacket; + int packetlen; + int len; + +// close(); + memset(&DestAddr, 0, sizeof(DestAddr)); + AddrFamily = AF_INET; + ipProtocol = IPPROTO_IP; + DestAddr.sin_addr.s_addr = inet_addr(ServerIP); + DestAddr.sin_family = AF_INET; + DestAddr.sin_port = htons(ServerPort); + + if (!dbName) + dbName = dbUser; + len = strlen(dbUser) + 1; + if (dbPasswd) { + len += strlen(dbPasswd) + 1; + } + _user = (char *) malloc(len); + strcpy(_user, dbUser); + if (dbPasswd) { + _passwd = _user + strlen(dbUser) + 1; + strcpy(_passwd, dbPasswd); + } else { + _passwd = NULL; + } + + //int8_t connected = connect(client->connect(server, port); + SockH = socket(AddrFamily, SOCK_STREAM, ipProtocol); + if (SockH < 0) { + ESP_LOGE(PGTAG, "Unable to create socket: errno %d", errno); + setMsg_P(EM_CONN, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } else { + int err = connect(SockH, (struct sockaddr *) &DestAddr, sizeof(DestAddr)); + if (err != 0) { + ESP_LOGE(PGTAG, "Socket unable to connect: errno %d", errno); + return conn_status = CONNECTION_BAD; + } + NetConnected = 1; + ESP_LOGI(PGTAG, "Successfully connected"); + } + + packetlen = build_startup_packet(NULL, dbName, dbCharset); + if (packetlen > _bufSize - 10) { + setMsg_P(EM_OOM, PG_RSTAT_HAVE_ERROR); + conn_status = CONNECTION_BAD; + return conn_status; + } + + startpacket = _buffer + (_bufSize - (packetlen + 1)); + build_startup_packet(startpacket, dbName, dbCharset); + if (pqPacketSend(0, startpacket, packetlen) < 0) { + setMsg_P(EM_WRITE, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + attempts = 0; + return conn_status = CONNECTION_AWAITING_RESPONSE; +} + +void PGconnection::PGclose(void) { + if (NetConnected) { + pqPacketSend('X', NULL, 0); +// client->stop(); + shutdown(SockH, 0); + close(SockH); + } + if (_user) { + free(_user); + _user = _passwd = NULL; + } + NetConnected = 0; + conn_status = CONNECTION_NEEDED; +} + +int PGconnection::PGstatus(void) { + char bereq; + char rc; + int32_t msgLen; + int32_t areq; + char * pwd = _passwd; + + switch (conn_status) { + case CONNECTION_NEEDED: + case CONNECTION_OK: + case CONNECTION_BAD: + + return conn_status; + + case CONNECTION_AWAITING_RESPONSE: + if (dataAvailable() == 0) return conn_status; + if (attempts++ >= 2) { + setMsg_P(EM_SYNC, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + if (pqGetc(&bereq)) { + goto read_error; + } + if (bereq == 'E') { + pqGetInt4(&msgLen); + pqGetNotice(PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + if (bereq != 'R') { + setMsg_P(EM_SYNC, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + if (pqGetInt4(&msgLen)) { + goto read_error; + } + if (pqGetInt4(&areq)) { + goto read_error; + } + if (areq == AUTH_REQ_OK) { + if (_user) { + free(_user); + _user = _passwd = NULL; + } + result_status = PG_RSTAT_READY; + return conn_status = CONNECTION_AUTH_OK; + } + if (areq != AUTH_REQ_PASSWORD) { + setMsg_P(EM_UAUTH, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + if (!_passwd || !*_passwd) { + setMsg_P(EM_PASSWD, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + pwd = _passwd; + rc = pqPacketSend('p', pwd, strlen(pwd) + 1); + if (rc) { + goto write_error; + } + return conn_status; + + case CONNECTION_AUTH_OK: + for (;;) { + if (dataAvailable() == 0) return conn_status; + if (pqGetc(&bereq)) + goto read_error; + if (pqGetInt4(&msgLen)) + goto read_error; + msgLen -= 4; + if (bereq == 'A' || bereq == 'N' || bereq == 'S' || bereq == 'K') { + if (pqSkipnchar(msgLen)) + goto read_error; + continue; + } + if (bereq == 'E') { + pqGetNotice(PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + + /* if (bereq == 'K') { + if (pqGetInt4(&be_pid)) goto read_error; + if (pqGetInt4(&be_key)) goto read_error; + continue; + } + */ + if (bereq == 'Z') { + pqSkipnchar(msgLen); + return conn_status = CONNECTION_OK; + } + return conn_status = CONNECTION_BAD; + } + break; + default: + setMsg_P(EM_INTR, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + } + read_error: setMsg_P(EM_READ, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; + write_error: setMsg_P(EM_WRITE, PG_RSTAT_HAVE_ERROR); + return conn_status = CONNECTION_BAD; +} + +int PGconnection::PGexecute(const char *query) { + /* + if (!(result_status & PG_RSTAT_READY)) { + setMsg_P(EM_EXEC, PG_RSTAT_HAVE_ERROR); + return -1; + } + */ + int len = strlen(query); + if (pqPacketSend('Q', query, len + 1)) { + setMsg_P(EM_WRITE, PG_RSTAT_HAVE_ERROR); + conn_status = CONNECTION_BAD; + return -1; + } + result_status = PG_RSTAT_COMMAND_SENT; + return 0; +} + +int PGconnection::PGescapeName(const char *inbuf, char *outbuf) { + const char *c; + int l = 2; + for (c = inbuf; *c; c++) { + l++; + if (*c == '\\' || *c == '"') + l++; + } + if (outbuf) { + *outbuf++ = '"'; + for (c = inbuf; *c; c++) { + *outbuf++ = *c; + if (*c == '\\' || *c == '"') + *outbuf++ = *c; + } + *outbuf++ = '"'; + } + return l; +} + +int PGconnection::PGescapeString(const char *inbuf, char *outbuf) { + const char *c; + int e = 0, l; + for (c = inbuf; *c; c++) { + if (*c == '\\' || *c == '\'') + e++; + } + l = e + (c - inbuf) + (e ? 4 : 2); + if (outbuf) { + if (e) { + *outbuf++ = ' '; + *outbuf++ = 'E'; + } + *outbuf++ = '\''; + for (c = inbuf; *c; c++) { + *outbuf++ = *c; + if (*c == '\\' || *c == '\'') + *outbuf++ = *c; + } + *outbuf++ = '\''; + } + return l; +} + +char * PGconnection::PGgetValue(int nr) { + int i; + if (_null & (1 << nr)) return NULL; + char *c = _buffer; + if (nr < 0 || nr >= _nfields) return NULL; + for (i = 0; i < nr; i++) { + if (_null & (1 << i)) continue; + c += strlen(c) + 1; + } + return c; +} + +char *PGconnection::PGgetColumn(int n) { + char *c; + int i; + if (!(result_status & PG_RSTAT_HAVE_COLUMNS)) return NULL; + if (n < 0 || n >= _nfields) return NULL; + for (c = _buffer, i = 0; i < n; i++) { + c += strlen(c) + 1; + } + return c; +} + +char *PGconnection::PGgetMessage(void) { + if (!(result_status & PG_RSTAT_HAVE_MESSAGE)) + return NULL; + return _buffer; +} + +void dumpbuffer(char *b,int l) { + int i; + unsigned int v; + for (i=0;i31) printf(" %c ",v); + else printf(" "); + b++; + } + printf("\n"); +} + +int PGconnection::PGgetData(void) { + char id; + int32_t msgLen; + int rc; + char *c; + int r=0; + r=dataAvailable(); +// printf("getData:avail:%d\n",r);fflush(stdout); + if (r==0) return 0; + + if (pqGetc(&id)) goto read_error; + if (pqGetInt4(&msgLen)) goto read_error; +// printf("MSG ID: %c Len:%d (avail:%d)\n",id,msgLen,r);fflush(stdout); + msgLen -= 4; + switch (id) { + case 'T': + if ((rc = pqGetRowDescriptions())) { + if (rc == -2) + setMsg_P(EM_OOM, PG_RSTAT_HAVE_ERROR); + else if (rc == -3) + setMsg_P(EM_BIN, PG_RSTAT_HAVE_ERROR); + goto read_error; + } + if (_flags & PG_FLAG_IGNORE_COLUMNS) { + result_status &= ~PG_RSTAT_HAVE_MASK; + return 0; + } + return result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | PG_RSTAT_HAVE_COLUMNS; + + case 'E': + if (pqGetNotice(PG_RSTAT_HAVE_ERROR)) + goto read_error; + return result_status; + + case 'N': + if (_flags & PG_FLAG_IGNORE_NOTICES) { + if (pqSkipnchar(msgLen)) + goto read_error; + return 0; + } + if (pqGetNotice(PG_RSTAT_HAVE_NOTICE)) + goto read_error; + return result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | PG_RSTAT_HAVE_NOTICE; + + case 'A': + if (_flags & PG_FLAG_IGNORE_NOTICES) { + if (pqSkipnchar(msgLen)) + goto read_error; + return 0; + } + if (pqGetNotify(msgLen)) + goto read_error; + return result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | PG_RSTAT_HAVE_NOTICE; + + case 'Z': + if (pqSkipnchar(msgLen)) + goto read_error; + result_status = (result_status & PG_RSTAT_HAVE_SUMMARY) | PG_RSTAT_READY; + return PG_RSTAT_READY; + + case 'S': + case 'K': + if (pqSkipnchar(msgLen)) + goto read_error; + return 0; + + case 'C': + if (msgLen > _bufSize - 1) + goto oom; + if (pqGetnchar(_buffer, msgLen)) + goto read_error; + _buffer[msgLen] = 0; + _ntuples = 0; + result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | PG_RSTAT_HAVE_SUMMARY; + for (c = _buffer; *c && !isdigit(*c); c++) + ; + if (!*c) + return result_status; + if (strncmp(_buffer, "SELECT ", 7)) { + for (; *c && isdigit(*c); c++) + ; + for (; *c && !isdigit(*c); c++) + ; + } + if (*c) + _ntuples = strtol(c, NULL, 10); + return result_status; + + case 'D': + if ((rc = pqGetRow())) { + if (rc == -2) + setMsg_P(EM_OOM, PG_RSTAT_HAVE_ERROR); + else if (rc == -3) + setMsg_P(EM_SYNC, PG_RSTAT_HAVE_ERROR); + goto read_error; + } + if (_flags & PG_FLAG_IGNORE_COLUMNS) { + result_status &= ~PG_RSTAT_HAVE_MASK; + return 0; + } + + return result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | PG_RSTAT_HAVE_ROW; + + case 'I': + if (pqSkipnchar(msgLen)) + goto read_error; + setMsg_P(EM_EMPTY, PG_RSTAT_HAVE_ERROR); + return result_status; + + default: + setMsg_P(EM_SYNC, PG_RSTAT_HAVE_ERROR); + conn_status = CONNECTION_BAD; + return -1; + } + + oom: setMsg_P(EM_OOM, PG_RSTAT_HAVE_ERROR); + + read_error: if (!(result_status & PG_RSTAT_HAVE_ERROR)) { + printf("READERROR!\n");fflush(stdout); + setMsg_P(EM_READ, PG_RSTAT_HAVE_ERROR); + } + conn_status = CONNECTION_BAD; + return -1; +} + +int PGconnection::PGexecuteFormat(const char *format, ...) { + int32_t msgLen; + va_list va; + va_start(va, format); + msgLen = writeFormattedQuery(0, format, va); + va_end(va); + if (msgLen < 0) + return -1; + va_start(va, format); + msgLen = writeFormattedQuery(msgLen, format, va); + va_end(va); + if (msgLen) { + return -1; + } + result_status = PG_RSTAT_COMMAND_SENT; + return 0; +} + +int PGconnection::build_startup_packet(char *packet, const char *dbName, const char *dbCharset) { + int packet_len = 4; + if (packet) { + memcpy(packet, "\0\003\0\0", 4); + } +#define ADD_STARTUP_OPTION(optname, optval) \ + do { \ + if (packet) \ + strcpy(packet + packet_len, (char *)optname); \ + packet_len += strlen((char *)optname) + 1; \ + if (packet) \ + strcpy(packet + packet_len, (char *)optval); \ + packet_len += strlen((char *)optval) + 1; \ + } while(0) + +#define ADD_STARTUP_OPTION_P(optname, optval) \ + do { \ + if (packet) \ + strcpy(packet + packet_len, (char *)optname); \ + packet_len += strlen((char *)optname) + 1; \ + if (packet) \ + strcpy(packet + packet_len, (char *)optval); \ + packet_len += strlen((char *)optval) + 1; \ + } while(0) + + if (_user && _user[0]) + ADD_STARTUP_OPTION("user", _user); + if (dbName && dbName[0]) + ADD_STARTUP_OPTION("database", dbName); + if (dbCharset && dbCharset[0]) + ADD_STARTUP_OPTION("client_encoding", dbCharset); + ADD_STARTUP_OPTION_P("application_name", "Scaladis"); +#undef ADD_STARTUP_OPTION + if (packet) + packet[packet_len] = '\0'; + packet_len++; + + return packet_len; +} + +int PGconnection::pqPacketSend(char pack_type, const char *buf, int buf_len) { + char *start = _buffer; + int l = _bufSize - 4; +// int n; + if (pack_type) { + *start++ = pack_type; + l--; + } + *start++ = ((buf_len + 4) >> 24) & 0xff; + *start++ = ((buf_len + 4) >> 16) & 0xff; + *start++ = ((buf_len + 4) >> 8) & 0xff; + *start++ = (buf_len + 4) & 0xff; + + if (buf) { + if (buf_len <= l) { + memcpy(start, buf, buf_len); + start += buf_len; + buf_len = 0; + } else { + memcpy(start, buf, l); + start += l; + buf_len -= l; + buf += l; + } + } + int err = send(SockH, _buffer, start - _buffer, 0); + if (err < 0) { + ESP_LOGE(PGTAG, "Send Error occurred during sending: errno %d", errno); + return err; + } + if (buf && buf_len) { + err = send(SockH, (const char *) buf, (size_t) buf_len, 0); + if (err < 0) { + ESP_LOGE(PGTAG, "Send2 Error occurred during sending: errno %d", errno); + return err; + + } + } + + return 0; +} + +int PGconnection::pqGetc(char *buf) { + int i=0; +// for (i = 0; !client->available() && i < 10; i++) { + while (i<10) { + if (dataAvailable()>0) break; + else { + vTaskDelay(i++); + } + } + if (i==10) return -1; + + int len = read(SockH, (void *) buf, 1); + _available-=len; + return -1+len; +} + +int PGconnection::pqGetInt4(int32_t *result) { + uint32_t tmp4 = 0; + uint8_t tmp, i; + int rt=0; + for (i = 0; i < 4; i++) { + rt=pqGetc((char *) &tmp); + if (rt) return -1; + tmp4 = (tmp4 << 8) | tmp; + } + *result = tmp4; + return 0; +} + +int PGconnection::pqGetInt2(int16_t *result) { + uint16_t tmp2 = 0; + uint8_t tmp, i; + for (i = 0; i < 2; i++) { + if (pqGetc((char *) &tmp)) return -1; + tmp2 = (tmp2 << 8) | tmp; + } + *result = tmp2; + return 0; +} + +int PGconnection::pqGetnchar(char *s, int len) { + while (len-- > 0) { + if (pqGetc(s++)) return -1; + } + return 0; +} + +int PGconnection::pqGets(char *s, int maxlen) { + int len; + char z; + for (len = 0; len < maxlen; len++) { + if (pqGetc(&z)) return -1; + if (s) *s++ = z; + if (!z) return len + 1; + } + return -(len + 1); +} + +int PGconnection::pqSkipnchar(int len) { + char dummy; + int i; + for (i=0;i 0) { + if (pqGetc(&dummy)) + return -1; + } + */ + return 0; +} + +int PGconnection::pqGetRow(void) { + int i; + int bufpos = 0; + int32_t len; + int16_t cols; + + _null = 0; + if (pqGetInt2(&cols)) return -1; + if (cols != _nfields) return -3; + + for (i = 0; i < _nfields; i++) { + if (pqGetInt4(&len)) return -1; + if (len < 0) { + _null |= 1 << i; + continue; + } + if (bufpos + len + 1 > _bufSize) { + return -2; + } + if (pqGetnchar(_buffer + bufpos, len)) + return -1; + bufpos += len; + _buffer[bufpos++] = 0; + } + return 0; +} + +int PGconnection::pqGetRowDescriptions(void) { + int i; + int16_t format; + int rc; + int bufpos; + if (pqGetInt2(&_nfields)) + return -1; + if (_nfields > PG_MAX_FIELDS) + return -2; // implementation limit + _formats = 0; + bufpos = 0; + + for (i = 0; i < _nfields; i++) { + if (!(_flags & PG_FLAG_IGNORE_COLUMNS)) { + if (bufpos >= _bufSize - 1) + return -2; + rc = pqGets(_buffer + bufpos, _bufSize - bufpos); + if (rc < 0) + return -1; + bufpos += rc; + } else { + if (pqGets(NULL, 8192) < 0) { + return -1; + } + } + if (pqSkipnchar(16)) + return -1; + if (pqGetInt2(&format)) + return -1; + format = format ? 1 : 0; + _formats |= format << i; + } + if (_formats) + return -3; + return 0; +} + +void PGconnection::setMsg(const char *s, int type) { + strcpy(_buffer, s); + result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | type; +} + +void PGconnection::setMsg_P(const char *s, int type) { + strcpy(_buffer, s); + result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | type; +} + +int PGconnection::pqGetNotice(int type) { + int bufpos = 0; + char id; + int rc; + for (;;) { + if (pqGetc(&id)) goto read_error; + if (!id) + break; + if (id == 'S' || id == 'M') { + if (bufpos && bufpos < _bufSize - 1) + _buffer[bufpos++] = ':'; + rc = pqGets(_buffer + bufpos, _bufSize - bufpos); + if (rc < 0) + goto read_error; + bufpos += rc - 1; + } else { + rc = pqGets(NULL, 8192); + if (rc < 0) goto read_error; + } + } + _buffer[bufpos] = 0; + result_status = (result_status & ~PG_RSTAT_HAVE_MASK) | type; + return 0; + + read_error: if (!bufpos) + setMsg_P(EM_READ, PG_RSTAT_HAVE_ERROR); + return -1; +} + +int PGconnection::pqGetNotify(int32_t msgLen) { + int32_t pid; + int bufpos, i; + if (pqGetInt4(&pid)) + return -1; + msgLen -= 4; + bufpos = sprintf(_buffer, "%d:", pid); + if (msgLen > _bufSize - (bufpos + 1)) { + if (pqGetnchar(_buffer + bufpos, _bufSize - (bufpos + 1))) + return -1; + msgLen -= _bufSize - (bufpos + 1); + if (pqSkipnchar(msgLen)) + return -1; + _buffer[msgLen = _bufSize - 1] = 0; + + } else { + if (pqGetnchar(_buffer + bufpos, msgLen)) + return -1; + _buffer[bufpos + msgLen] = 0; + msgLen += bufpos; + } + for (i = 0; i < msgLen; i++) + if (!_buffer[i]) + _buffer[i] = ':'; + return 0; +} + +int PGconnection::dataAvailable() { + int res=0; +// if (_available) return _available; + ioctl(SockH,FIONREAD,&res); + return res; +} + +int PGconnection::writeMsgPart(const char *s, int len, int fine) { + while (len > 0) { + int n = len; + if (n > _bufSize - bufPos) + n = _bufSize - bufPos; + memcpy(_buffer + bufPos, s, n); + bufPos += n; + s += n; + len -= n; + if (bufPos >= _bufSize) { +// if (client->write((uint8_t *) Buffer, bufPos) != (size_t) bufPos) return -1; + int err = send(SockH, _buffer, bufPos, 0); + if (err < 0) + return -1; + bufPos = 0; + } + } + if (bufPos && fine) { +// if (client->write((uint8_t *) Buffer, bufPos) != (size_t) bufPos) return -1; + int err = send(SockH, _buffer, bufPos, 0); + if (err < 0) + return -1; + + bufPos = 0; + } + + return 0; +} + +int32_t PGconnection::writeFormattedQuery(int32_t length, const char *format, va_list va) { + int32_t msgLen = 0; + const char *percent; + int blen, rc; +#define LBUFLEN 32 + char buf[LBUFLEN], znak; + if (length) { + length += 4; + bufPos = 0; + _buffer[bufPos++] = 'Q'; + _buffer[bufPos++] = (length >> 24) & 0xff; + _buffer[bufPos++] = (length >> 16) & 0xff; + _buffer[bufPos++] = (length >> 8) & 0xff; + _buffer[bufPos++] = (length) & 0xff; + } + for (;;) { + percent = strchr(format, '%'); + if (!percent) + break; + znak = percent[1]; + if (!length) { + msgLen += (percent - format); + } else { + rc = writeMsgPart(format, percent - format, false); + if (rc) + goto write_error; + } + format = percent + 2; + if (znak == 's' || znak == 'n') { + char *str = va_arg(va, char *); + blen = (znak == 's') ? PGescapeString(str, NULL) : PGescapeName(str, NULL); + if (!length) { + msgLen += blen; + } else { + if (bufPos + blen > _bufSize) { + rc = writeMsgPart(NULL, 0, true); + if (rc) + goto write_error; + } + } + if (znak == 's') { + PGescapeString(str, _buffer + bufPos); + } else { + PGescapeName(str, _buffer + bufPos); + } + bufPos += blen; + continue; + } + if (znak == 'l' || znak == 'd') { + if (znak == 'l') { + long n = va_arg(va, long); + blen = snprintf(buf, LBUFLEN, "'%ld'", n); + } else { + int n = va_arg(va, int); + blen = snprintf(buf, LBUFLEN, "'%d'", n); + } + if (length) { + rc = writeMsgPart(buf, blen, false); + if (rc) + goto write_error; + } else { + msgLen += blen; + } + } + setMsg_P(EM_FORMAT, PG_RSTAT_HAVE_ERROR); + return -1; + } + blen = strlen(format); + if (length) { + rc = writeMsgPart(format, blen, false); + if (!rc) { + rc = writeMsgPart("\0", 1, true); + } + if (rc) + goto write_error; + } else { + msgLen += blen + 1; + } + return msgLen; + + write_error: setMsg_P(EM_WRITE, PG_RSTAT_HAVE_ERROR); + conn_status = CONNECTION_BAD; + return -1; +} -- cgit v1.2.3