Пример #1
0
/*
 * FIXME: This function will only work if we have one db connection
 * in every context, otherwise it would initialize the result set
 * from the first connection in the context.
 */
static int check_result(db_cmd_t* cmd, struct my_cmd* payload)
{
	int i, n;
	MYSQL_FIELD *fld;
	MYSQL_RES *meta = NULL;

	meta = mysql_stmt_result_metadata(payload->st);
	if (meta == NULL) {
		/* No error means no result set to be checked */
		if (mysql_stmt_errno(payload->st) == 0) return 0;
		ERR("mysql: Error while getting metadata of SQL command: %d, %s\n",
			mysql_stmt_errno(payload->st), mysql_stmt_error(payload->st));
		return -1;
	}
	n = mysql_num_fields(meta);
	if (cmd->result == NULL) {
		/* The result set parameter of db_cmd function was empty, that
		 * means the command is select * and we have to create the array
		 * of result fields in the cmd structure manually.
		 */
		cmd->result = db_fld(n + 1);
		cmd->result_count = n;
		for(i = 0; i < cmd->result_count; i++) {
			struct my_fld *f;
			if (my_fld(cmd->result + i, cmd->table.s) < 0) goto error;
			f = DB_GET_PAYLOAD(cmd->result + i);
			fld = mysql_fetch_field_direct(meta, i);
			f->name = pkg_malloc(strlen(fld->name)+1);
			if (f->name == NULL) {
				ERR("mysql: Out of private memory\n");
				goto error;
			}
			strcpy(f->name, fld->name);
			cmd->result[i].name = f->name;
		}
	} else {
		if (cmd->result_count != n) {
			BUG("mysql: Number of fields in MySQL result does not match number of parameters in DB API\n");
			goto error;
		}
	}

	/* Now iterate through all the columns in the result set and replace
	 * any occurrence of DB_UNKNOWN type with the type of the column
	 * retrieved from the database and if no column name was provided then
	 * update it from the database as well. 
	 */
	for(i = 0; i < cmd->result_count; i++) {
		fld = mysql_fetch_field_direct(meta, i);
		if (cmd->result[i].type != DB_NONE) continue;
		switch(fld->type) {
		case MYSQL_TYPE_TINY:
		case MYSQL_TYPE_SHORT:
		case MYSQL_TYPE_INT24:
		case MYSQL_TYPE_LONG:
			cmd->result[i].type = DB_INT;
			break;

		case MYSQL_TYPE_FLOAT:
			cmd->result[i].type = DB_FLOAT;
			break;

		case MYSQL_TYPE_DOUBLE:
			cmd->result[i].type = DB_DOUBLE;
			break;

		case MYSQL_TYPE_TIMESTAMP:
		case MYSQL_TYPE_DATETIME:
			cmd->result[i].type = DB_DATETIME;
			break;

		case MYSQL_TYPE_STRING:
		case MYSQL_TYPE_VAR_STRING:
			cmd->result[i].type = DB_STR;
			break;

		default:
			ERR("mysql: Unsupported MySQL column type: %d, table: %s, column: %s\n",
				fld->type, cmd->table.s, fld->name);
			goto error;
		}
	}
	
	if (meta) mysql_free_result(meta);
	return 0;

error:
	if (meta) mysql_free_result(meta);
	return 1;
}
Пример #2
0
/** Prepare a query
 * @param cmd DB command structure
 * @param bcmd berkey DB command structure
 * @return 0 on success, -1 on error
 */
int bdb_prepare_query(db_cmd_t *cmd, bdb_cmd_t *bcmd)
{
	bdb_tcache_t *tbc = NULL;
	bdb_table_t *tp = NULL;
	bdb_fld_t *f;
	db_fld_t *fld;
	int mode;
	int i;

	if(bcmd->bcon == NULL || bcmd->bcon->dbp == NULL)
		return -1;

	tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
	if(tbc == NULL) {
		ERR("bdb: table does not exist!\n");
		return -1;
	}

	tp = tbc->dtp;
	if(tp == NULL || tp->db == NULL) {
		ERR("bdb: table not loaded!\n");
		return -1;
	}

	mode = 0;
	if(!DB_FLD_EMPTY(cmd->result)) { /* columns to be returned provided */
		if(cmd->result_count > tp->ncols) {
			ERR("bdb: too many columns in query\n");
			goto error;
		}
	} else {
		mode = 1;
		cmd->result = db_fld(tp->ncols + 1);
		cmd->result_count = tp->ncols;
		for(i = 0; i < cmd->result_count; i++) {
			if(bdb_fld(cmd->result + i, cmd->table.s) < 0)
				goto error;
		}
	}

	for(i = 0; i < cmd->result_count; i++) {
		fld = cmd->result + i;
		f = DB_GET_PAYLOAD(fld);
		if(mode == 1) {
			DBG("bdb: column name [%.*s]\n", tp->colp[i]->name.len,
					tp->colp[i]->name.s);

			f->name = pkg_malloc(tp->colp[i]->name.len + 1);
			if(f->name == NULL) {
				ERR("bdb: Out of private memory\n");
				goto error;
			}
			strncpy(f->name, tp->colp[i]->name.s, tp->colp[i]->name.len);
			f->name[tp->colp[i]->name.len] = '\0';
			fld->name = f->name;
			fld->type = tp->colp[i]->type;
			f->col_pos = i;
		} else {
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Column not found\n");
				goto error;
			}
		}
		switch(fld->type) {
			case DB_INT:
			case DB_BITMAP:
			case DB_FLOAT:
			case DB_DOUBLE:
			case DB_DATETIME:
			case DB_STR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.lstr.s = f->buf.s;
				break;

			case DB_CSTR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.cstr = f->buf.s;
				break;

			case DB_BLOB:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("mysql: No memory left\n");
					goto error;
				}
				fld[i].v.blob.s = f->buf.s;
				break;

			case DB_NONE:
				/* Eliminates gcc warning */
				break;
		}
	}

	if(!DB_FLD_EMPTY(cmd->match)) {
		if(cmd->match_count > tp->ncols) {
			ERR("bdb: too many columns in match struct of query\n");
			goto error;
		}
		for(i = 0; i < cmd->match_count; i++) {
			fld = cmd->result + i;
			f = DB_GET_PAYLOAD(fld);
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Match column not found\n");
				goto error;
			}
		}
	}

	return 0;

error:
	return -1;
}
Пример #3
0
static int get_types(db_cmd_t* cmd)
{
	struct pg_cmd* pcmd;
	struct pg_con* pcon;
	int i, n;
	pg_type_t *types;

	pcmd = DB_GET_PAYLOAD(cmd);
	/* FIXME */
	pcon = DB_GET_PAYLOAD(cmd->ctx->con[db_payload_idx]);

	types = pcon->oid;
	pcmd->types = PQdescribePrepared(pcon->con, pcmd->name);
	
	if (PQresultStatus(pcmd->types) != PGRES_COMMAND_OK) {
		ERR("postgres: Error while obtaining description of prepared statement\n");
		return -1;
	}
	/* adapted from check_result() in db_mysql */
	n = PQnfields(pcmd->types);
	if (cmd->result == NULL) {
		/* The result set parameter of db_cmd function was empty, that
		 * means the command is select * and we have to create the array
		 * of result fields in the cmd structure manually.
		 */
		cmd->result = db_fld(n + 1);
		cmd->result_count = n;
		for(i = 0; i < cmd->result_count; i++) {
			struct pg_fld *f;
			if (pg_fld(cmd->result + i, cmd->table.s) < 0) goto error;
			f = DB_GET_PAYLOAD(cmd->result + i);
			f->name = pkg_malloc(strlen(PQfname(pcmd->types, i))+1);
			if (f->name == NULL) {
				ERR("postgres: Out of private memory\n");
				goto error;
			}
			strcpy(f->name, PQfname(pcmd->types, i));
			cmd->result[i].name = f->name;
		}
	} else {
		if (cmd->result_count != n) {
			BUG("postgres: Number of fields in PQresult does not match number of parameters in DB API\n");
			goto error;
		}
	}

	/* Now iterate through all the columns in the result set and replace
	 * any occurrence of DB_UNKNOWN type with the type of the column
	 * retrieved from the database and if no column name was provided then
	 * update it from the database as well.
	 */
	for(i = 0; i < cmd->result_count; i++) {
		Oid type = PQftype(pcmd->types, i);
		if (cmd->result[i].type != DB_NONE) continue;

		if ((type == types[PG_INT2].oid) || (type == types[PG_INT4].oid) || (type == types[PG_INT8].oid))
			cmd->result[i].type = DB_INT;

		else if (type == types[PG_FLOAT4].oid)
			cmd->result[i].type = DB_FLOAT;

		else if (type == types[PG_FLOAT8].oid)
			cmd->result[i].type = DB_DOUBLE;

		else if ((type == types[PG_TIMESTAMP].oid) || (type == types[PG_TIMESTAMPTZ].oid))
			cmd->result[i].type = DB_DATETIME;

		else if ((type == types[PG_VARCHAR].oid) || (type == types[PG_CHAR].oid) || (type == types[PG_TEXT].oid))
			cmd->result[i].type = DB_STR;

		else if ((type == types[PG_BIT].oid) || (type == types[PG_VARBIT].oid))
			cmd->result[i].type = DB_BITMAP;

		else if (type == types[PG_BYTE].oid)
			cmd->result[i].type = DB_BLOB;

		else
		{
			ERR("postgres: Unsupported PostgreSQL column type: %d, table: %s, column: %s\n",
				type, cmd->table.s, PQfname(pcmd->types, i));
			goto error;
		}
	}
	return 0;
error:
	return -1;
}