/* * 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; }
/** 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; }
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; }