[tarantool-patches] Re: [PATCH v2 8/9] box: exported sql_bind structure and API

Kirill Shcherbatov kshcherbatov at tarantool.org
Tue Mar 26 13:59:33 MSK 2019


Exported sql_bind structure, sql_bind_decode, sql_bind_column
and sql_bind routines in separate module bind.h.
We need SQL bindings in further pathes with check constraints.

Needed for #3691
---
 src/box/CMakeLists.txt |   1 +
 src/box/bind.c         | 239 ++++++++++++++++++++++++++++++++++++
 src/box/bind.h         | 136 +++++++++++++++++++++
 src/box/execute.c      | 270 +----------------------------------------
 src/box/execute.h      |  15 ---
 src/box/iproto.cc      |   1 +
 6 files changed, 378 insertions(+), 284 deletions(-)
 create mode 100644 src/box/bind.c
 create mode 100644 src/box/bind.h

diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 070d4a9fe..8ea9afcdd 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -117,6 +117,7 @@ add_library(box STATIC
     journal.c
     ck_constraint.c
     sql.c
+    bind.c
     execute.c
     wal.c
     call.c
diff --git a/src/box/bind.c b/src/box/bind.c
new file mode 100644
index 000000000..fb73cf44d
--- /dev/null
+++ b/src/box/bind.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "bind.h"
+#include "errcode.h"
+#include "small/region.h"
+#include "sql/sqlInt.h"
+#include "sql/sqlLimit.h"
+#include "sql/vdbe.h"
+
+const char *sql_type_strs[] = {
+	NULL,
+	"INTEGER",
+	"FLOAT",
+	"TEXT",
+	"BLOB",
+	"NULL",
+};
+
+/**
+ * Return a string name of a parameter marker.
+ * @param Bind to get name.
+ * @retval Zero terminated name.
+ */
+static inline const char *
+sql_bind_name(const struct sql_bind *bind)
+{
+	if (bind->name)
+		return tt_sprintf("'%.*s'", bind->name_len, bind->name);
+	else
+		return tt_sprintf("%d", (int) bind->pos);
+}
+
+int
+sql_bind_decode(struct sql_bind *bind, int i, const char **packet)
+{
+	bind->pos = i + 1;
+	if (mp_typeof(**packet) == MP_MAP) {
+		uint32_t len = mp_decode_map(packet);
+		/*
+		 * A named parameter is an MP_MAP with
+		 * one key - {'name': value}.
+		 * Report parse error otherwise.
+		 */
+		if (len != 1 || mp_typeof(**packet) != MP_STR) {
+			diag_set(ClientError, ER_INVALID_MSGPACK,
+				 "SQL bind parameter");
+			return -1;
+		}
+		bind->name = mp_decode_str(packet, &bind->name_len);
+	} else {
+		bind->name = NULL;
+		bind->name_len = 0;
+	}
+	switch (mp_typeof(**packet)) {
+	case MP_UINT: {
+		uint64_t n = mp_decode_uint(packet);
+		if (n > INT64_MAX) {
+			diag_set(ClientError, ER_SQL_BIND_VALUE,
+				 sql_bind_name(bind), "INTEGER");
+			return -1;
+		}
+		bind->i64 = (int64_t) n;
+		bind->type = SQL_INTEGER;
+		bind->bytes = sizeof(bind->i64);
+		break;
+	}
+	case MP_INT:
+		bind->i64 = mp_decode_int(packet);
+		bind->type = SQL_INTEGER;
+		bind->bytes = sizeof(bind->i64);
+		break;
+	case MP_STR:
+		bind->s = mp_decode_str(packet, &bind->bytes);
+		bind->type = SQL_TEXT;
+		break;
+	case MP_DOUBLE:
+		bind->d = mp_decode_double(packet);
+		bind->type = SQL_FLOAT;
+		bind->bytes = sizeof(bind->d);
+		break;
+	case MP_FLOAT:
+		bind->d = mp_decode_float(packet);
+		bind->type = SQL_FLOAT;
+		bind->bytes = sizeof(bind->d);
+		break;
+	case MP_NIL:
+		mp_decode_nil(packet);
+		bind->type = SQL_NULL;
+		bind->bytes = 1;
+		break;
+	case MP_BOOL:
+		/* sql doesn't support boolean. Use int instead. */
+		bind->i64 = mp_decode_bool(packet) ? 1 : 0;
+		bind->type = SQL_INTEGER;
+		bind->bytes = sizeof(bind->i64);
+		break;
+	case MP_BIN:
+		bind->s = mp_decode_bin(packet, &bind->bytes);
+		bind->type = SQL_BLOB;
+		break;
+	case MP_EXT:
+		bind->s = *packet;
+		mp_next(packet);
+		bind->bytes = *packet - bind->s;
+		bind->type = SQL_BLOB;
+		break;
+	case MP_ARRAY:
+		diag_set(ClientError, ER_SQL_BIND_TYPE, "ARRAY",
+			 sql_bind_name(bind));
+		return -1;
+	case MP_MAP:
+		diag_set(ClientError, ER_SQL_BIND_TYPE, "MAP",
+			 sql_bind_name(bind));
+		return -1;
+	default:
+		unreachable();
+	}
+	return 0;
+}
+
+int
+sql_bind_list_decode(const char *data, struct sql_bind **out_bind)
+{
+	assert(data != NULL);
+	if (mp_typeof(*data) != MP_ARRAY) {
+		diag_set(ClientError, ER_INVALID_MSGPACK, "SQL parameter list");
+		return -1;
+	}
+	uint32_t bind_count = mp_decode_array(&data);
+	if (bind_count == 0)
+		return 0;
+	if (bind_count > SQL_BIND_PARAMETER_MAX) {
+		diag_set(ClientError, ER_SQL_BIND_PARAMETER_MAX,
+			 (int) bind_count);
+		return -1;
+	}
+	struct region *region = &fiber()->gc;
+	uint32_t used = region_used(region);
+	size_t size = sizeof(struct sql_bind) * bind_count;
+	struct sql_bind *bind = (struct sql_bind *) region_alloc(region, size);
+	if (bind == NULL) {
+		diag_set(OutOfMemory, size, "region_alloc", "struct sql_bind");
+		return -1;
+	}
+	for (uint32_t i = 0; i < bind_count; ++i) {
+		if (sql_bind_decode(&bind[i], i, &data) != 0) {
+			region_truncate(region, used);
+			return -1;
+		}
+	}
+	*out_bind = bind;
+	return bind_count;
+}
+
+int
+sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p,
+		uint32_t pos)
+{
+	int rc;
+	if (p->name != NULL) {
+		pos = sql_bind_parameter_lindex(stmt, p->name, p->name_len);
+		if (pos == 0) {
+			diag_set(ClientError, ER_SQL_BIND_NOT_FOUND,
+				 sql_bind_name(p));
+			return -1;
+		}
+	}
+	switch (p->type) {
+	case SQL_INTEGER:
+		rc = sql_bind_int64(stmt, pos, p->i64);
+		break;
+	case SQL_FLOAT:
+		rc = sql_bind_double(stmt, pos, p->d);
+		break;
+	case SQL_TEXT:
+		/*
+		 * Parameters are allocated within message pack,
+		 * received from the iproto thread. IProto thread
+		 * now is waiting for the response and it will not
+		 * free the packet until sql_finalize. So
+		 * there is no need to copy the packet and we can
+		 * use SQL_STATIC.
+		 */
+		rc = sql_bind_text64(stmt, pos, p->s, p->bytes,
+					 SQL_STATIC);
+		break;
+	case SQL_NULL:
+		rc = sql_bind_null(stmt, pos);
+		break;
+	case SQL_BLOB:
+		rc = sql_bind_blob64(stmt, pos, (const void *) p->s,
+					 p->bytes, SQL_STATIC);
+		break;
+	default:
+		unreachable();
+	}
+	if (rc == SQL_OK)
+		return 0;
+
+	switch (rc) {
+	case SQL_NOMEM:
+		diag_set(OutOfMemory, p->bytes, "vdbe", "bind value");
+		break;
+	case SQL_TOOBIG:
+	default:
+		diag_set(ClientError, ER_SQL_BIND_VALUE, sql_bind_name(p),
+			 sql_type_strs[p->type]);
+		break;
+	}
+	return -1;
+}
diff --git a/src/box/bind.h b/src/box/bind.h
new file mode 100644
index 000000000..4414ea793
--- /dev/null
+++ b/src/box/bind.h
@@ -0,0 +1,136 @@
+#ifndef TARANTOOL_SQL_BIND_H_INCLUDED
+#define TARANTOOL_SQL_BIND_H_INCLUDED
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+struct sql_stmt;
+
+/**
+ * Name and value of an SQL prepared statement parameter.
+ * @todo: merge with sql_value.
+ */
+struct sql_bind {
+	/** Bind name. NULL for ordinal binds. */
+	const char *name;
+	/** Length of the @name. */
+	uint32_t name_len;
+	/** Ordinal position of the bind, for ordinal binds. */
+	uint32_t pos;
+
+	/** Byte length of the value. */
+	uint32_t bytes;
+	/** SQL type of the value. */
+	uint8_t type;
+	/** Bind value. */
+	union {
+		double d;
+		int64_t i64;
+		/** For string or blob. */
+		const char *s;
+	};
+};
+
+/**
+ * Parse MessagePack array of SQL parameters.
+ * @param data MessagePack array of parameters. Each parameter
+ *        either must have scalar type, or must be a map with the
+ *        following format: {name: value}. Name - string name of
+ *        the named parameter, value - scalar value of the
+ *        parameter. Named and positioned parameters can be mixed.
+ * @param[out] out_bind Pointer to save decoded parameters.
+ *
+ * @retval  >= 0 Number of decoded parameters.
+ * @retval -1 Client or memory error.
+ */
+int
+sql_bind_list_decode(const char *data, struct sql_bind **out_bind);
+
+/**
+ * Decode a single bind column from the binary protocol packet.
+ * @param[out] bind Bind to decode to.
+ * @param i Ordinal bind number.
+ * @param packet MessagePack encoded parameter value. Either
+ *        scalar or map: {string_name: scalar_value}.
+ *
+ * @retval  0 Success.
+ * @retval -1 Memory or client error.
+ */
+int
+sql_bind_decode(struct sql_bind *bind, int i, const char **packet);
+
+/**
+ * Bind SQL parameter value to its position.
+ * @param stmt Prepared statement.
+ * @param p Parameter value.
+ * @param pos Ordinal bind position.
+ *
+ * @retval  0 Success.
+ * @retval -1 SQL error.
+ */
+int
+sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p,
+		uint32_t pos);
+
+/**
+ * Bind parameter values to the prepared statement.
+ * @param stmt Prepared statement.
+ * @param bind Parameters to bind.
+ * @param bind_count Length of @a bind.
+ *
+ * @retval  0 Success.
+ * @retval -1 Client or memory error.
+ */
+static inline int
+sql_bind(struct sql_stmt *stmt, const struct sql_bind *bind,
+	 uint32_t bind_count)
+{
+	assert(stmt != NULL);
+	uint32_t pos = 1;
+	for (uint32_t i = 0; i < bind_count; pos = ++i + 1) {
+		if (sql_bind_column(stmt, &bind[i], pos) != 0)
+			return -1;
+	}
+	return 0;
+}
+
+#if defined(__cplusplus)
+} /* extern "C" { */
+#endif
+
+#endif /* TARANTOOL_SQL_BIND_H_INCLUDED */
diff --git a/src/box/execute.c b/src/box/execute.c
index 7c77df2e5..4da2fe74a 100644
--- a/src/box/execute.c
+++ b/src/box/execute.c
@@ -30,6 +30,7 @@
  */
 #include "execute.h"
 
+#include "bind.h"
 #include "iproto_constants.h"
 #include "sql/sqlInt.h"
 #include "sql/sqlLimit.h"
@@ -44,190 +45,10 @@
 #include "tuple.h"
 #include "sql/vdbe.h"
 
-const char *sql_type_strs[] = {
-	NULL,
-	"INTEGER",
-	"FLOAT",
-	"TEXT",
-	"BLOB",
-	"NULL",
-};
-
 const char *sql_info_key_strs[] = {
 	"row count",
 };
 
-/**
- * Name and value of an SQL prepared statement parameter.
- * @todo: merge with sql_value.
- */
-struct sql_bind {
-	/** Bind name. NULL for ordinal binds. */
-	const char *name;
-	/** Length of the @name. */
-	uint32_t name_len;
-	/** Ordinal position of the bind, for ordinal binds. */
-	uint32_t pos;
-
-	/** Byte length of the value. */
-	uint32_t bytes;
-	/** SQL type of the value. */
-	uint8_t type;
-	/** Bind value. */
-	union {
-		double d;
-		int64_t i64;
-		/** For string or blob. */
-		const char *s;
-	};
-};
-
-/**
- * Return a string name of a parameter marker.
- * @param Bind to get name.
- * @retval Zero terminated name.
- */
-static inline const char *
-sql_bind_name(const struct sql_bind *bind)
-{
-	if (bind->name)
-		return tt_sprintf("'%.*s'", bind->name_len, bind->name);
-	else
-		return tt_sprintf("%d", (int) bind->pos);
-}
-
-/**
- * Decode a single bind column from the binary protocol packet.
- * @param[out] bind Bind to decode to.
- * @param i Ordinal bind number.
- * @param packet MessagePack encoded parameter value. Either
- *        scalar or map: {string_name: scalar_value}.
- *
- * @retval  0 Success.
- * @retval -1 Memory or client error.
- */
-static inline int
-sql_bind_decode(struct sql_bind *bind, int i, const char **packet)
-{
-	bind->pos = i + 1;
-	if (mp_typeof(**packet) == MP_MAP) {
-		uint32_t len = mp_decode_map(packet);
-		/*
-		 * A named parameter is an MP_MAP with
-		 * one key - {'name': value}.
-		 * Report parse error otherwise.
-		 */
-		if (len != 1 || mp_typeof(**packet) != MP_STR) {
-			diag_set(ClientError, ER_INVALID_MSGPACK,
-				 "SQL bind parameter");
-			return -1;
-		}
-		bind->name = mp_decode_str(packet, &bind->name_len);
-	} else {
-		bind->name = NULL;
-		bind->name_len = 0;
-	}
-	switch (mp_typeof(**packet)) {
-	case MP_UINT: {
-		uint64_t n = mp_decode_uint(packet);
-		if (n > INT64_MAX) {
-			diag_set(ClientError, ER_SQL_BIND_VALUE,
-				 sql_bind_name(bind), "INTEGER");
-			return -1;
-		}
-		bind->i64 = (int64_t) n;
-		bind->type = SQL_INTEGER;
-		bind->bytes = sizeof(bind->i64);
-		break;
-	}
-	case MP_INT:
-		bind->i64 = mp_decode_int(packet);
-		bind->type = SQL_INTEGER;
-		bind->bytes = sizeof(bind->i64);
-		break;
-	case MP_STR:
-		bind->s = mp_decode_str(packet, &bind->bytes);
-		bind->type = SQL_TEXT;
-		break;
-	case MP_DOUBLE:
-		bind->d = mp_decode_double(packet);
-		bind->type = SQL_FLOAT;
-		bind->bytes = sizeof(bind->d);
-		break;
-	case MP_FLOAT:
-		bind->d = mp_decode_float(packet);
-		bind->type = SQL_FLOAT;
-		bind->bytes = sizeof(bind->d);
-		break;
-	case MP_NIL:
-		mp_decode_nil(packet);
-		bind->type = SQL_NULL;
-		bind->bytes = 1;
-		break;
-	case MP_BOOL:
-		/* sql doesn't support boolean. Use int instead. */
-		bind->i64 = mp_decode_bool(packet) ? 1 : 0;
-		bind->type = SQL_INTEGER;
-		bind->bytes = sizeof(bind->i64);
-		break;
-	case MP_BIN:
-		bind->s = mp_decode_bin(packet, &bind->bytes);
-		bind->type = SQL_BLOB;
-		break;
-	case MP_EXT:
-		bind->s = *packet;
-		mp_next(packet);
-		bind->bytes = *packet - bind->s;
-		bind->type = SQL_BLOB;
-		break;
-	case MP_ARRAY:
-		diag_set(ClientError, ER_SQL_BIND_TYPE, "ARRAY",
-			 sql_bind_name(bind));
-		return -1;
-	case MP_MAP:
-		diag_set(ClientError, ER_SQL_BIND_TYPE, "MAP",
-			 sql_bind_name(bind));
-		return -1;
-	default:
-		unreachable();
-	}
-	return 0;
-}
-
-int
-sql_bind_list_decode(const char *data, struct sql_bind **out_bind)
-{
-	assert(data != NULL);
-	if (mp_typeof(*data) != MP_ARRAY) {
-		diag_set(ClientError, ER_INVALID_MSGPACK, "SQL parameter list");
-		return -1;
-	}
-	uint32_t bind_count = mp_decode_array(&data);
-	if (bind_count == 0)
-		return 0;
-	if (bind_count > SQL_BIND_PARAMETER_MAX) {
-		diag_set(ClientError, ER_SQL_BIND_PARAMETER_MAX,
-			 (int) bind_count);
-		return -1;
-	}
-	struct region *region = &fiber()->gc;
-	uint32_t used = region_used(region);
-	size_t size = sizeof(struct sql_bind) * bind_count;
-	struct sql_bind *bind = (struct sql_bind *) region_alloc(region, size);
-	if (bind == NULL) {
-		diag_set(OutOfMemory, size, "region_alloc", "struct sql_bind");
-		return -1;
-	}
-	for (uint32_t i = 0; i < bind_count; ++i) {
-		if (sql_bind_decode(&bind[i], i, &data) != 0) {
-			region_truncate(region, used);
-			return -1;
-		}
-	}
-	*out_bind = bind;
-	return bind_count;
-}
-
 /**
  * Serialize a single column of a result set row.
  * @param stmt Prepared and started statement. At least one
@@ -363,95 +184,6 @@ error:
 	return -1;
 }
 
-/**
- * Bind SQL parameter value to its position.
- * @param stmt Prepared statement.
- * @param p Parameter value.
- * @param pos Ordinal bind position.
- *
- * @retval  0 Success.
- * @retval -1 SQL error.
- */
-static inline int
-sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p,
-		uint32_t pos)
-{
-	int rc;
-	if (p->name != NULL) {
-		pos = sql_bind_parameter_lindex(stmt, p->name, p->name_len);
-		if (pos == 0) {
-			diag_set(ClientError, ER_SQL_BIND_NOT_FOUND,
-				 sql_bind_name(p));
-			return -1;
-		}
-	}
-	switch (p->type) {
-	case SQL_INTEGER:
-		rc = sql_bind_int64(stmt, pos, p->i64);
-		break;
-	case SQL_FLOAT:
-		rc = sql_bind_double(stmt, pos, p->d);
-		break;
-	case SQL_TEXT:
-		/*
-		 * Parameters are allocated within message pack,
-		 * received from the iproto thread. IProto thread
-		 * now is waiting for the response and it will not
-		 * free the packet until sql_finalize. So
-		 * there is no need to copy the packet and we can
-		 * use SQL_STATIC.
-		 */
-		rc = sql_bind_text64(stmt, pos, p->s, p->bytes,
-					 SQL_STATIC);
-		break;
-	case SQL_NULL:
-		rc = sql_bind_null(stmt, pos);
-		break;
-	case SQL_BLOB:
-		rc = sql_bind_blob64(stmt, pos, (const void *) p->s,
-					 p->bytes, SQL_STATIC);
-		break;
-	default:
-		unreachable();
-	}
-	if (rc == SQL_OK)
-		return 0;
-
-	switch (rc) {
-	case SQL_NOMEM:
-		diag_set(OutOfMemory, p->bytes, "vdbe", "bind value");
-		break;
-	case SQL_TOOBIG:
-	default:
-		diag_set(ClientError, ER_SQL_BIND_VALUE, sql_bind_name(p),
-			 sql_type_strs[p->type]);
-		break;
-	}
-	return -1;
-}
-
-/**
- * Bind parameter values to the prepared statement.
- * @param stmt Prepared statement.
- * @param bind Parameters to bind.
- * @param bind_count Length of @a bind.
- *
- * @retval  0 Success.
- * @retval -1 Client or memory error.
- */
-static inline int
-sql_bind(struct sql_stmt *stmt, const struct sql_bind *bind,
-	 uint32_t bind_count)
-{
-	assert(stmt != NULL);
-	uint32_t pos = 1;
-	for (uint32_t i = 0; i < bind_count; pos = ++i + 1) {
-		if (sql_bind_column(stmt, &bind[i], pos) != 0)
-			return -1;
-	}
-	return 0;
-}
-
 /**
  * Serialize a description of the prepared statement.
  * @param stmt Prepared statement.
diff --git a/src/box/execute.h b/src/box/execute.h
index 12d893a73..08bbbf5bf 100644
--- a/src/box/execute.h
+++ b/src/box/execute.h
@@ -60,21 +60,6 @@ struct sql_response {
 	void *prep_stmt;
 };
 
-/**
- * Parse MessagePack array of SQL parameters.
- * @param data MessagePack array of parameters. Each parameter
- *        either must have scalar type, or must be a map with the
- *        following format: {name: value}. Name - string name of
- *        the named parameter, value - scalar value of the
- *        parameter. Named and positioned parameters can be mixed.
- * @param[out] out_bind Pointer to save decoded parameters.
- *
- * @retval  >= 0 Number of decoded parameters.
- * @retval -1 Client or memory error.
- */
-int
-sql_bind_list_decode(const char *data, struct sql_bind **out_bind);
-
 /**
  * Dump a built response into @an out buffer. The response is
  * destroyed.
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 3b0ba6234..0a1a73554 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -49,6 +49,7 @@
 #include "memory.h"
 #include "random.h"
 
+#include "bind.h"
 #include "port.h"
 #include "box.h"
 #include "call.h"
-- 
2.21.0





More information about the Tarantool-patches mailing list