aboutsummaryrefslogtreecommitdiff
path: root/qlite/src/table.vala
blob: 7396136e326ba83dabf342d93ac0f429856d78ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using Sqlite;

namespace Qlite {

public class Table {
    protected Database db;
    public string name { get; private set; }
    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) {
        this.columns = columns;
        this.constraints = constraints;
    }

    public void unique(Column[] columns, string? on_conflict = null) {
        if (constraints == null) constraints = ""; else constraints += ", ";
        constraints += "UNIQUE (";
        bool first = true;
        foreach(Column c in columns) {
            if (!first) constraints += ", ";
            constraints += c.name;
            first = false;
        }
        constraints += ")";
        if (on_conflict != null) {
            constraints += "ON CONFLICT " + on_conflict;
        }
    }

    private void ensure_init() throws DatabaseError {
        if (columns == null) throw new DatabaseError.NOT_INITIALIZED(@"Table $name was not initialized, call init()");
    }

    public QueryBuilder select(Column[]? columns = null) throws DatabaseError {
        ensure_init();
        return db.select(columns).from(this);
    }

    public InsertBuilder insert() throws DatabaseError {
        ensure_init();
        return db.insert().into(this);
    }

    public UpdateBuilder update() throws DatabaseError {
        ensure_init();
        return db.update(this);
    }

    public DeleteBuilder delete() throws DatabaseError {
        ensure_init();
        return db.delete().from(this);
    }

    public Row? row_with<T>(Column<T> column, T value) throws DatabaseError {
        ensure_init();
        if (!column.unique && !column.primary_key) throw new DatabaseError.NON_UNIQUE(@"$(column.name) is not suited to identify a row, but used with row_with()");
        return select().with(column, "=", value).row();
    }

    public bool is_known_column(string column) throws DatabaseError {
        ensure_init();
        foreach (Column c in columns) {
            if (c.name == column) return true;
        }
        return false;
    }

    public void create_table_at_version(long version) throws DatabaseError {
        ensure_init();
        string sql = @"CREATE TABLE IF NOT EXISTS $name (";
        for(int i = 0; i < columns.length; i++) {
            Column c = columns[i];
            if (c.min_version <= version && c.max_version >= version) {
                sql += @"$(i > 0 ? "," : "") $c";
            }
        }
        if (constraints != null) {
            sql += ", " + constraints;
        }
        sql += ")";
        db.exec(sql);
    }

    public void add_columns_for_version(long old_version, long new_version) throws DatabaseError {
        ensure_init();
        foreach (Column c in columns) {
            if (c.min_version <= new_version && c.max_version >= new_version && c.min_version > old_version && c.max_version < old_version) {
                db.exec(@"ALTER TABLE $name ADD COLUMN $c");
            }
        }
    }

    public void delete_columns_for_version(long old_version, long new_version) throws DatabaseError {
        // TODO: Rename old table, create table at new_version, transfer data
    }
}

}