aboutsummaryrefslogtreecommitdiff
path: root/qlite
diff options
context:
space:
mode:
Diffstat (limited to 'qlite')
-rw-r--r--qlite/src/column.vala28
-rw-r--r--qlite/src/database.vala6
-rw-r--r--qlite/src/delete_builder.vala31
-rw-r--r--qlite/src/insert_builder.vala30
-rw-r--r--qlite/src/query_builder.vala70
-rw-r--r--qlite/src/row.vala33
-rw-r--r--qlite/src/statement_builder.vala31
-rw-r--r--qlite/src/table.vala20
-rw-r--r--qlite/src/update_builder.vala63
9 files changed, 131 insertions, 181 deletions
diff --git a/qlite/src/column.vala b/qlite/src/column.vala
index 048446fb..9c201885 100644
--- a/qlite/src/column.vala
+++ b/qlite/src/column.vala
@@ -4,12 +4,12 @@ namespace Qlite {
public abstract class Column<T> {
public string name { get; private set; }
- public string default { get; set; }
+ public string? default { get; set; }
public int sqlite_type { get; private set; }
public bool primary_key { get; set; }
public bool auto_increment { get; set; }
public bool unique { get; set; }
- public bool not_null { get; set; }
+ public virtual bool not_null { get; set; }
public long min_version { get; set; default = -1; }
public long max_version { get; set; default = long.MAX; }
@@ -43,7 +43,7 @@ public abstract class Column<T> {
}
if (not_null) res += " NOT NULL";
if (unique) res += " UNIQUE";
- if (default != null) res += @" DEFAULT $default";
+ if (default != null) res += @" DEFAULT $((!) default)";
return res;
}
@@ -122,13 +122,33 @@ public abstract class Column<T> {
internal override void bind(Statement stmt, int index, string? value) {
if (value != null) {
- stmt.bind_text(index, value);
+ stmt.bind_text(index, (!) value);
} else {
stmt.bind_null(index);
}
}
}
+ public class NonNullText : Column<string> {
+ public NonNullText(string name) {
+ base(name, TEXT);
+ }
+
+ public override bool not_null { get { return true; } set {} }
+
+ public override string get(Row row) {
+ return (!)row.get_text(name);
+ }
+
+ public override bool is_null(Row row) {
+ return false;
+ }
+
+ internal override void bind(Statement stmt, int index, string value) {
+ stmt.bind_text(index, (!) value);
+ }
+ }
+
public class BoolText : Column<bool> {
public BoolText(string name) {
base(name, TEXT);
diff --git a/qlite/src/database.vala b/qlite/src/database.vala
index 89eda204..0427df16 100644
--- a/qlite/src/database.vala
+++ b/qlite/src/database.vala
@@ -17,11 +17,11 @@ public class Database {
private string file_name;
private Sqlite.Database db;
private long expected_version;
- private Table[] tables;
+ private Table[]? tables;
- private Column<string> meta_name = new Column.Text("name") { primary_key = true };
+ private Column<string?> meta_name = new Column.Text("name") { primary_key = true };
private Column<long> meta_int_val = new Column.Long("int_val");
- private Column<string> meta_text_val = new Column.Text("text_val");
+ private Column<string?> meta_text_val = new Column.Text("text_val");
private Table meta_table;
public bool debug = false;
diff --git a/qlite/src/delete_builder.vala b/qlite/src/delete_builder.vala
index 8e4afb06..5483b652 100644
--- a/qlite/src/delete_builder.vala
+++ b/qlite/src/delete_builder.vala
@@ -5,12 +5,12 @@ namespace Qlite {
public class DeleteBuilder : StatementBuilder {
// DELETE FROM [...]
- private Table table;
+ private Table? table;
private string table_name;
// WHERE [...]
- private string selection;
- private StatementBuilder.Field[] selection_args;
+ private string selection = "1";
+ private StatementBuilder.AbstractField[] selection_args = {};
internal DeleteBuilder(Database db) {
base(db);
@@ -29,35 +29,22 @@ public class DeleteBuilder : StatementBuilder {
}
public DeleteBuilder where(string selection, string[]? selection_args = null) throws DatabaseError {
- if (this.selection != null) throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
+ if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
this.selection = selection;
- if (selection_args != null) {
- this.selection_args = new StatementBuilder.Field[selection_args.length];
- for (int i = 0; i < selection_args.length; i++) {
- this.selection_args[i] = new StatementBuilder.StringField(selection_args[i]);
- }
+ foreach (string arg in selection_args) {
+ this.selection_args += new StatementBuilder.StringField(arg);
}
return this;
}
public DeleteBuilder with<T>(Column<T> column, string comp, T value) {
- if (selection == null) {
- selection = @"$(column.name) $comp ?";
- selection_args = { new StatementBuilder.Field<T>(column, value) };
- } else {
- selection = @"($selection) AND $(column.name) $comp ?";
- StatementBuilder.Field[] selection_args_new = new StatementBuilder.Field[selection_args.length+1];
- for (int i = 0; i < selection_args.length; i++) {
- selection_args_new[i] = selection_args[i];
- }
- selection_args_new[selection_args.length] = new Field<T>(column, value);
- selection_args = selection_args_new;
- }
+ selection_args += new Field<T>(column, value);
+ selection = @"($selection) AND $(column.name) $comp ?";
return this;
}
internal override Statement prepare() throws DatabaseError {
- Statement stmt = db.prepare(@"DELETE FROM $table_name $(selection != null ? @"WHERE $selection": "")");
+ Statement stmt = db.prepare(@"DELETE FROM $table_name WHERE $selection");
for (int i = 0; i < selection_args.length; i++) {
selection_args[i].bind(stmt, i+1);
}
diff --git a/qlite/src/insert_builder.vala b/qlite/src/insert_builder.vala
index 51030294..91388f69 100644
--- a/qlite/src/insert_builder.vala
+++ b/qlite/src/insert_builder.vala
@@ -6,14 +6,14 @@ public class InsertBuilder : StatementBuilder {
// INSERT [OR ...]
private bool replace_val;
- private string or_val;
+ private string? or_val;
// INTO [...]
private Table table;
private string table_name;
// VALUES [...]
- private StatementBuilder.Field[] fields;
+ private StatementBuilder.AbstractField[] fields = {};
internal InsertBuilder(Database db) {
base(db);
@@ -41,31 +41,13 @@ public class InsertBuilder : StatementBuilder {
}
public InsertBuilder value<T>(Column<T> column, T value) {
- if (fields == null) {
- fields = { new StatementBuilder.Field<T>(column, value) };
- } else {
- StatementBuilder.Field[] fields_new = new StatementBuilder.Field[fields.length+1];
- for (int i = 0; i < fields.length; i++) {
- fields_new[i] = fields[i];
- }
- fields_new[fields.length] = new Field<T>(column, value);
- fields = fields_new;
- }
+ fields += new Field<T>(column, value);
return this;
}
public InsertBuilder value_null<T>(Column<T> column) throws DatabaseError {
if (column.not_null) throw new DatabaseError.ILLEGAL_QUERY(@"Can't set non-null column $(column.name) to null");
- if (fields == null) {
- fields = { new NullField<T>(column) };
- } else {
- StatementBuilder.Field[] fields_new = new StatementBuilder.Field[fields.length+1];
- for (int i = 0; i < fields.length; i++) {
- fields_new[i] = fields[i];
- }
- fields_new[fields.length] = new NullField<T>(column);
- fields = fields_new;
- }
+ fields += new NullField<T>(column);
return this;
}
@@ -77,11 +59,11 @@ public class InsertBuilder : StatementBuilder {
value_qs += ", ";
fields_text += ", ";
}
- fields_text += fields[i].column.name;
+ fields_text += ((!)fields[i].column).name;
value_qs += "?";
}
string sql = replace_val ? "REPLACE" : "INSERT";
- if (!replace_val && or_val != null) sql += @" OR $or_val";
+ if (!replace_val && or_val != null) sql += @" OR $((!)or_val)";
sql += @" INTO $table_name ( $fields_text ) VALUES ($value_qs)";
Statement stmt = db.prepare(sql);
for (int i = 0; i < fields.length; i++) {
diff --git a/qlite/src/query_builder.vala b/qlite/src/query_builder.vala
index 06232fc1..f46fe98c 100644
--- a/qlite/src/query_builder.vala
+++ b/qlite/src/query_builder.vala
@@ -7,18 +7,18 @@ public class QueryBuilder : StatementBuilder {
// SELECT [...]
private string column_selector = "*";
- private Column[] columns;
+ private Column[] columns = {};
// FROM [...]
- private Table table;
- private string table_name;
+ private Table? table;
+ private string? table_name;
// WHERE [...]
- private string selection;
- private StatementBuilder.Field[] selection_args;
+ private string selection = "1";
+ private StatementBuilder.AbstractField[] selection_args = {};
// ORDER BY [...]
- private OrderingTerm[] order_by_terms;
+ private OrderingTerm[]? order_by_terms = {};
// LIMIT [...]
private int limit_val;
@@ -27,9 +27,9 @@ public class QueryBuilder : StatementBuilder {
base(db);
}
- public QueryBuilder select(Column[]? columns = null) {
+ public QueryBuilder select(Column[] columns = {}) {
this.columns = columns;
- if (columns != null) {
+ if (columns.length == 0) {
for (int i = 0; i < columns.length; i++) {
if (column_selector == "*") {
column_selector = columns[0].name;
@@ -44,7 +44,7 @@ public class QueryBuilder : StatementBuilder {
}
public QueryBuilder select_string(string column_selector) {
- this.columns = null;
+ this.columns = {};
this.column_selector = column_selector;
return this;
}
@@ -61,32 +61,19 @@ public class QueryBuilder : StatementBuilder {
return this;
}
- public QueryBuilder where(string selection, string[]? selection_args = null) throws DatabaseError {
- if (this.selection != null) throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
+ public QueryBuilder where(string selection, string[] selection_args = {}) throws DatabaseError {
+ if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
this.selection = selection;
- if (selection_args != null) {
- this.selection_args = new StatementBuilder.Field[selection_args.length];
- for (int i = 0; i < selection_args.length; i++) {
- this.selection_args[i] = new StatementBuilder.StringField(selection_args[i]);
- }
+ foreach (string arg in selection_args) {
+ this.selection_args += new StatementBuilder.StringField(arg);
}
return this;
}
public QueryBuilder with<T>(Column<T> column, string comp, T value) {
if ((column.unique || column.primary_key) && comp == "=") single_result = true;
- if (selection == null) {
- selection = @"$(column.name) $comp ?";
- selection_args = { new StatementBuilder.Field<T>(column, value) };
- } else {
- selection = @"($selection) AND $(column.name) $comp ?";
- StatementBuilder.Field[] selection_args_new = new StatementBuilder.Field[selection_args.length+1];
- for (int i = 0; i < selection_args.length; i++) {
- selection_args_new[i] = selection_args[i];
- }
- selection_args_new[selection_args.length] = new Field<T>(column, value);
- selection_args = selection_args_new;
- }
+ selection_args += new Field<T>(column, value);
+ selection = @"($selection) AND $(column.name) $comp ?";
return this;
}
@@ -100,26 +87,13 @@ public class QueryBuilder : StatementBuilder {
return this;
}
- private void add_order_by(OrderingTerm term) {
- if (order_by_terms == null) {
- order_by_terms = { term };
- } else {
- OrderingTerm[] order_by_terms_new = new OrderingTerm[order_by_terms.length+1];
- for (int i = 0; i < order_by_terms.length; i++) {
- order_by_terms_new[i] = order_by_terms[i];
- }
- order_by_terms_new[order_by_terms.length] = term;
- order_by_terms = order_by_terms_new;
- }
- }
-
public QueryBuilder order_by(Column column, string dir = "ASC") {
- add_order_by(new OrderingTerm(column, dir));
+ order_by_terms += new OrderingTerm(column, dir);
return this;
}
public QueryBuilder order_by_name(string name, string dir) {
- add_order_by(new OrderingTerm.by_name(name, dir));
+ order_by_terms += new OrderingTerm.by_name(name, dir);
return this;
}
@@ -131,12 +105,12 @@ public class QueryBuilder : StatementBuilder {
public int64 count() throws DatabaseError {
this.column_selector = @"COUNT($column_selector) AS count";
this.single_result = true;
- return row_().get_integer("count");
+ return row().get_integer("count");
}
private Row? row_() throws DatabaseError {
if (!single_result) throw new DatabaseError.NON_UNIQUE("query is not suited to return a single row, but row() was called.");
- return iterator().next_value();
+ return iterator().get_next();
}
public RowOption row() throws DatabaseError {
@@ -148,7 +122,7 @@ public class QueryBuilder : StatementBuilder {
}
internal override Statement prepare() throws DatabaseError {
- Statement stmt = db.prepare(@"SELECT $column_selector FROM $table_name $(selection != null ? @"WHERE $selection" : "") $(order_by_terms != null ? OrderingTerm.all_to_string(order_by_terms) : "") $(limit_val > 0 ? @" LIMIT $limit_val" : "")");
+ Statement stmt = db.prepare(@"SELECT $column_selector $(table_name == null ? "" : @"FROM $((!) table_name)") WHERE $selection $(OrderingTerm.all_to_string(order_by_terms)) $(limit_val > 0 ? @" LIMIT $limit_val" : "")");
for (int i = 0; i < selection_args.length; i++) {
selection_args[i].bind(stmt, i+1);
}
@@ -179,8 +153,8 @@ public class QueryBuilder : StatementBuilder {
return @"$column_name $dir";
}
- public static string all_to_string(OrderingTerm[] terms) {
- if (terms.length == 0) return "";
+ public static string all_to_string(OrderingTerm[]? terms) {
+ if (terms == null || terms.length == 0) return "";
string res = "ORDER BY "+terms[0].to_string();
for (int i = 1; i < terms.length; i++) {
res += @", $(terms[i])";
diff --git a/qlite/src/row.vala b/qlite/src/row.vala
index 96762be3..8854656f 100644
--- a/qlite/src/row.vala
+++ b/qlite/src/row.vala
@@ -4,7 +4,7 @@ using Sqlite;
namespace Qlite {
public class Row {
- private Map<string, string> text_map = new HashMap<string, string>();
+ private Map<string, string?> text_map = new HashMap<string, string?>();
private Map<string, long> int_map = new HashMap<string, long>();
private Map<string, double?> real_map = new HashMap<string, double?>();
@@ -43,8 +43,8 @@ public class Row {
return int_map.has_key(field);
}
- public double get_real(string field) {
- return real_map[field];
+ public double get_real(string field, double def = 0) {
+ return real_map[field] ?? def;
}
public bool has_real(string field) {
@@ -71,11 +71,21 @@ public class RowIterator {
}
}
- public Row? next_value() throws DatabaseError {
+ public bool next() {
int r = stmt.step();
- if (r == Sqlite.ROW) return new Row(stmt);
- if (r == Sqlite.DONE) return null;
- throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
+ if (r == Sqlite.ROW) return true;
+ if (r == Sqlite.DONE) return false;
+ print(@"SQLite error: $(db.errcode()) - $(db.errmsg())\n");
+ return false;
+ }
+
+ public Row get() {
+ return new Row(stmt);
+ }
+
+ public Row? get_next() {
+ if (next()) return get();
+ return null;
}
}
@@ -91,8 +101,13 @@ public class RowOption {
}
public T get<T>(Column<T> field, T def = null) {
- if (inner == null || field.is_null(inner)) return def;
- return field[inner];
+ if (inner == null || field.is_null((!)inner)) return def;
+ return field[(!)inner];
+ }
+
+ internal long get_integer(string field, long def = 0) {
+ if (inner == null || !((!)inner).has_integer(field)) return def;
+ return ((!)inner).get_integer(field);
}
}
diff --git a/qlite/src/statement_builder.vala b/qlite/src/statement_builder.vala
index 11efb0de..6097a9cc 100644
--- a/qlite/src/statement_builder.vala
+++ b/qlite/src/statement_builder.vala
@@ -11,25 +11,32 @@ public abstract class StatementBuilder {
internal abstract Statement prepare() throws DatabaseError;
- internal class Field<T> {
+ internal abstract class AbstractField<T> {
public T value;
public Column<T>? column;
- public Field(Column<T>? column, T value) {
- this.column = column;
+ public AbstractField(T value) {
this.value = value;
}
- internal virtual void bind(Statement stmt, int index) {
- if (column != null) {
- column.bind(stmt, index, value);
- }
+ internal abstract void bind(Statement stmt, int index);
+ }
+
+ internal class Field<T> : AbstractField<T> {
+ public Field(Column<T> column, T value) {
+ base(value);
+ this.column = column;
+ }
+
+ internal override void bind(Statement stmt, int index) {
+ ((!)column).bind(stmt, index, value);
}
}
- internal class NullField<T> : Field<T> {
- public NullField(Column<T>? column) {
- base(column, null);
+ internal class NullField<T> : AbstractField<T> {
+ public NullField(Column<T> column) {
+ base(null);
+ this.column = column;
}
internal override void bind(Statement stmt, int index) {
@@ -37,9 +44,9 @@ public abstract class StatementBuilder {
}
}
- internal class StringField : Field<string> {
+ internal class StringField : AbstractField<string> {
public StringField(string value) {
- base(null, value);
+ base(value);
}
internal override void bind(Statement stmt, int index) {
diff --git a/qlite/src/table.vala b/qlite/src/table.vala
index 2a80c9a5..b4f2fee7 100644
--- a/qlite/src/table.vala
+++ b/qlite/src/table.vala
@@ -5,22 +5,21 @@ namespace Qlite {
public class Table {
protected Database db;
public string name { get; private set; }
- protected Column[] columns;
- private string constraints;
+ protected Column[]? columns;
+ private string constraints = "";
public Table(Database db, string name) {
this.db = db;
this.name = name;
}
- public void init(Column[] columns, string? constraints = null) {
+ public void init(Column[] columns, string constraints = "") {
this.columns = columns;
this.constraints = constraints;
}
public void unique(Column[] columns, string? on_conflict = null) {
- if (constraints == null) constraints = ""; else constraints += ", ";
- constraints += "UNIQUE (";
+ constraints += ", UNIQUE (";
bool first = true;
foreach (Column c in columns) {
if (!first) constraints += ", ";
@@ -29,7 +28,7 @@ public class Table {
}
constraints += ")";
if (on_conflict != null) {
- constraints += "ON CONFLICT " + on_conflict;
+ constraints += "ON CONFLICT " + (!)on_conflict;
}
}
@@ -80,10 +79,7 @@ public class Table {
sql += @"$(i > 0 ? "," : "") $c";
}
}
- if (constraints != null) {
- sql += ", " + constraints;
- }
- sql += ")";
+ sql += @"$constraints)";
db.exec(sql);
}
@@ -98,10 +94,10 @@ public class Table {
public void delete_columns_for_version(long old_version, long new_version) throws DatabaseError {
bool column_deletion_required = false;
- string column_list = null;
+ string column_list = "";
foreach (Column c in columns) {
if (c.min_version <= new_version && c.max_version >= new_version) {
- if (column_list == null) {
+ if (column_list == "") {
column_list = c.name;
} else {
column_list += ", " + c.name;
diff --git a/qlite/src/update_builder.vala b/qlite/src/update_builder.vala
index 6aad2aa1..139009c5 100644
--- a/qlite/src/update_builder.vala
+++ b/qlite/src/update_builder.vala
@@ -5,18 +5,18 @@ namespace Qlite {
public class UpdateBuilder : StatementBuilder {
// UPDATE [OR ...]
- private string or_val;
+ private string? or_val;
// [...]
- private Table table;
+ private Table? table;
private string table_name;
// SET [...]
- private StatementBuilder.Field[] fields;
+ private StatementBuilder.AbstractField[] fields = {};
// WHERE [...]
- private string selection;
- private StatementBuilder.Field[] selection_args;
+ private string selection = "1";
+ private StatementBuilder.AbstractField[] selection_args = {};
internal UpdateBuilder(Database db, Table table) {
base(db);
@@ -35,59 +35,28 @@ public class UpdateBuilder : StatementBuilder {
}
public UpdateBuilder set<T>(Column<T> column, T value) {
- if (fields == null) {
- fields = { new StatementBuilder.Field<T>(column, value) };
- } else {
- StatementBuilder.Field[] fields_new = new StatementBuilder.Field[fields.length+1];
- for (int i = 0; i < fields.length; i++) {
- fields_new[i] = fields[i];
- }
- fields_new[fields.length] = new Field<T>(column, value);
- fields = fields_new;
- }
+ fields += new Field<T>(column, value);
return this;
}
public UpdateBuilder set_null<T>(Column<T> column) throws DatabaseError {
if (column.not_null) throw new DatabaseError.ILLEGAL_QUERY(@"Can't set non-null column $(column.name) to null");
- if (fields == null) {
- fields = { new NullField<T>(column) };
- } else {
- StatementBuilder.Field[] fields_new = new StatementBuilder.Field[fields.length+1];
- for (int i = 0; i < fields.length; i++) {
- fields_new[i] = fields[i];
- }
- fields_new[fields.length] = new NullField<T>(column);
- fields = fields_new;
- }
+ fields += new NullField<T>(column);
return this;
}
- public UpdateBuilder where(string selection, string[]? selection_args = null) throws DatabaseError {
- if (this.selection != null) throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
+ public UpdateBuilder where(string selection, string[] selection_args = {}) throws DatabaseError {
+ if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
this.selection = selection;
- if (selection_args != null) {
- this.selection_args = new StatementBuilder.Field[selection_args.length];
- for (int i = 0; i < selection_args.length; i++) {
- this.selection_args[i] = new StatementBuilder.StringField(selection_args[i]);
- }
+ foreach (string arg in selection_args) {
+ this.selection_args += new StatementBuilder.StringField(arg);
}
return this;
}
public UpdateBuilder with<T>(Column<T> column, string comp, T value) {
- if (selection == null) {
- selection = @"$(column.name) $comp ?";
- selection_args = { new StatementBuilder.Field<T>(column, value) };
- } else {
- selection = @"($selection) AND $(column.name) $comp ?";
- StatementBuilder.Field[] selection_args_new = new StatementBuilder.Field[selection_args.length+1];
- for (int i = 0; i < selection_args.length; i++) {
- selection_args_new[i] = selection_args[i];
- }
- selection_args_new[selection_args.length] = new Field<T>(column, value);
- selection_args = selection_args_new;
- }
+ selection_args += new Field<T>(column, value);
+ selection = @"($selection) AND $(column.name) $comp ?";
return this;
}
@@ -103,13 +72,13 @@ public class UpdateBuilder : StatementBuilder {
internal override Statement prepare() throws DatabaseError {
string sql = "UPDATE";
- if (or_val != null) sql += @" OR $or_val";
+ if (or_val != null) sql += @" OR $((!)or_val)";
sql += @" $table_name SET ";
for (int i = 0; i < fields.length; i++) {
if (i != 0) {
sql += ", ";
}
- sql += @"$(fields[i].column.name) = ?";
+ sql += @"$(((!)fields[i].column).name) = ?";
}
sql += @" WHERE $selection";
Statement stmt = db.prepare(sql);
@@ -123,7 +92,7 @@ public class UpdateBuilder : StatementBuilder {
}
public void perform() throws DatabaseError {
- if (fields == null || fields.length == 0) return;
+ if (fields.length == 0) return;
if (prepare().step() != DONE) {
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
}