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;
};
示例#2
0
    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);
    }
示例#3
0
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");
		}
	}
}
示例#4
0
/* 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;
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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);
}
示例#9
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()");
      }
    }
示例#11
0
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;
}
示例#12
0
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;
}
示例#13
0
	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);
			}

		}

	}
示例#14
0
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;
        }
}
示例#15
0
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);
}
示例#16
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;
}
示例#17
0
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);
        }
    }
}
示例#19
0
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;
};
示例#21
0
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;
}
示例#22
0
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;
}
示例#23
0
/*
 * 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);
}
示例#24
0
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();
	}
}
示例#25
0
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, &timestamp);
			}
			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;
		}
示例#26
0
文件: mysql.c 项目: Hmaal/slash
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;
}
示例#27
0
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;
}
示例#28
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;
} /* }}} */
示例#29
0
    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;
    }
示例#30
0
文件: sql.c 项目: icxbb-xx/Hercules-1
/// 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;
}