1 /*
2  * Copyright (c) 2009 - 2020, Micro Systems Marc Balmer, CH-5073 Gipf-Oberfrick
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Micro Systems Marc Balmer nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /* PostgreSQL extension module (using Lua) */
29 
30 #ifdef __APPLE__
31 #include <libkern/OSByteOrder.h>
32 #define htobe64(x) OSSwapHostToBigInt64(x)
33 #elif __FreeBSD__
34 #include <sys/endian.h>
35 #elif __linux__
36 #include <endian.h>
37 #endif
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <string.h>
41 
42 #include <libpq-fe.h>
43 #include <libpq/libpq-fs.h>
44 #include <pg_config.h>
45 
46 #include <lua.h>
47 #include <lauxlib.h>
48 #include <lualib.h>
49 
50 #include "luapgsql.h"
51 
52 #if LUA_VERSION_NUM < 502
53 #define lua_setuservalue lua_setfenv
54 #define lua_getuservalue lua_getfenv
55 
56 static void
luaL_setmetatable(lua_State * L,const char * tname)57 luaL_setmetatable(lua_State *L, const char *tname)
58 {
59 	luaL_getmetatable(L, tname);
60 	lua_setmetatable(L, -2);
61 }
62 #endif
63 
64 /*
65  * Garbage collected memory
66  */
67 static void *
gcmalloc(lua_State * L,size_t size)68 gcmalloc(lua_State *L, size_t size)
69 {
70 	void **p;
71 
72 	p = lua_newuserdata(L, size);
73 	*p = NULL;
74 	luaL_setmetatable(L, GCMEM_METATABLE);
75 	return p;
76 }
77 
78 /* Memory can be free'ed immediately or left to the garbage collector */
79 static void
gcfree(void * p)80 gcfree(void *p)
81 {
82 	void **mem = (void **)p;
83 	PQfreemem(*mem);
84 	*mem = NULL;
85 }
86 
87 static int
gcmem_clear(lua_State * L)88 gcmem_clear(lua_State *L)
89 {
90 	void **p = luaL_checkudata(L, 1, GCMEM_METATABLE);
91 	PQfreemem(*p);
92 	*p = NULL;
93 	return 0;
94 }
95 
96 /*
97  * Create a new connection object with a uservalue table
98  */
99 static PGconn **
pgsql_conn_new(lua_State * L)100 pgsql_conn_new(lua_State *L) {
101 	PGconn **data;
102 
103 	data = lua_newuserdata(L, sizeof(PGconn *));
104 	*data = NULL;
105 	lua_newtable(L);
106 	lua_setuservalue(L, -2);
107 	luaL_setmetatable(L, CONN_METATABLE);
108 	return data;
109 }
110 
111 /*
112  * Database Connection Control Functions
113  */
114 static int
pgsql_connectdb(lua_State * L)115 pgsql_connectdb(lua_State *L)
116 {
117 	PGconn **data;
118 	const char *cstr;
119 
120 	cstr = luaL_checkstring(L, 1);
121 	data = pgsql_conn_new(L);
122 
123 	*data = PQconnectdb(cstr);
124 	if (*data == NULL)
125 		lua_pushnil(L);
126 	return 1;
127 }
128 
129 static int
pgsql_connectStart(lua_State * L)130 pgsql_connectStart(lua_State *L)
131 {
132 	PGconn **data;
133 	const char *cstr;
134 
135 	cstr = luaL_checkstring(L, 1);
136 	data = pgsql_conn_new(L);
137 	*data = PQconnectStart(cstr);
138 
139 	if (*data == NULL)
140 		lua_pushnil(L);
141 	return 1;
142 }
143 
144 static PGconn *
pgsql_conn(lua_State * L,int n)145 pgsql_conn(lua_State *L, int n)
146 {
147 	PGconn **data;
148 
149 	data = luaL_checkudata(L, n, CONN_METATABLE);
150 	luaL_argcheck(L, *data != NULL, n, "database connection is finished");
151 	return *data;
152 }
153 
154 static int
pgsql_connectPoll(lua_State * L)155 pgsql_connectPoll(lua_State *L)
156 {
157 	lua_pushinteger(L, PQconnectPoll(pgsql_conn(L, 1)));
158 	return 1;
159 }
160 
161 static int
pgsql_libVersion(lua_State * L)162 pgsql_libVersion(lua_State *L)
163 {
164 	lua_pushinteger(L, PQlibVersion());
165 	return 1;
166 }
167 
168 #if PG_VERSION_NUM >= 90100
169 static int
pgsql_ping(lua_State * L)170 pgsql_ping(lua_State *L)
171 {
172 	lua_pushinteger(L, PQping(luaL_checkstring(L, 1)));
173 	return 1;
174 }
175 #endif
176 
177 static int
pgsql_encryptPassword(lua_State * L)178 pgsql_encryptPassword(lua_State *L)
179 {
180 	char const **pw;
181 	const char *passwd, *user;
182 
183 	passwd = luaL_checkstring(L, 1);
184 	user = luaL_checkstring(L, 2);
185 	pw = gcmalloc(L, sizeof(char *));
186 	*pw = PQencryptPassword(passwd, user);
187 	lua_pushstring(L, *pw);
188 	gcfree(pw);
189 	return 1;
190 }
191 
192 static int
pgsql_unescapeBytea(lua_State * L)193 pgsql_unescapeBytea(lua_State *L)
194 {
195 	unsigned char **p;
196 	size_t len;
197 	const char *bytea;
198 
199 	bytea = luaL_checkstring(L, 1);
200 	p = gcmalloc(L, sizeof(char *));
201 	*p = PQunescapeBytea((const unsigned char *)bytea, &len);
202 	if (*p == NULL)
203 		lua_pushnil(L);
204 	else {
205 		lua_pushlstring(L, (const char *)*p, len);
206 		gcfree(p);
207 	}
208 	return 1;
209 }
210 
211 static int
pgsql_initOpenSSL(lua_State * L)212 pgsql_initOpenSSL(lua_State *L)
213 {
214 	PQinitOpenSSL(lua_toboolean(L, 1), lua_toboolean(L, 2));
215 	return 0;
216 }
217 
218 static int
conn_finish(lua_State * L)219 conn_finish(lua_State *L)
220 {
221 	PGconn **conn;
222 
223 	conn = luaL_checkudata(L, 1, CONN_METATABLE);
224 	if (*conn) {
225 		/*
226 		 * Check in the registry if a value has been stored at
227 		 * index '*conn'; if a value is found, don't close the
228 		 * connection.
229 		 * This mechanism can be used when the PostgreSQL connection
230 		 * object is provided to Lua from a C program that wants to
231 		 * ensure the connections stays open, even when the Lua
232 		 * program has terminated.
233 		 * To prevent the closing of the connection, use the following
234 		 * code to set a value in the registry at index '*conn' just
235 		 * before handing the connection object to Lua:
236 		 *
237 		 * PGconn *conn, **data;
238 		 *
239 		 * conn = PQconnectdb(...);
240 		 * data = lua_newuserdata(L, sizeof(PGconn *));
241 		 * *data = conn;
242 		 * lua_pushlightuserdata(L, *data);
243 		 * lua_pushboolean(L, 1);
244 		 * lua_settable(L, LUA_REGISTRYINDEX);
245 		 */
246 		lua_pushlightuserdata(L, *conn);
247 		lua_gettable(L, LUA_REGISTRYINDEX);
248 		if (lua_isnil(L, -1)) {
249 			PQfinish(*conn);
250 			*conn = NULL;
251 			/* clean out now invalidated keys from uservalue */
252 			lua_getuservalue(L, 1);
253 			lua_pushnil(L);
254 			lua_setfield(L, -2, "trace_file");
255 		}
256 	}
257 	return 0;
258 }
259 
260 static int
conn_reset(lua_State * L)261 conn_reset(lua_State *L)
262 {
263 	PQreset(pgsql_conn(L, 1));
264 	return 0;
265 }
266 
267 static int
conn_resetStart(lua_State * L)268 conn_resetStart(lua_State *L)
269 {
270 	lua_pushboolean(L, PQresetStart(pgsql_conn(L, 1)));
271 	return 1;
272 }
273 
274 static int
conn_resetPoll(lua_State * L)275 conn_resetPoll(lua_State *L)
276 {
277 	lua_pushinteger(L, PQresetPoll(pgsql_conn(L, 1)));
278 	return 1;
279 }
280 
281 /*
282  * Connection status functions
283  */
284 static int
conn_db(lua_State * L)285 conn_db(lua_State *L)
286 {
287 	lua_pushstring(L, PQdb(pgsql_conn(L, 1)));
288 	return 1;
289 }
290 
291 static int
conn_user(lua_State * L)292 conn_user(lua_State *L)
293 {
294 	lua_pushstring(L, PQuser(pgsql_conn(L, 1)));
295 	return 1;
296 }
297 
298 static int
conn_pass(lua_State * L)299 conn_pass(lua_State *L)
300 {
301 	lua_pushstring(L, PQpass(pgsql_conn(L, 1)));
302 	return 1;
303 }
304 
305 static int
conn_host(lua_State * L)306 conn_host(lua_State *L)
307 {
308 	lua_pushstring(L, PQhost(pgsql_conn(L, 1)));
309 	return 1;
310 }
311 
312 static int
conn_port(lua_State * L)313 conn_port(lua_State *L)
314 {
315 	lua_pushstring(L, PQport(pgsql_conn(L, 1)));
316 	return 1;
317 }
318 
319 static int
conn_tty(lua_State * L)320 conn_tty(lua_State *L)
321 {
322 	lua_pushstring(L, PQtty(pgsql_conn(L, 1)));
323 	return 1;
324 }
325 
326 static int
conn_options(lua_State * L)327 conn_options(lua_State *L)
328 {
329 	lua_pushstring(L, PQoptions(pgsql_conn(L, 1)));
330 	return 1;
331 }
332 
333 static int
conn_status(lua_State * L)334 conn_status(lua_State *L)
335 {
336 	PGconn **conn;
337 
338 	conn = luaL_checkudata(L, 1, CONN_METATABLE);
339 	lua_pushinteger(L, PQstatus(*conn));
340 	return 1;
341 }
342 
343 static int
conn_transactionStatus(lua_State * L)344 conn_transactionStatus(lua_State *L)
345 {
346 	lua_pushinteger(L, PQtransactionStatus(pgsql_conn(L, 1)));
347 	return 1;
348 }
349 
350 static int
conn_parameterStatus(lua_State * L)351 conn_parameterStatus(lua_State *L)
352 {
353 	const char *status;
354 
355 	status = PQparameterStatus(pgsql_conn(L, 1), luaL_checkstring(L, 2));
356 	if (status == NULL)
357 		lua_pushnil(L);
358 	else
359 		lua_pushstring(L, status);
360 	return 1;
361 }
362 
363 static int
conn_protocolVersion(lua_State * L)364 conn_protocolVersion(lua_State *L)
365 {
366 	lua_pushinteger(L, PQprotocolVersion(pgsql_conn(L, 1)));
367 	return 1;
368 }
369 
370 static int
conn_serverVersion(lua_State * L)371 conn_serverVersion(lua_State *L)
372 {
373 	lua_pushinteger(L, PQserverVersion(pgsql_conn(L, 1)));
374 	return 1;
375 }
376 
377 static int
conn_errorMessage(lua_State * L)378 conn_errorMessage(lua_State *L)
379 {
380 	lua_pushstring(L, PQerrorMessage(pgsql_conn(L, 1)));
381 	return 1;
382 }
383 
384 static int
conn_socket(lua_State * L)385 conn_socket(lua_State *L)
386 {
387 	int fd;
388 
389 	fd = PQsocket(pgsql_conn(L, 1));
390 	if (fd >= 0)
391 		lua_pushinteger(L, fd);
392 	else
393 		lua_pushnil(L);
394 	return 1;
395 }
396 
397 static int
conn_backendPID(lua_State * L)398 conn_backendPID(lua_State *L)
399 {
400 	lua_pushinteger(L, PQbackendPID(pgsql_conn(L, 1)));
401 	return 1;
402 }
403 
404 static int
conn_connectionNeedsPassword(lua_State * L)405 conn_connectionNeedsPassword(lua_State *L)
406 {
407 	lua_pushboolean(L, PQconnectionNeedsPassword(pgsql_conn(L, 1)));
408 	return 1;
409 }
410 
411 static int
conn_connectionUsedPassword(lua_State * L)412 conn_connectionUsedPassword(lua_State *L)
413 {
414 	lua_pushboolean(L, PQconnectionUsedPassword(pgsql_conn(L, 1)));
415 	return 1;
416 }
417 
418 #if PG_VERSION_NUM >= 90500
419 static int
conn_sslInUse(lua_State * L)420 conn_sslInUse(lua_State *L)
421 {
422 	lua_pushboolean(L, PQsslInUse(pgsql_conn(L, 1)));
423 	return 1;
424 }
425 
426 static int
conn_sslAttribute(lua_State * L)427 conn_sslAttribute(lua_State *L)
428 {
429 	lua_pushstring(L,
430 		PQsslAttribute(pgsql_conn(L, 1), luaL_checkstring(L, 2)));
431 	return 1;
432 }
433 
434 static int
conn_sslAttributeNames(lua_State * L)435 conn_sslAttributeNames(lua_State *L)
436 {
437 	const char * const *attribNames;
438 	int k;
439 
440 	attribNames = PQsslAttributeNames(pgsql_conn(L, 1));
441 	lua_newtable(L);
442 	for (k = 1; *attribNames; k++, attribNames++) {
443 		lua_pushinteger(L, k);
444 		lua_pushstring(L, *attribNames);
445 		lua_settable(L, -3);
446 	}
447 	return 1;
448 }
449 #endif
450 
451 /*
452  * Command Execution Functions
453  */
454 static int
conn_exec(lua_State * L)455 conn_exec(lua_State *L)
456 {
457 	PGconn *conn;
458 	PGresult **res;
459 	const char *command;
460 
461 	conn = pgsql_conn(L, 1);
462 	command = luaL_checkstring(L, 2);
463 
464 	res = lua_newuserdata(L, sizeof(PGresult *));
465 	*res = PQexec(conn, command);
466 	if (*res == NULL)
467 		lua_pushnil(L);
468 	else
469 		luaL_setmetatable(L, RES_METATABLE);
470 	return 1;
471 }
472 
473 static void
get_param(lua_State * L,int t,int n,Oid * paramTypes,char ** paramValues,int * paramLengths,int * paramFormats)474 get_param(lua_State *L, int t, int n, Oid *paramTypes, char **paramValues,
475     int *paramLengths, int *paramFormats)
476 {
477 	switch (lua_type(L, t)) {
478 	case LUA_TBOOLEAN:
479 		if (paramTypes != NULL)
480 			paramTypes[n] = BOOLOID;
481 		if (paramValues != NULL) {
482 			paramValues[n] = lua_newuserdata(L, sizeof(char));
483 			*(char *)paramValues[n] = lua_toboolean(L, t);
484 			paramLengths[n] = 1;
485 		}
486 		if (paramFormats != NULL)
487 			paramFormats[n] = 1;
488 		break;
489 	case LUA_TNUMBER:
490 		if (paramTypes != NULL) {
491 #if LUA_VERSION_NUM >= 503
492 			if (lua_isinteger(L, t))
493 				paramTypes[n] = INT8OID;
494 			else
495 #endif
496 				paramTypes[n] = FLOAT8OID;
497 		}
498 		if (paramValues != NULL) {
499 			union {
500 				double v;
501 				uint64_t i;
502 			} swap;
503 
504 #if LUA_VERSION_NUM >= 503
505 			if (lua_isinteger(L, t))
506 				swap.i = lua_tointeger(L, t);
507 			else
508 #endif
509 				swap.v = lua_tonumber(L, t);
510 			paramValues[n] = lua_newuserdata(L, sizeof(uint64_t));
511 			*(uint64_t *)paramValues[n] = htobe64(swap.i);
512 			paramLengths[n] = sizeof(uint64_t);
513 		}
514 		if (paramFormats != NULL)
515 			paramFormats[n] = 1;
516 		break;
517 	case LUA_TSTRING:
518 		if (paramTypes != NULL)
519 			paramTypes[n] = TEXTOID;
520 		if (paramValues != NULL) {
521 			const char *s;
522 			size_t len;
523 
524 			s = lua_tolstring(L, t, &len);
525 			paramValues[n] = lua_newuserdata(L, len + 1);
526 			/*
527 			 * lua_tolstring returns a string with '\0' after
528 			 * the last character.
529 			 */
530 			memcpy(paramValues[n], s, len + 1);
531 		}
532 		if (paramFormats != NULL)
533 			paramFormats[n] = 0;
534 		break;
535 	case LUA_TNIL:
536 		if (paramTypes != NULL)
537 			paramTypes[n] = 0;
538 		if (paramValues != NULL)
539 			paramValues[n] = NULL;
540 		if (paramFormats != NULL)
541 			paramFormats[n] = 0;
542 		break;
543 	default:
544 		luaL_error(L, "unsupported PostgreSQL parameter type %s ("
545 		    "use table.unpack() for table types)", luaL_typename(L, t));
546 		/* NOTREACHED */
547 	}
548 }
549 
550 static int
conn_execParams(lua_State * L)551 conn_execParams(lua_State *L)
552 {
553 	PGconn *conn;
554 	PGresult **res;
555 	Oid *paramTypes;
556 	char **paramValues;
557 	const char *command;
558 	int n, nParams, *paramLengths, *paramFormats;
559 
560 	conn = pgsql_conn(L, 1);
561 	command = luaL_checkstring(L, 2);
562 
563 	nParams = lua_gettop(L) - 2;	/* subtract connection and command */
564 
565 	if (nParams > 65535)
566 		luaL_error(L, "number of parameters must not exceed 65535");
567 
568 	if (nParams) {
569 		luaL_checkstack(L, 4 + nParams, "out of stack space");
570 
571 		paramTypes = lua_newuserdata(L, nParams * sizeof(Oid));
572 		paramValues = lua_newuserdata(L, nParams * sizeof(char *));
573 		paramLengths = lua_newuserdata(L, nParams * sizeof(int));
574 		paramFormats = lua_newuserdata(L, nParams * sizeof(int));
575 
576 		for (n = 0; n < nParams; n++)
577 			get_param(L, 3 + n, n, paramTypes, paramValues,
578 			    paramLengths, paramFormats);
579 	} else {
580 		paramTypes = NULL;
581 		paramValues = NULL;
582 		paramLengths = NULL;
583 		paramFormats = NULL;
584 	}
585 	luaL_checkstack(L, 2, "out of stack space");
586 	res = lua_newuserdata(L, sizeof(PGresult *));
587 	*res = PQexecParams(conn, command, nParams, paramTypes,
588 	    (const char * const*)paramValues, paramLengths, paramFormats, 0);
589 	if (*res == NULL)
590 		lua_pushnil(L);
591 	else
592 		luaL_setmetatable(L, RES_METATABLE);
593 	return 1;
594 }
595 
596 static int
conn_prepare(lua_State * L)597 conn_prepare(lua_State *L)
598 {
599 	PGconn *conn;
600 	PGresult **res;
601 	Oid *paramTypes;
602 	const char *command, *name;
603 	int n, nParams;
604 
605 	conn = pgsql_conn(L, 1);
606 	command = luaL_checkstring(L, 2);
607 	name = luaL_checkstring(L, 3);
608 
609 	nParams = lua_gettop(L) - 3;	/* subtract connection, name, command */
610 
611 	if (nParams > 65535)
612 		luaL_error(L, "number of parameters must not exceed 65535");
613 
614 	if (nParams) {
615 		paramTypes = lua_newuserdata(L, nParams * sizeof(Oid));
616 
617 		for (n = 0; n < nParams; n++)
618 			get_param(L, 4 + n, n, paramTypes, NULL, NULL, NULL);
619 	} else
620 		paramTypes = NULL;
621 
622 	res = lua_newuserdata(L, sizeof(PGresult *));
623 	*res = PQprepare(conn, command, name, nParams, paramTypes);
624 	if (*res == NULL)
625 		lua_pushnil(L);
626 	else
627 		luaL_setmetatable(L, RES_METATABLE);
628 	return 1;
629 }
630 
631 static int
conn_execPrepared(lua_State * L)632 conn_execPrepared(lua_State *L)
633 {
634 	PGconn *conn;
635 	PGresult **res;
636 	char **paramValues;
637 	const char *command;
638 	int n, nParams, *paramLengths, *paramFormats;
639 
640 	conn = pgsql_conn(L, 1);
641 	command = luaL_checkstring(L, 2);
642 
643 	nParams = lua_gettop(L) - 2;	/* subtract connection and name */
644 
645 	if (nParams > 65535)
646 		luaL_error(L, "number of parameters must not exceed 65535");
647 
648 	if (nParams) {
649 		luaL_checkstack(L, 3 + nParams, "out of stack space");
650 
651 		paramValues = lua_newuserdata(L, nParams * sizeof(char *));
652 		paramLengths = lua_newuserdata(L, nParams * sizeof(int));
653 		paramFormats = lua_newuserdata(L, nParams * sizeof(int));
654 
655 		for (n = 0; n < nParams; n++)
656 			get_param(L, 3 + n, n, NULL, paramValues, paramLengths,
657 			    paramFormats);
658 	} else {
659 		paramValues = NULL;
660 		paramLengths = NULL;
661 		paramFormats = NULL;
662 	}
663 	luaL_checkstack(L, 2, "out of stack space");
664 
665 	res = lua_newuserdata(L, sizeof(PGresult *));
666 	*res = PQexecPrepared(conn, command, nParams,
667 	    (const char * const*)paramValues, paramLengths, paramFormats, 0);
668 	if (*res == NULL)
669 		lua_pushnil(L);
670 	else
671 		luaL_setmetatable(L, RES_METATABLE);
672 	return 1;
673 }
674 
675 static int
conn_describePrepared(lua_State * L)676 conn_describePrepared(lua_State *L)
677 {
678 	PGconn *conn;
679 	PGresult **res;
680 	const char *name;
681 
682 	conn = pgsql_conn(L, 1);
683 	name = luaL_checkstring(L, 2);
684 
685 	res = lua_newuserdata(L, sizeof(PGresult *));
686 	*res = PQdescribePrepared(conn, name);
687 	if (*res == NULL)
688 		lua_pushnil(L);
689 	else
690 		luaL_setmetatable(L, RES_METATABLE);
691 	return 1;
692 }
693 
694 static int
conn_describePortal(lua_State * L)695 conn_describePortal(lua_State *L)
696 {
697 	PGconn *conn;
698 	PGresult **res;
699 	const char *name;
700 
701 	conn = pgsql_conn(L, 1);
702 	name = luaL_checkstring(L, 2);
703 
704 	res = lua_newuserdata(L, sizeof(PGresult *));
705 	*res = PQdescribePortal(conn, name);
706 	if (*res == NULL)
707 		lua_pushnil(L);
708 	else
709 		luaL_setmetatable(L, RES_METATABLE);
710 	return 1;
711 }
712 
713 static int
conn_escapeString(lua_State * L)714 conn_escapeString(lua_State *L)
715 {
716 	PGconn *d;
717 	size_t len;
718 	char *buf;
719 	const char *str;
720 	int error;
721 
722 	d = pgsql_conn(L, 1);
723 
724 	str = lua_tolstring(L, 2, &len);
725 	if (str == NULL) {
726 		lua_pushnil(L);
727 		return 1;
728 	}
729 	buf = lua_newuserdata(L, 2 * (len + 1));
730 
731 	PQescapeStringConn(d, buf, str, len, &error);
732 	if (!error)
733 		lua_pushstring(L, buf);
734 	else
735 		lua_pushnil(L);
736 	return 1;
737 }
738 
739 static int
conn_escapeLiteral(lua_State * L)740 conn_escapeLiteral(lua_State *L)
741 {
742 	const char *s;
743 	char **p;
744 	PGconn *d;
745 	size_t len;
746 
747 	d = pgsql_conn(L, 1);
748 	s = luaL_checklstring(L, 2, &len);
749 	p = gcmalloc(L, sizeof(char *));
750 	*p = PQescapeLiteral(d, s, len);
751 	lua_pushstring(L, *p);
752 	gcfree(p);
753 	return 1;
754 }
755 
756 static int
conn_escapeIdentifier(lua_State * L)757 conn_escapeIdentifier(lua_State *L)
758 {
759 	const char *s;
760 	char  **p;
761 	PGconn *d;
762 	size_t len;
763 
764 	d = pgsql_conn(L, 1);
765 	s = luaL_checklstring(L, 2, &len);
766 	p = gcmalloc(L, sizeof(char *));
767 	*p = PQescapeIdentifier(d, s, len);
768 	lua_pushstring(L, *p);
769 	gcfree(p);
770 	return 1;
771 }
772 
773 static int
conn_escapeBytea(lua_State * L)774 conn_escapeBytea(lua_State *L)
775 {
776 	unsigned char **p;
777 	const unsigned char *s;
778 	PGconn *d;
779 	size_t from_length, to_length;
780 
781 	d = pgsql_conn(L, 1);
782 	s = (const unsigned char *)luaL_checklstring(L, 2, &from_length);
783 	p = gcmalloc(L, sizeof(char *));
784 	*p = PQescapeByteaConn(d, s, from_length, &to_length);
785 	if (*p) {
786 		lua_pushlstring(L, (const char *)*p, to_length - 1);
787 		gcfree(p);
788 	} else
789 		lua_pushnil(L);
790 	return 1;
791 }
792 
793 /*
794  * Asynchronous Command Execution Functions
795  */
796 static int
conn_sendQuery(lua_State * L)797 conn_sendQuery(lua_State *L)
798 {
799 	lua_pushboolean(L, PQsendQuery(pgsql_conn(L, 1),
800 	    luaL_checkstring(L, 2)));
801 	return 1;
802 }
803 
804 static int
conn_sendQueryParams(lua_State * L)805 conn_sendQueryParams(lua_State *L)
806 {
807 	PGconn *conn;
808 	Oid *paramTypes;
809 	char **paramValues;
810 	const char *command;
811 	int n, nParams, *paramLengths, *paramFormats;
812 
813 	conn = pgsql_conn(L, 1);
814 	command = luaL_checkstring(L, 2);
815 
816 	nParams = lua_gettop(L) - 2;	/* subtract connection and command */
817 
818 	if (nParams) {
819 		luaL_checkstack(L, 4 + nParams, "out of stack space");
820 
821 		paramTypes = lua_newuserdata(L, nParams * sizeof(Oid));
822 		paramValues = lua_newuserdata(L, nParams * sizeof(char *));
823 		paramLengths = lua_newuserdata(L, nParams * sizeof(int));
824 		paramFormats = lua_newuserdata(L, nParams * sizeof(int));
825 
826 		for (n = 0; n < nParams; n++)
827 			get_param(L, 3 + n, n, paramTypes, paramValues,
828 			   paramLengths, paramFormats);
829 	} else {
830 		paramTypes = NULL;
831 		paramValues = NULL;
832 		paramLengths = NULL;
833 		paramFormats = NULL;
834 	}
835 	lua_pushboolean(L,
836 	    PQsendQueryParams(conn, command, nParams, paramTypes,
837 	    (const char * const*)paramValues, paramLengths, paramFormats, 0));
838 	return 1;
839 }
840 
841 static int
conn_sendPrepare(lua_State * L)842 conn_sendPrepare(lua_State *L)
843 {
844 	PGconn *conn;
845 	Oid *paramTypes;
846 	const char *command, *name;
847 	int n, nParams;
848 
849 	conn = pgsql_conn(L, 1);
850 	command = luaL_checkstring(L, 2);
851 	name = luaL_checkstring(L, 3);
852 
853 	nParams = lua_gettop(L) - 3;	/* subtract connection, name, command */
854 
855 	if (nParams) {
856 		paramTypes = lua_newuserdata(L, nParams * sizeof(Oid));
857 
858 		for (n = 0; n < nParams; n++)
859 			get_param(L, 4 + n, n, paramTypes, NULL, NULL, NULL);
860 	} else
861 		paramTypes = NULL;
862 	lua_pushboolean(L,
863 	    PQsendPrepare(conn, command, name, nParams, paramTypes));
864 	return 1;
865 }
866 
867 static int
conn_sendQueryPrepared(lua_State * L)868 conn_sendQueryPrepared(lua_State *L)
869 {
870 	PGconn *conn;
871 	char **paramValues;
872 	const char *name;
873 	int n, nParams, *paramLengths, *paramFormats;
874 
875 	conn = pgsql_conn(L, 1);
876 	name = luaL_checkstring(L, 2);
877 
878 	nParams = lua_gettop(L) - 2;	/* subtract connection and name */
879 
880 	if (nParams) {
881 		luaL_checkstack(L, 3 + nParams, "out of stack space");
882 
883 		paramValues = lua_newuserdata(L, nParams * sizeof(char *));
884 		paramLengths = lua_newuserdata(L, nParams * sizeof(int));
885 		paramFormats = lua_newuserdata(L, nParams * sizeof(int));
886 
887 		for (n = 0; n < nParams; n++)
888 			get_param(L, 3 + n, n, NULL, paramValues, paramLengths,
889 			    paramFormats);
890 	} else {
891 		paramValues = NULL;
892 		paramLengths = NULL;
893 		paramFormats = NULL;
894 	}
895 	lua_pushboolean(L,
896 	    PQsendQueryPrepared(conn, name, nParams,
897 	    (const char * const*)paramValues, paramLengths, paramFormats, 0));
898 	return 1;
899 }
900 
901 static int
conn_sendDescribePrepared(lua_State * L)902 conn_sendDescribePrepared(lua_State *L)
903 {
904 	lua_pushboolean(L,
905 	    PQsendDescribePrepared(pgsql_conn(L, 1), luaL_checkstring(L, 2)));
906 	return 1;
907 }
908 
909 static int
conn_sendDescribePortal(lua_State * L)910 conn_sendDescribePortal(lua_State *L)
911 {
912 	lua_pushboolean(L,
913 	    PQsendDescribePortal(pgsql_conn(L, 1), luaL_checkstring(L, 2)));
914 	return 1;
915 }
916 
917 static int
conn_getResult(lua_State * L)918 conn_getResult(lua_State *L)
919 {
920 	PGresult *r, **res;
921 
922 	r = PQgetResult(pgsql_conn(L, 1));
923 	if (r == NULL)
924 		lua_pushnil(L);
925 	else {
926 		res = lua_newuserdata(L, sizeof(PGresult *));
927 		*res = r;
928 		luaL_setmetatable(L, RES_METATABLE);
929 	}
930 	return 1;
931 }
932 
933 static int
conn_cancel(lua_State * L)934 conn_cancel(lua_State *L)
935 {
936 	PGconn *d;
937 	PGcancel *cancel;
938 	char errbuf[256];
939 	int res = 1;
940 
941 	d = pgsql_conn(L, 1);
942 	cancel = PQgetCancel(d);
943 	if (cancel != NULL) {
944 		res = PQcancel(cancel, errbuf, sizeof errbuf);
945 		if (!res) {
946 			lua_pushboolean(L, 0);
947 			lua_pushstring(L, errbuf);
948 		} else
949 			lua_pushboolean(L, 1);
950 		PQfreeCancel(cancel);
951 	} else
952 		lua_pushboolean(L, 0);
953 	return res == 1 ? 1 : 2;
954 }
955 
956 #if PG_VERSION_NUM >= 90200
957 static int
conn_setSingleRowMode(lua_State * L)958 conn_setSingleRowMode(lua_State *L)
959 {
960 	lua_pushboolean(L, PQsetSingleRowMode(pgsql_conn(L, 1)));
961 	return 1;
962 }
963 #endif
964 
965 /*
966  * Asynchronous Notification Functions
967  */
968 static int
conn_notifies(lua_State * L)969 conn_notifies(lua_State *L)
970 {
971 	PGnotify **notify, *n;
972 
973 	n = PQnotifies(pgsql_conn(L, 1));
974 	if (n == NULL)
975 		lua_pushnil(L);
976 	else {
977 		notify = lua_newuserdata(L, sizeof(PGnotify *));
978 		*notify = n;
979 		luaL_setmetatable(L, NOTIFY_METATABLE);
980 	}
981 	return 1;
982 }
983 
984 /*
985  * Commands associated with the COPY command
986  */
987 static int
conn_putCopyData(lua_State * L)988 conn_putCopyData(lua_State *L)
989 {
990 	const char *data;
991 	size_t len;
992 	int r;
993 
994 	data = luaL_checklstring(L, 2, &len);
995 	r = PQputCopyData(pgsql_conn(L, 1), data, len);
996 
997 	if (r != -1)
998 		lua_pushboolean(L, r);
999 	else
1000 		lua_pushnil(L);
1001 	return 1;
1002 }
1003 
1004 static int
conn_putCopyEnd(lua_State * L)1005 conn_putCopyEnd(lua_State *L)
1006 {
1007 	PGconn *conn;
1008 	int r;
1009 
1010 	conn = pgsql_conn(L, 1);
1011 	r = PQputCopyEnd(conn, luaL_optstring(L, 2, NULL));
1012 
1013 	if (r != -1)
1014 		lua_pushboolean(L, r);
1015 	else
1016 		lua_pushnil(L);
1017 	return 1;
1018 }
1019 
1020 static int
conn_getCopyData(lua_State * L)1021 conn_getCopyData(lua_State *L)
1022 {
1023 	PGconn *conn;
1024 	int async, len;
1025 	char **data;
1026 
1027 	conn = pgsql_conn(L, 1);
1028 	async = lua_toboolean(L, 2);
1029 	data = gcmalloc(L, sizeof(char *));
1030 	len = PQgetCopyData(conn, data, async);
1031 	if (len > 0)
1032 		lua_pushlstring(L, *data, len);
1033 	else if (len == 0)	/* no data yet */
1034 		lua_pushboolean(L, 0);
1035 	else if (len == -1)	/* copy done */
1036 		lua_pushboolean(L, 1);
1037 	else			/* an error occurred */
1038 		lua_pushnil(L);
1039 	gcfree(data);
1040 	return 1;
1041 }
1042 
1043 /*
1044  * Control functions
1045  */
1046 static int
conn_clientEncoding(lua_State * L)1047 conn_clientEncoding(lua_State *L)
1048 {
1049 	lua_pushstring(L,
1050 	    pg_encoding_to_char(PQclientEncoding(pgsql_conn(L, 1))));
1051 	return 1;
1052 }
1053 
1054 static int
conn_setClientEncoding(lua_State * L)1055 conn_setClientEncoding(lua_State *L)
1056 {
1057 	if (PQsetClientEncoding(pgsql_conn(L, 1), luaL_checkstring(L, 2)))
1058 		lua_pushboolean(L, 0);
1059 	else
1060 		lua_pushboolean(L, 1);
1061 	return 1;
1062 }
1063 
1064 static int
conn_setErrorVerbosity(lua_State * L)1065 conn_setErrorVerbosity(lua_State *L)
1066 {
1067 	lua_pushinteger(L,
1068 	    PQsetErrorVerbosity(pgsql_conn(L, 1), luaL_checkinteger(L, 2)));
1069 	return 1;
1070 }
1071 
1072 static int
closef_untrace(lua_State * L)1073 closef_untrace(lua_State *L)
1074 {
1075 	PGconn *conn;
1076 	lua_CFunction cf;
1077 
1078 	luaL_checkudata(L, 1, LUA_FILEHANDLE);
1079 
1080 	/* untrace so libpq doesn't segfault */
1081 	lua_getuservalue(L, 1);
1082 	lua_getfield(L, -1, "PGconn");
1083 	conn = pgsql_conn(L, -1);
1084 	lua_getfield(L, -2, "old_uservalue");
1085 #if LUA_VERSION_NUM >= 502
1086 	lua_getfield(L, -3, "old_closef");
1087 #else
1088 	lua_getfield(L, -1, "__close");
1089 #endif
1090 	cf = lua_tocfunction(L, -1);
1091 	lua_pop(L, 1);
1092 	lua_setuservalue(L, 1);
1093 
1094 	PQuntrace(conn);
1095 
1096 	/* let go of PGconn's reference to file handle */
1097 	lua_getuservalue(L, -1);
1098 	lua_pushnil(L);
1099 	lua_setfield(L, -2, "trace_file");
1100 
1101 	/* pop stream uservalue, PGconn, PGconn uservalue */
1102 	lua_pop(L, 3);
1103 
1104 	/* call original close function */
1105 	return (*cf)(L);
1106 }
1107 
1108 static int
conn_trace(lua_State * L)1109 conn_trace(lua_State *L)
1110 {
1111 	PGconn *conn;
1112 #if LUA_VERSION_NUM >= 502
1113 	luaL_Stream *stream;
1114 
1115 	conn = pgsql_conn(L, 1);
1116 	stream = luaL_checkudata(L, 2, LUA_FILEHANDLE);
1117 	luaL_argcheck(L, stream->f != NULL, 2, "invalid file handle");
1118 
1119 	/*
1120 	 * Keep a reference to the file object in uservalue of connection
1121 	 * so it doesn't get garbage collected.
1122 	 */
1123 	lua_getuservalue(L, 1);
1124 	lua_pushvalue(L, 2);
1125 	lua_setfield(L, -2, "trace_file");
1126 
1127 	/*
1128 	 * Swap out closef luaL_Stream member for our wrapper that will
1129 	 * untrace.
1130 	 */
1131 	lua_createtable(L, 0, 3);
1132 	lua_getuservalue(L, 2);
1133 	lua_setfield(L, -2, "old_uservalue");
1134 	lua_pushcfunction(L, stream->closef);
1135 	lua_setfield(L, -2, "old_closef");
1136 	lua_pushvalue(L, 1);
1137 	lua_setfield(L, -2, "PGconn");
1138 	lua_setuservalue(L, 2);
1139 	stream->closef = closef_untrace;
1140 
1141 	PQtrace(conn, stream->f);
1142 #else
1143 	FILE **fp;
1144 
1145 	conn = pgsql_conn(L, 1);
1146 	fp = luaL_checkudata(L, 2, LUA_FILEHANDLE);
1147 	luaL_argcheck(L, *fp != NULL, 2, "invalid file handle");
1148 
1149 	/*
1150 	 * Keep a reference to the file object in uservalue of connection
1151 	 * so it doesn't get garbage collected.
1152 	 */
1153 	lua_getuservalue(L, 1);
1154 	lua_pushvalue(L, 2);
1155 	lua_setfield(L, -2, "trace_file");
1156 
1157 	/*
1158 	 * Swap __close field in file environment for our wrapper that will
1159 	 * untrace keep the old closef under the key of the PGconn.
1160 	 */
1161 	lua_createtable(L, 0, 3);
1162 	lua_pushcfunction(L, closef_untrace);
1163 	lua_setfield(L, -2, "__close");
1164 	lua_getuservalue(L, 2);
1165 	lua_setfield(L, -2, "old_uservalue");
1166 	lua_pushvalue(L, 1);
1167 	lua_setfield(L, -2, "PGconn");
1168 	lua_setuservalue(L, 2);
1169 
1170 	PQtrace(conn, *fp);
1171 #endif
1172 	return 0;
1173 }
1174 
1175 static int
conn_untrace(lua_State * L)1176 conn_untrace(lua_State *L)
1177 {
1178 	PQuntrace(pgsql_conn(L, 1));
1179 
1180 	/* Let go of PGconn's reference to file handle. */
1181 	lua_getuservalue(L, 1);
1182 	lua_pushnil(L);
1183 	lua_setfield(L, -2, "trace_file");
1184 
1185 	return 0;
1186 }
1187 
1188 /*
1189  * Miscellaneous Functions
1190  */
1191 static int
conn_consumeInput(lua_State * L)1192 conn_consumeInput(lua_State *L)
1193 {
1194 	lua_pushboolean(L, PQconsumeInput(pgsql_conn(L, 1)));
1195 	return 1;
1196 }
1197 
1198 static int
conn_isBusy(lua_State * L)1199 conn_isBusy(lua_State *L)
1200 {
1201 	lua_pushboolean(L, PQisBusy(pgsql_conn(L, 1)));
1202 	return 1;
1203 }
1204 
1205 static int
conn_setnonblocking(lua_State * L)1206 conn_setnonblocking(lua_State *L)
1207 {
1208 	int r;
1209 
1210 	r = PQsetnonblocking(pgsql_conn(L, 1), lua_toboolean(L, 2));
1211 	lua_pushboolean(L, !r);
1212 	return 1;
1213 }
1214 
1215 static int
conn_isnonblocking(lua_State * L)1216 conn_isnonblocking(lua_State *L)
1217 {
1218 	lua_pushboolean(L, PQisnonblocking(pgsql_conn(L, 1)));
1219 	return 1;
1220 }
1221 
1222 static int
conn_flush(lua_State * L)1223 conn_flush(lua_State *L)
1224 {
1225 	int r;
1226 
1227 	r = PQflush(pgsql_conn(L, 1));
1228 
1229 	if (r >= 0)
1230 		lua_pushboolean(L, r == 0);
1231 	else
1232 		lua_pushnil(L);
1233 	return 1;
1234 }
1235 
1236 #if PG_VERSION_NUM >= 100000
1237 static int
conn_encryptPassword(lua_State * L)1238 conn_encryptPassword(lua_State *L)
1239 {
1240 	const char *algorithm = NULL;
1241 	char **pw;
1242 
1243 	if (lua_isstring(L, 4))
1244 		algorithm = lua_tostring(L, 4);
1245 
1246 	pw = gcmalloc(L, sizeof(char *));
1247 	*pw = PQencryptPasswordConn(pgsql_conn(L, 1), luaL_checkstring(L, 2),
1248 	    luaL_checkstring(L, 3), algorithm);
1249 	if (*pw) {
1250 		lua_pushstring(L, *pw);
1251 		gcfree(pw);
1252 	} else
1253 		lua_pushnil(L);
1254 	return 1;
1255 }
1256 #endif
1257 
1258 /* Notice processing */
1259 static void
noticeReceiver(void * arg,const PGresult * r)1260 noticeReceiver(void *arg, const PGresult *r)
1261 {
1262 	notice *n = arg;
1263 	PGresult **res;
1264 
1265 	lua_rawgeti(n->L, LUA_REGISTRYINDEX, n->f);
1266 	res = lua_newuserdata(n->L, sizeof(PGresult *));
1267 
1268 	*res = (PGresult *)r;
1269 	luaL_setmetatable(n->L, RES_METATABLE);
1270 
1271 	if (lua_pcall(n->L, 1, 0, 0))
1272 		luaL_error(n->L, "%s", lua_tostring(n->L, -1));
1273 	*res = NULL;	/* avoid double free */
1274 }
1275 
1276 static void
noticeProcessor(void * arg,const char * message)1277 noticeProcessor(void *arg, const char *message)
1278 {
1279 	notice *n = arg;
1280 
1281 	lua_rawgeti(n->L, LUA_REGISTRYINDEX, n->f);
1282 	lua_pushstring(n->L, message);
1283 	if (lua_pcall(n->L, 1, 0, 0))
1284 		luaL_error(n->L, "%s", lua_tostring(n->L, -1));
1285 }
1286 
1287 static int
conn_setNoticeReceiver(lua_State * L)1288 conn_setNoticeReceiver(lua_State *L)
1289 {
1290 	notice **n;
1291 	PGconn *conn;
1292 	int f;
1293 
1294 	if (!lua_isfunction(L, -1))
1295 		return luaL_argerror(L, -1, "function expected");
1296 
1297 	f = luaL_ref(L, LUA_REGISTRYINDEX);
1298 	conn = pgsql_conn(L, 1);
1299 
1300 	n = gcmalloc(L, sizeof(notice *));
1301 	*n = malloc(sizeof(notice));
1302 	if (*n != NULL) {
1303 		(*n)->L = L;
1304 		(*n)->f = f;
1305 		PQsetNoticeReceiver(conn, noticeReceiver, *n);
1306 	} else
1307 		return luaL_error(L, "out of memory");
1308 	return 0;
1309 }
1310 
1311 static int
conn_setNoticeProcessor(lua_State * L)1312 conn_setNoticeProcessor(lua_State *L)
1313 {
1314 	notice **n;
1315 	PGconn *conn;
1316 	int f;
1317 
1318 	if (!lua_isfunction(L, -1))
1319 		return luaL_argerror(L, -1, "function expected");
1320 
1321 	f = luaL_ref(L, LUA_REGISTRYINDEX);
1322 	conn = pgsql_conn(L, 1);
1323 
1324 	n = gcmalloc(L, sizeof(notice *));
1325 	*n = malloc(sizeof(notice));
1326 	if (*n != NULL) {
1327 		(*n)->L = L;
1328 		(*n)->f = f;
1329 		PQsetNoticeProcessor(conn, noticeProcessor, *n);
1330 	} else
1331 		return luaL_error(L, "out of memory");
1332 	return 0;
1333 }
1334 
1335 /* Large objects */
1336 static int
conn_lo_create(lua_State * L)1337 conn_lo_create(lua_State *L)
1338 {
1339 	Oid oid;
1340 
1341 	if (lua_gettop(L) == 2)
1342 		oid = luaL_checkinteger(L, 2);
1343 	else
1344 		oid = 0;
1345 	lua_pushinteger(L, lo_create(pgsql_conn(L, 1), oid));
1346 	return 1;
1347 }
1348 
1349 static int
conn_lo_import(lua_State * L)1350 conn_lo_import(lua_State *L)
1351 {
1352 	lua_pushinteger(L, lo_import(pgsql_conn(L, 1), luaL_checkstring(L, 2)));
1353 	return 1;
1354 }
1355 
1356 static int
conn_lo_import_with_oid(lua_State * L)1357 conn_lo_import_with_oid(lua_State *L)
1358 {
1359 	lua_pushinteger(L,
1360 	    lo_import_with_oid(pgsql_conn(L, 1), luaL_checkstring(L, 2),
1361 	    luaL_checkinteger(L, 3)));
1362 	return 1;
1363 }
1364 
1365 static int
conn_lo_export(lua_State * L)1366 conn_lo_export(lua_State *L)
1367 {
1368 	int r;
1369 
1370 	r = lo_export(pgsql_conn(L, 1), luaL_checkinteger(L, 2),
1371 	    luaL_checkstring(L, 3));
1372 
1373 	lua_pushboolean(L, r == 1);
1374 	return 1;
1375 }
1376 
1377 static int
conn_lo_open(lua_State * L)1378 conn_lo_open(lua_State *L)
1379 {
1380 	int fd;
1381 
1382 	fd = lo_open(pgsql_conn(L, 1), luaL_checkinteger(L, 2),
1383 	    luaL_checkinteger(L, 3));
1384 	if (fd == -1)
1385 		lua_pushnil(L);
1386 	else
1387 		lua_pushinteger(L, fd);
1388 	return 1;
1389 }
1390 
1391 static int
conn_lo_write(lua_State * L)1392 conn_lo_write(lua_State *L)
1393 {
1394 	const char *s;
1395 	size_t len;
1396 
1397 	s = lua_tolstring(L, 3, &len);
1398 	lua_pushinteger(L, lo_write(pgsql_conn(L, 1), luaL_checkinteger(L, 2),
1399 	    s, len));
1400 	return 1;
1401 }
1402 
1403 static int
conn_lo_read(lua_State * L)1404 conn_lo_read(lua_State *L)
1405 {
1406 	char *buf;
1407 	size_t len;
1408 
1409 	len = luaL_checkinteger(L, 3);
1410 	buf = lua_newuserdata(L, len);
1411 	len = lo_read(pgsql_conn(L, 1), luaL_checkinteger(L, 2), buf, len);
1412 	lua_pushlstring(L, buf, len);
1413 	lua_pushinteger(L, len);
1414 	return 2;
1415 }
1416 
1417 static int
conn_lo_lseek(lua_State * L)1418 conn_lo_lseek(lua_State *L)
1419 {
1420 	lua_pushinteger(L, lo_lseek(pgsql_conn(L, 1), luaL_checkinteger(L, 2),
1421 	    luaL_checkinteger(L, 3), luaL_checkinteger(L, 4)));
1422 	return 1;
1423 }
1424 
1425 static int
conn_lo_tell(lua_State * L)1426 conn_lo_tell(lua_State *L)
1427 {
1428 	lua_pushinteger(L, lo_tell(pgsql_conn(L, 1), luaL_checkinteger(L, 2)));
1429 	return 1;
1430 }
1431 
1432 static int
conn_lo_truncate(lua_State * L)1433 conn_lo_truncate(lua_State *L)
1434 {
1435 	lua_pushinteger(L, lo_truncate(pgsql_conn(L, 1),
1436 	    luaL_checkinteger(L, 2), luaL_checkinteger(L, 3)));
1437 	return 1;
1438 }
1439 
1440 static int
conn_lo_close(lua_State * L)1441 conn_lo_close(lua_State *L)
1442 {
1443 	lua_pushboolean(L,
1444 	    lo_close(pgsql_conn(L, 1), luaL_checkinteger(L, 2)) == 0);
1445 	return 1;
1446 }
1447 
1448 static int
conn_lo_unlink(lua_State * L)1449 conn_lo_unlink(lua_State *L)
1450 {
1451 	lua_pushboolean(L,
1452 	    lo_unlink(pgsql_conn(L, 1), luaL_checkinteger(L, 2)) == 1);
1453 	return 1;
1454 }
1455 
1456 #if PG_VERSION_NUM >= 90300
1457 static int
conn_lo_lseek64(lua_State * L)1458 conn_lo_lseek64(lua_State *L)
1459 {
1460 	lua_pushinteger(L, lo_lseek64(pgsql_conn(L, 1), luaL_checkinteger(L, 2),
1461 	    luaL_checkinteger(L, 3), luaL_checkinteger(L, 4)));
1462 	return 1;
1463 }
1464 
1465 static int
conn_lo_tell64(lua_State * L)1466 conn_lo_tell64(lua_State *L)
1467 {
1468 	lua_pushinteger(L,
1469 	    lo_tell64(pgsql_conn(L, 1), luaL_checkinteger(L, 2)));
1470 	return 1;
1471 }
1472 
1473 static int
conn_lo_truncate64(lua_State * L)1474 conn_lo_truncate64(lua_State *L)
1475 {
1476 	lua_pushinteger(L, lo_truncate64(pgsql_conn(L, 1),
1477 	    luaL_checkinteger(L, 2), luaL_checkinteger(L, 3)));
1478 	return 1;
1479 }
1480 #endif
1481 
1482 /*
1483  * Result set functions
1484  */
1485 static int
res_status(lua_State * L)1486 res_status(lua_State *L)
1487 {
1488 	lua_pushinteger(L,
1489 	    PQresultStatus(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1490 	return 1;
1491 }
1492 
1493 static int
res_resStatus(lua_State * L)1494 res_resStatus(lua_State *L)
1495 {
1496 	lua_pushstring(L, PQresStatus(luaL_checkinteger(L, 2)));
1497 	return 1;
1498 }
1499 
1500 static int
res_errorMessage(lua_State * L)1501 res_errorMessage(lua_State *L)
1502 {
1503 	lua_pushstring(L,
1504 	    PQresultErrorMessage(*(PGresult **)luaL_checkudata(L, 1,
1505 	    RES_METATABLE)));
1506 	return 1;
1507 }
1508 
1509 static int
res_errorField(lua_State * L)1510 res_errorField(lua_State *L)
1511 {
1512 	char *field;
1513 
1514 	field = PQresultErrorField(
1515 	    *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1516 	    lua_tointeger(L, 2));
1517 	if (field == NULL)
1518 		lua_pushnil(L);
1519 	else
1520 		lua_pushstring(L, field);
1521 	return 1;
1522 }
1523 
1524 static int
res_nfields(lua_State * L)1525 res_nfields(lua_State *L)
1526 {
1527 	lua_pushinteger(L,
1528 	    PQnfields(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1529 	return 1;
1530 }
1531 
1532 static int
res_ntuples(lua_State * L)1533 res_ntuples(lua_State *L)
1534 {
1535 	lua_pushinteger(L,
1536 	    PQntuples(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1537 	return 1;
1538 }
1539 
1540 static int
res_fname(lua_State * L)1541 res_fname(lua_State *L)
1542 {
1543 	lua_pushstring(L,
1544 	    PQfname(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1545 	    luaL_checkinteger(L, 2) - 1));
1546 	return 1;
1547 }
1548 
1549 static int
res_fnumber(lua_State * L)1550 res_fnumber(lua_State *L)
1551 {
1552 	lua_pushinteger(L,
1553 	    PQfnumber(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1554 	    luaL_checkstring(L, 2)) + 1);
1555 	return 1;
1556 }
1557 
1558 static int
res_ftable(lua_State * L)1559 res_ftable(lua_State *L)
1560 {
1561 	lua_pushinteger(L,
1562 	    PQftable(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1563 	    luaL_checkinteger(L, 2) - 1));
1564 	return 1;
1565 }
1566 
1567 static int
res_ftablecol(lua_State * L)1568 res_ftablecol(lua_State *L)
1569 {
1570 	lua_pushinteger(L,
1571 	    PQftablecol(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1572 	    luaL_checkinteger(L, 2) - 1));
1573 	return 1;
1574 }
1575 
1576 static int
res_fformat(lua_State * L)1577 res_fformat(lua_State *L)
1578 {
1579 	lua_pushinteger(L,
1580 	    PQfformat(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1581 	    luaL_checkinteger(L, 2) - 1));
1582 	return 1;
1583 }
1584 
1585 static int
res_ftype(lua_State * L)1586 res_ftype(lua_State *L)
1587 {
1588 	lua_pushinteger(L,
1589 	    PQftype(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1590 	    luaL_checkinteger(L, 2) - 1));
1591 	return 1;
1592 }
1593 
1594 static int
res_fmod(lua_State * L)1595 res_fmod(lua_State *L)
1596 {
1597 	lua_pushinteger(L,
1598 	    PQfmod(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1599 	    luaL_checkinteger(L, 2) - 1));
1600 	return 1;
1601 }
1602 
1603 static int
res_fsize(lua_State * L)1604 res_fsize(lua_State *L)
1605 {
1606 	lua_pushinteger(L,
1607 	    PQfsize(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1608 	    luaL_checkinteger(L, 2) - 1));
1609 	return 1;
1610 }
1611 
1612 static int
res_binaryTuples(lua_State * L)1613 res_binaryTuples(lua_State *L)
1614 {
1615 	lua_pushboolean(L,
1616 	    PQbinaryTuples(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1617 	return 1;
1618 }
1619 
1620 static int
res_getvalue(lua_State * L)1621 res_getvalue(lua_State *L)
1622 {
1623 	lua_pushstring(L,
1624 	    PQgetvalue(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1625 	    luaL_checkinteger(L, 2) - 1, luaL_checkinteger(L, 3) - 1));
1626 	return 1;
1627 }
1628 
1629 static int
res_getisnull(lua_State * L)1630 res_getisnull(lua_State *L)
1631 {
1632 	lua_pushboolean(L,
1633 	    PQgetisnull(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1634 	    luaL_checkinteger(L, 2) - 1, luaL_checkinteger(L, 3) - 1));
1635 	return 1;
1636 }
1637 
1638 static int
res_getlength(lua_State * L)1639 res_getlength(lua_State *L)
1640 {
1641 	lua_pushinteger(L,
1642 	    PQgetlength(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1643 	    luaL_checkinteger(L, 2) - 1, luaL_checkinteger(L, 3) - 1));
1644 	return 1;
1645 }
1646 
1647 static int
res_nparams(lua_State * L)1648 res_nparams(lua_State *L)
1649 {
1650 	lua_pushinteger(L,
1651 	    PQnparams(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1652 	return 1;
1653 }
1654 
1655 static int
res_paramtype(lua_State * L)1656 res_paramtype(lua_State *L)
1657 {
1658 	lua_pushinteger(L,
1659 	    PQparamtype(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE),
1660 	    luaL_checkinteger(L, 2)) - 1);
1661 	return 1;
1662 }
1663 
1664 static int
res_cmdStatus(lua_State * L)1665 res_cmdStatus(lua_State *L)
1666 {
1667 	lua_pushstring(L,
1668 	    PQcmdStatus(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1669 	return 1;
1670 }
1671 
1672 static int
res_cmdTuples(lua_State * L)1673 res_cmdTuples(lua_State *L)
1674 {
1675 	lua_pushstring(L,
1676 	    PQcmdTuples(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1677 	return 1;
1678 }
1679 
1680 static int
res_oidValue(lua_State * L)1681 res_oidValue(lua_State *L)
1682 {
1683 	lua_pushinteger(L,
1684 	    PQoidValue(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1685 	return 1;
1686 }
1687 
1688 static int
res_oidStatus(lua_State * L)1689 res_oidStatus(lua_State *L)
1690 {
1691 	lua_pushstring(L,
1692 	    PQoidStatus(*(PGresult **)luaL_checkudata(L, 1, RES_METATABLE)));
1693 	return 1;
1694 }
1695 
1696 /* Lua specific functions */
1697 static int
res_copy(lua_State * L)1698 res_copy(lua_State *L)
1699 {
1700 	PGresult *res = *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
1701 	int row, col, convert;
1702 
1703 	convert = 0;	/* Do not convert numeric types */
1704 
1705 	if (lua_gettop(L) == 2)
1706 		convert = lua_toboolean(L, 2);
1707 
1708 	lua_newtable(L);
1709 	for (row = 0; row < PQntuples(res); row++) {
1710 		lua_pushinteger(L, row + 1);
1711 		lua_newtable(L);
1712 		for (col = 0; col < PQnfields(res); col++) {
1713 			if (convert)
1714 				switch (PQftype(res, col)) {
1715 				case BOOLOID:
1716 					lua_pushboolean(L,
1717 					    strcmp(PQgetvalue(res, row, col),
1718 					    "f"));
1719 					break;
1720 				case INT2OID:
1721 				case INT4OID:
1722 				case INT8OID:
1723 					lua_pushinteger(L,
1724 					    atol(PQgetvalue(res, row, col)));
1725 					break;
1726 				case FLOAT4OID:
1727 				case FLOAT8OID:
1728 				case NUMERICOID:
1729 					lua_pushnumber(L,
1730 					    atof(PQgetvalue(res, row, col)));
1731 					break;
1732 				default:
1733 					lua_pushstring(L,
1734 					    PQgetvalue(res, row, col));
1735 				}
1736 			else
1737 				lua_pushstring(L, PQgetvalue(res, row, col));
1738 			lua_setfield(L, -2, PQfname(res, col));
1739 		}
1740 		lua_settable(L, -3);
1741 	}
1742 	return 1;
1743 }
1744 
1745 static int
res_fields_iterator(lua_State * L)1746 res_fields_iterator(lua_State *L)
1747 {
1748 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1749 	int n;
1750 
1751 	t->row++;
1752 
1753 	luaL_checkstack(L, PQnfields(t->res), "out of stack space");
1754 	if (t->row == PQntuples(t->res))
1755 		for (n = 0; n < PQnfields(t->res); n++)
1756 			lua_pushnil(L);
1757 	else
1758 		for (n = 0; n < PQnfields(t->res); n++)
1759 			lua_pushstring(L, PQgetvalue(t->res, t->row, n));
1760 	return PQnfields(t->res);
1761 }
1762 
1763 static int
res_fields(lua_State * L)1764 res_fields(lua_State *L)
1765 {
1766 	tuple *t;
1767 
1768 	lua_pushcfunction(L, res_fields_iterator);
1769 	t = lua_newuserdata(L, sizeof(tuple));
1770 	luaL_setmetatable(L, TUPLE_METATABLE);
1771 	t->res = *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
1772 	t->row = -1;
1773 	return 2;
1774 }
1775 
1776 static int
res_tuples_iterator(lua_State * L)1777 res_tuples_iterator(lua_State *L)
1778 {
1779 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1780 
1781 	t->row++;
1782 
1783 	if (t->row == PQntuples(t->res)) {
1784 		lua_pushnil(L);
1785 		lua_pushnil(L);
1786 	} else {
1787 		lua_pushvalue(L, 1);
1788 		lua_pushinteger(L, t->row + 1);
1789 	}
1790 	return 2;
1791 }
1792 
1793 static int
res_tuples(lua_State * L)1794 res_tuples(lua_State *L)
1795 {
1796 	PGresult **res;
1797 	tuple *t;
1798 
1799 	res = (PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
1800 
1801 	lua_pushcfunction(L, res_tuples_iterator);
1802 	t = lua_newuserdata(L, sizeof(tuple));
1803 	luaL_setmetatable(L, TUPLE_METATABLE);
1804 	t->res = *res;
1805 	t->row = -1;
1806 	return 2;
1807 }
1808 
1809 static int
res_index(lua_State * L)1810 res_index(lua_State *L)
1811 {
1812 	if (lua_type(L, -1) == LUA_TNUMBER) {
1813 		tuple *t;
1814 		PGresult *res;
1815 		int row;
1816 
1817 		res = *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
1818 		row = luaL_checkinteger(L, 2) - 1;
1819 
1820 		if (row < 0 || row >= PQntuples(res))
1821 			lua_pushnil(L);
1822 		else {
1823 			t = lua_newuserdata(L, sizeof(tuple));
1824 			t->res = res;
1825 			t->row = row;
1826 			luaL_setmetatable(L, TUPLE_METATABLE);
1827 		}
1828 	} else {
1829 		const char *nam;
1830 
1831 		nam = lua_tostring(L, -1);
1832 		if (lua_getmetatable(L, -2)) {
1833 			lua_pushstring(L, nam);
1834 			lua_rawget(L, -2);
1835 		} else
1836 			lua_pushnil(L);
1837 	}
1838 	return 1;
1839 }
1840 
1841 static int
res_clear(lua_State * L)1842 res_clear(lua_State *L)
1843 {
1844 	PGresult **r;
1845 
1846 	r = luaL_checkudata(L, 1, RES_METATABLE);
1847 	if (*r) {
1848 		PQclear(*r);
1849 		*r = NULL;
1850 	}
1851 	return 0;
1852 }
1853 
1854 /*
1855  * Notifies methods (objects returned by conn:notifies())
1856  */
1857 static int
notify_relname(lua_State * L)1858 notify_relname(lua_State *L)
1859 {
1860 	PGnotify **n;
1861 
1862 	n = luaL_checkudata(L, 1, NOTIFY_METATABLE);
1863 	lua_pushstring(L, (*n)->relname);
1864 	return 1;
1865 }
1866 
1867 static int
notify_pid(lua_State * L)1868 notify_pid(lua_State *L)
1869 {
1870 	PGnotify **n;
1871 
1872 	n = luaL_checkudata(L, 1, NOTIFY_METATABLE);
1873 	lua_pushinteger(L, (*n)->be_pid);
1874 	return 1;
1875 }
1876 
1877 static int
notify_extra(lua_State * L)1878 notify_extra(lua_State *L)
1879 {
1880 	PGnotify **n;
1881 
1882 	n = luaL_checkudata(L, 1, NOTIFY_METATABLE);
1883 	lua_pushstring(L, (*n)->extra);
1884 	return 1;
1885 }
1886 
1887 static int
notify_clear(lua_State * L)1888 notify_clear(lua_State *L)
1889 {
1890 	PGnotify **n;
1891 
1892 	n = luaL_checkudata(L, 1, NOTIFY_METATABLE);
1893 	if (*n) {
1894 		PQfreemem(*n);
1895 		*n = NULL;
1896 	}
1897 	return 0;
1898 }
1899 
1900 /*
1901  * Tuple and value functions
1902  */
1903 static int
tuple_copy(lua_State * L)1904 tuple_copy(lua_State *L)
1905 {
1906 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1907 	int col;
1908 
1909 	lua_newtable(L);
1910 	for (col = 0; col < PQnfields(t->res); col++) {
1911 		lua_pushstring(L, PQgetvalue(t->res, t->row, col));
1912 		lua_setfield(L, -2, PQfname(t->res, col));
1913 	}
1914 	return 1;
1915 }
1916 
1917 static int
field_iterator(lua_State * L)1918 field_iterator(lua_State *L)
1919 {
1920 	field *f = luaL_checkudata(L, 1, FIELD_METATABLE);
1921 
1922 	f->col++;
1923 
1924 	if (f->col == PQnfields(f->tuple->res)) {
1925 		lua_pushnil(L);
1926 		lua_pushnil(L);
1927 	} else {
1928 		lua_pushstring(L, PQfname(f->tuple->res, f->col));
1929 		lua_pushstring(L,
1930 		    PQgetvalue(f->tuple->res, f->tuple->row, f->col));
1931 	}
1932 	return 2;
1933 }
1934 
1935 static int
tuple_getfields(lua_State * L)1936 tuple_getfields(lua_State *L)
1937 {
1938 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1939 	field *f;
1940 
1941 	lua_pushcfunction(L, field_iterator);
1942 	f = lua_newuserdata(L, sizeof(field));
1943 	f->tuple = t;
1944 	f->col = -1;
1945 	luaL_setmetatable(L, FIELD_METATABLE);
1946 	return 2;
1947 }
1948 
1949 static int
tuple_getisnull(lua_State * L)1950 tuple_getisnull(lua_State *L)
1951 {
1952 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1953 	const char *fnam;
1954 	int fnumber;
1955 
1956 	switch (lua_type(L, 2)) {
1957 	case LUA_TNUMBER:
1958 		fnumber = lua_tointeger(L, 2) - 1;
1959 		if (fnumber < 0 || fnumber >= PQnfields(t->res))
1960 			lua_pushnil(L);
1961 		else
1962 			lua_pushboolean(L, PQgetisnull(t->res, t->row,
1963 			    lua_tointeger(L, 2) - 1));
1964 		break;
1965 	case LUA_TSTRING:
1966 		fnam = lua_tostring(L, 2);
1967 		fnumber = PQfnumber(t->res, fnam);
1968 
1969 		if (fnumber == -1)
1970 			lua_pushnil(L);
1971 		else
1972 			lua_pushboolean(L, PQgetisnull(t->res, t->row,
1973 			    PQfnumber(t->res, lua_tostring(L, 2))));
1974 		break;
1975 	default:
1976 		lua_pushnil(L);
1977 	}
1978 	return 1;
1979 }
1980 
1981 static int
tuple_getlength(lua_State * L)1982 tuple_getlength(lua_State *L)
1983 {
1984 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
1985 	const char *fnam;
1986 	int fnumber;
1987 
1988 	switch (lua_type(L, 2)) {
1989 	case LUA_TNUMBER:
1990 		fnumber = lua_tointeger(L, 2) - 1;
1991 		if (fnumber < 0 || fnumber >= PQnfields(t->res))
1992 			lua_pushnil(L);
1993 		else
1994 			lua_pushinteger(L, PQgetlength(t->res, t->row,
1995 			    lua_tointeger(L, 2) - 1));
1996 		break;
1997 	case LUA_TSTRING:
1998 		fnam = lua_tostring(L, 2);
1999 		fnumber = PQfnumber(t->res, fnam);
2000 
2001 		if (fnumber == -1)
2002 			lua_pushnil(L);
2003 		else
2004 			lua_pushinteger(L, PQgetlength(t->res, t->row,
2005 			    PQfnumber(t->res, lua_tostring(L, 2))));
2006 		break;
2007 	default:
2008 		lua_pushnil(L);
2009 	}
2010 	return 1;
2011 }
2012 
2013 static int
tuple_index(lua_State * L)2014 tuple_index(lua_State *L)
2015 {
2016 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
2017 	const char *fnam;
2018 	int fnumber;
2019 
2020 	switch (lua_type(L, 2)) {
2021 	case LUA_TNUMBER:
2022 		fnumber = lua_tointeger(L, 2) - 1;
2023 		if (fnumber < 0 || fnumber >= PQnfields(t->res))
2024 			lua_pushnil(L);
2025 		else
2026 			lua_pushstring(L, PQgetvalue(t->res, t->row, fnumber));
2027 		break;
2028 	case LUA_TSTRING:
2029 		fnam = lua_tostring(L, 2);
2030 		fnumber = PQfnumber(t->res, fnam);
2031 
2032 		if (fnumber == -1) {
2033 			if (!strcmp(fnam, "copy"))
2034 				lua_pushcfunction(L, tuple_copy);
2035 			else if (!strcmp(fnam, "getfields"))
2036 				lua_pushcfunction(L, tuple_getfields);
2037 			else if (!strcmp(fnam, "getisnull"))
2038 				lua_pushcfunction(L, tuple_getisnull);
2039 			else if (!strcmp(fnam, "getlength"))
2040 				lua_pushcfunction(L, tuple_getlength);
2041 			else
2042 				lua_pushnil(L);
2043 		} else
2044 			lua_pushstring(L, PQgetvalue(t->res, t->row,
2045 			    PQfnumber(t->res, fnam)));
2046 		break;
2047 	default:
2048 		lua_pushnil(L);
2049 	}
2050 	return 1;
2051 }
2052 
2053 static int
tuple_length(lua_State * L)2054 tuple_length(lua_State *L)
2055 {
2056 	tuple *t = luaL_checkudata(L, 1, TUPLE_METATABLE);
2057 
2058 	lua_pushinteger(L, PQnfields(t->res));
2059 	return 1;
2060 }
2061 
2062 /*
2063  * Module definitions, constants etc.
2064  */
2065 struct constant {
2066 	char *name;
2067 	int value;
2068 };
2069 
2070 static struct constant pgsql_constant[] = {
2071 	/* Connection status */
2072 	{ "CONNECTION_STARTED",		CONNECTION_STARTED },
2073 	{ "CONNECTION_MADE",		CONNECTION_MADE },
2074 	{ "CONNECTION_AWAITING_RESPONSE", CONNECTION_AWAITING_RESPONSE },
2075 	{ "CONNECTION_AUTH_OK",		CONNECTION_AUTH_OK },
2076 	{ "CONNECTION_OK",		CONNECTION_OK },
2077 	{ "CONNECTION_SSL_STARTUP",	CONNECTION_SSL_STARTUP },
2078 	{ "CONNECTION_SETENV",		CONNECTION_SETENV },
2079 	{ "CONNECTION_BAD",		CONNECTION_BAD },
2080 #if PG_VERSION_NUM >= 100000
2081 	{ "CONNECTION_CONSUME",		CONNECTION_CONSUME },
2082 #endif
2083 
2084 	/* Resultset status codes */
2085 	{ "PGRES_EMPTY_QUERY",		PGRES_EMPTY_QUERY },
2086 	{ "PGRES_COMMAND_OK",		PGRES_COMMAND_OK },
2087 	{ "PGRES_TUPLES_OK",		PGRES_TUPLES_OK },
2088 #if PG_VERSION_NUM >= 90200
2089 	{ "PGRES_SINGLE_TUPLE",		PGRES_SINGLE_TUPLE },
2090 #endif
2091 	{ "PGRES_COPY_OUT",		PGRES_COPY_OUT },
2092 	{ "PGRES_COPY_IN",		PGRES_COPY_IN },
2093 #if PG_VERSION_NUM >= 90100
2094 	{ "PGRES_COPY_BOTH",		PGRES_COPY_BOTH },
2095 	{ "PGRES_SINGLE_TUPLE",		PGRES_SINGLE_TUPLE },
2096 #endif
2097 	{ "PGRES_BAD_RESPONSE",		PGRES_BAD_RESPONSE },
2098 	{ "PGRES_NONFATAL_ERROR",	PGRES_NONFATAL_ERROR },
2099 	{ "PGRES_FATAL_ERROR",		PGRES_FATAL_ERROR },
2100 
2101 	/* Polling status */
2102 	{ "PGRES_POLLING_FAILED",	PGRES_POLLING_FAILED },
2103 	{ "PGRES_POLLING_READING",	PGRES_POLLING_READING },
2104 	{ "PGRES_POLLING_WRITING",	PGRES_POLLING_WRITING },
2105 	{ "PGRES_POLLING_OK",		PGRES_POLLING_OK },
2106 
2107 	/* Transaction status */
2108 	{ "PQTRANS_IDLE",		PQTRANS_IDLE },
2109 	{ "PQTRANS_ACTIVE",		PQTRANS_ACTIVE },
2110 	{ "PQTRANS_INTRANS",		PQTRANS_INTRANS },
2111 	{ "PQTRANS_INERROR",		PQTRANS_INERROR },
2112 	{ "PQTRANS_UNKNOWN",		PQTRANS_UNKNOWN },
2113 
2114 	/* Diagnostic codes */
2115 	{ "PG_DIAG_SEVERITY",		PG_DIAG_SEVERITY },
2116 	{ "PG_DIAG_SQLSTATE",		PG_DIAG_SQLSTATE },
2117 	{ "PG_DIAG_MESSAGE_PRIMARY",	PG_DIAG_MESSAGE_PRIMARY },
2118 	{ "PG_DIAG_MESSAGE_DETAIL",	PG_DIAG_MESSAGE_DETAIL },
2119 	{ "PG_DIAG_MESSAGE_HINT",	PG_DIAG_MESSAGE_HINT },
2120 	{ "PG_DIAG_STATEMENT_POSITION",	PG_DIAG_STATEMENT_POSITION },
2121 	{ "PG_DIAG_INTERNAL_POSITION",	PG_DIAG_INTERNAL_POSITION },
2122 	{ "PG_DIAG_INTERNAL_QUERY",	PG_DIAG_INTERNAL_QUERY },
2123 	{ "PG_DIAG_CONTEXT",		PG_DIAG_CONTEXT },
2124 	{ "PG_DIAG_SOURCE_FILE",	PG_DIAG_SOURCE_FILE },
2125 	{ "PG_DIAG_SOURCE_LINE",	PG_DIAG_SOURCE_LINE },
2126 	{ "PG_DIAG_SOURCE_FUNCTION",	PG_DIAG_SOURCE_FUNCTION },
2127 
2128 	/* Error verbosity */
2129 	{ "PQERRORS_TERSE",		PQERRORS_TERSE },
2130 	{ "PQERRORS_DEFAULT",		PQERRORS_DEFAULT },
2131 	{ "PQERRORS_VERBOSE",		PQERRORS_VERBOSE },
2132 
2133 #if PG_VERSION_NUM >= 90100
2134 	/* PQping codes */
2135 	{ "PQPING_OK",			PQPING_OK },
2136 	{ "PQPING_REJECT",		PQPING_REJECT },
2137 	{ "PQPING_NO_RESPONSE",		PQPING_NO_RESPONSE },
2138 	{ "PQPING_NO_ATTEMPT",		PQPING_NO_ATTEMPT },
2139 #endif
2140 
2141 	/* Large objects */
2142 	{ "INV_READ",			INV_READ },
2143 	{ "INV_WRITE",			INV_WRITE },
2144 	{ "SEEK_CUR",			SEEK_CUR },
2145 	{ "SEEK_END",			SEEK_END },
2146 	{ "SEEK_SET",			SEEK_SET },
2147 
2148 	/* Miscellaneous values */
2149 	{ "InvalidOid",			InvalidOid },
2150 
2151 	{ NULL,				0 }
2152 };
2153 
2154 static void
pgsql_set_info(lua_State * L)2155 pgsql_set_info(lua_State *L)
2156 {
2157 	lua_pushliteral(L, "_COPYRIGHT");
2158 	lua_pushliteral(L, "Copyright (C) 2009 - 2020 by "
2159 	    "micro systems marc balmer");
2160 	lua_settable(L, -3);
2161 	lua_pushliteral(L, "_DESCRIPTION");
2162 	lua_pushliteral(L, "PostgreSQL binding for Lua");
2163 	lua_settable(L, -3);
2164 	lua_pushliteral(L, "_VERSION");
2165 	lua_pushliteral(L, "pgsql 1.6.8");
2166 	lua_settable(L, -3);
2167 }
2168 
2169 int
luaopen_pgsql(lua_State * L)2170 luaopen_pgsql(lua_State *L)
2171 {
2172 	int n;
2173 	struct luaL_Reg luapgsql[] = {
2174 		/* Database Connection Control Functions */
2175 		{ "connectdb", pgsql_connectdb },
2176 		{ "connectStart", pgsql_connectStart },
2177 		{ "libVersion", pgsql_libVersion },
2178 #if PG_VERSION_NUM >= 90100
2179 		{ "ping", pgsql_ping },
2180 #endif
2181 		{ "encryptPassword", pgsql_encryptPassword },
2182 		{ "unescapeBytea", pgsql_unescapeBytea },
2183 
2184 		/* SSL support */
2185 		{ "initOpenSSL", pgsql_initOpenSSL },
2186 		{ NULL, NULL }
2187 	};
2188 
2189 	struct luaL_Reg conn_methods[] = {
2190 		/* Database Connection Control Functions */
2191 		{ "connectPoll", pgsql_connectPoll },
2192 		{ "finish", conn_finish },
2193 		{ "reset", conn_reset },
2194 		{ "resetStart", conn_resetStart },
2195 		{ "resetPoll", conn_resetPoll },
2196 
2197 		/* Connection Status Functions */
2198 		{ "db", conn_db },
2199 		{ "user", conn_user },
2200 		{ "pass", conn_pass },
2201 		{ "host", conn_host },
2202 		{ "port", conn_port },
2203 		{ "tty", conn_tty },
2204 		{ "options", conn_options },
2205 		{ "status", conn_status },
2206 		{ "transactionStatus", conn_transactionStatus },
2207 		{ "parameterStatus", conn_parameterStatus },
2208 		{ "protocolVersion", conn_protocolVersion },
2209 		{ "serverVersion", conn_serverVersion },
2210 		{ "errorMessage", conn_errorMessage },
2211 		{ "socket", conn_socket },
2212 		{ "backendPID", conn_backendPID },
2213 		{ "connectionNeedsPassword", conn_connectionNeedsPassword },
2214 		{ "connectionUsedPassword", conn_connectionUsedPassword },
2215 #if PG_VERSION_NUM >= 90500
2216 		{ "sslInUse", conn_sslInUse },
2217 		{ "sslAttribute", conn_sslAttribute },
2218 		{ "sslAttributeNames", conn_sslAttributeNames },
2219 #endif
2220 
2221 		/* Command Execution Functions */
2222 		{ "escapeString", conn_escapeString },
2223 		{ "escapeLiteral", conn_escapeLiteral },
2224 		{ "escapeIdentifier", conn_escapeIdentifier },
2225 		{ "escapeBytea", conn_escapeBytea },
2226 		{ "exec", conn_exec },
2227 		{ "execParams", conn_execParams },
2228 		{ "prepare", conn_prepare },
2229 		{ "execPrepared", conn_execPrepared },
2230 		{ "describePrepared", conn_describePrepared },
2231 		{ "describePortal", conn_describePortal },
2232 
2233 		/* Asynchronous command processing */
2234 		{ "sendQuery", conn_sendQuery },
2235 		{ "sendQueryParams", conn_sendQueryParams },
2236 		{ "sendPrepare", conn_sendPrepare },
2237 		{ "sendQueryPrepared", conn_sendQueryPrepared },
2238 		{ "sendDescribePrepared", conn_sendDescribePrepared },
2239 		{ "sendDescribePortal", conn_sendDescribePortal },
2240 		{ "getResult", conn_getResult },
2241 		{ "cancel", conn_cancel },
2242 
2243 #if PG_VERSION_NUM >= 90200
2244 		/* Retrieving query results row-by-row */
2245 		{ "setSingleRowMode", conn_setSingleRowMode },
2246 #endif
2247 
2248 		/* Asynchronous Notifications Functions */
2249 		{ "notifies", conn_notifies },
2250 
2251 		/* Function associated with the COPY command */
2252 		{ "putCopyData", conn_putCopyData },
2253 		{ "putCopyEnd", conn_putCopyEnd },
2254 		{ "getCopyData", conn_getCopyData },
2255 
2256 		/* Control Functions */
2257 		{ "clientEncoding", conn_clientEncoding },
2258 		{ "setClientEncoding", conn_setClientEncoding },
2259 		{ "setErrorVerbosity", conn_setErrorVerbosity },
2260 		{ "trace", conn_trace },
2261 		{ "untrace", conn_untrace },
2262 
2263 		/* Miscellaneous Functions */
2264 		{ "consumeInput", conn_consumeInput },
2265 		{ "isBusy", conn_isBusy },
2266 		{ "setnonblocking", conn_setnonblocking },
2267 		{ "isnonblocking", conn_isnonblocking },
2268 		{ "flush", conn_flush },
2269 #if PG_VERSION_NUM >= 100000
2270 		{ "encryptPassword", conn_encryptPassword },
2271 #endif
2272 		/* Notice processing */
2273 		{ "setNoticeReceiver", conn_setNoticeReceiver },
2274 		{ "setNoticeProcessor", conn_setNoticeProcessor },
2275 
2276 		/* Large Objects */
2277 		{ "lo_create", conn_lo_create },
2278 		{ "lo_import", conn_lo_import },
2279 		{ "lo_import_with_oid", conn_lo_import_with_oid },
2280 		{ "lo_export", conn_lo_export },
2281 		{ "lo_open", conn_lo_open },
2282 		{ "lo_write", conn_lo_write },
2283 		{ "lo_read", conn_lo_read },
2284 		{ "lo_lseek", conn_lo_lseek },
2285 		{ "lo_tell", conn_lo_tell },
2286 		{ "lo_truncate", conn_lo_truncate },
2287 		{ "lo_close", conn_lo_close },
2288 		{ "lo_unlink", conn_lo_unlink },
2289 #if PG_VERSION_NUM >= 90300
2290 		{ "lo_lseek64", conn_lo_lseek64 },
2291 		{ "lo_tell64", conn_lo_tell64 },
2292 		{ "lo_truncate64", conn_lo_truncate64 },
2293 #endif
2294 		{ NULL, NULL }
2295 	};
2296 	struct luaL_Reg res_methods[] = {
2297 		/* Main functions */
2298 		{ "status", res_status },
2299 		{ "resStatus", res_resStatus },
2300 		{ "errorMessage", res_errorMessage },
2301 		{ "errorField", res_errorField },
2302 
2303 		/* Retrieving query result information */
2304 		{ "ntuples", res_ntuples },
2305 		{ "nfields", res_nfields },
2306 		{ "fname", res_fname },
2307 		{ "fnumber", res_fnumber },
2308 		{ "ftable", res_ftable },
2309 		{ "ftablecol", res_ftablecol },
2310 		{ "fformat", res_fformat },
2311 		{ "ftype", res_ftype },
2312 		{ "fmod", res_fmod },
2313 		{ "fsize", res_fsize },
2314 		{ "binaryTuples", res_binaryTuples },
2315 		{ "getvalue", res_getvalue },
2316 		{ "getisnull", res_getisnull },
2317 		{ "getlength", res_getlength },
2318 		{ "nparams", res_nparams },
2319 		{ "paramtype", res_paramtype },
2320 
2321 		/* Other result information */
2322 		{ "cmdStatus", res_cmdStatus },
2323 		{ "cmdTuples", res_cmdTuples },
2324 		{ "oidValue", res_oidValue },
2325 		{ "oidStatus", res_oidStatus },
2326 
2327 		/* Lua specific extension */
2328 		{ "copy", res_copy },
2329 		{ "fields", res_fields },
2330 		{ "tuples", res_tuples },
2331 		{ "clear", res_clear },
2332 		{ NULL, NULL }
2333 	};
2334 	struct luaL_Reg notify_methods[] = {
2335 		{ "relname", notify_relname },
2336 		{ "pid", notify_pid },
2337 		{ "extra", notify_extra },
2338 		{ NULL, NULL }
2339 	};
2340 	if (luaL_newmetatable(L, CONN_METATABLE)) {
2341 #if LUA_VERSION_NUM >= 502
2342 		luaL_setfuncs(L, conn_methods, 0);
2343 #else
2344 		luaL_register(L, NULL, conn_methods);
2345 #endif
2346 		lua_pushliteral(L, "__gc");
2347 		lua_pushcfunction(L, conn_finish);
2348 		lua_settable(L, -3);
2349 
2350 		lua_pushliteral(L, "__index");
2351 		lua_pushvalue(L, -2);
2352 		lua_settable(L, -3);
2353 
2354 		lua_pushliteral(L, "__metatable");
2355 		lua_pushliteral(L, "must not access this metatable");
2356 		lua_settable(L, -3);
2357 	}
2358 	lua_pop(L, 1);
2359 
2360 	if (luaL_newmetatable(L, RES_METATABLE)) {
2361 #if LUA_VERSION_NUM >= 502
2362 		luaL_setfuncs(L, res_methods, 0);
2363 #else
2364 		luaL_register(L, NULL, res_methods);
2365 #endif
2366 		lua_pushliteral(L, "__gc");
2367 		lua_pushcfunction(L, res_clear);
2368 		lua_settable(L, -3);
2369 
2370 		lua_pushliteral(L, "__index");
2371 		lua_pushcfunction(L, res_index);
2372 		lua_settable(L, -3);
2373 
2374 		lua_pushliteral(L, "__len");
2375 		lua_pushcfunction(L, res_ntuples);
2376 		lua_settable(L, -3);
2377 
2378 		lua_pushliteral(L, "__metatable");
2379 		lua_pushliteral(L, "must not access this metatable");
2380 		lua_settable(L, -3);
2381 	}
2382 	lua_pop(L, 1);
2383 
2384 	if (luaL_newmetatable(L, NOTIFY_METATABLE)) {
2385 #if LUA_VERSION_NUM >= 502
2386 		luaL_setfuncs(L, notify_methods, 0);
2387 #else
2388 		luaL_register(L, NULL, notify_methods);
2389 #endif
2390 		lua_pushliteral(L, "__gc");
2391 		lua_pushcfunction(L, notify_clear);
2392 		lua_settable(L, -3);
2393 
2394 		lua_pushliteral(L, "__index");
2395 		lua_pushvalue(L, -2);
2396 		lua_settable(L, -3);
2397 
2398 		lua_pushliteral(L, "__metatable");
2399 		lua_pushliteral(L, "must not access this metatable");
2400 		lua_settable(L, -3);
2401 	}
2402 	lua_pop(L, 1);
2403 
2404 	if (luaL_newmetatable(L, TUPLE_METATABLE)) {
2405 		lua_pushliteral(L, "__index");
2406 		lua_pushcfunction(L, tuple_index);
2407 		lua_settable(L, -3);
2408 
2409 		lua_pushliteral(L, "__len");
2410 		lua_pushcfunction(L, tuple_length);
2411 		lua_settable(L, -3);
2412 
2413 		lua_pushliteral(L, "__metatable");
2414 		lua_pushliteral(L, "must not access this metatable");
2415 		lua_settable(L, -3);
2416 	}
2417 	lua_pop(L, 1);
2418 
2419 	if (luaL_newmetatable(L, FIELD_METATABLE)) {
2420 		lua_pushliteral(L, "__metatable");
2421 		lua_pushliteral(L, "must not access this metatable");
2422 		lua_settable(L, -3);
2423 	}
2424 	lua_pop(L, 1);
2425 
2426 	if (luaL_newmetatable(L, GCMEM_METATABLE)) {
2427 		lua_pushliteral(L, "__gc");
2428 		lua_pushcfunction(L, gcmem_clear);
2429 		lua_settable(L, -3);
2430 	}
2431 	lua_pop(L, 1);
2432 
2433 #if LUA_VERSION_NUM >= 502
2434 	luaL_newlib(L, luapgsql);
2435 #else
2436 	luaL_register(L, "pgsql", luapgsql);
2437 #endif
2438 	pgsql_set_info(L);
2439 	for (n = 0; pgsql_constant[n].name != NULL; n++) {
2440 		lua_pushinteger(L, pgsql_constant[n].value);
2441 		lua_setfield(L, -2, pgsql_constant[n].name);
2442 	};
2443 
2444 	return 1;
2445 }
2446