Skip to content

Instantly share code, notes, and snippets.

@alexeyr
Created April 5, 2011 06:45
Show Gist options
  • Select an option

  • Save alexeyr/903137 to your computer and use it in GitHub Desktop.

Select an option

Save alexeyr/903137 to your computer and use it in GitHub Desktop.

Revisions

  1. alexeyr revised this gist Apr 5, 2011. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions sqlite3_drv.c
    Original file line number Diff line number Diff line change
    @@ -195,12 +195,13 @@ static void sql_exec_one_statement(
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 1] = drv->atom_ok;
    }
    printf("\nEnd if");

    printf("\nEnd of sql_exec_one_statement: term_count=%d, term_allocated=%d", *term_count_p, *term_allocated_p);
    printf("\nEnd of sql_exec_one_statement");

    #ifdef DEBUG
    fprintf(drv->log, "Total term count: %p %d, rows count: %dx%d\n", statement, *term_count_p, column_count, row_count);
    fflush(drv->log);
    #endif
    async_command->finalize_statement_on_free = 1;
    }
    }
  2. alexeyr created this gist Apr 5, 2011.
    206 changes: 206 additions & 0 deletions sqlite3_drv.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,206 @@
    static void sql_exec_one_statement(
    sqlite3_stmt *statement, async_sqlite3_command *async_command,
    int *term_count_p, int *term_allocated_p, ErlDrvTermData **dataset_p) {
    int column_count = sqlite3_column_count(statement);
    int row_count = 0, next_row;
    int base_term_count;
    sqlite3_drv_t *drv = async_command->driver_data;
    ptr_list **ptrs_p = &(async_command->ptrs);
    ptr_list **binaries_p = &(async_command->binaries);

    // printf("\nStart of sql_exec_one_statement: term_count=%d, term_allocated=%d", *term_count_p, *term_allocated_p);
    int i;

    if (column_count > 0) {
    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 1] = drv->atom_columns;
    base_term_count = *term_count_p;
    get_columns(
    drv, statement, column_count, base_term_count, term_count_p, term_allocated_p, dataset_p);
    *term_count_p += 4;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[base_term_count + column_count * 3 + 3] = ERL_DRV_TUPLE;
    (*dataset_p)[base_term_count + column_count * 3 + 4] = 2;

    (*dataset_p)[base_term_count + column_count * 3 + 5] = ERL_DRV_ATOM;
    (*dataset_p)[base_term_count + column_count * 3 + 6] = drv->atom_rows;
    // printf("\nAfter adding columns: column_count=%d, term_count=%d, term_allocated=%d", column_count, *term_count_p, *term_allocated_p);
    }

    #ifdef DEBUG
    fprintf(drv->log, "Exec: %s\n", sqlite3_sql(statement));
    fflush(drv->log);
    #endif

    while ((next_row = sqlite3_step(statement)) == SQLITE_ROW) {
    for (i = 0; i < column_count; i++) {
    #ifdef DEBUG
    fprintf(drv->log, "Column %d type: %d\n", i, sqlite3_column_type(statement, i));
    fflush(drv->log);
    #endif
    switch (sqlite3_column_type(statement, i)) {
    case SQLITE_INTEGER: {
    ErlDrvSInt64 *int64_ptr = driver_alloc(sizeof(ErlDrvSInt64));
    *int64_ptr = (ErlDrvSInt64) sqlite3_column_int64(statement, i);
    *ptrs_p = add_to_ptr_list(*ptrs_p, int64_ptr);

    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_INT64;
    (*dataset_p)[*term_count_p - 1] = (ErlDrvTermData) int64_ptr;
    break;
    }
    case SQLITE_FLOAT: {
    double *float_ptr = driver_alloc(sizeof(double));
    *float_ptr = sqlite3_column_double(statement, i);
    *ptrs_p = add_to_ptr_list(*ptrs_p, float_ptr);

    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_FLOAT;
    (*dataset_p)[*term_count_p - 1] = (ErlDrvTermData) float_ptr;
    break;
    }
    case SQLITE_BLOB: {
    int bytes = sqlite3_column_bytes(statement, i);
    ErlDrvBinary* binary = driver_alloc_binary(bytes);
    binary->orig_size = bytes;
    memcpy(binary->orig_bytes,
    sqlite3_column_blob(statement, i), bytes);
    *binaries_p = add_to_ptr_list(*binaries_p, binary);

    *term_count_p += 8;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 8] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 7] = drv->atom_blob;
    (*dataset_p)[*term_count_p - 6] = ERL_DRV_BINARY;
    (*dataset_p)[*term_count_p - 5] = (ErlDrvTermData) binary;
    (*dataset_p)[*term_count_p - 4] = bytes;
    (*dataset_p)[*term_count_p - 3] = 0;
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_TUPLE;
    (*dataset_p)[*term_count_p - 1] = 2;
    break;
    }
    case SQLITE_TEXT: {
    int bytes = sqlite3_column_bytes(statement, i);
    ErlDrvBinary* binary = driver_alloc_binary(bytes);
    binary->orig_size = bytes;
    memcpy(binary->orig_bytes,
    sqlite3_column_blob(statement, i), bytes);
    *binaries_p = add_to_ptr_list(*binaries_p, binary);

    *term_count_p += 4;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 4] = ERL_DRV_BINARY;
    (*dataset_p)[*term_count_p - 3] = (ErlDrvTermData) binary;
    (*dataset_p)[*term_count_p - 2] = bytes;
    (*dataset_p)[*term_count_p - 1] = 0;
    break;
    }
    case SQLITE_NULL: {
    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 1] = drv->atom_null;
    break;
    }
    }
    }
    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_TUPLE;
    (*dataset_p)[*term_count_p - 1] = column_count;

    row_count++;
    }

    if (next_row == SQLITE_BUSY) {
    return_error(drv, SQLITE_BUSY, "SQLite3 database is busy",
    &async_command->dataset, &async_command->term_count,
    &async_command->error_code);
    return;
    }
    if (next_row != SQLITE_DONE) {
    return_error(drv, next_row, sqlite3_errmsg(drv->db),
    &async_command->dataset, &async_command->term_count,
    &async_command->error_code);
    return;
    }

    printf("\nAfter adding rows: column_count=%d, term_count=%d, term_allocated=%d", column_count, *term_count_p, *term_allocated_p);
    if (column_count > 0) {
    *term_count_p += 3+2+3;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 8] = ERL_DRV_NIL;
    (*dataset_p)[*term_count_p - 7] = ERL_DRV_LIST;
    (*dataset_p)[*term_count_p - 6] = row_count + 1;

    (*dataset_p)[*term_count_p - 5] = ERL_DRV_TUPLE;
    (*dataset_p)[*term_count_p - 4] = 2;

    (*dataset_p)[*term_count_p - 3] = ERL_DRV_NIL;
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_LIST;
    (*dataset_p)[*term_count_p - 1] = 3;
    printf("\nEnd if branch 1");
    } else if (sql_is_insert(sqlite3_sql(statement))) {
    ErlDrvSInt64 *rowid_ptr = driver_alloc(sizeof(ErlDrvSInt64));
    *rowid_ptr = (ErlDrvSInt64) sqlite3_last_insert_rowid(drv->db);
    *ptrs_p = add_to_ptr_list(*ptrs_p, rowid_ptr);
    *term_count_p += 6;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 6] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 5] = drv->atom_rowid;
    (*dataset_p)[*term_count_p - 4] = ERL_DRV_INT64;
    (*dataset_p)[*term_count_p - 3] = (ErlDrvTermData) rowid_ptr;
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_TUPLE;
    (*dataset_p)[*term_count_p - 1] = 2;
    } else {
    *term_count_p += 2;
    if (*term_count_p > *term_allocated_p) {
    *term_allocated_p = max(*term_count_p, *term_allocated_p*2);
    *dataset_p = driver_realloc(*dataset_p, sizeof(ErlDrvTermData) * *term_allocated_p);
    }
    (*dataset_p)[*term_count_p - 2] = ERL_DRV_ATOM;
    (*dataset_p)[*term_count_p - 1] = drv->atom_ok;
    }

    printf("\nEnd of sql_exec_one_statement: term_count=%d, term_allocated=%d", *term_count_p, *term_allocated_p);

    #ifdef DEBUG
    fprintf(drv->log, "Total term count: %p %d, rows count: %dx%d\n", statement, *term_count_p, column_count, row_count);
    fflush(drv->log);
    #endif
    async_command->finalize_statement_on_free = 1;
    }