X-Git-Url: http://nitlanguage.org diff --git a/lib/sqlite3/native_sqlite3.nit b/lib/sqlite3/native_sqlite3.nit index 6fe0828..6419ea8 100644 --- a/lib/sqlite3/native_sqlite3.nit +++ b/lib/sqlite3/native_sqlite3.nit @@ -16,12 +16,17 @@ # limitations under the License. # Low-level Sqlite3 features -module sqlite3 is pkgconfig("sqlite3") +module native_sqlite3 is pkgconfig("sqlite3") 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; `} @@ -73,7 +78,7 @@ extern class Sqlite3Code `{int`} end # A prepared statement -extern class Statement `{sqlite3_stmt*`} +extern class NativeStatement `{sqlite3_stmt*`} # Evaluate the statement fun step: Sqlite3Code `{ @@ -89,6 +94,7 @@ extern class Statement `{sqlite3_stmt*`} return NativeString_to_s(ret); `} + # Number of bytes in the blob or string at row `i` fun column_bytes(i: Int) : Int `{ return sqlite3_column_bytes(recv, i); `} @@ -101,15 +107,12 @@ extern class Statement `{sqlite3_stmt*`} return sqlite3_column_int(recv, 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(recv, i); `} - fun column_type(i: Int) : Int `{ + # Type of the entry at row `i` + fun column_type(i: Int): DataType `{ return sqlite3_column_type(recv, i); `} @@ -127,15 +130,21 @@ extern class Statement `{sqlite3_stmt*`} 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: 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`. @@ -144,7 +153,16 @@ extern class Sqlite3 `{sqlite3 *`} fun destroy do close # Close this connection - fun close `{ sqlite3_close_v2(recv); `} + fun close `{ +#if SQLITE_VERSION_NUMBER >= 3007014 + sqlite3_close_v2(recv); +#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(recv); +#endif + `} # Execute a SQL statement fun exec(sql: String): Sqlite3Code import String.to_cstring `{ @@ -152,13 +170,13 @@ extern class Sqlite3 `{sqlite3 *`} `} # Prepare a SQL statement - fun prepare(sql: String): nullable Statement import String.to_cstring, Statement.as nullable `{ + 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); if (res == SQLITE_OK) - return Statement_as_nullable(stmt); + return NativeStatement_as_nullable(stmt); else - return null_Statement(); + return null_NativeStatement(); `} fun last_insert_rowid: Int `{ @@ -169,3 +187,14 @@ extern class Sqlite3 `{sqlite3 *`} return sqlite3_errcode(recv); `} 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 to_i: Int `{ return recv; `} +end