From: Tomas Mlcoch Date: Tue, 26 Jun 2012 11:14:38 +0000 (+0200) Subject: Add SQLite module X-Git-Tag: upstream/0.2.1~371 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=31035478a3eb3b04f937e82fb4711bdf37e3ddf9;p=services%2Fcreaterepo_c.git Add SQLite module --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c254fc..d086ad6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ find_package(LibXml2 REQUIRED) find_package(Libmagic REQUIRED) find_package(CURL REQUIRED) find_package(LZMA REQUIRED) +find_package(Sqlite3 REQUIRED) # Check libraries @@ -70,6 +71,10 @@ IF (NOT LZMA_FOUND) MESSAGE(FATAL_ERROR "No LZMA (xz) library installed") ENDIF (NOT LZMA_FOUND) +IF (NOT SQLITE3_FOUND) + MESSAGE(FATAL_ERROR "No Sqlite3 library installed") +ENDIF (NOT SQLITE3_FOUND) + # Add include dirs include_directories(${GLIB2_INCLUDE_DIRS}) diff --git a/cmake/Modules/FindSqlite3.cmake b/cmake/Modules/FindSqlite3.cmake new file mode 100644 index 0000000..0eccec2 --- /dev/null +++ b/cmake/Modules/FindSqlite3.cmake @@ -0,0 +1,56 @@ +# - find Sqlite 3 +# SQLITE3_INCLUDE_DIR - Where to find Sqlite 3 header files (directory) +# SQLITE3_LIBRARIES - Sqlite 3 libraries +# SQLITE3_LIBRARY_RELEASE - Where the release library is +# SQLITE3_LIBRARY_DEBUG - Where the debug library is +# SQLITE3_FOUND - Set to TRUE if we found everything (library, includes and executable) + +# Copyright (c) 2010 Pau Garcia i Quiles, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# Generated by CModuler, a CMake Module Generator - http://gitorious.org/cmoduler + +IF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG ) + SET(SQLITE3_FIND_QUIETLY TRUE) +ENDIF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG ) + +FIND_PATH( SQLITE3_INCLUDE_DIR sqlite3.h ) + +FIND_LIBRARY(SQLITE3_LIBRARY_RELEASE NAMES sqlite3 ) + +FIND_LIBRARY(SQLITE3_LIBRARY_DEBUG NAMES sqlite3 sqlite3d HINTS /usr/lib/debug/usr/lib/ ) + +IF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR ) + SET( SQLITE3_FOUND TRUE ) +ENDIF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR ) + +IF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) + # if the generator supports configuration types then set + # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value + IF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) + SET( SQLITE3_LIBRARIES optimized ${SQLITE3_LIBRARY_RELEASE} debug ${SQLITE3_LIBRARY_DEBUG} ) + ELSE( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) + # if there are no configuration types and CMAKE_BUILD_TYPE has no value + # then just use the release libraries + SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} ) + ENDIF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) +ELSEIF( SQLITE3_LIBRARY_RELEASE ) + SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} ) +ELSE( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) + SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_DEBUG} ) +ENDIF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) + +IF( SQLITE3_FOUND ) + IF( NOT SQLITE3_FIND_QUIETLY ) + MESSAGE( STATUS "Found Sqlite3 header file in ${SQLITE3_INCLUDE_DIR}") + MESSAGE( STATUS "Found Sqlite3 libraries: ${SQLITE3_LIBRARIES}") + ENDIF( NOT SQLITE3_FIND_QUIETLY ) +ELSE(SQLITE3_FOUND) + IF( SQLITE3_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Could not find Sqlite3" ) + ELSE( SQLITE3_FIND_REQUIRED) + MESSAGE( STATUS "Optional package Sqlite3 was not found" ) + ENDIF( SQLITE3_FIND_REQUIRED) +ENDIF(SQLITE3_FOUND) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 477205f..6f01776 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ SET (createrepo_c_SRCS compression_wrapper.c load_metadata.c misc.c package.c parsehdr.c parsepkg.c repomd.c xml_dump.c xml_dump_filelists.c xml_dump_other.c xml_dump_primary.c - locate_metadata.c) + locate_metadata.c sqlite.c) ADD_LIBRARY(libcreaterepo_c SHARED ${createrepo_c_SRCS}) TARGET_LINK_LIBRARIES(libcreaterepo_c ${ZLIB_LIBRARY}) @@ -13,6 +13,7 @@ TARGET_LINK_LIBRARIES(libcreaterepo_c ${LIBXML2_LIBRARIES}) TARGET_LINK_LIBRARIES(libcreaterepo_c ${EXPAT_LIBRARIES}) TARGET_LINK_LIBRARIES(libcreaterepo_c ${CURL_LIBRARY}) TARGET_LINK_LIBRARIES(libcreaterepo_c ${LZMA_LIBRARIES}) +TARGET_LINK_LIBRARIES(libcreaterepo_c ${SQLITE3_LIBRARIES}) SET_TARGET_PROPERTIES(libcreaterepo_c PROPERTIES OUTPUT_NAME "createrepo_c" SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR} VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") diff --git a/src/sqlite.c b/src/sqlite.c new file mode 100644 index 0000000..4a1cf80 --- /dev/null +++ b/src/sqlite.c @@ -0,0 +1,1261 @@ +/* createrepo_c - Library of routines for manipulation with repodata + * Copyright (C) 2012 Tomas Mlcoch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "logging.h" +#include "misc.h" +#include "sqlite.h" + +#undef MODULE +#define MODULE "sqlite: " + +#define ENCODED_PACKAGE_FILE_FILES 2048 +#define ENCODED_PACKAGE_FILE_TYPES 60 + + +GQuark +cr_db_error_quark (void) +{ + static GQuark quark; + + if (!quark) + quark = g_quark_from_static_string("cr_db_error"); + + return quark; +} + + +struct _DbPrimaryStatements { + sqlite3 *db; + sqlite3_stmt *pkg_handle; + sqlite3_stmt *provides_handle; + sqlite3_stmt *conflicts_handle; + sqlite3_stmt *obsoletes_handle; + sqlite3_stmt *requires_handle; + sqlite3_stmt *files_handle; +}; + +struct _DbFilelistsStatements { + sqlite3 *db; + sqlite3_stmt *package_id_handle; + sqlite3_stmt *filelists_handle; +}; + +struct _DbOtherStatements { + sqlite3 *db; + sqlite3_stmt *package_id_handle; + sqlite3_stmt *changelog_handle; +}; + +/* + * Base DB operation + * - Open db + * - Creation of tables + * - Tweaking of db settings + * - Creation of info table + * - Creation of index + * - Close db + */ + +static sqlite3 * +open_sqlite_db(const char *path, GError **err) +{ + int rc; + sqlite3 *db = NULL; + + rc = sqlite3_open(path, &db); + if (rc != SQLITE_OK) { + g_set_error(err, CR_DB_ERROR, CR_DB_ERROR, + "Can not open SQL database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + db = NULL; + } + + return db; +} + + +static void +db_create_dbinfo_table(sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = "CREATE TABLE db_info (dbversion INTEGER, checksum TEXT)"; + rc = sqlite3_exec(db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error(err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create db_info table: %s", + sqlite3_errmsg (db)); + } +} + + +static void +db_create_primary_tables(sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = + "CREATE TABLE packages (" + " pkgKey INTEGER PRIMARY KEY," + " pkgId TEXT," + " name TEXT," + " arch TEXT," + " version TEXT," + " epoch TEXT," + " release TEXT," + " summary TEXT," + " description TEXT," + " url TEXT," + " time_file INTEGER," + " time_build INTEGER," + " rpm_license TEXT," + " rpm_vendor TEXT," + " rpm_group TEXT," + " rpm_buildhost TEXT," + " rpm_sourcerpm TEXT," + " rpm_header_start INTEGER," + " rpm_header_end INTEGER," + " rpm_packager TEXT," + " size_package INTEGER," + " size_installed INTEGER," + " size_archive INTEGER," + " location_href TEXT," + " location_base TEXT," + " checksum_type TEXT)"; + + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create packages table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TABLE files (" + " name TEXT," + " type TEXT," + " pkgKey INTEGER)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create files table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TABLE %s (" + " name TEXT," + " flags TEXT," + " epoch TEXT," + " version TEXT," + " release TEXT," + " pkgKey INTEGER %s)"; + + const char *deps[] = { "requires", "provides", "conflicts", "obsoletes", NULL }; + int i; + + for (i = 0; deps[i]; i++) { + const char *prereq; + char *query; + + if (!strcmp(deps[i], "requires")) { + prereq = ", pre BOOLEAN DEFAULT FALSE"; + } else + prereq = ""; + + query = g_strdup_printf (sql, deps[i], prereq); + rc = sqlite3_exec (db, query, NULL, NULL, NULL); + g_free (query); + + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create %s table: %s", + deps[i], sqlite3_errmsg (db)); + return; + } + } + + sql = + "CREATE TRIGGER removals AFTER DELETE ON packages" + " BEGIN" + " DELETE FROM files WHERE pkgKey = old.pkgKey;" + " DELETE FROM requires WHERE pkgKey = old.pkgKey;" + " DELETE FROM provides WHERE pkgKey = old.pkgKey;" + " DELETE FROM conflicts WHERE pkgKey = old.pkgKey;" + " DELETE FROM obsoletes WHERE pkgKey = old.pkgKey;" + " END;"; + + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create removals trigger: %s", + sqlite3_errmsg (db)); + return; + } +} + + +void +db_create_filelists_tables(sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = + "CREATE TABLE packages (" + " pkgKey INTEGER PRIMARY KEY," + " pkgId TEXT)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create packages table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TABLE filelist (" + " pkgKey INTEGER," + " dirname TEXT," + " filenames TEXT," + " filetypes TEXT)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create filelist table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TRIGGER remove_filelist AFTER DELETE ON packages" + " BEGIN" + " DELETE FROM filelist WHERE pkgKey = old.pkgKey;" + " END;"; + + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create remove_filelist trigger: %s", + sqlite3_errmsg (db)); + return; + } +} + + +void +db_create_other_tables (sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = + "CREATE TABLE packages (" + " pkgKey INTEGER PRIMARY KEY," + " pkgId TEXT)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create packages table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TABLE changelog (" + " pkgKey INTEGER," + " author TEXT," + " date INTEGER," + " changelog TEXT)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create changelog table: %s", + sqlite3_errmsg (db)); + return; + } + + sql = + "CREATE TRIGGER remove_changelogs AFTER DELETE ON packages" + " BEGIN" + " DELETE FROM changelog WHERE pkgKey = old.pkgKey;" + " END;"; + + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create remove_changelogs trigger: %s", + sqlite3_errmsg (db)); + return; + } +} + + +static void +db_tweak(sqlite3 *db, GError **err) +{ + UNUSED(err); + + // Do not wait for disk writes to be fully + // written to disk before continuing + sqlite3_exec (db, "PRAGMA synchronous = OFF", NULL, NULL, NULL); + + sqlite3_exec (db, "PRAGMA journal_mode = MEMORY", NULL, NULL, NULL); + + sqlite3_exec (db, "PRAGMA temp_store = MEMORY", NULL, NULL, NULL); +} + + +void +db_index_primary_tables (sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = "CREATE INDEX IF NOT EXISTS packagename ON packages (name)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create packagename index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS packageId ON packages (pkgId)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create packageId index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS filenames ON files (name)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create filenames index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS pkgfiles ON files (pkgKey)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create index on files table: %s", + sqlite3_errmsg (db)); + return; + } + + const char *deps[] = { "requires", "provides", "conflicts", "obsoletes", NULL }; + int i; + + const char *pkgindexsql = "CREATE INDEX IF NOT EXISTS pkg%s on %s (pkgKey)"; + const char *nameindexsql = "CREATE INDEX IF NOT EXISTS %sname ON %s (name)"; + + for (i = 0; deps[i]; i++) { + char *query; + + query = g_strdup_printf(pkgindexsql, deps[i], deps[i]); + rc = sqlite3_exec (db, query, NULL, NULL, NULL); + g_free (query); + + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create index on %s table: %s", + deps[i], sqlite3_errmsg (db)); + return; + } + + if (i < 2) { + query = g_strdup_printf(nameindexsql, deps[i], deps[i]); + rc = sqlite3_exec (db, query, NULL, NULL, NULL); + g_free(query); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create %sname index: %s", + deps[i], sqlite3_errmsg (db)); + return; + } + } + } +} + + +void +db_index_filelists_tables (sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = "CREATE INDEX IF NOT EXISTS keyfile ON filelist (pkgKey)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create keyfile index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS pkgId ON packages (pkgId)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create pkgId index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS dirnames ON filelist (dirname)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create dirnames index: %s", + sqlite3_errmsg (db)); + return; + } +} + + +void +db_index_other_tables (sqlite3 *db, GError **err) +{ + int rc; + const char *sql; + + sql = "CREATE INDEX IF NOT EXISTS keychange ON changelog (pkgKey)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create keychange index: %s", + sqlite3_errmsg (db)); + return; + } + + sql = "CREATE INDEX IF NOT EXISTS pkgId ON packages (pkgId)"; + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not create pkgId index: %s", + sqlite3_errmsg (db)); + return; + } +} + + +sqlite3 * +open_db(const char *path, DatabaseType db_type, GError **err) +{ + GError *tmp_err = NULL; + sqlite3 *db = NULL; + + if (!path || path[0] == '\0') + return db; + + sqlite3_enable_shared_cache(1); + + db = open_sqlite_db(path, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return db; + } + + sqlite3_exec(db, "BEGIN", NULL, NULL, NULL); + + db_create_dbinfo_table(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return db; + } + + switch (db_type) { + case DB_PRIMARY: + db_create_primary_tables(db, &tmp_err); break; + case DB_FILELISTS: + db_create_filelists_tables(db, &tmp_err); break; + case DB_OTHER: + db_create_other_tables(db, &tmp_err); break; + } + if (tmp_err) { + g_propagate_error(err, tmp_err); + return db; + } + + db_tweak(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return db; + } + +// sqlite3_exec (db, "COMMIT", NULL, NULL, NULL); + + return db; +} + + +void +close_db(sqlite3 *db, DatabaseType db_type, GError **err) +{ + GError *tmp_err = NULL; + + if (!db) + return; + + switch (db_type) { + case DB_PRIMARY: + db_index_primary_tables(db, &tmp_err); break; + case DB_FILELISTS: + db_index_filelists_tables(db, &tmp_err); break; + case DB_OTHER: + db_index_other_tables(db, &tmp_err); break; + } + + if (tmp_err) { + g_propagate_error(err, tmp_err); + } + + sqlite3_exec (db, "COMMIT", NULL, NULL, NULL); + + sqlite3_close(db); +} + + +/* + * Package insertion stuff + */ + + +void +dbinfo_update(sqlite3 *db, const char *checksum, GError **err) +{ + int rc; + char *sql; + + sql = g_strdup_printf + ("INSERT INTO db_info (dbversion, checksum) VALUES (%d, '%s')", + CR_SQLITE_CACHE_DBVERSION, checksum); + + rc = sqlite3_exec (db, sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not update dbinfo table: %s", + sqlite3_errmsg (db)); + g_free (sql); +} + + +/* + * primary.sqlite + */ + + +sqlite3_stmt * +db_package_prepare (sqlite3 *db, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + const char *query; + + query = + "INSERT INTO packages (" + " pkgId, name, arch, version, epoch, release, summary, description," + " url, time_file, time_build, rpm_license, rpm_vendor, rpm_group," + " rpm_buildhost, rpm_sourcerpm, rpm_header_start, rpm_header_end," + " rpm_packager, size_package, size_installed, size_archive," + " location_href, location_base, checksum_type) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," + " ?, ?, ?, ?, ?, ?, ?)"; + + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare packages insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + + return handle; +} + + +inline const char * +prevent_null(const char *str) +{ + if (!str) + return ""; + else + return str; +} + +inline const char * +force_null(const char *str) +{ + if (!str || str[0] == '\0') + return NULL; + else + return str; +} + + +void +db_package_write (sqlite3 *db, sqlite3_stmt *handle, Package *p) +{ + int rc; + + sqlite3_bind_text (handle, 1, p->pkgId, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 2, p->name, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 3, p->arch, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 4, p->version, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 5, p->epoch, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 6, p->release, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 7, p->summary, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 8, p->description, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 9, force_null(p->url), -1, SQLITE_STATIC); // {null} + sqlite3_bind_int (handle, 10, p->time_file); + sqlite3_bind_int (handle, 11, p->time_build); + sqlite3_bind_text (handle, 12, p->rpm_license, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 13, prevent_null(p->rpm_vendor), -1, SQLITE_STATIC); // "" + sqlite3_bind_text (handle, 14, p->rpm_group, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 15, p->rpm_buildhost, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 16, prevent_null(p->rpm_sourcerpm), -1, SQLITE_STATIC); // "" + sqlite3_bind_int (handle, 17, p->rpm_header_start); + sqlite3_bind_int (handle, 18, p->rpm_header_end); + sqlite3_bind_text (handle, 19, force_null(p->rpm_packager), -1, SQLITE_STATIC); // {null} + sqlite3_bind_int64(handle, 20, p->size_package); + sqlite3_bind_int64(handle, 21, p->size_installed); + sqlite3_bind_int64(handle, 22, p->size_archive); + sqlite3_bind_text (handle, 23, p->location_href, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 24, force_null(p->location_base), -1, SQLITE_STATIC); // {null} + sqlite3_bind_text (handle, 25, p->checksum_type, -1, SQLITE_STATIC); + + rc = sqlite3_step (handle); + sqlite3_reset (handle); + + if (rc != SQLITE_DONE) { + g_critical ("Error adding package to SQL: %s", + sqlite3_errmsg (db)); + } else + p->pkgKey = sqlite3_last_insert_rowid (db); +} + + +sqlite3_stmt * +db_dependency_prepare (sqlite3 *db, const char *table, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + char *query; + + const char *pre_name = ""; + const char *pre_value = ""; + + if (!strcmp (table, "requires")) { + pre_name = ", pre"; + pre_value = ", ?"; + } + + query = g_strdup_printf + ("INSERT INTO %s (name, flags, epoch, version, release, pkgKey%s) " + "VALUES (?, ?, ?, ?, ?, ?%s)", table, pre_name, pre_value); + + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + g_free (query); + + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare dependency insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + + return handle; +} + +void +db_dependency_write (sqlite3 *db, + sqlite3_stmt *handle, + gint64 pkgKey, + Dependency *dep, + gboolean isRequirement) +{ + int rc; + + sqlite3_bind_text (handle, 1, dep->name, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 2, dep->flags, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 3, dep->epoch, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 4, dep->version, -1, SQLITE_STATIC); + sqlite3_bind_text (handle, 5, dep->release, -1, SQLITE_STATIC); + sqlite3_bind_int (handle, 6, pkgKey); + + if (isRequirement) { + if (dep->pre) + sqlite3_bind_text (handle, 7, "TRUE", -1, SQLITE_TRANSIENT); + else + sqlite3_bind_text (handle, 7, "FALSE", -1, SQLITE_TRANSIENT); + } + + rc = sqlite3_step (handle); + sqlite3_reset (handle); + + if (rc != SQLITE_DONE) + g_critical ("Error adding dependency to SQL: %s", + sqlite3_errmsg (db)); +} + +sqlite3_stmt * +db_file_prepare (sqlite3 *db, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + const char *query; + + query = "INSERT INTO files (name, type, pkgKey) VALUES (?, ?, ?)"; + + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare file insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + + return handle; + +} + +void +db_file_write (sqlite3 *db, + sqlite3_stmt *handle, + gint64 pkgKey, + PackageFile *file) +{ + int rc; + + gchar *fullpath = g_strconcat(file->path, file->name, NULL); + if (!fullpath) + return; // Nothing to do + + if (!is_primary(fullpath)) { + g_free(fullpath); + return; + } + + const char* file_type = file->type; + if (!file_type || file_type[0] == '\0') { + file_type = "file"; + } + + sqlite3_bind_text (handle, 1, fullpath, -1, SQLITE_TRANSIENT); + g_free(fullpath); + sqlite3_bind_text (handle, 2, file_type, -1, SQLITE_STATIC); + sqlite3_bind_int (handle, 3, pkgKey); + + rc = sqlite3_step (handle); + sqlite3_reset (handle); + + if (rc != SQLITE_DONE) + g_critical ("Error adding package file to SQL: %s", + sqlite3_errmsg (db)); +} + + +/* + * filelists.sqlite + */ + + +sqlite3_stmt * +db_filelists_prepare (sqlite3 *db, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + const char *query; + + query = + "INSERT INTO filelist (pkgKey, dirname, filenames, filetypes) " + " VALUES (?, ?, ?, ?)"; + + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare filelist insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + + return handle; +} + + +typedef struct { + GString *files; + GString *types; +} EncodedPackageFile; + + +static EncodedPackageFile * +encoded_package_file_new (void) +{ + EncodedPackageFile *enc; + + enc = g_new0 (EncodedPackageFile, 1); + enc->files = g_string_sized_new (ENCODED_PACKAGE_FILE_FILES); + enc->types = g_string_sized_new (ENCODED_PACKAGE_FILE_TYPES); + + return enc; +} + + +static void +encoded_package_file_free (EncodedPackageFile *file) +{ + g_string_free (file->files, TRUE); + g_string_free (file->types, TRUE); + g_free (file); +} + + +static GHashTable * +package_files_to_hash (GSList *files) +{ + GHashTable *hash; + GSList *iter; + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + (GDestroyNotify) encoded_package_file_free); + + for (iter = files; iter; iter = iter->next) { + PackageFile *file; + EncodedPackageFile *enc; + char *dir; + char *name; + + file = (PackageFile *) iter->data; + + dir = file->path; + name = file->name; + + enc = (EncodedPackageFile *) g_hash_table_lookup (hash, dir); + if (!enc) { + enc = encoded_package_file_new (); + g_hash_table_insert (hash, dir, enc); + } + + if (enc->files->len) + g_string_append_c (enc->files, '/'); + + if (!name || name[0] == '\0') + // Root directory '/' has empty name + g_string_append_c (enc->files, '/'); + else + g_string_append (enc->files, name); + + + if (!(file->type) || file->type[0] == '\0' || !strcmp (file->type, "file")) + g_string_append_c (enc->types, 'f'); + else if (!strcmp (file->type, "dir")) + g_string_append_c (enc->types, 'd'); + else if (!strcmp (file->type, "ghost")) + g_string_append_c (enc->types, 'g'); + } + + return hash; +} + + +typedef struct { + sqlite3 *db; + sqlite3_stmt *handle; + gint64 pkgKey; +} FileWriteInfo; + + +static void +write_file (gpointer key, gpointer value, gpointer user_data) +{ + EncodedPackageFile *file = (EncodedPackageFile *) value; + FileWriteInfo *info = (FileWriteInfo *) user_data; + int rc; + + sqlite3_bind_int (info->handle, 1, info->pkgKey); + sqlite3_bind_text (info->handle, 2, (const char *) key, -1, SQLITE_STATIC); + sqlite3_bind_text (info->handle, 3, file->files->str, -1, SQLITE_STATIC); + sqlite3_bind_text (info->handle, 4, file->types->str, -1, SQLITE_STATIC); + + rc = sqlite3_step (info->handle); + sqlite3_reset (info->handle); + + if (rc != SQLITE_DONE) { + g_critical ("Error adding file to SQL: %s", + sqlite3_errmsg (info->db)); + } +} + + +void +db_filelists_write (sqlite3 *db, sqlite3_stmt *handle, Package *p) +{ + GHashTable *hash; + FileWriteInfo info; + + info.db = db; + info.handle = handle; + info.pkgKey = p->pkgKey; + + hash = package_files_to_hash (p->files); + g_hash_table_foreach (hash, write_file, &info); + g_hash_table_destroy (hash); +} + + + +/* + * other.sqlite + */ + + +sqlite3_stmt * +db_changelog_prepare (sqlite3 *db, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + const char *query; + + query = + "INSERT INTO changelog (pkgKey, author, date, changelog) " + " VALUES (?, ?, ?, ?)"; + + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare changelog insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + + return handle; +} + + +// Stuff common for both filelists.sqlite and other.sqlite + + +sqlite3_stmt * +db_package_ids_prepare(sqlite3 *db, GError **err) +{ + int rc; + sqlite3_stmt *handle = NULL; + const char *query; + + query = "INSERT INTO packages (pkgId) VALUES (?)"; + rc = sqlite3_prepare_v2 (db, query, -1, &handle, NULL); + if (rc != SQLITE_OK) { + g_set_error (err, CR_DB_ERROR, CR_DB_ERROR, + "Can not prepare package ids insertion: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (handle); + handle = NULL; + } + return handle; +} + + +void +db_package_ids_write (sqlite3 *db, sqlite3_stmt *handle, Package *pkg) +{ + int rc; + + sqlite3_bind_text (handle, 1, pkg->pkgId, -1, SQLITE_STATIC); + rc = sqlite3_step (handle); + sqlite3_reset (handle); + + if (rc != SQLITE_DONE) { + g_critical ("Error adding package to SQL: %s", + sqlite3_errmsg (db)); + } else + pkg->pkgKey = sqlite3_last_insert_rowid (db); +} + + +/* + * Module interface + */ + + +// Primary.sqlite interface + +DbPrimaryStatements +prepare_primary_db_statements(sqlite3 *db, GError **err) +{ + GError *tmp_err = NULL; + DbPrimaryStatements ret = malloc(sizeof(*ret)); + + ret->db = db; + ret->pkg_handle = NULL; + ret->provides_handle = NULL; + ret->conflicts_handle = NULL; + ret->obsoletes_handle = NULL; + ret->requires_handle = NULL; + ret->files_handle = NULL; + + ret->pkg_handle = db_package_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->provides_handle = db_dependency_prepare(db, "provides", &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->conflicts_handle = db_dependency_prepare(db, "conflicts", &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->obsoletes_handle = db_dependency_prepare(db, "obsoletes", &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->requires_handle = db_dependency_prepare(db, "requires", &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->files_handle = db_file_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + return ret; +} + + +void +destroy_primary_db_statements(DbPrimaryStatements stmts) +{ + if (!stmts) + return; + + if (stmts->pkg_handle) + sqlite3_finalize(stmts->pkg_handle); + if (stmts->provides_handle) + sqlite3_finalize(stmts->provides_handle); + if (stmts->conflicts_handle) + sqlite3_finalize(stmts->conflicts_handle); + if (stmts->obsoletes_handle) + sqlite3_finalize(stmts->obsoletes_handle); + if (stmts->requires_handle) + sqlite3_finalize(stmts->requires_handle); + if (stmts->files_handle) + sqlite3_finalize(stmts->files_handle); + free(stmts); +} + + +void +add_primary_pkg_db(DbPrimaryStatements stmts, Package *pkg) +{ + GSList *iter; + +// sqlite3_exec(stmts->db, "BEGIN", NULL, NULL, NULL); + + db_package_write(stmts->db, stmts->pkg_handle, pkg); + + for (iter = pkg->provides; iter; iter = iter->next) + db_dependency_write (stmts->db, + stmts->provides_handle, + pkg->pkgKey, + (Dependency *) iter->data, + FALSE); + + for (iter = pkg->conflicts; iter; iter = iter->next) + db_dependency_write (stmts->db, + stmts->conflicts_handle, + pkg->pkgKey, + (Dependency *) iter->data, + FALSE); + + for (iter = pkg->obsoletes; iter; iter = iter->next) + db_dependency_write (stmts->db, + stmts->obsoletes_handle, + pkg->pkgKey, + (Dependency *) iter->data, + FALSE); + + for (iter = pkg->requires; iter; iter = iter->next) + db_dependency_write (stmts->db, + stmts->requires_handle, + pkg->pkgKey, + (Dependency *) iter->data, + TRUE); + + for (iter = pkg->files; iter; iter = iter->next) + db_file_write (stmts->db, stmts->files_handle, pkg->pkgKey, + (PackageFile *) iter->data); + +// sqlite3_exec (stmts->db, "COMMIT", NULL, NULL, NULL); +} + + +// filelists.sqlite interface + + +DbFilelistsStatements +prepare_filelists_db_statements(sqlite3 *db, GError **err) +{ + GError *tmp_err = NULL; + DbFilelistsStatements ret = malloc(sizeof(*ret)); + + ret->db = db; + ret->package_id_handle = NULL; + ret->filelists_handle = NULL; + + ret->package_id_handle = db_package_ids_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->filelists_handle = db_filelists_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + return ret; +} + + +void +destroy_filelists_db_statements(DbFilelistsStatements stmts) +{ + if (!stmts) + return; + + if (stmts->package_id_handle) + sqlite3_finalize(stmts->package_id_handle); + if (stmts->filelists_handle) + sqlite3_finalize(stmts->filelists_handle); + free(stmts); +} + + +void +add_filelists_pkg_db(DbFilelistsStatements stmts, Package *pkg) +{ + // Add package record into the filelists.sqlite + db_package_ids_write(stmts->db, stmts->package_id_handle, pkg); + db_filelists_write(stmts->db, stmts->filelists_handle, pkg); +} + + +// other.sqlite interface + + +DbOtherStatements +prepare_other_db_statements(sqlite3 *db, GError **err) +{ + GError *tmp_err = NULL; + DbOtherStatements ret = malloc(sizeof(*ret)); + + ret->db = db; + ret->package_id_handle = NULL; + ret->changelog_handle = NULL; + + ret->package_id_handle = db_package_ids_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + ret->changelog_handle = db_changelog_prepare(db, &tmp_err); + if (tmp_err) { + g_propagate_error(err, tmp_err); + return ret; + } + + return ret; +} + + +void +destroy_other_db_statements(DbOtherStatements stmts) +{ + if (!stmts) + return; + + if (stmts->package_id_handle) + sqlite3_finalize(stmts->package_id_handle); + if (stmts->changelog_handle) + sqlite3_finalize(stmts->changelog_handle); + free(stmts); +} + + +void +add_other_pkg_db(DbOtherStatements stmts, Package *pkg) +{ + GSList *iter; + ChangelogEntry *entry; + int rc; + + sqlite3_stmt *handle = stmts->changelog_handle; + + // Add package record into the other.sqlite + + db_package_ids_write(stmts->db, stmts->package_id_handle, pkg); + + for (iter = pkg->changelogs; iter; iter = iter->next) { + entry = (ChangelogEntry *) iter->data; + + sqlite3_bind_int (handle, 1, pkg->pkgKey); + sqlite3_bind_text (handle, 2, entry->author, -1, SQLITE_STATIC); + sqlite3_bind_int (handle, 3, entry->date); + sqlite3_bind_text (handle, 4, entry->changelog, -1, SQLITE_STATIC); + + rc = sqlite3_step (handle); + sqlite3_reset (handle); + + if (rc != SQLITE_DONE) { + g_critical ("Error adding changelog to SQL: %s", + sqlite3_errmsg (stmts->db)); + } + } +} diff --git a/src/sqlite.h b/src/sqlite.h new file mode 100644 index 0000000..fa83552 --- /dev/null +++ b/src/sqlite.h @@ -0,0 +1,211 @@ +/* createrepo_c - Library of routines for manipulation with repodata + * Copyright (C) 2012 Tomas Mlcoch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __C_CREATEREPOLIB_SQLITE_H__ +#define __C_CREATEREPOLIB_SQLITE_H__ + +#include +#include +#include "package.h" + + +/** \defgroup sqlite SQLite metadata API. + */ + +#define CR_SQLITE_CACHE_DBVERSION 10 /*!< Version of DB api */ + +#define CR_DB_ERROR cr_db_error_quark() +GQuark cr_db_error_quark (void); + +typedef struct _DbPrimaryStatements * DbPrimaryStatements; +typedef struct _DbFilelistsStatements * DbFilelistsStatements; +typedef struct _DbOtherStatements * DbOtherStatements; + +/** \ingroup sqlite + * Database type. + */ +typedef enum { + DB_PRIMARY, /*!< primary */ + DB_FILELISTS, /*!< filelists */ + DB_OTHER /*!< other */ +} DatabaseType; + +/** \ingroup sqlite + * Macro over open_db function. Open (create new) primary sqlite sqlite db. + * - creates db file + * - creates primary tables + * - creates info table + * - tweak some db params + * @param PATH Path to the db file. + * @param ERR **GError + * @return open db pointer + */ +#define open_primary_db(PATH, ERR) open_db(PATH, DB_PRIMARY, ERR) + +/** \ingroup sqlite + * Macro over open_db function. Open (create new) filelists sqlite sqlite db. + * - creates db file + * - creates filelists tables + * - creates info table + * - tweak some db params + * @param PATH Path to the db file. + * @param ERR **GError + * @return open db pointer + */ +#define open_filelists_db(PATH, ERR) open_db(PATH, DB_FILELISTS, ERR) + +/** \ingroup sqlite + * Macro over open_db function. Open (create new) other sqlite sqlite db. + * - creates db file + * - opens transaction + * - creates other tables + * - creates info table + * - tweak some db params + * @param PATH Path to the db file. + * @param ERR **GError + * @return open db connection + */ +#define open_other_db(PATH, ERR) open_db(PATH, DB_OTHER, ERR) + +/** \ingroup sqlite + * Macro over close_db function. Close db. + * - creates indexes on tables + * - commits transaction + * - closes db + * @param DB open db connection + * @param ERR **GError + */ +#define close_primary_db(DB, ERR) close_db(DB, DB_PRIMARY, ERR) + +/** \ingroup sqlite + * Macro over close_db function. Close db. + * - creates indexes on tables + * - commits transaction + * - closes db + * @param DB open db connection + * @param ERR **GError + */ +#define close_filelists_db(DB, ERR) close_db(DB, DB_FILELISTS, ERR) + +/** \ingroup sqlite + * Macro over close_db function. Close db. + * - creates indexes on tables + * - commits transaction + * - closes db + * @param DB open db connection + * @param ERR **GError + */ +#define close_other_db(DB, ERR) close_db(DB, DB_OTHER, ERR) + +/** \ingroup sqlite + * Open (create new) other sqlite sqlite db. + * - creates db file + * - opens transaction + * - creates other tables + * - creates info table + * - tweak some db params + * @param path Path to the db file. + * @param db_type Type of database (primary, filelists, other) + * @param err **GError + * @return open db connection + */ +sqlite3 *open_db(const char *path, DatabaseType db_type, GError **err); + +/** \ingroup sqlite + * Prepare compiled statements for use in the add_primary_pkg_db function. + * @param db Open db connection + * @param err **GError + * @return DbPrimaryStatements object + */ +DbPrimaryStatements prepare_primary_db_statements(sqlite3 *db, GError **err); + +/** \ingroup sqlite + * Prepare compiled statements for use in the add_filelists_pkg_db function. + * @param db Open db connection + * @param err **GError + * @return DbFilelistsStatements object + */ +DbFilelistsStatements prepare_filelists_db_statements(sqlite3 *db, GError **err); + +/** \ingroup sqlite + * Prepare compiled statements for use in the add_other_pkg_db function. + * @param db Open db connection + * @param err **GError + * @return DbOtherStatements object + */ +DbOtherStatements prepare_other_db_statements(sqlite3 *db, GError **err); + +/** \ingroup sqlite + * Frees DbPrimaryStatements object. + * @param stmts statements object + */ +void destroy_primary_db_statements(DbPrimaryStatements stmts); + +/** \ingroup sqlite + * Frees DbFilelistsStatements object. + * @param stmts statements object + */ +void destroy_filelists_db_statements(DbFilelistsStatements stmts); + +/** \ingroup sqlite + * Frees DbOtherStatements object. + * @param stmts statements object + */ +void destroy_other_db_statements(DbOtherStatements stmts); + +/** \ingroup sqlite + * Add package into the database. + * @param stmts object with compiled statements + * @param pkg package object + */ +void add_primary_pkg_db(DbPrimaryStatements stmts, Package *pkg); + +/** \ingroup sqlite + * Add package into the database. + * @param stmts object with compiled statements + * @param pkg package object + */ +void add_filelists_pkg_db(DbFilelistsStatements, Package *pkg); + +/** \ingroup sqlite + * Add package into the database. + * @param stmts object with compiled statements + * @param pkg package object + */ +void add_other_pkg_db(DbOtherStatements stmts, Package *pkg); + +/** \ingroup sqlite + * Insert record into the updateinfo table + * @param open db connection + * @checksum compressed xml file checksum + * @err **GError + */ +void dbinfo_update(sqlite3 *db, const char *checksum, GError **err); + +/** \ingroup sqlite + * Close db. + * - creates indexes on tables + * - commits transaction + * - closes db + * @param db open db connection + * @param db_type Type of database (primary, filelists, other) + * @param err **GError + */ +void close_db(sqlite3 *db, DatabaseType db_type, GError **err); + +#endif /* __C_CREATEREPOLIB_SQLITE_H__ */