mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 16:35:01 +00:00
Revert "[samples/ffi] Generate sqlite3 bindings with package:ffigen"
This reverts commit af4940fc57
as it broke
flutter engine license script, engine autoroller - it introduced dart
file with unrecognizable license.
Bug: https://bugs.chromium.org/p/skia/issues/detail?id=10598
Change-Id: I351931808316638d9bbc1b18aaf5a2525f04ee6b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158108
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
parent
490a4b65e2
commit
38ec554d6b
2
samples/ffi/sqlite/.gitignore
vendored
2
samples/ffi/sqlite/.gitignore
vendored
|
@ -4,4 +4,4 @@
|
|||
.vscode
|
||||
pubspec.lock
|
||||
test.db
|
||||
test.db-journal
|
||||
test.db-journal
|
394
samples/ffi/sqlite/lib/src/bindings/bindings.dart
Normal file
394
samples/ffi/sqlite/lib/src/bindings/bindings.dart
Normal file
|
@ -0,0 +1,394 @@
|
|||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:ffi";
|
||||
import "package:ffi/ffi.dart";
|
||||
|
||||
import "../ffi/dylib_utils.dart";
|
||||
|
||||
import "signatures.dart";
|
||||
import "types.dart";
|
||||
|
||||
class _SQLiteBindings {
|
||||
DynamicLibrary sqlite;
|
||||
|
||||
/// Opening A New Database Connection
|
||||
///
|
||||
/// ^These routines open an SQLite database file as specified by the
|
||||
/// filename argument. ^The filename argument is interpreted as UTF-8 for
|
||||
/// sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
|
||||
/// order for sqlite3_open16(). ^(A database connection handle is usually
|
||||
/// returned in *ppDb, even if an error occurs. The only exception is that
|
||||
/// if SQLite is unable to allocate memory to hold the sqlite3 object,
|
||||
/// a NULL will be written into *ppDb instead of a pointer to the sqlite3
|
||||
/// object.)^ ^(If the database is opened (and/or created) successfully, then
|
||||
/// [SQLITE_OK] is returned. Otherwise an error code is returned.)^ ^The
|
||||
/// [sqlite3_errmsg] or sqlite3_errmsg16() routines can be used to obtain
|
||||
/// an English language description of the error following a failure of any
|
||||
/// of the sqlite3_open() routines.
|
||||
int Function(Pointer<Utf8> filename, Pointer<Pointer<Database>> databaseOut,
|
||||
int flags, Pointer<Utf8> vfs) sqlite3_open_v2;
|
||||
|
||||
int Function(Pointer<Database> database) sqlite3_close_v2;
|
||||
|
||||
/// Compiling An SQL Statement
|
||||
///
|
||||
/// To execute an SQL query, it must first be compiled into a byte-code
|
||||
/// program using one of these routines.
|
||||
///
|
||||
/// The first argument, "db", is a database connection obtained from a
|
||||
/// prior successful call to sqlite3_open, [sqlite3_open_v2] or
|
||||
/// sqlite3_open16. The database connection must not have been closed.
|
||||
///
|
||||
/// The second argument, "zSql", is the statement to be compiled, encoded
|
||||
/// as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
|
||||
/// interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
|
||||
/// use UTF-16.
|
||||
///
|
||||
/// ^If the nByte argument is less than zero, then zSql is read up to the
|
||||
/// first zero terminator. ^If nByte is non-negative, then it is the maximum
|
||||
/// number of bytes read from zSql. ^When nByte is non-negative, the
|
||||
/// zSql string ends at either the first '\000' or '\u0000' character or
|
||||
/// the nByte-th byte, whichever comes first. If the caller knows
|
||||
/// that the supplied string is nul-terminated, then there is a small
|
||||
/// performance advantage to be gained by passing an nByte parameter that
|
||||
/// is equal to the number of bytes in the input string <i>including</i>
|
||||
/// the nul-terminator bytes.
|
||||
///
|
||||
/// ^If pzTail is not NULL then *pzTail is made to point to the first byte
|
||||
/// past the end of the first SQL statement in zSql. These routines only
|
||||
/// compile the first statement in zSql, so *pzTail is left pointing to
|
||||
/// what remains uncompiled.
|
||||
///
|
||||
/// ^*ppStmt is left pointing to a compiled prepared statement that can be
|
||||
/// executed using sqlite3_step. ^If there is an error, *ppStmt is set
|
||||
/// to NULL. ^If the input text contains no SQL (if the input is an empty
|
||||
/// string or a comment) then *ppStmt is set to NULL.
|
||||
/// The calling procedure is responsible for deleting the compiled
|
||||
/// SQL statement using [sqlite3_finalize] after it has finished with it.
|
||||
/// ppStmt may not be NULL.
|
||||
///
|
||||
/// ^On success, the sqlite3_prepare family of routines return [SQLITE_OK];
|
||||
/// otherwise an error code is returned.
|
||||
///
|
||||
/// The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
|
||||
/// recommended for all new programs. The two older interfaces are retained
|
||||
/// for backwards compatibility, but their use is discouraged.
|
||||
/// ^In the "v2" interfaces, the prepared statement
|
||||
/// that is returned (the sqlite3_stmt object) contains a copy of the
|
||||
/// original SQL text. This causes the [sqlite3_step] interface to
|
||||
/// behave differently in three ways:
|
||||
int Function(
|
||||
Pointer<Database> database,
|
||||
Pointer<Utf8> query,
|
||||
int nbytes,
|
||||
Pointer<Pointer<Statement>> statementOut,
|
||||
Pointer<Pointer<Utf8>> tail) sqlite3_prepare_v2;
|
||||
|
||||
/// Evaluate An SQL Statement
|
||||
///
|
||||
/// After a prepared statement has been prepared using either
|
||||
/// [sqlite3_prepare_v2] or sqlite3_prepare16_v2() or one of the legacy
|
||||
/// interfaces sqlite3_prepare() or sqlite3_prepare16(), this function
|
||||
/// must be called one or more times to evaluate the statement.
|
||||
///
|
||||
/// The details of the behavior of the sqlite3_step() interface depend
|
||||
/// on whether the statement was prepared using the newer "v2" interface
|
||||
/// [sqlite3_prepare_v2] and sqlite3_prepare16_v2() or the older legacy
|
||||
/// interface sqlite3_prepare() and sqlite3_prepare16(). The use of the
|
||||
/// new "v2" interface is recommended for new applications but the legacy
|
||||
/// interface will continue to be supported.
|
||||
///
|
||||
/// ^In the legacy interface, the return value will be either [SQLITE_BUSY],
|
||||
/// [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
|
||||
/// ^With the "v2" interface, any of the other [result codes] or
|
||||
/// [extended result codes] might be returned as well.
|
||||
///
|
||||
/// ^[SQLITE_BUSY] means that the database engine was unable to acquire the
|
||||
/// database locks it needs to do its job. ^If the statement is a [COMMIT]
|
||||
/// or occurs outside of an explicit transaction, then you can retry the
|
||||
/// statement. If the statement is not a [COMMIT] and occurs within an
|
||||
/// explicit transaction then you should rollback the transaction before
|
||||
/// continuing.
|
||||
///
|
||||
/// ^[SQLITE_DONE] means that the statement has finished executing
|
||||
/// successfully. sqlite3_step() should not be called again on this virtual
|
||||
/// machine without first calling [sqlite3_reset()] to reset the virtual
|
||||
/// machine back to its initial state.
|
||||
///
|
||||
/// ^If the SQL statement being executed returns any data, then [SQLITE_ROW]
|
||||
/// is returned each time a new row of data is ready for processing by the
|
||||
/// caller. The values may be accessed using the [column access functions].
|
||||
/// sqlite3_step() is called again to retrieve the next row of data.
|
||||
///
|
||||
/// ^[SQLITE_ERROR] means that a run-time error (such as a constraint
|
||||
/// violation) has occurred. sqlite3_step() should not be called again on
|
||||
/// the VM. More information may be found by calling [sqlite3_errmsg()].
|
||||
/// ^With the legacy interface, a more specific error code (for example,
|
||||
/// [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
|
||||
/// can be obtained by calling [sqlite3_reset()] on the
|
||||
/// prepared statement. ^In the "v2" interface,
|
||||
/// the more specific error code is returned directly by sqlite3_step().
|
||||
///
|
||||
/// [SQLITE_MISUSE] means that the this routine was called inappropriately.
|
||||
/// Perhaps it was called on a prepared statement that has
|
||||
/// already been [sqlite3_finalize | finalized] or on one that had
|
||||
/// previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
|
||||
/// be the case that the same database connection is being used by two or
|
||||
/// more threads at the same moment in time.
|
||||
///
|
||||
/// For all versions of SQLite up to and including 3.6.23.1, a call to
|
||||
/// [sqlite3_reset] was required after sqlite3_step() returned anything
|
||||
/// other than [Errors.SQLITE_ROW] before any subsequent invocation of
|
||||
/// sqlite3_step(). Failure to reset the prepared statement using
|
||||
/// [sqlite3_reset()] would result in an [Errors.SQLITE_MISUSE] return from
|
||||
/// sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
|
||||
/// calling [sqlite3_reset] automatically in this circumstance rather
|
||||
/// than returning [Errors.SQLITE_MISUSE]. This is not considered a
|
||||
/// compatibility break because any application that ever receives an
|
||||
/// [Errors.SQLITE_MISUSE] error is broken by definition. The
|
||||
/// [SQLITE_OMIT_AUTORESET] compile-time option
|
||||
/// can be used to restore the legacy behavior.
|
||||
///
|
||||
/// <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
|
||||
/// API always returns a generic error code, [SQLITE_ERROR], following any
|
||||
/// error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
|
||||
/// [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the
|
||||
/// specific [error codes] that better describes the error.
|
||||
/// We admit that this is a goofy design. The problem has been fixed
|
||||
/// with the "v2" interface. If you prepare all of your SQL statements
|
||||
/// using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
|
||||
/// of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
|
||||
/// then the more specific [error codes] are returned directly
|
||||
/// by sqlite3_step(). The use of the "v2" interface is recommended.
|
||||
int Function(Pointer<Statement> statement) sqlite3_step;
|
||||
|
||||
/// CAPI3REF: Reset A Prepared Statement Object
|
||||
///
|
||||
/// The sqlite3_reset() function is called to reset a prepared statement
|
||||
/// object back to its initial state, ready to be re-executed.
|
||||
/// ^Any SQL statement variables that had values bound to them using
|
||||
/// the sqlite3_bind_blob | sqlite3_bind_*() API retain their values.
|
||||
/// Use sqlite3_clear_bindings() to reset the bindings.
|
||||
///
|
||||
/// ^The [sqlite3_reset] interface resets the prepared statement S
|
||||
/// back to the beginning of its program.
|
||||
///
|
||||
/// ^If the most recent call to [sqlite3_step] for the
|
||||
/// prepared statement S returned [Errors.SQLITE_ROW] or [Errors.SQLITE_DONE],
|
||||
/// or if [sqlite3_step] has never before been called on S,
|
||||
/// then [sqlite3_reset] returns [Errors.SQLITE_OK].
|
||||
///
|
||||
/// ^If the most recent call to [sqlite3_step(S)] for the
|
||||
/// prepared statement S indicated an error, then
|
||||
/// [sqlite3_reset] returns an appropriate [Errors].
|
||||
///
|
||||
/// ^The [sqlite3_reset] interface does not change the values
|
||||
int Function(Pointer<Statement> statement) sqlite3_reset;
|
||||
|
||||
/// Destroy A Prepared Statement Object
|
||||
///
|
||||
/// ^The sqlite3_finalize() function is called to delete a prepared statement.
|
||||
/// ^If the most recent evaluation of the statement encountered no errors
|
||||
/// or if the statement is never been evaluated, then sqlite3_finalize()
|
||||
/// returns SQLITE_OK. ^If the most recent evaluation of statement S failed,
|
||||
/// then sqlite3_finalize(S) returns the appropriate error code or extended
|
||||
/// error code.
|
||||
///
|
||||
/// ^The sqlite3_finalize(S) routine can be called at any point during
|
||||
/// the life cycle of prepared statement S:
|
||||
/// before statement S is ever evaluated, after
|
||||
/// one or more calls to [sqlite3_reset], or after any call
|
||||
/// to [sqlite3_step] regardless of whether or not the statement has
|
||||
/// completed execution.
|
||||
///
|
||||
/// ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
|
||||
///
|
||||
/// The application must finalize every prepared statement in order to avoid
|
||||
/// resource leaks. It is a grievous error for the application to try to use
|
||||
/// a prepared statement after it has been finalized. Any use of a prepared
|
||||
/// statement after it has been finalized can result in undefined and
|
||||
/// undesirable behavior such as segfaults and heap corruption.
|
||||
int Function(Pointer<Statement> statement) sqlite3_finalize;
|
||||
|
||||
/// Number Of Columns In A Result Set
|
||||
///
|
||||
/// ^Return the number of columns in the result set returned by the
|
||||
/// prepared statement. ^This routine returns 0 if pStmt is an SQL
|
||||
/// statement that does not return data (for example an [UPDATE]).
|
||||
int Function(Pointer<Statement> statement) sqlite3_column_count;
|
||||
|
||||
/// Column Names In A Result Set
|
||||
///
|
||||
/// ^These routines return the name assigned to a particular column
|
||||
/// in the result set of a SELECT statement. ^The sqlite3_column_name()
|
||||
/// interface returns a pointer to a zero-terminated UTF-8 string
|
||||
/// and sqlite3_column_name16() returns a pointer to a zero-terminated
|
||||
/// UTF-16 string. ^The first parameter is the prepared statement
|
||||
/// that implements the SELECT statement. ^The second parameter is the
|
||||
/// column number. ^The leftmost column is number 0.
|
||||
///
|
||||
/// ^The returned string pointer is valid until either the prepared statement
|
||||
/// is destroyed by [sqlite3_finalize] or until the statement is automatically
|
||||
/// reprepared by the first call to [sqlite3_step] for a particular run
|
||||
/// or until the next call to
|
||||
/// sqlite3_column_name() or sqlite3_column_name16() on the same column.
|
||||
///
|
||||
/// ^If sqlite3_malloc() fails during the processing of either routine
|
||||
/// (for example during a conversion from UTF-8 to UTF-16) then a
|
||||
/// NULL pointer is returned.
|
||||
///
|
||||
/// ^The name of a result column is the value of the "AS" clause for
|
||||
/// that column, if there is an AS clause. If there is no AS clause
|
||||
/// then the name of the column is unspecified and may change from
|
||||
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_name;
|
||||
|
||||
/// CAPI3REF: Declared Datatype Of A Query Result
|
||||
///
|
||||
/// ^(The first parameter is a prepared statement.
|
||||
/// If this statement is a SELECT statement and the Nth column of the
|
||||
/// returned result set of that SELECT is a table column (not an
|
||||
/// expression or subquery) then the declared type of the table
|
||||
/// column is returned.)^ ^If the Nth column of the result set is an
|
||||
/// expression or subquery, then a NULL pointer is returned.
|
||||
/// ^The returned string is always UTF-8 encoded.
|
||||
///
|
||||
/// ^(For example, given the database schema:
|
||||
///
|
||||
/// CREATE TABLE t1(c1 VARIANT);
|
||||
///
|
||||
/// and the following statement to be compiled:
|
||||
///
|
||||
/// SELECT c1 + 1, c1 FROM t1;
|
||||
///
|
||||
/// this routine would return the string "VARIANT" for the second result
|
||||
/// column (i==1), and a NULL pointer for the first result column (i==0).)^
|
||||
///
|
||||
/// ^SQLite uses dynamic run-time typing. ^So just because a column
|
||||
/// is declared to contain a particular type does not mean that the
|
||||
/// data stored in that column is of the declared type. SQLite is
|
||||
/// strongly typed, but the typing is dynamic not static. ^Type
|
||||
/// is associated with individual values, not with the containers
|
||||
/// used to hold those values.
|
||||
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_decltype;
|
||||
|
||||
int Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_type;
|
||||
|
||||
Pointer<Value> Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_value;
|
||||
|
||||
double Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_double;
|
||||
|
||||
int Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_int;
|
||||
|
||||
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
|
||||
sqlite3_column_text;
|
||||
|
||||
/// The sqlite3_errstr() interface returns the English-language text that
|
||||
/// describes the result code, as UTF-8. Memory to hold the error message
|
||||
/// string is managed internally and must not be freed by the application.
|
||||
Pointer<Utf8> Function(int code) sqlite3_errstr;
|
||||
|
||||
/// Error Codes And Messages
|
||||
///
|
||||
/// ^The sqlite3_errcode() interface returns the numeric [result code] or
|
||||
/// [extended result code] for the most recent failed sqlite3_* API call
|
||||
/// associated with a [database connection]. If a prior API call failed
|
||||
/// but the most recent API call succeeded, the return value from
|
||||
/// sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
|
||||
/// interface is the same except that it always returns the
|
||||
/// [extended result code] even when extended result codes are
|
||||
/// disabled.
|
||||
///
|
||||
/// ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
/// text that describes the error, as either UTF-8 or UTF-16 respectively.
|
||||
/// ^(Memory to hold the error message string is managed internally.
|
||||
/// The application does not need to worry about freeing the result.
|
||||
/// However, the error string might be overwritten or deallocated by
|
||||
/// subsequent calls to other SQLite interface functions.)^
|
||||
///
|
||||
/// When the serialized [threading mode] is in use, it might be the
|
||||
/// case that a second error occurs on a separate thread in between
|
||||
/// the time of the first error and the call to these interfaces.
|
||||
/// When that happens, the second error will be reported since these
|
||||
/// interfaces always report the most recent result. To avoid
|
||||
/// this, each thread can obtain exclusive use of the [database connection] D
|
||||
/// by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
|
||||
/// to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
|
||||
/// all calls to the interfaces listed here are completed.
|
||||
///
|
||||
/// If an interface fails with SQLITE_MISUSE, that means the interface
|
||||
/// was invoked incorrectly by the application. In that case, the
|
||||
/// error code and message may or may not be set.
|
||||
Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg;
|
||||
|
||||
_SQLiteBindings() {
|
||||
sqlite = dlopenPlatformSpecific("sqlite3");
|
||||
sqlite3_open_v2 = sqlite
|
||||
.lookup<NativeFunction<sqlite3_open_v2_native_t>>("sqlite3_open_v2")
|
||||
.asFunction();
|
||||
sqlite3_close_v2 = sqlite
|
||||
.lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2")
|
||||
.asFunction();
|
||||
sqlite3_prepare_v2 = sqlite
|
||||
.lookup<NativeFunction<sqlite3_prepare_v2_native_t>>(
|
||||
"sqlite3_prepare_v2")
|
||||
.asFunction();
|
||||
sqlite3_step = sqlite
|
||||
.lookup<NativeFunction<sqlite3_step_native_t>>("sqlite3_step")
|
||||
.asFunction();
|
||||
sqlite3_reset = sqlite
|
||||
.lookup<NativeFunction<sqlite3_reset_native_t>>("sqlite3_reset")
|
||||
.asFunction();
|
||||
sqlite3_finalize = sqlite
|
||||
.lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize")
|
||||
.asFunction();
|
||||
sqlite3_errstr = sqlite
|
||||
.lookup<NativeFunction<sqlite3_errstr_native_t>>("sqlite3_errstr")
|
||||
.asFunction();
|
||||
sqlite3_errmsg = sqlite
|
||||
.lookup<NativeFunction<sqlite3_errmsg_native_t>>("sqlite3_errmsg")
|
||||
.asFunction();
|
||||
sqlite3_column_count = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_count_native_t>>(
|
||||
"sqlite3_column_count")
|
||||
.asFunction();
|
||||
sqlite3_column_name = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_name_native_t>>(
|
||||
"sqlite3_column_name")
|
||||
.asFunction();
|
||||
sqlite3_column_decltype = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_decltype_native_t>>(
|
||||
"sqlite3_column_decltype")
|
||||
.asFunction();
|
||||
sqlite3_column_type = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_type_native_t>>(
|
||||
"sqlite3_column_type")
|
||||
.asFunction();
|
||||
sqlite3_column_value = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_value_native_t>>(
|
||||
"sqlite3_column_value")
|
||||
.asFunction();
|
||||
sqlite3_column_double = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_double_native_t>>(
|
||||
"sqlite3_column_double")
|
||||
.asFunction();
|
||||
sqlite3_column_int = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_int_native_t>>(
|
||||
"sqlite3_column_int")
|
||||
.asFunction();
|
||||
sqlite3_column_text = sqlite
|
||||
.lookup<NativeFunction<sqlite3_column_text_native_t>>(
|
||||
"sqlite3_column_text")
|
||||
.asFunction();
|
||||
}
|
||||
}
|
||||
|
||||
_SQLiteBindings _cachedBindings;
|
||||
_SQLiteBindings get bindings => _cachedBindings ??= _SQLiteBindings();
|
182
samples/ffi/sqlite/lib/src/bindings/constants.dart
Normal file
182
samples/ffi/sqlite/lib/src/bindings/constants.dart
Normal file
|
@ -0,0 +1,182 @@
|
|||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// Result Codes
|
||||
///
|
||||
/// Many SQLite functions return an integer result code from the set shown
|
||||
/// here in order to indicates success or failure.
|
||||
///
|
||||
/// New error codes may be added in future versions of SQLite.
|
||||
///
|
||||
/// See also: SQLITE_IOERR_READ | extended result codes,
|
||||
/// sqlite3_vtab_on_conflict() SQLITE_ROLLBACK | result codes.
|
||||
class Errors {
|
||||
/// Successful result
|
||||
static const int SQLITE_OK = 0;
|
||||
|
||||
/// Generic error
|
||||
static const int SQLITE_ERROR = 1;
|
||||
|
||||
/// Internal logic error in SQLite
|
||||
static const int SQLITE_INTERNAL = 2;
|
||||
|
||||
/// Access permission denied
|
||||
static const int SQLITE_PERM = 3;
|
||||
|
||||
/// Callback routine requested an abort
|
||||
static const int SQLITE_ABORT = 4;
|
||||
|
||||
/// The database file is locked
|
||||
static const int SQLITE_BUSY = 5;
|
||||
|
||||
/// A table in the database is locked
|
||||
static const int SQLITE_LOCKED = 6;
|
||||
|
||||
/// A malloc() failed
|
||||
static const int SQLITE_NOMEM = 7;
|
||||
|
||||
/// Attempt to write a readonly database
|
||||
static const int SQLITE_READONLY = 8;
|
||||
|
||||
/// Operation terminated by sqlite3_interrupt()
|
||||
static const int SQLITE_INTERRUPT = 9;
|
||||
|
||||
/// Some kind of disk I/O error occurred
|
||||
static const int SQLITE_IOERR = 10;
|
||||
|
||||
/// The database disk image is malformed
|
||||
static const int SQLITE_CORRUPT = 11;
|
||||
|
||||
/// Unknown opcode in sqlite3_file_control()
|
||||
static const int SQLITE_NOTFOUND = 12;
|
||||
|
||||
/// Insertion failed because database is full
|
||||
static const int SQLITE_FULL = 13;
|
||||
|
||||
/// Unable to open the database file
|
||||
static const int SQLITE_CANTOPEN = 14;
|
||||
|
||||
/// Database lock protocol error
|
||||
static const int SQLITE_PROTOCOL = 15;
|
||||
|
||||
/// Internal use only
|
||||
static const int SQLITE_EMPTY = 16;
|
||||
|
||||
/// The database schema changed
|
||||
static const int SQLITE_SCHEMA = 17;
|
||||
|
||||
/// String or BLOB exceeds size limit
|
||||
static const int SQLITE_TOOBIG = 18;
|
||||
|
||||
/// Abort due to constraint violation
|
||||
static const int SQLITE_CONSTRAINT = 19;
|
||||
|
||||
/// Data type mismatch
|
||||
static const int SQLITE_MISMATCH = 20;
|
||||
|
||||
/// Library used incorrectly
|
||||
static const int SQLITE_MISUSE = 21;
|
||||
|
||||
/// Uses OS features not supported on host
|
||||
static const int SQLITE_NOLFS = 22;
|
||||
|
||||
/// Authorization denied
|
||||
static const int SQLITE_AUTH = 23;
|
||||
|
||||
/// Not used
|
||||
static const int SQLITE_FORMAT = 24;
|
||||
|
||||
/// 2nd parameter to sqlite3_bind out of range
|
||||
static const int SQLITE_RANGE = 25;
|
||||
|
||||
/// File opened that is not a database file
|
||||
static const int SQLITE_NOTADB = 26;
|
||||
|
||||
/// Notifications from sqlite3_log()
|
||||
static const int SQLITE_NOTICE = 27;
|
||||
|
||||
/// Warnings from sqlite3_log()
|
||||
static const int SQLITE_WARNING = 28;
|
||||
|
||||
/// sqlite3_step() has another row ready
|
||||
static const int SQLITE_ROW = 100;
|
||||
|
||||
/// sqlite3_step() has finished executing
|
||||
static const int SQLITE_DONE = 101;
|
||||
}
|
||||
|
||||
/// Flags For File Open Operations
|
||||
///
|
||||
/// These bit values are intended for use in the
|
||||
/// 3rd parameter to the [sqlite3_open_v2()] interface and
|
||||
/// in the 4th parameter to the [sqlite3_vfs.xOpen] method.
|
||||
class Flags {
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_READONLY = 0x00000001;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_READWRITE = 0x00000002;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_CREATE = 0x00000004;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_DELETEONCLOSE = 0x00000008;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_EXCLUSIVE = 0x00000010;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_AUTOPROXY = 0x00000020;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_URI = 0x00000040;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_MEMORY = 0x00000080;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_MAIN_DB = 0x00000100;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_TEMP_DB = 0x00000200;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_TRANSIENT_DB = 0x00000400;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_MAIN_JOURNAL = 0x00000800;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_TEMP_JOURNAL = 0x00001000;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_SUBJOURNAL = 0x00002000;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_MASTER_JOURNAL = 0x00004000;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_NOMUTEX = 0x00008000;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_FULLMUTEX = 0x00010000;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_SHAREDCACHE = 0x00020000;
|
||||
|
||||
/// Ok for sqlite3_open_v2()
|
||||
static const int SQLITE_OPEN_PRIVATECACHE = 0x00040000;
|
||||
|
||||
/// VFS only
|
||||
static const int SQLITE_OPEN_WAL = 0x00080000;
|
||||
}
|
||||
|
||||
class Types {
|
||||
static const int SQLITE_INTEGER = 1;
|
||||
static const int SQLITE_FLOAT = 2;
|
||||
static const int SQLITE_TEXT = 3;
|
||||
static const int SQLITE_BLOB = 4;
|
||||
static const int SQLITE_NULL = 5;
|
||||
}
|
57
samples/ffi/sqlite/lib/src/bindings/signatures.dart
Normal file
57
samples/ffi/sqlite/lib/src/bindings/signatures.dart
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:ffi";
|
||||
|
||||
import "package:ffi/ffi.dart";
|
||||
|
||||
import "types.dart";
|
||||
|
||||
typedef sqlite3_open_v2_native_t = Int32 Function(Pointer<Utf8> filename,
|
||||
Pointer<Pointer<Database>> ppDb, Int32 flags, Pointer<Utf8> vfs);
|
||||
|
||||
typedef sqlite3_close_v2_native_t = Int32 Function(Pointer<Database> database);
|
||||
|
||||
typedef sqlite3_prepare_v2_native_t = Int32 Function(
|
||||
Pointer<Database> database,
|
||||
Pointer<Utf8> query,
|
||||
Int32 nbytes,
|
||||
Pointer<Pointer<Statement>> statementOut,
|
||||
Pointer<Pointer<Utf8>> tail);
|
||||
|
||||
typedef sqlite3_step_native_t = Int32 Function(Pointer<Statement> statement);
|
||||
|
||||
typedef sqlite3_reset_native_t = Int32 Function(Pointer<Statement> statement);
|
||||
|
||||
typedef sqlite3_finalize_native_t = Int32 Function(
|
||||
Pointer<Statement> statement);
|
||||
|
||||
typedef sqlite3_errstr_native_t = Pointer<Utf8> Function(Int32 error);
|
||||
|
||||
typedef sqlite3_errmsg_native_t = Pointer<Utf8> Function(
|
||||
Pointer<Database> database);
|
||||
|
||||
typedef sqlite3_column_count_native_t = Int32 Function(
|
||||
Pointer<Statement> statement);
|
||||
|
||||
typedef sqlite3_column_name_native_t = Pointer<Utf8> Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_decltype_native_t = Pointer<Utf8> Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_type_native_t = Int32 Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_value_native_t = Pointer<Value> Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_double_native_t = Double Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_int_native_t = Int32 Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
||||
|
||||
typedef sqlite3_column_text_native_t = Pointer<Utf8> Function(
|
||||
Pointer<Statement> statement, Int32 columnIndex);
|
75
samples/ffi/sqlite/lib/src/bindings/types.dart
Normal file
75
samples/ffi/sqlite/lib/src/bindings/types.dart
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:ffi";
|
||||
|
||||
/// Database Connection Handle
|
||||
///
|
||||
/// Each open SQLite database is represented by a pointer to an instance of
|
||||
/// the opaque structure named "sqlite3". It is useful to think of an sqlite3
|
||||
/// pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
|
||||
/// [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
|
||||
/// is its destructor. There are many other interfaces (such as
|
||||
/// [sqlite3_prepare_v2()], [sqlite3_create_function()], and
|
||||
/// [sqlite3_busy_timeout()] to name but three) that are methods on an
|
||||
class Database extends Struct {}
|
||||
|
||||
/// SQL Statement Object
|
||||
///
|
||||
/// An instance of this object represents a single SQL statement.
|
||||
/// This object is variously known as a "prepared statement" or a
|
||||
/// "compiled SQL statement" or simply as a "statement".
|
||||
///
|
||||
/// The life of a statement object goes something like this:
|
||||
///
|
||||
/// <ol>
|
||||
/// <li> Create the object using [sqlite3_prepare_v2()] or a related
|
||||
/// function.
|
||||
/// <li> Bind values to [host parameters] using the sqlite3_bind_*()
|
||||
/// interfaces.
|
||||
/// <li> Run the SQL by calling [sqlite3_step()] one or more times.
|
||||
/// <li> Reset the statement using [sqlite3_reset()] then go back
|
||||
/// to step 2. Do this zero or more times.
|
||||
/// <li> Destroy the object using [sqlite3_finalize()].
|
||||
/// </ol>
|
||||
///
|
||||
/// Refer to documentation on individual methods above for additional
|
||||
/// information.
|
||||
class Statement extends Struct {}
|
||||
|
||||
/// Dynamically Typed Value Object
|
||||
///
|
||||
/// SQLite uses the sqlite3_value object to represent all values
|
||||
/// that can be stored in a database table. SQLite uses dynamic typing
|
||||
/// for the values it stores. ^Values stored in sqlite3_value objects
|
||||
/// can be integers, floating point values, strings, BLOBs, or NULL.
|
||||
///
|
||||
/// An sqlite3_value object may be either "protected" or "unprotected".
|
||||
/// Some interfaces require a protected sqlite3_value. Other interfaces
|
||||
/// will accept either a protected or an unprotected sqlite3_value.
|
||||
/// Every interface that accepts sqlite3_value arguments specifies
|
||||
/// whether or not it requires a protected sqlite3_value.
|
||||
///
|
||||
/// The terms "protected" and "unprotected" refer to whether or not
|
||||
/// a mutex is held. An internal mutex is held for a protected
|
||||
/// sqlite3_value object but no mutex is held for an unprotected
|
||||
/// sqlite3_value object. If SQLite is compiled to be single-threaded
|
||||
/// (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
|
||||
/// or if SQLite is run in one of reduced mutex modes
|
||||
/// [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
|
||||
/// then there is no distinction between protected and unprotected
|
||||
/// sqlite3_value objects and they can be used interchangeably. However,
|
||||
/// for maximum code portability it is recommended that applications
|
||||
/// still make the distinction between protected and unprotected
|
||||
/// sqlite3_value objects even when not strictly required.
|
||||
///
|
||||
/// ^The sqlite3_value objects that are passed as parameters into the
|
||||
/// implementation of [application-defined SQL functions] are protected.
|
||||
/// ^The sqlite3_value object returned by
|
||||
/// [sqlite3_column_value()] is unprotected.
|
||||
/// Unprotected sqlite3_value objects may only be used with
|
||||
/// [sqlite3_result_value()] and [sqlite3_bind_value()].
|
||||
/// The [sqlite3_value_blob | sqlite3_value_type()] family of
|
||||
/// interfaces require protected sqlite3_value objects.
|
||||
class Value extends Struct {}
|
|
@ -7,11 +7,13 @@ import "dart:ffi";
|
|||
|
||||
import "package:ffi/ffi.dart";
|
||||
|
||||
import "third_party/sqlite/sqlite3_bindings_generated.dart" as bindings;
|
||||
import "collections/closable_iterator.dart";
|
||||
import "ffi/dylib_utils.dart";
|
||||
import "bindings/bindings.dart";
|
||||
|
||||
final sqlite = bindings.SQLite(dlopenPlatformSpecific("sqlite3"));
|
||||
import "bindings/types.dart" as types;
|
||||
import "bindings/types.dart" hide Database;
|
||||
|
||||
import "bindings/constants.dart";
|
||||
import "collections/closable_iterator.dart";
|
||||
|
||||
/// [Database] represents an open connection to a SQLite database.
|
||||
///
|
||||
|
@ -19,27 +21,26 @@ final sqlite = bindings.SQLite(dlopenPlatformSpecific("sqlite3"));
|
|||
///
|
||||
/// This database interacts with SQLite synchonously.
|
||||
class Database {
|
||||
Pointer<bindings.sqlite3> _database;
|
||||
Pointer<types.Database> _database;
|
||||
bool _open = false;
|
||||
|
||||
/// Open a database located at the file [path].
|
||||
Database(String path,
|
||||
[int flags =
|
||||
bindings.SQLITE_OPEN_READWRITE | bindings.SQLITE_OPEN_CREATE]) {
|
||||
Pointer<Pointer<bindings.sqlite3>> dbOut = allocate();
|
||||
final pathC = Utf8.toUtf8(path).cast<Int8>();
|
||||
final int resultCode = sqlite.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
|
||||
[int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
|
||||
Pointer<Pointer<types.Database>> dbOut = allocate();
|
||||
final pathC = Utf8.toUtf8(path);
|
||||
final int resultCode =
|
||||
bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
|
||||
_database = dbOut.value;
|
||||
free(dbOut);
|
||||
free(pathC);
|
||||
|
||||
if (resultCode == bindings.SQLITE_OK) {
|
||||
if (resultCode == Errors.SQLITE_OK) {
|
||||
_open = true;
|
||||
} else {
|
||||
// Even if "open" fails, sqlite3 will still create a database object. We
|
||||
// can just destroy it.
|
||||
SQLiteException exception = _loadError(resultCode);
|
||||
_open = true;
|
||||
close();
|
||||
throw exception;
|
||||
}
|
||||
|
@ -52,8 +53,8 @@ class Database {
|
|||
/// avoid resource leaks.
|
||||
void close() {
|
||||
assert(_open);
|
||||
final int resultCode = sqlite.sqlite3_close_v2(_database);
|
||||
if (resultCode == bindings.SQLITE_OK) {
|
||||
final int resultCode = bindings.sqlite3_close_v2(_database);
|
||||
if (resultCode == Errors.SQLITE_OK) {
|
||||
_open = false;
|
||||
} else {
|
||||
throw _loadError(resultCode);
|
||||
|
@ -62,44 +63,43 @@ class Database {
|
|||
|
||||
/// Execute a query, discarding any returned rows.
|
||||
void execute(String query) {
|
||||
Pointer<Pointer<bindings.sqlite3_stmt>> statementOut = allocate();
|
||||
final queryC = Utf8.toUtf8(query).cast<Int8>();
|
||||
int resultCode =
|
||||
sqlite.sqlite3_prepare_v2(_database, queryC, -1, statementOut, nullptr);
|
||||
Pointer<bindings.sqlite3_stmt> statement = statementOut.value;
|
||||
Pointer<Pointer<Statement>> statementOut = allocate();
|
||||
Pointer<Utf8> queryC = Utf8.toUtf8(query);
|
||||
int resultCode = bindings.sqlite3_prepare_v2(
|
||||
_database, queryC, -1, statementOut, nullptr);
|
||||
Pointer<Statement> statement = statementOut.value;
|
||||
free(statementOut);
|
||||
free(queryC);
|
||||
|
||||
while (
|
||||
resultCode == bindings.SQLITE_ROW || resultCode == bindings.SQLITE_OK) {
|
||||
resultCode = sqlite.sqlite3_step(statement);
|
||||
while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
|
||||
resultCode = bindings.sqlite3_step(statement);
|
||||
}
|
||||
sqlite.sqlite3_finalize(statement);
|
||||
if (resultCode != bindings.SQLITE_DONE) {
|
||||
bindings.sqlite3_finalize(statement);
|
||||
if (resultCode != Errors.SQLITE_DONE) {
|
||||
throw _loadError(resultCode);
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a query and return the resulting rows as an iterable.
|
||||
Result query(String query) {
|
||||
Pointer<Pointer<bindings.sqlite3_stmt>> statementOut = allocate();
|
||||
final queryC = Utf8.toUtf8(query).cast<Int8>();
|
||||
int resultCode =
|
||||
sqlite.sqlite3_prepare_v2(_database, queryC, -1, statementOut, nullptr);
|
||||
Pointer<bindings.sqlite3_stmt> statement = statementOut.value;
|
||||
Pointer<Pointer<Statement>> statementOut = allocate();
|
||||
Pointer<Utf8> queryC = Utf8.toUtf8(query);
|
||||
int resultCode = bindings.sqlite3_prepare_v2(
|
||||
_database, queryC, -1, statementOut, nullptr);
|
||||
Pointer<Statement> statement = statementOut.value;
|
||||
free(statementOut);
|
||||
free(queryC);
|
||||
|
||||
if (resultCode != bindings.SQLITE_OK) {
|
||||
sqlite.sqlite3_finalize(statement);
|
||||
if (resultCode != Errors.SQLITE_OK) {
|
||||
bindings.sqlite3_finalize(statement);
|
||||
throw _loadError(resultCode);
|
||||
}
|
||||
|
||||
Map<String, int> columnIndices = {};
|
||||
int columnCount = sqlite.sqlite3_column_count(statement);
|
||||
int columnCount = bindings.sqlite3_column_count(statement);
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
String columnName =
|
||||
sqlite.sqlite3_column_name(statement, i).cast<Utf8>().ref.toString();
|
||||
bindings.sqlite3_column_name(statement, i).ref.toString();
|
||||
columnIndices[columnName] = i;
|
||||
}
|
||||
|
||||
|
@ -107,13 +107,12 @@ class Database {
|
|||
}
|
||||
|
||||
SQLiteException _loadError([int errorCode]) {
|
||||
String errorMessage =
|
||||
sqlite.sqlite3_errmsg(_database).cast<Utf8>().ref.toString();
|
||||
String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
|
||||
if (errorCode == null) {
|
||||
return SQLiteException(errorMessage);
|
||||
}
|
||||
String errorCodeExplanation =
|
||||
sqlite.sqlite3_errstr(errorCode).cast<Utf8>().ref.toString();
|
||||
bindings.sqlite3_errstr(errorCode).ref.toString();
|
||||
return SQLiteException(
|
||||
"$errorMessage (Code $errorCode: $errorCodeExplanation)");
|
||||
}
|
||||
|
@ -127,7 +126,7 @@ class Database {
|
|||
class Result extends IterableBase<Row> implements ClosableIterable<Row> {
|
||||
final Database _database;
|
||||
final ClosableIterator<Row> _iterator;
|
||||
final Pointer<bindings.sqlite3_stmt> _statement;
|
||||
final Pointer<Statement> _statement;
|
||||
final Map<String, int> _columnIndices;
|
||||
|
||||
Row _currentRow = null;
|
||||
|
@ -144,7 +143,7 @@ class Result extends IterableBase<Row> implements ClosableIterable<Row> {
|
|||
}
|
||||
|
||||
class _ResultIterator implements ClosableIterator<Row> {
|
||||
final Pointer<bindings.sqlite3_stmt> _statement;
|
||||
final Pointer<Statement> _statement;
|
||||
final Map<String, int> _columnIndices;
|
||||
|
||||
Row _currentRow = null;
|
||||
|
@ -157,8 +156,8 @@ class _ResultIterator implements ClosableIterator<Row> {
|
|||
throw SQLiteException("The result has already been closed.");
|
||||
}
|
||||
_currentRow?._setNotCurrent();
|
||||
int stepResult = sqlite.sqlite3_step(_statement);
|
||||
if (stepResult == bindings.SQLITE_ROW) {
|
||||
int stepResult = bindings.sqlite3_step(_statement);
|
||||
if (stepResult == Errors.SQLITE_ROW) {
|
||||
_currentRow = Row._(_statement, _columnIndices);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -177,12 +176,12 @@ class _ResultIterator implements ClosableIterator<Row> {
|
|||
void close() {
|
||||
_currentRow?._setNotCurrent();
|
||||
_closed = true;
|
||||
sqlite.sqlite3_finalize(_statement);
|
||||
bindings.sqlite3_finalize(_statement);
|
||||
}
|
||||
}
|
||||
|
||||
class Row {
|
||||
final Pointer<bindings.sqlite3_stmt> _statement;
|
||||
final Pointer<Statement> _statement;
|
||||
final Map<String, int> _columnIndices;
|
||||
|
||||
bool _isCurrentRow = true;
|
||||
|
@ -211,11 +210,10 @@ class Row {
|
|||
Type dynamicType;
|
||||
if (convert == Convert.DynamicType) {
|
||||
dynamicType =
|
||||
_typeFromCode(sqlite.sqlite3_column_type(_statement, columnIndex));
|
||||
_typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex));
|
||||
} else {
|
||||
dynamicType = _typeFromText(sqlite
|
||||
dynamicType = _typeFromText(bindings
|
||||
.sqlite3_column_decltype(_statement, columnIndex)
|
||||
.cast<Utf8>()
|
||||
.ref
|
||||
.toString());
|
||||
}
|
||||
|
@ -242,7 +240,7 @@ class Row {
|
|||
/// integer.
|
||||
int readColumnByIndexAsInt(int columnIndex) {
|
||||
_checkIsCurrentRow();
|
||||
return sqlite.sqlite3_column_int(_statement, columnIndex);
|
||||
return bindings.sqlite3_column_int(_statement, columnIndex);
|
||||
}
|
||||
|
||||
/// Reads column [columnName] and converts to [Type.Text] if not text.
|
||||
|
@ -253,11 +251,7 @@ class Row {
|
|||
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
|
||||
String readColumnByIndexAsText(int columnIndex) {
|
||||
_checkIsCurrentRow();
|
||||
return sqlite
|
||||
.sqlite3_column_text(_statement, columnIndex)
|
||||
.cast<Utf8>()
|
||||
.ref
|
||||
.toString();
|
||||
return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString();
|
||||
}
|
||||
|
||||
void _checkIsCurrentRow() {
|
||||
|
@ -275,15 +269,15 @@ class Row {
|
|||
|
||||
Type _typeFromCode(int code) {
|
||||
switch (code) {
|
||||
case bindings.SQLITE_INTEGER:
|
||||
case Types.SQLITE_INTEGER:
|
||||
return Type.Integer;
|
||||
case bindings.SQLITE_FLOAT:
|
||||
case Types.SQLITE_FLOAT:
|
||||
return Type.Float;
|
||||
case bindings.SQLITE_TEXT:
|
||||
case Types.SQLITE_TEXT:
|
||||
return Type.Text;
|
||||
case bindings.SQLITE_BLOB:
|
||||
case Types.SQLITE_BLOB:
|
||||
return Type.Blob;
|
||||
case bindings.SQLITE_NULL:
|
||||
case Types.SQLITE_NULL:
|
||||
return Type.Null;
|
||||
}
|
||||
throw Exception("Unknown type [$code]");
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,55 +1,11 @@
|
|||
name: sqlite3
|
||||
|
||||
version: 0.0.1
|
||||
|
||||
description: >-
|
||||
Sqlite3 wrapper. Demo for dart:ffi.
|
||||
|
||||
author: Daco Harkes <dacoharkes@google.com>, Samir Jindel <sjindel@google.com>
|
||||
|
||||
environment:
|
||||
sdk: '>=2.1.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
ffi: ^0.1.3
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.5.3
|
||||
ffigen: ^0.2.0
|
||||
|
||||
ffigen:
|
||||
name: SQLite
|
||||
description: SQLite bindings.
|
||||
output: 'lib/src/third_party/sqlite/sqlite3_bindings_generated.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- '/usr/include/sqlite3.h'
|
||||
include-directives:
|
||||
- '**sqlite3.h'
|
||||
functions:
|
||||
include:
|
||||
- sqlite3_close_v2
|
||||
- sqlite3_column_count
|
||||
- sqlite3_column_decltype
|
||||
- sqlite3_column_int
|
||||
- sqlite3_column_name
|
||||
- sqlite3_column_text
|
||||
- sqlite3_column_type
|
||||
- sqlite3_errmsg
|
||||
- sqlite3_errstr
|
||||
- sqlite3_finalize
|
||||
- sqlite3_open_v2
|
||||
- sqlite3_prepare_v2
|
||||
- sqlite3_step
|
||||
comments:
|
||||
style: any
|
||||
length: full
|
||||
preamble: |
|
||||
// 2001 September 15
|
||||
//
|
||||
// The author disclaims copyright to this source code. In place of
|
||||
// a legal notice, here is a blessing:
|
||||
//
|
||||
// May you do good and not evil.
|
||||
// May you find forgiveness for yourself and forgive others.
|
||||
// May you share freely, never taking more than you give.
|
||||
|
|
|
@ -13,7 +13,6 @@ import "package:test/test.dart";
|
|||
import '../lib/sqlite.dart';
|
||||
|
||||
void main() {
|
||||
assert(Platform.script.hasAbsolutePath); // `pub run test` is broken.
|
||||
final dbPath = Platform.script.resolve("test.db").path;
|
||||
test("sqlite integration test", () {
|
||||
Database d = Database(dbPath);
|
||||
|
@ -167,7 +166,6 @@ void main() {
|
|||
r.close();
|
||||
d.close();
|
||||
});
|
||||
|
||||
test("Utf8 unit test", () {
|
||||
final String test = 'Hasta Mañana';
|
||||
final medium = Utf8.toUtf8(test);
|
||||
|
|
1
third_party/.gitignore
vendored
1
third_party/.gitignore
vendored
|
@ -13,6 +13,5 @@
|
|||
!unittest.tar.gz.sha1
|
||||
!update.sh
|
||||
!/wasmer
|
||||
!/sqlite
|
||||
# but ignore a subfolder of tcmalloc (some client ignores /tcmalloc/.gitignore)
|
||||
/tcmalloc/gperftools
|
||||
|
|
9
third_party/sqlite/LICENSE.md
vendored
9
third_party/sqlite/LICENSE.md
vendored
|
@ -1,9 +0,0 @@
|
|||
The author disclaims copyright to this source code. In place of
|
||||
a legal notice, here is a blessing:
|
||||
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
|
||||
Files generated from sqlite source files are in
|
||||
samples/ffi/sqlite/lib/src/third_party/sqlite.
|
Loading…
Reference in a new issue