[Tarantool-patches] [PATCH 1/6] sql: refactor resulting set metadata

Sergey Ostanevich sergos at tarantool.org
Tue Dec 17 16:23:35 MSK 2019


Hi!

LGTM the latest version in branch.

Sergos.


On 27 Nov 15:15, Nikita Pettik wrote:
> Move names and types of resulting set to a separate structure. Simplify
> their storage by introducing separate members for name and type
> (previously names and types were stored in one char * array). It will
> allow us to add new metadata properties with ease.
> 
> Needed for #4407
> ---
>  src/box/sql/delete.c  |  6 ++--
>  src/box/sql/insert.c  |  5 ++--
>  src/box/sql/legacy.c  |  2 +-
>  src/box/sql/pragma.c  | 14 ++++-----
>  src/box/sql/prepare.c |  9 +++---
>  src/box/sql/select.c  | 60 ++++++++++++++++++--------------------
>  src/box/sql/update.c  |  6 ++--
>  src/box/sql/vdbe.h    | 28 ++++++++++--------
>  src/box/sql/vdbeInt.h |  8 ++++-
>  src/box/sql/vdbeapi.c | 81 +++++++++------------------------------------------
>  src/box/sql/vdbeaux.c | 81 +++++++++++++++++++++++++++------------------------
>  11 files changed, 124 insertions(+), 176 deletions(-)
> 
> diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
> index 91c2157ac..31570099b 100644
> --- a/src/box/sql/delete.c
> +++ b/src/box/sql/delete.c
> @@ -418,10 +418,8 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
>  	    parse->triggered_space != NULL) {
>  		sqlVdbeAddOp2(v, OP_ResultRow, reg_count, 1);
>  		sqlVdbeSetNumCols(v, 1);
> -		sqlVdbeSetColName(v, 0, COLNAME_NAME, "rows deleted",
> -				      SQL_STATIC);
> -		sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "integer",
> -				  SQL_STATIC);
> +		vdbe_set_metadata_col_name(v, 0, "rows deleted");
> +		vdbe_set_metadata_col_type(v, 0, "integer");
>  	}
>  
>   delete_from_cleanup:
> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> index 70504c800..9be9c191d 100644
> --- a/src/box/sql/insert.c
> +++ b/src/box/sql/insert.c
> @@ -785,9 +785,8 @@ sqlInsert(Parse * pParse,	/* Parser context */
>  			column_name = "rows replaced";
>  		else
>  			column_name = "rows inserted";
> -		sqlVdbeSetColName(v, 0, COLNAME_NAME, column_name, SQL_STATIC);
> -		sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "integer",
> -				  SQL_STATIC);
> +		vdbe_set_metadata_col_name(v, 0, column_name);
> +		vdbe_set_metadata_col_type(v, 0, "integer");
>  	}
>  
>   insert_cleanup:
> diff --git a/src/box/sql/legacy.c b/src/box/sql/legacy.c
> index 0b1370f4a..ee58f1eb7 100644
> --- a/src/box/sql/legacy.c
> +++ b/src/box/sql/legacy.c
> @@ -103,7 +103,7 @@ sql_exec(sql * db,	/* The database on which the SQL executes */
>  						    (char *)
>  						    sql_column_name(pStmt,
>  									i);
> -						/* sqlVdbeSetColName() installs column names as UTF8
> +						/* vdbe_set_metadata_col_name() installs column names as UTF8
>  						 * strings so there is no way for sql_column_name() to fail.
>  						 */
>  						assert(azCols[i] != 0);
> diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
> index 92bcf4e68..874eb93d2 100644
> --- a/src/box/sql/pragma.c
> +++ b/src/box/sql/pragma.c
> @@ -120,10 +120,8 @@ vdbe_set_pragma_result_columns(struct Vdbe *v, const struct PragmaName *pragma)
>  	assert(n > 0);
>  	sqlVdbeSetNumCols(v, n);
>  	for (int i = 0, j = pragma->iPragCName; i < n; ++i) {
> -		sqlVdbeSetColName(v, i, COLNAME_NAME, pragCName[j++],
> -				  SQL_STATIC);
> -		sqlVdbeSetColName(v, i, COLNAME_DECLTYPE, pragCName[j++],
> -				  SQL_STATIC);
> +		vdbe_set_metadata_col_name(v, i, pragCName[j++]);
> +		vdbe_set_metadata_col_type(v, i, pragCName[j++]);
>  	}
>  }
>  
> @@ -168,10 +166,10 @@ vdbe_emit_pragma_status(struct Parse *parse)
>  	struct session *user_session = current_session();
>  
>  	sqlVdbeSetNumCols(v, 2);
> -	sqlVdbeSetColName(v, 0, COLNAME_NAME, "pragma_name", SQL_STATIC);
> -	sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "text", SQL_STATIC);
> -	sqlVdbeSetColName(v, 1, COLNAME_NAME, "pragma_value", SQL_STATIC);
> -	sqlVdbeSetColName(v, 1, COLNAME_DECLTYPE, "integer", SQL_STATIC);
> +	vdbe_set_metadata_col_name(v, 0, "pragma_name");
> +	vdbe_set_metadata_col_type(v, 0, "text");
> +	vdbe_set_metadata_col_name(v, 1, "pragma_value");
> +	vdbe_set_metadata_col_type(v, 1, "integer");
>  
>  	parse->nMem = 2;
>  	for (int i = 0; i < ArraySize(aPragmaName); ++i) {
> diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
> index 0ecc676e2..2d3466cc7 100644
> --- a/src/box/sql/prepare.c
> +++ b/src/box/sql/prepare.c
> @@ -146,11 +146,10 @@ sqlPrepare(sql * db,	/* Database handle. */
>  		sqlVdbeSetNumCols(sParse.pVdbe, name_count);
>  		for (int i = 0; i < name_count; i++) {
>  			int name_index = 2 * i + name_first;
> -			sqlVdbeSetColName(sParse.pVdbe, i, COLNAME_NAME,
> -					  azColName[name_index], SQL_STATIC);
> -			sqlVdbeSetColName(sParse.pVdbe, i, COLNAME_DECLTYPE,
> -					  azColName[name_index + 1],
> -					  SQL_STATIC);
> +			vdbe_set_metadata_col_name(sParse.pVdbe, i,
> +					  azColName[name_index]);
> +			vdbe_set_metadata_col_type(sParse.pVdbe, i,
> +					  azColName[name_index + 1]);
>  		}
>  	}
>  
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index 8f93edd16..d6b8a158f 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -1747,15 +1747,18 @@ generateSortTail(Parse * pParse,	/* Parsing context */
>  	sqlVdbeResolveLabel(v, addrBreak);
>  }
>  
> -/*
> +/**
>   * Generate code that will tell the VDBE the names of columns
> - * in the result set.  This information is used to provide the
> - * azCol[] values in the callback.
> + * in the result set. This information is used to provide the
> + * metadata during/after statement execution.
> + *
> + * @param pParse Parsing context.
> + * @param pTabList List of tables.
> + * @param pEList Expressions defining the result set.
>   */
>  static void
> -generateColumnNames(Parse * pParse,	/* Parser context */
> -		    SrcList * pTabList,	/* List of tables */
> -		    ExprList * pEList)	/* Expressions defining the result set */
> +generate_column_metadata(struct Parse *pParse, struct SrcList *pTabList,
> +			 struct ExprList *pEList)
>  {
>  	Vdbe *v = pParse->pVdbe;
>  	int i, j;
> @@ -1789,12 +1792,11 @@ generateColumnNames(Parse * pParse,	/* Parser context */
>  			continue;
>  		if (p->op == TK_VARIABLE)
>  			var_pos[var_count++] = i;
> -		sqlVdbeSetColName(v, i, COLNAME_DECLTYPE,
> -				  field_type_strs[sql_expr_type(p)], SQL_TRANSIENT);
> +		vdbe_set_metadata_col_type(v, i,
> +					   field_type_strs[sql_expr_type(p)]);
>  		if (pEList->a[i].zName) {
>  			char *zName = pEList->a[i].zName;
> -			sqlVdbeSetColName(v, i, COLNAME_NAME, zName,
> -					      SQL_TRANSIENT);
> +			vdbe_set_metadata_col_name(v, i, zName);
>  		} else if (p->op == TK_COLUMN || p->op == TK_AGG_COLUMN) {
>  			char *zCol;
>  			int iCol = p->iColumn;
> @@ -1807,27 +1809,21 @@ generateColumnNames(Parse * pParse,	/* Parser context */
>  			assert(iCol >= 0 && iCol < (int)space_def->field_count);
>  			zCol = space_def->fields[iCol].name;
>  			if (!shortNames && !fullNames) {
> -				sqlVdbeSetColName(v, i, COLNAME_NAME,
> -						      sqlDbStrDup(db,
> -								      pEList->a[i].zSpan),
> -						      SQL_DYNAMIC);
> +				vdbe_set_metadata_col_name(v, i,
> +							   pEList->a[i].zSpan);
>  			} else if (fullNames) {
> -				char *zName = 0;
> -				zName = sqlMPrintf(db, "%s.%s",
> -						       space_def->name, zCol);
> -				sqlVdbeSetColName(v, i, COLNAME_NAME, zName,
> -						      SQL_DYNAMIC);
> +				const char *zName = tt_sprintf("%s.%s",
> +							       space_def->name,
> +							       zCol);
> +				vdbe_set_metadata_col_name(v, i, zName);
>  			} else {
> -				sqlVdbeSetColName(v, i, COLNAME_NAME, zCol,
> -						      SQL_TRANSIENT);
> +				vdbe_set_metadata_col_name(v, i, zCol);
>  			}
>  		} else {
>  			const char *z = pEList->a[i].zSpan;
> -			z = z == 0 ? sqlMPrintf(db, "column%d",
> -						    i + 1) : sqlDbStrDup(db,
> -									     z);
> -			sqlVdbeSetColName(v, i, COLNAME_NAME, z,
> -					      SQL_DYNAMIC);
> +			if (z == NULL)
> +				z = tt_sprintf("column%d", i + 1);
> +			vdbe_set_metadata_col_name(v, i, z);
>  		}
>  	}
>  	if (var_count == 0)
> @@ -2828,7 +2824,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
>  						Select *pFirst = p;
>  						while (pFirst->pPrior)
>  							pFirst = pFirst->pPrior;
> -						generateColumnNames(pParse,
> +						generate_column_metadata(pParse,
>  								    pFirst->pSrc,
>  								    pFirst->pEList);
>  					}
> @@ -2927,9 +2923,9 @@ multiSelect(Parse * pParse,	/* Parsing context */
>  					Select *pFirst = p;
>  					while (pFirst->pPrior)
>  						pFirst = pFirst->pPrior;
> -					generateColumnNames(pParse,
> -							    pFirst->pSrc,
> -							    pFirst->pEList);
> +					generate_column_metadata(pParse,
> +								 pFirst->pSrc,
> +								 pFirst->pEList);
>  				}
>  				iBreak = sqlVdbeMakeLabel(v);
>  				iCont = sqlVdbeMakeLabel(v);
> @@ -3575,7 +3571,7 @@ multiSelectOrderBy(Parse * pParse,	/* Parsing context */
>  		Select *pFirst = pPrior;
>  		while (pFirst->pPrior)
>  			pFirst = pFirst->pPrior;
> -		generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
> +		generate_column_metadata(pParse, pFirst->pSrc, pFirst->pEList);
>  	}
>  
>  	/* Reassembly the compound query so that it will be freed correctly
> @@ -6433,7 +6429,7 @@ sqlSelect(Parse * pParse,		/* The parser context */
>  	/* Identify column names if results of the SELECT are to be output.
>  	 */
>  	if (rc == 0 && pDest->eDest == SRT_Output) {
> -		generateColumnNames(pParse, pTabList, pEList);
> +		generate_column_metadata(pParse, pTabList, pEList);
>  	}
>  
>  	sqlDbFree(db, sAggInfo.aCol);
> diff --git a/src/box/sql/update.c b/src/box/sql/update.c
> index 6d69b7252..881f87d6f 100644
> --- a/src/box/sql/update.c
> +++ b/src/box/sql/update.c
> @@ -498,10 +498,8 @@ sqlUpdate(Parse * pParse,		/* The parser context */
>  	    pParse->triggered_space == NULL) {
>  		sqlVdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
>  		sqlVdbeSetNumCols(v, 1);
> -		sqlVdbeSetColName(v, 0, COLNAME_NAME, "rows updated",
> -				      SQL_STATIC);
> -		sqlVdbeSetColName(v, 0, COLNAME_DECLTYPE, "integer",
> -				  SQL_STATIC);
> +		vdbe_set_metadata_col_name(v, 0, "rows updated");
> +		vdbe_set_metadata_col_type(v, 0, "integer");
>  	}
>  
>   update_cleanup:
> diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
> index 582d48a1f..4142fb6ba 100644
> --- a/src/box/sql/vdbe.h
> +++ b/src/box/sql/vdbe.h
> @@ -148,17 +148,6 @@ struct SubProgram {
>  #define P5_ConstraintUnique  2
>  #define P5_ConstraintFK      4
>  
> -/*
> - * The Vdbe.aColName array contains 5n Mem structures, where n is the
> - * number of columns of data returned by the statement.
> - */
> -#define COLNAME_NAME     0
> -#define COLNAME_DECLTYPE 1
> -#define COLNAME_DATABASE 2
> -#define COLNAME_TABLE    3
> -#define COLNAME_COLUMN   4
> -#define COLNAME_N        2	/* Store the name and decltype */
> -
>  /*
>   * The following macro converts a relative address in the p2 field
>   * of a VdbeOp structure into a negative number.
> @@ -238,6 +227,10 @@ sql_vdbe_set_p4_key_def(struct Parse *parse, struct key_def *key_def);
>  VdbeOp *sqlVdbeGetOp(Vdbe *, int);
>  int sqlVdbeMakeLabel(Vdbe *);
>  void sqlVdbeRunOnlyOnce(Vdbe *);
> +
> +void
> +vdbe_metadata_delete(struct Vdbe *v);
> +
>  void sqlVdbeDelete(Vdbe *);
>  void sqlVdbeClearObject(sql *, Vdbe *);
>  void sqlVdbeMakeReady(Vdbe *, Parse *);
> @@ -248,7 +241,18 @@ void sqlVdbeResetStepResult(Vdbe *);
>  void sqlVdbeRewind(Vdbe *);
>  int sqlVdbeReset(Vdbe *);
>  void sqlVdbeSetNumCols(Vdbe *, int);
> -int sqlVdbeSetColName(Vdbe *, int, int, const char *, void (*)(void *));
> +
> +/**
> + * Set the name of the idx'th column to be returned by the SQL
> + * statement. @name must be a pointer to a nul terminated string.
> + * This call must be made after a call to sqlVdbeSetNumCols().
> + */
> +int
> +vdbe_set_metadata_col_name(struct Vdbe *v, int col_idx, const char *name);
> +
> +int
> +vdbe_set_metadata_col_type(struct Vdbe *v, int col_idx, const char *type);
> +
>  void sqlVdbeCountChanges(Vdbe *);
>  sql *sqlVdbeDb(Vdbe *);
>  void sqlVdbeSetSql(Vdbe *, const char *z, int n, int);
> diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
> index 0f32b4cd6..9ab3753cb 100644
> --- a/src/box/sql/vdbeInt.h
> +++ b/src/box/sql/vdbeInt.h
> @@ -346,6 +346,11 @@ struct ScanStatus {
>  	char *zName;		/* Name of table or index */
>  };
>  
> +struct sql_column_metadata {
> +	const char *name;
> +	const char *type;
> +};
> +
>  /*
>   * An instance of the virtual machine.  This structure contains the complete
>   * state of the virtual machine.
> @@ -394,7 +399,8 @@ struct Vdbe {
>  	Op *aOp;		/* Space to hold the virtual machine's program */
>  	Mem *aMem;		/* The memory locations */
>  	Mem **apArg;		/* Arguments to currently executing user function */
> -	Mem *aColName;		/* Column names to return */
> +	/** SQL metadata for SELECT queries. */
> +	struct sql_column_metadata *metadata;
>  	Mem *pResultSet;	/* Pointer to an array of results */
>  	VdbeCursor **apCsr;	/* One element of this array for each open cursor */
>  	Mem *aVar;		/* Values for the OP_Variable opcode. */
> diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
> index 685212d91..d746a42f2 100644
> --- a/src/box/sql/vdbeapi.c
> +++ b/src/box/sql/vdbeapi.c
> @@ -725,77 +725,24 @@ sql_column_subtype(struct sql_stmt *stmt, int i)
>  	return sql_value_subtype(columnMem(stmt, i));
>  }
>  
> -/*
> - * Convert the N-th element of pStmt->pColName[] into a string using
> - * xFunc() then return that string.  If N is out of range, return 0.
> - *
> - * There are up to 5 names for each column.  useType determines which
> - * name is returned.  Here are the names:
> - *
> - *    0      The column name as it should be displayed for output
> - *    1      The datatype name for the column
> - *    2      The name of the database that the column derives from
> - *    3      The name of the table that the column derives from
> - *    4      The name of the table column that the result column derives from
> - *
> - * If the result is not a simple column reference (if it is an expression
> - * or a constant) then useTypes 2, 3, and 4 return NULL.
> - */
> -static const void *
> -columnName(sql_stmt * pStmt,
> -	   int N, const void *(*xFunc) (Mem *), int useType)
> -{
> -	const void *ret;
> -	Vdbe *p;
> -	int n;
> -	sql *db;
> -	ret = 0;
> -	p = (Vdbe *) pStmt;
> -	db = p->db;
> -	assert(db != 0);
> -	n = sql_column_count(pStmt);
> -	if (N < n && N >= 0) {
> -		N += useType * n;
> -		assert(db->mallocFailed == 0);
> -		ret = xFunc(&p->aColName[N]);
> -		/* A malloc may have failed inside of the xFunc() call. If this
> -		 * is the case, clear the mallocFailed flag and return NULL.
> -		 */
> -		if (db->mallocFailed) {
> -			sqlOomClear(db);
> -			ret = 0;
> -		}
> -	}
> -	return ret;
> -}
> -
>  /*
>   * Return the name of the Nth column of the result set returned by SQL
>   * statement pStmt.
>   */
>  const char *
> -sql_column_name(sql_stmt * pStmt, int N)
> -{
> -	return columnName(pStmt, N, (const void *(*)(Mem *))sql_value_text,
> -			  COLNAME_NAME);
> -}
> -
> -const char *
> -sql_column_datatype(sql_stmt *pStmt, int N)
> +sql_column_name(sql_stmt *stmt, int n)
>  {
> -	return columnName(pStmt, N, (const void *(*)(Mem *))sql_value_text,
> -			  COLNAME_DECLTYPE);
> +	struct Vdbe *p = (struct Vdbe *) stmt;
> +	assert(n < sql_column_count(stmt) && n >= 0);
> +	return p->metadata[n].name;
>  }
>  
> -/*
> - * Return the column declaration type (if applicable) of the 'i'th column
> - * of the result set of SQL statement pStmt.
> - */
>  const char *
> -sql_column_decltype(sql_stmt * pStmt, int N)
> +sql_column_datatype(sql_stmt *stmt, int n)
>  {
> -	return columnName(pStmt, N, (const void *(*)(Mem *))sql_value_text,
> -			  COLNAME_DECLTYPE);
> +	struct Vdbe *p = (struct Vdbe *) stmt;
> +	assert(n < sql_column_count(stmt) && n >= 0);
> +	return p->metadata[n].type;
>  }
>  
>  /******************************* sql_bind_  **************************
> @@ -853,17 +800,15 @@ sql_bind_type(struct Vdbe *v, uint32_t position, const char *type)
>  	if (v->res_var_count < position)
>  		return 0;
>  	int rc = 0;
> -	if (sqlVdbeSetColName(v, v->var_pos[position - 1], COLNAME_DECLTYPE,
> -			      type, SQL_TRANSIENT) != 0)
> +	if (vdbe_set_metadata_col_type(v, v->var_pos[position - 1], type) != 0)
>  		rc = -1;
> -	const char *bind_name = v->aColName[position - 1].z;
> +	const char *bind_name = v->metadata[position - 1].name;
>  	if (strcmp(bind_name, "?") == 0)
>  		return rc;
>  	for (uint32_t i = position; i < v->res_var_count; ++i) {
> -		if (strcmp(bind_name,  v->aColName[i].z) == 0) {
> -			if (sqlVdbeSetColName(v, v->var_pos[i],
> -					      COLNAME_DECLTYPE, type,
> -					      SQL_TRANSIENT) != 0)
> +		if (strcmp(bind_name, v->metadata[i].name) == 0) {
> +			if (vdbe_set_metadata_col_type(v, v->var_pos[i],
> +						       type) != 0)
>  				return -1;
>  		}
>  	}
> diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
> index a1d658648..db11fbf33 100644
> --- a/src/box/sql/vdbeaux.c
> +++ b/src/box/sql/vdbeaux.c
> @@ -1827,6 +1827,18 @@ Cleanup(Vdbe * p)
>  	p->pResultSet = 0;
>  }
>  
> +void
> +vdbe_metadata_delete(struct Vdbe *v)
> +{
> +	if (v->metadata != NULL) {
> +		for (int i = 0; i < v->nResColumn; ++i) {
> +			free((void *)v->metadata[i].name);
> +			free((void *)v->metadata[i].type);
> +		}
> +		free(v->metadata);
> +	}
> +}
> +
>  /*
>   * Set the number of result columns that will be returned by this SQL
>   * statement. This is now set at compile time, rather than during
> @@ -1836,50 +1848,44 @@ Cleanup(Vdbe * p)
>  void
>  sqlVdbeSetNumCols(Vdbe * p, int nResColumn)
>  {
> -	int n;
> -	sql *db = p->db;
> -
> -	releaseMemArray(p->aColName, p->nResColumn * COLNAME_N);
> -	sqlDbFree(db, p->aColName);
> -	n = nResColumn * COLNAME_N;
> +	vdbe_metadata_delete(p);
>  	p->nResColumn = (u16) nResColumn;
> -	p->aColName = (Mem *) sqlDbMallocRawNN(db, sizeof(Mem) * n);
> -	if (p->aColName == 0)
> +	p->metadata = (struct sql_column_metadata *)
> +		calloc(nResColumn, sizeof(struct sql_column_metadata));
> +	if (p->metadata == NULL) {
> +		diag_set(OutOfMemory,
> +			 nResColumn * sizeof(struct sql_column_metadata),
> +			 "calloc", "metadata");
>  		return;
> -	initMemArray(p->aColName, n, p->db, MEM_Null);
> +	}
>  }
>  
> -/*
> - * Set the name of the idx'th column to be returned by the SQL statement.
> - * zName must be a pointer to a nul terminated string.
> - *
> - * This call must be made after a call to sqlVdbeSetNumCols().
> - *
> - * The final parameter, xDel, must be one of SQL_DYNAMIC, SQL_STATIC
> - * or SQL_TRANSIENT. If it is SQL_DYNAMIC, then the buffer pointed
> - * to by zName will be freed by sqlDbFree() when the vdbe is destroyed.
> - */
>  int
> -sqlVdbeSetColName(Vdbe * p,			/* Vdbe being configured */
> -		      int idx,			/* Index of column zName applies to */
> -		      int var,			/* One of the COLNAME_* constants */
> -		      const char *zName,	/* Pointer to buffer containing name */
> -		      void (*xDel) (void *))	/* Memory management strategy for zName */
> -{
> -	int rc;
> -	Mem *pColName;
> +vdbe_set_metadata_col_name(struct Vdbe *p, int idx, const char *name)
> +{
>  	assert(idx < p->nResColumn);
> -	assert(var < COLNAME_N);
> -	if (p->db->mallocFailed) {
> -		assert(!zName || xDel != SQL_DYNAMIC);
> +	if (p->metadata[idx].name != NULL)
> +		free((void *)p->metadata[idx].name);
> +	p->metadata[idx].name = strdup(name);
> +	if (p->metadata[idx].name == NULL) {
> +		diag_set(OutOfMemory, strlen(name), "strdup", "name");
>  		return -1;
>  	}
> -	assert(p->aColName != 0);
> -	assert(var == COLNAME_NAME || var == COLNAME_DECLTYPE);
> -	pColName = &(p->aColName[idx + var * p->nResColumn]);
> -	rc = sqlVdbeMemSetStr(pColName, zName, -1, 1, xDel);
> -	assert(rc != 0 || !zName || (pColName->flags & MEM_Term) != 0);
> -	return rc;
> +	return 0;
> +}
> +
> +int
> +vdbe_set_metadata_col_type(struct Vdbe *p, int idx, const char *type)
> +{
> +	assert(idx < p->nResColumn);
> +	if (p->metadata[idx].type != NULL)
> +		free((void *)p->metadata[idx].type);
> +	p->metadata[idx].type = strdup(type);
> +	if (p->metadata[idx].type == NULL) {
> +		diag_set(OutOfMemory, strlen(type), "strdup", "type");
> +		return -1;
> +	}
> +	return 0;
>  }
>  
>  /*
> @@ -2230,7 +2236,7 @@ sqlVdbeClearObject(sql * db, Vdbe * p)
>  {
>  	SubProgram *pSub, *pNext;
>  	assert(p->db == 0 || p->db == db);
> -	releaseMemArray(p->aColName, p->nResColumn * COLNAME_N);
> +	vdbe_metadata_delete(p);
>  	for (pSub = p->pProgram; pSub; pSub = pNext) {
>  		pNext = pSub->pNext;
>  		vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
> @@ -2242,7 +2248,6 @@ sqlVdbeClearObject(sql * db, Vdbe * p)
>  		sqlDbFree(db, p->pFree);
>  	}
>  	vdbeFreeOpArray(db, p->aOp, p->nOp);
> -	sqlDbFree(db, p->aColName);
>  	sqlDbFree(db, p->zSql);
>  }
>  
> -- 
> 2.15.1
> 


More information about the Tarantool-patches mailing list