195
118
return (gchar*)sqlite3_column_text(statement, column);
198
Data::Data(gboolean initialise)
200
Glib::ustring database_path = Glib::build_filename(get_application().get_application_dir(), "/me-tv.db");
202
g_debug("Opening database file '%s'", database_path.c_str());
203
if (sqlite3_open(database_path.c_str(), &database) != 0)
205
throw SQLiteException(database, _("Failed to connect to Me TV database"));
211
"CREATE TABLE IF NOT EXISTS PROFILE ("\
212
"PROFILE_ID INTEGER PRIMARY KEY AUTOINCREMENT, "\
213
"NAME CHAR(50) NOT NULL, "\
217
"CREATE TABLE IF NOT EXISTS CHANNEL ("\
218
"CHANNEL_ID INTEGER PRIMARY KEY AUTOINCREMENT, "\
219
"PROFILE_ID INTEGER NOT NULL, "\
220
"NAME CHAR(50) NOT NULL, "\
221
"FLAGS INTEGER NOT NULL, "\
222
"SORT_ORDER INTEGER NOT NULL, "\
224
"SERVICE_ID INTEGER, "\
225
"FREQUENCY INTEGER, "\
226
"INVERSION INTEGER, "\
228
"BANDWIDTH INTEGER, "\
229
"CODE_RATE_HP INTEGER, "\
230
"CODE_RATE_LP INTEGER, "\
231
"CONSTELLATION INTEGER, "\
232
"TRANSMISSION_MODE INTEGER, "\
233
"GUARD_INTERVAL INTEGER, "\
234
"HIERARCHY_INFORMATION INTEGER, "\
236
"SYMBOL_RATE INTEGER, "\
237
"FEC_INNER INTEGER, "\
238
"MODULATION INTEGER, "\
243
"CREATE TABLE IF NOT EXISTS EPG_EVENT ("\
244
"EPG_EVENT_ID INTEGER PRIMARY KEY AUTOINCREMENT, "\
245
"CHANNEL_ID INTEGER NOT NULL, "\
246
"EVENT_ID INTEGER NOT NULL, "\
247
"START_TIME INTEGER NOT NULL, "\
248
"DURATION INTEGER NOT NULL, "\
249
"UNIQUE (CHANNEL_ID, EVENT_ID));");
252
"CREATE TABLE IF NOT EXISTS EPG_EVENT_TEXT ("\
253
"EPG_EVENT_TEXT_ID INTEGER PRIMARY KEY AUTOINCREMENT, "\
254
"EPG_EVENT_ID INTEGER NOT NULL, "\
255
"LANGUAGE CHAR(3) NOT NULL, "\
256
"TITLE CHAR(100) NOT NULL, "\
257
"DESCRIPTION CHAR(200) NOT NULL, "\
258
"UNIQUE (EPG_EVENT_ID, LANGUAGE));");
261
"CREATE TABLE IF NOT EXISTS SCHEDULED_RECORDING ("\
262
"SCHEDULED_RECORDING_ID INTEGER PRIMARY KEY AUTOINCREMENT, "\
263
"DESCRIPTION CHAR(100) NOT NULL, "\
264
"TYPE INTEGER NOT NULL, " \
265
"CHANNEL_ID INTEGER NOT NULL, " \
266
"START_TIME INTEGER NOT NULL, " \
267
"DURATION INTEGER NOT NULL);");
269
delete_old_scheduled_recordings();
275
if (database != NULL)
277
sqlite3_close(database);
282
guint Data::execute_non_query(const Glib::ustring& command)
284
Statement statement(database, command);
285
return statement.step();
288
void fix_quotes(Glib::ustring& text)
290
replace_text(text, "'", "''");
293
void Data::replace_epg_event(EpgEvent& epg_event)
295
if (epg_event.channel_id == 0)
297
throw Exception(_("ASSERT: epg_event.channel_id == 0"));
300
Glib::ustring insert_command = Glib::ustring::compose
302
"REPLACE INTO EPG_EVENT "\
303
"(CHANNEL_ID, EVENT_ID, START_TIME, DURATION) "\
304
"VALUES (%1, %2, %3, %4);",
305
epg_event.channel_id, epg_event.event_id, epg_event.start_time, epg_event.duration
308
execute_non_query(insert_command);
310
if (epg_event.epg_event_id == 0)
312
epg_event.epg_event_id = sqlite3_last_insert_rowid(database);
315
if (epg_event.epg_event_id == 0)
317
Glib::ustring select_command = Glib::ustring::compose
319
"SELECT EPG_EVENT_ID FROM EPG_EVENT WHERE CHANNEL_ID = %1 AND EVENT_ID = %2",
320
epg_event.channel_id, epg_event.event_id
323
Statement statement(database, select_command);
324
if (statement.step() == SQLITE_ROW)
326
epg_event.epg_event_id = statement.get_int(0);
329
if (epg_event.epg_event_id == 0)
331
throw Exception(_("Failed to get epg_event_id"));
335
for (EpgEventTextList::iterator i = epg_event.texts.begin(); i != epg_event.texts.end(); i++)
337
EpgEventText& epg_event_text = *i;
338
epg_event_text.epg_event_id = epg_event.epg_event_id;
339
replace_epg_event_text(epg_event_text);
343
void Data::replace_epg_event_text(EpgEventText& epg_event_text)
345
Glib::ustring command;
347
if (epg_event_text.epg_event_id == 0)
349
throw Exception(_("Event ID was 0"));
352
Glib::ustring fixed_title = epg_event_text.title;
353
Glib::ustring fixed_description = epg_event_text.description;
355
fix_quotes(fixed_title);
356
fix_quotes(fixed_description);
358
guint existing_epg_event_text_id = 0;
360
// Make sure that statement exists before we start the next command
362
Statement statement(database, Glib::ustring::compose(
363
"SELECT EPG_EVENT_TEXT_ID FROM EPG_EVENT_TEXT WHERE EPG_EVENT_ID=%1;",
364
epg_event_text.epg_event_id));
365
if (statement.step() == SQLITE_ROW)
367
existing_epg_event_text_id = statement.get_int(0);
371
if (existing_epg_event_text_id != 0)
373
if (epg_event_text.is_extended)
375
command = Glib::ustring::compose
377
"UPDATE EPG_EVENT_TEXT SET DESCRIPTION = DESCRIPTION || '%1' WHERE EPG_EVENT_TEXT_ID=%2;",
378
fixed_description, existing_epg_event_text_id
383
command = Glib::ustring::compose
385
"UPDATE EPG_EVENT_TEXT SET TITLE = '%1' WHERE EPG_EVENT_TEXT_ID=%2;",
386
fixed_title, existing_epg_event_text_id
392
if (epg_event_text.is_extended)
394
command = Glib::ustring::compose
396
"INSERT INTO EPG_EVENT_TEXT "\
397
"(EPG_EVENT_ID, LANGUAGE, TITLE, DESCRIPTION) "\
398
"VALUES (%1, '%2', '%3', '%4');",
399
epg_event_text.epg_event_id, epg_event_text.language, fixed_title, fixed_description
404
command = Glib::ustring::compose
406
"INSERT INTO EPG_EVENT_TEXT "\
407
"(EPG_EVENT_ID, LANGUAGE, TITLE, DESCRIPTION) "\
408
"VALUES (%1, '%2', '%3', '%4');",
409
epg_event_text.epg_event_id, epg_event_text.language, fixed_title, fixed_description
414
execute_non_query(command);
416
if (epg_event_text.epg_event_text_id == 0)
418
epg_event_text.epg_event_text_id = sqlite3_last_insert_rowid(database);
422
void Data::load_epg_event(Statement& statement, EpgEvent& epg_event)
424
epg_event.epg_event_id = statement.get_int(0);
425
epg_event.channel_id = statement.get_int(1);
426
epg_event.event_id = statement.get_int(2);
427
epg_event.start_time = statement.get_int(3);
428
epg_event.duration = statement.get_int(4);
429
epg_event.save = false;
431
Glib::ustring text_select_command = Glib::ustring::compose
433
"SELECT * FROM EPG_EVENT_TEXT WHERE EPG_EVENT_ID=%1;",
434
epg_event.epg_event_id
437
Statement text_statement(database, text_select_command);
438
while (text_statement.step() == SQLITE_ROW)
440
EpgEventText epg_event_text;
441
epg_event_text.epg_event_text_id = text_statement.get_int(0);
442
epg_event_text.epg_event_id = text_statement.get_int(1);
443
epg_event_text.language = text_statement.get_text(2);
444
epg_event_text.title = text_statement.get_text(3);
445
epg_event_text.description = text_statement.get_text(4);
446
epg_event.texts.push_back(epg_event_text);
450
EpgEventList Data::get_epg_events(const Channel& channel)
454
Glib::ustring select_command = Glib::ustring::compose
456
"SELECT * FROM EPG_EVENT WHERE CHANNEL_ID=%1 ORDER BY START_TIME;",
460
Statement statement(database, select_command);
461
while (statement.step() == SQLITE_ROW)
464
load_epg_event(statement, epg_event);
465
result.push_back(epg_event);
467
g_debug("Event %d (%s) loaded", epg_event.event_id, epg_event.get_title().c_str());
473
void Data::replace_channel(Channel& channel)
475
ParameterList parameters;
477
Glib::ustring fixed_name = channel.name;
478
fix_quotes(fixed_name);
481
if (channel.channel_id == 0)
483
parameters.add("CHANNEL_ID");
487
parameters.add("CHANNEL_ID", channel.channel_id);
490
g_debug("Saving channel %d (%s)", channel.channel_id, channel.name.c_str());
492
parameters.add("PROFILE_ID", channel.profile_id);
493
parameters.add("NAME", fixed_name);
494
parameters.add("FLAGS", channel.flags);
495
parameters.add("SORT_ORDER", channel.sort_order);
496
parameters.add("MRL", channel.mrl);
497
parameters.add("SERVICE_ID", channel.service_id);
498
parameters.add("FREQUENCY", (guint)channel.frontend_parameters.frequency);
499
parameters.add("INVERSION", (guint)channel.frontend_parameters.inversion);
501
if (channel.flags & CHANNEL_FLAG_DVB_T)
503
parameters.add("BANDWIDTH", (guint)channel.frontend_parameters.u.ofdm.bandwidth);
504
parameters.add("CODE_RATE_HP", (guint)channel.frontend_parameters.u.ofdm.code_rate_HP);
505
parameters.add("CODE_RATE_LP", (guint)channel.frontend_parameters.u.ofdm.code_rate_LP);
506
parameters.add("CONSTELLATION", (guint)channel.frontend_parameters.u.ofdm.constellation);
507
parameters.add("TRANSMISSION_MODE", (guint)channel.frontend_parameters.u.ofdm.transmission_mode);
508
parameters.add("GUARD_INTERVAL", (guint)channel.frontend_parameters.u.ofdm.guard_interval);
509
parameters.add("HIERARCHY_INFORMATION", (guint)channel.frontend_parameters.u.ofdm.hierarchy_information);
511
else if (channel.flags & CHANNEL_FLAG_DVB_C)
513
parameters.add("SYMBOL_RATE", (guint)channel.frontend_parameters.u.qam.symbol_rate);
514
parameters.add("FEC_INNER", (guint)channel.frontend_parameters.u.qam.fec_inner);
515
parameters.add("MODULATION", (guint)channel.frontend_parameters.u.qam.modulation);
517
else if (channel.flags & CHANNEL_FLAG_ATSC)
519
parameters.add("MODULATION", (guint)channel.frontend_parameters.u.vsb.modulation);
523
throw Exception(_("Invalid channel flag"));
526
Glib::ustring insert_command = Glib::ustring::compose
528
"REPLACE INTO CHANNEL (%1) VALUES (%2);",
529
parameters.get_names(), parameters.get_values()
532
execute_non_query(insert_command);
534
if (channel.channel_id == 0)
536
channel.channel_id = sqlite3_last_insert_rowid(database);
539
EpgEventList epg_event_list = channel.epg_events.get_list(true);
540
for (EpgEventList::iterator i = epg_event_list.begin(); i != epg_event_list.end(); i++)
542
EpgEvent& epg_event = *i;
545
replace_epg_event(epg_event);
546
g_debug("Saved EPG event %d (%s)", epg_event.event_id, epg_event.get_title().c_str());
551
void Data::replace_profile(Profile& profile)
553
ParameterList parameters;
554
Glib::ustring fixed_name = profile.name;
556
fix_quotes(fixed_name);
558
if (profile.profile_id == 0)
560
parameters.add("PROFILE_ID");
564
parameters.add("PROFILE_ID", profile.profile_id);
566
parameters.add("NAME", profile.name);
568
Glib::ustring replace_command = Glib::ustring::compose
570
"REPLACE INTO PROFILE (%1) VALUES (%2);",
571
parameters.get_names(), parameters.get_values()
574
execute_non_query(replace_command);
576
if (profile.profile_id == 0)
578
profile.profile_id = sqlite3_last_insert_rowid(database);
579
if (profile.profile_id == 0)
581
throw Exception("ASSERT: profile.profile_id == 0");
585
// First, remove channels
586
Statement statement(database,
587
Glib::ustring::compose("SELECT CHANNEL_ID FROM CHANNEL WHERE PROFILE_ID=%1;", profile.profile_id));
588
while (statement.step() == SQLITE_ROW)
590
gint channel_id = statement.get_int(0);
591
if (profile.find_channel(channel_id) == NULL)
593
delete_channel(channel_id);
597
ChannelList& channels = profile.get_channels();
598
for (ChannelList::iterator channel_iterator = channels.begin(); channel_iterator != channels.end(); channel_iterator++)
600
Channel& channel = *channel_iterator;
601
channel.profile_id = profile.profile_id;
602
replace_channel(channel);
606
ProfileList Data::get_all_profiles()
608
ProfileList profiles;
610
Statement statement(database, "SELECT * FROM PROFILE ORDER BY PROFILE_ID");
611
while (statement.step() == SQLITE_ROW)
614
profile.profile_id = statement.get_int(0);
615
profile.name = statement.get_text(1);
617
Statement channel_statement(database,
618
Glib::ustring::compose("SELECT * FROM CHANNEL WHERE PROFILE_ID = %1 ORDER BY SORT_ORDER", profile.profile_id));
619
while (channel_statement.step() == SQLITE_ROW)
623
channel.channel_id = channel_statement.get_int(0);
624
channel.profile_id = channel_statement.get_int(1);
625
channel.name = channel_statement.get_text(2);
626
channel.flags = channel_statement.get_int(3);
627
channel.sort_order = channel_statement.get_int(4);
628
channel.mrl = channel_statement.get_text(5);
629
channel.service_id = channel_statement.get_int(6);
631
channel.frontend_parameters.frequency = channel_statement.get_int(7);
632
channel.frontend_parameters.inversion = (fe_spectral_inversion_t)channel_statement.get_int(8);
634
if (channel.flags & CHANNEL_FLAG_DVB_T)
636
channel.frontend_parameters.u.ofdm.bandwidth = (fe_bandwidth_t)channel_statement.get_int(9);
637
channel.frontend_parameters.u.ofdm.code_rate_HP = (fe_code_rate_t)channel_statement.get_int(10);
638
channel.frontend_parameters.u.ofdm.code_rate_LP = (fe_code_rate_t)channel_statement.get_int(11);
639
channel.frontend_parameters.u.ofdm.constellation = (fe_modulation_t)channel_statement.get_int(12);
640
channel.frontend_parameters.u.ofdm.transmission_mode = (fe_transmit_mode_t)channel_statement.get_int(13);
641
channel.frontend_parameters.u.ofdm.guard_interval = (fe_guard_interval_t)channel_statement.get_int(14);
642
channel.frontend_parameters.u.ofdm.hierarchy_information = (fe_hierarchy_t)channel_statement.get_int(15);
644
else if (channel.flags & CHANNEL_FLAG_DVB_C)
646
channel.frontend_parameters.u.qam.symbol_rate = channel_statement.get_int(16);
647
channel.frontend_parameters.u.qam.fec_inner = (fe_code_rate_t)channel_statement.get_int(17);
648
channel.frontend_parameters.u.qam.modulation = (fe_modulation_t)channel_statement.get_int(18);
650
else if (channel.flags & CHANNEL_FLAG_ATSC)
652
channel.frontend_parameters.u.vsb.modulation = (fe_modulation_t)channel_statement.get_int(18);
654
channel.epg_events.insert(get_epg_events(channel));
655
profile.add_channel(channel);
657
g_debug("Loaded channel: %s", channel.name.c_str());
660
profiles.push_back(profile);
662
g_debug("Loaded profile: %s", profile.name.c_str());
668
void Data::replace_scheduled_recording(ScheduledRecording& scheduled_recording)
670
Glib::ustring fixed_description = scheduled_recording.description;
672
Glib::ustring select_command = Glib::ustring::compose
674
"SELECT * FROM SCHEDULED_RECORDING WHERE "\
675
"((START_TIME >= %1 AND START_TIME <= %2) OR "\
676
"(START_TIME+DURATION >= %1 AND START_TIME+DURATION <= %2) OR "\
677
"(START_TIME <= %1 AND START_TIME+DURATION >= %2)) AND "\
679
scheduled_recording.start_time,
680
scheduled_recording.start_time + scheduled_recording.duration,
681
scheduled_recording.channel_id
684
Statement statement(database, select_command);
685
if (statement.step() == SQLITE_ROW)
687
Glib::ustring message = Glib::ustring::compose
689
_("Failed to save scheduled recording because it conflicts with another scheduled recording called '%1'"),
690
statement.get_text(1)
121
void Statement::set_int_parameter(guint index, int value)
123
sqlite3_bind_int(statement, index, value);
126
void Statement::set_string_parameter(guint index, const Glib::ustring& value)
128
sqlite3_bind_text(statement, index, value.c_str(), -1, NULL);
131
guint Statement::get_parameter_index(const Glib::ustring& name)
133
int index = sqlite3_bind_parameter_index(statement, name.c_str());
136
Glib::ustring message = Glib::ustring::compose("Unknown parameter name '%1'", name);
692
137
throw Exception(message);
695
fix_quotes(fixed_description);
697
Glib::ustring replace_command = Glib::ustring::compose
699
"REPLACE INTO SCHEDULED_RECORDING " \
700
"(SCHEDULED_RECORDING_ID, DESCRIPTION, TYPE, CHANNEL_ID, START_TIME, DURATION) VALUES " \
701
"(%1, '%2', %3, %4, %5, %6);",
702
scheduled_recording.scheduled_recording_id == 0 ? "NULL" : Glib::ustring::compose("%1", scheduled_recording.scheduled_recording_id),
704
scheduled_recording.type,
705
scheduled_recording.channel_id,
706
scheduled_recording.start_time,
707
scheduled_recording.duration
710
execute_non_query(replace_command);
712
if (scheduled_recording.scheduled_recording_id == 0)
714
scheduled_recording.scheduled_recording_id = sqlite3_last_insert_rowid(database);
715
if (scheduled_recording.scheduled_recording_id == 0)
717
throw Exception(_("ASSERT: scheduled_recording.scheduled_recording_id == 0"));
721
g_debug("Scheduled recording ID '%d' saved", scheduled_recording.scheduled_recording_id);
724
ScheduledRecordingList Data::get_scheduled_recordings()
726
ScheduledRecordingList result;
728
Glib::ustring select_command = "SELECT * FROM SCHEDULED_RECORDING ORDER BY START_TIME";
730
Statement statement(database, select_command);
142
void Statement::set_int_parameter(const Glib::ustring& name, int value)
144
set_int_parameter(get_parameter_index(name), value);
147
void Statement::set_string_parameter(const Glib::ustring& name, const Glib::ustring& value)
149
set_string_parameter(get_parameter_index(name), value);
152
Connection::Connection(const Glib::ustring& filename)
154
gboolean database_exists = Gio::File::create_for_path(filename)->query_exists();
156
g_debug("Database '%s' ", database_exists ? "exists" : "does not exist");
157
g_debug("Opening database file '%s'", filename.c_str());
158
if (sqlite3_open(filename.c_str(), &connection) != 0)
160
Glib::ustring message = Glib::ustring::compose(_("Failed to connect to Me TV database '%1'"), filename);
161
throw SQLiteException(connection, message);
164
database_created = !database_exists;
167
Connection::~Connection()
169
if (connection != NULL)
171
sqlite3_close(connection);
176
guint Connection::get_last_insert_rowid()
178
return sqlite3_last_insert_rowid(connection);
181
void SchemaAdapter::initialise_schema()
183
for (Tables::iterator i = schema.tables.begin(); i != schema.tables.end(); i++)
185
Table& table = i->second;
186
initialise_table(table);
190
void SchemaAdapter::initialise_table(Table& table)
192
g_debug("Initialising table '%s'", table.name.c_str());
194
Glib::ustring command = "CREATE TABLE IF NOT EXISTS ";
195
command += table.name;
197
gboolean first_column = true;
198
for (Columns::const_iterator j = table.columns.begin(); j != table.columns.end(); j++)
200
const Column& column = *j;
204
first_column = false;
211
command += column.name;
216
case DATA_TYPE_INTEGER:
217
command += "INTEGER";
219
case DATA_TYPE_STRING:
220
command += Glib::ustring::compose("CHAR(%1)", column.size);
226
if (column.name == table.primary_key)
228
if (column.type != DATA_TYPE_INTEGER)
230
throw Exception(_("Only integers can be primary keys"));
233
command += " PRIMARY KEY AUTOINCREMENT";
237
if (!column.nullable)
239
command += " NOT NULL";
244
for (Constraints::const_iterator j = table.constraints.begin(); j != table.constraints.end(); j++)
246
const Constraint& constraint = *j;
247
if (constraint.type == ConstraintTypeUnique)
249
gboolean first_constraint = true;
250
command += ", UNIQUE (";
251
for (StringList::const_iterator k = constraint.columns.begin(); k != constraint.columns.end(); k++)
253
Glib::ustring column = *k;
255
if (first_constraint)
257
first_constraint = false;
272
Statement statement(connection, command);
276
void SchemaAdapter::drop_schema()
278
for (Tables::const_iterator i = schema.tables.begin(); i != schema.tables.end(); i++)
280
const Table& table = i->second;
282
g_debug("Dropping table '%s'", table.name.c_str());
284
Glib::ustring command = Glib::ustring::compose("DROP TABLE %1", table.name);
285
Statement statement(connection, command);
290
TableAdapter::TableAdapter(Connection& connection, Table& table)
291
: connection(connection), table(table)
293
Glib::ustring fields;
294
Glib::ustring replace_fields;
295
Glib::ustring replace_values;
297
for (Columns::const_iterator j = table.columns.begin(); j != table.columns.end(); j++)
299
const Column& column = *j;
301
if (fields.length() > 0) fields += ", ";
302
if (replace_fields.length() > 0) replace_fields += ", ";
303
if (replace_values.length() > 0) replace_values += ", ";
305
fields += column.name;
306
replace_fields += column.name;
307
replace_values += ":" + column.name;
310
select_command = Glib::ustring::compose("SELECT %1 FROM %2", fields, table.name);
311
replace_command = Glib::ustring::compose("REPLACE INTO %1 (%2) VALUES (%3)", table.name, replace_fields, replace_values);
312
delete_command = Glib::ustring::compose("DELETE FROM %1", table.name);
313
update_command = Glib::ustring::compose("UPDATE %1 SET", table.name);
316
void TableAdapter::replace_rows(DataTable& data_table)
318
Glib::ustring primary_key = data_table.table.primary_key;
320
Statement statement(connection, replace_command);
322
if (data_table.rows.size() > 0)
324
Statement statementBegin(connection, "BEGIN");
325
statementBegin.step();
327
for (Data::Rows::iterator i = data_table.rows.begin(); i != data_table.rows.end(); i++)
331
for (Columns::iterator j = data_table.table.columns.begin(); j != data_table.table.columns.end(); j++)
335
if (column.name != primary_key || row[column.name].int_value != 0)
339
case DATA_TYPE_INTEGER:
340
statement.set_int_parameter(":" + column.name, row[column.name].int_value);
342
case DATA_TYPE_STRING:
343
statement.set_string_parameter(":" + column.name, row[column.name].string_value);
353
if (row.auto_increment != NULL && *row.auto_increment == 0)
355
*(row.auto_increment) = connection.get_last_insert_rowid();
356
g_debug("%s row replaced for id %d",
357
data_table.table.name.c_str(), *(row.auto_increment));
361
g_debug("%s row replaced", data_table.table.name.c_str());
367
Statement statementEnd(connection, "End");
372
DataTable TableAdapter::select_row(guint key)
374
Glib::ustring where = Glib::ustring::compose(
375
"%1 = %2", table.name, table.primary_key, key);
376
return select_rows(where);
379
DataTable TableAdapter::select_rows(const Glib::ustring& where, const Glib::ustring& sort)
381
DataTable data_table(table);
382
Glib::ustring command = select_command;
383
if (where.length() > 0)
385
command += Glib::ustring::compose(" WHERE %1", where);
387
if (sort.length() > 0)
389
command += Glib::ustring::compose(" ORDER BY %1", sort);
392
Statement statement(connection, command);
731
393
while (statement.step() == SQLITE_ROW)
733
ScheduledRecording scheduled_recording;
734
load_scheduled_recording(statement, scheduled_recording);
735
result.push_back(scheduled_recording);
741
void Data::delete_scheduled_recording(guint scheduled_recording_id)
743
Glib::ustring command = Glib::ustring::compose(
744
"DELETE FROM SCHEDULED_RECORDING WHERE SCHEDULED_RECORDING_ID=%1",
745
scheduled_recording_id);
746
execute_non_query(command);
749
void Data::load_scheduled_recording(Statement& statement, ScheduledRecording& scheduled_recording)
751
scheduled_recording.scheduled_recording_id = statement.get_int(0);
752
scheduled_recording.description = statement.get_text(1);
753
scheduled_recording.type = statement.get_int(2);
754
scheduled_recording.channel_id = statement.get_int(3);
755
scheduled_recording.start_time = statement.get_int(4);
756
scheduled_recording.duration = statement.get_int(5);
759
gboolean Data::get_scheduled_recording(guint scheduled_recording_id, ScheduledRecording& scheduled_recording)
761
gboolean result = false;
762
Glib::ustring select_command = Glib::ustring::compose(
763
"SELECT * FROM SCHEDULED_RECORDING WHERE SCHEDULED_RECORDING_ID=%1;",
764
scheduled_recording_id
767
Statement statement(database, select_command);
768
if (statement.step() == SQLITE_ROW)
770
load_scheduled_recording(statement, scheduled_recording);
777
void Data::delete_channel(guint channel_id)
779
execute_non_query(Glib::ustring::compose(
780
"DELETE FROM EPG_EVENT_TEXT WHERE EPG_EVENT_ID IN "\
781
"(SELECT EPG_EVENT_ID FROM EPG_EVENT WHERE CHANNEL_ID=%1);",
783
execute_non_query(Glib::ustring::compose(
784
"DELETE FROM EPG_EVENT WHERE CHANNEL_ID=%1;",
786
execute_non_query(Glib::ustring::compose(
787
"DELETE FROM CHANNEL WHERE CHANNEL_ID=%1;",
789
execute_non_query(Glib::ustring::compose(
790
"DELETE FROM SCHEDULED_RECORDING WHERE CHANNEL_ID=%1;",
794
void Data::delete_old_scheduled_recordings()
796
execute_non_query(Glib::ustring::compose(
797
"DELETE FROM SCHEDULED_RECORDING WHERE (START_TIME+DURATION)<%1;",
801
void Data::delete_old_epg_events()
803
time_t expired_time = convert_to_local_time(time(NULL));
805
execute_non_query(Glib::ustring::compose(
806
"DELETE FROM EPG_EVENT_TEXT WHERE EPG_EVENT_ID IN "\
807
"(SELECT EPG_EVENT_ID FROM EPG_EVENT WHERE (START_TIME+DURATION)<%1);",
809
execute_non_query(Glib::ustring::compose(
810
"DELETE FROM EPG_EVENT WHERE (START_TIME+DURATION)<%1;",
813
g_debug("Expired EPG events cleanup");
818
execute_non_query("VACUUM;");
b'\\ No newline at end of file'
397
for (Columns::const_iterator j = table.columns.begin(); j != table.columns.end(); j++)
399
const Column& column = *j;
403
case DATA_TYPE_INTEGER:
404
row[column.name].int_value = statement.get_int(column.index);
406
case DATA_TYPE_STRING:
407
row[column.name].string_value = statement.get_text(column.index);
414
data_table.rows.push_back(row);
419
void TableAdapter::delete_row(guint key)
421
Glib::ustring where = Glib::ustring::compose("%1 = %2", table.primary_key, key);
425
void TableAdapter::delete_rows(const Glib::ustring& where)
427
Glib::ustring command = delete_command;
428
if (where.length() > 0)
430
command += Glib::ustring::compose(" WHERE %1", where);
432
Statement statement(connection, command);
436
void TableAdapter::update_rows(const Glib::ustring& set, const Glib::ustring& where)
438
DataTable data_table(table);
439
Glib::ustring command = update_command;
440
if (set.length() > 0)
442
command += Glib::ustring::compose(" %1", set);
444
if (where.length() > 0)
446
command += Glib::ustring::compose(" WHERE %1", where);
449
Statement statement(connection, command);
453
void Connection::vacuum()
455
Statement statement(*this, "VACUUM");