mirror of
https://github.com/TakeV-Lambda/dino.git
synced 2024-11-21 22:44:23 +00:00
qlite: cleanup, fix nullity issues
This commit is contained in:
parent
c6ff3387fa
commit
765c2605cd
9 changed files with 131 additions and 181 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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])";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue