00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres_fe.h"
00016
00017 #include <ctype.h>
00018 #include <fcntl.h>
00019
00020 #include "libpq-fe.h"
00021 #include "libpq-int.h"
00022
00023 #include "mb/pg_wchar.h"
00024
00025 #ifdef WIN32
00026 #include "win32.h"
00027 #else
00028 #include <unistd.h>
00029 #endif
00030
00031
00032 char *const pgresStatus[] = {
00033 "PGRES_EMPTY_QUERY",
00034 "PGRES_COMMAND_OK",
00035 "PGRES_TUPLES_OK",
00036 "PGRES_COPY_OUT",
00037 "PGRES_COPY_IN",
00038 "PGRES_BAD_RESPONSE",
00039 "PGRES_NONFATAL_ERROR",
00040 "PGRES_FATAL_ERROR",
00041 "PGRES_COPY_BOTH",
00042 "PGRES_SINGLE_TUPLE"
00043 };
00044
00045
00046
00047
00048
00049 static int static_client_encoding = PG_SQL_ASCII;
00050 static bool static_std_strings = false;
00051
00052
00053 static PGEvent *dupEvents(PGEvent *events, int count);
00054 static bool pqAddTuple(PGresult *res, PGresAttValue *tup);
00055 static bool PQsendQueryStart(PGconn *conn);
00056 static int PQsendQueryGuts(PGconn *conn,
00057 const char *command,
00058 const char *stmtName,
00059 int nParams,
00060 const Oid *paramTypes,
00061 const char *const * paramValues,
00062 const int *paramLengths,
00063 const int *paramFormats,
00064 int resultFormat);
00065 static void parseInput(PGconn *conn);
00066 static bool PQexecStart(PGconn *conn);
00067 static PGresult *PQexecFinish(PGconn *conn);
00068 static int PQsendDescribe(PGconn *conn, char desc_type,
00069 const char *desc_target);
00070 static int check_field_number(const PGresult *res, int field_num);
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 #define PGRESULT_DATA_BLOCKSIZE 2048
00127 #define PGRESULT_ALIGN_BOUNDARY MAXIMUM_ALIGNOF
00128 #define PGRESULT_BLOCK_OVERHEAD Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
00129 #define PGRESULT_SEP_ALLOC_THRESHOLD (PGRESULT_DATA_BLOCKSIZE / 2)
00130
00131
00132
00133
00134
00135
00136
00137
00138 PGresult *
00139 PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
00140 {
00141 PGresult *result;
00142
00143 result = (PGresult *) malloc(sizeof(PGresult));
00144 if (!result)
00145 return NULL;
00146
00147 result->ntups = 0;
00148 result->numAttributes = 0;
00149 result->attDescs = NULL;
00150 result->tuples = NULL;
00151 result->tupArrSize = 0;
00152 result->numParameters = 0;
00153 result->paramDescs = NULL;
00154 result->resultStatus = status;
00155 result->cmdStatus[0] = '\0';
00156 result->binary = 0;
00157 result->events = NULL;
00158 result->nEvents = 0;
00159 result->errMsg = NULL;
00160 result->errFields = NULL;
00161 result->null_field[0] = '\0';
00162 result->curBlock = NULL;
00163 result->curOffset = 0;
00164 result->spaceLeft = 0;
00165
00166 if (conn)
00167 {
00168
00169 result->noticeHooks = conn->noticeHooks;
00170 result->client_encoding = conn->client_encoding;
00171
00172
00173 switch (status)
00174 {
00175 case PGRES_EMPTY_QUERY:
00176 case PGRES_COMMAND_OK:
00177 case PGRES_TUPLES_OK:
00178 case PGRES_COPY_OUT:
00179 case PGRES_COPY_IN:
00180 case PGRES_COPY_BOTH:
00181 case PGRES_SINGLE_TUPLE:
00182
00183 break;
00184 default:
00185 pqSetResultError(result, conn->errorMessage.data);
00186 break;
00187 }
00188
00189
00190 if (conn->nEvents > 0)
00191 {
00192 result->events = dupEvents(conn->events, conn->nEvents);
00193 if (!result->events)
00194 {
00195 PQclear(result);
00196 return NULL;
00197 }
00198 result->nEvents = conn->nEvents;
00199 }
00200 }
00201 else
00202 {
00203
00204 result->noticeHooks.noticeRec = NULL;
00205 result->noticeHooks.noticeRecArg = NULL;
00206 result->noticeHooks.noticeProc = NULL;
00207 result->noticeHooks.noticeProcArg = NULL;
00208 result->client_encoding = PG_SQL_ASCII;
00209 }
00210
00211 return result;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 int
00224 PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
00225 {
00226 int i;
00227
00228
00229 if (!res || res->numAttributes > 0)
00230 return FALSE;
00231
00232
00233 if (numAttributes <= 0 || !attDescs)
00234 return TRUE;
00235
00236 res->attDescs = (PGresAttDesc *)
00237 PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
00238
00239 if (!res->attDescs)
00240 return FALSE;
00241
00242 res->numAttributes = numAttributes;
00243 memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
00244
00245
00246 res->binary = 1;
00247 for (i = 0; i < res->numAttributes; i++)
00248 {
00249 if (res->attDescs[i].name)
00250 res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
00251 else
00252 res->attDescs[i].name = res->null_field;
00253
00254 if (!res->attDescs[i].name)
00255 return FALSE;
00256
00257 if (res->attDescs[i].format == 0)
00258 res->binary = 0;
00259 }
00260
00261 return TRUE;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 PGresult *
00289 PQcopyResult(const PGresult *src, int flags)
00290 {
00291 PGresult *dest;
00292 int i;
00293
00294 if (!src)
00295 return NULL;
00296
00297 dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
00298 if (!dest)
00299 return NULL;
00300
00301
00302 dest->client_encoding = src->client_encoding;
00303 strcpy(dest->cmdStatus, src->cmdStatus);
00304
00305
00306 if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
00307 {
00308 if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
00309 {
00310 PQclear(dest);
00311 return NULL;
00312 }
00313 }
00314
00315
00316 if (flags & PG_COPYRES_TUPLES)
00317 {
00318 int tup,
00319 field;
00320
00321 for (tup = 0; tup < src->ntups; tup++)
00322 {
00323 for (field = 0; field < src->numAttributes; field++)
00324 {
00325 if (!PQsetvalue(dest, tup, field,
00326 src->tuples[tup][field].value,
00327 src->tuples[tup][field].len))
00328 {
00329 PQclear(dest);
00330 return NULL;
00331 }
00332 }
00333 }
00334 }
00335
00336
00337 if (flags & PG_COPYRES_NOTICEHOOKS)
00338 dest->noticeHooks = src->noticeHooks;
00339
00340
00341 if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
00342 {
00343 dest->events = dupEvents(src->events, src->nEvents);
00344 if (!dest->events)
00345 {
00346 PQclear(dest);
00347 return NULL;
00348 }
00349 dest->nEvents = src->nEvents;
00350 }
00351
00352
00353 for (i = 0; i < dest->nEvents; i++)
00354 {
00355 if (src->events[i].resultInitialized)
00356 {
00357 PGEventResultCopy evt;
00358
00359 evt.src = src;
00360 evt.dest = dest;
00361 if (!dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
00362 dest->events[i].passThrough))
00363 {
00364 PQclear(dest);
00365 return NULL;
00366 }
00367 dest->events[i].resultInitialized = TRUE;
00368 }
00369 }
00370
00371 return dest;
00372 }
00373
00374
00375
00376
00377
00378
00379 static PGEvent *
00380 dupEvents(PGEvent *events, int count)
00381 {
00382 PGEvent *newEvents;
00383 int i;
00384
00385 if (!events || count <= 0)
00386 return NULL;
00387
00388 newEvents = (PGEvent *) malloc(count * sizeof(PGEvent));
00389 if (!newEvents)
00390 return NULL;
00391
00392 for (i = 0; i < count; i++)
00393 {
00394 newEvents[i].proc = events[i].proc;
00395 newEvents[i].passThrough = events[i].passThrough;
00396 newEvents[i].data = NULL;
00397 newEvents[i].resultInitialized = FALSE;
00398 newEvents[i].name = strdup(events[i].name);
00399 if (!newEvents[i].name)
00400 {
00401 while (--i >= 0)
00402 free(newEvents[i].name);
00403 free(newEvents);
00404 return NULL;
00405 }
00406 }
00407
00408 return newEvents;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418 int
00419 PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
00420 {
00421 PGresAttValue *attval;
00422
00423 if (!check_field_number(res, field_num))
00424 return FALSE;
00425
00426
00427 if (tup_num < 0 || tup_num > res->ntups)
00428 return FALSE;
00429
00430
00431 if (tup_num == res->ntups)
00432 {
00433 PGresAttValue *tup;
00434 int i;
00435
00436 tup = (PGresAttValue *)
00437 pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue),
00438 TRUE);
00439
00440 if (!tup)
00441 return FALSE;
00442
00443
00444 for (i = 0; i < res->numAttributes; i++)
00445 {
00446 tup[i].len = NULL_LEN;
00447 tup[i].value = res->null_field;
00448 }
00449
00450
00451 if (!pqAddTuple(res, tup))
00452 return FALSE;
00453 }
00454
00455 attval = &res->tuples[tup_num][field_num];
00456
00457
00458 if (len == NULL_LEN || value == NULL)
00459 {
00460 attval->len = NULL_LEN;
00461 attval->value = res->null_field;
00462 }
00463 else if (len <= 0)
00464 {
00465 attval->len = 0;
00466 attval->value = res->null_field;
00467 }
00468 else
00469 {
00470 attval->value = (char *) pqResultAlloc(res, len + 1, TRUE);
00471 if (!attval->value)
00472 return FALSE;
00473 attval->len = len;
00474 memcpy(attval->value, value, len);
00475 attval->value[len] = '\0';
00476 }
00477
00478 return TRUE;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void *
00488 PQresultAlloc(PGresult *res, size_t nBytes)
00489 {
00490 return pqResultAlloc(res, nBytes, TRUE);
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 void *
00504 pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
00505 {
00506 char *space;
00507 PGresult_data *block;
00508
00509 if (!res)
00510 return NULL;
00511
00512 if (nBytes <= 0)
00513 return res->null_field;
00514
00515
00516
00517
00518
00519 if (isBinary)
00520 {
00521 int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
00522
00523 if (offset)
00524 {
00525 res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
00526 res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
00527 }
00528 }
00529
00530
00531 if (nBytes <= (size_t) res->spaceLeft)
00532 {
00533 space = res->curBlock->space + res->curOffset;
00534 res->curOffset += nBytes;
00535 res->spaceLeft -= nBytes;
00536 return space;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545 if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
00546 {
00547 block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
00548 if (!block)
00549 return NULL;
00550 space = block->space + PGRESULT_BLOCK_OVERHEAD;
00551 if (res->curBlock)
00552 {
00553
00554
00555
00556
00557 block->next = res->curBlock->next;
00558 res->curBlock->next = block;
00559 }
00560 else
00561 {
00562
00563 block->next = NULL;
00564 res->curBlock = block;
00565 res->spaceLeft = 0;
00566 }
00567 return space;
00568 }
00569
00570
00571 block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
00572 if (!block)
00573 return NULL;
00574 block->next = res->curBlock;
00575 res->curBlock = block;
00576 if (isBinary)
00577 {
00578
00579 res->curOffset = PGRESULT_BLOCK_OVERHEAD;
00580 res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
00581 }
00582 else
00583 {
00584
00585 res->curOffset = sizeof(PGresult_data);
00586 res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
00587 }
00588
00589 space = block->space + res->curOffset;
00590 res->curOffset += nBytes;
00591 res->spaceLeft -= nBytes;
00592 return space;
00593 }
00594
00595
00596
00597
00598
00599 char *
00600 pqResultStrdup(PGresult *res, const char *str)
00601 {
00602 char *space = (char *) pqResultAlloc(res, strlen(str) + 1, FALSE);
00603
00604 if (space)
00605 strcpy(space, str);
00606 return space;
00607 }
00608
00609
00610
00611
00612
00613 void
00614 pqSetResultError(PGresult *res, const char *msg)
00615 {
00616 if (!res)
00617 return;
00618 if (msg && *msg)
00619 res->errMsg = pqResultStrdup(res, msg);
00620 else
00621 res->errMsg = NULL;
00622 }
00623
00624
00625
00626
00627
00628 void
00629 pqCatenateResultError(PGresult *res, const char *msg)
00630 {
00631 PQExpBufferData errorBuf;
00632
00633 if (!res || !msg)
00634 return;
00635 initPQExpBuffer(&errorBuf);
00636 if (res->errMsg)
00637 appendPQExpBufferStr(&errorBuf, res->errMsg);
00638 appendPQExpBufferStr(&errorBuf, msg);
00639 pqSetResultError(res, errorBuf.data);
00640 termPQExpBuffer(&errorBuf);
00641 }
00642
00643
00644
00645
00646
00647 void
00648 PQclear(PGresult *res)
00649 {
00650 PGresult_data *block;
00651 int i;
00652
00653 if (!res)
00654 return;
00655
00656 for (i = 0; i < res->nEvents; i++)
00657 {
00658
00659 if (res->events[i].resultInitialized)
00660 {
00661 PGEventResultDestroy evt;
00662
00663 evt.result = res;
00664 (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
00665 res->events[i].passThrough);
00666 }
00667 free(res->events[i].name);
00668 }
00669
00670 if (res->events)
00671 free(res->events);
00672
00673
00674 while ((block = res->curBlock) != NULL)
00675 {
00676 res->curBlock = block->next;
00677 free(block);
00678 }
00679
00680
00681 if (res->tuples)
00682 free(res->tuples);
00683
00684
00685 res->attDescs = NULL;
00686 res->tuples = NULL;
00687 res->paramDescs = NULL;
00688 res->errFields = NULL;
00689 res->events = NULL;
00690 res->nEvents = 0;
00691
00692
00693
00694 free(res);
00695 }
00696
00697
00698
00699
00700
00701
00702 void
00703 pqClearAsyncResult(PGconn *conn)
00704 {
00705 if (conn->result)
00706 PQclear(conn->result);
00707 conn->result = NULL;
00708 if (conn->next_result)
00709 PQclear(conn->next_result);
00710 conn->next_result = NULL;
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 void
00726 pqSaveErrorResult(PGconn *conn)
00727 {
00728
00729
00730
00731
00732 if (conn->result == NULL ||
00733 conn->result->resultStatus != PGRES_FATAL_ERROR ||
00734 conn->result->errMsg == NULL)
00735 {
00736 pqClearAsyncResult(conn);
00737 conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
00738 }
00739 else
00740 {
00741
00742 pqCatenateResultError(conn->result, conn->errorMessage.data);
00743 }
00744 }
00745
00746
00747
00748
00749
00750
00751
00752
00753 PGresult *
00754 pqPrepareAsyncResult(PGconn *conn)
00755 {
00756 PGresult *res;
00757
00758
00759
00760
00761
00762
00763 res = conn->result;
00764 if (!res)
00765 res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
00766 else
00767 {
00768
00769
00770
00771
00772 resetPQExpBuffer(&conn->errorMessage);
00773 appendPQExpBufferStr(&conn->errorMessage,
00774 PQresultErrorMessage(res));
00775 }
00776
00777
00778
00779
00780
00781
00782
00783 conn->result = conn->next_result;
00784 conn->next_result = NULL;
00785
00786 return res;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 void
00799 pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
00800 {
00801 char msgBuf[1024];
00802 va_list args;
00803 PGresult *res;
00804
00805 if (hooks->noticeRec == NULL)
00806 return;
00807
00808
00809 va_start(args, fmt);
00810 vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
00811 va_end(args);
00812 msgBuf[sizeof(msgBuf) - 1] = '\0';
00813
00814
00815 res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR);
00816 if (!res)
00817 return;
00818 res->noticeHooks = *hooks;
00819
00820
00821
00822
00823 pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
00824 pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
00825
00826
00827
00828
00829
00830
00831 res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, FALSE);
00832 if (res->errMsg)
00833 {
00834 sprintf(res->errMsg, "%s\n", msgBuf);
00835
00836
00837
00838
00839 (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
00840 }
00841 PQclear(res);
00842 }
00843
00844
00845
00846
00847
00848
00849 static bool
00850 pqAddTuple(PGresult *res, PGresAttValue *tup)
00851 {
00852 if (res->ntups >= res->tupArrSize)
00853 {
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 int newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
00866 PGresAttValue **newTuples;
00867
00868 if (res->tuples == NULL)
00869 newTuples = (PGresAttValue **)
00870 malloc(newSize * sizeof(PGresAttValue *));
00871 else
00872 newTuples = (PGresAttValue **)
00873 realloc(res->tuples, newSize * sizeof(PGresAttValue *));
00874 if (!newTuples)
00875 return FALSE;
00876 res->tupArrSize = newSize;
00877 res->tuples = newTuples;
00878 }
00879 res->tuples[res->ntups] = tup;
00880 res->ntups++;
00881 return TRUE;
00882 }
00883
00884
00885
00886
00887 void
00888 pqSaveMessageField(PGresult *res, char code, const char *value)
00889 {
00890 PGMessageField *pfield;
00891
00892 pfield = (PGMessageField *)
00893 pqResultAlloc(res,
00894 sizeof(PGMessageField) + strlen(value),
00895 TRUE);
00896 if (!pfield)
00897 return;
00898 pfield->code = code;
00899 strcpy(pfield->contents, value);
00900 pfield->next = res->errFields;
00901 res->errFields = pfield;
00902 }
00903
00904
00905
00906
00907 void
00908 pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
00909 {
00910 pgParameterStatus *pstatus;
00911 pgParameterStatus *prev;
00912
00913 if (conn->Pfdebug)
00914 fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
00915 name, value);
00916
00917
00918
00919
00920 for (pstatus = conn->pstatus, prev = NULL;
00921 pstatus != NULL;
00922 prev = pstatus, pstatus = pstatus->next)
00923 {
00924 if (strcmp(pstatus->name, name) == 0)
00925 {
00926 if (prev)
00927 prev->next = pstatus->next;
00928 else
00929 conn->pstatus = pstatus->next;
00930 free(pstatus);
00931 break;
00932 }
00933 }
00934
00935
00936
00937
00938 pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
00939 strlen(name) +strlen(value) + 2);
00940 if (pstatus)
00941 {
00942 char *ptr;
00943
00944 ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
00945 pstatus->name = ptr;
00946 strcpy(ptr, name);
00947 ptr += strlen(name) + 1;
00948 pstatus->value = ptr;
00949 strcpy(ptr, value);
00950 pstatus->next = conn->pstatus;
00951 conn->pstatus = pstatus;
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 if (strcmp(name, "client_encoding") == 0)
00962 {
00963 conn->client_encoding = pg_char_to_encoding(value);
00964
00965 if (conn->client_encoding < 0)
00966 conn->client_encoding = PG_SQL_ASCII;
00967 static_client_encoding = conn->client_encoding;
00968 }
00969 else if (strcmp(name, "standard_conforming_strings") == 0)
00970 {
00971 conn->std_strings = (strcmp(value, "on") == 0);
00972 static_std_strings = conn->std_strings;
00973 }
00974 else if (strcmp(name, "server_version") == 0)
00975 {
00976 int cnt;
00977 int vmaj,
00978 vmin,
00979 vrev;
00980
00981 cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
00982
00983 if (cnt < 2)
00984 conn->sversion = 0;
00985 else
00986 {
00987 if (cnt == 2)
00988 vrev = 0;
00989 conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
00990 }
00991 }
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 int
01009 pqRowProcessor(PGconn *conn, const char **errmsgp)
01010 {
01011 PGresult *res = conn->result;
01012 int nfields = res->numAttributes;
01013 const PGdataValue *columns = conn->rowBuf;
01014 PGresAttValue *tup;
01015 int i;
01016
01017
01018
01019
01020
01021
01022 if (conn->singleRowMode)
01023 {
01024
01025 res = PQcopyResult(res,
01026 PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
01027 PG_COPYRES_NOTICEHOOKS);
01028 if (!res)
01029 return 0;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 tup = (PGresAttValue *)
01042 pqResultAlloc(res, nfields * sizeof(PGresAttValue), TRUE);
01043 if (tup == NULL)
01044 goto fail;
01045
01046 for (i = 0; i < nfields; i++)
01047 {
01048 int clen = columns[i].len;
01049
01050 if (clen < 0)
01051 {
01052
01053 tup[i].len = NULL_LEN;
01054 tup[i].value = res->null_field;
01055 }
01056 else
01057 {
01058 bool isbinary = (res->attDescs[i].format != 0);
01059 char *val;
01060
01061 val = (char *) pqResultAlloc(res, clen + 1, isbinary);
01062 if (val == NULL)
01063 goto fail;
01064
01065
01066 memcpy(val, columns[i].value, clen);
01067 val[clen] = '\0';
01068
01069 tup[i].len = clen;
01070 tup[i].value = val;
01071 }
01072 }
01073
01074
01075 if (!pqAddTuple(res, tup))
01076 goto fail;
01077
01078
01079
01080
01081
01082 if (conn->singleRowMode)
01083 {
01084
01085 res->resultStatus = PGRES_SINGLE_TUPLE;
01086
01087 conn->next_result = conn->result;
01088 conn->result = res;
01089
01090 conn->asyncStatus = PGASYNC_READY;
01091 }
01092
01093 return 1;
01094
01095 fail:
01096
01097 if (res != conn->result)
01098 PQclear(res);
01099 return 0;
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 int
01111 PQsendQuery(PGconn *conn, const char *query)
01112 {
01113 if (!PQsendQueryStart(conn))
01114 return 0;
01115
01116
01117 if (!query)
01118 {
01119 printfPQExpBuffer(&conn->errorMessage,
01120 libpq_gettext("command string is a null pointer\n"));
01121 return 0;
01122 }
01123
01124
01125 if (pqPutMsgStart('Q', false, conn) < 0 ||
01126 pqPuts(query, conn) < 0 ||
01127 pqPutMsgEnd(conn) < 0)
01128 {
01129 pqHandleSendFailure(conn);
01130 return 0;
01131 }
01132
01133
01134 conn->queryclass = PGQUERY_SIMPLE;
01135
01136
01137
01138 if (conn->last_query)
01139 free(conn->last_query);
01140 conn->last_query = strdup(query);
01141
01142
01143
01144
01145
01146 if (pqFlush(conn) < 0)
01147 {
01148 pqHandleSendFailure(conn);
01149 return 0;
01150 }
01151
01152
01153 conn->asyncStatus = PGASYNC_BUSY;
01154 return 1;
01155 }
01156
01157
01158
01159
01160
01161 int
01162 PQsendQueryParams(PGconn *conn,
01163 const char *command,
01164 int nParams,
01165 const Oid *paramTypes,
01166 const char *const * paramValues,
01167 const int *paramLengths,
01168 const int *paramFormats,
01169 int resultFormat)
01170 {
01171 if (!PQsendQueryStart(conn))
01172 return 0;
01173
01174
01175 if (!command)
01176 {
01177 printfPQExpBuffer(&conn->errorMessage,
01178 libpq_gettext("command string is a null pointer\n"));
01179 return 0;
01180 }
01181 if (nParams < 0 || nParams > 65535)
01182 {
01183 printfPQExpBuffer(&conn->errorMessage,
01184 libpq_gettext("number of parameters must be between 0 and 65535\n"));
01185 return 0;
01186 }
01187
01188 return PQsendQueryGuts(conn,
01189 command,
01190 "",
01191 nParams,
01192 paramTypes,
01193 paramValues,
01194 paramLengths,
01195 paramFormats,
01196 resultFormat);
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206 int
01207 PQsendPrepare(PGconn *conn,
01208 const char *stmtName, const char *query,
01209 int nParams, const Oid *paramTypes)
01210 {
01211 if (!PQsendQueryStart(conn))
01212 return 0;
01213
01214
01215 if (!stmtName)
01216 {
01217 printfPQExpBuffer(&conn->errorMessage,
01218 libpq_gettext("statement name is a null pointer\n"));
01219 return 0;
01220 }
01221 if (!query)
01222 {
01223 printfPQExpBuffer(&conn->errorMessage,
01224 libpq_gettext("command string is a null pointer\n"));
01225 return 0;
01226 }
01227 if (nParams < 0 || nParams > 65535)
01228 {
01229 printfPQExpBuffer(&conn->errorMessage,
01230 libpq_gettext("number of parameters must be between 0 and 65535\n"));
01231 return 0;
01232 }
01233
01234
01235 if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
01236 {
01237 printfPQExpBuffer(&conn->errorMessage,
01238 libpq_gettext("function requires at least protocol version 3.0\n"));
01239 return 0;
01240 }
01241
01242
01243 if (pqPutMsgStart('P', false, conn) < 0 ||
01244 pqPuts(stmtName, conn) < 0 ||
01245 pqPuts(query, conn) < 0)
01246 goto sendFailed;
01247
01248 if (nParams > 0 && paramTypes)
01249 {
01250 int i;
01251
01252 if (pqPutInt(nParams, 2, conn) < 0)
01253 goto sendFailed;
01254 for (i = 0; i < nParams; i++)
01255 {
01256 if (pqPutInt(paramTypes[i], 4, conn) < 0)
01257 goto sendFailed;
01258 }
01259 }
01260 else
01261 {
01262 if (pqPutInt(0, 2, conn) < 0)
01263 goto sendFailed;
01264 }
01265 if (pqPutMsgEnd(conn) < 0)
01266 goto sendFailed;
01267
01268
01269 if (pqPutMsgStart('S', false, conn) < 0 ||
01270 pqPutMsgEnd(conn) < 0)
01271 goto sendFailed;
01272
01273
01274 conn->queryclass = PGQUERY_PREPARE;
01275
01276
01277
01278 if (conn->last_query)
01279 free(conn->last_query);
01280 conn->last_query = strdup(query);
01281
01282
01283
01284
01285
01286 if (pqFlush(conn) < 0)
01287 goto sendFailed;
01288
01289
01290 conn->asyncStatus = PGASYNC_BUSY;
01291 return 1;
01292
01293 sendFailed:
01294 pqHandleSendFailure(conn);
01295 return 0;
01296 }
01297
01298
01299
01300
01301
01302
01303 int
01304 PQsendQueryPrepared(PGconn *conn,
01305 const char *stmtName,
01306 int nParams,
01307 const char *const * paramValues,
01308 const int *paramLengths,
01309 const int *paramFormats,
01310 int resultFormat)
01311 {
01312 if (!PQsendQueryStart(conn))
01313 return 0;
01314
01315
01316 if (!stmtName)
01317 {
01318 printfPQExpBuffer(&conn->errorMessage,
01319 libpq_gettext("statement name is a null pointer\n"));
01320 return 0;
01321 }
01322 if (nParams < 0 || nParams > 65535)
01323 {
01324 printfPQExpBuffer(&conn->errorMessage,
01325 libpq_gettext("number of parameters must be between 0 and 65535\n"));
01326 return 0;
01327 }
01328
01329 return PQsendQueryGuts(conn,
01330 NULL,
01331 stmtName,
01332 nParams,
01333 NULL,
01334 paramValues,
01335 paramLengths,
01336 paramFormats,
01337 resultFormat);
01338 }
01339
01340
01341
01342
01343 static bool
01344 PQsendQueryStart(PGconn *conn)
01345 {
01346 if (!conn)
01347 return false;
01348
01349
01350 resetPQExpBuffer(&conn->errorMessage);
01351
01352
01353 if (conn->status != CONNECTION_OK)
01354 {
01355 printfPQExpBuffer(&conn->errorMessage,
01356 libpq_gettext("no connection to the server\n"));
01357 return false;
01358 }
01359
01360 if (conn->asyncStatus != PGASYNC_IDLE)
01361 {
01362 printfPQExpBuffer(&conn->errorMessage,
01363 libpq_gettext("another command is already in progress\n"));
01364 return false;
01365 }
01366
01367
01368 conn->result = NULL;
01369 conn->next_result = NULL;
01370
01371
01372 conn->singleRowMode = false;
01373
01374
01375 return true;
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385 static int
01386 PQsendQueryGuts(PGconn *conn,
01387 const char *command,
01388 const char *stmtName,
01389 int nParams,
01390 const Oid *paramTypes,
01391 const char *const * paramValues,
01392 const int *paramLengths,
01393 const int *paramFormats,
01394 int resultFormat)
01395 {
01396 int i;
01397
01398
01399 if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
01400 {
01401 printfPQExpBuffer(&conn->errorMessage,
01402 libpq_gettext("function requires at least protocol version 3.0\n"));
01403 return 0;
01404 }
01405
01406
01407
01408
01409
01410
01411 if (command)
01412 {
01413
01414 if (pqPutMsgStart('P', false, conn) < 0 ||
01415 pqPuts(stmtName, conn) < 0 ||
01416 pqPuts(command, conn) < 0)
01417 goto sendFailed;
01418 if (nParams > 0 && paramTypes)
01419 {
01420 if (pqPutInt(nParams, 2, conn) < 0)
01421 goto sendFailed;
01422 for (i = 0; i < nParams; i++)
01423 {
01424 if (pqPutInt(paramTypes[i], 4, conn) < 0)
01425 goto sendFailed;
01426 }
01427 }
01428 else
01429 {
01430 if (pqPutInt(0, 2, conn) < 0)
01431 goto sendFailed;
01432 }
01433 if (pqPutMsgEnd(conn) < 0)
01434 goto sendFailed;
01435 }
01436
01437
01438 if (pqPutMsgStart('B', false, conn) < 0 ||
01439 pqPuts("", conn) < 0 ||
01440 pqPuts(stmtName, conn) < 0)
01441 goto sendFailed;
01442
01443
01444 if (nParams > 0 && paramFormats)
01445 {
01446 if (pqPutInt(nParams, 2, conn) < 0)
01447 goto sendFailed;
01448 for (i = 0; i < nParams; i++)
01449 {
01450 if (pqPutInt(paramFormats[i], 2, conn) < 0)
01451 goto sendFailed;
01452 }
01453 }
01454 else
01455 {
01456 if (pqPutInt(0, 2, conn) < 0)
01457 goto sendFailed;
01458 }
01459
01460 if (pqPutInt(nParams, 2, conn) < 0)
01461 goto sendFailed;
01462
01463
01464 for (i = 0; i < nParams; i++)
01465 {
01466 if (paramValues && paramValues[i])
01467 {
01468 int nbytes;
01469
01470 if (paramFormats && paramFormats[i] != 0)
01471 {
01472
01473 if (paramLengths)
01474 nbytes = paramLengths[i];
01475 else
01476 {
01477 printfPQExpBuffer(&conn->errorMessage,
01478 libpq_gettext("length must be given for binary parameter\n"));
01479 goto sendFailed;
01480 }
01481 }
01482 else
01483 {
01484
01485 nbytes = strlen(paramValues[i]);
01486 }
01487 if (pqPutInt(nbytes, 4, conn) < 0 ||
01488 pqPutnchar(paramValues[i], nbytes, conn) < 0)
01489 goto sendFailed;
01490 }
01491 else
01492 {
01493
01494 if (pqPutInt(-1, 4, conn) < 0)
01495 goto sendFailed;
01496 }
01497 }
01498 if (pqPutInt(1, 2, conn) < 0 ||
01499 pqPutInt(resultFormat, 2, conn))
01500 goto sendFailed;
01501 if (pqPutMsgEnd(conn) < 0)
01502 goto sendFailed;
01503
01504
01505 if (pqPutMsgStart('D', false, conn) < 0 ||
01506 pqPutc('P', conn) < 0 ||
01507 pqPuts("", conn) < 0 ||
01508 pqPutMsgEnd(conn) < 0)
01509 goto sendFailed;
01510
01511
01512 if (pqPutMsgStart('E', false, conn) < 0 ||
01513 pqPuts("", conn) < 0 ||
01514 pqPutInt(0, 4, conn) < 0 ||
01515 pqPutMsgEnd(conn) < 0)
01516 goto sendFailed;
01517
01518
01519 if (pqPutMsgStart('S', false, conn) < 0 ||
01520 pqPutMsgEnd(conn) < 0)
01521 goto sendFailed;
01522
01523
01524 conn->queryclass = PGQUERY_EXTENDED;
01525
01526
01527
01528 if (conn->last_query)
01529 free(conn->last_query);
01530 if (command)
01531 conn->last_query = strdup(command);
01532 else
01533 conn->last_query = NULL;
01534
01535
01536
01537
01538
01539 if (pqFlush(conn) < 0)
01540 goto sendFailed;
01541
01542
01543 conn->asyncStatus = PGASYNC_BUSY;
01544 return 1;
01545
01546 sendFailed:
01547 pqHandleSendFailure(conn);
01548 return 0;
01549 }
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559 void
01560 pqHandleSendFailure(PGconn *conn)
01561 {
01562
01563
01564
01565
01566
01567 while (pqReadData(conn) > 0)
01568 ;
01569
01570
01571
01572
01573
01574 parseInput(conn);
01575 }
01576
01577
01578
01579
01580 int
01581 PQsetSingleRowMode(PGconn *conn)
01582 {
01583
01584
01585
01586
01587 if (!conn)
01588 return 0;
01589 if (conn->asyncStatus != PGASYNC_BUSY)
01590 return 0;
01591 if (conn->queryclass != PGQUERY_SIMPLE &&
01592 conn->queryclass != PGQUERY_EXTENDED)
01593 return 0;
01594 if (conn->result)
01595 return 0;
01596
01597
01598 conn->singleRowMode = true;
01599 return 1;
01600 }
01601
01602
01603
01604
01605
01606
01607 int
01608 PQconsumeInput(PGconn *conn)
01609 {
01610 if (!conn)
01611 return 0;
01612
01613
01614
01615
01616
01617
01618 if (pqIsnonblocking(conn))
01619 {
01620 if (pqFlush(conn) < 0)
01621 return 0;
01622 }
01623
01624
01625
01626
01627
01628
01629
01630 if (pqReadData(conn) < 0)
01631 return 0;
01632
01633
01634 return 1;
01635 }
01636
01637
01638
01639
01640
01641
01642
01643 static void
01644 parseInput(PGconn *conn)
01645 {
01646 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
01647 pqParseInput3(conn);
01648 else
01649 pqParseInput2(conn);
01650 }
01651
01652
01653
01654
01655
01656
01657 int
01658 PQisBusy(PGconn *conn)
01659 {
01660 if (!conn)
01661 return FALSE;
01662
01663
01664 parseInput(conn);
01665
01666
01667 return conn->asyncStatus == PGASYNC_BUSY;
01668 }
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678 PGresult *
01679 PQgetResult(PGconn *conn)
01680 {
01681 PGresult *res;
01682
01683 if (!conn)
01684 return NULL;
01685
01686
01687 parseInput(conn);
01688
01689
01690 while (conn->asyncStatus == PGASYNC_BUSY)
01691 {
01692 int flushResult;
01693
01694
01695
01696
01697
01698 while ((flushResult = pqFlush(conn)) > 0)
01699 {
01700 if (pqWait(FALSE, TRUE, conn))
01701 {
01702 flushResult = -1;
01703 break;
01704 }
01705 }
01706
01707
01708 if (flushResult ||
01709 pqWait(TRUE, FALSE, conn) ||
01710 pqReadData(conn) < 0)
01711 {
01712
01713
01714
01715
01716 pqSaveErrorResult(conn);
01717 conn->asyncStatus = PGASYNC_IDLE;
01718 return pqPrepareAsyncResult(conn);
01719 }
01720
01721
01722 parseInput(conn);
01723 }
01724
01725
01726 switch (conn->asyncStatus)
01727 {
01728 case PGASYNC_IDLE:
01729 res = NULL;
01730 break;
01731 case PGASYNC_READY:
01732 res = pqPrepareAsyncResult(conn);
01733
01734 conn->asyncStatus = PGASYNC_BUSY;
01735 break;
01736 case PGASYNC_COPY_IN:
01737 if (conn->result && conn->result->resultStatus == PGRES_COPY_IN)
01738 res = pqPrepareAsyncResult(conn);
01739 else
01740 res = PQmakeEmptyPGresult(conn, PGRES_COPY_IN);
01741 break;
01742 case PGASYNC_COPY_OUT:
01743 if (conn->result && conn->result->resultStatus == PGRES_COPY_OUT)
01744 res = pqPrepareAsyncResult(conn);
01745 else
01746 res = PQmakeEmptyPGresult(conn, PGRES_COPY_OUT);
01747 break;
01748 case PGASYNC_COPY_BOTH:
01749 if (conn->result && conn->result->resultStatus == PGRES_COPY_BOTH)
01750 res = pqPrepareAsyncResult(conn);
01751 else
01752 res = PQmakeEmptyPGresult(conn, PGRES_COPY_BOTH);
01753 break;
01754 default:
01755 printfPQExpBuffer(&conn->errorMessage,
01756 libpq_gettext("unexpected asyncStatus: %d\n"),
01757 (int) conn->asyncStatus);
01758 res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
01759 break;
01760 }
01761
01762 if (res)
01763 {
01764 int i;
01765
01766 for (i = 0; i < res->nEvents; i++)
01767 {
01768 PGEventResultCreate evt;
01769
01770 evt.conn = conn;
01771 evt.result = res;
01772 if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
01773 res->events[i].passThrough))
01774 {
01775 printfPQExpBuffer(&conn->errorMessage,
01776 libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
01777 res->events[i].name);
01778 pqSetResultError(res, conn->errorMessage.data);
01779 res->resultStatus = PGRES_FATAL_ERROR;
01780 break;
01781 }
01782 res->events[i].resultInitialized = TRUE;
01783 }
01784 }
01785
01786 return res;
01787 }
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801 PGresult *
01802 PQexec(PGconn *conn, const char *query)
01803 {
01804 if (!PQexecStart(conn))
01805 return NULL;
01806 if (!PQsendQuery(conn, query))
01807 return NULL;
01808 return PQexecFinish(conn);
01809 }
01810
01811
01812
01813
01814
01815 PGresult *
01816 PQexecParams(PGconn *conn,
01817 const char *command,
01818 int nParams,
01819 const Oid *paramTypes,
01820 const char *const * paramValues,
01821 const int *paramLengths,
01822 const int *paramFormats,
01823 int resultFormat)
01824 {
01825 if (!PQexecStart(conn))
01826 return NULL;
01827 if (!PQsendQueryParams(conn, command,
01828 nParams, paramTypes, paramValues, paramLengths,
01829 paramFormats, resultFormat))
01830 return NULL;
01831 return PQexecFinish(conn);
01832 }
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 PGresult *
01846 PQprepare(PGconn *conn,
01847 const char *stmtName, const char *query,
01848 int nParams, const Oid *paramTypes)
01849 {
01850 if (!PQexecStart(conn))
01851 return NULL;
01852 if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
01853 return NULL;
01854 return PQexecFinish(conn);
01855 }
01856
01857
01858
01859
01860
01861
01862 PGresult *
01863 PQexecPrepared(PGconn *conn,
01864 const char *stmtName,
01865 int nParams,
01866 const char *const * paramValues,
01867 const int *paramLengths,
01868 const int *paramFormats,
01869 int resultFormat)
01870 {
01871 if (!PQexecStart(conn))
01872 return NULL;
01873 if (!PQsendQueryPrepared(conn, stmtName,
01874 nParams, paramValues, paramLengths,
01875 paramFormats, resultFormat))
01876 return NULL;
01877 return PQexecFinish(conn);
01878 }
01879
01880
01881
01882
01883 static bool
01884 PQexecStart(PGconn *conn)
01885 {
01886 PGresult *result;
01887
01888 if (!conn)
01889 return false;
01890
01891
01892
01893
01894
01895 while ((result = PQgetResult(conn)) != NULL)
01896 {
01897 ExecStatusType resultStatus = result->resultStatus;
01898
01899 PQclear(result);
01900 if (resultStatus == PGRES_COPY_IN)
01901 {
01902 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
01903 {
01904
01905 if (PQputCopyEnd(conn,
01906 libpq_gettext("COPY terminated by new PQexec")) < 0)
01907 return false;
01908
01909 }
01910 else
01911 {
01912
01913 printfPQExpBuffer(&conn->errorMessage,
01914 libpq_gettext("COPY IN state must be terminated first\n"));
01915 return false;
01916 }
01917 }
01918 else if (resultStatus == PGRES_COPY_OUT)
01919 {
01920 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
01921 {
01922
01923
01924
01925
01926
01927 conn->asyncStatus = PGASYNC_BUSY;
01928
01929 }
01930 else
01931 {
01932
01933 printfPQExpBuffer(&conn->errorMessage,
01934 libpq_gettext("COPY OUT state must be terminated first\n"));
01935 return false;
01936 }
01937 }
01938 else if (resultStatus == PGRES_COPY_BOTH)
01939 {
01940
01941 printfPQExpBuffer(&conn->errorMessage,
01942 libpq_gettext("PQexec not allowed during COPY BOTH\n"));
01943 return false;
01944 }
01945
01946 if (conn->status == CONNECTION_BAD)
01947 return false;
01948 }
01949
01950
01951 return true;
01952 }
01953
01954
01955
01956
01957 static PGresult *
01958 PQexecFinish(PGconn *conn)
01959 {
01960 PGresult *result;
01961 PGresult *lastResult;
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 lastResult = NULL;
01974 while ((result = PQgetResult(conn)) != NULL)
01975 {
01976 if (lastResult)
01977 {
01978 if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
01979 result->resultStatus == PGRES_FATAL_ERROR)
01980 {
01981 pqCatenateResultError(lastResult, result->errMsg);
01982 PQclear(result);
01983 result = lastResult;
01984
01985
01986
01987
01988 resetPQExpBuffer(&conn->errorMessage);
01989 appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
01990 }
01991 else
01992 PQclear(lastResult);
01993 }
01994 lastResult = result;
01995 if (result->resultStatus == PGRES_COPY_IN ||
01996 result->resultStatus == PGRES_COPY_OUT ||
01997 result->resultStatus == PGRES_COPY_BOTH ||
01998 conn->status == CONNECTION_BAD)
01999 break;
02000 }
02001
02002 return lastResult;
02003 }
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018 PGresult *
02019 PQdescribePrepared(PGconn *conn, const char *stmt)
02020 {
02021 if (!PQexecStart(conn))
02022 return NULL;
02023 if (!PQsendDescribe(conn, 'S', stmt))
02024 return NULL;
02025 return PQexecFinish(conn);
02026 }
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 PGresult *
02038 PQdescribePortal(PGconn *conn, const char *portal)
02039 {
02040 if (!PQexecStart(conn))
02041 return NULL;
02042 if (!PQsendDescribe(conn, 'P', portal))
02043 return NULL;
02044 return PQexecFinish(conn);
02045 }
02046
02047
02048
02049
02050
02051
02052
02053
02054 int
02055 PQsendDescribePrepared(PGconn *conn, const char *stmt)
02056 {
02057 return PQsendDescribe(conn, 'S', stmt);
02058 }
02059
02060
02061
02062
02063
02064
02065
02066
02067 int
02068 PQsendDescribePortal(PGconn *conn, const char *portal)
02069 {
02070 return PQsendDescribe(conn, 'P', portal);
02071 }
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082 static int
02083 PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
02084 {
02085
02086 if (!desc_target)
02087 desc_target = "";
02088
02089 if (!PQsendQueryStart(conn))
02090 return 0;
02091
02092
02093 if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
02094 {
02095 printfPQExpBuffer(&conn->errorMessage,
02096 libpq_gettext("function requires at least protocol version 3.0\n"));
02097 return 0;
02098 }
02099
02100
02101 if (pqPutMsgStart('D', false, conn) < 0 ||
02102 pqPutc(desc_type, conn) < 0 ||
02103 pqPuts(desc_target, conn) < 0 ||
02104 pqPutMsgEnd(conn) < 0)
02105 goto sendFailed;
02106
02107
02108 if (pqPutMsgStart('S', false, conn) < 0 ||
02109 pqPutMsgEnd(conn) < 0)
02110 goto sendFailed;
02111
02112
02113 conn->queryclass = PGQUERY_DESCRIBE;
02114
02115
02116 if (conn->last_query)
02117 {
02118 free(conn->last_query);
02119 conn->last_query = NULL;
02120 }
02121
02122
02123
02124
02125
02126 if (pqFlush(conn) < 0)
02127 goto sendFailed;
02128
02129
02130 conn->asyncStatus = PGASYNC_BUSY;
02131 return 1;
02132
02133 sendFailed:
02134 pqHandleSendFailure(conn);
02135 return 0;
02136 }
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148 PGnotify *
02149 PQnotifies(PGconn *conn)
02150 {
02151 PGnotify *event;
02152
02153 if (!conn)
02154 return NULL;
02155
02156
02157 parseInput(conn);
02158
02159 event = conn->notifyHead;
02160 if (event)
02161 {
02162 conn->notifyHead = event->next;
02163 if (!conn->notifyHead)
02164 conn->notifyTail = NULL;
02165 event->next = NULL;
02166 }
02167 return event;
02168 }
02169
02170
02171
02172
02173
02174
02175
02176 int
02177 PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
02178 {
02179 if (!conn)
02180 return -1;
02181 if (conn->asyncStatus != PGASYNC_COPY_IN &&
02182 conn->asyncStatus != PGASYNC_COPY_BOTH)
02183 {
02184 printfPQExpBuffer(&conn->errorMessage,
02185 libpq_gettext("no COPY in progress\n"));
02186 return -1;
02187 }
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197 parseInput(conn);
02198
02199 if (nbytes > 0)
02200 {
02201
02202
02203
02204
02205
02206
02207
02208 if ((conn->outBufSize - conn->outCount - 5) < nbytes)
02209 {
02210 if (pqFlush(conn) < 0)
02211 return -1;
02212 if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
02213 conn))
02214 return pqIsnonblocking(conn) ? 0 : -1;
02215 }
02216
02217 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02218 {
02219 if (pqPutMsgStart('d', false, conn) < 0 ||
02220 pqPutnchar(buffer, nbytes, conn) < 0 ||
02221 pqPutMsgEnd(conn) < 0)
02222 return -1;
02223 }
02224 else
02225 {
02226 if (pqPutMsgStart(0, false, conn) < 0 ||
02227 pqPutnchar(buffer, nbytes, conn) < 0 ||
02228 pqPutMsgEnd(conn) < 0)
02229 return -1;
02230 }
02231 }
02232 return 1;
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243 int
02244 PQputCopyEnd(PGconn *conn, const char *errormsg)
02245 {
02246 if (!conn)
02247 return -1;
02248 if (conn->asyncStatus != PGASYNC_COPY_IN &&
02249 conn->asyncStatus != PGASYNC_COPY_BOTH)
02250 {
02251 printfPQExpBuffer(&conn->errorMessage,
02252 libpq_gettext("no COPY in progress\n"));
02253 return -1;
02254 }
02255
02256
02257
02258
02259
02260 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02261 {
02262 if (errormsg)
02263 {
02264
02265 if (pqPutMsgStart('f', false, conn) < 0 ||
02266 pqPuts(errormsg, conn) < 0 ||
02267 pqPutMsgEnd(conn) < 0)
02268 return -1;
02269 }
02270 else
02271 {
02272
02273 if (pqPutMsgStart('c', false, conn) < 0 ||
02274 pqPutMsgEnd(conn) < 0)
02275 return -1;
02276 }
02277
02278
02279
02280
02281
02282 if (conn->queryclass != PGQUERY_SIMPLE)
02283 {
02284 if (pqPutMsgStart('S', false, conn) < 0 ||
02285 pqPutMsgEnd(conn) < 0)
02286 return -1;
02287 }
02288 }
02289 else
02290 {
02291 if (errormsg)
02292 {
02293
02294 printfPQExpBuffer(&conn->errorMessage,
02295 libpq_gettext("function requires at least protocol version 3.0\n"));
02296 return -1;
02297 }
02298 else
02299 {
02300
02301 if (pqPutMsgStart(0, false, conn) < 0 ||
02302 pqPutnchar("\\.\n", 3, conn) < 0 ||
02303 pqPutMsgEnd(conn) < 0)
02304 return -1;
02305 }
02306 }
02307
02308
02309 if (conn->asyncStatus == PGASYNC_COPY_BOTH)
02310 conn->asyncStatus = PGASYNC_COPY_OUT;
02311 else
02312 conn->asyncStatus = PGASYNC_BUSY;
02313 resetPQExpBuffer(&conn->errorMessage);
02314
02315
02316 if (pqFlush(conn) < 0)
02317 return -1;
02318
02319 return 1;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332 int
02333 PQgetCopyData(PGconn *conn, char **buffer, int async)
02334 {
02335 *buffer = NULL;
02336 if (!conn)
02337 return -2;
02338 if (conn->asyncStatus != PGASYNC_COPY_OUT &&
02339 conn->asyncStatus != PGASYNC_COPY_BOTH)
02340 {
02341 printfPQExpBuffer(&conn->errorMessage,
02342 libpq_gettext("no COPY in progress\n"));
02343 return -2;
02344 }
02345 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02346 return pqGetCopyData3(conn, buffer, async);
02347 else
02348 return pqGetCopyData2(conn, buffer, async);
02349 }
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 int
02375 PQgetline(PGconn *conn, char *s, int maxlen)
02376 {
02377 if (!s || maxlen <= 0)
02378 return EOF;
02379 *s = '\0';
02380
02381 if (maxlen < 3)
02382 return EOF;
02383
02384 if (!conn)
02385 return EOF;
02386
02387 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02388 return pqGetline3(conn, s, maxlen);
02389 else
02390 return pqGetline2(conn, s, maxlen);
02391 }
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424 int
02425 PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
02426 {
02427 if (!conn)
02428 return -1;
02429
02430 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02431 return pqGetlineAsync3(conn, buffer, bufsize);
02432 else
02433 return pqGetlineAsync2(conn, buffer, bufsize);
02434 }
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444 int
02445 PQputline(PGconn *conn, const char *s)
02446 {
02447 return PQputnbytes(conn, s, strlen(s));
02448 }
02449
02450
02451
02452
02453
02454 int
02455 PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
02456 {
02457 if (PQputCopyData(conn, buffer, nbytes) > 0)
02458 return 0;
02459 else
02460 return EOF;
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477 int
02478 PQendcopy(PGconn *conn)
02479 {
02480 if (!conn)
02481 return 0;
02482
02483 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02484 return pqEndcopy3(conn);
02485 else
02486 return pqEndcopy2(conn);
02487 }
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513 PGresult *
02514 PQfn(PGconn *conn,
02515 int fnid,
02516 int *result_buf,
02517 int *actual_result_len,
02518 int result_is_int,
02519 const PQArgBlock *args,
02520 int nargs)
02521 {
02522 *actual_result_len = 0;
02523
02524 if (!conn)
02525 return NULL;
02526
02527
02528 resetPQExpBuffer(&conn->errorMessage);
02529
02530 if (conn->sock < 0 || conn->asyncStatus != PGASYNC_IDLE ||
02531 conn->result != NULL)
02532 {
02533 printfPQExpBuffer(&conn->errorMessage,
02534 libpq_gettext("connection in wrong state\n"));
02535 return NULL;
02536 }
02537
02538 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02539 return pqFunctionCall3(conn, fnid,
02540 result_buf, actual_result_len,
02541 result_is_int,
02542 args, nargs);
02543 else
02544 return pqFunctionCall2(conn, fnid,
02545 result_buf, actual_result_len,
02546 result_is_int,
02547 args, nargs);
02548 }
02549
02550
02551
02552
02553 ExecStatusType
02554 PQresultStatus(const PGresult *res)
02555 {
02556 if (!res)
02557 return PGRES_FATAL_ERROR;
02558 return res->resultStatus;
02559 }
02560
02561 char *
02562 PQresStatus(ExecStatusType status)
02563 {
02564 if ((unsigned int) status >= sizeof pgresStatus / sizeof pgresStatus[0])
02565 return libpq_gettext("invalid ExecStatusType code");
02566 return pgresStatus[status];
02567 }
02568
02569 char *
02570 PQresultErrorMessage(const PGresult *res)
02571 {
02572 if (!res || !res->errMsg)
02573 return "";
02574 return res->errMsg;
02575 }
02576
02577 char *
02578 PQresultErrorField(const PGresult *res, int fieldcode)
02579 {
02580 PGMessageField *pfield;
02581
02582 if (!res)
02583 return NULL;
02584 for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
02585 {
02586 if (pfield->code == fieldcode)
02587 return pfield->contents;
02588 }
02589 return NULL;
02590 }
02591
02592 int
02593 PQntuples(const PGresult *res)
02594 {
02595 if (!res)
02596 return 0;
02597 return res->ntups;
02598 }
02599
02600 int
02601 PQnfields(const PGresult *res)
02602 {
02603 if (!res)
02604 return 0;
02605 return res->numAttributes;
02606 }
02607
02608 int
02609 PQbinaryTuples(const PGresult *res)
02610 {
02611 if (!res)
02612 return 0;
02613 return res->binary;
02614 }
02615
02616
02617
02618
02619
02620
02621 static int
02622 check_field_number(const PGresult *res, int field_num)
02623 {
02624 if (!res)
02625 return FALSE;
02626 if (field_num < 0 || field_num >= res->numAttributes)
02627 {
02628 pqInternalNotice(&res->noticeHooks,
02629 "column number %d is out of range 0..%d",
02630 field_num, res->numAttributes - 1);
02631 return FALSE;
02632 }
02633 return TRUE;
02634 }
02635
02636 static int
02637 check_tuple_field_number(const PGresult *res,
02638 int tup_num, int field_num)
02639 {
02640 if (!res)
02641 return FALSE;
02642 if (tup_num < 0 || tup_num >= res->ntups)
02643 {
02644 pqInternalNotice(&res->noticeHooks,
02645 "row number %d is out of range 0..%d",
02646 tup_num, res->ntups - 1);
02647 return FALSE;
02648 }
02649 if (field_num < 0 || field_num >= res->numAttributes)
02650 {
02651 pqInternalNotice(&res->noticeHooks,
02652 "column number %d is out of range 0..%d",
02653 field_num, res->numAttributes - 1);
02654 return FALSE;
02655 }
02656 return TRUE;
02657 }
02658
02659 static int
02660 check_param_number(const PGresult *res, int param_num)
02661 {
02662 if (!res)
02663 return FALSE;
02664 if (param_num < 0 || param_num >= res->numParameters)
02665 {
02666 pqInternalNotice(&res->noticeHooks,
02667 "parameter number %d is out of range 0..%d",
02668 param_num, res->numParameters - 1);
02669 return FALSE;
02670 }
02671
02672 return TRUE;
02673 }
02674
02675
02676
02677
02678 char *
02679 PQfname(const PGresult *res, int field_num)
02680 {
02681 if (!check_field_number(res, field_num))
02682 return NULL;
02683 if (res->attDescs)
02684 return res->attDescs[field_num].name;
02685 else
02686 return NULL;
02687 }
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700 int
02701 PQfnumber(const PGresult *res, const char *field_name)
02702 {
02703 char *field_case;
02704 bool in_quotes;
02705 char *iptr;
02706 char *optr;
02707 int i;
02708
02709 if (!res)
02710 return -1;
02711
02712
02713
02714
02715
02716 if (field_name == NULL ||
02717 field_name[0] == '\0' ||
02718 res->attDescs == NULL)
02719 return -1;
02720
02721
02722
02723
02724
02725
02726 field_case = strdup(field_name);
02727 if (field_case == NULL)
02728 return -1;
02729
02730 in_quotes = false;
02731 optr = field_case;
02732 for (iptr = field_case; *iptr; iptr++)
02733 {
02734 char c = *iptr;
02735
02736 if (in_quotes)
02737 {
02738 if (c == '"')
02739 {
02740 if (iptr[1] == '"')
02741 {
02742
02743 *optr++ = '"';
02744 iptr++;
02745 }
02746 else
02747 in_quotes = false;
02748 }
02749 else
02750 *optr++ = c;
02751 }
02752 else if (c == '"')
02753 in_quotes = true;
02754 else
02755 {
02756 c = pg_tolower((unsigned char) c);
02757 *optr++ = c;
02758 }
02759 }
02760 *optr = '\0';
02761
02762 for (i = 0; i < res->numAttributes; i++)
02763 {
02764 if (strcmp(field_case, res->attDescs[i].name) == 0)
02765 {
02766 free(field_case);
02767 return i;
02768 }
02769 }
02770 free(field_case);
02771 return -1;
02772 }
02773
02774 Oid
02775 PQftable(const PGresult *res, int field_num)
02776 {
02777 if (!check_field_number(res, field_num))
02778 return InvalidOid;
02779 if (res->attDescs)
02780 return res->attDescs[field_num].tableid;
02781 else
02782 return InvalidOid;
02783 }
02784
02785 int
02786 PQftablecol(const PGresult *res, int field_num)
02787 {
02788 if (!check_field_number(res, field_num))
02789 return 0;
02790 if (res->attDescs)
02791 return res->attDescs[field_num].columnid;
02792 else
02793 return 0;
02794 }
02795
02796 int
02797 PQfformat(const PGresult *res, int field_num)
02798 {
02799 if (!check_field_number(res, field_num))
02800 return 0;
02801 if (res->attDescs)
02802 return res->attDescs[field_num].format;
02803 else
02804 return 0;
02805 }
02806
02807 Oid
02808 PQftype(const PGresult *res, int field_num)
02809 {
02810 if (!check_field_number(res, field_num))
02811 return InvalidOid;
02812 if (res->attDescs)
02813 return res->attDescs[field_num].typid;
02814 else
02815 return InvalidOid;
02816 }
02817
02818 int
02819 PQfsize(const PGresult *res, int field_num)
02820 {
02821 if (!check_field_number(res, field_num))
02822 return 0;
02823 if (res->attDescs)
02824 return res->attDescs[field_num].typlen;
02825 else
02826 return 0;
02827 }
02828
02829 int
02830 PQfmod(const PGresult *res, int field_num)
02831 {
02832 if (!check_field_number(res, field_num))
02833 return 0;
02834 if (res->attDescs)
02835 return res->attDescs[field_num].atttypmod;
02836 else
02837 return 0;
02838 }
02839
02840 char *
02841 PQcmdStatus(PGresult *res)
02842 {
02843 if (!res)
02844 return NULL;
02845 return res->cmdStatus;
02846 }
02847
02848
02849
02850
02851
02852
02853 char *
02854 PQoidStatus(const PGresult *res)
02855 {
02856
02857
02858
02859
02860 static char buf[24];
02861
02862 size_t len;
02863
02864 if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
02865 return "";
02866
02867 len = strspn(res->cmdStatus + 7, "0123456789");
02868 if (len > 23)
02869 len = 23;
02870 strncpy(buf, res->cmdStatus + 7, len);
02871 buf[len] = '\0';
02872
02873 return buf;
02874 }
02875
02876
02877
02878
02879
02880
02881 Oid
02882 PQoidValue(const PGresult *res)
02883 {
02884 char *endptr = NULL;
02885 unsigned long result;
02886
02887 if (!res ||
02888 !res->cmdStatus ||
02889 strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
02890 res->cmdStatus[7] < '0' ||
02891 res->cmdStatus[7] > '9')
02892 return InvalidOid;
02893
02894 result = strtoul(res->cmdStatus + 7, &endptr, 10);
02895
02896 if (!endptr || (*endptr != ' ' && *endptr != '\0'))
02897 return InvalidOid;
02898 else
02899 return (Oid) result;
02900 }
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911 char *
02912 PQcmdTuples(PGresult *res)
02913 {
02914 char *p,
02915 *c;
02916
02917 if (!res)
02918 return "";
02919
02920 if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
02921 {
02922 p = res->cmdStatus + 7;
02923
02924 while (*p && *p != ' ')
02925 p++;
02926 if (*p == 0)
02927 goto interpret_error;
02928 p++;
02929 }
02930 else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
02931 strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
02932 strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
02933 p = res->cmdStatus + 7;
02934 else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
02935 p = res->cmdStatus + 6;
02936 else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
02937 strncmp(res->cmdStatus, "COPY ", 5) == 0)
02938 p = res->cmdStatus + 5;
02939 else
02940 return "";
02941
02942
02943 for (c = p; *c; c++)
02944 {
02945 if (!isdigit((unsigned char) *c))
02946 goto interpret_error;
02947 }
02948 if (c == p)
02949 goto interpret_error;
02950
02951 return p;
02952
02953 interpret_error:
02954 pqInternalNotice(&res->noticeHooks,
02955 "could not interpret result from server: %s",
02956 res->cmdStatus);
02957 return "";
02958 }
02959
02960
02961
02962
02963
02964 char *
02965 PQgetvalue(const PGresult *res, int tup_num, int field_num)
02966 {
02967 if (!check_tuple_field_number(res, tup_num, field_num))
02968 return NULL;
02969 return res->tuples[tup_num][field_num].value;
02970 }
02971
02972
02973
02974
02975 int
02976 PQgetlength(const PGresult *res, int tup_num, int field_num)
02977 {
02978 if (!check_tuple_field_number(res, tup_num, field_num))
02979 return 0;
02980 if (res->tuples[tup_num][field_num].len != NULL_LEN)
02981 return res->tuples[tup_num][field_num].len;
02982 else
02983 return 0;
02984 }
02985
02986
02987
02988
02989 int
02990 PQgetisnull(const PGresult *res, int tup_num, int field_num)
02991 {
02992 if (!check_tuple_field_number(res, tup_num, field_num))
02993 return 1;
02994 if (res->tuples[tup_num][field_num].len == NULL_LEN)
02995 return 1;
02996 else
02997 return 0;
02998 }
02999
03000
03001
03002
03003 int
03004 PQnparams(const PGresult *res)
03005 {
03006 if (!res)
03007 return 0;
03008 return res->numParameters;
03009 }
03010
03011
03012
03013
03014 Oid
03015 PQparamtype(const PGresult *res, int param_num)
03016 {
03017 if (!check_param_number(res, param_num))
03018 return InvalidOid;
03019 if (res->paramDescs)
03020 return res->paramDescs[param_num].typid;
03021 else
03022 return InvalidOid;
03023 }
03024
03025
03026
03027
03028
03029
03030
03031
03032 int
03033 PQsetnonblocking(PGconn *conn, int arg)
03034 {
03035 bool barg;
03036
03037 if (!conn || conn->status == CONNECTION_BAD)
03038 return -1;
03039
03040 barg = (arg ? TRUE : FALSE);
03041
03042
03043 if (barg == conn->nonblocking)
03044 return 0;
03045
03046
03047
03048
03049
03050
03051
03052
03053 if (pqFlush(conn))
03054 return -1;
03055
03056 conn->nonblocking = barg;
03057
03058 return 0;
03059 }
03060
03061
03062
03063
03064
03065 int
03066 PQisnonblocking(const PGconn *conn)
03067 {
03068 return pqIsnonblocking(conn);
03069 }
03070
03071
03072 int
03073 PQisthreadsafe(void)
03074 {
03075 #ifdef ENABLE_THREAD_SAFETY
03076 return true;
03077 #else
03078 return false;
03079 #endif
03080 }
03081
03082
03083
03084 int
03085 PQflush(PGconn *conn)
03086 {
03087 return pqFlush(conn);
03088 }
03089
03090
03091
03092
03093
03094
03095
03096
03097 void
03098 PQfreemem(void *ptr)
03099 {
03100 free(ptr);
03101 }
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111 #undef PQfreeNotify
03112 void PQfreeNotify(PGnotify *notify);
03113
03114 void
03115 PQfreeNotify(PGnotify *notify)
03116 {
03117 PQfreemem(notify);
03118 }
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136 static size_t
03137 PQescapeStringInternal(PGconn *conn,
03138 char *to, const char *from, size_t length,
03139 int *error,
03140 int encoding, bool std_strings)
03141 {
03142 const char *source = from;
03143 char *target = to;
03144 size_t remaining = length;
03145
03146 if (error)
03147 *error = 0;
03148
03149 while (remaining > 0 && *source != '\0')
03150 {
03151 char c = *source;
03152 int len;
03153 int i;
03154
03155
03156 if (!IS_HIGHBIT_SET(c))
03157 {
03158
03159 if (SQL_STR_DOUBLE(c, !std_strings))
03160 *target++ = c;
03161
03162 *target++ = c;
03163 source++;
03164 remaining--;
03165 continue;
03166 }
03167
03168
03169 len = pg_encoding_mblen(encoding, source);
03170
03171
03172 for (i = 0; i < len; i++)
03173 {
03174 if (remaining == 0 || *source == '\0')
03175 break;
03176 *target++ = *source++;
03177 remaining--;
03178 }
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188 if (i < len)
03189 {
03190 if (error)
03191 *error = 1;
03192 if (conn)
03193 printfPQExpBuffer(&conn->errorMessage,
03194 libpq_gettext("incomplete multibyte character\n"));
03195 for (; i < len; i++)
03196 {
03197 if (((size_t) (target - to)) / 2 >= length)
03198 break;
03199 *target++ = ' ';
03200 }
03201 break;
03202 }
03203 }
03204
03205
03206 *target = '\0';
03207
03208 return target - to;
03209 }
03210
03211 size_t
03212 PQescapeStringConn(PGconn *conn,
03213 char *to, const char *from, size_t length,
03214 int *error)
03215 {
03216 if (!conn)
03217 {
03218
03219 *to = '\0';
03220 if (error)
03221 *error = 1;
03222 return 0;
03223 }
03224 return PQescapeStringInternal(conn, to, from, length, error,
03225 conn->client_encoding,
03226 conn->std_strings);
03227 }
03228
03229 size_t
03230 PQescapeString(char *to, const char *from, size_t length)
03231 {
03232 return PQescapeStringInternal(NULL, to, from, length, NULL,
03233 static_client_encoding,
03234 static_std_strings);
03235 }
03236
03237
03238
03239
03240
03241
03242
03243
03244 static char *
03245 PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
03246 {
03247 const char *s;
03248 char *result;
03249 char *rp;
03250 int num_quotes = 0;
03251 int num_backslashes = 0;
03252 int input_len;
03253 int result_size;
03254 char quote_char = as_ident ? '"' : '\'';
03255
03256
03257 if (!conn)
03258 return NULL;
03259
03260
03261 for (s = str; (s - str) < len && *s != '\0'; ++s)
03262 {
03263 if (*s == quote_char)
03264 ++num_quotes;
03265 else if (*s == '\\')
03266 ++num_backslashes;
03267 else if (IS_HIGHBIT_SET(*s))
03268 {
03269 int charlen;
03270
03271
03272 charlen = pg_encoding_mblen(conn->client_encoding, s);
03273
03274
03275 if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
03276 {
03277 printfPQExpBuffer(&conn->errorMessage,
03278 libpq_gettext("incomplete multibyte character\n"));
03279 return NULL;
03280 }
03281
03282
03283 s += charlen - 1;
03284 }
03285 }
03286
03287
03288 input_len = s - str;
03289 result_size = input_len + num_quotes + 3;
03290 if (!as_ident && num_backslashes > 0)
03291 result_size += num_backslashes + 2;
03292 result = rp = (char *) malloc(result_size);
03293 if (rp == NULL)
03294 {
03295 printfPQExpBuffer(&conn->errorMessage,
03296 libpq_gettext("out of memory\n"));
03297 return NULL;
03298 }
03299
03300
03301
03302
03303
03304
03305
03306
03307 if (!as_ident && num_backslashes > 0)
03308 {
03309 *rp++ = ' ';
03310 *rp++ = 'E';
03311 }
03312
03313
03314 *rp++ = quote_char;
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327 if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
03328 {
03329 memcpy(rp, str, input_len);
03330 rp += input_len;
03331 }
03332 else
03333 {
03334 for (s = str; s - str < input_len; ++s)
03335 {
03336 if (*s == quote_char || (!as_ident && *s == '\\'))
03337 {
03338 *rp++ = *s;
03339 *rp++ = *s;
03340 }
03341 else if (!IS_HIGHBIT_SET(*s))
03342 *rp++ = *s;
03343 else
03344 {
03345 int i = pg_encoding_mblen(conn->client_encoding, s);
03346
03347 while (1)
03348 {
03349 *rp++ = *s;
03350 if (--i == 0)
03351 break;
03352 ++s;
03353 }
03354 }
03355 }
03356 }
03357
03358
03359 *rp++ = quote_char;
03360 *rp = '\0';
03361
03362 return result;
03363 }
03364
03365 char *
03366 PQescapeLiteral(PGconn *conn, const char *str, size_t len)
03367 {
03368 return PQescapeInternal(conn, str, len, false);
03369 }
03370
03371 char *
03372 PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
03373 {
03374 return PQescapeInternal(conn, str, len, true);
03375 }
03376
03377
03378 static const char hextbl[] = "0123456789abcdef";
03379
03380 static const int8 hexlookup[128] = {
03381 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03382 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03383 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03384 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
03385 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03386 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03387 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03388 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
03389 };
03390
03391 static inline char
03392 get_hex(char c)
03393 {
03394 int res = -1;
03395
03396 if (c > 0 && c < 127)
03397 res = hexlookup[(unsigned char) c];
03398
03399 return (char) res;
03400 }
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418 static unsigned char *
03419 PQescapeByteaInternal(PGconn *conn,
03420 const unsigned char *from, size_t from_length,
03421 size_t *to_length, bool std_strings, bool use_hex)
03422 {
03423 const unsigned char *vp;
03424 unsigned char *rp;
03425 unsigned char *result;
03426 size_t i;
03427 size_t len;
03428 size_t bslash_len = (std_strings ? 1 : 2);
03429
03430
03431
03432
03433 len = 1;
03434
03435 if (use_hex)
03436 {
03437 len += bslash_len + 1 + 2 * from_length;
03438 }
03439 else
03440 {
03441 vp = from;
03442 for (i = from_length; i > 0; i--, vp++)
03443 {
03444 if (*vp < 0x20 || *vp > 0x7e)
03445 len += bslash_len + 3;
03446 else if (*vp == '\'')
03447 len += 2;
03448 else if (*vp == '\\')
03449 len += bslash_len + bslash_len;
03450 else
03451 len++;
03452 }
03453 }
03454
03455 *to_length = len;
03456 rp = result = (unsigned char *) malloc(len);
03457 if (rp == NULL)
03458 {
03459 if (conn)
03460 printfPQExpBuffer(&conn->errorMessage,
03461 libpq_gettext("out of memory\n"));
03462 return NULL;
03463 }
03464
03465 if (use_hex)
03466 {
03467 if (!std_strings)
03468 *rp++ = '\\';
03469 *rp++ = '\\';
03470 *rp++ = 'x';
03471 }
03472
03473 vp = from;
03474 for (i = from_length; i > 0; i--, vp++)
03475 {
03476 unsigned char c = *vp;
03477
03478 if (use_hex)
03479 {
03480 *rp++ = hextbl[(c >> 4) & 0xF];
03481 *rp++ = hextbl[c & 0xF];
03482 }
03483 else if (c < 0x20 || c > 0x7e)
03484 {
03485 if (!std_strings)
03486 *rp++ = '\\';
03487 *rp++ = '\\';
03488 *rp++ = (c >> 6) + '0';
03489 *rp++ = ((c >> 3) & 07) + '0';
03490 *rp++ = (c & 07) + '0';
03491 }
03492 else if (c == '\'')
03493 {
03494 *rp++ = '\'';
03495 *rp++ = '\'';
03496 }
03497 else if (c == '\\')
03498 {
03499 if (!std_strings)
03500 {
03501 *rp++ = '\\';
03502 *rp++ = '\\';
03503 }
03504 *rp++ = '\\';
03505 *rp++ = '\\';
03506 }
03507 else
03508 *rp++ = c;
03509 }
03510 *rp = '\0';
03511
03512 return result;
03513 }
03514
03515 unsigned char *
03516 PQescapeByteaConn(PGconn *conn,
03517 const unsigned char *from, size_t from_length,
03518 size_t *to_length)
03519 {
03520 if (!conn)
03521 return NULL;
03522 return PQescapeByteaInternal(conn, from, from_length, to_length,
03523 conn->std_strings,
03524 (conn->sversion >= 90000));
03525 }
03526
03527 unsigned char *
03528 PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
03529 {
03530 return PQescapeByteaInternal(NULL, from, from_length, to_length,
03531 static_std_strings,
03532 false );
03533 }
03534
03535
03536 #define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
03537 #define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
03538 #define OCTVAL(CH) ((CH) - '0')
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552 unsigned char *
03553 PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
03554 {
03555 size_t strtextlen,
03556 buflen;
03557 unsigned char *buffer,
03558 *tmpbuf;
03559 size_t i,
03560 j;
03561
03562 if (strtext == NULL)
03563 return NULL;
03564
03565 strtextlen = strlen((const char *) strtext);
03566
03567 if (strtext[0] == '\\' && strtext[1] == 'x')
03568 {
03569 const unsigned char *s;
03570 unsigned char *p;
03571
03572 buflen = (strtextlen - 2) / 2;
03573
03574 buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1);
03575 if (buffer == NULL)
03576 return NULL;
03577
03578 s = strtext + 2;
03579 p = buffer;
03580 while (*s)
03581 {
03582 char v1,
03583 v2;
03584
03585
03586
03587
03588
03589 v1 = get_hex(*s++);
03590 if (!*s || v1 == (char) -1)
03591 continue;
03592 v2 = get_hex(*s++);
03593 if (v2 != (char) -1)
03594 *p++ = (v1 << 4) | v2;
03595 }
03596
03597 buflen = p - buffer;
03598 }
03599 else
03600 {
03601
03602
03603
03604
03605 buffer = (unsigned char *) malloc(strtextlen + 1);
03606 if (buffer == NULL)
03607 return NULL;
03608
03609 for (i = j = 0; i < strtextlen;)
03610 {
03611 switch (strtext[i])
03612 {
03613 case '\\':
03614 i++;
03615 if (strtext[i] == '\\')
03616 buffer[j++] = strtext[i++];
03617 else
03618 {
03619 if ((ISFIRSTOCTDIGIT(strtext[i])) &&
03620 (ISOCTDIGIT(strtext[i + 1])) &&
03621 (ISOCTDIGIT(strtext[i + 2])))
03622 {
03623 int byte;
03624
03625 byte = OCTVAL(strtext[i++]);
03626 byte = (byte << 3) + OCTVAL(strtext[i++]);
03627 byte = (byte << 3) + OCTVAL(strtext[i++]);
03628 buffer[j++] = byte;
03629 }
03630 }
03631
03632
03633
03634
03635
03636
03637
03638
03639 break;
03640
03641 default:
03642 buffer[j++] = strtext[i++];
03643 break;
03644 }
03645 }
03646 buflen = j;
03647 }
03648
03649
03650
03651 tmpbuf = realloc(buffer, buflen + 1);
03652
03653
03654 if (!tmpbuf)
03655 {
03656 free(buffer);
03657 return NULL;
03658 }
03659
03660 *retbuflen = buflen;
03661 return tmpbuf;
03662 }