const unsigned char* sqlite3_column_text(mysqlite3_stmt* stmt, int iCol) { MYSQL_BIND* result = &stmt->results[iCol]; result->buffer_type = MYSQL_TYPE_STRING; if (result->length) { unsigned long length = *result->length; if (result->buffer) { free(result->buffer); } // The +1 for the \0 at the end of the string result->buffer = (unsigned char*)malloc(length+1); memset(result->buffer, 0, length+1); // Don't tell MySQL about the extra byte at the end so that we return // a proper zero-byte terminated string. result->buffer_length = length; } mysql_stmt_fetch_column(stmt->mystmt, result, iCol, 0); return (const unsigned char*)result->buffer; };
Row Cursor::fetch() { log_debug("mysql_stmt_fetch(" << stmt << ')'); int ret = mysql_stmt_fetch(stmt); if (ret == MYSQL_DATA_TRUNCATED) { // fetch column data where truncated MYSQL_FIELD* fields = mysqlStatement->getFields(); for (unsigned n = 0; n < row->getSize(); ++n) { if (*row->getMysqlBind()[n].length > row->getMysqlBind()[n].buffer_length) { // actual length was longer than buffer_length, so this column is truncated fields[n].length = *row->getMysqlBind()[n].length; row->initOutBuffer(n, fields[n]); log_debug("mysql_stmt_fetch_column(" << stmt << ", BIND, " << n << ", 0) with " << fields[n].length << " bytes"); if (mysql_stmt_fetch_column(stmt, row->getMysqlBind() + n, n, 0) != 0) throw MysqlStmtError("mysql_stmt_fetch_column", stmt); } } } else if (ret == MYSQL_NO_DATA) { log_debug("MYSQL_NO_DATA"); row = 0; return Row(); } else if (ret == 1) throw MysqlStmtError("mysql_stmt_fetch", stmt); return Row(&*row); }
void wpl_mysql_res_holder::refetch_truncated() { int i = -1; for (wpl_mysql_field &field : fields) { i++; if (!field.error) { continue; } int new_length = field.real_length; field.value->resize(new_length); MYSQL_BIND my_bind; memset (&my_bind, 0, sizeof (my_bind)); my_bind.buffer_type = bind[i].buffer_type; my_bind.buffer_length = new_length; my_bind.buffer = field.value->toVoid(); if (mysql_stmt_fetch_column(stmt, &my_bind, i, 0)) { cerr << "MySQL error: " << mysql_stmt_error(stmt) << endl; throw runtime_error("Could not re-fetch column"); } } }
/* An improved API that was proposed but not followed up */ static int dbd_mysql_get_entry(const apr_dbd_row_t *row, int n, apr_dbd_datum_t *val) { MYSQL_BIND *bind; if (dbd_mysql_num_cols(row->res) <= n) { return NULL; } if (row->res->statement) { bind = &row->res->bind[n]; if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) { val->type = APR_DBD_VALUE_NULL; return -1; } if (*bind->is_null) { val->type = APR_DBD_VALUE_NULL; return -1; } else { val->type = APR_DBD_VALUE_STRING; val->value.stringval = bind->buffer; } } else { val->type = APR_DBD_VALUE_STRING; val->value.stringval = row->row[n]; } return 0; }
json::Node PreparedQueryBase::_refetchStringValue( const std::size_t index ){ // These types which are of uncertain size we must fetch separately now that we know how much // space to allocate. MYSQL_BIND& binder = m_results[ index ]; if( *binder.length == 0 ){ return json::Node( "", "" ); } // It is not empty, so create a new binder and copy over this one's values. MYSQL_BIND rightSizeBinder; memcpy( &rightSizeBinder, &binder, sizeof( MYSQL_BIND ) ); rightSizeBinder.buffer = new char[ (*binder.length) + 1 ]; rightSizeBinder.buffer_length = (*binder.length) + 1; // Now fetch the column with our right-sized buffer. try { mysql_stmt_fetch_column( m_statement, &rightSizeBinder, index, 0 ); LW_MYSQL_STMT_CHECK_FOR_ERRORS( m_statement, "Failed to fetch column" ); } catch( ... ){ lw::util::safeDeleteArray( (char*&)rightSizeBinder.buffer ); rethrow_exception( current_exception() ); } // Now convert the value to a string JSON node, clean up, and return. json::Node node( "", string( (char*)rightSizeBinder.buffer, *rightSizeBinder.length ) ); lw::util::safeDeleteArray( (char*&)rightSizeBinder.buffer ); return node; }
static const char *dbd_mysql_get_entry(const apr_dbd_row_t *row, int n) { MYSQL_BIND *bind; const char *result = NULL; if (dbd_mysql_num_cols(row->res) <= n) { return NULL; } if (row->res->statement) { bind = &row->res->bind[n]; if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) { return NULL; } if (*bind->is_null) { return NULL; } else { result = bind->buffer; } } else { result = row->row[n]; } if (result != NULL) { /* need to copy this - PR 46421 * Don't know why, when it apparently came from an array * in the first place. */ result = apr_pstrdup(row->res->pool, result); } return result; }
static int gt_rdb_stmt_mysql_get_double(GtRDBStmt *st, GtUword field_no, double *result, GtError *err) { GtRDBStmtMySQL *stm; MYSQL_BIND res_bind; int had_err = 0; double res_double = GT_UNDEF_DOUBLE; my_bool error, is_null; gt_assert(st && result); gt_error_check(err); stm = gt_rdb_stmt_mysql_cast(st); CHECK_INIT_STATEMENT if (!had_err) { memset(&res_bind, 0, sizeof (res_bind)); res_bind.buffer_type = MYSQL_TYPE_DOUBLE; res_bind.buffer = &res_double; res_bind.error = &error; res_bind.is_null = &is_null; if ((had_err = mysql_stmt_fetch_column(stm->stmt, &res_bind, field_no, 0))) gt_error_set(err, GT_MYSQL_ERRMSG, had_err, mysql_stmt_error(stm->stmt)); } if (!had_err) *result = res_double; return had_err; }
bool MyBoundResults::RefetchField(MYSQL_STMT *stmt, unsigned int id, size_t initSize, enum_field_types type) { ResultBind *rbind = &m_pull[id]; /* Make sure there is a buffer to pull into */ ResizeBuffer(rbind, initSize); /* Update the bind with the buffer size */ m_bind[id].buffer = rbind->blob; m_bind[id].buffer_length = (unsigned long)rbind->length; m_bUpdatedBinds = true; MYSQL_BIND bind; /* Initialize bind info */ memset(&bind, 0, sizeof(MYSQL_BIND)); bind.buffer = rbind->blob; bind.buffer_type = type; bind.buffer_length = (unsigned long)rbind->length; bind.length = &(rbind->my_length); bind.is_null = &(rbind->my_null); /* Attempt to fetch */ return (mysql_stmt_fetch_column(stmt, &bind, id, 0) == 0); }
NS_IMETHODIMP jxMySQL50Statement::GetUTF8Text(PRUint32 aIndex, nsACString &aData) { if (mConnection == nsnull) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_NOT_CONNECTED); } if (mSTMT == nsnull) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_STMT_NULL); } if (aIndex < 0 || aIndex >= mOut.mCount) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_ILLEGAL_VALUE); } if (mOut.mBindArrayIsNull[aIndex]) { // null columns get IsVoid set to distinguish them from empty strings aData.Truncate(0); aData.SetIsVoid(PR_TRUE); }else { int nsize = mOut.mBindArrayBufferTYPE_STRING_LEN_OUT[aIndex]; char *data = static_cast<char*>(nsMemory::Alloc(nsize+1)); //extra for the null if (data == NULL) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_OUT_OF_MEMORY); } my_bool is_null; my_bool error; unsigned long length; MYSQL_BIND bind; memset(&bind, 0, sizeof(bind)); bind.buffer= (void*)data; bind.buffer_length= nsize; bind.buffer_type = MYSQL_TYPE_STRING; bind.is_null= &is_null; bind.length= &length; bind.error= &error; if (mysql_stmt_fetch_column(mSTMT, &bind, aIndex, 0)) { SET_ERROR_RETURN (JX_MYSQL50_MYSQL_ERROR); } data[nsize] = 0; aData = nsDependentCString(data, nsize); } return NS_OK; }
bool bind_result_t::next_impl() { if (_handle->debug) std::cerr << "MySQL debug: Accessing next row of handle at " << _handle.get() << std::endl; auto flag = mysql_stmt_fetch(_handle->mysql_stmt); switch (flag) { case 0: case MYSQL_DATA_TRUNCATED: { bool need_to_rebind = false; for (auto& r : _handle->result_param_meta_data) { if (r.len) { if (r.bound_is_null) { *r.text_buffer = nullptr; *r.len = 0; } else { if (r.bound_len > r.bound_text_buffer.size()) { if (_handle->debug) std::cerr << "MySQL debug: Need to reallocate buffer at index " << r.index << " for handle at " << _handle.get() << std::endl; need_to_rebind = true; r.bound_text_buffer.resize(r.bound_len); MYSQL_BIND& param = _handle->result_params[r.index]; param.buffer = r.bound_text_buffer.data(); param.buffer_length = r.bound_text_buffer.size(); if (mysql_stmt_fetch_column(_handle->mysql_stmt, _handle->result_params.data() + r.index, r.index, 0)) throw sqlpp::exception(std::string("MySQL: Fetch column after reallocate failed: ") + mysql_stmt_error(_handle->mysql_stmt)); } *r.text_buffer = r.bound_text_buffer.data(); *r.len = r.bound_len; } } if (r.is_null) *r.is_null = r.bound_is_null; } if (need_to_rebind) bind_impl(); } return true; case 1: throw sqlpp::exception(std::string("MySQL: Could not fetch next result: ") + mysql_stmt_error(_handle->mysql_stmt)); case MYSQL_NO_DATA: return false; default: throw sqlpp::exception("MySQL: Unexpected return value for mysql_stmt_fetch()"); } }
NS_IMETHODIMP jxMySQL50Statement::GetBlob(PRUint32 aIndex, PRUint32 *aDataSize, PRUint8 **aData) { if (mConnection == nsnull) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_NOT_CONNECTED); } if (mSTMT == nsnull) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_STMT_NULL); } if (aIndex < 0 || aIndex >= mOut.mCount) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_ILLEGAL_VALUE); } int blobsize = mOut.mBindArrayBufferTYPE_STRING_LEN_OUT[aIndex]; if (blobsize > 0) { void *blob = static_cast<void*>(nsMemory::Alloc(blobsize)); if (blob == NULL) { SET_ERROR_RETURN (JX_MYSQL50_ERROR_OUT_OF_MEMORY); } my_bool is_null; my_bool error; unsigned long length; MYSQL_BIND bind; memset(&bind, 0, sizeof(bind)); bind.buffer_type = MYSQL_TYPE_BLOB; bind.buffer= blob; bind.buffer_length= blobsize; bind.is_null= &is_null; bind.length= &length; bind.error= &error; if (mysql_stmt_fetch_column(mSTMT, &bind, aIndex, 0)) { SET_ERROR_RETURN (JX_MYSQL50_MYSQL_ERROR); } *aData = (PRUint8*) blob; *aDataSize = blobsize; }else { *aData = 0; *aDataSize = 0; } return NS_OK; }
static apr_status_t lob_bucket_read(apr_bucket *e, const char **str, apr_size_t *len, apr_read_type_e block) { apr_bucket_lob *a = e->data; const apr_dbd_row_t *row = a->row; apr_dbd_results_t *res = row->res; int col = a->col; apr_bucket *b = NULL; int rv; apr_size_t blength = e->length; /* bytes remaining in file past offset */ apr_off_t boffset = e->start; MYSQL_BIND *bind = &res->bind[col]; *str = NULL; /* in case we die prematurely */ /* fetch from offset if not at the beginning */ if (boffset > 0) { rv = mysql_stmt_fetch_column(res->statement, bind, col, (unsigned long) boffset); if (rv != 0) { return APR_EGENERAL; } } blength -= blength > bind->buffer_length ? bind->buffer_length : blength; *len = e->length - blength; *str = bind->buffer; /* allocate new buffer, since we used this one for the bucket */ bind->buffer = apr_palloc(res->pool, bind->buffer_length); /* * Change the current bucket to refer to what we read, * even if we read nothing because we hit EOF. */ apr_bucket_pool_make(e, *str, *len, res->pool); /* If we have more to read from the field, then create another bucket */ if (blength > 0) { /* for efficiency, we can just build a new apr_bucket struct * to wrap around the existing LOB bucket */ b = apr_bucket_alloc(sizeof(*b), e->list); b->start = boffset + *len; b->length = blength; b->data = a; b->type = &apr_bucket_type_lob; b->free = apr_bucket_free; b->list = e->list; APR_BUCKET_INSERT_AFTER(e, b); } else { lob_bucket_destroy(a); } return APR_SUCCESS; }
FOR_EACH_UINT32(i, mResultCount) { MYSQL_BIND& bind = resultBinds[i]; ulong alreadyRetrieved = bind.buffer_length; if (bind.length != nullptr&&alreadyRetrieved < *bind.length) { if (bind.buffer_type == MYSQL_TYPE_BLOB || bind.buffer_type == MYSQL_TYPE_TINY_BLOB || bind.buffer_type == MYSQL_TYPE_MEDIUM_BLOB || bind.buffer_type == MYSQL_TYPE_LONG_BLOB) { MemoryData& data = *(MemoryData*)bind.extension; data.Realloc(*bind.length); bind.buffer = data.MutableData() + alreadyRetrieved; bind.buffer_length = (ulong)data.Size() - alreadyRetrieved; const int status = mysql_stmt_fetch_column(mSTMT, &bind, i, alreadyRetrieved); if (0 != status) { throw SqlException(mSTMT, mysql_stmt_error(mSTMT)); } } else if (bind.buffer_type == MYSQL_TYPE_VAR_STRING || bind.buffer_type == MYSQL_TYPE_STRING || bind.buffer_type == MYSQL_TYPE_VARCHAR) { HeapString& str = *(HeapString*)bind.extension; str.ReserveLength(*bind.length); bind.buffer = str.MutableBuffer() + alreadyRetrieved; bind.buffer_length = (ulong)str.Size() - alreadyRetrieved; const int status = mysql_stmt_fetch_column(mSTMT, &bind, i, alreadyRetrieved); if (0 != status) { throw SqlException(mSTMT, mysql_stmt_error(mSTMT)); } str.ForceSetLength(*bind.length); } } }
static inline void ensureCapacity(T R, int i) { if ((R->columns[i].real_length > R->bind[i].buffer_length)) { /* Column was truncated, resize and fetch column directly. */ RESIZE(R->columns[i].buffer, R->columns[i].real_length + 1); R->bind[i].buffer = R->columns[i].buffer; R->bind[i].buffer_length = R->columns[i].real_length; if ((R->lastError = mysql_stmt_fetch_column(R->stmt, &R->bind[i], i, 0))) THROW(SQLException, "mysql_stmt_fetch_column -- %s", mysql_stmt_error(R->stmt)); R->needRebind = true; } }
bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind) { if (_state < STMT_EXECUTED) throw StatementException("Statement is not executed yet"); int res = mysql_stmt_fetch_column(_pHandle, bind, static_cast<unsigned int>(n), 0); if ((res != 0) && (res != MYSQL_NO_DATA)) throw StatementException(Poco::format("mysql_stmt_fetch_column(%z) error", n), _pHandle, _query); return (res == 0); }
bool RefetchUserField(MYSQL_STMT *stmt, unsigned int id, void *userbuf, size_t userlen, enum_field_types type, my_bool &is_null, size_t *written) { MYSQL_BIND bind; unsigned long length; /* Initialize bind info */ memset(&bind, 0, sizeof(MYSQL_BIND)); bind.buffer = userbuf; bind.buffer_type = type; bind.length = &length; bind.is_null = &is_null; bind.buffer_length = (unsigned long)userlen; if (mysql_stmt_fetch_column(stmt, &bind, id, 0) != 0) { return false; } if (is_null) { return true; } if (type == MYSQL_TYPE_STRING && (size_t)length == userlen) { /* Enforce null termination in case MySQL forgot. * Note we subtract one from the length (which must be >= 1) * so we can pass the number of bytes written below. */ char *data = (char *)userbuf; data[--userlen] = '\0'; } if (written) { /* In the case of strings, they will never be equal */ *written = (userlen < length) ? userlen : length; } return true; }
bool StatementExecutor::fetchColumn(size_t n, MYSQL_BIND *bind) { if (_state < STMT_EXECUTED) { throw StatementException("Satement is not executed yet"); } int res = mysql_stmt_fetch_column(h, bind, static_cast<unsigned int>(n), 0); if ((res != 0) && (res != MYSQL_NO_DATA)) { std::ostringstream msg; msg << "mysql_stmt_fetch_column(" << n << ") error"; throw StatementException(msg.str(), h, _query); } return (res == 0); }
static void store_buffer(MYSQL_STMT *stmt, int offset_index, MYSQL_BIND *bind, int chunk_length, VALUE block, VALUE obj) { int status = mysql_stmt_fetch_column(stmt, bind, 0, offset_index); if (status != 0) { rb_raise(rb_eRuntimeError, "Fetching column failed"); } if (!*bind->is_null) { if (bind->buffer_type == MYSQL_TYPE_BLOB) { if(RTEST(block)) { rb_funcall(block, rb_intern("call"), 1, rb_str_new(bind->buffer, chunk_length)); } else { rb_raise(rb_eArgError, "a block is required"); } } else { rb_raise(rb_eRuntimeError, "wrong buffer_type (must be: MYSQL_TYPE_BLOB): %d", bind->buffer_type); } } }
static const char *dbd_mysql_get_entry(const apr_dbd_row_t *row, int n) { MYSQL_BIND *bind; if (row->res->statement) { bind = &row->res->bind[n]; if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) { return NULL; } if (*bind->is_null) { return NULL; } else { return bind->buffer; } } else { return row->row[n]; } return NULL; }
int sqlite3_column_int(mysqlite3_stmt* stmt, int iCol) { MYSQL_BIND* result = &stmt->results[iCol]; result->buffer_type = MYSQL_TYPE_LONG; if (result->length) { unsigned long length = *result->length; if (result->buffer) { free(result->buffer); } result->buffer = (int*)malloc(length); result->buffer_length = length; } mysql_stmt_fetch_column(stmt->mystmt, result, iCol, 0); return *(int*)result->buffer; };
DBResult RefetchSize4Field(MYSQL_STMT *stmt, unsigned int id, void *buffer, enum_field_types type) { MYSQL_BIND bind; my_bool is_null; /* Initialize bind info */ memset(&bind, 0, sizeof(MYSQL_BIND)); bind.buffer = buffer; bind.buffer_type = type; bind.is_null = &is_null; /* Attempt to fetch */ if (mysql_stmt_fetch_column(stmt, &bind, id, 0) != 0) { return DBVal_TypeMismatch; } return is_null ? DBVal_Null : DBVal_Data; }
int sql_fetch_row(struct subdbinfo *info, void *result, unsigned int ncolumns, struct stralloc *columns) { MYSQL_BIND bind[ncolumns]; unsigned long lengths[ncolumns]; unsigned int i; byte_zero((char*)bind,sizeof bind); byte_zero((char*)lengths,sizeof lengths); for (i = 0; i < ncolumns; ++i) { bind[i].buffer_type = MYSQL_TYPE_BLOB; bind[i].buffer = 0; bind[i].buffer_length = 0; bind[i].length = &lengths[i]; } if (mysql_stmt_bind_result((MYSQL_STMT*)result,bind) != 0) die_sqlerror(info); switch (mysql_stmt_fetch((MYSQL_STMT*)result)) { case MYSQL_DATA_TRUNCATED: /* expect this since buffer_length == 0 */ break; case MYSQL_NO_DATA: return 0; default: die_sqlerror(info); } for (i = 0; i < ncolumns; ++i) { stralloc_ready(&columns[i],lengths[i]); bind[i].buffer = columns[i].s; bind[i].buffer_length = lengths[i]; mysql_stmt_fetch_column((MYSQL_STMT*)result,&bind[i],i,0); columns[i].len = lengths[i]; } return 1; }
/* * Fetches a string column. */ void read_string (lua_State *L, mysql_rec *m, int i) { luaL_Buffer b; unsigned long length, offset, count; luaL_buffinit(L, &b); length = m->lengths[i]; offset = 0; m->bind[i].buffer_length = LUAL_BUFFERSIZE; while (offset < length) { m->bind[i].buffer = luaL_prepbuffer(&b); if (mysql_stmt_fetch_column(m->stmt, &m->bind[i], i, offset) != 0) { error(L, m); } count = length - offset; if (count > LUAL_BUFFERSIZE) { count = LUAL_BUFFERSIZE; } luaL_addsize(&b, count); offset += count; } luaL_pushresult(&b); }
void Statement::GetDataInRow(unsigned int column, Nullable<Binary> &result) { if (column >= _resultParams.size()) { throw DatabaseException("Error in Statement::GetDataInRow", 0, "----", "column out of range"); } if (! (*(_resultParams[column]->IsNull()))) { if (_resultBind[column].buffer_type == MYSQL_TYPE_TINY_BLOB) { if (*(_resultParams[column]->BufferLength()) >= 256) { throw DatabaseException("Error in Statement::GetDataInRow", 0, "----", "data too large for Blob type"); } } else if (_resultBind[column].buffer_type == MYSQL_TYPE_BLOB) { if (*(_resultParams[column]->BufferLength()) >= 64 * 1024) { throw DatabaseException("Error in Statement::GetDataInRow", 0, "----", "data too large for Blob type"); } } else if (_resultBind[column].buffer_type == MYSQL_TYPE_MEDIUM_BLOB) { if (*(_resultParams[column]->BufferLength()) >= 16 * 1024 * 1024) { throw DatabaseException("Error in Statement::GetDataInRow", 0, "----", "data too large for Medium Blob type"); } } else if (_resultBind[column].buffer_type == MYSQL_TYPE_LONG_BLOB) { if (*(_resultParams[column]->BufferLength()) >= (size_t) 4 * 1024 * 1024 * 1024) { throw DatabaseException("Error in Statement::GetDataInRow", 0, "----", "data too large for Large Blob type"); } } else { throw DatabaseException("Error in Statement::GetDataInRow<Binary>", 0, "----", "column not of correct type (should be Blob)"); } if (mysql_stmt_fetch_column(_stmt, &(_resultBind[column]), column, 0) != 0) { throw DatabaseException(_stmt, "Error in GetDataInRow<Binary>"); } Binary fromdb; fromdb.AssignDataToBuffer((unsigned char *)_resultParams[column]->Buffer(), *(_resultParams[column]->BufferLength())); result = fromdb; } else { result.ClearValue(); } }
static GdaRow * new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, GError **error) { //g_print ("%s(): NCOLS=%d ROWNUM=%d\n", __func__, ((GdaDataSelect *) imodel)->prep_stmt->ncols, rownum); int res; MYSQL_BIND *mysql_bind_result; g_return_val_if_fail (imodel->priv->mysql_stmt != NULL, NULL); mysql_bind_result = ((GdaMysqlPStmt *) ((GdaDataSelect *) imodel)->prep_stmt)->mysql_bind_result; g_assert (mysql_bind_result); res = mysql_stmt_fetch (imodel->priv->mysql_stmt); if (res == MYSQL_NO_DATA) { /* should not happen */ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR, "%s", "No more data, please report this bug to " "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider."); } else if (res == MYSQL_DATA_TRUNCATED) { GString *string; string = g_string_new ("Truncated data, please report this bug to " "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider."); gint col; for (col = 0; col < ((GdaDataSelect *) imodel)->prep_stmt->ncols; ++col) { my_bool truncated; mysql_bind_result[col].error = &truncated; mysql_stmt_fetch_column (imodel->priv->mysql_stmt, &(mysql_bind_result[col]), (unsigned int)col, 0); if (truncated) g_string_append_printf (string, "\n column %d is truncated\n", col); mysql_bind_result[col].error = NULL; } g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR, "%s", string->str); g_string_free (string, TRUE); return NULL; } else if (res) { _gda_mysql_make_error (imodel->priv->cnc, NULL, imodel->priv->mysql_stmt, error); return NULL; } /* g_print ("%s: SQL=%s\n", __func__, ((GdaDataSelect *) imodel)->prep_stmt->sql); */ GdaRow *row = gda_row_new (((GdaDataSelect *) imodel)->prep_stmt->ncols); gint col; for (col = 0; col < ((GdaDataSelect *) imodel)->prep_stmt->ncols; ++col) { gint i = col; GValue *value = gda_row_get_value (row, i); GType type = ((GdaDataSelect *) imodel)->prep_stmt->types[i]; /*g_print ("%s: #%d : TYPE=%d, GTYPE=%s\n", __func__, i, mysql_bind_result[i].buffer_type, g_type_name (type));*/ my_bool is_null = FALSE; unsigned long length; g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof (my_bool)); if (is_null) { gda_value_set_null (value); continue; } else gda_value_reset_with_type (value, type); switch (mysql_bind_result[i].buffer_type) { case MYSQL_TYPE_SHORT: { short int bvalue = 0; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); g_value_set_int (value, bvalue); break; } case MYSQL_TYPE_TINY: { signed char bvalue = 0; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); g_value_set_int (value, bvalue); break; } case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: case MYSQL_TYPE_YEAR: { int bvalue = 0; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); if (type == G_TYPE_INT) g_value_set_int (value, bvalue); else if (type == G_TYPE_LONG) g_value_set_long (value, (long) bvalue); else if (type == G_TYPE_BOOLEAN) g_value_set_boolean (value, bvalue ? TRUE : FALSE); else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %d"), g_type_name (type), bvalue); } break; } case MYSQL_TYPE_LONGLONG: { long long bvalue = 0; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); if (type == G_TYPE_BOOLEAN) g_value_set_boolean (value, bvalue ? TRUE : FALSE); else if (type == G_TYPE_INT) g_value_set_int (value, bvalue); else if (type == G_TYPE_LONG) g_value_set_long (value, bvalue); else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %lld"), g_type_name (type), bvalue); } break; } case MYSQL_TYPE_NULL: gda_value_set_null (value); break; case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME bvalue = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); if (type == GDA_TYPE_TIME) { GdaTime time = { .hour = bvalue.hour, .minute = bvalue.minute, .second = bvalue.second, .fraction = bvalue.second_part, .timezone = 0 /* GMT */ }; gda_value_set_time (value, &time); } else if (type == G_TYPE_DATE) { GDate *date = g_date_new_dmy ((bvalue.day != 0) ? bvalue.day : 1, (bvalue.month != 0) ? bvalue.month : 1, (bvalue.year != 0) ? bvalue.year : 1970); g_value_take_boxed (value, date); } else if (type == GDA_TYPE_TIMESTAMP) { GdaTimestamp timestamp = { .year = bvalue.year, .month = bvalue.month, .day = bvalue.day, .hour = bvalue.hour, .minute = bvalue.minute, .second = bvalue.second, .fraction = bvalue.second_part, .timezone = 0 /* GMT */ }; gda_value_set_timestamp (value, ×tamp); } else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %d/%d/%d %d:%d:%d.%lu"), g_type_name (type), bvalue.year, bvalue.month, bvalue.day, bvalue.hour, bvalue.minute, bvalue.second, bvalue.second_part); } break; } case MYSQL_TYPE_FLOAT: { float bvalue = 0.; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); if (type == G_TYPE_FLOAT) g_value_set_float (value, (float) bvalue); else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %f"), g_type_name (type), bvalue); } break; } case MYSQL_TYPE_DOUBLE: { double bvalue = 0.0; g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue)); if (type == G_TYPE_DOUBLE) g_value_set_double (value, bvalue); else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %f"), g_type_name (type), bvalue); } break; } case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_NEWDECIMAL: case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_BIT: { char *bvalue = NULL; g_memmove (&length, mysql_bind_result[i].length, sizeof (unsigned long)); if (length > 0) { bvalue = g_malloc (length + 1); memcpy (bvalue, mysql_bind_result[i].buffer, length); bvalue [length] = 0; } if (type == G_TYPE_STRING) g_value_set_string (value, bvalue); else if (type == GDA_TYPE_BINARY) { GdaBinary binary = { .data = (guchar*) bvalue, .binary_length = length }; gda_value_set_binary (value, &binary); } else if (type == GDA_TYPE_BLOB) { /* we don't use GdaMysqlBlobOp because it looks like the MySQL * API does not support BLOBs accessed in a random way, * so we return the whole BLOB at once */ GdaBlob blob = { {(guchar*) bvalue, length}, NULL }; gda_value_set_blob (value, &blob); } else if (type == GDA_TYPE_NUMERIC) { if (length > 0) { GdaNumeric *numeric; numeric = gda_numeric_new (); gda_numeric_set_from_string (numeric, bvalue); gda_numeric_set_precision (numeric, 6); gda_numeric_set_width (numeric, length); gda_value_set_numeric (value, numeric); gda_numeric_free (numeric); } } else if (type == G_TYPE_DOUBLE) { if (length > 0) g_value_set_double (value, g_ascii_strtod (bvalue, NULL)); else { /* error: wrong column type */ gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Invalid column bind data type. %d\n"), mysql_bind_result[i].buffer_type); break; } } else if (type == G_TYPE_INT) { if (length > 0) g_value_set_int (value, atoi (bvalue)); else { /* error: wrong column type */ gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Invalid column bind data type. %d\n"), mysql_bind_result[i].buffer_type); break; } } else if (type == G_TYPE_BOOLEAN) { if (length > 0) g_value_set_boolean (value, atoi (bvalue)); else { /* error: wrong column type */ gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Invalid column bind data type. %d\n"), mysql_bind_result[i].buffer_type); break; } } else { gda_row_invalidate_value (row, value); g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR, _("Type %s not mapped for value %s"), g_type_name (type), bvalue); } g_free (bvalue); break; }
static SLVAL sl_mysql_stmt_execute(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { mysql_stmt_t* stmt = get_mysql_stmt(vm, self); size_t req = mysql_stmt_param_count(stmt->stmt); if(argc < req) { char buff[100]; sprintf(buff, "Prepared statement has %lu parameter markers, but only %lu parameters were given", req, argc); sl_throw_message2(vm, vm->lib.ArgumentError, buff); } if(!stmt->bind) { stmt->bind = sl_alloc(vm->arena, sizeof(MYSQL_BIND) * req); } for(size_t i = 0; i < req; i++) { stmt->bind[i].buffer_type = MYSQL_TYPE_STRING; sl_string_t* str = sl_get_string(vm, sl_to_s(vm, argv[i])); stmt->bind[i].buffer = str->buff; stmt->bind[i].buffer_length = str->buff_len; stmt->bind[i].length = NULL; stmt->bind[i].is_null = NULL; stmt->bind[i].is_unsigned = 1; stmt->bind[i].error = NULL; } if(mysql_stmt_bind_param(stmt->stmt, stmt->bind)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } if(mysql_stmt_execute(stmt->stmt)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } MYSQL_RES* res = mysql_stmt_result_metadata(stmt->stmt); if(!res) { /* query did not produce a result set */ return sl_make_int(vm, mysql_stmt_affected_rows(stmt->stmt)); } int field_count = mysql_stmt_field_count(stmt->stmt); MYSQL_FIELD* field; SLVAL field_names[field_count]; enum enum_field_types field_types[field_count]; size_t field_i = 0; while((field = mysql_fetch_field(res))) { field_names[field_i] = sl_make_cstring(vm, field->name); if(field->type == MYSQL_TYPE_LONG || field->type == MYSQL_TYPE_SHORT || field->type == MYSQL_TYPE_TINY) { field_types[field_i] = MYSQL_TYPE_LONG; } else { field_types[field_i] = MYSQL_TYPE_STRING; } field_i++; } MYSQL_BIND output_binds[field_count]; my_bool output_errors[field_count]; my_bool output_is_nulls[field_count]; unsigned long output_lengths[field_count]; for(int i = 0; i < field_count; i++) { output_binds[i].buffer_type = MYSQL_TYPE_STRING; output_binds[i].buffer = NULL; output_binds[i].buffer_length = 0; output_binds[i].length = &output_lengths[i]; output_binds[i].is_null = &output_is_nulls[i]; output_binds[i].error = &output_errors[i]; } if(mysql_stmt_bind_result(stmt->stmt, output_binds)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL result_rows = sl_make_array(vm, 0, NULL); while(1) { int code = mysql_stmt_fetch(stmt->stmt); if(code == MYSQL_NO_DATA) { break; } if(code == 1) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL row = sl_make_dict(vm, 0, NULL); for(int i = 0; i < field_count; i++) { MYSQL_BIND cell; cell.length = &output_lengths[i]; cell.is_null = &output_is_nulls[i]; cell.error = &output_errors[i]; cell.buffer_type = field_types[i]; int buffer_long; switch(field_types[i]) { case MYSQL_TYPE_LONG: cell.buffer = &buffer_long; cell.buffer_length = sizeof(buffer_long); break; default: /* MYSQL_TYPE_STRING */ cell.buffer = sl_alloc_buffer(vm->arena, output_lengths[i] + 1); cell.buffer_length = output_lengths[i]; break; } if(mysql_stmt_fetch_column(stmt->stmt, &cell, i, 0)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } switch(field_types[i]) { case MYSQL_TYPE_LONG: sl_dict_set(vm, row, field_names[i], sl_make_int(vm, buffer_long)); break; default: /* MYSQL_TYPE_STRING */ sl_dict_set(vm, row, field_names[i], sl_make_string(vm, cell.buffer, output_lengths[i])); break; } } sl_array_push(vm, result_rows, 1, &row); } return result_rows; }
static apr_status_t dbd_mysql_datum_get(const apr_dbd_row_t *row, int n, apr_dbd_type_e type, void *data) { if (row->res->statement) { MYSQL_BIND *bind = &row->res->bind[n]; unsigned long len = *bind->length; if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) { return APR_EGENERAL; } if (*bind->is_null) { return APR_ENOENT; } switch (type) { case APR_DBD_TYPE_TINY: *(char*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_UTINY: *(unsigned char*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_SHORT: *(short*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_USHORT: *(unsigned short*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_INT: *(int*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_UINT: *(unsigned int*)data = atoi(bind->buffer); break; case APR_DBD_TYPE_LONG: *(long*)data = atol(bind->buffer); break; case APR_DBD_TYPE_ULONG: *(unsigned long*)data = atol(bind->buffer); break; case APR_DBD_TYPE_LONGLONG: *(apr_int64_t*)data = apr_atoi64(bind->buffer); break; case APR_DBD_TYPE_ULONGLONG: *(apr_uint64_t*)data = apr_atoi64(bind->buffer); break; case APR_DBD_TYPE_FLOAT: *(float*)data = (float) atof(bind->buffer); break; case APR_DBD_TYPE_DOUBLE: *(double*)data = atof(bind->buffer); break; case APR_DBD_TYPE_STRING: case APR_DBD_TYPE_TEXT: case APR_DBD_TYPE_TIME: case APR_DBD_TYPE_DATE: case APR_DBD_TYPE_DATETIME: case APR_DBD_TYPE_TIMESTAMP: case APR_DBD_TYPE_ZTIMESTAMP: *((char*)bind->buffer+bind->buffer_length-1) = '\0'; *(char**)data = bind->buffer; break; case APR_DBD_TYPE_BLOB: case APR_DBD_TYPE_CLOB: { apr_bucket *e; apr_bucket_brigade *b = (apr_bucket_brigade*)data; e = apr_bucket_lob_create(row, n, 0, len, row->res->pool, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); } break; case APR_DBD_TYPE_NULL: *(void**)data = NULL; break; default: return APR_EGENERAL; } } else { if (row->row[n] == NULL) { return APR_ENOENT; } switch (type) { case APR_DBD_TYPE_TINY: *(char*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_UTINY: *(unsigned char*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_SHORT: *(short*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_USHORT: *(unsigned short*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_INT: *(int*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_UINT: *(unsigned int*)data = atoi(row->row[n]); break; case APR_DBD_TYPE_LONG: *(long*)data = atol(row->row[n]); break; case APR_DBD_TYPE_ULONG: *(unsigned long*)data = atol(row->row[n]); break; case APR_DBD_TYPE_LONGLONG: *(apr_int64_t*)data = apr_atoi64(row->row[n]); break; case APR_DBD_TYPE_ULONGLONG: *(apr_uint64_t*)data = apr_atoi64(row->row[n]); break; case APR_DBD_TYPE_FLOAT: *(float*)data = (float) atof(row->row[n]); break; case APR_DBD_TYPE_DOUBLE: *(double*)data = atof(row->row[n]); break; case APR_DBD_TYPE_STRING: case APR_DBD_TYPE_TEXT: case APR_DBD_TYPE_TIME: case APR_DBD_TYPE_DATE: case APR_DBD_TYPE_DATETIME: case APR_DBD_TYPE_TIMESTAMP: case APR_DBD_TYPE_ZTIMESTAMP: *(char**)data = row->row[n]; break; case APR_DBD_TYPE_BLOB: case APR_DBD_TYPE_CLOB: { apr_bucket *e; apr_bucket_brigade *b = (apr_bucket_brigade*)data; e = apr_bucket_pool_create(row->row[n], row->len[n], row->res->pool, b->bucket_alloc); APR_BRIGADE_INSERT_TAIL(b, e); } break; case APR_DBD_TYPE_NULL: *(void**)data = NULL; break; default: return APR_EGENERAL; } } return 0; }
static int statement_fetch_impl (lua_State * L, statement_t * statement, /* {{{ */ int named_columns) { int column_count, fetch_result_ok; MYSQL_BIND *bind = NULL; unsigned long *real_length = NULL; const char *error_message = NULL; if (!statement->stmt) { luaL_error (L, DBI_ERR_FETCH_INVALID); return 0; } if (!statement->metadata) { luaL_error (L, DBI_ERR_FETCH_NO_EXECUTE); return 0; } column_count = mysql_num_fields (statement->metadata); if (column_count > 0) { int i; MYSQL_FIELD *fields; real_length = calloc (column_count, sizeof (unsigned long)); bind = malloc (sizeof (MYSQL_BIND) * column_count); memset (bind, 0, sizeof (MYSQL_BIND) * column_count); fields = mysql_fetch_fields (statement->metadata); for (i = 0; i < column_count; i++) { unsigned int length = mysql_buffer_size (&fields[i]); if (length > sizeof (MYSQL_TIME)) { bind[i].buffer = NULL; bind[i].buffer_length = 0; } else { char *buffer = (char *) malloc (length); memset (buffer, 0, length); bind[i].buffer = buffer; bind[i].buffer_length = length; } bind[i].buffer_type = fields[i].type; bind[i].length = &real_length[i]; } if (mysql_stmt_bind_result (statement->stmt, bind)) { error_message = DBI_ERR_BINDING_RESULTS; goto cleanup; } fetch_result_ok = mysql_stmt_fetch (statement->stmt); if (fetch_result_ok == 0 || fetch_result_ok == MYSQL_DATA_TRUNCATED) { int d = 1; lua_newtable (L); for (i = 0; i < column_count; i++) { lua_push_type_t lua_push = mysql_to_lua_push (fields[i].type); const char *name = fields[i].name; if (bind[i].buffer == NULL) { char *buffer = (char *) calloc (real_length[i] + 1, sizeof (char)); bind[i].buffer = buffer; bind[i].buffer_length = real_length[i]; mysql_stmt_fetch_column (statement->stmt, &bind[i], i, 0); } if (lua_push == LUA_PUSH_NIL) { if (named_columns) { LUA_PUSH_ATTRIB_NIL (name); } else { LUA_PUSH_ARRAY_NIL (d); } } else if (lua_push == LUA_PUSH_INTEGER) { if (fields[i].type == MYSQL_TYPE_YEAR || fields[i].type == MYSQL_TYPE_SHORT) { if (named_columns) { LUA_PUSH_ATTRIB_INT (name, *(short *) (bind[i].buffer)); } else { LUA_PUSH_ARRAY_INT (d, *(short *) (bind[i].buffer)); } } else if (fields[i].type == MYSQL_TYPE_TINY) { if (named_columns) { LUA_PUSH_ATTRIB_INT (name, (int) *(char *) (bind[i].buffer)); } else { LUA_PUSH_ARRAY_INT (d, (int) *(char *) (bind[i].buffer)); } } else { if (named_columns) { LUA_PUSH_ATTRIB_INT (name, *(int *) (bind[i].buffer)); } else { LUA_PUSH_ARRAY_INT (d, *(int *) (bind[i].buffer)); } } } else if (lua_push == LUA_PUSH_NUMBER) { if (named_columns) { LUA_PUSH_ATTRIB_FLOAT (name, *(double *) (bind[i].buffer)); } else { LUA_PUSH_ARRAY_FLOAT (d, *(double *) (bind[i].buffer)); } } else if (lua_push == LUA_PUSH_STRING) { if (fields[i].type == MYSQL_TYPE_TIMESTAMP || fields[i].type == MYSQL_TYPE_DATETIME) { char str[20]; struct st_mysql_time *t = bind[i].buffer; snprintf (str, 20, "%d-%02d-%02d %02d:%02d:%02d", t->year, t->month, t->day, t->hour, t->minute, t->second); if (named_columns) { LUA_PUSH_ATTRIB_STRING (name, str); } else { LUA_PUSH_ARRAY_STRING (d, str); } } else if (fields[i].type == MYSQL_TYPE_TIME) { char str[9]; struct st_mysql_time *t = bind[i].buffer; snprintf (str, 9, "%02d:%02d:%02d", t->hour, t->minute, t->second); if (named_columns) { LUA_PUSH_ATTRIB_STRING (name, str); } else { LUA_PUSH_ARRAY_STRING (d, str); } } else if (fields[i].type == MYSQL_TYPE_DATE) { char str[20]; struct st_mysql_time *t = bind[i].buffer; snprintf (str, 11, "%d-%02d-%02d", t->year, t->month, t->day); if (named_columns) { LUA_PUSH_ATTRIB_STRING (name, str); } else { LUA_PUSH_ARRAY_STRING (d, str); } } else { if (named_columns) { LUA_PUSH_ATTRIB_STRING (name, bind[i].buffer); } else { LUA_PUSH_ARRAY_STRING (d, bind[i].buffer); } } } else if (lua_push == LUA_PUSH_BOOLEAN) { if (named_columns) { LUA_PUSH_ATTRIB_BOOL (name, *(int *) (bind[i].buffer)); } else { LUA_PUSH_ARRAY_BOOL (d, *(int *) (bind[i].buffer)); } } else { luaL_error (L, DBI_ERR_UNKNOWN_PUSH); } } } else { lua_pushnil (L); } } cleanup: free (real_length); if (bind) { int i; for (i = 0; i < column_count; i++) { free (bind[i].buffer); } free (bind); } if (error_message) { luaL_error (L, error_message, mysql_stmt_error (statement->stmt)); return 0; } return 1; } /* }}} */
bool MySqlResultReader::Next() { if (finished) { return false; } int status = mysql_stmt_fetch(stmt); if (status == 1 || status == MYSQL_NO_DATA) { finished = true; return false; } /*if (status == MYSQL_DATA_TRUNCATED) { throw std::exception("data truncated"); }*/ currentResult.Clear(); unsigned int fieldCount = resultMetadata->field_count; for (int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex) { MYSQL_BIND& f = fieldBuffers[fieldIndex]; std::string fieldName = fieldsMetadata[fieldIndex].name; bool isVariableLength = (f.buffer_length == 0 && f.length_value > 0); bool isConstantLength = (f.buffer != NULL && f.buffer_length > 0); //HACK: quick win bool isNullValue = !isVariableLength && !isConstantLength; if (f.is_null_value || isNullValue) { currentResult.Add(fieldName, FieldValue::CreateNull()); } else if (isVariableLength) { //if the field being fetched has variable length data let's use the variable length buffer f.buffer = varLengthBufs[fieldIndex].Acquire(f.length_value); f.buffer_length = f.length_value; if (mysql_stmt_fetch_column(stmt, &fieldBuffers[fieldIndex], fieldIndex, 0)) { throw std::exception("mysql_stmt_fetch_column failed"); } if (f.is_null_value) { currentResult.Add(fieldName, FieldValue::CreateNull()); } else { currentResult.Add(fieldName, FieldValue::Create(f.buffer, f.buffer_length)); } //for this field to be considered as a variable length field by mysql when it will read the next row f.buffer = NULL; f.buffer_length = 0; } else if (isConstantLength) { currentResult.Add(fieldName, FieldValue::Create(f.buffer, f.buffer_length)); } else { std::string msg = "cannot read value of the column "; msg.append(fieldName); throw std::exception(msg.c_str()); } } return true; }
/// Fetches the next row. int SqlStmt_NextRow(SqlStmt* self) { int err; size_t i; size_t cols; MYSQL_BIND* column; unsigned long length; if( self == NULL ) return SQL_ERROR; // bind columns if( self->bind_columns && mysql_stmt_bind_result(self->stmt, self->columns) ) err = 1;// error binding columns else err = mysql_stmt_fetch(self->stmt);// fetch row // check for errors if( err == MYSQL_NO_DATA ) return SQL_NO_DATA; #if defined(MYSQL_DATA_TRUNCATED) // MySQL 5.0/5.1 defines and returns MYSQL_DATA_TRUNCATED [FlavioJS] if( err == MYSQL_DATA_TRUNCATED ) { my_bool truncated; if( !self->bind_columns ) { ShowSQL("DB error - data truncated (unknown source, columns are not bound)\n"); return SQL_ERROR; } // find truncated column cols = SqlStmt_NumColumns(self); for( i = 0; i < cols; ++i ) { column = &self->columns[i]; column->error = &truncated; mysql_stmt_fetch_column(self->stmt, column, (unsigned int)i, 0); column->error = NULL; if( truncated ) {// report truncated column SqlStmt_P_ShowDebugTruncatedColumn(self, i); return SQL_ERROR; } } ShowSQL("DB error - data truncated (unknown source)\n"); return SQL_ERROR; } #endif if( err ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } // propagate column lengths and clear unused parts of string/enum/blob buffers cols = SqlStmt_NumColumns(self); for( i = 0; i < cols; ++i ) { length = self->column_lengths[i].length; column = &self->columns[i]; #if !defined(MYSQL_DATA_TRUNCATED) // MySQL 4.1/(below?) returns success even if data is truncated, so we test truncation manually [FlavioJS] if( column->buffer_length < length ) {// report truncated column if( column->buffer_type == MYSQL_TYPE_STRING || column->buffer_type == MYSQL_TYPE_BLOB ) {// string/enum/blob column SqlStmt_P_ShowDebugTruncatedColumn(self, i); return SQL_ERROR; } // FIXME numeric types and null [FlavioJS] } #endif if( self->column_lengths[i].out_length ) *self->column_lengths[i].out_length = (uint32)length; if( column->buffer_type == MYSQL_TYPE_STRING ) {// clear unused part of the string/enum buffer (and nul-terminate) memset((char*)column->buffer + length, 0, column->buffer_length - length + 1); } else if( column->buffer_type == MYSQL_TYPE_BLOB && length < column->buffer_length ) {// clear unused part of the blob buffer memset((char*)column->buffer + length, 0, column->buffer_length - length); } } return SQL_SUCCESS; }