static void free_db( value v ) { database *db = val_db(v); if( db->last != NULL ) finalize_result(val_result(db->last),0); if( sqlite3_close(db->db) != SQLITE_OK ) { // No exception : we shouldn't alloc memory in a finalizer anyway } }
/** result_next : 'result -> object? <doc>Returns the next row in the result or [null] if no more result.</doc> **/ static value result_next( value v ) { int i; result *r; val_check_kind(v,k_result); r = val_result(v); if( r->done ) return val_null; switch( sqlite3_step(r->r) ) { case SQLITE_ROW: r->first = 0; v = alloc_object(NULL); for(i=0;i<r->ncols;i++) { value f; switch( sqlite3_column_type(r->r,i) ) { case SQLITE_NULL: f = val_null; break; case SQLITE_INTEGER: if( r->bools[i] ) f = alloc_bool(sqlite3_column_int(r->r,i)); else f = alloc_int(sqlite3_column_int(r->r,i)); break; case SQLITE_FLOAT: f = alloc_float(sqlite3_column_double(r->r,i)); break; case SQLITE_TEXT: f = alloc_string((char*)sqlite3_column_text(r->r,i)); break; case SQLITE_BLOB: { int size = sqlite3_column_bytes(r->r,i); f = alloc_empty_string(size); memcpy(val_string(f),sqlite3_column_blob(r->r,i),size); break; } default: { buffer b = alloc_buffer("Unknown Sqlite type #"); val_buffer(b,alloc_int(sqlite3_column_type(r->r,i))); val_throw(buffer_to_string(b)); } } alloc_field(v,r->names[i],f); } return v; case SQLITE_DONE: finalize_result(r,1); return val_null; case SQLITE_BUSY: val_throw(alloc_string("Database is busy")); case SQLITE_ERROR: sqlite_error(r->db->db); default: neko_error(); } return val_null; }
/** request : 'db -> sql:string -> 'result <doc>Executes the SQL request and returns its result</doc> **/ static value request( value v, value sql ) { database *db; result *r; const char *tl; int i,j; val_check_kind(v,k_db); val_check(sql,string); db = val_db(v); r = (result*)alloc(sizeof(result)); r->db = db; if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error in "); val_buffer(b,sql); buffer_append(b," : "); buffer_append(b,sqlite3_errmsg(db->db)); val_throw(buffer_to_string(b)); } if( *tl ) { sqlite3_finalize(r->r); val_throw(alloc_string("Cannot execute several SQL requests at the same time")); } r->ncols = sqlite3_column_count(r->r); r->names = (field*)alloc_private(sizeof(field)*r->ncols); r->bools = (int*)alloc_private(sizeof(int)*r->ncols); r->first = 1; r->done = 0; for(i=0;i<r->ncols;i++) { field id = val_id(sqlite3_column_name(r->r,i)); const char *dtype = sqlite3_column_decltype(r->r,i); for(j=0;j<i;j++) if( r->names[j] == id ) { if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) { buffer b = alloc_buffer("Error, same field is two times in the request "); val_buffer(b,sql); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } else { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,sqlite3_column_name(r->r,i)); buffer_append(b," and "); buffer_append(b,sqlite3_column_name(r->r,j)); buffer_append_char(b,'.'); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } } r->names[i] = id; r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0; } // changes in an update/delete if( db->last != NULL ) finalize_result(val_result(db->last),0); db->last = alloc_abstract(k_result,r); return db->last; }
static dfsch_object_t* result_next(sqlite3_result_t* res){ char* err; int ret; char**values; ret = sqlite3_step(res->stmt); if (ret == SQLITE_ROW){ res->last_res = get_row_as_vector(res->stmt); return res; } else if (ret == SQLITE_BUSY) { dfsch_error("Database is busy", (dfsch_object_t*)res->db); } else if (ret == SQLITE_ERROR){ finalize_result(res); return NULL; } else { return NULL; } }
static dfsch_object_t* result_next(sqlite_result_t* res){ char* err; int ret; char**values; pthread_mutex_lock(res->mutex); ret = sqlite_step(res->vm, &res->n_columns, &values, &res->names); if (ret == SQLITE_ROW){ res->last_res = get_row_as_vector(res->n_columns, values); pthread_mutex_unlock(res->mutex); return res; } else { pthread_mutex_unlock(res->mutex); if (ret == SQLITE_BUSY) { dfsch_error("Database is busy", (dfsch_object_t*)res->db); } else if (ret == SQLITE_ERROR){ finalize_result(res); return NULL; } else { return NULL; } } }