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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
using Sqlite;
namespace Qlite {
public abstract class Column<T> {
public string name { get; private 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 long min_version { get; set; default = -1; }
public long max_version { get; set; default = long.MAX; }
public abstract T get(Row row);
public virtual bool is_null(Row row) {
return false;
}
public virtual void bind(Statement stmt, int index, T value) {
throw new DatabaseError.NOT_SUPPORTED(@"bind() was not implemented for field $name");
}
public string to_string() {
string res = name;
switch (sqlite_type) {
case INTEGER:
res += " INTEGER";
break;
case FLOAT:
res += " REAL";
break;
case TEXT:
res += " TEXT";
break;
default:
res += " UNKNOWN";
break;
}
if (primary_key) {
res += " PRIMARY KEY";
if (auto_increment) res += " AUTOINCREMENT";
}
if (not_null) res += " NOT NULL";
if (unique) res += " UNIQUE";
if (default != null) res += @" DEFAULT $default";
return res;
}
public Column(string name, int type) {
this.name = name;
this.sqlite_type = type;
}
public class Integer : Column<int> {
public Integer(string name) {
base(name, INTEGER);
}
public override int get(Row row) {
return (int) row.get_integer(name);
}
public override bool is_null(Row row) {
return !row.has_integer(name);
}
public override void bind(Statement stmt, int index, int value) {
stmt.bind_int(index, value);
}
}
public class Long : Column<long> {
public Long(string name) {
base(name, INTEGER);
}
public override long get(Row row) {
return (long) row.get_integer(name);
}
public override bool is_null(Row row) {
return !row.has_integer(name);
}
public override void bind(Statement stmt, int index, long value) {
stmt.bind_int64(index, value);
}
}
public class Real : Column<double> {
public Real(string name) {
base(name, FLOAT);
}
public override double get(Row row) {
return row.get_real(name);
}
public override bool is_null(Row row) {
return !row.has_real(name);
}
public override void bind(Statement stmt, int index, double value) {
stmt.bind_double(index, value);
}
}
public class Text : Column<string?> {
public Text(string name) {
base(name, TEXT);
}
public override string? get(Row row) {
return row.get_text(name);
}
public override bool is_null(Row row) {
return get(row) == null;
}
public override void bind(Statement stmt, int index, string? value) {
if (value != null) {
stmt.bind_text(index, value);
} else {
stmt.bind_null(index);
}
}
}
public class BoolText : Column<bool> {
public BoolText(string name) {
base(name, TEXT);
}
public override bool get(Row row) {
return row.get_text(name) == "1";
}
public override void bind(Statement stmt, int index, bool value) {
stmt.bind_text(index, value ? "1" : "0");
}
}
public class BoolInt : Column<bool> {
public BoolInt(string name) {
base(name, INTEGER);
}
public override bool get(Row row) {
return row.get_integer(name) == 1;
}
public override void bind(Statement stmt, int index, bool value) {
stmt.bind_int(index, value ? 1 : 0);
}
}
public class RowReference : Column<Row?> {
private Table table;
private Column<int> id_column;
public RowReference(string name, Table table, Column<int> id_column) throws DatabaseError {
base(name, INTEGER);
if (!table.is_known_column(id_column.name)) throw new DatabaseError.ILLEGAL_REFERENCE(@"$(id_column.name) is not a column in $(table.name)");
if (!id_column.primary_key && !id_column.unique) throw new DatabaseError.NON_UNIQUE(@"$(id_column.name) is not suited to identify a row, but used with RowReference");
this.table = table;
this.id_column = id_column;
}
public override Row? get(Row row) {
return table.row_with(id_column, (int)row.get_integer(name));
}
public override void bind(Statement stmt, int index, Row? value) {
if (value != null) {
stmt.bind_int(index, id_column.get(value));
} else {
stmt.bind_null(index);
}
}
}
}
}
|