X-Git-Url: http://nitlanguage.org diff --git a/lib/sqlite3/native_sqlite3.nit b/lib/sqlite3/native_sqlite3.nit index f200b23..dd45211 100644 --- a/lib/sqlite3/native_sqlite3.nit +++ b/lib/sqlite3/native_sqlite3.nit @@ -22,9 +22,14 @@ in "C header" `{ #include `} +redef class Sys + # Last error raised when calling `Sqlite3::open` + var sqlite_open_error: nullable Sqlite3Code = null +end + extern class Sqlite3Code `{int`} new ok `{ return SQLITE_OK; `} # 0 /* Successful result */ - fun is_ok: Bool `{ return recv == SQLITE_OK; `} + fun is_ok: Bool `{ return self == SQLITE_OK; `} # new `{ return SQLITE_ERROR; `} # 1 /* SQL error or missing database */ # new `{ return SQLITE_INTERNAL; `} # 2 /* Internal logic error in SQLite */ @@ -56,14 +61,14 @@ extern class Sqlite3Code `{int`} # new `{ return SQLITE_WARNING; `} # 28 /* Warnings from sqlite3_log() */ new row `{ return SQLITE_ROW; `} # 100 /* sqlite3_step() has another row ready */ - fun is_row: Bool `{ return recv == SQLITE_ROW; `} + fun is_row: Bool `{ return self == SQLITE_ROW; `} new done `{ return SQLITE_DONE; `} # 101 /* sqlite3_step() has finished executing */ - fun is_done: Bool `{ return recv == SQLITE_DONE; `} + fun is_done: Bool `{ return self == SQLITE_DONE; `} - redef fun to_s: String import NativeString.to_s `{ + redef fun to_s import NativeString.to_s `{ #if SQLITE_VERSION_NUMBER >= 3007015 - char *err = (char *)sqlite3_errstr(recv); + char *err = (char *)sqlite3_errstr(self); #else char *err = "sqlite3_errstr supported only by version >= 3.7.15"; #endif @@ -77,11 +82,11 @@ extern class NativeStatement `{sqlite3_stmt*`} # Evaluate the statement fun step: Sqlite3Code `{ - return sqlite3_step(recv); + return sqlite3_step(self); `} fun column_name(i: Int) : String import NativeString.to_s `{ - const char * name = (sqlite3_column_name(recv, i)); + const char * name = (sqlite3_column_name(self, i)); if(name == NULL){ name = ""; } @@ -91,53 +96,55 @@ extern class NativeStatement `{sqlite3_stmt*`} # Number of bytes in the blob or string at row `i` fun column_bytes(i: Int) : Int `{ - return sqlite3_column_bytes(recv, i); + return sqlite3_column_bytes(self, i); `} fun column_double(i: Int) : Float `{ - return sqlite3_column_double(recv, i); + return sqlite3_column_double(self, i); `} fun column_int(i: Int) : Int `{ - return sqlite3_column_int(recv, i); + return sqlite3_column_int(self, i); `} - fun column_text(i: Int) : String import NativeString.to_s `{ - char * ret = (char *) sqlite3_column_text(recv, i); - if( ret == NULL ){ - ret = ""; - } - return NativeString_to_s(ret); + fun column_text(i: Int): NativeString `{ + return (char *)sqlite3_column_text(self, i); `} # Type of the entry at row `i` fun column_type(i: Int): DataType `{ - return sqlite3_column_type(recv, i); + return sqlite3_column_type(self, i); `} - fun column_blob(i: Int): Pointer `{ return (void*)sqlite3_column_blob(recv, i); `} + fun column_blob(i: Int): Pointer `{ return (void*)sqlite3_column_blob(self, i); `} fun column_count: Int `{ - return sqlite3_column_count(recv); + return sqlite3_column_count(self); `} # Reset this statement to its original state, to be reexecuted - fun reset: Sqlite3Code `{ return sqlite3_reset(recv); `} + fun reset: Sqlite3Code `{ return sqlite3_reset(self); `} # Delete this statement - fun finalize: Sqlite3Code `{ return sqlite3_finalize(recv); `} + fun finalize: Sqlite3Code `{ return sqlite3_finalize(self); `} end # A database connection extern class NativeSqlite3 `{sqlite3 *`} # Open a connection to a database in UTF-8 - new open(filename: String) import String.to_cstring `{ + new open(filename: String) import String.to_cstring, set_sys_sqlite_open_error `{ sqlite3 *self = NULL; - sqlite3_open(String_to_cstring(filename), &self); + int err = sqlite3_open(String_to_cstring(filename), &self); + NativeSqlite3_set_sys_sqlite_open_error(self, (void*)(long)err); + // The previous cast is a hack, using non pointers in extern classes is not + // yet in the spec of the FFI. return self; `} + # Utility method to set `Sys.sqlite_open_error` + private fun set_sys_sqlite_open_error(err: Sqlite3Code) do sys.sqlite_open_error = err + # Has this DB been correctly opened? # # To know if it has been closed or interrupted, you must check for errors with `error`. @@ -146,17 +153,26 @@ extern class NativeSqlite3 `{sqlite3 *`} fun destroy do close # Close this connection - fun close `{ sqlite3_close_v2(recv); `} + fun close `{ +#if SQLITE_VERSION_NUMBER >= 3007014 + sqlite3_close_v2(self); +#else + // A program using the older version should not rely on the garbage-collector + // to close its connections. They must be closed manually after the associated + // prepare statements have been finalized. + sqlite3_close(self); +#endif + `} # Execute a SQL statement fun exec(sql: String): Sqlite3Code import String.to_cstring `{ - return sqlite3_exec(recv, String_to_cstring(sql), 0, 0, 0); + return sqlite3_exec(self, String_to_cstring(sql), 0, 0, 0); `} # Prepare a SQL statement fun prepare(sql: String): nullable NativeStatement import String.to_cstring, NativeStatement.as nullable `{ sqlite3_stmt *stmt; - int res = sqlite3_prepare_v2(recv, String_to_cstring(sql), -1, &stmt, 0); + int res = sqlite3_prepare_v2(self, String_to_cstring(sql), -1, &stmt, 0); if (res == SQLITE_OK) return NativeStatement_as_nullable(stmt); else @@ -164,21 +180,21 @@ extern class NativeSqlite3 `{sqlite3 *`} `} fun last_insert_rowid: Int `{ - return sqlite3_last_insert_rowid(recv); + return sqlite3_last_insert_rowid(self); `} fun error: Sqlite3Code `{ - return sqlite3_errcode(recv); + return sqlite3_errcode(self); `} end # Sqlite data types extern class DataType `{ int `} - fun is_integer: Bool `{ return recv == SQLITE_INTEGER; `} - fun is_float: Bool `{ return recv == SQLITE_FLOAT; `} - fun is_blob: Bool `{ return recv == SQLITE_BLOB; `} - fun is_null: Bool `{ return recv == SQLITE_NULL; `} - fun is_text: Bool `{ return recv == SQLITE_TEXT; `} + fun is_integer: Bool `{ return self == SQLITE_INTEGER; `} + fun is_float: Bool `{ return self == SQLITE_FLOAT; `} + fun is_blob: Bool `{ return self == SQLITE_BLOB; `} + fun is_null: Bool `{ return self == SQLITE_NULL; `} + fun is_text: Bool `{ return self == SQLITE_TEXT; `} - fun to_i: Int `{ return recv; `} + fun to_i: Int `{ return self; `} end