3
* Copyright © 2011 Collabora Ltd.
4
* By Siegfried-Angel Gevatter Pujals <siegfried@gevatter.com>
5
* By Seif Lotfy <seif@lotfy.com>
6
* Copyright © 2011 Manish Sinha <manishsinha@ubuntu.com>
8
* This program is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License as published by
10
* the Free Software Foundation, either version 2.1 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
25
namespace Zeitgeist.SQLite
28
public enum EventViewRows
38
SUBJECT_INTERPRETATION,
39
SUBJECT_MANIFESTATION,
45
SUBJECT_STORAGE_STATE,
52
public delegate void DeletionCallback (string table, int64 rowid);
54
public class ZeitgeistDatabase : Object
57
public Sqlite.Statement event_insertion_stmt;
58
public Sqlite.Statement id_retrieval_stmt;
59
public Sqlite.Statement move_handling_stmt;
60
public Sqlite.Statement payload_insertion_stmt;
62
// The DB should be accessible from engine for statement preperations
63
// as well as allowing extensions to add tables to it.
64
public Sqlite.Database database;
66
private DeletionCallback? deletion_callback = null;
68
public ZeitgeistDatabase () throws EngineError
70
int rc = Sqlite.Database.open_v2 (
71
Utils.get_database_file_path (),
73
assert_query_success (rc, "Can't open database");
75
DatabaseSchema.ensure_schema (database);
79
// Register a data change notification callback to look for
80
// deletions, so we can keep the TableLookups up to date.
81
database.update_hook (update_callback);
84
public uint32 get_last_id () throws EngineError
87
int rc = database.exec ("SELECT MAX(id) FROM event",
88
(n_columns, values, column_names) =>
90
if (values[0] == null)
93
last_id = int.parse (values[0]);
96
assert_query_success (rc, "Can't query database");
97
assert (last_id != -1);
101
public void set_deletion_callback (DeletionCallback? callback)
103
deletion_callback = callback;
107
* Join all given event_ids into a comma-separated string suitable
108
* for use in a SQL query like "WHERE id IN (...)".
110
public string get_sql_string_from_event_ids (uint32[] event_ids)
111
requires (event_ids.length > 0)
113
var sql_condition = new StringBuilder ();
114
sql_condition.append_printf ("%u", event_ids[0]);
115
for (int i = 1; i < event_ids.length; ++i) {
116
sql_condition.append_printf (", %u", event_ids[i]);
118
return sql_condition.str;
121
public TimeRange? get_time_range_for_event_ids (uint32[] event_ids)
124
if (event_ids.length == 0)
128
SELECT MIN(timestamp), MAX(timestamp)
131
""".printf (get_sql_string_from_event_ids (event_ids));
133
TimeRange? time_range = null;
134
int rc = database.exec (sql,
135
(n_columns, values, column_names) =>
137
if (values[0] != null)
139
int64 start = int64.parse (values[0]);
140
int64 end = int64.parse (values[1]);
141
time_range = new TimeRange (start, end);
145
assert_query_success (rc, "SQL Error");
150
public void insert_or_ignore_into_table (string table_name,
151
GenericArray<string> values) throws EngineError
155
assert (values.length > 0);
156
var sql = new StringBuilder ();
157
sql.append ("INSERT OR IGNORE INTO ");
158
sql.append (table_name);
159
sql.append (" (value) SELECT ?");
160
for (int i = 1; i < values.length; ++i)
161
sql.append (" UNION SELECT ?");
163
Sqlite.Statement stmt;
164
rc = database.prepare_v2 (sql.str, -1, out stmt);
165
assert_query_success (rc, "SQL error");
167
for (int i = 0; i < values.length; ++i)
168
stmt.bind_text (i+1, values[i]);
171
assert_query_success (rc, "SQL error", Sqlite.DONE);
174
public void begin_transaction () throws EngineError
176
int rc = database.exec ("BEGIN");
177
assert_query_success (rc, "Can't start transaction");
180
public void end_transaction () throws EngineError
182
int rc = database.exec ("COMMIT");
183
assert_query_success (rc, "Can't commit transaction");
188
// SQLite connection is implicitly closed upon destruction
193
* Ensure `rc' is SQLITE_OK. If it isn't, print an error message
194
* and throw an error.
196
* @param rc error code returned by a SQLite call
197
* @param msg message to print if `rc' indicates an error
198
* @throws EngineError
200
public void assert_query_success (int rc, string msg,
201
int success_code=Sqlite.OK) throws EngineError
203
if (rc != success_code)
205
string error_message = "%s: %d, %s".printf(
206
msg, rc, database.errmsg ());
207
warning ("%s\n", error_message);
208
throw new EngineError.DATABASE_ERROR (error_message);
212
private void prepare_queries () throws EngineError
217
// Event insertion statement
220
id, timestamp, interpretation, manifestation, actor,
221
origin, payload, subj_id, subj_id_current,
222
subj_interpretation, subj_manifestation, subj_origin,
223
subj_mimetype, subj_text, subj_storage
226
(SELECT id FROM uri WHERE value=?),
228
(SELECT id FROM uri WHERE value=?),
229
(SELECT id FROM uri WHERE value=?),
231
(SELECT id FROM uri WHERE value=?),
233
(SELECT id FROM text WHERE value=?),
234
(SELECT id FROM storage WHERE value=?)
237
rc = database.prepare_v2 (sql, -1, out event_insertion_stmt);
238
assert_query_success (rc, "Insertion query error");
240
// Event ID retrieval statement
243
WHERE timestamp=? AND interpretation=? AND
244
manifestation=? AND actor=?
246
rc = database.prepare_v2 (sql, -1, out id_retrieval_stmt);
247
assert_query_success (rc, "Event ID retrieval query error");
249
// Move handling statment
252
SET subj_id_current=(SELECT id FROM uri WHERE value=?)
253
WHERE subj_id_current=(SELECT id FROM uri WHERE value=?)
254
AND interpretation!=? AND timestamp<?
256
rc = database.prepare_v2 (sql, -1, out move_handling_stmt);
257
assert_query_success (rc, "Move handling error");
259
// Payload insertion statment
261
INSERT INTO payload (value) VALUES (?)
263
rc = database.prepare_v2 (sql, -1, out payload_insertion_stmt);
264
assert_query_success (rc, "Payload insertion query error");
268
protected void update_callback (Sqlite.Action action,
269
string dbname, string table, int64 rowid)
271
if (action != Sqlite.Action.DELETE)
273
if (deletion_callback != null)
274
deletion_callback (table, rowid);
275
//interpretations_table
277
//mimetypes_table - mimetype table
278
// actors_ . actor table
281
stdout.printf ("%s", dbname); // = main
282
stdout.printf ("%s", table);
283
stdout.printf ("%li", (long) rowid);
291
// vim:expandtab:ts=4:sw=4