fe-exec.c 55.4 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * fe-exec.c
4
 *	  functions related to sending a query down to the backend
5
 *
6
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.100 2001/02/06 02:02:27 tgl Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
15 16
#include <errno.h>
#include <ctype.h>
17
#include <fcntl.h>
18 19

#include "postgres.h"
20 21 22
#include "libpq-fe.h"
#include "libpq-int.h"

Bruce Momjian's avatar
Bruce Momjian committed
23 24
#ifdef WIN32
#include "win32.h"
25 26
#else
#include <unistd.h>
Bruce Momjian's avatar
Bruce Momjian committed
27
#endif
Bruce Momjian's avatar
Bruce Momjian committed
28

Bruce Momjian's avatar
Bruce Momjian committed
29
/* keep this in same order as ExecStatusType in libpq-fe.h */
30
char	   *const pgresStatus[] = {
31 32 33
	"PGRES_EMPTY_QUERY",
	"PGRES_COMMAND_OK",
	"PGRES_TUPLES_OK",
34
	"PGRES_COPY_OUT",
35
	"PGRES_COPY_IN",
36 37 38
	"PGRES_BAD_RESPONSE",
	"PGRES_NONFATAL_ERROR",
	"PGRES_FATAL_ERROR"
39 40 41
};


42
/* Note: DONOTICE macro will work if applied to either PGconn or PGresult */
43 44 45 46
#define DONOTICE(conn,message) \
	((*(conn)->noticeHook) ((conn)->noticeArg, (message)))


47 48 49
static void pqCatenateResultError(PGresult *res, const char *msg);
static void saveErrorResult(PGconn *conn);
static PGresult *prepareAsyncResult(PGconn *conn);
50
static int	addTuple(PGresult *res, PGresAttValue * tup);
Bruce Momjian's avatar
Bruce Momjian committed
51
static void parseInput(PGconn *conn);
52
static void handleSendFailure(PGconn *conn);
53 54 55 56
static int	getRowDescriptions(PGconn *conn);
static int	getAnotherTuple(PGconn *conn, int binary);
static int	getNotify(PGconn *conn);
static int	getNotice(PGconn *conn);
57

58

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
/* ----------------
 * Space management for PGresult.
 *
 * Formerly, libpq did a separate malloc() for each field of each tuple
 * returned by a query.  This was remarkably expensive --- malloc/free
 * consumed a sizable part of the application's runtime.  And there is
 * no real need to keep track of the fields separately, since they will
 * all be freed together when the PGresult is released.  So now, we grab
 * large blocks of storage from malloc and allocate space for query data
 * within these blocks, using a trivially simple allocator.  This reduces
 * the number of malloc/free calls dramatically, and it also avoids
 * fragmentation of the malloc storage arena.
 * The PGresult structure itself is still malloc'd separately.  We could
 * combine it with the first allocation block, but that would waste space
 * for the common case that no extra storage is actually needed (that is,
 * the SQL command did not return tuples).
 * We also malloc the top-level array of tuple pointers separately, because
 * we need to be able to enlarge it via realloc, and our trivial space
 * allocator doesn't handle that effectively.  (Too bad the FE/BE protocol
 * doesn't tell us up front how many tuples will be returned.)
 * All other subsidiary storage for a PGresult is kept in PGresult_data blocks
 * of size PGRESULT_DATA_BLOCKSIZE.  The overhead at the start of each block
Bruce Momjian's avatar
Bruce Momjian committed
81
 * is just a link to the next one, if any.	Free-space management info is
82 83 84 85 86 87 88 89 90 91 92 93 94 95
 * kept in the owning PGresult.
 * A query returning a small amount of data will thus require three malloc
 * calls: one for the PGresult, one for the tuples pointer array, and one
 * PGresult_data block.
 * Only the most recently allocated PGresult_data block is a candidate to
 * have more stuff added to it --- any extra space left over in older blocks
 * is wasted.  We could be smarter and search the whole chain, but the point
 * here is to be simple and fast.  Typical applications do not keep a PGresult
 * around very long anyway, so some wasted space within one is not a problem.
 *
 * Tuning constants for the space allocator are:
 * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes
 * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
 * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
Bruce Momjian's avatar
Bruce Momjian committed
96
 *	 blocks, instead of being crammed into a regular allocation block.
97 98
 * Requirements for correct function are:
 * PGRESULT_ALIGN_BOUNDARY must be a multiple of the alignment requirements
Bruce Momjian's avatar
Bruce Momjian committed
99
 *		of all machine data types.	(Currently this is set from configure
100 101
 *		tests, so it should be OK automatically.)
 * PGRESULT_SEP_ALLOC_THRESHOLD + PGRESULT_BLOCK_OVERHEAD <=
102 103 104 105 106 107 108 109
 *			PGRESULT_DATA_BLOCKSIZE
 *		pqResultAlloc assumes an object smaller than the threshold will fit
 *		in a new block.
 * The amount of space wasted at the end of a block could be as much as
 * PGRESULT_SEP_ALLOC_THRESHOLD, so it doesn't pay to make that too large.
 * ----------------
 */

110 111 112 113 114
#ifdef MAX
#undef MAX
#endif
#define MAX(a,b)  ((a) > (b) ? (a) : (b))

115
#define PGRESULT_DATA_BLOCKSIZE		2048
Bruce Momjian's avatar
Bruce Momjian committed
116
#define PGRESULT_ALIGN_BOUNDARY		MAXIMUM_ALIGNOF		/* from configure */
117
#define PGRESULT_BLOCK_OVERHEAD		MAX(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
118 119 120
#define PGRESULT_SEP_ALLOC_THRESHOLD	(PGRESULT_DATA_BLOCKSIZE / 2)


121
/*
122
 * PQmakeEmptyPGresult
123 124 125
 *	 returns a newly allocated, initialized PGresult with given status.
 *	 If conn is not NULL and status indicates an error, the conn's
 *	 errorMessage is copied.
126
 *
127 128 129
 * Note this is exported --- you wouldn't think an application would need
 * to build its own PGresults, but this has proven useful in both libpgtcl
 * and the Perl5 interface, so maybe it's not so unreasonable.
130 131
 */

Bruce Momjian's avatar
Bruce Momjian committed
132
PGresult   *
133
PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
134
{
135
	PGresult   *result;
136 137 138

	result = (PGresult *) malloc(sizeof(PGresult));

139
	result->xconn = conn;		/* might be NULL */
140 141 142 143 144 145 146 147
	result->ntups = 0;
	result->numAttributes = 0;
	result->attDescs = NULL;
	result->tuples = NULL;
	result->tupArrSize = 0;
	result->resultStatus = status;
	result->cmdStatus[0] = '\0';
	result->binary = 0;
148
	result->errMsg = NULL;
149 150 151 152 153
	result->null_field[0] = '\0';
	result->curBlock = NULL;
	result->curOffset = 0;
	result->spaceLeft = 0;

154
	if (conn)
155
	{
156
		/* copy connection data we might need for operations on PGresult */
157 158
		result->noticeHook = conn->noticeHook;
		result->noticeArg = conn->noticeArg;
159 160
		result->client_encoding = conn->client_encoding;

161
		/* consider copying conn's errorMessage */
162 163 164 165 166 167 168 169 170 171
		switch (status)
		{
			case PGRES_EMPTY_QUERY:
			case PGRES_COMMAND_OK:
			case PGRES_TUPLES_OK:
			case PGRES_COPY_OUT:
			case PGRES_COPY_IN:
				/* non-error cases */
				break;
			default:
172
				pqSetResultError(result, conn->errorMessage.data);
173 174 175
				break;
		}
	}
176 177
	else
	{
178
		/* defaults... */
179 180
		result->noticeHook = NULL;
		result->noticeArg = NULL;
181
		result->client_encoding = 0;	/* should be SQL_ASCII */
182 183
	}

184
	return result;
185 186
}

187 188 189 190 191 192 193 194 195 196 197
/*
 * pqResultAlloc -
 *		Allocate subsidiary storage for a PGresult.
 *
 * nBytes is the amount of space needed for the object.
 * If isBinary is true, we assume that we need to align the object on
 * a machine allocation boundary.
 * If isBinary is false, we assume the object is a char string and can
 * be allocated on any byte boundary.
 */
void *
Bruce Momjian's avatar
Bruce Momjian committed
198
pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
199
{
Bruce Momjian's avatar
Bruce Momjian committed
200 201
	char	   *space;
	PGresult_data *block;
202

Bruce Momjian's avatar
Bruce Momjian committed
203
	if (!res)
204 205 206 207 208
		return NULL;

	if (nBytes <= 0)
		return res->null_field;

Bruce Momjian's avatar
Bruce Momjian committed
209 210
	/*
	 * If alignment is needed, round up the current position to an
211 212 213 214
	 * alignment boundary.
	 */
	if (isBinary)
	{
Bruce Momjian's avatar
Bruce Momjian committed
215 216
		int			offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
		if (offset)
		{
			res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
			res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
		}
	}

	/* If there's enough space in the current block, no problem. */
	if (nBytes <= res->spaceLeft)
	{
		space = res->curBlock->space + res->curOffset;
		res->curOffset += nBytes;
		res->spaceLeft -= nBytes;
		return space;
	}

Bruce Momjian's avatar
Bruce Momjian committed
233 234 235 236 237 238
	/*
	 * If the requested object is very large, give it its own block; this
	 * avoids wasting what might be most of the current block to start a
	 * new block.  (We'd have to special-case requests bigger than the
	 * block size anyway.)	The object is always given binary alignment in
	 * this case.
239 240 241
	 */
	if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
	{
242
		block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
Bruce Momjian's avatar
Bruce Momjian committed
243
		if (!block)
244
			return NULL;
245
		space = block->space + PGRESULT_BLOCK_OVERHEAD;
246 247
		if (res->curBlock)
		{
Bruce Momjian's avatar
Bruce Momjian committed
248 249 250

			/*
			 * Tuck special block below the active block, so that we don't
251 252 253 254 255 256 257 258 259 260
			 * have to waste the free space in the active block.
			 */
			block->next = res->curBlock->next;
			res->curBlock->next = block;
		}
		else
		{
			/* Must set up the new block as the first active block. */
			block->next = NULL;
			res->curBlock = block;
Bruce Momjian's avatar
Bruce Momjian committed
261
			res->spaceLeft = 0; /* be sure it's marked full */
262 263 264 265 266 267
		}
		return space;
	}

	/* Otherwise, start a new block. */
	block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
Bruce Momjian's avatar
Bruce Momjian committed
268
	if (!block)
269 270 271 272 273 274
		return NULL;
	block->next = res->curBlock;
	res->curBlock = block;
	if (isBinary)
	{
		/* object needs full alignment */
275 276
		res->curOffset = PGRESULT_BLOCK_OVERHEAD;
		res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	}
	else
	{
		/* we can cram it right after the overhead pointer */
		res->curOffset = sizeof(PGresult_data);
		res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
	}

	space = block->space + res->curOffset;
	res->curOffset += nBytes;
	res->spaceLeft -= nBytes;
	return space;
}

/*
 * pqResultStrdup -
 *		Like strdup, but the space is subsidiary PGresult space.
 */
char *
pqResultStrdup(PGresult *res, const char *str)
{
Bruce Momjian's avatar
Bruce Momjian committed
298 299
	char	   *space = (char *) pqResultAlloc(res, strlen(str) + 1, FALSE);

300 301 302 303 304
	if (space)
		strcpy(space, str);
	return space;
}

305 306 307 308 309 310 311 312 313 314
/*
 * pqSetResultError -
 *		assign a new error message to a PGresult
 */
void
pqSetResultError(PGresult *res, const char *msg)
{
	if (!res)
		return;
	if (msg && *msg)
315 316 317
		res->errMsg = pqResultStrdup(res, msg);
	else
		res->errMsg = NULL;
318 319
}

320 321 322 323 324 325 326
/*
 * pqCatenateResultError -
 *		concatenate a new error message to the one already in a PGresult
 */
static void
pqCatenateResultError(PGresult *res, const char *msg)
{
327
	PQExpBufferData errorBuf;
328 329 330 331 332 333 334 335 336 337 338

	if (!res || !msg)
		return;
	initPQExpBuffer(&errorBuf);
	if (res->errMsg)
		appendPQExpBufferStr(&errorBuf, res->errMsg);
	appendPQExpBufferStr(&errorBuf, msg);
	pqSetResultError(res, errorBuf.data);
	termPQExpBuffer(&errorBuf);
}

339
/*
Bruce Momjian's avatar
Bruce Momjian committed
340 341
 * PQclear -
 *	  free's the memory associated with a PGresult
342
 */
Bruce Momjian's avatar
Bruce Momjian committed
343 344
void
PQclear(PGresult *res)
345
{
Bruce Momjian's avatar
Bruce Momjian committed
346
	PGresult_data *block;
347

Bruce Momjian's avatar
Bruce Momjian committed
348 349
	if (!res)
		return;
350

351
	/* Free all the subsidiary blocks */
Bruce Momjian's avatar
Bruce Momjian committed
352 353
	while ((block = res->curBlock) != NULL)
	{
354 355
		res->curBlock = block->next;
		free(block);
Bruce Momjian's avatar
Bruce Momjian committed
356 357
	}

358 359 360
	/* Free the top-level tuple pointer array */
	if (res->tuples)
		free(res->tuples);
361

362
	/* Free the PGresult structure itself */
Bruce Momjian's avatar
Bruce Momjian committed
363 364 365 366 367 368
	free(res);
}

/*
 * Handy subroutine to deallocate any partially constructed async result.
 */
369

Bruce Momjian's avatar
Bruce Momjian committed
370
void
371
pqClearAsyncResult(PGconn *conn)
Bruce Momjian's avatar
Bruce Momjian committed
372 373 374 375 376
{
	if (conn->result)
		PQclear(conn->result);
	conn->result = NULL;
	conn->curTuple = NULL;
377 378
}

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
/*
 * This subroutine deletes any existing async result, sets conn->result
 * to a PGresult with status PGRES_FATAL_ERROR, and stores the current
 * contents of conn->errorMessage into that result.  It differs from a
 * plain call on PQmakeEmptyPGresult() in that if there is already an
 * async result with status PGRES_FATAL_ERROR, the current error message
 * is APPENDED to the old error message instead of replacing it.  This
 * behavior lets us report multiple error conditions properly, if necessary.
 * (An example where this is needed is when the backend sends an 'E' message
 * and immediately closes the connection --- we want to report both the
 * backend error and the connection closure error.)
 */
static void
saveErrorResult(PGconn *conn)
{
394 395 396

	/*
	 * If no old async result, just let PQmakeEmptyPGresult make one.
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
	 * Likewise if old result is not an error message.
	 */
	if (conn->result == NULL ||
		conn->result->resultStatus != PGRES_FATAL_ERROR ||
		conn->result->errMsg == NULL)
	{
		pqClearAsyncResult(conn);
		conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
	}
	else
	{
		/* Else, concatenate error message to existing async result. */
		pqCatenateResultError(conn->result, conn->errorMessage.data);
	}
}

/*
 * This subroutine prepares an async result object for return to the caller.
 * If there is not already an async result object, build an error object
 * using whatever is in conn->errorMessage.  In any case, clear the async
 * result storage and make sure PQerrorMessage will agree with the result's
 * error string.
 */
static PGresult *
prepareAsyncResult(PGconn *conn)
{
	PGresult   *res;

	/*
426 427 428
	 * conn->result is the PGresult to return.	If it is NULL (which
	 * probably shouldn't happen) we assume there is an appropriate error
	 * message in conn->errorMessage.
429 430 431 432 433 434 435 436
	 */
	res = conn->result;
	conn->result = NULL;		/* handing over ownership to caller */
	conn->curTuple = NULL;		/* just in case */
	if (!res)
		res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
	else
	{
437

438
		/*
439 440
		 * Make sure PQerrorMessage agrees with result; it could be
		 * different if we have concatenated messages.
441 442 443 444 445 446 447
		 */
		resetPQExpBuffer(&conn->errorMessage);
		appendPQExpBufferStr(&conn->errorMessage,
							 PQresultErrorMessage(res));
	}
	return res;
}
448 449 450

/*
 * addTuple
451
 *	  add a row pointer to the PGresult structure, growing it if necessary
452
 *	  Returns TRUE if OK, FALSE if not enough memory to add the row
453
 */
454
static int
455
addTuple(PGresult *res, PGresAttValue * tup)
456
{
Bruce Momjian's avatar
Bruce Momjian committed
457
	if (res->ntups >= res->tupArrSize)
458
	{
Bruce Momjian's avatar
Bruce Momjian committed
459

Bruce Momjian's avatar
Bruce Momjian committed
460
		/*
461 462 463
		 * Try to grow the array.
		 *
		 * We can use realloc because shallow copying of the structure is
464
		 * okay.  Note that the first time through, res->tuples is NULL.
465 466 467
		 * While ANSI says that realloc() should act like malloc() in that
		 * case, some old C libraries (like SunOS 4.1.x) coredump instead.
		 * On failure realloc is supposed to return NULL without damaging
Bruce Momjian's avatar
Bruce Momjian committed
468 469
		 * the existing allocation. Note that the positions beyond
		 * res->ntups are garbage, not necessarily NULL.
Bruce Momjian's avatar
Bruce Momjian committed
470
		 */
Bruce Momjian's avatar
Bruce Momjian committed
471 472 473
		int			newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
		PGresAttValue **newTuples;

474 475 476 477 478 479
		if (res->tuples == NULL)
			newTuples = (PGresAttValue **)
				malloc(newSize * sizeof(PGresAttValue *));
		else
			newTuples = (PGresAttValue **)
				realloc(res->tuples, newSize * sizeof(PGresAttValue *));
Bruce Momjian's avatar
Bruce Momjian committed
480
		if (!newTuples)
481
			return FALSE;		/* malloc or realloc failed */
482 483
		res->tupArrSize = newSize;
		res->tuples = newTuples;
484 485 486
	}
	res->tuples[res->ntups] = tup;
	res->ntups++;
487
	return TRUE;
488 489
}

Bruce Momjian's avatar
Bruce Momjian committed
490

491
/*
Bruce Momjian's avatar
Bruce Momjian committed
492
 * PQsendQuery
493
 *	 Submit a query, but don't wait for it to finish
494
 *
Bruce Momjian's avatar
Bruce Momjian committed
495
 * Returns: 1 if successfully submitted
496
 *			0 if error (conn->errorMessage is set)
497 498
 */

Bruce Momjian's avatar
Bruce Momjian committed
499 500
int
PQsendQuery(PGconn *conn, const char *query)
501
{
Bruce Momjian's avatar
Bruce Momjian committed
502 503
	if (!conn)
		return 0;
504 505 506 507

	/* clear the error string */
	resetPQExpBuffer(&conn->errorMessage);

Bruce Momjian's avatar
Bruce Momjian committed
508
	if (!query)
509
	{
510 511
		printfPQExpBuffer(&conn->errorMessage,
						  "PQsendQuery() -- query pointer is null.\n");
512 513 514
		return 0;
	}

Bruce Momjian's avatar
Bruce Momjian committed
515 516 517
	/* Don't try to send if we know there's no live connection. */
	if (conn->status != CONNECTION_OK)
	{
518 519 520
		printfPQExpBuffer(&conn->errorMessage,
						  "PQsendQuery() -- There is no connection "
						  "to the backend.\n");
Bruce Momjian's avatar
Bruce Momjian committed
521 522
		return 0;
	}
523 524 525
	/* Can't send while already busy, either. */
	if (conn->asyncStatus != PGASYNC_IDLE)
	{
526
		printfPQExpBuffer(&conn->errorMessage,
527
				"PQsendQuery() -- another query already in progress.\n");
528 529
		return 0;
	}
530

531 532 533 534
	/* initialize async result-accumulation state */
	conn->result = NULL;
	conn->curTuple = NULL;

Bruce Momjian's avatar
Bruce Momjian committed
535
	/* send the query to the backend; */
536 537

	/*
538 539 540 541
	 * in order to guarantee that we don't send a partial query where we
	 * would become out of sync with the backend and/or block during a
	 * non-blocking connection we must first flush the send buffer before
	 * sending more data
542
	 *
543 544 545
	 * an alternative is to implement 'queue reservations' where we are able
	 * to roll up a transaction (the 'Q' along with our query) and make
	 * sure we have enough space for it all in the send buffer.
546 547
	 */
	if (pqIsnonblocking(conn))
548
	{
549

550
		/*
551 552
		 * the buffer must have emptied completely before we allow a new
		 * query to be buffered
553 554 555 556 557 558 559 560
		 */
		if (pqFlush(conn))
			return 0;
		/* 'Q' == queries */
		/* XXX: if we fail here we really ought to not block */
		if (pqPutnchar("Q", 1, conn) ||
			pqPuts(query, conn))
		{
561
			handleSendFailure(conn);
562 563
			return 0;
		}
564

565
		/*
566 567
		 * give the data a push, ignore the return value as ConsumeInput()
		 * will do any aditional flushing if needed
568
		 */
569
		(void) pqFlush(conn);
570 571 572
	}
	else
	{
573 574 575

		/*
		 * the frontend-backend protocol uses 'Q' to designate queries
576 577 578 579 580 581 582 583
		 */
		if (pqPutnchar("Q", 1, conn) ||
			pqPuts(query, conn) ||
			pqFlush(conn))
		{
			handleSendFailure(conn);
			return 0;
		}
584
	}
585

Bruce Momjian's avatar
Bruce Momjian committed
586 587 588
	/* OK, it's launched! */
	conn->asyncStatus = PGASYNC_BUSY;
	return 1;
589 590
}

591 592 593 594 595 596 597 598 599 600 601 602
/*
 * handleSendFailure: try to clean up after failure to send command.
 *
 * Primarily, what we want to accomplish here is to process an async
 * NOTICE message that the backend might have sent just before it died.
 *
 * NOTE: this routine should only be called in PGASYNC_IDLE state.
 */

static void
handleSendFailure(PGconn *conn)
{
603

604 605 606 607 608 609
	/*
	 * Accept any available input data, ignoring errors.  Note that if
	 * pqReadData decides the backend has closed the channel, it will
	 * close our side of the socket --- that's just what we want here.
	 */
	while (pqReadData(conn) > 0)
610
		 /* loop until no more data readable */ ;
611 612

	/*
613
	 * Parse any available input messages.	Since we are in PGASYNC_IDLE
614 615 616 617
	 * state, only NOTICE and NOTIFY messages will be eaten.
	 */
	parseInput(conn);
}
618

619
/*
Bruce Momjian's avatar
Bruce Momjian committed
620
 * Consume any available input from the backend
621 622
 * 0 return: some kind of trouble
 * 1 return: no problem
623 624
 */

625
int
Bruce Momjian's avatar
Bruce Momjian committed
626
PQconsumeInput(PGconn *conn)
627
{
Bruce Momjian's avatar
Bruce Momjian committed
628
	if (!conn)
629
		return 0;
630

631 632 633 634 635
	/*
	 * Load more data, if available. We do this no matter what state we
	 * are in, since we are probably getting called because the
	 * application wants to get rid of a read-select condition. Note that
	 * we will NOT block waiting for more input.
636
	 */
637
	if (pqReadData(conn) < 0)
638
	{
639

640
		/*
641 642 643
		 * for non-blocking connections try to flush the send-queue
		 * otherwise we may never get a responce for something that may
		 * not have already been sent because it's in our write buffer!
644 645 646
		 */
		if (pqIsnonblocking(conn))
			(void) pqFlush(conn);
647
		return 0;
648
	}
Bruce Momjian's avatar
Bruce Momjian committed
649
	/* Parsing of the data waits till later. */
650
	return 1;
Bruce Momjian's avatar
Bruce Momjian committed
651
}
652 653


Bruce Momjian's avatar
Bruce Momjian committed
654 655 656 657 658
/*
 * parseInput: if appropriate, parse input data from backend
 * until input is exhausted or a stopping state is reached.
 * Note that this function will NOT attempt to read more data from the backend.
 */
659

Bruce Momjian's avatar
Bruce Momjian committed
660 661 662
static void
parseInput(PGconn *conn)
{
663
	char		id;
664
	char		noticeWorkspace[128];
665

666
	/*
Bruce Momjian's avatar
Bruce Momjian committed
667
	 * Loop to parse successive complete messages available in the buffer.
668
	 */
Bruce Momjian's avatar
Bruce Momjian committed
669
	for (;;)
670
	{
671 672 673 674 675 676 677

		/*
		 * Quit if in COPY_OUT state: we expect raw data from the server
		 * until PQendcopy is called.  Don't try to parse it according to
		 * the normal protocol.  (This is bogus.  The data lines ought to
		 * be part of the protocol and have identifying leading
		 * characters.)
Bruce Momjian's avatar
Bruce Momjian committed
678 679 680
		 */
		if (conn->asyncStatus == PGASYNC_COPY_OUT)
			return;
681

Bruce Momjian's avatar
Bruce Momjian committed
682 683 684 685 686 687
		/*
		 * OK to try to read a message type code.
		 */
		conn->inCursor = conn->inStart;
		if (pqGetc(&id, conn))
			return;
688

Bruce Momjian's avatar
Bruce Momjian committed
689
		/*
690 691
		 * NOTIFY and NOTICE messages can happen in any state besides COPY
		 * OUT; always process them right away.
692 693
		 *
		 * Most other messages should only be processed while in BUSY state.
694 695
		 * (In particular, in READY state we hold off further parsing
		 * until the application collects the current PGresult.)
696
		 *
697 698
		 * However, if the state is IDLE then we got trouble; we need to deal
		 * with the unexpected message somehow.
Bruce Momjian's avatar
Bruce Momjian committed
699 700
		 */
		if (id == 'A')
701
		{
Bruce Momjian's avatar
Bruce Momjian committed
702 703
			if (getNotify(conn))
				return;
704
		}
705 706 707 708 709
		else if (id == 'N')
		{
			if (getNotice(conn))
				return;
		}
710
		else if (conn->asyncStatus != PGASYNC_BUSY)
711
		{
712 713 714
			/* If not IDLE state, just wait ... */
			if (conn->asyncStatus != PGASYNC_IDLE)
				return;
715

Bruce Momjian's avatar
Bruce Momjian committed
716
			/*
717 718 719 720 721 722
			 * Unexpected message in IDLE state; need to recover somehow.
			 * ERROR messages are displayed using the notice processor;
			 * anything else is just dropped on the floor after displaying
			 * a suitable warning notice.  (An ERROR is very possibly the
			 * backend telling us why it is about to close the connection,
			 * so we don't want to just discard it...)
Bruce Momjian's avatar
Bruce Momjian committed
723
			 */
724
			if (id == 'E')
Bruce Momjian's avatar
Bruce Momjian committed
725
			{
726 727 728 729 730 731
				if (getNotice(conn))
					return;
			}
			else
			{
				sprintf(noticeWorkspace,
732
					  "Backend message type 0x%02x arrived while idle\n",
733 734 735 736 737
						id);
				DONOTICE(conn, noticeWorkspace);
				/* Discard the unexpected message; good idea?? */
				conn->inStart = conn->inEnd;
				break;
Bruce Momjian's avatar
Bruce Momjian committed
738
			}
739 740 741
		}
		else
		{
742

743 744 745
			/*
			 * In BUSY state, we can process everything.
			 */
746 747
			switch (id)
			{
Bruce Momjian's avatar
Bruce Momjian committed
748
				case 'C':		/* command complete */
749 750
					if (pqGets(&conn->workBuffer, conn))
						return;
Bruce Momjian's avatar
Bruce Momjian committed
751
					if (conn->result == NULL)
752
						conn->result = PQmakeEmptyPGresult(conn,
753
													   PGRES_COMMAND_OK);
754 755
					strncpy(conn->result->cmdStatus, conn->workBuffer.data,
							CMDSTATUS_LEN);
756
					conn->asyncStatus = PGASYNC_READY;
Bruce Momjian's avatar
Bruce Momjian committed
757 758
					break;
				case 'E':		/* error return */
759
					if (pqGets(&conn->errorMessage, conn))
Bruce Momjian's avatar
Bruce Momjian committed
760
						return;
761 762
					/* build an error result holding the error message */
					saveErrorResult(conn);
763
					conn->asyncStatus = PGASYNC_READY;
Bruce Momjian's avatar
Bruce Momjian committed
764 765 766
					break;
				case 'Z':		/* backend is ready for new query */
					conn->asyncStatus = PGASYNC_IDLE;
767
					break;
Bruce Momjian's avatar
Bruce Momjian committed
768 769 770 771 772
				case 'I':		/* empty query */
					/* read and throw away the closing '\0' */
					if (pqGetc(&id, conn))
						return;
					if (id != '\0')
773
					{
774 775 776 777
						sprintf(noticeWorkspace,
								"unexpected character %c following 'I'\n",
								id);
						DONOTICE(conn, noticeWorkspace);
778
					}
Bruce Momjian's avatar
Bruce Momjian committed
779
					if (conn->result == NULL)
780
						conn->result = PQmakeEmptyPGresult(conn,
Bruce Momjian's avatar
Bruce Momjian committed
781
													  PGRES_EMPTY_QUERY);
782
					conn->asyncStatus = PGASYNC_READY;
Bruce Momjian's avatar
Bruce Momjian committed
783
					break;
784
				case 'K':		/* secret key data from the backend */
785 786 787 788 789

					/*
					 * This is expected only during backend startup, but
					 * it's just as easy to handle it as part of the main
					 * loop.  Save the data and continue processing.
790 791 792 793 794 795
					 */
					if (pqGetInt(&(conn->be_pid), 4, conn))
						return;
					if (pqGetInt(&(conn->be_key), 4, conn))
						return;
					break;
Bruce Momjian's avatar
Bruce Momjian committed
796
				case 'P':		/* synchronous (normal) portal */
797
					if (pqGets(&conn->workBuffer, conn))
Bruce Momjian's avatar
Bruce Momjian committed
798 799 800
						return;
					/* We pretty much ignore this message type... */
					break;
801 802
				case 'T':		/* row descriptions (start of query
								 * results) */
Bruce Momjian's avatar
Bruce Momjian committed
803
					if (conn->result == NULL)
804
					{
Bruce Momjian's avatar
Bruce Momjian committed
805 806 807
						/* First 'T' in a query sequence */
						if (getRowDescriptions(conn))
							return;
808 809 810
					}
					else
					{
811 812 813

						/*
						 * A new 'T' message is treated as the start of
Bruce Momjian's avatar
Bruce Momjian committed
814 815 816 817
						 * another PGresult.  (It is not clear that this
						 * is really possible with the current backend.)
						 * We stop parsing until the application accepts
						 * the current result.
818
						 */
Bruce Momjian's avatar
Bruce Momjian committed
819 820
						conn->asyncStatus = PGASYNC_READY;
						return;
821 822
					}
					break;
Bruce Momjian's avatar
Bruce Momjian committed
823 824
				case 'D':		/* ASCII data tuple */
					if (conn->result != NULL)
825
					{
Bruce Momjian's avatar
Bruce Momjian committed
826 827 828
						/* Read another tuple of a normal query response */
						if (getAnotherTuple(conn, FALSE))
							return;
829
					}
Bruce Momjian's avatar
Bruce Momjian committed
830
					else
831
					{
832
						sprintf(noticeWorkspace,
833
							 "Backend sent D message without prior T\n");
834
						DONOTICE(conn, noticeWorkspace);
Bruce Momjian's avatar
Bruce Momjian committed
835 836 837
						/* Discard the unexpected message; good idea?? */
						conn->inStart = conn->inEnd;
						return;
838
					}
839
					break;
Bruce Momjian's avatar
Bruce Momjian committed
840 841
				case 'B':		/* Binary data tuple */
					if (conn->result != NULL)
842
					{
Bruce Momjian's avatar
Bruce Momjian committed
843 844 845
						/* Read another tuple of a normal query response */
						if (getAnotherTuple(conn, TRUE))
							return;
846
					}
847
					else
Bruce Momjian's avatar
Bruce Momjian committed
848
					{
849
						sprintf(noticeWorkspace,
850
							 "Backend sent B message without prior T\n");
851
						DONOTICE(conn, noticeWorkspace);
Bruce Momjian's avatar
Bruce Momjian committed
852 853 854 855
						/* Discard the unexpected message; good idea?? */
						conn->inStart = conn->inEnd;
						return;
					}
856
					break;
Bruce Momjian's avatar
Bruce Momjian committed
857 858
				case 'G':		/* Start Copy In */
					conn->asyncStatus = PGASYNC_COPY_IN;
859
					break;
Bruce Momjian's avatar
Bruce Momjian committed
860 861
				case 'H':		/* Start Copy Out */
					conn->asyncStatus = PGASYNC_COPY_OUT;
862 863
					break;
				default:
864
					printfPQExpBuffer(&conn->errorMessage,
865 866 867 868
					"Unknown protocol character '%c' read from backend.  "
					"(The protocol character is the first character the "
									  "backend sends in response to a query it receives).\n",
									  id);
869 870
					/* build an error result holding the error message */
					saveErrorResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
871 872 873 874
					/* Discard the unexpected message; good idea?? */
					conn->inStart = conn->inEnd;
					conn->asyncStatus = PGASYNC_READY;
					return;
875
			}					/* switch on protocol character */
Bruce Momjian's avatar
Bruce Momjian committed
876 877 878 879
		}
		/* Successfully consumed this message */
		conn->inStart = conn->inCursor;
	}
880 881 882
}


883
/*
Bruce Momjian's avatar
Bruce Momjian committed
884 885 886
 * parseInput subroutine to read a 'T' (row descriptions) message.
 * We build a PGresult structure containing the attribute data.
 * Returns: 0 if completed message, EOF if not enough data yet.
887
 *
Bruce Momjian's avatar
Bruce Momjian committed
888 889 890
 * Note that if we run out of data, we have to release the partially
 * constructed PGresult, and rebuild it again next time.  Fortunately,
 * that shouldn't happen often, since 'T' messages usually fit in a packet.
891 892
 */

Bruce Momjian's avatar
Bruce Momjian committed
893 894
static int
getRowDescriptions(PGconn *conn)
895
{
896
	PGresult   *result;
Bruce Momjian's avatar
Bruce Momjian committed
897 898
	int			nfields;
	int			i;
899

900
	result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
901

Bruce Momjian's avatar
Bruce Momjian committed
902 903 904
	/* parseInput already read the 'T' label. */
	/* the next two bytes are the number of fields	*/
	if (pqGetInt(&(result->numAttributes), 2, conn))
905
	{
Bruce Momjian's avatar
Bruce Momjian committed
906 907
		PQclear(result);
		return EOF;
908
	}
Bruce Momjian's avatar
Bruce Momjian committed
909
	nfields = result->numAttributes;
910

Bruce Momjian's avatar
Bruce Momjian committed
911 912
	/* allocate space for the attribute descriptors */
	if (nfields > 0)
913
	{
Bruce Momjian's avatar
Bruce Momjian committed
914
		result->attDescs = (PGresAttDesc *)
915
			pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
Bruce Momjian's avatar
Bruce Momjian committed
916
		MemSet((char *) result->attDescs, 0, nfields * sizeof(PGresAttDesc));
917 918
	}

Bruce Momjian's avatar
Bruce Momjian committed
919 920
	/* get type info */
	for (i = 0; i < nfields; i++)
921
	{
922
		int			typid;
923
		int			typlen;
924
		int			atttypmod;
Bruce Momjian's avatar
Bruce Momjian committed
925

926
		if (pqGets(&conn->workBuffer, conn) ||
927
			pqGetInt(&typid, 4, conn) ||
928 929
			pqGetInt(&typlen, 2, conn) ||
			pqGetInt(&atttypmod, 4, conn))
Bruce Momjian's avatar
Bruce Momjian committed
930 931 932 933
		{
			PQclear(result);
			return EOF;
		}
Bruce Momjian's avatar
Bruce Momjian committed
934

935 936 937 938
		/*
		 * Since pqGetInt treats 2-byte integers as unsigned, we need to
		 * coerce the special value "-1" to signed form.  (-1 is sent for
		 * variable-length fields.)  Formerly, libpq effectively did a
Bruce Momjian's avatar
Bruce Momjian committed
939 940
		 * sign-extension on the 2-byte value by storing it in a signed
		 * short. Now we only coerce the single value 65535 == -1; values
941 942 943 944
		 * 32768..65534 are taken as valid field lengths.
		 */
		if (typlen == 0xFFFF)
			typlen = -1;
945 946
		result->attDescs[i].name = pqResultStrdup(result,
												  conn->workBuffer.data);
947
		result->attDescs[i].typid = typid;
948
		result->attDescs[i].typlen = typlen;
949
		result->attDescs[i].atttypmod = atttypmod;
950 951
	}

Bruce Momjian's avatar
Bruce Momjian committed
952 953 954
	/* Success! */
	conn->result = result;
	return 0;
955
}
956 957

/*
Bruce Momjian's avatar
Bruce Momjian committed
958 959
 * parseInput subroutine to read a 'B' or 'D' (row data) message.
 * We add another tuple to the existing PGresult structure.
960
 * Returns: 0 if completed message, EOF if error or not enough data yet.
961
 *
Bruce Momjian's avatar
Bruce Momjian committed
962 963 964
 * Note that if we run out of data, we have to suspend and reprocess
 * the message after more data is received.  We keep a partially constructed
 * tuple in conn->curTuple, and avoid reallocating already-allocated storage.
965 966
 */

Bruce Momjian's avatar
Bruce Momjian committed
967 968
static int
getAnotherTuple(PGconn *conn, int binary)
969
{
970 971
	PGresult   *result = conn->result;
	int			nfields = result->numAttributes;
Bruce Momjian's avatar
Bruce Momjian committed
972
	PGresAttValue *tup;
973

974 975 976
	/* the backend sends us a bitmap of which attributes are null */
	char		std_bitmap[64]; /* used unless it doesn't fit */
	char	   *bitmap = std_bitmap;
Bruce Momjian's avatar
Bruce Momjian committed
977
	int			i;
Bruce Momjian's avatar
Bruce Momjian committed
978
	size_t		nbytes;			/* the number of bytes in bitmap  */
Bruce Momjian's avatar
Bruce Momjian committed
979 980 981 982
	char		bmap;			/* One byte of the bitmap */
	int			bitmap_index;	/* Its index */
	int			bitcnt;			/* number of bits examined in current byte */
	int			vlen;			/* length of the current field value */
983

984
	result->binary = binary;
985

Bruce Momjian's avatar
Bruce Momjian committed
986 987 988 989
	/* Allocate tuple space if first time for this data message */
	if (conn->curTuple == NULL)
	{
		conn->curTuple = (PGresAttValue *)
990
			pqResultAlloc(result, nfields * sizeof(PGresAttValue), TRUE);
991 992
		if (conn->curTuple == NULL)
			goto outOfMemory;
Bruce Momjian's avatar
Bruce Momjian committed
993 994 995
		MemSet((char *) conn->curTuple, 0, nfields * sizeof(PGresAttValue));
	}
	tup = conn->curTuple;
996

Bruce Momjian's avatar
Bruce Momjian committed
997
	/* Get the null-value bitmap */
998
	nbytes = (nfields + BYTELEN - 1) / BYTELEN;
999 1000 1001
	/* malloc() only for unusually large field counts... */
	if (nbytes > sizeof(std_bitmap))
		bitmap = (char *) malloc(nbytes);
1002

Bruce Momjian's avatar
Bruce Momjian committed
1003
	if (pqGetnchar(bitmap, nbytes, conn))
1004
		goto EOFexit;
1005

Bruce Momjian's avatar
Bruce Momjian committed
1006 1007 1008 1009
	/* Scan the fields */
	bitmap_index = 0;
	bmap = bitmap[bitmap_index];
	bitcnt = 0;
1010

Bruce Momjian's avatar
Bruce Momjian committed
1011
	for (i = 0; i < nfields; i++)
1012
	{
Bruce Momjian's avatar
Bruce Momjian committed
1013 1014 1015
		if (!(bmap & 0200))
		{
			/* if the field value is absent, make it a null string */
1016
			tup[i].value = result->null_field;
Bruce Momjian's avatar
Bruce Momjian committed
1017 1018 1019 1020 1021 1022
			tup[i].len = NULL_LEN;
		}
		else
		{
			/* get the value length (the first four bytes are for length) */
			if (pqGetInt(&vlen, 4, conn))
1023
				goto EOFexit;
Bruce Momjian's avatar
Bruce Momjian committed
1024 1025 1026 1027 1028
			if (binary == 0)
				vlen = vlen - 4;
			if (vlen < 0)
				vlen = 0;
			if (tup[i].value == NULL)
1029
			{
Bruce Momjian's avatar
Bruce Momjian committed
1030
				tup[i].value = (char *) pqResultAlloc(result, vlen + 1, binary);
1031 1032 1033
				if (tup[i].value == NULL)
					goto outOfMemory;
			}
Bruce Momjian's avatar
Bruce Momjian committed
1034 1035 1036 1037
			tup[i].len = vlen;
			/* read in the value */
			if (vlen > 0)
				if (pqGetnchar((char *) (tup[i].value), vlen, conn))
1038
					goto EOFexit;
1039
			/* we have to terminate this ourselves */
Bruce Momjian's avatar
Bruce Momjian committed
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
			tup[i].value[vlen] = '\0';
		}
		/* advance the bitmap stuff */
		bitcnt++;
		if (bitcnt == BYTELEN)
		{
			bitmap_index++;
			bmap = bitmap[bitmap_index];
			bitcnt = 0;
		}
		else
			bmap <<= 1;
1052 1053
	}

Bruce Momjian's avatar
Bruce Momjian committed
1054
	/* Success!  Store the completed tuple in the result */
Bruce Momjian's avatar
Bruce Momjian committed
1055
	if (!addTuple(result, tup))
1056
		goto outOfMemory;
Bruce Momjian's avatar
Bruce Momjian committed
1057 1058
	/* and reset for a new message */
	conn->curTuple = NULL;
1059 1060 1061

	if (bitmap != std_bitmap)
		free(bitmap);
Bruce Momjian's avatar
Bruce Momjian committed
1062
	return 0;
1063 1064 1065

outOfMemory:
	/* Replace partially constructed result with an error result */
1066 1067 1068

	/*
	 * we do NOT use saveErrorResult() here, because of the likelihood
1069 1070
	 * that there's not enough memory to concatenate messages...
	 */
1071
	pqClearAsyncResult(conn);
1072 1073
	printfPQExpBuffer(&conn->errorMessage,
					  "getAnotherTuple() -- out of memory for result\n");
1074 1075 1076 1077
	conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
	conn->asyncStatus = PGASYNC_READY;
	/* Discard the failed message --- good idea? */
	conn->inStart = conn->inEnd;
1078 1079 1080 1081

EOFexit:
	if (bitmap != std_bitmap)
		free(bitmap);
1082
	return EOF;
1083 1084 1085 1086
}


/*
Bruce Momjian's avatar
Bruce Momjian committed
1087
 * PQisBusy
1088
 *	 Return TRUE if PQgetResult would block waiting for input.
1089
 */
Bruce Momjian's avatar
Bruce Momjian committed
1090

1091
int
Bruce Momjian's avatar
Bruce Momjian committed
1092
PQisBusy(PGconn *conn)
1093
{
1094
	if (!conn)
Bruce Momjian's avatar
Bruce Momjian committed
1095
		return FALSE;
1096

Bruce Momjian's avatar
Bruce Momjian committed
1097 1098
	/* Parse any available data, if our state permits. */
	parseInput(conn);
1099

Bruce Momjian's avatar
Bruce Momjian committed
1100
	/* PQgetResult will return immediately in all states except BUSY. */
1101
	return conn->asyncStatus == PGASYNC_BUSY;
1102 1103
}

1104 1105

/*
Bruce Momjian's avatar
Bruce Momjian committed
1106
 * PQgetResult
1107 1108
 *	  Get the next PGresult produced by a query.
 *	  Returns NULL if and only if no query work remains.
1109
 */
1110

1111
PGresult   *
Bruce Momjian's avatar
Bruce Momjian committed
1112 1113
PQgetResult(PGconn *conn)
{
1114
	PGresult   *res;
1115

Bruce Momjian's avatar
Bruce Momjian committed
1116 1117
	if (!conn)
		return NULL;
1118

Bruce Momjian's avatar
Bruce Momjian committed
1119 1120
	/* Parse any available data, if our state permits. */
	parseInput(conn);
1121

Bruce Momjian's avatar
Bruce Momjian committed
1122 1123
	/* If not ready to return something, block until we are. */
	while (conn->asyncStatus == PGASYNC_BUSY)
1124
	{
Bruce Momjian's avatar
Bruce Momjian committed
1125 1126 1127
		/* Wait for some more data, and load it. */
		if (pqWait(TRUE, FALSE, conn) ||
			pqReadData(conn) < 0)
1128
		{
1129 1130 1131 1132

			/*
			 * conn->errorMessage has been set by pqWait or pqReadData. We
			 * want to append it to any already-received error message.
1133 1134
			 */
			saveErrorResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1135
			conn->asyncStatus = PGASYNC_IDLE;
1136
			return prepareAsyncResult(conn);
1137
		}
Bruce Momjian's avatar
Bruce Momjian committed
1138 1139
		/* Parse it. */
		parseInput(conn);
1140 1141
	}

Bruce Momjian's avatar
Bruce Momjian committed
1142 1143
	/* Return the appropriate thing. */
	switch (conn->asyncStatus)
1144
	{
Bruce Momjian's avatar
Bruce Momjian committed
1145 1146 1147 1148
		case PGASYNC_IDLE:
			res = NULL;			/* query is complete */
			break;
		case PGASYNC_READY:
1149
			res = prepareAsyncResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1150 1151 1152 1153
			/* Set the state back to BUSY, allowing parsing to proceed. */
			conn->asyncStatus = PGASYNC_BUSY;
			break;
		case PGASYNC_COPY_IN:
1154
			res = PQmakeEmptyPGresult(conn, PGRES_COPY_IN);
Bruce Momjian's avatar
Bruce Momjian committed
1155 1156
			break;
		case PGASYNC_COPY_OUT:
1157
			res = PQmakeEmptyPGresult(conn, PGRES_COPY_OUT);
Bruce Momjian's avatar
Bruce Momjian committed
1158 1159
			break;
		default:
1160 1161 1162
			printfPQExpBuffer(&conn->errorMessage,
							  "PQgetResult: Unexpected asyncStatus %d\n",
							  (int) conn->asyncStatus);
1163
			res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
Bruce Momjian's avatar
Bruce Momjian committed
1164
			break;
1165 1166
	}

Bruce Momjian's avatar
Bruce Momjian committed
1167
	return res;
1168 1169
}

1170 1171

/*
Bruce Momjian's avatar
Bruce Momjian committed
1172 1173
 * PQexec
 *	  send a query to the backend and package up the result in a PGresult
1174
 *
1175 1176 1177 1178 1179 1180
 * If the query was not even sent, return NULL; conn->errorMessage is set to
 * a relevant message.
 * If the query was sent, a new PGresult is returned (which could indicate
 * either success or failure).
 * The user is responsible for freeing the PGresult via PQclear()
 * when done with it.
1181
 */
1182

Bruce Momjian's avatar
Bruce Momjian committed
1183 1184
PGresult   *
PQexec(PGconn *conn, const char *query)
1185
{
1186 1187
	PGresult   *result;
	PGresult   *lastResult;
1188
	bool		savedblocking;
1189 1190

	/*
1191 1192 1193
	 * we assume anyone calling PQexec wants blocking behaviour, we force
	 * the blocking status of the connection to blocking for the duration
	 * of this function and restore it on return
1194 1195 1196 1197
	 */
	savedblocking = pqIsnonblocking(conn);
	if (PQsetnonblocking(conn, FALSE) == -1)
		return NULL;
1198

1199 1200 1201 1202
	/*
	 * Silently discard any prior query result that application didn't
	 * eat. This is probably poor design, but it's here for backward
	 * compatibility.
Bruce Momjian's avatar
Bruce Momjian committed
1203 1204
	 */
	while ((result = PQgetResult(conn)) != NULL)
1205
	{
Bruce Momjian's avatar
Bruce Momjian committed
1206 1207
		if (result->resultStatus == PGRES_COPY_IN ||
			result->resultStatus == PGRES_COPY_OUT)
1208
		{
Bruce Momjian's avatar
Bruce Momjian committed
1209
			PQclear(result);
1210
			printfPQExpBuffer(&conn->errorMessage,
1211
				"PQexec: you gotta get out of a COPY state yourself.\n");
1212 1213
			/* restore blocking status */
			goto errout;
1214
		}
Bruce Momjian's avatar
Bruce Momjian committed
1215
		PQclear(result);
1216 1217
	}

Bruce Momjian's avatar
Bruce Momjian committed
1218
	/* OK to send the message */
1219
	if (!PQsendQuery(conn, query))
1220
		goto errout;			/* restore blocking status */
1221

1222 1223
	/*
	 * For backwards compatibility, return the last result if there are
1224 1225 1226
	 * more than one --- but merge error messages if we get more than one
	 * error result.
	 *
1227 1228
	 * We have to stop if we see copy in/out, however. We will resume parsing
	 * when application calls PQendcopy.
Bruce Momjian's avatar
Bruce Momjian committed
1229 1230 1231 1232 1233
	 */
	lastResult = NULL;
	while ((result = PQgetResult(conn)) != NULL)
	{
		if (lastResult)
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
		{
			if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
				result->resultStatus == PGRES_FATAL_ERROR)
			{
				pqCatenateResultError(lastResult, result->errMsg);
				PQclear(result);
				result = lastResult;
				/* Make sure PQerrorMessage agrees with catenated result */
				resetPQExpBuffer(&conn->errorMessage);
				appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
			}
			else
				PQclear(lastResult);
		}
Bruce Momjian's avatar
Bruce Momjian committed
1248
		lastResult = result;
1249 1250 1251
		if (result->resultStatus == PGRES_COPY_IN ||
			result->resultStatus == PGRES_COPY_OUT)
			break;
1252
	}
1253 1254 1255

	if (PQsetnonblocking(conn, savedblocking) == -1)
		return NULL;
Bruce Momjian's avatar
Bruce Momjian committed
1256
	return lastResult;
1257 1258 1259 1260 1261

errout:
	if (PQsetnonblocking(conn, savedblocking) == -1)
		return NULL;
	return NULL;
1262 1263
}

1264

Bruce Momjian's avatar
Bruce Momjian committed
1265 1266 1267 1268 1269
/*
 * Attempt to read a Notice response message.
 * This is possible in several places, so we break it out as a subroutine.
 * Entry: 'N' flag character has already been consumed.
 * Exit: returns 0 if successfully consumed Notice message.
1270
 *		 returns EOF if not enough data.
Bruce Momjian's avatar
Bruce Momjian committed
1271 1272 1273
 */
static int
getNotice(PGconn *conn)
1274
{
1275 1276 1277 1278

	/*
	 * Since the Notice might be pretty long, we create a temporary
	 * PQExpBuffer rather than using conn->workBuffer.	workBuffer is
1279 1280
	 * intended for stuff that is expected to be short.
	 */
1281
	PQExpBufferData noticeBuf;
1282 1283 1284 1285 1286

	initPQExpBuffer(&noticeBuf);
	if (pqGets(&noticeBuf, conn))
	{
		termPQExpBuffer(&noticeBuf);
Bruce Momjian's avatar
Bruce Momjian committed
1287
		return EOF;
1288 1289 1290
	}
	DONOTICE(conn, noticeBuf.data);
	termPQExpBuffer(&noticeBuf);
Bruce Momjian's avatar
Bruce Momjian committed
1291 1292
	return 0;
}
1293

Bruce Momjian's avatar
Bruce Momjian committed
1294 1295 1296 1297 1298
/*
 * Attempt to read a Notify response message.
 * This is possible in several places, so we break it out as a subroutine.
 * Entry: 'A' flag character has already been consumed.
 * Exit: returns 0 if successfully consumed Notify message.
1299
 *		 returns EOF if not enough data.
Bruce Momjian's avatar
Bruce Momjian committed
1300 1301 1302 1303
 */
static int
getNotify(PGconn *conn)
{
1304
	int			be_pid;
Bruce Momjian's avatar
Bruce Momjian committed
1305
	PGnotify   *newNotify;
1306

1307
	if (pqGetInt(&be_pid, 4, conn))
Bruce Momjian's avatar
Bruce Momjian committed
1308
		return EOF;
1309
	if (pqGets(&conn->workBuffer, conn))
Bruce Momjian's avatar
Bruce Momjian committed
1310 1311
		return EOF;
	newNotify = (PGnotify *) malloc(sizeof(PGnotify));
1312 1313
	strncpy(newNotify->relname, conn->workBuffer.data, NAMEDATALEN);
	newNotify->be_pid = be_pid;
Bruce Momjian's avatar
Bruce Momjian committed
1314 1315
	DLAddTail(conn->notifyList, DLNewElem(newNotify));
	return 0;
1316 1317
}

Bruce Momjian's avatar
Bruce Momjian committed
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
/*
 * PQnotifies
 *	  returns a PGnotify* structure of the latest async notification
 * that has not yet been handled
 *
 * returns NULL, if there is currently
 * no unhandled async notification from the backend
 *
 * the CALLER is responsible for FREE'ing the structure returned
 */

PGnotify   *
PQnotifies(PGconn *conn)
{
	Dlelem	   *e;
	PGnotify   *event;

	if (!conn)
		return NULL;
1337

Bruce Momjian's avatar
Bruce Momjian committed
1338 1339
	/* Parse any available data to see if we can extract NOTIFY messages. */
	parseInput(conn);
1340

Bruce Momjian's avatar
Bruce Momjian committed
1341 1342 1343 1344 1345 1346 1347 1348
	/* RemHead returns NULL if list is empty */
	e = DLRemHead(conn->notifyList);
	if (!e)
		return NULL;
	event = (PGnotify *) DLE_VAL(e);
	DLFreeElem(e);
	return event;
}
1349

1350
/*
Bruce Momjian's avatar
Bruce Momjian committed
1351
 * PQgetline - gets a newline-terminated string from the backend.
1352
 *
Bruce Momjian's avatar
Bruce Momjian committed
1353 1354
 * Chiefly here so that applications can use "COPY <rel> to stdout"
 * and read the output string.	Returns a null-terminated string in s.
1355
 *
Bruce Momjian's avatar
Bruce Momjian committed
1356 1357
 * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
 * the terminating \n (like gets(3)).
1358
 *
1359 1360 1361
 * CAUTION: the caller is responsible for detecting the end-of-copy signal
 * (a line containing just "\.") when using this routine.
 *
Bruce Momjian's avatar
Bruce Momjian committed
1362 1363 1364 1365 1366 1367 1368
 * RETURNS:
 *		EOF if it is detected or invalid arguments are given
 *		0 if EOL is reached (i.e., \n has been read)
 *				(this is required for backward-compatibility -- this
 *				 routine used to always return EOF or 0, assuming that
 *				 the line ended within maxlen bytes.)
 *		1 in other cases (i.e., the buffer was filled before \n is reached)
1369
 */
Bruce Momjian's avatar
Bruce Momjian committed
1370 1371
int
PQgetline(PGconn *conn, char *s, int maxlen)
1372
{
Bruce Momjian's avatar
Bruce Momjian committed
1373
	int			result = 1;		/* return value if buffer overflows */
1374

Bruce Momjian's avatar
Bruce Momjian committed
1375 1376
	if (!s || maxlen <= 0)
		return EOF;
1377

Bruce Momjian's avatar
Bruce Momjian committed
1378 1379 1380 1381 1382
	if (!conn || conn->sock < 0)
	{
		*s = '\0';
		return EOF;
	}
1383

1384 1385
	/*
	 * Since this is a purely synchronous routine, we don't bother to
Bruce Momjian's avatar
Bruce Momjian committed
1386 1387 1388 1389 1390
	 * maintain conn->inCursor; there is no need to back up.
	 */
	while (maxlen > 1)
	{
		if (conn->inStart < conn->inEnd)
1391
		{
1392 1393
			char		c = conn->inBuffer[conn->inStart++];

Bruce Momjian's avatar
Bruce Momjian committed
1394
			if (c == '\n')
1395
			{
Bruce Momjian's avatar
Bruce Momjian committed
1396 1397
				result = 0;		/* success exit */
				break;
1398
			}
Bruce Momjian's avatar
Bruce Momjian committed
1399 1400
			*s++ = c;
			maxlen--;
1401
		}
Bruce Momjian's avatar
Bruce Momjian committed
1402
		else
1403
		{
Bruce Momjian's avatar
Bruce Momjian committed
1404 1405 1406
			/* need to load more data */
			if (pqWait(TRUE, FALSE, conn) ||
				pqReadData(conn) < 0)
1407
			{
Bruce Momjian's avatar
Bruce Momjian committed
1408 1409
				result = EOF;
				break;
1410
			}
Bruce Momjian's avatar
Bruce Momjian committed
1411 1412 1413
		}
	}
	*s = '\0';
1414

Bruce Momjian's avatar
Bruce Momjian committed
1415 1416
	return result;
}
1417

1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
/*
 * PQgetlineAsync - gets a newline-terminated string without blocking.
 *
 * This routine is for applications that want to do "COPY <rel> to stdout"
 * asynchronously, that is without blocking.  Having issued the COPY command
 * and gotten a PGRES_COPY_OUT response, the app should call PQconsumeInput
 * and this routine until the end-of-data signal is detected.  Unlike
 * PQgetline, this routine takes responsibility for detecting end-of-data.
 *
 * On each call, PQgetlineAsync will return data if a complete newline-
 * terminated data line is available in libpq's input buffer, or if the
 * incoming data line is too long to fit in the buffer offered by the caller.
 * Otherwise, no data is returned until the rest of the line arrives.
 *
 * If -1 is returned, the end-of-data signal has been recognized (and removed
 * from libpq's input buffer).  The caller *must* next call PQendcopy and
 * then return to normal processing.
 *
 * RETURNS:
Bruce Momjian's avatar
Bruce Momjian committed
1437 1438 1439
 *	 -1    if the end-of-copy-data marker has been recognized
 *	 0	   if no data is available
 *	 >0    the number of bytes returned.
1440 1441 1442
 * The data returned will not extend beyond a newline character.  If possible
 * a whole line will be returned at one time.  But if the buffer offered by
 * the caller is too small to hold a line sent by the backend, then a partial
Bruce Momjian's avatar
Bruce Momjian committed
1443
 * data line will be returned.	This can be detected by testing whether the
1444 1445 1446 1447 1448 1449 1450
 * last returned byte is '\n' or not.
 * The returned string is *not* null-terminated.
 */

int
PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
{
Bruce Momjian's avatar
Bruce Momjian committed
1451
	int			avail;
1452 1453 1454 1455 1456

	if (!conn || conn->asyncStatus != PGASYNC_COPY_OUT)
		return -1;				/* we are not doing a copy... */

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1457 1458 1459 1460 1461
	 * Move data from libpq's buffer to the caller's. We want to accept
	 * data only in units of whole lines, not partial lines.  This ensures
	 * that we can recognize the terminator line "\\.\n".  (Otherwise, if
	 * it happened to cross a packet/buffer boundary, we might hand the
	 * first one or two characters off to the caller, which we shouldn't.)
1462 1463 1464 1465 1466 1467 1468
	 */

	conn->inCursor = conn->inStart;

	avail = bufsize;
	while (avail > 0 && conn->inCursor < conn->inEnd)
	{
Bruce Momjian's avatar
Bruce Momjian committed
1469 1470
		char		c = conn->inBuffer[conn->inCursor++];

1471 1472 1473 1474 1475 1476 1477
		*buffer++ = c;
		--avail;
		if (c == '\n')
		{
			/* Got a complete line; mark the data removed from libpq */
			conn->inStart = conn->inCursor;
			/* Is it the endmarker line? */
Bruce Momjian's avatar
Bruce Momjian committed
1478
			if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
1479 1480 1481 1482 1483 1484 1485
				return -1;
			/* No, return the data line to the caller */
			return bufsize - avail;
		}
	}

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1486 1487 1488 1489 1490 1491 1492
	 * We don't have a complete line. We'd prefer to leave it in libpq's
	 * buffer until the rest arrives, but there is a special case: what if
	 * the line is longer than the buffer the caller is offering us?  In
	 * that case we'd better hand over a partial line, else we'd get into
	 * an infinite loop. Do this in a way that ensures we can't
	 * misrecognize a terminator line later: leave last 3 characters in
	 * libpq buffer.
1493 1494 1495 1496 1497 1498 1499 1500 1501
	 */
	if (avail == 0 && bufsize > 3)
	{
		conn->inStart = conn->inCursor - 3;
		return bufsize - 3;
	}
	return 0;
}

Bruce Momjian's avatar
Bruce Momjian committed
1502 1503
/*
 * PQputline -- sends a string to the backend.
1504
 * Returns 0 if OK, EOF if not.
Bruce Momjian's avatar
Bruce Momjian committed
1505 1506 1507
 *
 * Chiefly here so that applications can use "COPY <rel> from stdin".
 */
1508
int
Bruce Momjian's avatar
Bruce Momjian committed
1509 1510
PQputline(PGconn *conn, const char *s)
{
1511 1512 1513
	if (!conn || conn->sock < 0)
		return EOF;
	return pqPutnchar(s, strlen(s), conn);
Bruce Momjian's avatar
Bruce Momjian committed
1514 1515
}

1516 1517
/*
 * PQputnbytes -- like PQputline, but buffer need not be null-terminated.
1518
 * Returns 0 if OK, EOF if not.
1519
 */
1520
int
1521 1522
PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
{
1523 1524 1525
	if (!conn || conn->sock < 0)
		return EOF;
	return pqPutnchar(buffer, nbytes, conn);
1526 1527
}

Bruce Momjian's avatar
Bruce Momjian committed
1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
/*
 * PQendcopy
 *		After completing the data transfer portion of a copy in/out,
 *		the application must call this routine to finish the command protocol.
 *
 * RETURNS:
 *		0 on success
 *		1 on failure
 */
int
PQendcopy(PGconn *conn)
{
1540
	PGresult   *result;
Bruce Momjian's avatar
Bruce Momjian committed
1541 1542 1543 1544 1545 1546 1547

	if (!conn)
		return 0;

	if (conn->asyncStatus != PGASYNC_COPY_IN &&
		conn->asyncStatus != PGASYNC_COPY_OUT)
	{
1548
		printfPQExpBuffer(&conn->errorMessage,
1549
		   "PQendcopy() -- I don't think there's a copy in progress.\n");
Bruce Momjian's avatar
Bruce Momjian committed
1550 1551 1552
		return 1;
	}

1553
	/*
1554 1555
	 * make sure no data is waiting to be sent, abort if we are
	 * non-blocking and the flush fails
1556 1557 1558 1559 1560 1561 1562
	 */
	if (pqFlush(conn) && pqIsnonblocking(conn))
		return (1);

	/* non blocking connections may have to abort at this point. */
	if (pqIsnonblocking(conn) && PQisBusy(conn))
		return (1);
Bruce Momjian's avatar
Bruce Momjian committed
1563 1564 1565

	/* Return to active duty */
	conn->asyncStatus = PGASYNC_BUSY;
1566
	resetPQExpBuffer(&conn->errorMessage);
Bruce Momjian's avatar
Bruce Momjian committed
1567 1568 1569 1570 1571

	/* Wait for the completion response */
	result = PQgetResult(conn);

	/* Expecting a successful result */
1572
	if (result && result->resultStatus == PGRES_COMMAND_OK)
Bruce Momjian's avatar
Bruce Momjian committed
1573 1574 1575
	{
		PQclear(result);
		return 0;
1576
	}
Bruce Momjian's avatar
Bruce Momjian committed
1577

1578 1579 1580 1581
	/*
	 * Trouble. The worst case is that we've lost sync with the backend
	 * entirely due to application screwup of the copy in/out protocol. To
	 * recover, reset the connection (talk about using a sledgehammer...)
Bruce Momjian's avatar
Bruce Momjian committed
1582 1583
	 */
	PQclear(result);
1584

1585 1586
	if (conn->errorMessage.len > 0)
		DONOTICE(conn, conn->errorMessage.data);
1587 1588

	DONOTICE(conn, "PQendcopy: resetting connection\n");
1589

1590 1591 1592 1593 1594 1595 1596 1597 1598
	/*
	 * Users doing non-blocking connections need to handle the reset
	 * themselves, they'll need to check the connection status if we
	 * return an error.
	 */
	if (pqIsnonblocking(conn))
		PQresetStart(conn);
	else
		PQreset(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1599 1600

	return 1;
1601 1602
}

1603 1604

/* ----------------
1605
 *		PQfn -	Send a function call to the POSTGRES backend.
1606
 *
1607 1608 1609 1610 1611 1612 1613 1614
 *		conn			: backend connection
 *		fnid			: function id
 *		result_buf		: pointer to result buffer (&int if integer)
 *		result_len		: length of return value.
 *		actual_result_len: actual length returned. (differs from result_len
 *						  for varlena structures.)
 *		result_type		: If the result is an integer, this must be 1,
 *						  otherwise this should be 0
Bruce Momjian's avatar
Bruce Momjian committed
1615 1616
 *		args			: pointer to an array of function arguments.
 *						  (each has length, if integer, and value/pointer)
1617
 *		nargs			: # of arguments in args array.
1618 1619
 *
 * RETURNS
1620
 *		PGresult with status = PGRES_COMMAND_OK if successful.
Bruce Momjian's avatar
Bruce Momjian committed
1621
 *			*actual_result_len is > 0 if there is a return value, 0 if not.
1622
 *		PGresult with status = PGRES_FATAL_ERROR if backend returns an error.
Bruce Momjian's avatar
Bruce Momjian committed
1623
 *		NULL on communications failure.  conn->errorMessage will be set.
1624 1625 1626
 * ----------------
 */

1627
PGresult   *
1628
PQfn(PGconn *conn,
1629 1630 1631 1632
	 int fnid,
	 int *result_buf,
	 int *actual_result_len,
	 int result_is_int,
Bruce Momjian's avatar
Bruce Momjian committed
1633
	 const PQArgBlock *args,
1634
	 int nargs)
1635
{
Bruce Momjian's avatar
Bruce Momjian committed
1636
	bool		needInput = false;
1637
	ExecStatusType status = PGRES_FATAL_ERROR;
Bruce Momjian's avatar
Bruce Momjian committed
1638
	char		id;
1639
	int			i;
1640

Bruce Momjian's avatar
Bruce Momjian committed
1641 1642
	*actual_result_len = 0;

1643 1644 1645
	if (!conn)
		return NULL;

1646 1647 1648 1649 1650
	/* clear the error string */
	resetPQExpBuffer(&conn->errorMessage);

	if (conn->sock < 0 || conn->asyncStatus != PGASYNC_IDLE ||
		conn->result != NULL)
Bruce Momjian's avatar
Bruce Momjian committed
1651
	{
1652 1653
		printfPQExpBuffer(&conn->errorMessage,
						  "PQfn() -- connection in wrong state\n");
Bruce Momjian's avatar
Bruce Momjian committed
1654 1655
		return NULL;
	}
1656

1657
	if (pqPuts("F ", conn) ||	/* function */
1658 1659 1660 1661
		pqPutInt(fnid, 4, conn) ||		/* function id */
		pqPutInt(nargs, 4, conn))		/* # of args */
	{
		handleSendFailure(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1662
		return NULL;
1663
	}
1664 1665 1666

	for (i = 0; i < nargs; ++i)
	{							/* len.int4 + contents	   */
Bruce Momjian's avatar
Bruce Momjian committed
1667
		if (pqPutInt(args[i].len, 4, conn))
1668 1669
		{
			handleSendFailure(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1670
			return NULL;
1671
		}
Bruce Momjian's avatar
Bruce Momjian committed
1672

1673 1674
		if (args[i].isint)
		{
Bruce Momjian's avatar
Bruce Momjian committed
1675
			if (pqPutInt(args[i].u.integer, 4, conn))
1676 1677
			{
				handleSendFailure(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1678
				return NULL;
1679
			}
1680 1681 1682
		}
		else
		{
Bruce Momjian's avatar
Bruce Momjian committed
1683
			if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1684 1685
			{
				handleSendFailure(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1686
				return NULL;
1687
			}
1688 1689
		}
	}
Bruce Momjian's avatar
Bruce Momjian committed
1690
	if (pqFlush(conn))
1691 1692
	{
		handleSendFailure(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1693
		return NULL;
1694
	}
1695

Bruce Momjian's avatar
Bruce Momjian committed
1696
	for (;;)
1697
	{
Bruce Momjian's avatar
Bruce Momjian committed
1698
		if (needInput)
1699
		{
Bruce Momjian's avatar
Bruce Momjian committed
1700 1701 1702 1703
			/* Wait for some data to arrive (or for the channel to close) */
			if (pqWait(TRUE, FALSE, conn) ||
				pqReadData(conn) < 0)
				break;
1704
		}
1705 1706 1707 1708

		/*
		 * Scan the message. If we run out of data, loop around to try
		 * again.
Bruce Momjian's avatar
Bruce Momjian committed
1709 1710 1711
		 */
		conn->inCursor = conn->inStart;
		needInput = true;
1712

Bruce Momjian's avatar
Bruce Momjian committed
1713 1714
		if (pqGetc(&id, conn))
			continue;
1715

1716 1717 1718 1719
		/*
		 * We should see V or E response to the command, but might get N
		 * and/or A notices first. We also need to swallow the final Z
		 * before returning.
Bruce Momjian's avatar
Bruce Momjian committed
1720
		 */
1721 1722
		switch (id)
		{
Bruce Momjian's avatar
Bruce Momjian committed
1723 1724 1725 1726
			case 'V':			/* function result */
				if (pqGetc(&id, conn))
					continue;
				if (id == 'G')
1727
				{
Bruce Momjian's avatar
Bruce Momjian committed
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742
					/* function returned nonempty value */
					if (pqGetInt(actual_result_len, 4, conn))
						continue;
					if (result_is_int)
					{
						if (pqGetInt(result_buf, 4, conn))
							continue;
					}
					else
					{
						if (pqGetnchar((char *) result_buf,
									   *actual_result_len,
									   conn))
							continue;
					}
1743
					if (pqGetc(&id, conn))		/* get the last '0' */
Bruce Momjian's avatar
Bruce Momjian committed
1744
						continue;
1745
				}
Bruce Momjian's avatar
Bruce Momjian committed
1746
				if (id == '0')
1747
				{
Bruce Momjian's avatar
Bruce Momjian committed
1748 1749
					/* correctly finished function result message */
					status = PGRES_COMMAND_OK;
1750
				}
1751 1752
				else
				{
Bruce Momjian's avatar
Bruce Momjian committed
1753
					/* The backend violates the protocol. */
1754
					printfPQExpBuffer(&conn->errorMessage,
1755
								"FATAL: PQfn: protocol error: id=0x%x\n",
1756 1757
									  id);
					saveErrorResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1758
					conn->inStart = conn->inCursor;
1759
					return prepareAsyncResult(conn);
1760 1761
				}
				break;
Bruce Momjian's avatar
Bruce Momjian committed
1762
			case 'E':			/* error return */
1763
				if (pqGets(&conn->errorMessage, conn))
Bruce Momjian's avatar
Bruce Momjian committed
1764
					continue;
1765 1766
				/* build an error result holding the error message */
				saveErrorResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
				status = PGRES_FATAL_ERROR;
				break;
			case 'A':			/* notify message */
				/* handle notify and go back to processing return values */
				if (getNotify(conn))
					continue;
				break;
			case 'N':			/* notice */
				/* handle notice and go back to processing return values */
				if (getNotice(conn))
					continue;
				break;
			case 'Z':			/* backend is ready for new query */
				/* consume the message and exit */
				conn->inStart = conn->inCursor;
1782 1783 1784
				/* if we saved a result object (probably an error), use it */
				if (conn->result)
					return prepareAsyncResult(conn);
1785
				return PQmakeEmptyPGresult(conn, status);
1786 1787
			default:
				/* The backend violates the protocol. */
1788
				printfPQExpBuffer(&conn->errorMessage,
1789
								"FATAL: PQfn: protocol error: id=0x%x\n",
1790 1791
								  id);
				saveErrorResult(conn);
Bruce Momjian's avatar
Bruce Momjian committed
1792
				conn->inStart = conn->inCursor;
1793
				return prepareAsyncResult(conn);
1794
		}
Bruce Momjian's avatar
Bruce Momjian committed
1795 1796 1797
		/* Completed this message, keep going */
		conn->inStart = conn->inCursor;
		needInput = false;
1798
	}
Bruce Momjian's avatar
Bruce Momjian committed
1799

1800 1801 1802 1803
	/*
	 * We fall out of the loop only upon failing to read data.
	 * conn->errorMessage has been set by pqWait or pqReadData. We want to
	 * append it to any already-received error message.
1804 1805 1806
	 */
	saveErrorResult(conn);
	return prepareAsyncResult(conn);
1807 1808
}

Bruce Momjian's avatar
Bruce Momjian committed
1809

1810 1811
/* ====== accessor funcs for PGresult ======== */

1812
ExecStatusType
Bruce Momjian's avatar
Bruce Momjian committed
1813
PQresultStatus(const PGresult *res)
1814 1815 1816 1817
{
	if (!res)
		return PGRES_NONFATAL_ERROR;
	return res->resultStatus;
1818 1819
}

1820
char *
1821 1822
PQresStatus(ExecStatusType status)
{
1823
	if (status < 0 || status >= sizeof pgresStatus / sizeof pgresStatus[0])
1824 1825 1826 1827
		return "Invalid ExecStatusType code";
	return pgresStatus[status];
}

1828
char *
Bruce Momjian's avatar
Bruce Momjian committed
1829
PQresultErrorMessage(const PGresult *res)
1830 1831 1832 1833 1834 1835
{
	if (!res || !res->errMsg)
		return "";
	return res->errMsg;
}

1836
int
Bruce Momjian's avatar
Bruce Momjian committed
1837
PQntuples(const PGresult *res)
1838
{
1839
	if (!res)
Bruce Momjian's avatar
Bruce Momjian committed
1840
		return 0;
1841
	return res->ntups;
1842 1843 1844
}

int
Bruce Momjian's avatar
Bruce Momjian committed
1845
PQnfields(const PGresult *res)
1846
{
1847
	if (!res)
Bruce Momjian's avatar
Bruce Momjian committed
1848
		return 0;
1849
	return res->numAttributes;
1850 1851
}

1852
int
Bruce Momjian's avatar
Bruce Momjian committed
1853
PQbinaryTuples(const PGresult *res)
1854 1855 1856 1857 1858 1859
{
	if (!res)
		return 0;
	return res->binary;
}

1860
/*
1861 1862 1863 1864 1865
 * Helper routines to range-check field numbers and tuple numbers.
 * Return TRUE if OK, FALSE if not
 */

static int
Bruce Momjian's avatar
Bruce Momjian committed
1866
check_field_number(const char *routineName, const PGresult *res, int field_num)
1867
{
1868
	char		noticeBuf[128];
1869

1870
	if (!res)
1871 1872
		return FALSE;			/* no way to display error message... */
	if (field_num < 0 || field_num >= res->numAttributes)
1873
	{
1874
		if (res->noticeHook)
1875
		{
1876
			sprintf(noticeBuf,
1877 1878
					"%s: ERROR! field number %d is out of range 0..%d\n",
					routineName, field_num, res->numAttributes - 1);
1879
			DONOTICE(res, noticeBuf);
1880
		}
1881
		return FALSE;
1882
	}
1883 1884
	return TRUE;
}
1885

1886
static int
Bruce Momjian's avatar
Bruce Momjian committed
1887
check_tuple_field_number(const char *routineName, const PGresult *res,
1888 1889
						 int tup_num, int field_num)
{
1890
	char		noticeBuf[128];
1891

1892 1893 1894 1895
	if (!res)
		return FALSE;			/* no way to display error message... */
	if (tup_num < 0 || tup_num >= res->ntups)
	{
1896
		if (res->noticeHook)
1897
		{
1898
			sprintf(noticeBuf,
1899 1900
					"%s: ERROR! tuple number %d is out of range 0..%d\n",
					routineName, tup_num, res->ntups - 1);
1901
			DONOTICE(res, noticeBuf);
1902
		}
1903 1904
		return FALSE;
	}
Bruce Momjian's avatar
Bruce Momjian committed
1905
	if (field_num < 0 || field_num >= res->numAttributes)
1906
	{
1907
		if (res->noticeHook)
1908
		{
1909
			sprintf(noticeBuf,
1910 1911
					"%s: ERROR! field number %d is out of range 0..%d\n",
					routineName, field_num, res->numAttributes - 1);
1912
			DONOTICE(res, noticeBuf);
1913
		}
1914
		return FALSE;
1915
	}
1916 1917 1918 1919 1920 1921
	return TRUE;
}

/*
   returns NULL if the field_num is invalid
*/
1922
char *
Bruce Momjian's avatar
Bruce Momjian committed
1923
PQfname(const PGresult *res, int field_num)
1924
{
1925
	if (!check_field_number("PQfname", res, field_num))
1926
		return NULL;
1927 1928 1929 1930
	if (res->attDescs)
		return res->attDescs[field_num].name;
	else
		return NULL;
1931 1932 1933 1934 1935 1936
}

/*
   returns -1 on a bad field name
*/
int
Bruce Momjian's avatar
Bruce Momjian committed
1937
PQfnumber(const PGresult *res, const char *field_name)
1938
{
1939
	int			i;
Bruce Momjian's avatar
Bruce Momjian committed
1940
	char	   *field_case;
1941

1942 1943
	if (!res)
		return -1;
1944

1945 1946 1947 1948
	if (field_name == NULL ||
		field_name[0] == '\0' ||
		res->attDescs == NULL)
		return -1;
1949

Bruce Momjian's avatar
Bruce Momjian committed
1950 1951 1952 1953 1954 1955 1956
	field_case = strdup(field_name);
	if (*field_case == '"')
	{
		strcpy(field_case, field_case + 1);
		*(field_case + strlen(field_case) - 1) = '\0';
	}
	else
1957
		for (i = 0; field_case[i]; i++)
1958 1959
			if (isupper((unsigned char) field_case[i]))
				field_case[i] = tolower((unsigned char) field_case[i]);
Bruce Momjian's avatar
Bruce Momjian committed
1960

1961 1962
	for (i = 0; i < res->numAttributes; i++)
	{
1963
		if (strcmp(field_case, res->attDescs[i].name) == 0)
Bruce Momjian's avatar
Bruce Momjian committed
1964 1965
		{
			free(field_case);
1966
			return i;
Bruce Momjian's avatar
Bruce Momjian committed
1967
		}
1968
	}
Bruce Momjian's avatar
Bruce Momjian committed
1969
	free(field_case);
1970
	return -1;
1971 1972 1973
}

Oid
Bruce Momjian's avatar
Bruce Momjian committed
1974
PQftype(const PGresult *res, int field_num)
1975
{
1976
	if (!check_field_number("PQftype", res, field_num))
1977 1978
		return InvalidOid;
	if (res->attDescs)
1979
		return res->attDescs[field_num].typid;
1980 1981
	else
		return InvalidOid;
1982 1983
}

1984
int
Bruce Momjian's avatar
Bruce Momjian committed
1985
PQfsize(const PGresult *res, int field_num)
1986
{
1987
	if (!check_field_number("PQfsize", res, field_num))
Bruce Momjian's avatar
Bruce Momjian committed
1988
		return 0;
1989
	if (res->attDescs)
1990
		return res->attDescs[field_num].typlen;
1991 1992
	else
		return 0;
1993 1994
}

1995
int
Bruce Momjian's avatar
Bruce Momjian committed
1996
PQfmod(const PGresult *res, int field_num)
Bruce Momjian's avatar
Bruce Momjian committed
1997
{
1998
	if (!check_field_number("PQfmod", res, field_num))
Bruce Momjian's avatar
Bruce Momjian committed
1999 2000
		return 0;
	if (res->attDescs)
2001
		return res->attDescs[field_num].atttypmod;
Bruce Momjian's avatar
Bruce Momjian committed
2002 2003 2004 2005
	else
		return 0;
}

2006 2007
char *
PQcmdStatus(PGresult *res)
2008 2009 2010 2011
{
	if (!res)
		return NULL;
	return res->cmdStatus;
2012 2013 2014 2015
}

/*
   PQoidStatus -
2016 2017
	if the last command was an INSERT, return the oid string
	if not, return ""
2018
*/
2019
char *
Bruce Momjian's avatar
Bruce Momjian committed
2020
PQoidStatus(const PGresult *res)
2021
{
2022 2023 2024 2025

	/*
	 * This must be enough to hold the result. Don't laugh, this is better
	 * than what this function used to do.
2026 2027
	 */
	static char buf[24];
Bruce Momjian's avatar
Bruce Momjian committed
2028

2029
	size_t		len;
2030

Bruce Momjian's avatar
Bruce Momjian committed
2031
	if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
2032
		return "";
2033

Bruce Momjian's avatar
Bruce Momjian committed
2034 2035
	len = strspn(res->cmdStatus + 7, "0123456789");
	if (len > 23)
2036
		len = 23;
Bruce Momjian's avatar
Bruce Momjian committed
2037
	strncpy(buf, res->cmdStatus + 7, len);
2038
	buf[len] = '\0';
2039

Bruce Momjian's avatar
Bruce Momjian committed
2040 2041
	return buf;
}
2042

Bruce Momjian's avatar
Bruce Momjian committed
2043 2044
/*
  PQoidValue -
2045
		a perhaps preferable form of the above which just returns
Bruce Momjian's avatar
Bruce Momjian committed
2046 2047 2048 2049 2050
	an Oid type
*/
Oid
PQoidValue(const PGresult *res)
{
2051
	char	   *endptr = NULL;
2052
	unsigned long result;
2053

2054 2055
	if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
		return InvalidOid;
2056

2057 2058
	errno = 0;
	result = strtoul(res->cmdStatus + 7, &endptr, 10);
Bruce Momjian's avatar
Bruce Momjian committed
2059

2060 2061 2062 2063
	if (!endptr || (*endptr != ' ' && *endptr != '\0') || errno == ERANGE)
		return InvalidOid;
	else
		return (Oid) result;
2064
}
2065

2066 2067
/*
   PQcmdTuples -
2068 2069
	if the last command was an INSERT/UPDATE/DELETE, return number
	of inserted/affected tuples, if not, return ""
2070
*/
2071 2072
char *
PQcmdTuples(PGresult *res)
2073
{
2074
	char		noticeBuf[128];
2075

2076
	if (!res)
2077
		return "";
2078 2079 2080 2081 2082

	if (strncmp(res->cmdStatus, "INSERT", 6) == 0 ||
		strncmp(res->cmdStatus, "DELETE", 6) == 0 ||
		strncmp(res->cmdStatus, "UPDATE", 6) == 0)
	{
2083
		char	   *p = res->cmdStatus + 6;
2084 2085 2086

		if (*p == 0)
		{
2087
			if (res->noticeHook)
2088
			{
2089
				sprintf(noticeBuf,
2090 2091
						"PQcmdTuples (%s) -- bad input from server\n",
						res->cmdStatus);
2092
				DONOTICE(res, noticeBuf);
2093
			}
2094
			return "";
2095 2096 2097
		}
		p++;
		if (*(res->cmdStatus) != 'I')	/* UPDATE/DELETE */
2098
			return p;
2099 2100 2101 2102
		while (*p != ' ' && *p)
			p++;				/* INSERT: skip oid */
		if (*p == 0)
		{
2103
			if (res->noticeHook)
2104
			{
2105
				sprintf(noticeBuf,
Bruce Momjian's avatar
Bruce Momjian committed
2106
					 "PQcmdTuples (INSERT) -- there's no # of tuples\n");
2107
				DONOTICE(res, noticeBuf);
2108
			}
2109
			return "";
2110 2111
		}
		p++;
2112
		return p;
2113 2114
	}
	return "";
2115 2116 2117 2118
}

/*
   PQgetvalue:
2119
	return the value of field 'field_num' of row 'tup_num'
2120

2121 2122 2123
	If res is binary, then the value returned is NOT a null-terminated
	ASCII string, but the binary representation in the server's native
	format.
2124

2125
	if res is not binary, a null-terminated ASCII string is returned.
2126
*/
2127
char *
Bruce Momjian's avatar
Bruce Momjian committed
2128
PQgetvalue(const PGresult *res, int tup_num, int field_num)
2129
{
2130
	if (!check_tuple_field_number("PQgetvalue", res, tup_num, field_num))
2131 2132
		return NULL;
	return res->tuples[tup_num][field_num].value;
2133 2134 2135
}

/* PQgetlength:
2136 2137
	 returns the length of a field value in bytes.	If res is binary,
	 i.e. a result of a binary portal, then the length returned does
2138 2139
	 NOT include the size field of the varlena.  (The data returned
	 by PQgetvalue doesn't either.)
2140 2141
*/
int
Bruce Momjian's avatar
Bruce Momjian committed
2142
PQgetlength(const PGresult *res, int tup_num, int field_num)
2143
{
2144
	if (!check_tuple_field_number("PQgetlength", res, tup_num, field_num))
Bruce Momjian's avatar
Bruce Momjian committed
2145
		return 0;
2146 2147 2148 2149 2150
	if (res->tuples[tup_num][field_num].len != NULL_LEN)
		return res->tuples[tup_num][field_num].len;
	else
		return 0;
}
Marc G. Fournier's avatar
Marc G. Fournier committed
2151 2152

/* PQgetisnull:
2153
	 returns the null status of a field value.
Marc G. Fournier's avatar
Marc G. Fournier committed
2154 2155
*/
int
Bruce Momjian's avatar
Bruce Momjian committed
2156
PQgetisnull(const PGresult *res, int tup_num, int field_num)
Marc G. Fournier's avatar
Marc G. Fournier committed
2157
{
2158
	if (!check_tuple_field_number("PQgetisnull", res, tup_num, field_num))
Bruce Momjian's avatar
Bruce Momjian committed
2159
		return 1;				/* pretend it is null */
2160 2161 2162 2163
	if (res->tuples[tup_num][field_num].len == NULL_LEN)
		return 1;
	else
		return 0;
Bruce Momjian's avatar
Bruce Momjian committed
2164
}
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185

/* PQsetnonblocking:
	 sets the PGconn's database connection non-blocking if the arg is TRUE
	 or makes it non-blocking if the arg is FALSE, this will not protect
	 you from PQexec(), you'll only be safe when using the non-blocking
	 API
	 Needs to be called only on a connected database connection.
*/

int
PQsetnonblocking(PGconn *conn, int arg)
{

	arg = (arg == TRUE) ? 1 : 0;
	/* early out if the socket is already in the state requested */
	if (arg == conn->nonblocking)
		return (0);

	/*
	 * to guarantee constancy for flushing/query/result-polling behavior
	 * we need to flush the send queue at this point in order to guarantee
2186 2187 2188
	 * proper behavior. this is ok because either they are making a
	 * transition _from_ or _to_ blocking mode, either way we can block
	 * them.
2189 2190
	 */
	/* if we are going from blocking to non-blocking flush here */
2191
	if (pqFlush(conn))
2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215
		return (-1);

	conn->nonblocking = arg;

	return (0);
}

/* return the blocking status of the database connection, TRUE == nonblocking,
	 FALSE == blocking
*/
int
PQisnonblocking(const PGconn *conn)
{

	return (pqIsnonblocking(conn));
}

/* try to force data out, really only useful for non-blocking users */
int
PQflush(PGconn *conn)
{

	return (pqFlush(conn));
}