| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | /*-------------------------------------------------------------------------
 | 
					
						
							|  |  |  |  * pgut-spi.c | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-04-29 05:06:48 +00:00
										 |  |  |  * Portions Copyright (c) 2008-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION | 
					
						
							|  |  |  |  * Portions Copyright (c) 2011, Itagaki Takahiro | 
					
						
							| 
									
										
										
										
											2012-11-11 03:00:00 +00:00
										 |  |  |  * Portions Copyright (c) 2012, The Reorg Development Team | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  |  *------------------------------------------------------------------------- | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "postgres.h"
 | 
					
						
							|  |  |  | #include "pgut-spi.h"
 | 
					
						
							| 
									
										
										
										
											2012-09-20 03:48:53 +00:00
										 |  |  | #include "lib/stringinfo.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | #define EXEC_FAILED(ret, expected) \
 | 
					
						
							|  |  |  | 	(((expected) > 0 && (ret) != (expected)) || (ret) < 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-18 20:32:18 -07:00
										 |  |  | static void | 
					
						
							|  |  |  | appendStringInfoVA_s(StringInfo str, const char *fmt, va_list args) | 
					
						
							|  |  |  | __attribute__((format(printf, 2, 0))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | termStringInfo(StringInfo str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (str && str->data) | 
					
						
							|  |  |  | 		pfree(str->data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | /* appendStringInfoVA + automatic buffer extension */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | appendStringInfoVA_s(StringInfo str, const char *fmt, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while (!appendStringInfoVA(str, fmt, args)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* Double the buffer size and try again. */ | 
					
						
							|  |  |  | 		enlargeStringInfo(str, str->maxlen); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | /* simple execute */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | execute(int expected, const char *sql) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int ret = SPI_execute(sql, false, 0); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	if EXEC_FAILED(ret, expected) | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 		elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql, ret, expected); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* execute prepared plan */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int	ret = SPI_execute_plan(plan, values, nulls, false, 0); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	if EXEC_FAILED(ret, expected) | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 		elog(ERROR, "query failed: (code=%d, expected=%d)", ret, expected); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* execute sql with format */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | execute_with_format(int expected, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list			ap; | 
					
						
							|  |  |  | 	StringInfoData	sql; | 
					
						
							|  |  |  | 	int				ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	initStringInfo(&sql); | 
					
						
							|  |  |  | 	va_start(ap, format); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	appendStringInfoVA_s(&sql, format, ap); | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 	va_end(ap); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-26 20:08:47 -07:00
										 |  |  | 	if (sql.len == 0) | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 		elog(WARNING, "execute_with_format(%s)", format); | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 	ret = SPI_exec(sql.data, 0); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	if EXEC_FAILED(ret, expected) | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 		elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", sql.data, ret, expected); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	termStringInfo(&sql); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | execute_with_args(int expected, const char *src, int nargs, Oid argtypes[], Datum values[], const bool nulls[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int		ret; | 
					
						
							|  |  |  | 	int		i; | 
					
						
							|  |  |  | 	char	c_nulls[FUNC_MAX_ARGS]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < nargs; i++) | 
					
						
							|  |  |  | 		c_nulls[i] = (nulls[i] ? 'n' : ' '); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = SPI_execute_with_args(src, nargs, argtypes, values, c_nulls, false, 0); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	if EXEC_FAILED(ret, expected) | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 		elog(ERROR, "query failed: (sql=%s, code=%d, expected=%d)", src, ret, expected); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | execute_with_format_args(int expected, const char *format, int nargs, Oid argtypes[], Datum values[], const bool nulls[], ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list			ap; | 
					
						
							|  |  |  | 	StringInfoData	sql; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	initStringInfo(&sql); | 
					
						
							|  |  |  | 	va_start(ap, nulls); | 
					
						
							| 
									
										
										
										
											2009-07-03 05:52:31 +00:00
										 |  |  | 	appendStringInfoVA_s(&sql, format, ap); | 
					
						
							| 
									
										
										
										
											2009-07-02 09:55:57 +00:00
										 |  |  | 	va_end(ap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	execute_with_args(expected, sql.data, nargs, argtypes, values, nulls); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	termStringInfo(&sql); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if PG_VERSION_NUM < 80400
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | SPI_execute_with_args(const char *src, | 
					
						
							|  |  |  | 					  int nargs, Oid *argtypes, | 
					
						
							|  |  |  | 					  Datum *values, const char *nulls, | 
					
						
							|  |  |  | 					  bool read_only, long tcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	SPIPlanPtr	plan; | 
					
						
							|  |  |  | 	int			ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	plan = SPI_prepare(src, nargs, argtypes); | 
					
						
							|  |  |  | 	if (plan == NULL) | 
					
						
							|  |  |  | 		return SPI_result; | 
					
						
							|  |  |  | 	ret = SPI_execute_plan(plan, values, nulls, read_only, tcount); | 
					
						
							|  |  |  | 	SPI_freeplan(plan); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |