Skip to content

Instantly share code, notes, and snippets.

@alexeyr
Created April 5, 2011 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexeyr/903137 to your computer and use it in GitHub Desktop.
Save alexeyr/903137 to your computer and use it in GitHub Desktop.
Weirdness
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 if");
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;
}
@alexeyr
Copy link
Author

alexeyr commented Apr 5, 2011

Prints

After adding columns...
After adding rows...
End if branch 1

but doesn't print

End of sql_exec_one_statement...

How is this possible? Probably don't see something absolutely obvious...

@alexeyr
Copy link
Author

alexeyr commented Apr 5, 2011

Ok, now this version prints "End if" but doesn't print "End of sql_exec_one_statement". WTF?

@alexeyr
Copy link
Author

alexeyr commented Apr 5, 2011

Just buffered IO, nothing to see here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment