X-Git-Url: http://nitlanguage.org diff --git a/lib/sqlite3/native_sqlite3.nit b/lib/sqlite3/native_sqlite3.nit index 6fe0828..8e49c96 100644 --- a/lib/sqlite3/native_sqlite3.nit +++ b/lib/sqlite3/native_sqlite3.nit @@ -16,15 +16,25 @@ # limitations under the License. # Low-level Sqlite3 features -module sqlite3 is pkgconfig("sqlite3") +module native_sqlite3 is pkgconfig("sqlite3") in "C header" `{ #include `} +in "C" `{ + // Return code of the last call to the constructor of `NativeSqlite3` + static int nit_sqlite_open_error = SQLITE_OK; +`} + +redef class Sys + # Last error raised when calling `Sqlite3::open` + fun sqlite_open_error: Sqlite3Code `{ return nit_sqlite_open_error; `} +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,83 +66,82 @@ 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 + do + var err = native_to_s + if err.address_is_null then return "Unknown error" + return err.to_s + end - redef fun to_s: String import NativeString.to_s `{ + private fun native_to_s: CString `{ #if SQLITE_VERSION_NUMBER >= 3007015 - char *err = (char *)sqlite3_errstr(recv); + return (char *)sqlite3_errstr(self); #else - char *err = "sqlite3_errstr supported only by version >= 3.7.15"; + return "sqlite3_errstr is not supported in version < 3.7.15"; #endif - if (err == NULL) err = ""; - return NativeString_to_s(err); `} end # A prepared statement -extern class Statement `{sqlite3_stmt*`} +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)); - if(name == NULL){ - name = ""; - } - char * ret = (char *) name; - return NativeString_to_s(ret); + fun column_name(i: Int): CString `{ + return (char *)sqlite3_column_name(self, i); `} + # 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): CString `{ + return (char *)sqlite3_column_text(self, i); `} - fun column_type(i: Int) : Int `{ - return sqlite3_column_type(recv, i); + # Type of the entry at row `i` + fun column_type(i: Int): DataType `{ + 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 Sqlite3 `{sqlite3 *`} +extern class NativeSqlite3 `{sqlite3 *`} # Open a connection to a database in UTF-8 - new open(filename: String) import String.to_cstring `{ + new open(filename: CString) `{ sqlite3 *self = NULL; - sqlite3_open(String_to_cstring(filename), &self); + int err = sqlite3_open(filename, &self); + nit_sqlite_open_error = err; return self; `} @@ -141,31 +150,49 @@ extern class Sqlite3 `{sqlite3 *`} # To know if it has been closed or interrupted, you must check for errors with `error`. fun is_valid: Bool do return not address_is_null - 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); + fun exec(sql: CString): Sqlite3Code `{ + return sqlite3_exec(self, sql, NULL, NULL, NULL); `} # Prepare a SQL statement - fun prepare(sql: String): nullable Statement import String.to_cstring, Statement.as nullable `{ + fun prepare(sql: CString): NativeStatement `{ sqlite3_stmt *stmt; - int res = sqlite3_prepare_v2(recv, String_to_cstring(sql), -1, &stmt, 0); + int res = sqlite3_prepare_v2(self, sql, -1, &stmt, 0); if (res == SQLITE_OK) - return Statement_as_nullable(stmt); + return stmt; else - return null_Statement(); + return NULL; `} 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 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 self; `} +end