>From ad0175d7f34a950fd17fb23fc3efb632d34b24b7 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Sat, 24 Jan 2015 00:44:21 +0200
Subject: [PATCH] Don't do premature execution. Use v3 Parse instead.

Remove the DisallowPremature config option.

diff --git a/Makefile.am b/Makefile.am
index c266e77..7564151 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -124,6 +124,7 @@ EXTRA_DIST = license.txt readme.txt readme_winbuild.txt \
 	test/expected/param-conversions.out \
 	test/expected/param-conversions_1.out \
 	test/expected/positioned-update.out \
+	test/expected/premature.out \
 	test/expected/prepare.out \
 	test/expected/quotes.out \
 	test/expected/result-conversions.out \
@@ -172,6 +173,7 @@ EXTRA_DIST = license.txt readme.txt readme_winbuild.txt \
 	test/src/params-test.c \
 	test/src/param-conversions-test.c \
 	test/src/positioned-update-test.c \
+	test/src/premature-test.c \
 	test/src/prepare-test.c \
 	test/src/quotes-test.c \
 	test/src/result-conversions-test.c \
diff --git a/bind.c b/bind.c
index 850db9d..c82985f 100644
--- a/bind.c
+++ b/bind.c
@@ -132,7 +132,7 @@ PGAPI_BindParameter(HSTMT hstmt,
 #endif /* NOT_USED */
 
 	/* Clear premature result */
-	if (stmt->status == STMT_PREMATURE)
+	if (stmt->status == STMT_DESCRIBED)
 		SC_recycle_statement(stmt);
 
 	mylog("%s: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d,", func, ipar, fParamType, fCType, fSqlType, cbColDef, ibScale);
@@ -353,7 +353,7 @@ inolog("howTo=%d\n", SC_get_prepare_method(stmt));
 			case NAMED_PARSE_REQUEST:
 			case PARSE_TO_EXEC_ONCE:
 			case PARSE_REQ_FOR_INFO:
-				if (ret = prepareParameters(stmt), SQL_ERROR == ret)
+				if (ret = prepareParameters(stmt, FALSE), SQL_ERROR == ret)
 					goto cleanup;
 		}
 	}
@@ -457,8 +457,6 @@ inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
 		stmt->num_params = *pcpar;
 		stmt->proc_return = proc_return;
 		stmt->multi_statement = multi;
-		if (multi)
-			SC_no_parse_tricky(stmt);
 	}
 inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
 	return SQL_SUCCESS;
diff --git a/bind.h b/bind.h
index 5779640..a9154d7 100644
--- a/bind.h
+++ b/bind.h
@@ -111,8 +111,8 @@ void	reset_a_putdata_info(PutDataInfo *pdata, int ipar);
 void	PDATA_free_params(PutDataInfo *pdata, char option);
 void	SC_param_next(const StatementClass*, int *param_number, ParameterInfoClass **, ParameterImplClass **);
 
-RETCODE       prepareParameters(StatementClass *stmt);
-RETCODE       prepareParametersNoDesc(StatementClass *stmt);
+RETCODE       prepareParameters(StatementClass *stmt, BOOL fake_params);
+RETCODE       prepareParametersNoDesc(StatementClass *stmt, BOOL fake_params);
 int	decideHowToPrepare(StatementClass *stmt, BOOL force);
 
 #endif
diff --git a/connection.c b/connection.c
index 8a924eb..0ef38af 100644
--- a/connection.c
+++ b/connection.c
@@ -270,7 +270,6 @@ CC_conninfo_init(ConnInfo *conninfo, UInt4 option)
 	if (0 != (CLEANUP_FOR_REUSE & option))
 		CC_conninfo_release(conninfo);
 	memset(conninfo, 0, sizeof(ConnInfo));
-	conninfo->disallow_premature = -1;
 	conninfo->allow_keyset = -1;
 	conninfo->lf_conversion = -1;
 	conninfo->true_is_minus1 = -1;
@@ -322,7 +321,6 @@ CC_copy_conninfo(ConnInfo *ci, const ConnInfo *sci)
 	CORR_STRCPY(translation_option);
 	CORR_VALCPY(password_required);
 	NAME_TO_NAME(ci->conn_settings, sci->conn_settings);
-	CORR_VALCPY(disallow_premature);
 	CORR_VALCPY(allow_keyset);
 	CORR_VALCPY(updatable_cursors);
 	CORR_VALCPY(lf_conversion);
diff --git a/connection.h b/connection.h
index 262a1e4..20d0bbb 100644
--- a/connection.h
+++ b/connection.h
@@ -227,7 +227,6 @@ typedef struct
 	char		translation_option[SMALL_REGISTRY_LEN];
 	char		password_required;
 	pgNAME		conn_settings;
-	signed char	disallow_premature;
 	signed char	allow_keyset;
 	signed char	updatable_cursors;
 	signed char	lf_conversion;
diff --git a/convert.c b/convert.c
index c9f78d5..f303493 100644
--- a/convert.c
+++ b/convert.c
@@ -1930,7 +1930,6 @@ inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
  *--------------------------------------------------------------------
  */
 
-#define	FLGP_PREPARE_DUMMY_CURSOR	1L
 #define	FLGP_USING_CURSOR	(1L << 1)
 #define	FLGP_SELECT_INTO		(1L << 2)
 #define	FLGP_SELECT_FOR_UPDATE_OR_SHARE	(1L << 3)
@@ -2606,9 +2605,14 @@ buildProcessedStmt(const char *srvquery, ssize_t endp, int num_params)
  * Split a possible multi-statement query into parts, and replace ?-style
  * parameter markers with $n. The resulting queries are stored in a linked
  * list in stmt->processed_statements.
+ *
+ * If 'fake_params' is true, we will replace ?-style parameter markers with
+ * fake parameter values instead. This is used when a query's result columns
+ * have to be described (SQLPrepare+SQLDescribeCol) before executing the
+ * query, in UseServerSidePrepare=0 mode.
  */
 RETCODE
-prepareParametersNoDesc(StatementClass *stmt)
+prepareParametersNoDesc(StatementClass *stmt, BOOL fake_params)
 {
 	CSTR		func = "process_statements";
 	RETCODE		retval;
@@ -2627,7 +2631,8 @@ inolog("prepareParametersNoDesc\n");
 	qp = &query_org;
 	QP_initialize(qp, stmt);
 	qb = &query_crt;
-	if (QB_initialize(qb, qp->stmt_len, stmt, RPM_BUILDING_PREPARE_STATEMENT) < 0)
+	if (QB_initialize(qb, qp->stmt_len, stmt,
+					  fake_params ? RPM_FAKE_PARAMS : RPM_BUILDING_PREPARE_STATEMENT) < 0)
 		return SQL_ERROR;
 
 	for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
@@ -2657,7 +2662,9 @@ inolog("prepareParametersNoDesc\n");
 	SC_scanQueryAndCountParams(orgquery, conn, &endp1, &num_p1, &multi, NULL);
 	SC_scanQueryAndCountParams(srvquery, conn, &endp2, NULL, NULL, NULL);
 	mylog("%s:parsed for the first command length=%d(%d) num_p=%d\n", func, endp2, endp1, num_p1);
-	pstmt = buildProcessedStmt(srvquery, endp2 < 0 ? SQL_NTS : endp2, num_p1);
+	pstmt = buildProcessedStmt(srvquery,
+							   endp2 < 0 ? SQL_NTS : endp2,
+							   fake_params ? 0 : num_p1);
 	if (!pstmt)
 		goto cleanup;
 	stmt->processed_statements = last_pstmt = pstmt;
@@ -2669,7 +2676,9 @@ inolog("prepareParametersNoDesc\n");
 		SC_scanQueryAndCountParams(orgquery, conn, &endp1, &num_p1, &multi, NULL);
 		SC_scanQueryAndCountParams(srvquery, conn, &endp2, &num_p2, NULL, NULL);
 		mylog("%s:parsed for the subsequent command length=%d(%d) num_p=%d\n", func, endp2, endp1, num_p1);
-		pstmt = buildProcessedStmt(srvquery, endp2 < 0 ? SQL_NTS : endp2, num_p1);
+		pstmt = buildProcessedStmt(srvquery,
+								   endp2 < 0 ? SQL_NTS : endp2,
+								   fake_params ? 0 : num_p1);
 		if (!pstmt)
 			goto cleanup;
 		last_pstmt->next = pstmt;
@@ -2747,7 +2756,7 @@ cleanup:
  * Process the original SQL query, and and ask the server describe the
  * parameters.
  */
-RETCODE	prepareParameters(StatementClass *stmt)
+RETCODE	prepareParameters(StatementClass *stmt, BOOL fake_params)
 {
 	ConnectionClass *conn = SC_get_conn(stmt);
 
@@ -2768,7 +2777,7 @@ RETCODE	prepareParameters(StatementClass *stmt)
 
 inolog("prepareParameters\n");
 
-	if (prepareParametersNoDesc(stmt) == SQL_ERROR)
+	if (prepareParametersNoDesc(stmt, fake_params) == SQL_ERROR)
 		return SQL_ERROR;
 	return desc_params_and_sync(stmt);
 }
@@ -2788,7 +2797,6 @@ copy_statement_with_parameters(StatementClass *stmt, BOOL buildPrepareStatement)
 
 	char	   *new_statement;
 
-	BOOL	begin_first = FALSE, prepare_dummy_cursor = FALSE;
 	ConnectionClass *conn = SC_get_conn(stmt);
 	ConnInfo   *ci = &(conn->connInfo);
 	const		char *bestitem = NULL;
@@ -2873,9 +2881,6 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 	}
 
 	SC_no_fetchcursor(stmt);
-	SC_no_pre_executable(stmt);
-	if (SC_may_use_cursor(stmt))
-		SC_set_pre_executable(stmt);
 	qb = &query_crt;
 	qb->query_statement = NULL;
 	if (PREPARED_PERMANENTLY == stmt->prepared)
@@ -2908,12 +2913,7 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 	}
 
 	/* Otherwise... */
-	if (ci->disallow_premature)
-		prepare_dummy_cursor = stmt->pre_executing;
-	if (prepare_dummy_cursor)
-		qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
-	if (QB_initialize(qb, qp->stmt_len, stmt,
-					  stmt->pre_executing ? RPM_FAKE_PARAMS : RPM_REPLACE_PARAMS) < 0)
+	if (QB_initialize(qb, qp->stmt_len, stmt, RPM_REPLACE_PARAMS) < 0)
 	{
 		retval = SQL_ERROR;
 		goto cleanup;
@@ -2925,17 +2925,7 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 	{
 		const char *opt_scroll = NULL_STRING, *opt_hold = NULL_STRING;
 
-		if (prepare_dummy_cursor)
-		{
-			SC_set_fetchcursor(stmt);
-			opt_scroll = " scroll";
-			if (!CC_is_in_trans(conn))
-			{
-				strcpy(new_statement, "BEGIN;");
-				begin_first = TRUE;
-			}
-		}
-		else if (ci->drivers.use_declarefetch
+		if (ci->drivers.use_declarefetch
 			 /** && SQL_CONCUR_READ_ONLY == stmt->options.scroll_concurrency **/
 			)
 		{
@@ -2976,7 +2966,6 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 
 	new_statement = qb->query_statement;
 	stmt->statement_type = qp->statement_type;
-	stmt->inaccurate_result = (0 != (qb->flags & FLGB_INACCURATE_RESULT));
 	if (0 == (qp->flags & FLGP_USING_CURSOR))
 		SC_no_fetchcursor(stmt);
 #ifdef NOT_USED	/* this seems problematic */
@@ -3005,7 +2994,6 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 	if (0 != (qp->flags & FLGP_SELECT_INTO) ||
 	    0 != (qp->flags & FLGP_MULTIPLE_STATEMENT))
 	{
-		SC_no_pre_executable(stmt);
 		stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
 	}
 	if (0 != (qp->flags & FLGP_SELECT_FOR_UPDATE_OR_SHARE))
@@ -3059,17 +3047,6 @@ inolog("type=%d concur=%d\n", stmt->options.cursor_type, stmt->options.scroll_co
 		memcpy(stmt->load_statement, qb->query_statement + qp->declare_pos, npos);
 		stmt->load_statement[npos] = '\0';
 	}
-	if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
-	{
-		char		fetchstr[128];
-
-		sprintf(fetchstr, ";fetch backward in \"%s\";close \"%s\";",
-				SC_cursor_name(stmt), SC_cursor_name(stmt));
-		if (begin_first && CC_is_in_autocommit(conn))
-			strcat(fetchstr, "COMMIT;");
-		CVT_APPEND_STR(qb, fetchstr);
-		stmt->inaccurate_result = TRUE;
-	}
 
 	stmt->stmt_with_params = qb->query_statement;
 	retval = SQL_SUCCESS;
@@ -3517,16 +3494,8 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
 							flg = table_for_update_or_share(F_OldPtr(qp), &endpos);
 							if (0 != (FLGP_SELECT_FOR_UPDATE_OR_SHARE & flg))
 							{
-								if (qp->flags & FLGP_PREPARE_DUMMY_CURSOR)
-								{
-									qb->npos -= 4;
-									qp->opos += endpos;
-								}
-								else
-								{
-									qp->flags |= flg;
-									remove_declare_cursor(qb, qp);
-								}
+								qp->flags |= flg;
+								remove_declare_cursor(qb, qp);
 							}
 							else
 								qp->flags |= flg;
diff --git a/dlg_specific.c b/dlg_specific.c
index 4361f26..6ab7464 100644
--- a/dlg_specific.c
+++ b/dlg_specific.c
@@ -310,7 +310,6 @@ inolog("hlen=%d", hlen);
 			INI_EXTRASYSTABLEPREFIXES "=%s;"
 			INI_LFCONVERSION "=%d;"
 			INI_UPDATABLECURSORS "=%d;"
-			INI_DISALLOWPREMATURE "=%d;"
 			INI_TRUEISMINUS1 "=%d;"
 			INI_INT8AS "=%d;"
 			INI_BYTEAASLONGVARBINARY "=%d;"
@@ -345,7 +344,6 @@ inolog("hlen=%d", hlen);
 			,ci->drivers.extra_systable_prefixes
 			,ci->lf_conversion
 			,ci->allow_keyset
-			,ci->disallow_premature
 			,ci->true_is_minus1
 			,ci->int8_as
 			,ci->bytea_as_longvarbinary
@@ -364,8 +362,6 @@ inolog("hlen=%d", hlen);
 	if (abbrev || olen >= nlen || olen < 0)
 	{
 		flag = 0;
-		if (ci->disallow_premature)
-			flag |= BIT_DISALLOWPREMATURE;
 		if (ci->allow_keyset)
 			flag |= BIT_UPDATABLECURSORS;
 		if (ci->lf_conversion)
@@ -500,7 +496,6 @@ unfoldCXAttribute(ConnInfo *ci, const char *value)
 		sscanf(cnt, "%x", &count);
 		sscanf(value + 2, "%x", &flag);
 	}
-	ci->disallow_premature = (char)((flag & BIT_DISALLOWPREMATURE) != 0);
 	ci->allow_keyset = (char)((flag & BIT_UPDATABLECURSORS) != 0);
 	ci->lf_conversion = (char)((flag & BIT_LFCONVERSION) != 0);
 	if (count < 4)
@@ -613,8 +608,6 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
 		else
 			ci->conn_settings = decode(value);
 	}
-	else if (stricmp(attribute, INI_DISALLOWPREMATURE) == 0 || stricmp(attribute, ABBR_DISALLOWPREMATURE) == 0)
-		ci->disallow_premature = atoi(value);
 	else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, ABBR_UPDATABLECURSORS) == 0)
 		ci->allow_keyset = atoi(value);
 	else if (stricmp(attribute, INI_LFCONVERSION) == 0 || stricmp(attribute, ABBR_LFCONVERSION) == 0)
@@ -696,7 +689,7 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
 	else
 		found = FALSE;
 
-	mylog("%s: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',conn_settings='%s',disallow_premature=%d)\n", func, ci->dsn, ci->server, ci->database, ci->username, NAME_IS_VALID(ci->password) ? "xxxxx" : "", ci->port, ci->onlyread, ci->conn_settings, ci->disallow_premature);
+	mylog("%s: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',conn_settings='%s')\n", func, ci->dsn, ci->server, ci->database, ci->username, NAME_IS_VALID(ci->password) ? "xxxxx" : "", ci->port, ci->onlyread, ci->conn_settings);
 
 	return found;
 }
@@ -779,8 +772,6 @@ getDSNdefaults(ConnInfo *ci)
 	if (ci->row_versioning[0] == '\0')
 		sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING);
 
-	if (ci->disallow_premature < 0)
-		ci->disallow_premature = DEFAULT_DISALLOWPREMATURE;
 	if (ci->allow_keyset < 0)
 		ci->allow_keyset = DEFAULT_UPDATABLECURSORS;
 	if (ci->lf_conversion < 0)
@@ -935,13 +926,6 @@ getDSNinfo(ConnInfo *ci, char overwrite)
 	if (ci->translation_option[0] == '\0' || overwrite)
 		SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
 
-	if (ci->disallow_premature < 0 || overwrite)
-	{
-		SQLGetPrivateProfileString(DSN, INI_DISALLOWPREMATURE, "", temp, sizeof(temp), ODBC_INI);
-		if (temp[0])
-			ci->disallow_premature = atoi(temp);
-	}
-
 	if (ci->allow_keyset < 0 || overwrite)
 	{
 		SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI);
@@ -1237,11 +1221,6 @@ writeDSNinfo(const ConnInfo *ci)
 								 encoded_item,
 								 ODBC_INI);
 
-	sprintf(temp, "%d", ci->disallow_premature);
-	SQLWritePrivateProfileString(DSN,
-								 INI_DISALLOWPREMATURE,
-								 temp,
-								 ODBC_INI);
 	sprintf(temp, "%d", ci->allow_keyset);
 	SQLWritePrivateProfileString(DSN,
 								 INI_UPDATABLECURSORS,
diff --git a/dlg_specific.h b/dlg_specific.h
index 6a2fcac..30ea389 100644
--- a/dlg_specific.h
+++ b/dlg_specific.h
@@ -134,8 +134,14 @@ extern "C" {
 #define INI_TRANSLATIONNAME		"TranslationName"
 #define INI_TRANSLATIONDLL		"TranslationDLL"
 #define INI_TRANSLATIONOPTION		"TranslationOption"
-#define INI_DISALLOWPREMATURE		"DisallowPremature"
-#define ABBR_DISALLOWPREMATURE		"C3"
+/*
+ * "DisallowPremature", abbreviated "C3", used to mean that we should not
+ * execute a statement prematurely, before SQLExecute() when e.g.
+ * SQLPrepare+SQLDescribeCol is called. We never do that anymore.
+ *
+#define INI_DISALLOWPREMATURE          "DisallowPremature"
+#define ABBR_DISALLOWPREMATURE         "C3"
+*/
 #define INI_UPDATABLECURSORS		"UpdatableCursors"
 #define ABBR_UPDATABLECURSORS		"C4"
 #define INI_LFCONVERSION		"LFConversion"
@@ -182,10 +188,10 @@ extern "C" {
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 #define INI_XAOPT			"XaOpt"
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
-/* Bit representaion for abbreviated connection strings */
+/* Bit representation for abbreviated connection strings */
 #define BIT_LFCONVERSION			(1L)
 #define BIT_UPDATABLECURSORS			(1L<<1)
-#define BIT_DISALLOWPREMATURE			(1L<<2)
+/* #define BIT_DISALLOWPREMATURE                  (1L<<2) */
 #define BIT_UNIQUEINDEX				(1L<<3)
 #define BIT_UNKNOWN_DONTKNOW			(1L<<6)
 #define BIT_UNKNOWN_ASMAX			(1L<<7)
@@ -244,7 +250,6 @@ extern "C" {
 
 #define DEFAULT_EXTRASYSTABLEPREFIXES	"dd_"
 
-#define DEFAULT_DISALLOWPREMATURE	0
 #define DEFAULT_TRUEISMINUS1		0
 #define DEFAULT_UPDATABLECURSORS	1
 #ifdef	WIN32
diff --git a/dlg_wingui.c b/dlg_wingui.c
index d897525..23f1189 100644
--- a/dlg_wingui.c
+++ b/dlg_wingui.c
@@ -531,7 +531,6 @@ ds_options_update(HWND hdlg, ConnInfo *ci)
 	sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
 
 	sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
-	ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE);
 	ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
 	ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
 	ci->allow_keyset = IsDlgButtonChecked(hdlg, DS_UPDATABLECURSORS);
@@ -661,7 +660,6 @@ ds_options2Proc(HWND hdlg,
 			CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
 			CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
 			CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables));
-			CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature);
 			CheckDlgButton(hdlg, DS_LFCONVERSION, ci->lf_conversion);
 			CheckDlgButton(hdlg, DS_TRUEISMINUS1, ci->true_is_minus1);
 			CheckDlgButton(hdlg, DS_UPDATABLECURSORS, ci->allow_keyset);
diff --git a/docs/config-opt.html b/docs/config-opt.html
index c4e06d9..9c77320 100644
--- a/docs/config-opt.html
+++ b/docs/config-opt.html
@@ -333,17 +333,6 @@
 	</TR>
 	<TR>
 		<TD WIDTH=38%>
-			Disallow Premature
-		</TD>
-		<TD WIDTH=31%>
-			DisallowPremature
-		</TD>
-		<TD WIDTH=31%>
-			C3
-		</TD>
-	</TR>
-	<TR>
-		<TD WIDTH=38%>
 			Updateable Cursors
 		</TD>
 		<TD WIDTH=31%>
diff --git a/docs/config.html b/docs/config.html
index dd18931..63d077b 100644
--- a/docs/config.html
+++ b/docs/config.html
@@ -36,9 +36,9 @@ the old podbc32.<br />&nbsp;</li>
 Log communications to/from the backend to that file. This is good
 for debugging problems.<br />&nbsp;</li>
 
-<li><b>Parse Statements:</b> Tell the driver how to gather the information about result columns of queries. See also <em>Disallow Premature</em> and <em>ServerSide Prepare</em> options.<br>
-The driver checks this option first. If disabled then it checks the Server Side Prepare option. If disabled also it checks the Disallow Premature option.<br>
-If neither of them is specified the driver would execute the prepared statement prematurely when the application inquires the result columns' info.<br><br>
+<li><b>Parse Statements:</b> Tell the driver how to gather the information about result columns of queries. See also <em>ServerSide Prepare</em> options.<br>
+The driver checks this option first. If disabled then it checks the Server Side Prepare option.<br>
+<br>
 
 If this option is enabled,
 the driver will parse an SQL query statement to identify the columns and
@@ -154,42 +154,10 @@ option well. See the <a "https://odbc.postgresql.org/faq.html">faq</a>
 for details on what you need to do to your database to allow for the row
 versioning feature to be used.<br />&nbsp;</li>
 
-<li><b>Disallow Premature:</b>
-<b><em>Server side prepare</em></b> is a more preferable option.<br>
-Tell the driver how to gather the information about result columns. See also <em>Parse Staements</em> and <em>Server Side Prepare</em> options.<br>
-This is an option to compensate for the lack of a server's <em>Prepare</em> functionality.
-For example, (Middleware) applications issue the following ODBC API calls.<br><br>
-
-   SQLPrepare(hstmt, "select ...", ..)<br><br>
-
-In most cases they have to know how many fields, what kind
-of fields they would return and so they would issue<br><br>
-
-   SQLNumResultCols and/or <br>
-   SQLDescribeCols/SQLColAttribute etc.<br><br>
-
-The problem is how the psqlODBC driver answers the inquiry. PostgreSQL hadn't
-provided the <em>Prepare</em> functionality until 7.4 and we couldn't ask the
-backend about it directly.
-
-When using Disallow Premature, the driver will get the column info as follows:<br><br>
-<i>
-&nbsp;&nbsp;&nbsp;begin;(unless in a transaction)<br>
-&nbsp;&nbsp;&nbsp;declare cursor .. for select ...<br>
-&nbsp;&nbsp;&nbsp;fetch backward in ..<br>
-&nbsp;&nbsp;&nbsp;close ..<br><br>
-</i>
-The driver gets the field info using the fetch backward's result. The fetch
-backward command returns no row but returns the field info. Though the command
-is expected to be returned immediately it isn't true for 7.0- servers
-unfortunately.
-The 7.1 or later servers <b>do</b> seem to return from the fetch backward
-command immediately.<br />&nbsp;</li>
-
 <li><b>True is -1:</b> Represent TRUE as -1 for compatibility with some applications.
 <br />&nbsp;</li>
 
-<li><b>Server side prepare:</b>If set, the driver uses server-side prepared statements. See also <em>Parse Statement</em> and <em>Disallow Premature</em> options.
+<li><b>Server side prepare:</b>If set, the driver uses server-side prepared statements. See also <em>Parse Statement</em> option.
 
 <li><b>use gssapi for GSS request:</b> GSSAPI use to AUTH_REQ_GSS request from a server.(only Windows)<br />&nbsp;</li>
 
diff --git a/execute.c b/execute.c
index 612e7bb..2eeffce 100644
--- a/execute.c
+++ b/execute.c
@@ -62,8 +62,8 @@ PGAPI_Prepare(HSTMT hstmt,
 	SC_set_prepared(self, NOT_YET_PREPARED);
 	switch (self->status)
 	{
-		case STMT_PREMATURE:
-			mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n");
+		case STMT_DESCRIBED:
+			mylog("**** PGAPI_Prepare: STMT_DESCRIBED, recycle\n");
 			SC_recycle_statement(self); /* recycle the statement, but do
 										 * not remove parameter bindings */
 			break;
@@ -174,10 +174,10 @@ inolog("a2\n");
 
 	/*
 	 * If an SQLPrepare was performed prior to this, but was left in the
-	 * premature state because an error occurred prior to SQLExecute then
+	 * described state because an error occurred prior to SQLExecute then
 	 * set the statement to finished so it can be recycled.
 	 */
-	if (stmt->status == STMT_PREMATURE)
+	if (stmt->status == STMT_DESCRIBED)
 		stmt->status = STMT_FINISHED;
 
 	stmt->statement_type = statement_type(stmt->statement);
@@ -259,8 +259,6 @@ decideHowToPrepare(StatementClass *stmt, BOOL force)
 
 	if (0 != method) /* a method was already determined */
 		return method;
-	if (stmt->inaccurate_result)
-		return method;
 	switch (stmt->prepare)
 	{
 		case NON_PREPARE_STATEMENT: /* not a prepare statement */
@@ -426,11 +424,9 @@ RETCODE	Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
 	cursor_type = stmt->options.cursor_type;
 	scroll_concurrency = stmt->options.scroll_concurrency;
 	/* Prepare the statement if possible at backend side */
-	if (!stmt->inaccurate_result)
-	{
-		if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
-			prepare_before_exec = TRUE;
-	}
+	if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
+		prepare_before_exec = TRUE;
+
 inolog("prepare_before_exec=%d srv=%d\n", prepare_before_exec, conn->connInfo.use_server_side_prepare);
 	/* Create the statement with parameters substituted. */
 	retval = copy_statement_with_parameters(stmt, prepare_before_exec);
@@ -445,55 +441,6 @@ inolog("prepare_before_exec=%d srv=%d\n", prepare_before_exec, conn->connInfo.us
 	mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);
 
 	/*
-	 *	Dummy exection to get the column info.
-	 */
-	if (stmt->inaccurate_result && SC_is_parse_tricky(stmt))
-	{
-		BOOL		in_trans = CC_is_in_trans(conn);
-		BOOL		issued_begin = FALSE;
-		QResultClass *curres;
-
-		stmt->exec_current_row = -1;
-		*exec_end = TRUE;
-		if (!SC_is_pre_executable(stmt))
-			RETURN(SQL_SUCCESS)
-		if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
-		{
-			/* do nothing */
-		}
-		else if (!in_trans)
-		{
-			if (issued_begin = CC_begin(conn), !issued_begin)
-			{
-				SC_set_error(stmt, STMT_EXEC_ERROR,  "Handle prepare error", func);
-				RETURN(SQL_ERROR)
-			}
-		}
-		/* we are now in a transaction */
-		res = CC_send_query(conn, stmt->stmt_with_params, NULL, 0, SC_get_ancestor(stmt));
-		if (!QR_command_maybe_successful(res))
-		{
-#ifndef	_LEGACY_MODE_
-			if (PG_VERSION_LT(conn, 8.0))
-				CC_abort(conn);
-#endif /* LEGACY_MODE_ */
-			SC_set_error(stmt, STMT_EXEC_ERROR, "Handle prepare error", func);
-			QR_Destructor(res);
-			RETURN(SQL_ERROR)
-		}
-		SC_set_Result(stmt, res);
-		for (curres = res; !curres->num_fields; curres = curres->next)
-			;
-		SC_set_Curres(stmt, curres);
-		if (CC_does_autocommit(conn))
-		{
-			if (issued_begin)
-				CC_commit(conn);
-		}
-		stmt->status = STMT_FINISHED;
-		RETURN(SQL_SUCCESS)
-	}
-	/*
 	 *	The real execution.
 	 */
 mylog("about to begin SC_execute\n");
@@ -542,8 +489,7 @@ mylog("about to begin SC_execute\n");
 		apdopts = SC_get_APDF(stmt);
 		end_row = (SQLINTEGER) apdopts->paramset_size - 1;
 	}
-	if (stmt->inaccurate_result ||
-	    stmt->exec_current_row >= end_row)
+	if (stmt->exec_current_row >= end_row)
 	{
 		*exec_end = TRUE;
 		stmt->exec_current_row = -1;
@@ -878,34 +824,15 @@ PGAPI_Execute(HSTMT hstmt, UWORD flag)
 
 	conn = SC_get_conn(stmt);
 	apdopts = SC_get_APDF(stmt);
+
 	/*
-	 * If the statement is premature, it means we already executed it from
-	 * an SQLPrepare/SQLDescribeCol type of scenario.  So just return
-	 * success.
+	 * If the statement was previously described, just recycle the old result
+	 * set that contained just the column information.
 	 */
-	if (stmt->prepare && stmt->status == STMT_PREMATURE)
+	if (stmt->prepare && stmt->status == STMT_DESCRIBED)
 	{
-		if (stmt->inaccurate_result)
-		{
-			stmt->exec_current_row = -1;
-			SC_recycle_statement(stmt);
-		}
-		else
-		{
-			stmt->status = STMT_FINISHED;
-			if (NULL == SC_get_errormsg(stmt))
-			{
-				mylog("%s: premature statement but return SQL_SUCCESS\n", func);
-				retval = SQL_SUCCESS;
-				goto cleanup;
-			}
-			else
-			{
-				SC_set_error(stmt,STMT_INTERNAL_ERROR, "premature statement so return SQL_ERROR", func);
-				retval = SQL_ERROR;
-				goto cleanup;
-			}
-		}
+		stmt->exec_current_row = -1;
+		SC_recycle_statement(stmt);
 	}
 
 	mylog("%s: clear errors...\n", func);
@@ -984,7 +911,7 @@ PGAPI_Execute(HSTMT hstmt, UWORD flag)
 			switch (nCallParse = HowToPrepareBeforeExec(stmt, TRUE))
 			{
 				case shouldParse:
-					if (retval = prepareParameters(stmt), SQL_ERROR == retval)
+					if (retval = prepareParameters(stmt, FALSE), SQL_ERROR == retval)
 						goto cleanup;
 					break;
 			}
@@ -1035,7 +962,6 @@ next_param_row:
 	 * Check if statement has any data-at-execute parameters when it is
 	 * not in SC_pre_execute.
 	 */
-	if (!stmt->pre_executing)
 	{
 		/*
 		 * The bound parameters could have possibly changed since the last
diff --git a/psqlodbc.rc b/psqlodbc.rc
index 937fddd..17ab14c 100644
--- a/psqlodbc.rc
+++ b/psqlodbc.rc
@@ -148,9 +148,6 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,139,25,114,10
     CONTROL         "�V�X�e���e�|�u����\��(&T)",DS_SHOWSYSTEMTABLES,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,41,111,10
-    CONTROL         "Prepare���擾�ɐ�s���s���Ȃ�(&P)",
-                    DS_DISALLOWPREMATURE,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,139,41,162,10
     CONTROL         "LF <-> CR/LF �ϊ����s��",DS_LFCONVERSION,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,56,106,10
     CONTROL         "-1 ��^�l(True)�Ƃ���",DS_TRUEISMINUS1,"Button",
@@ -590,8 +587,6 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,163,26,85,10
     CONTROL         "Show System &Tables",DS_SHOWSYSTEMTABLES,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,41,100,10
-    CONTROL         "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,163,41,85,10
     CONTROL         "LF <-> CR/LF conversion",DS_LFCONVERSION,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,56,106,10
     CONTROL         "True is -1",DS_TRUEISMINUS1,"Button",BS_AUTOCHECKBOX | 
diff --git a/results.c b/results.c
index e9138c9..0795fc9 100644
--- a/results.c
+++ b/results.c
@@ -85,11 +85,15 @@ PGAPI_RowCount(HSTMT hstmt,
 	return SQL_SUCCESS;
 }
 
-static BOOL SC_pre_execute_ok(StatementClass *stmt, BOOL build_fi, int col_idx, const char *func)
+static BOOL
+SC_describe_ok(StatementClass *stmt, BOOL build_fi, int col_idx, const char *func)
 {
-	Int2 num_fields = SC_pre_execute(stmt);
-	QResultClass	*result = SC_get_Curres(stmt);
-	BOOL	exec_ok = TRUE;
+	Int2		num_fields;
+	QResultClass *result;
+	BOOL		exec_ok = TRUE;
+
+	num_fields = SC_describe(stmt);
+	result = SC_get_Curres(stmt);
 
 	mylog("%s: result = %p, status = %d, numcols = %d\n", func, result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
 	/****if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) ****/
@@ -181,7 +185,7 @@ PGAPI_NumResultCols(HSTMT hstmt,
 
 	if (!parse_ok)
 	{
-		if (!SC_pre_execute_ok(stmt, FALSE, -1, func))
+		if (!SC_describe_ok(stmt, FALSE, -1, func))
 		{
 			ret = SQL_ERROR;
 			goto cleanup;
@@ -310,7 +314,7 @@ inolog("answering bookmark info\n");
 		 */
 		BOOL	build_fi = (NULL != pfNullable || NULL != pfSqlType);
 		fi = NULL;
-		if (!SC_pre_execute_ok(stmt, build_fi, icol, func))
+		if (!SC_describe_ok(stmt, build_fi, icol, func))
 		{
 			result = SQL_ERROR;
 			goto cleanup;
@@ -572,7 +576,7 @@ inolog("answering bookmark info\n");
 				build_fi = TRUE;
 				break;
 		}
-		if (!SC_pre_execute_ok(stmt, build_fi, col_idx, func))
+		if (!SC_describe_ok(stmt, build_fi, col_idx, func))
 			return SQL_ERROR;
 
 		res = SC_get_Curres(stmt);
diff --git a/statement.c b/statement.c
index adcbca3..693c321 100644
--- a/statement.c
+++ b/statement.c
@@ -366,8 +366,6 @@ static void SC_init_parse_method(StatementClass *self)
 	if (self->catalog_result) return;
 	if (conn->connInfo.drivers.parse)
 		SC_set_parse_forced(self);
-	if (self->multi_statement <= 0 && conn->connInfo.disallow_premature)
-		SC_set_parse_tricky(self);
 }
 
 StatementClass *
@@ -447,8 +445,6 @@ SC_Constructor(ConnectionClass *conn)
 		InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->ipdi),
 				rv, SQL_ATTR_IMP_PARAM_DESC);
 
-		rv->pre_executing = FALSE;
-		rv->inaccurate_result = FALSE;
 		rv->miscinfo = 0;
 		rv->rbonerr = 0;
 		SC_reset_updatable(rv);
@@ -755,11 +751,11 @@ BOOL	SC_opencheck(StatementClass *self, const char *func)
 		return TRUE;
 	}
 	/*
-	 * We can dispose the result of PREMATURE execution any time.
+	 * We can dispose the result of Describe-only any time.
 	 */
-	if (self->prepare && self->status == STMT_PREMATURE)
+	if (self->prepare && self->status == STMT_DESCRIBED)
 	{
-		mylog("SC_opencheck: self->prepare && self->status == STMT_PREMATURE\n");
+		mylog("SC_opencheck: self->prepare && self->status == STMT_DESCRIBED\n");
 		return FALSE;
 	}
 	if (res = SC_get_Curres(self), NULL != res)
@@ -839,20 +835,7 @@ SC_recycle_statement(StatementClass *self)
 		case STMT_READY:
 			break;
 
-		case STMT_PREMATURE:
-
-			/*
-			 * Premature execution of the statement might have caused the
-			 * start of a transaction. If so, we have to rollback that
-			 * transaction.
-			 */
-			if (CC_loves_visible_trans(conn) && CC_is_in_trans(conn))
-			{
-				if (SC_is_pre_executable(self) && !SC_is_parse_tricky(self))
-				{
-					/* CC_abort(conn); */
-				}
-			}
+		case STMT_DESCRIBED:
 			break;
 
 		case STMT_FINISHED:
@@ -878,7 +861,6 @@ inolog("SC_clear_parse_status\n");
 	/* Free any cursors */
 	if (SC_get_Result(self))
 		SC_set_Result(self, NULL);
-	self->inaccurate_result = FALSE;
 	self->miscinfo = 0;
 	/* self->rbonerr = 0; Never clear the bits here */
 
@@ -1087,14 +1069,17 @@ SC_scanQueryAndCountParams(const char *query, const ConnectionClass *conn,
 }
 
 /*
- * Pre-execute a statement (for SQLPrepare/SQLDescribeCol)
+ * Describe the result set a statement will produce (for
+ * SQLPrepare/SQLDescribeCol)
+ *
+ * returns # of fields if successful, -1 on error.
  */
-Int4	/* returns # of fields if successful */
-SC_pre_execute(StatementClass *self)
+Int4
+SC_describe(StatementClass *self)
 {
 	Int4		num_fields = -1;
 	QResultClass	*res;
-	mylog("SC_pre_execute: status = %d\n", self->status);
+	mylog("SC_describe: status = %d\n", self->status);
 
 	res = SC_get_Curres(self);
 	if (NULL != res)
@@ -1106,53 +1091,33 @@ SC_pre_execute(StatementClass *self)
 	}
 	if (self->status == STMT_READY)
 	{
-		mylog("              preprocess: status = READY\n");
+mylog("              preprocess: status = READY\n");
 
 		self->miscinfo = 0;
-		if (SC_can_req_colinfo(self))
-		{
-			char		old_pre_executing = self->pre_executing;
 
-			decideHowToPrepare(self, FALSE);
-			self->inaccurate_result = FALSE;
-			switch (SC_get_prepare_method(self))
-			{
-				case NAMED_PARSE_REQUEST:
-				case PARSE_TO_EXEC_ONCE:
-					if (SQL_SUCCESS != prepareParameters(self))
-						return num_fields;
-					break;
-				case PARSE_REQ_FOR_INFO:
-					if (SQL_SUCCESS != prepareParameters(self))
-						return num_fields;
-					self->status = STMT_PREMATURE;
-					self->inaccurate_result = TRUE;
-					break;
-				default:
-					self->pre_executing = TRUE;
-					PGAPI_Execute(self, 0);
-
-					self->pre_executing = old_pre_executing;
-
-					if (self->status == STMT_FINISHED)
-					{
-						mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
-						self->status = STMT_PREMATURE;
-					}
-			}
-			if (res = SC_get_Curres(self), NULL != res)
-			{
-				num_fields = QR_NumResultCols(res);
-				return num_fields;
-			}
+		decideHowToPrepare(self, FALSE);
+		switch (SC_get_prepare_method(self))
+		{
+			case NAMED_PARSE_REQUEST:
+			case PARSE_TO_EXEC_ONCE:
+				if (SQL_SUCCESS != prepareParameters(self, FALSE))
+					return num_fields;
+				break;
+			case PARSE_REQ_FOR_INFO:
+				if (SQL_SUCCESS != prepareParameters(self, FALSE))
+					return num_fields;
+				self->status = STMT_DESCRIBED;
+				break;
+			default:
+				if (SQL_SUCCESS != prepareParameters(self, TRUE))
+					return num_fields;
+				self->status = STMT_DESCRIBED;
+				break;
 		}
-		if (!SC_is_pre_executable(self))
+		if (res = SC_get_Curres(self), NULL != res)
 		{
-			SC_set_Result(self, QR_Constructor());
-			QR_set_rstatus(SC_get_Result(self), PORES_TUPLES_OK);
-			self->inaccurate_result = TRUE;
-			self->status = STMT_PREMATURE;
-			num_fields = 0;
+			num_fields = QR_NumResultCols(res);
+			return num_fields;
 		}
 	}
 	return num_fields;
@@ -2502,7 +2467,7 @@ libpq_bind_and_exec(StatementClass *stmt)
 
 		if (!stmt->processed_statements)
 		{
-			if (prepareParametersNoDesc(stmt) == SQL_ERROR)
+			if (prepareParametersNoDesc(stmt, FALSE) == SQL_ERROR)
 				goto cleanup;
 		}
 
@@ -2522,7 +2487,7 @@ libpq_bind_and_exec(StatementClass *stmt)
 
 		if (stmt->prepared == PREPARING_PERMANENTLY)
 		{
-			if (prepareParameters(stmt) == SQL_ERROR)
+			if (prepareParameters(stmt, FALSE) == SQL_ERROR)
 				goto cleanup;
 		}
 
diff --git a/statement.h b/statement.h
index 84a1114..7c4e85d 100644
--- a/statement.h
+++ b/statement.h
@@ -25,14 +25,14 @@ typedef enum
 	STMT_ALLOCATED,				/* The statement handle is allocated, but
 								 * not used so far */
 	STMT_READY,					/* the statement is waiting to be executed */
-	STMT_PREMATURE,				/* ODBC states that it is legal to call
+	STMT_DESCRIBED,				/* ODBC states that it is legal to call
 								 * e.g. SQLDescribeCol before a call to
 								 * SQLExecute, but after SQLPrepare. To
 								 * get all the necessary information in
-								 * such a case, we simply execute the
-								 * query _before_ the actual call to
-								 * SQLExecute, so that statement is
-								 * considered to be "premature". */
+								 * such a case, we parse the query _before_
+								 * the actual call to SQLExecute, and the
+								 * result set contains only column information,
+								 * but no actual data. */
 	STMT_FINISHED,				/* statement execution has finished */
 	STMT_EXECUTING				/* statement execution is still going on */
 } STMT_Status;
@@ -279,9 +279,6 @@ struct StatementClass_
 	SQLLEN		exec_end_row;
 	SQLLEN		exec_current_row;
 
-	po_ind_t	pre_executing;	/* This statement is prematurely executing */
-	po_ind_t	inaccurate_result;	/* Current status is PREMATURE but
-						 * result is inaccurate */
 	unsigned char	miscinfo;
 	po_ind_t	updatable;
 	SQLLEN		diag_row_count;
@@ -346,9 +343,6 @@ void SC_set_Result(StatementClass *self, QResultClass *res);
 #define	SC_clear_parse_method(s)	((s)->parse_method = 0)
 #define	SC_is_parse_forced(s)	(0 != ((s)->parse_method & 1L))
 #define	SC_set_parse_forced(s)	((s)->parse_method |= 1L)
-#define	SC_is_parse_tricky(s)	(0 != ((s)->parse_method & 2L))
-#define	SC_set_parse_tricky(s)	((s)->parse_method |= 2L)
-#define	SC_no_parse_tricky(s)	((s)->parse_method &= ~2L)
 
 #define	SC_cursor_is_valid(s)	(NAME_IS_VALID(s->cursor_name))
 #define	SC_cursor_name(s)	(SAFE_NAME(s->cursor_name))
@@ -405,9 +399,6 @@ enum
 };
 
 /*	misc info */
-#define SC_set_pre_executable(a) (a->miscinfo |= 1L)
-#define SC_no_pre_executable(a) (a->miscinfo &= ~1L)
-#define SC_is_pre_executable(a) ((a->miscinfo & 1L) != 0)
 #define SC_set_fetchcursor(a)	(a->miscinfo |= (1L << 1))
 #define SC_no_fetchcursor(a)	(a->miscinfo &= ~(1L << 1))
 #define SC_is_fetchcursor(a)	((a->miscinfo & (1L << 1)) != 0)
@@ -443,13 +434,6 @@ enum
 	(SC_get_APDF(a)->paramset_size <= 1 &&								\
 	 (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type) )
 #define SC_may_fetch_rows(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
-#define SC_can_req_colinfo(a) (STMT_TYPE_SELECT == (a)->statement_type || \
-		 STMT_TYPE_WITH == (a)->statement_type || \
-		((a)->prepare && \
-		 STMT_TYPE_INSERT <= (a)->statement_type && \
-		 STMT_TYPE_DELETE >= (a)->statement_type && \
-		 SC_get_conn((a))->connInfo.use_server_side_prepare))
-#define SC_determine_statement_type(a) (STMT_TYPE_SELECT != (a)->statement_type ? (a)->statement_type : ((a)->statement_type = || statement_type((a)->statement)))
 
 
 /* For Multi-thread */
@@ -484,7 +468,7 @@ int		statement_type(const char *statement);
 char		parse_statement(StatementClass *stmt, BOOL);
 char		parse_sqlsvr(StatementClass *stmt);
 SQLRETURN	SC_set_SS_columnkey(StatementClass *stmt);
-Int4		SC_pre_execute(StatementClass *self);
+Int4		SC_describe(StatementClass *self);
 char		SC_unbind_cols(StatementClass *self);
 char		SC_recycle_statement(StatementClass *self);
 
diff --git a/test/expected/insertreturning.out b/test/expected/insertreturning.out
index fb88477..1e925eb 100644
--- a/test/expected/insertreturning.out
+++ b/test/expected/insertreturning.out
@@ -304,304 +304,304 @@ foobar 99
 disconnecting
 Testing with UseServerSidePrepare=0
 connected
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 0
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 1
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 2
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 3
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 4
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 5
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 6
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 7
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 8
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 9
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 10
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 11
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 12
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 13
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 14
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 15
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 16
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 17
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 18
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 19
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 20
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 21
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 22
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 23
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 24
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 25
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 26
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 27
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 28
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 29
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 30
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 31
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 32
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 33
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 34
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 35
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 36
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 37
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 38
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 39
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 40
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 41
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 42
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 43
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 44
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 45
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 46
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 47
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 48
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 49
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 50
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 51
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 52
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 53
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 54
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 55
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 56
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 57
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 58
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 59
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 60
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 61
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 62
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 63
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 64
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 65
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 66
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 67
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 68
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 69
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 70
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 71
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 72
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 73
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 74
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 75
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 76
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 77
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 78
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 79
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 80
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 81
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 82
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 83
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 84
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 85
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 86
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 87
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 88
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 89
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 90
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 91
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 92
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 93
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 94
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 95
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 96
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 97
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 98
-# of result cols before SQLExecute: 0, after: 1
+# of result cols before SQLExecute: 1, after: 1
 Result set:
 foobar 99
 disconnecting
diff --git a/test/expected/premature.out b/test/expected/premature.out
new file mode 100644
index 0000000..1a7cfdb
--- /dev/null
+++ b/test/expected/premature.out
@@ -0,0 +1,19 @@
+\! "./src/premature-test"
+connected
+
+Preparing an INSERT statement
+# of result cols: 1
+
+Preparing an insert using a function
+# of result cols: 1
+
+Preparing a multi-statement
+# of result cols: 3
+
+Prepare with function, but execute with different param
+# of result cols: 1
+
+Checking table contents. Should contain only one row.
+Result set:
+function insert right
+disconnecting
diff --git a/test/src/premature-test.c b/test/src/premature-test.c
new file mode 100644
index 0000000..445839c
--- /dev/null
+++ b/test/src/premature-test.c
@@ -0,0 +1,201 @@
+/*
+ * This test case tests the so-called "premature execution" behaviour, which
+ * can be influenced with the DisallowPremature setting.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+
+int main(int argc, char **argv)
+{
+	SQLRETURN rc;
+	HSTMT hstmt = SQL_NULL_HSTMT;
+	char *param1;
+	SQLLEN cbParam1;
+	SQLSMALLINT colcount;
+
+	test_connect();
+
+	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
+	if (!SQL_SUCCEEDED(rc))
+	{
+		print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
+		exit(1);
+	}
+
+	/**** Set up a test table and function ****/
+
+	rc = SQLExecDirect(hstmt, (SQLCHAR *) "CREATE TEMPORARY TABLE premature_test (t text)", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+	rc = SQLExecDirect(hstmt, (SQLCHAR *)
+		"CREATE OR REPLACE FUNCTION insertfunc (t text) RETURNS text AS "
+		"$$ INSERT INTO premature_test VALUES ($1) RETURNING 'func insert'::text $$ "
+		"LANGUAGE sql",
+					   SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+	printf("\nPreparing an INSERT statement\n");
+
+
+	/****
+	 * First, try with a plain INSERT. Prepare the statement, run
+	 * SQLNumResultCols() which forces the statement to be sent and parsed
+	 * in the backend.
+	 */
+	rc = SQLPrepare(hstmt, (SQLCHAR *) "INSERT INTO premature_test VALUES (?) RETURNING 'plain insert'::text", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+
+	/* bind param  */
+	param1 = "plain insert";
+	cbParam1 = SQL_NTS;
+	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
+						  SQL_C_CHAR,	/* value type */
+						  SQL_CHAR,		/* param type */
+						  20,			/* column size */
+						  0,			/* dec digits */
+						  param1,		/* param value ptr */
+						  0,			/* buffer len */
+						  &cbParam1		/* StrLen_or_IndPtr */);
+	CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
+
+	/* Test SQLNumResultCols, called before SQLExecute() */
+	rc = SQLNumResultCols(hstmt, &colcount);
+	CHECK_STMT_RESULT(rc, "SQLNumResultCols failed", hstmt);
+	printf("# of result cols: %d\n", colcount);
+
+	/* Don't execute the statement! The row should not be inserted. */
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+
+	/*** Now, do the same with the function ***/
+
+	printf("\nPreparing an insert using a function\n");
+	rc = SQLPrepare(hstmt, (SQLCHAR *) "SELECT insertfunc(?)", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+
+	/* bind param  */
+	param1 = "function insert";
+	cbParam1 = SQL_NTS;
+	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
+						  SQL_C_CHAR,	/* value type */
+						  SQL_CHAR,		/* param type */
+						  20,			/* column size */
+						  0,			/* dec digits */
+						  param1,		/* param value ptr */
+						  0,			/* buffer len */
+						  &cbParam1		/* StrLen_or_IndPtr */);
+	CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
+
+
+	/* Test SQLNumResultCols, called before SQLExecute() */
+	rc = SQLNumResultCols(hstmt, &colcount);
+	CHECK_STMT_RESULT(rc, "SQLNumResultCols failed", hstmt);
+	printf("# of result cols: %d\n", colcount);
+
+	/* Don't execute the statement! The row should not be inserted. */
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+
+	/*** Same with the function, used in a multi-statement ***/
+
+	printf("\nPreparing a multi-statement\n");
+	rc = SQLPrepare(hstmt, (SQLCHAR *) "SELECT 'foo', 2, 3; SELECT insertfunc(?), 2; SELECT 'bar'", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+
+	/* bind param  */
+	param1 = "function insert in multi-statement";
+	cbParam1 = SQL_NTS;
+	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
+						  SQL_C_CHAR,	/* value type */
+						  SQL_CHAR,		/* param type */
+						  20,			/* column size */
+						  0,			/* dec digits */
+						  param1,		/* param value ptr */
+						  0,			/* buffer len */
+						  &cbParam1		/* StrLen_or_IndPtr */);
+	CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
+
+	/* Test SQLNumResultCols, called before SQLExecute() */
+	rc = SQLNumResultCols(hstmt, &colcount);
+	CHECK_STMT_RESULT(rc, "SQLNumResultCols failed", hstmt);
+	printf("# of result cols: %d\n", colcount);
+
+	/* Don't execute the statement! The row should not be inserted. */
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+
+	/*** Again with the function, but this time execute it too. With a
+	 * twist: we rebind a different parameter after the SQLNumResultCols
+	 * call.
+	 */
+
+	printf("\nPrepare with function, but execute with different param\n");
+	rc = SQLPrepare(hstmt, (SQLCHAR *) "SELECT insertfunc(?)", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+
+	/* bind param  */
+	param1 = "function insert wrong";
+	cbParam1 = SQL_NTS;
+	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
+						  SQL_C_CHAR,	/* value type */
+						  SQL_CHAR,		/* param type */
+						  20,			/* column size */
+						  0,			/* dec digits */
+						  param1,		/* param value ptr */
+						  0,			/* buffer len */
+						  &cbParam1		/* StrLen_or_IndPtr */);
+	CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
+
+	/* Test SQLNumResultCols, called before SQLExecute() */
+	rc = SQLNumResultCols(hstmt, &colcount);
+	CHECK_STMT_RESULT(rc, "SQLNumResultCols failed", hstmt);
+	printf("# of result cols: %d\n", colcount);
+
+
+	/* Rebind param */
+	param1 = "function insert right";
+	cbParam1 = SQL_NTS;
+	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
+						  SQL_C_CHAR,	/* value type */
+						  SQL_CHAR,		/* param type */
+						  20,			/* column size */
+						  0,			/* dec digits */
+						  param1,		/* param value ptr */
+						  0,			/* buffer len */
+						  &cbParam1		/* StrLen_or_IndPtr */);
+	CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
+
+	/* And execute */
+	rc = SQLExecute(hstmt);
+	CHECK_STMT_RESULT(rc, "SQLExecute failed", hstmt);
+
+	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+	CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+
+	/*** Now check that the table contains only the last insertion  ***/
+
+	printf("\nChecking table contents. Should contain only one row.\n");
+	rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT * FROM premature_test", SQL_NTS);
+	CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
+	print_result(hstmt);
+
+	/* Clean up */
+	test_disconnect();
+
+	return 0;
+}
diff --git a/test/tests b/test/tests
index c3f415f..4fd68a0 100644
--- a/test/tests
+++ b/test/tests
@@ -17,6 +17,7 @@ TESTBINS = src/connect-test \
 	src/colattribute-test \
 	src/result-conversions-test \
 	src/prepare-test \
+	src/premature-test \
 	src/params-test \
 	src/param-conversions-test \
 	src/notice-test \
-- 
2.1.4

