Merge pull request #303 from chme/dbinit
Move db init into its own source file
This commit is contained in:
commit
f0e2218a8c
|
@ -79,6 +79,7 @@ forked_daapd_LDADD = -lrt \
|
|||
|
||||
forked_daapd_SOURCES = main.c \
|
||||
db.c db.h \
|
||||
db_init.c db_init.h \
|
||||
db_upgrade.c db_upgrade.h \
|
||||
logger.c logger.h \
|
||||
conffile.c conffile.h \
|
||||
|
|
397
src/db.c
397
src/db.c
|
@ -44,6 +44,7 @@
|
|||
#include "cache.h"
|
||||
#include "misc.h"
|
||||
#include "db.h"
|
||||
#include "db_init.h"
|
||||
#include "db_upgrade.h"
|
||||
|
||||
|
||||
|
@ -4808,398 +4809,6 @@ db_perthread_deinit(void)
|
|||
}
|
||||
|
||||
|
||||
#define T_ADMIN \
|
||||
"CREATE TABLE IF NOT EXISTS admin(" \
|
||||
" key VARCHAR(32) NOT NULL," \
|
||||
" value VARCHAR(32) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_FILES \
|
||||
"CREATE TABLE IF NOT EXISTS files (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" path VARCHAR(4096) NOT NULL," \
|
||||
" fname VARCHAR(255) NOT NULL," \
|
||||
" title VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" artist VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" genre VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
|
||||
" comment VARCHAR(4096) DEFAULT NULL COLLATE DAAP," \
|
||||
" type VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
|
||||
" composer VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" orchestra VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" conductor VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" grouping VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" url VARCHAR(1024) DEFAULT NULL," \
|
||||
" bitrate INTEGER DEFAULT 0," \
|
||||
" samplerate INTEGER DEFAULT 0," \
|
||||
" song_length INTEGER DEFAULT 0," \
|
||||
" file_size INTEGER DEFAULT 0," \
|
||||
" year INTEGER DEFAULT 0," \
|
||||
" track INTEGER DEFAULT 0," \
|
||||
" total_tracks INTEGER DEFAULT 0," \
|
||||
" disc INTEGER DEFAULT 0," \
|
||||
" total_discs INTEGER DEFAULT 0," \
|
||||
" bpm INTEGER DEFAULT 0," \
|
||||
" compilation INTEGER DEFAULT 0," \
|
||||
" artwork INTEGER DEFAULT 0," \
|
||||
" rating INTEGER DEFAULT 0," \
|
||||
" play_count INTEGER DEFAULT 0," \
|
||||
" seek INTEGER DEFAULT 0," \
|
||||
" data_kind INTEGER DEFAULT 0," \
|
||||
" item_kind INTEGER DEFAULT 0," \
|
||||
" description INTEGER DEFAULT 0," \
|
||||
" time_added INTEGER DEFAULT 0," \
|
||||
" time_modified INTEGER DEFAULT 0," \
|
||||
" time_played INTEGER DEFAULT 0," \
|
||||
" db_timestamp INTEGER DEFAULT 0," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" sample_count INTEGER DEFAULT 0," \
|
||||
" codectype VARCHAR(5) DEFAULT NULL," \
|
||||
" idx INTEGER NOT NULL," \
|
||||
" has_video INTEGER DEFAULT 0," \
|
||||
" contentrating INTEGER DEFAULT 0," \
|
||||
" bits_per_sample INTEGER DEFAULT 0," \
|
||||
" album_artist VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" media_kind INTEGER NOT NULL," \
|
||||
" tv_series_name VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_episode_num_str VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_network_name VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_episode_sort INTEGER NOT NULL," \
|
||||
" tv_season_num INTEGER NOT NULL," \
|
||||
" songartistid INTEGER NOT NULL," \
|
||||
" songalbumid INTEGER NOT NULL," \
|
||||
" title_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" composer_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" virtual_path VARCHAR(4096) DEFAULT NULL," \
|
||||
" directory_id INTEGER DEFAULT 0," \
|
||||
" date_released INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define T_PL \
|
||||
"CREATE TABLE IF NOT EXISTS playlists (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" title VARCHAR(255) NOT NULL COLLATE DAAP," \
|
||||
" type INTEGER NOT NULL," \
|
||||
" query VARCHAR(1024)," \
|
||||
" db_timestamp INTEGER NOT NULL," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" path VARCHAR(4096)," \
|
||||
" idx INTEGER NOT NULL," \
|
||||
" special_id INTEGER DEFAULT 0," \
|
||||
" virtual_path VARCHAR(4096)," \
|
||||
" parent_id INTEGER DEFAULT 0," \
|
||||
" directory_id INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define T_PLITEMS \
|
||||
"CREATE TABLE IF NOT EXISTS playlistitems (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" playlistid INTEGER NOT NULL," \
|
||||
" filepath VARCHAR(4096) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_GROUPS \
|
||||
"CREATE TABLE IF NOT EXISTS groups (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" type INTEGER NOT NULL," \
|
||||
" name VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" persistentid INTEGER NOT NULL," \
|
||||
"CONSTRAINT groups_type_unique_persistentid UNIQUE (type, persistentid)" \
|
||||
");"
|
||||
|
||||
#define T_PAIRINGS \
|
||||
"CREATE TABLE IF NOT EXISTS pairings(" \
|
||||
" remote VARCHAR(64) PRIMARY KEY NOT NULL," \
|
||||
" name VARCHAR(255) NOT NULL," \
|
||||
" guid VARCHAR(16) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_SPEAKERS \
|
||||
"CREATE TABLE IF NOT EXISTS speakers(" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" selected INTEGER NOT NULL," \
|
||||
" volume INTEGER NOT NULL," \
|
||||
" name VARCHAR(255) DEFAULT NULL" \
|
||||
");"
|
||||
|
||||
#define T_INOTIFY \
|
||||
"CREATE TABLE IF NOT EXISTS inotify (" \
|
||||
" wd INTEGER PRIMARY KEY NOT NULL," \
|
||||
" cookie INTEGER NOT NULL," \
|
||||
" path VARCHAR(4096) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_DIRECTORIES \
|
||||
"CREATE TABLE IF NOT EXISTS directories (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" virtual_path VARCHAR(4096) NOT NULL," \
|
||||
" db_timestamp INTEGER DEFAULT 0," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" parent_id INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define TRG_GROUPS_INSERT_FILES \
|
||||
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
|
||||
" BEGIN" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
|
||||
" END;"
|
||||
|
||||
#define TRG_GROUPS_UPDATE_FILES \
|
||||
"CREATE TRIGGER update_groups_update_file AFTER UPDATE OF songalbumid ON files FOR EACH ROW" \
|
||||
" BEGIN" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
|
||||
" END;"
|
||||
|
||||
#define Q_PL1 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(1, 'Library', 0, '1 = 1', 0, '', 0, 0);"
|
||||
|
||||
#define Q_PL2 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(2, 'Music', 0, 'f.media_kind = 1', 0, '', 0, 6);"
|
||||
|
||||
#define Q_PL3 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(3, 'Movies', 0, 'f.media_kind = 2', 0, '', 0, 4);"
|
||||
|
||||
#define Q_PL4 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(4, 'TV Shows', 0, 'f.media_kind = 64', 0, '', 0, 5);"
|
||||
|
||||
#define Q_PL5 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(5, 'Podcasts', 0, 'f.media_kind = 4', 0, '', 0, 1);"
|
||||
|
||||
#define Q_PL6 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(6, 'Audiobooks', 0, 'f.media_kind = 8', 0, '', 0, 7);"
|
||||
|
||||
/* These are the remaining automatically-created iTunes playlists, but
|
||||
* their query is unknown
|
||||
" VALUES(6, 'iTunes U', 0, 'media_kind = 256', 0, '', 0, 13);"
|
||||
" VALUES(8, 'Purchased', 0, 'media_kind = 1024', 0, '', 0, 8);"
|
||||
*/
|
||||
|
||||
|
||||
#define Q_DIR1 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (1, '/', 0, 0, 0);"
|
||||
#define Q_DIR2 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (2, '/file:', 0, 0, 1);"
|
||||
#define Q_DIR3 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (3, '/http:', 0, 0, 1);"
|
||||
#define Q_DIR4 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
|
||||
|
||||
/* Rule of thumb: Will the current version of forked-daapd work with the new
|
||||
* version of the database? If yes, then it is a minor upgrade, if no, then it
|
||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||
* forked-daapd after the database was upgraded. */
|
||||
#define SCHEMA_VERSION_MAJOR 19
|
||||
#define SCHEMA_VERSION_MINOR 00
|
||||
#define Q_SCVER_MAJOR \
|
||||
"INSERT INTO admin (key, value) VALUES ('schema_version_major', '19');"
|
||||
#define Q_SCVER_MINOR \
|
||||
"INSERT INTO admin (key, value) VALUES ('schema_version_minor', '00');"
|
||||
|
||||
struct db_init_query {
|
||||
char *query;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
static const struct db_init_query db_init_table_queries[] =
|
||||
{
|
||||
{ T_ADMIN, "create table admin" },
|
||||
{ T_FILES, "create table files" },
|
||||
{ T_PL, "create table playlists" },
|
||||
{ T_PLITEMS, "create table playlistitems" },
|
||||
{ T_GROUPS, "create table groups" },
|
||||
{ T_PAIRINGS, "create table pairings" },
|
||||
{ T_SPEAKERS, "create table speakers" },
|
||||
{ T_INOTIFY, "create table inotify" },
|
||||
{ T_DIRECTORIES, "create table directories" },
|
||||
|
||||
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
|
||||
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_file" },
|
||||
|
||||
{ Q_PL1, "create default playlist" },
|
||||
{ Q_PL2, "create default smart playlist 'Music'" },
|
||||
{ Q_PL3, "create default smart playlist 'Movies'" },
|
||||
{ Q_PL4, "create default smart playlist 'TV Shows'" },
|
||||
{ Q_PL5, "create default smart playlist 'Podcasts'" },
|
||||
{ Q_PL6, "create default smart playlist 'Audiobooks'" },
|
||||
{ Q_DIR1, "create default root directory '/'" },
|
||||
{ Q_DIR2, "create default base directory '/file:'" },
|
||||
{ Q_DIR3, "create default base directory '/http:'" },
|
||||
{ Q_DIR4, "create default base directory '/spotify:'" },
|
||||
|
||||
{ Q_SCVER_MAJOR, "set schema version major" },
|
||||
{ Q_SCVER_MINOR, "set schema version minor" },
|
||||
};
|
||||
|
||||
|
||||
/* Indices must be prefixed with idx_ for db_drop_indices() to id them */
|
||||
|
||||
#define I_RESCAN \
|
||||
"CREATE INDEX IF NOT EXISTS idx_rescan ON files(path, db_timestamp);"
|
||||
|
||||
#define I_SONGARTISTID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_sari ON files(songartistid);"
|
||||
|
||||
/* Used by Q_GROUP_ALBUMS */
|
||||
#define I_SONGALBUMID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_sali ON files(songalbumid, disabled, media_kind, album_sort, disc, track);"
|
||||
|
||||
/* Used by Q_GROUP_ARTISTS */
|
||||
#define I_STATEMKINDSARI \
|
||||
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sari ON files(disabled, media_kind, songartistid);"
|
||||
|
||||
#define I_STATEMKINDSALI \
|
||||
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sali ON files(disabled, media_kind, songalbumid);"
|
||||
|
||||
#define I_ARTIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_artist ON files(artist, artist_sort);"
|
||||
|
||||
#define I_ALBUMARTIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);"
|
||||
|
||||
/* Used by Q_BROWSE_COMPOSERS */
|
||||
#define I_COMPOSER \
|
||||
"CREATE INDEX IF NOT EXISTS idx_composer ON files(disabled, media_kind, composer_sort);"
|
||||
|
||||
/* Used by Q_BROWSE_GENRES */
|
||||
#define I_GENRE \
|
||||
"CREATE INDEX IF NOT EXISTS idx_genre ON files(disabled, media_kind, genre);"
|
||||
|
||||
/* Used by Q_PLITEMS for smart playlists */
|
||||
#define I_TITLE \
|
||||
"CREATE INDEX IF NOT EXISTS idx_title ON files(disabled, media_kind, title_sort);"
|
||||
|
||||
#define I_ALBUM \
|
||||
"CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);"
|
||||
|
||||
#define I_FILELIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_filelist ON files(disabled, virtual_path, time_modified);"
|
||||
|
||||
#define I_FILE_DIR \
|
||||
"CREATE INDEX IF NOT EXISTS idx_file_dir ON files(disabled, directory_id);"
|
||||
|
||||
#define I_PL_PATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_path ON playlists(path);"
|
||||
|
||||
#define I_PL_DISABLED \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_disabled ON playlists(disabled, type, virtual_path, db_timestamp);"
|
||||
|
||||
#define I_PL_DIR \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_dir ON files(disabled, directory_id);"
|
||||
|
||||
#define I_FILEPATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_filepath ON playlistitems(filepath ASC);"
|
||||
|
||||
#define I_PLITEMID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, filepath);"
|
||||
|
||||
#define I_GRP_PERSIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_grp_persist ON groups(persistentid);"
|
||||
|
||||
#define I_PAIRING \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pairingguid ON pairings(guid);"
|
||||
|
||||
#define I_DIR_VPATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_dir_vpath ON directories(disabled, virtual_path);"
|
||||
|
||||
#define I_DIR_PARENT \
|
||||
"CREATE INDEX IF NOT EXISTS idx_dir_parentid ON directories(parent_id);"
|
||||
|
||||
static const struct db_init_query db_init_index_queries[] =
|
||||
{
|
||||
{ I_RESCAN, "create rescan index" },
|
||||
{ I_SONGARTISTID, "create songartistid index" },
|
||||
{ I_SONGALBUMID, "create songalbumid index" },
|
||||
{ I_STATEMKINDSARI, "create state/mkind/sari index" },
|
||||
{ I_STATEMKINDSALI, "create state/mkind/sali index" },
|
||||
|
||||
{ I_ARTIST, "create artist index" },
|
||||
{ I_ALBUMARTIST, "create album_artist index" },
|
||||
{ I_COMPOSER, "create composer index" },
|
||||
{ I_GENRE, "create genre index" },
|
||||
{ I_TITLE, "create title index" },
|
||||
{ I_ALBUM, "create album index" },
|
||||
{ I_FILELIST, "create filelist index" },
|
||||
{ I_FILE_DIR, "create file dir index" },
|
||||
|
||||
{ I_PL_PATH, "create playlist path index" },
|
||||
{ I_PL_DISABLED, "create playlist state index" },
|
||||
{ I_PL_DIR, "create playlist dir index" },
|
||||
|
||||
{ I_FILEPATH, "create file path index" },
|
||||
{ I_PLITEMID, "create playlist id index" },
|
||||
|
||||
{ I_GRP_PERSIST, "create groups persistentid index" },
|
||||
|
||||
{ I_PAIRING, "create pairing guid index" },
|
||||
|
||||
{ I_DIR_VPATH, "create directories disabled_virtualpath index" },
|
||||
{ I_DIR_PARENT, "create directories parentid index" },
|
||||
};
|
||||
|
||||
static int
|
||||
db_create_indices(void)
|
||||
{
|
||||
char *errmsg;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < (sizeof(db_init_index_queries) / sizeof(db_init_index_queries[0])); i++)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DB, "DB init index query: %s\n", db_init_index_queries[i].desc);
|
||||
|
||||
ret = sqlite3_exec(hdl, db_init_index_queries[i].query, NULL, NULL, &errmsg);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
db_create_tables(void)
|
||||
{
|
||||
char *errmsg;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < (sizeof(db_init_table_queries) / sizeof(db_init_table_queries[0])); i++)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DB, "DB init table query: %s\n", db_init_table_queries[i].desc);
|
||||
|
||||
ret = sqlite3_exec(hdl, db_init_table_queries[i].query, NULL, NULL, &errmsg);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = db_create_indices();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
|
@ -5278,7 +4887,7 @@ db_check_version(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = db_create_indices();
|
||||
ret = db_init_indices(hdl);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Database upgrade errored out, rolling back changes ...\n");
|
||||
|
@ -5373,7 +4982,7 @@ db_init(void)
|
|||
{
|
||||
DPRINTF(E_LOG, L_DB, "Could not check database version, trying DB init\n");
|
||||
|
||||
ret = db_create_tables();
|
||||
ret = db_init_tables(hdl);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "Could not create tables\n");
|
||||
|
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011 Julien BLACHE <jb@jblache.org>
|
||||
* Copyright (C) 2010 Kai Elwert <elwertk@googlemail.com>
|
||||
* Copyright (C) 2016 Christian Meffert <christian.meffert@googlemail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "db_init.h"
|
||||
#include "logger.h"
|
||||
|
||||
|
||||
#define T_ADMIN \
|
||||
"CREATE TABLE IF NOT EXISTS admin(" \
|
||||
" key VARCHAR(32) NOT NULL," \
|
||||
" value VARCHAR(32) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_FILES \
|
||||
"CREATE TABLE IF NOT EXISTS files (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" path VARCHAR(4096) NOT NULL," \
|
||||
" fname VARCHAR(255) NOT NULL," \
|
||||
" title VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" artist VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" genre VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
|
||||
" comment VARCHAR(4096) DEFAULT NULL COLLATE DAAP," \
|
||||
" type VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
|
||||
" composer VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" orchestra VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" conductor VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" grouping VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" url VARCHAR(1024) DEFAULT NULL," \
|
||||
" bitrate INTEGER DEFAULT 0," \
|
||||
" samplerate INTEGER DEFAULT 0," \
|
||||
" song_length INTEGER DEFAULT 0," \
|
||||
" file_size INTEGER DEFAULT 0," \
|
||||
" year INTEGER DEFAULT 0," \
|
||||
" track INTEGER DEFAULT 0," \
|
||||
" total_tracks INTEGER DEFAULT 0," \
|
||||
" disc INTEGER DEFAULT 0," \
|
||||
" total_discs INTEGER DEFAULT 0," \
|
||||
" bpm INTEGER DEFAULT 0," \
|
||||
" compilation INTEGER DEFAULT 0," \
|
||||
" artwork INTEGER DEFAULT 0," \
|
||||
" rating INTEGER DEFAULT 0," \
|
||||
" play_count INTEGER DEFAULT 0," \
|
||||
" seek INTEGER DEFAULT 0," \
|
||||
" data_kind INTEGER DEFAULT 0," \
|
||||
" item_kind INTEGER DEFAULT 0," \
|
||||
" description INTEGER DEFAULT 0," \
|
||||
" time_added INTEGER DEFAULT 0," \
|
||||
" time_modified INTEGER DEFAULT 0," \
|
||||
" time_played INTEGER DEFAULT 0," \
|
||||
" db_timestamp INTEGER DEFAULT 0," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" sample_count INTEGER DEFAULT 0," \
|
||||
" codectype VARCHAR(5) DEFAULT NULL," \
|
||||
" idx INTEGER NOT NULL," \
|
||||
" has_video INTEGER DEFAULT 0," \
|
||||
" contentrating INTEGER DEFAULT 0," \
|
||||
" bits_per_sample INTEGER DEFAULT 0," \
|
||||
" album_artist VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" media_kind INTEGER NOT NULL," \
|
||||
" tv_series_name VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_episode_num_str VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_network_name VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" tv_episode_sort INTEGER NOT NULL," \
|
||||
" tv_season_num INTEGER NOT NULL," \
|
||||
" songartistid INTEGER NOT NULL," \
|
||||
" songalbumid INTEGER NOT NULL," \
|
||||
" title_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" composer_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
|
||||
" virtual_path VARCHAR(4096) DEFAULT NULL," \
|
||||
" directory_id INTEGER DEFAULT 0," \
|
||||
" date_released INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define T_PL \
|
||||
"CREATE TABLE IF NOT EXISTS playlists (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" title VARCHAR(255) NOT NULL COLLATE DAAP," \
|
||||
" type INTEGER NOT NULL," \
|
||||
" query VARCHAR(1024)," \
|
||||
" db_timestamp INTEGER NOT NULL," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" path VARCHAR(4096)," \
|
||||
" idx INTEGER NOT NULL," \
|
||||
" special_id INTEGER DEFAULT 0," \
|
||||
" virtual_path VARCHAR(4096)," \
|
||||
" parent_id INTEGER DEFAULT 0," \
|
||||
" directory_id INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define T_PLITEMS \
|
||||
"CREATE TABLE IF NOT EXISTS playlistitems (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" playlistid INTEGER NOT NULL," \
|
||||
" filepath VARCHAR(4096) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_GROUPS \
|
||||
"CREATE TABLE IF NOT EXISTS groups (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" type INTEGER NOT NULL," \
|
||||
" name VARCHAR(1024) NOT NULL COLLATE DAAP," \
|
||||
" persistentid INTEGER NOT NULL," \
|
||||
"CONSTRAINT groups_type_unique_persistentid UNIQUE (type, persistentid)" \
|
||||
");"
|
||||
|
||||
#define T_PAIRINGS \
|
||||
"CREATE TABLE IF NOT EXISTS pairings(" \
|
||||
" remote VARCHAR(64) PRIMARY KEY NOT NULL," \
|
||||
" name VARCHAR(255) NOT NULL," \
|
||||
" guid VARCHAR(16) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_SPEAKERS \
|
||||
"CREATE TABLE IF NOT EXISTS speakers(" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" selected INTEGER NOT NULL," \
|
||||
" volume INTEGER NOT NULL," \
|
||||
" name VARCHAR(255) DEFAULT NULL" \
|
||||
");"
|
||||
|
||||
#define T_INOTIFY \
|
||||
"CREATE TABLE IF NOT EXISTS inotify (" \
|
||||
" wd INTEGER PRIMARY KEY NOT NULL," \
|
||||
" cookie INTEGER NOT NULL," \
|
||||
" path VARCHAR(4096) NOT NULL" \
|
||||
");"
|
||||
|
||||
#define T_DIRECTORIES \
|
||||
"CREATE TABLE IF NOT EXISTS directories (" \
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" virtual_path VARCHAR(4096) NOT NULL," \
|
||||
" db_timestamp INTEGER DEFAULT 0," \
|
||||
" disabled INTEGER DEFAULT 0," \
|
||||
" parent_id INTEGER DEFAULT 0" \
|
||||
");"
|
||||
|
||||
#define TRG_GROUPS_INSERT_FILES \
|
||||
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
|
||||
" BEGIN" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
|
||||
" END;"
|
||||
|
||||
#define TRG_GROUPS_UPDATE_FILES \
|
||||
"CREATE TRIGGER update_groups_update_file AFTER UPDATE OF songalbumid ON files FOR EACH ROW" \
|
||||
" BEGIN" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
|
||||
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
|
||||
" END;"
|
||||
|
||||
#define Q_PL1 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(1, 'Library', 0, '1 = 1', 0, '', 0, 0);"
|
||||
|
||||
#define Q_PL2 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(2, 'Music', 0, 'f.media_kind = 1', 0, '', 0, 6);"
|
||||
|
||||
#define Q_PL3 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(3, 'Movies', 0, 'f.media_kind = 2', 0, '', 0, 4);"
|
||||
|
||||
#define Q_PL4 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(4, 'TV Shows', 0, 'f.media_kind = 64', 0, '', 0, 5);"
|
||||
|
||||
#define Q_PL5 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(5, 'Podcasts', 0, 'f.media_kind = 4', 0, '', 0, 1);"
|
||||
|
||||
#define Q_PL6 \
|
||||
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
|
||||
" VALUES(6, 'Audiobooks', 0, 'f.media_kind = 8', 0, '', 0, 7);"
|
||||
|
||||
/* These are the remaining automatically-created iTunes playlists, but
|
||||
* their query is unknown
|
||||
" VALUES(6, 'iTunes U', 0, 'media_kind = 256', 0, '', 0, 13);"
|
||||
" VALUES(8, 'Purchased', 0, 'media_kind = 1024', 0, '', 0, 8);"
|
||||
*/
|
||||
|
||||
|
||||
#define Q_DIR1 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (1, '/', 0, 0, 0);"
|
||||
#define Q_DIR2 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (2, '/file:', 0, 0, 1);"
|
||||
#define Q_DIR3 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (3, '/http:', 0, 0, 1);"
|
||||
#define Q_DIR4 \
|
||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
|
||||
|
||||
#define Q_SCVER_MAJOR \
|
||||
"INSERT INTO admin (key, value) VALUES ('schema_version_major', '%d');"
|
||||
#define Q_SCVER_MINOR \
|
||||
"INSERT INTO admin (key, value) VALUES ('schema_version_minor', '%02d');"
|
||||
|
||||
struct db_init_query {
|
||||
char *query;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
static const struct db_init_query db_init_table_queries[] =
|
||||
{
|
||||
{ T_ADMIN, "create table admin" },
|
||||
{ T_FILES, "create table files" },
|
||||
{ T_PL, "create table playlists" },
|
||||
{ T_PLITEMS, "create table playlistitems" },
|
||||
{ T_GROUPS, "create table groups" },
|
||||
{ T_PAIRINGS, "create table pairings" },
|
||||
{ T_SPEAKERS, "create table speakers" },
|
||||
{ T_INOTIFY, "create table inotify" },
|
||||
{ T_DIRECTORIES, "create table directories" },
|
||||
|
||||
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
|
||||
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_file" },
|
||||
|
||||
{ Q_PL1, "create default playlist" },
|
||||
{ Q_PL2, "create default smart playlist 'Music'" },
|
||||
{ Q_PL3, "create default smart playlist 'Movies'" },
|
||||
{ Q_PL4, "create default smart playlist 'TV Shows'" },
|
||||
{ Q_PL5, "create default smart playlist 'Podcasts'" },
|
||||
{ Q_PL6, "create default smart playlist 'Audiobooks'" },
|
||||
{ Q_DIR1, "create default root directory '/'" },
|
||||
{ Q_DIR2, "create default base directory '/file:'" },
|
||||
{ Q_DIR3, "create default base directory '/http:'" },
|
||||
{ Q_DIR4, "create default base directory '/spotify:'" },
|
||||
};
|
||||
|
||||
|
||||
/* Indices must be prefixed with idx_ for db_drop_indices() to id them */
|
||||
|
||||
#define I_RESCAN \
|
||||
"CREATE INDEX IF NOT EXISTS idx_rescan ON files(path, db_timestamp);"
|
||||
|
||||
#define I_SONGARTISTID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_sari ON files(songartistid);"
|
||||
|
||||
/* Used by Q_GROUP_ALBUMS */
|
||||
#define I_SONGALBUMID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_sali ON files(songalbumid, disabled, media_kind, album_sort, disc, track);"
|
||||
|
||||
/* Used by Q_GROUP_ARTISTS */
|
||||
#define I_STATEMKINDSARI \
|
||||
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sari ON files(disabled, media_kind, songartistid);"
|
||||
|
||||
#define I_STATEMKINDSALI \
|
||||
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sali ON files(disabled, media_kind, songalbumid);"
|
||||
|
||||
#define I_ARTIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_artist ON files(artist, artist_sort);"
|
||||
|
||||
#define I_ALBUMARTIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);"
|
||||
|
||||
/* Used by Q_BROWSE_COMPOSERS */
|
||||
#define I_COMPOSER \
|
||||
"CREATE INDEX IF NOT EXISTS idx_composer ON files(disabled, media_kind, composer_sort);"
|
||||
|
||||
/* Used by Q_BROWSE_GENRES */
|
||||
#define I_GENRE \
|
||||
"CREATE INDEX IF NOT EXISTS idx_genre ON files(disabled, media_kind, genre);"
|
||||
|
||||
/* Used by Q_PLITEMS for smart playlists */
|
||||
#define I_TITLE \
|
||||
"CREATE INDEX IF NOT EXISTS idx_title ON files(disabled, media_kind, title_sort);"
|
||||
|
||||
#define I_ALBUM \
|
||||
"CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);"
|
||||
|
||||
#define I_FILELIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_filelist ON files(disabled, virtual_path, time_modified);"
|
||||
|
||||
#define I_FILE_DIR \
|
||||
"CREATE INDEX IF NOT EXISTS idx_file_dir ON files(disabled, directory_id);"
|
||||
|
||||
#define I_PL_PATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_path ON playlists(path);"
|
||||
|
||||
#define I_PL_DISABLED \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_disabled ON playlists(disabled, type, virtual_path, db_timestamp);"
|
||||
|
||||
#define I_PL_DIR \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pl_dir ON files(disabled, directory_id);"
|
||||
|
||||
#define I_FILEPATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_filepath ON playlistitems(filepath ASC);"
|
||||
|
||||
#define I_PLITEMID \
|
||||
"CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, filepath);"
|
||||
|
||||
#define I_GRP_PERSIST \
|
||||
"CREATE INDEX IF NOT EXISTS idx_grp_persist ON groups(persistentid);"
|
||||
|
||||
#define I_PAIRING \
|
||||
"CREATE INDEX IF NOT EXISTS idx_pairingguid ON pairings(guid);"
|
||||
|
||||
#define I_DIR_VPATH \
|
||||
"CREATE INDEX IF NOT EXISTS idx_dir_vpath ON directories(disabled, virtual_path);"
|
||||
|
||||
#define I_DIR_PARENT \
|
||||
"CREATE INDEX IF NOT EXISTS idx_dir_parentid ON directories(parent_id);"
|
||||
|
||||
static const struct db_init_query db_init_index_queries[] =
|
||||
{
|
||||
{ I_RESCAN, "create rescan index" },
|
||||
{ I_SONGARTISTID, "create songartistid index" },
|
||||
{ I_SONGALBUMID, "create songalbumid index" },
|
||||
{ I_STATEMKINDSARI, "create state/mkind/sari index" },
|
||||
{ I_STATEMKINDSALI, "create state/mkind/sali index" },
|
||||
|
||||
{ I_ARTIST, "create artist index" },
|
||||
{ I_ALBUMARTIST, "create album_artist index" },
|
||||
{ I_COMPOSER, "create composer index" },
|
||||
{ I_GENRE, "create genre index" },
|
||||
{ I_TITLE, "create title index" },
|
||||
{ I_ALBUM, "create album index" },
|
||||
{ I_FILELIST, "create filelist index" },
|
||||
{ I_FILE_DIR, "create file dir index" },
|
||||
|
||||
{ I_PL_PATH, "create playlist path index" },
|
||||
{ I_PL_DISABLED, "create playlist state index" },
|
||||
{ I_PL_DIR, "create playlist dir index" },
|
||||
|
||||
{ I_FILEPATH, "create file path index" },
|
||||
{ I_PLITEMID, "create playlist id index" },
|
||||
|
||||
{ I_GRP_PERSIST, "create groups persistentid index" },
|
||||
|
||||
{ I_PAIRING, "create pairing guid index" },
|
||||
|
||||
{ I_DIR_VPATH, "create directories disabled_virtualpath index" },
|
||||
{ I_DIR_PARENT, "create directories parentid index" },
|
||||
};
|
||||
|
||||
int
|
||||
db_init_indices(sqlite3 *hdl)
|
||||
{
|
||||
char *errmsg;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < (sizeof(db_init_index_queries) / sizeof(db_init_index_queries[0])); i++)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DB, "DB init index query: %s\n", db_init_index_queries[i].desc);
|
||||
|
||||
ret = sqlite3_exec(hdl, db_init_index_queries[i].query, NULL, NULL, &errmsg);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
db_init_tables(sqlite3 *hdl)
|
||||
{
|
||||
char *query;
|
||||
char *errmsg;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < (sizeof(db_init_table_queries) / sizeof(db_init_table_queries[0])); i++)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DB, "DB init table query: %s\n", db_init_table_queries[i].desc);
|
||||
|
||||
ret = sqlite3_exec(hdl, db_init_table_queries[i].query, NULL, NULL, &errmsg);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(Q_SCVER_MAJOR, SCHEMA_VERSION_MAJOR);
|
||||
DPRINTF(E_DBG, L_DB, "DB init table query: %s\n", query);
|
||||
|
||||
ret = sqlite3_exec(hdl, query, NULL, NULL, &errmsg);
|
||||
sqlite3_free(query);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
query = sqlite3_mprintf(Q_SCVER_MINOR, SCHEMA_VERSION_MINOR);
|
||||
DPRINTF(E_DBG, L_DB, "DB init table query: %s\n", query);
|
||||
|
||||
ret = sqlite3_exec(hdl, query, NULL, NULL, &errmsg);
|
||||
sqlite3_free(query);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DB, "DB init error: %s\n", errmsg);
|
||||
sqlite3_free(errmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = db_init_indices(hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Christian Meffert <christian.meffert@googlemail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SRC_DB_INIT_H_
|
||||
#define SRC_DB_INIT_H_
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
/* Rule of thumb: Will the current version of forked-daapd work with the new
|
||||
* version of the database? If yes, then it is a minor upgrade, if no, then it
|
||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||
* forked-daapd after the database was upgraded. */
|
||||
#define SCHEMA_VERSION_MAJOR 19
|
||||
#define SCHEMA_VERSION_MINOR 00
|
||||
|
||||
int
|
||||
db_init_indices(sqlite3 *hdl);
|
||||
|
||||
int
|
||||
db_init_tables(sqlite3 *hdl);
|
||||
|
||||
#endif /* SRC_DB_INIT_H_ */
|
Loading…
Reference in New Issue