# Open a connection to the database file at `path`
init open(path: Text)
do
- init(new NativeSqlite3.open(path.to_s))
+ init(new NativeSqlite3.open(path.to_cstring))
if native_connection.is_valid then is_open = true
end
# Close this connection to the DB and all open statements
fun close
do
+ if not is_open then return
+
is_open = false
# close open statements
fun last_insert_rowid: Int do return native_connection.last_insert_rowid
end
-# A prepared Sqlite3 statement, created from `Sqlite3DB::prepare` or `Sqlite3DB::select`
+# Prepared Sqlite3 statement
+#
+# Instances of this class are created from `Sqlite3DB::prepare` and
+# its shortcuts: `create_table`, `insert`, `replace` and `select`.
+# The results should be explored with an `iterator`,
+# and each call to `iterator` resets the request.
+# If `close_with_iterator` the iterator calls `close`
+# on this request upon finishing.
class Statement
private var native_statement: NativeStatement
# Is this statement usable?
var is_open = true
+ # Should any `iterator` close this statement on `Iterator::finish`?
+ #
+ # If `true`, the default, any `StatementIterator` created by calls to
+ # `iterator` invokes `close` on this request when finished iterating.
+ # Otherwise, `close` must be called manually.
+ var close_with_iterator = true is writable
+
# Close and finalize this statement
fun close
do
+ if not is_open then return
+
is_open = false
native_statement.finalize
end
is_ok = false
end
end
+
+ redef fun finish do if statement.close_with_iterator then statement.close
end
# A data type supported by Sqlite3
interface Sqlite3Data end
redef universal Int super Sqlite3Data end
+
redef universal Float super Sqlite3Data end
-redef class String
- super Sqlite3Data
- # Return `self` between `'`s and escaping any extra `'`
+redef class String super Sqlite3Data end
+
+redef class Text
+
+ # Return `self` between `'`s, escaping `\` and `'`
#
# assert "'; DROP TABLE students".to_sql_string == "'''; DROP TABLE students'"
fun to_sql_string: String
do
- return "'{self.replace('\'', "''")}'"
+ return "'{self.replace('\\', "\\\\").replace('\'', "''")}'"
+ end
+
+ # Format the date represented by `self` into an escaped string for SQLite
+ #
+ # `self` must be composed of 1 to 3 integers separated by '-'.
+ # An incompatible format will result in an invalid date string.
+ #
+ # assert "2016-5-1".to_sql_date_string == "'2016-05-01'"
+ # assert "2016".to_sql_date_string == "'2016-01-01'"
+ fun to_sql_date_string: String
+ do
+ var parts = self.split("-")
+ for i in [parts.length .. 3[ do parts[i] = "1"
+
+ var year = parts[0].justify(4, 1.0, '0')
+ var month = parts[1].justify(2, 1.0, '0')
+ var day = parts[2].justify(2, 1.0, '0')
+ return "{year}-{month}-{day}".to_sql_string
end
end