sqlite3_stmt * Connection::prepare( const string &query,
                                    const AttributeList &parameters ) {
  if( db_ == NULL )
    throw ActiveRecordException( "Database not connected", __FILE__, __LINE__ );
  sqlite3_stmt *ppStmt = 0;
  int prepare_result = sqlite3_prepare_v2( db_, query.c_str(), query.size(), &ppStmt, 0 );
  if( prepare_result != SQLITE_OK ) {
    stringstream error;
    error << "SQL error: \"" << sqlite_error( prepare_result ) << "\" ";
    error << "in \"" << query << "\"";
    bool added = false;
    for( AttributeList::const_iterator it = parameters.begin(); it != parameters.end(); ++it ) {
      error << ", ";
      if( ! added )
        error << "[";
      error << *it;
      added = true;
    }
    if( added )
      error << "]";
    log( error.str() );
    throw ActiveRecordException( error.str(), __FILE__, __LINE__ );
  }
  bind_parameters( ppStmt, parameters );
  return ppStmt;
}
Esempio n. 2
0
static int prepared_bind(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
  int result;
  unsigned int prepared_index;
  long long_prepared_index;
  int index = 0, type, size;
  sqlite3_stmt *statement;

#ifdef DEBUG
  fprintf(drv->log, "Finalizing prepared statement: %.*s\n", buffer_size, buffer);
  fflush(drv->log);
#endif

  ei_decode_version(buffer, &index, NULL);
  ei_decode_tuple_header(buffer, &index, &size);
  // assert(size == 2);
  ei_decode_long(buffer, &index, &long_prepared_index);
  prepared_index = (unsigned int) long_prepared_index;

  if (prepared_index >= drv->prepared_count) {
    return output_error(drv, SQLITE_MISUSE,
                        "Trying to bind non-existent prepared statement");
  }

  statement = drv->prepared_stmts[prepared_index];
  result =
      bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size);
  if (result == SQLITE_OK) {
    return output_ok(drv);
  } else {
    return result; // error has already been output
  }
}
Esempio n. 3
0
static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buffer, int buffer_size) {
  int result;
  int index = 0;
  int type, size;
  const char *rest;
  sqlite3_stmt *statement;
  long bin_size;
  char *command;

#ifdef DEBUG
  fprintf(drv->log, "Preexec: %.*s\n", buffer_size, buffer);
  fflush(drv->log);
#endif

  ei_decode_version(buffer, &index, NULL);
  result = ei_decode_tuple_header(buffer, &index, &size);
  if (result || (size != 2)) {
    return output_error(drv, SQLITE_MISUSE,
                        "Expected a tuple of SQL command and params");
  }

  // decode SQL statement
  ei_get_type(buffer, &index, &type, &size);
  // TODO support any iolists
  if (type != ERL_BINARY_EXT) {
    return output_error(drv, SQLITE_MISUSE,
                        "SQL should be sent as an Erlang binary");
  }

  command = driver_alloc(size * sizeof(char));
  ei_decode_binary(buffer, &index, command, &bin_size);
  // assert(bin_size == size)
  result = sqlite3_prepare_v2(drv->db, command, size, &statement, &rest);
  driver_free(command);

  if (result != SQLITE_OK) {
    return output_db_error(drv);
  } else if (statement == NULL) {
    return output_error(drv, SQLITE_MISUSE, "empty statement");
  }

  result = bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size);
  if (result == SQLITE_OK) {
    return sql_exec_statement(drv, statement);
  } else {
    return result; // error has already been output
  }
}