From 9a576a454c1f3d52618c0f5ad1c99257283e030a Mon Sep 17 00:00:00 2001
From: Srikanth Raju <srikiraju@gmail.com>
Date: Wed, 19 Aug 2009 22:34:06 +0530
Subject: [PATCH] Sqlite Module for VLC

This module provides a basic abstraction to sqlite from vlc for modules
to use.
---
 configure.ac            |   35 ++++
 include/vlc_sql.h       |  230 ++++++++++++++++++++++++++
 modules/LIST            |    1 +
 modules/misc/Modules.am |    1 +
 modules/misc/sqlite.c   |  417 +++++++++++++++++++++++++++++++++++++++++++++++
 src/Makefile.am         |    2 +
 src/libvlccore.sym      |    1 +
 src/misc/sql.c          |   88 ++++++++++
 8 files changed, 775 insertions(+), 0 deletions(-)
 create mode 100644 include/vlc_sql.h
 create mode 100644 modules/misc/sqlite.c
 create mode 100644 src/misc/sql.c

diff --git a/configure.ac b/configure.ac
index 748bb21..9d2ef0c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4664,6 +4664,41 @@ then
   AC_DEFINE([UPDATE_CHECK], 1, [Define if you want to use the VLC update mechanism])
 fi
 
+dnl
+dnl SQLite
+dnl
+if test "${SYS}" != "darwin"; then
+  PKG_ENABLE_MODULES_VLC([SQLITE], [], [sqlite3], [sqlite3], [auto])
+else
+  AC_ARG_ENABLE(sqlite,
+    [  --enable-sqlite   SQLite (default disabled)])
+  if test "${enable_sqlite}" = "yes"
+  then
+    AC_ARG_WITH(sqlite,
+      [    --with-sqlite=PATH sqlite path linking])
+    AC_CHECK_HEADERS(sqlite3.h, [
+        VLC_ADD_PLUGIN([sqlite])
+        if test "${with_sqlite}" != "no" -a -n "${with_sqlite}"; then
+          AC_MSG_CHECKING(existence of sqlite directory in ${with_sqlite})
+          real_sqlite="`cd ${with_sqlite} 2>/dev/null && pwd`"
+          if test -z "${real_sqlite}"
+          then
+            dnl  The given directory can't be found
+            AC_MSG_RESULT(no)
+            AC_MSG_ERROR([cannot cd to ${with_sqlite}])
+          fi
+          VLC_ADD_CFLAGS([sqlite],[-I${with_sqlite}/include])
+          VLC_ADD_LIBS([sqlite], [-L${with_sqlite}/lib -lsqlite3])
+          AC_MSG_RESULT(yes)
+        else
+          VLC_ADD_LIBS([sqlite], [-lsqlite3])
+        fi
+        AC_DEFINE([SQLITE_MODULE], 1, [Define if you want to use SQLite module]) ],
+        AC_MSG_ERROR([sqlite3 is required for sqlite module]) )
+  fi
+  AM_CONDITIONAL([HAVE_SQLITE], [test "${enable_sqlite}" = "yes"])
+fi
+
 
 dnl
 dnl  Endianness check
diff --git a/include/vlc_sql.h b/include/vlc_sql.h
new file mode 100644
index 0000000..4520052
--- /dev/null
+++ b/include/vlc_sql.h
@@ -0,0 +1,230 @@
+/*****************************************************************************
+ * vlc_sql.h: SQL abstraction layer
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Antoine Lejeune <phytos@videolan.org>
+ *          Jean-Philippe André <jpeg@videolan.org>
+ *          Srikanth Raju <srikiraju@gmail.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if !defined( __LIBVLC__ )
+# error You are not libvlc or one of its plugins. You cannot include this file
+#endif
+
+#ifndef VLC_SQL_H
+# define VLC_SQL_H
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+/*****************************************************************************
+ * General structure: SQL object.
+ *****************************************************************************/
+
+typedef struct sql_t sql_t;
+typedef struct sql_sys_t sql_sys_t;
+
+struct sql_t
+{
+    VLC_COMMON_MEMBERS
+
+    /** Module properties */
+    module_t  *p_module;
+
+    /** Internal data */
+    sql_sys_t *p_sys;
+
+    /** Perform a query with a row-by-row callback function */
+    int (*pf_query_callback) ( sql_t *, const char *,
+            int (*callback) ( void*, int, char**, char** ), void * );
+
+    /** Perform a query and return result directly */
+    int (*pf_query) ( sql_t *, const char *, char ***, int *, int * );
+
+    /** Get database tables */
+    int (*pf_get_tables) ( sql_t *, char *** );
+
+    /** Free result of a call to sql_Query or sql_GetTables */
+    void (*pf_free) ( sql_t *, char ** );
+
+    /** vmprintf replacement for SQL */
+    char* (*pf_vmprintf) ( const char*, va_list args );
+
+    /** Begin transaction */
+    int (*pf_begintransaction) ( sql_t* );
+
+    /** Commit transaction */
+    void (*pf_committransaction) ( sql_t* );
+
+    /** Rollback transaction */
+    void (*pf_rollbacktransaction) ( sql_t* );
+};
+
+
+/*****************************************************************************
+ * SQL Function headers
+ *****************************************************************************/
+
+/**
+ * @brief Create a new SQL object.
+ * @param p_this Parent object to attach the SQL object to.
+ * @param psz_host URL to the database
+ * @param i_port Port on which the database is running
+ * @param psz_user Username to access the database
+ * @param psz_pass Password for the database
+ * @return The VLC SQL object, type sql_t.
+ **/
+#define sql_Create( a, b, c, d, e, f ) __sql_Create( VLC_OBJECT(a), b, c, d, e, f )
+VLC_EXPORT( sql_t*, __sql_Create, ( vlc_object_t *p_this, char *psz_name,
+            char* psz_host, int i_port, char* psz_user, char* psz_pass ) );
+/**
+ * @brief Perform a query using a callback function
+ * @param p_sql This SQL object.
+ * @param psz_query The SQL query string.
+ * @param pf_callback A callback function that will be called for each row of
+ * the result: 1st argument is be p_opaque,
+ *             2nd argument is the number of columns,
+ *             3rd is the result columns (array of strings),
+ *             4th is the columns names (array of strings).
+ * @param p_opaque Any pointer to an object you may need in the callback.
+ * @return VLC_SUCCESS or VLC_EGENERIC.
+ * @note The query will not necessarily be processed in a separate thread!
+ **/
+static inline int sql_QueryCallback( sql_t *p_sql, const char *psz_query,
+                                     int ( *pf_callback ) ( void*, int,
+                                                            char **, char ** ),
+                                     void *p_opaque )
+{
+    return p_sql->pf_query_callback( p_sql, psz_query, pf_callback, p_opaque );
+}
+
+/**
+ * @brief Perform a query directly
+ * @param p_sql This SQL object.
+ * @param psz_query The SQL query string.
+ * @param pppsz_result A pointer to a array of strings: result of the query.
+ * Dynamically allocated.
+ * @param pi_rows Pointer to an integer that will receive the number of result
+ * rows written.
+ * @param pi_cols Pointer to an integer that will receive the number of result
+ * columns written.
+ * @return VLC_SUCCESS or VLC_EGENERIC.
+ * @note pppsz_result will point to an array of strings, ppsz_result.
+ * This array of strings contains actually a 2D-matrix of strings where the
+ * first row (row 0) contains the SQL table header names.
+ * *pi_rows will be the number of result rows, so that the number of text rows
+ * in ppsz_result will be (*pi_rows + 1) (because of row 0).
+ * To get result[row,col] use (*pppsz_result)[ (row+1) * (*pi_cols) + col ].
+ **/
+static inline int sql_Query( sql_t *p_sql, const char *psz_query,
+                             char ***pppsz_result, int *pi_rows, int *pi_cols )
+{
+    return p_sql->pf_query( p_sql, psz_query, pppsz_result, pi_rows, pi_cols );
+}
+
+/**
+ * @brief Get database table name list
+ * @param p_sql This SQL object.
+ * @param pppsz_tables Pointer to an array of strings. Dynamically allocated.
+ * Similar to pppsz_result of sql_Query but with only one row.
+ * @return Number of tables or <0 in case of error.
+ **/
+static inline int sql_GetTables( sql_t *p_sql, char ***pppsz_tables )
+{
+    return p_sql->pf_get_tables( p_sql, pppsz_tables );
+}
+
+/**
+ * @brief Free the result of a query.
+ * @param p_sql This SQL object.
+ * @param ppsz_result The result of sql_Query or sql_GetTables. See above.
+ * @return Nothing.
+ **/
+static inline void sql_Free( sql_t *p_sql, char **ppsz_result )
+{
+    p_sql->pf_free( p_sql, ppsz_result );
+}
+
+/**
+ * @brief printf-like function that can escape forbidden/reserved characters.
+ * @param p_sql This SQL object.
+ * @param psz_fmt Format of the string (with %q, %Q and %z enabled).
+ * @param ... Printf arguments
+ * @return Dynamically allocated string or NULL in case of error.
+ * @note Refer to SQLite documentation for more details about %q, %Q and %z.
+ **/
+static inline char* sql_Printf( sql_t *p_sql, const char *psz_fmt, ... )
+{
+    va_list args;
+    va_start( args, psz_fmt );
+    char *r = p_sql->pf_vmprintf( psz_fmt, args );
+    va_end( args );
+    return r;
+}
+
+/**
+ * @brief vprintf replacement for SQL queries, escaping forbidden characters
+ * @param p_sql This SQL object
+ * @param psz_fmt Format of the string
+ * @param arg Variable list of arguments
+ * @return Dynamically allocated string or NULL in case of error.
+ **/
+static inline char* sql_VPrintf( sql_t *p_sql, const char *psz_fmt,
+                                 va_list arg )
+{
+    return p_sql->pf_vmprintf( psz_fmt, arg );
+}
+
+/**
+ * @brief Begin a SQL transaction
+ * @param p_sql The SQL object
+ * @return VLC error code or success
+ **/
+static inline int sql_BeginTransaction( sql_t *p_sql )
+{
+    return p_sql->pf_begintransaction( p_sql );
+}
+
+/**
+ * @brief Commit a SQL transaction
+ * @param p_sql The SQL object
+ * @return VLC error code or success
+ **/
+static inline void sql_CommitTransaction( sql_t *p_sql )
+{
+    p_sql->pf_committransaction( p_sql );
+}
+
+/**
+ * @brief Rollback a SQL transaction
+ * @param p_sql The SQL object
+ * @return VLC error code or success
+ **/
+static inline void sql_RollbackTransaction( sql_t *p_sql )
+{
+    p_sql->pf_rollbacktransaction( p_sql );
+}
+
+# ifdef __cplusplus
+}
+# endif /* C++ extern "C" */
+
+#endif /* VLC_SQL_H */
diff --git a/modules/LIST b/modules/LIST
index 6159976..2039c08 100644
--- a/modules/LIST
+++ b/modules/LIST
@@ -294,6 +294,7 @@ $Id$
  * spdif_mixer: dummy audio mixer for the S/PDIF output
  * speex: a speex audio decoder/packetizer using the libspeex library
  * spudec: RLE DVD subtitles decoder
+ * sqlite: manage an SQLite database
  * stats: Stats encoder function
  * stream_filter_rar: Stream filter to read inside Rar files
  * stream_filter_record: record any stream instantly
diff --git a/modules/misc/Modules.am b/modules/misc/Modules.am
index 4756fa1..79d354c 100644
--- a/modules/misc/Modules.am
+++ b/modules/misc/Modules.am
@@ -23,6 +23,7 @@ SOURCES_gnutls = gnutls.c dhparams.h
 SOURCES_svg = svg.c
 SOURCES_audioscrobbler = audioscrobbler.c
 SOURCES_inhibit = inhibit.c
+SOURCES_sqlite = sqlite.c
 
 libvlc_LTLIBRARIES += \
 	liblogger_plugin.la
diff --git a/modules/misc/sqlite.c b/modules/misc/sqlite.c
new file mode 100644
index 0000000..3ece418
--- /dev/null
+++ b/modules/misc/sqlite.c
@@ -0,0 +1,417 @@
+/*****************************************************************************
+ * sqlite.c: An SQLite3 wrapper for VLC
+ *****************************************************************************
+ * Copyright (C) 2008-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Antoine Lejeune <phytos@videolan.org>
+ *          Jean-Philippe André <jpeg@videolan.org>
+ *          Rémi Duraffort <ivoire@videolan.org>
+ *          Adrien Maglo <magsoft@videolan.org>
+ *          Srikanth Raju <srikiraju@gmail.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc/vlc.h>
+#include <vlc_sql.h>
+#include <vlc_plugin.h>
+
+#include <sqlite3.h>
+#include <assert.h>
+
+#define SQLITE_DB_TEXT N_( "Filename of the SQLite database" )
+#define SQLITE_DB_LONGTEXT N_( "Path to the file containing the SQLite database" )
+
+
+/*****************************************************************************
+ * Private structures
+ *****************************************************************************/
+struct sql_sys_t
+{
+    char *psz_host;           /**< Database host: SQLite DB filename */
+    sqlite3 *db;              /**< Database connection. */
+    vlc_mutex_t lock;         /**< SQLite mutex. Threads are evil here. */
+    vlc_mutex_t trans_lock;   /**< Mutex for running transactions */
+};
+
+
+/*****************************************************************************
+ * Headers
+ *****************************************************************************/
+static int load ( vlc_object_t * );
+static void unload ( vlc_object_t * );
+
+static int OpenDatabase( sql_t * );
+static int CloseDatabase (sql_t * );
+static int QueryCallback( sql_t * p_sql,
+                          const char * query,
+                          int (*callback) ( void*, int, char**, char** ),
+                          void *arg ); // 1st argument to callback
+static int Query( sql_t * p_sql,
+                  const char * query,
+                  char *** result,
+                  int * nrow,
+                  int * ncol );
+static int GetTables( sql_t * p_sql,
+                      char *** result );
+static void FreeResult( sql_t * p_sql, char **pp_result );
+static char* VMSprintf( const char* psz_fmt, va_list args );
+static int BeginTransaction( sql_t* p_sql );
+static void CommitTransaction( sql_t* p_sql );
+static void RollbackTransaction( sql_t* p_sql );
+
+/*****************************************************************************
+ * Module description
+ *****************************************************************************/
+vlc_module_begin()
+    set_shortname( "SQLite" )
+    set_description( _("SQLite database module") )
+    set_capability( "sql", 1 )
+    set_callbacks( load, unload )
+    set_category( CAT_ADVANCED )
+    add_string( "database-path", "", NULL,
+                SQLITE_DB_TEXT, SQLITE_DB_LONGTEXT, false )
+    add_string( "database-user", "", NULL,
+            "Username", "Username", false )
+    add_string( "database-pass", "", NULL,
+            "Password", "Password", false )
+    add_integer( "database-port", "", NULL,
+            "Port", "Port", false )
+vlc_module_end()
+
+
+/**
+ * @brief Load module
+ * @param obj Parent object
+ * @return VLC_SUCCESS or VLC_ENOMEM
+ */
+static int load( vlc_object_t *p_this )
+{
+    sql_t *p_sql = (sql_t *) p_this;
+
+    p_sql->pf_query_callback = QueryCallback;
+    p_sql->pf_get_tables = GetTables;
+    p_sql->pf_query = Query;
+    p_sql->pf_free = FreeResult;
+    p_sql->pf_vmprintf = VMSprintf;
+    p_sql->pf_begintransaction = BeginTransaction;
+    p_sql->pf_committransaction = CommitTransaction;
+    p_sql->pf_rollbacktransaction = RollbackTransaction;
+
+    /* Initialize sys_t */
+    p_sql->p_sys = ( sql_sys_t* ) calloc( 1, sizeof( sql_sys_t ) );
+    if( !p_sql->p_sys )
+        return VLC_ENOMEM;
+
+    vlc_mutex_init( &p_sql->p_sys->lock );
+    vlc_mutex_init( &p_sql->p_sys->trans_lock );
+
+    /* Open Database */
+    p_sql->p_sys->psz_host = var_CreateGetString( p_this, "database-path" );
+    if( OpenDatabase( p_sql ) == VLC_SUCCESS )
+        msg_Dbg( p_sql, "sqlite module loaded" );
+    else
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+}
+
+/**
+ * @brief Unload module
+ * @param obj This sql_t object
+ * @return Nothing
+ */
+static void unload( vlc_object_t *p_this )
+{
+    sql_t *p_sql = (sql_t *)p_this;
+
+    CloseDatabase( p_sql );
+    vlc_mutex_destroy( &p_sql->p_sys->lock );
+    vlc_mutex_destroy( &p_sql->p_sys->trans_lock );
+    free( p_sql->p_sys->psz_host );
+    free( p_sql->p_sys );
+}
+
+/**
+ * @brief Open current database
+ * @param p_sql This sql_t object
+ * @return VLC_SUCCESS or VLC_EGENERIC
+ * @note You have to set current database first
+ */
+static int OpenDatabase( sql_t *p_sql )
+{
+    vlc_mutex_lock( &p_sql->p_sys->lock );
+
+    assert( !p_sql->p_sys->db );
+    assert( p_sql->p_sys->psz_host && *p_sql->p_sys->psz_host );
+
+    if( sqlite3_open( p_sql->p_sys->psz_host, &p_sql->p_sys->db ) )
+    {
+        msg_Err( p_sql, "Can't open database : %s", p_sql->p_sys->psz_host );
+        vlc_mutex_unlock( &p_sql->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+    vlc_mutex_unlock( &p_sql->p_sys->lock );
+    return VLC_SUCCESS;
+}
+
+/**
+ * @brief Close current database
+ * @param p_sql This sql_t object
+ * @return VLC_SUCCESS
+ * You have to set and open current database first
+ */
+static int CloseDatabase( sql_t *p_sql )
+{
+    vlc_mutex_lock( &p_sql->p_sys->lock );
+    assert( p_sql->p_sys->db );
+
+    /* Close database */
+    int i_ret = sqlite3_close( p_sql->p_sys->db );
+    p_sql->p_sys->db = NULL;
+
+    vlc_mutex_unlock( &p_sql->p_sys->lock );
+    return ( i_ret == SQLITE_OK ) ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
+/**
+ * @brief SQL Query with callback
+ * @param p_sql This sql_t object
+ * @param query SQL query
+ * @param callback Callback function to receive results row by row
+ * @param arg Argument to pass to callback
+ * @return VLC_SUCCESS or an error code
+ * You have to set and open current database first
+ */
+static int QueryCallback( sql_t * p_sql,
+                          const char * query,
+                          int (*callback) ( void*, int, char**, char** ),
+                          void *arg )
+{
+    vlc_mutex_lock( &p_sql->p_sys->lock );
+
+    assert( p_sql->p_sys->db );
+
+#ifndef NDEBUG
+    msg_Dbg( p_sql, "QueryCallback: %s", query );
+#endif
+    sqlite3_exec( p_sql->p_sys->db, query, callback, arg, NULL );
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+        vlc_mutex_unlock( &p_sql->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+    vlc_mutex_unlock( &p_sql->p_sys->lock );
+    return VLC_SUCCESS;
+}
+
+/**
+ * @brief Direct SQL Query
+ * @param p_sql This sql_t object
+ * @param query SQL query
+ * @param result Return value : Array of results
+ * @param nrow Return value : Row number
+ * @param ncol Return value : Column number
+ * @return VLC_SUCCESS or an error code
+ * You have to set and open current database first
+ * @todo Handle transaction closing due to errors in sql query
+ */
+static int Query( sql_t * p_sql,
+                  const char * query,
+                  char *** result,
+                  int * nrow,
+                  int * ncol )
+{
+    vlc_mutex_lock( &p_sql->p_sys->lock );
+
+    if( !p_sql->p_sys->db )
+    {
+        vlc_mutex_unlock( &p_sql->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+#ifndef NDEBUG
+    msg_Dbg( p_sql, "Query: %s", query );
+#endif
+    sqlite3_get_table( p_sql->p_sys->db, query, result, nrow, ncol, NULL );
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+        vlc_mutex_unlock( &p_sql->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+    vlc_mutex_unlock( &p_sql->p_sys->lock );
+    return VLC_SUCCESS;
+}
+
+/**
+ * @brief Get tables in database
+ * @param p_sql This sql_t object
+ * @param result SQL query result
+ * @return Number of elements
+ * You have to set and open current database first
+ */
+static int GetTables( sql_t * p_sql,
+                      char *** result )
+{
+    int nrow, i_num = false;
+    char ***pppsz_res;
+
+    vlc_mutex_lock( &p_sql->p_sys->lock );
+
+    if( !p_sql->p_sys->db )
+    {
+        vlc_mutex_unlock( &p_sql->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+    if( result )
+        pppsz_res = result;
+    else
+        pppsz_res = (char ***) malloc( sizeof( char ** ) );
+
+    sqlite3_get_table( p_sql->p_sys->db, "SELECT * FROM sqlite_master;",
+                       pppsz_res, &nrow, &i_num, NULL );
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+    }
+    if( !result )
+    {
+        sqlite3_free_table( *pppsz_res );
+        free( pppsz_res );
+    }
+    vlc_mutex_unlock( &p_sql->p_sys->lock );
+    return i_num;
+}
+
+/**
+ * @brief Free SQL request's result
+ * @param p_sql This SQL object.
+ * @param ppsz_result SQL result to free
+ */
+static void FreeResult( sql_t * p_sql, char **ppsz_result )
+{
+    VLC_UNUSED( p_sql );
+    if( ppsz_result != NULL )
+        sqlite3_free_table( ppsz_result );
+}
+
+/**
+ * @brief vmprintf replacement for SQLite.
+ * @param psz_fmt Format string
+ * @param args va_list of arguments
+ * This function implements the formats %q, %Q and %z.
+ */
+static char* VMSprintf( const char* psz_fmt, va_list args )
+{
+    char *psz = sqlite3_vmprintf( psz_fmt, args );
+    char *ret = strdup( psz );
+    sqlite3_free( psz );
+    return ret;
+}
+
+/**
+ * @brief Starts a Transaction and waits if necessary
+ * @param p_sql The SQL object
+ * @note This function locks the transactions on the database.
+ * Within the period of the transaction, only the calling thread may
+ * execute sql statements provided all threads use these transaction fns.
+ */
+static int BeginTransaction( sql_t* p_sql )
+{
+    vlc_mutex_lock( &p_sql->p_sys->trans_lock );
+    if( !p_sql->p_sys->db )
+    {
+        vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
+        return VLC_EGENERIC;
+    }
+    sqlite3_exec( p_sql->p_sys->db, "BEGIN;", NULL, NULL, NULL );
+#ifndef NDEBUG
+    msg_Dbg( p_sql, "Transaction Query: BEGIN;" );
+#endif
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+/**
+ * @brief Commit a transaction
+ * @param p_sql The SQL object
+ * @note This function unlocks the transactions on the database
+ * Only the calling thread of "BeginTransaction" is allowed to call this method
+ * If the commit fails, the transaction lock is still held by the thread
+ * and this function may be retried or RollbackTransaction can be called
+ */
+static void CommitTransaction( sql_t* p_sql )
+{
+    /** This turns the auto commit on. */
+    sqlite3_exec( p_sql->p_sys->db, "COMMIT;", NULL, NULL, NULL );
+#ifndef NDEBUG
+    msg_Dbg( p_sql, "Transaction Query: COMMIT;" );
+#endif
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+    }
+    else
+        vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
+}
+
+/**
+ * @brief Rollback a transaction, in case of failure
+ * @param p_sql The SQL object
+ * @note This function unlocks the transactions on the database
+ * Only the calling thread of "BeginTransaction" is allowed to call this method
+ */
+static void RollbackTransaction( sql_t* p_sql )
+{
+    sqlite3_exec( p_sql->p_sys->db, "ROLLBACK;", NULL, NULL, NULL );
+#ifndef NDEBUG
+    msg_Dbg( p_sql, "Transaction Query: ROLLBACK;" );
+#endif
+    if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
+    {
+        msg_Warn( p_sql, "sqlite3 error: %d: %s",
+                  sqlite3_errcode( p_sql->p_sys->db ),
+                  sqlite3_errmsg( p_sql->p_sys->db ) );
+    }
+    vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 78a92bf..e3198a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -86,6 +86,7 @@ pluginsinclude_HEADERS = \
 	../include/vlc_plugin.h \
 	../include/vlc_rand.h \
 	../include/vlc_services_discovery.h \
+	../include/vlc_sql.h \
 	../include/vlc_sout.h \
 	../include/vlc_stream.h \
 	../include/vlc_strings.h \
@@ -428,6 +429,7 @@ SOURCES_libvlc_common = \
 	misc/filter.c \
 	misc/filter_chain.c \
 	misc/http_auth.c \
+	misc/sql.c \
 	$(NULL)
 
 SOURCES_libvlc_httpd = \
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 01cbbb4..1af3f51 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -372,6 +372,7 @@ spu_DisplaySubpicture
 spu_Init
 spu_RenderSubpictures
 spu_SortSubpictures
+__sql_Create
 __stats_TimerClean
 __stats_TimerDump
 __stats_TimersCleanAll
diff --git a/src/misc/sql.c b/src/misc/sql.c
new file mode 100644
index 0000000..3a17a14
--- /dev/null
+++ b/src/misc/sql.c
@@ -0,0 +1,88 @@
+/*****************************************************************************
+ * sql.c: SQL Connection: Creators and destructors
+ *****************************************************************************
+ * Copyright (C) 2008-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Srikanth Raju <srikiraju at gmail dot 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if !defined( __LIBVLC__ )
+  #error You are not libvlc or one of its plugins. You cannot include this file
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_sql.h>
+#include <assert.h>
+#include "libvlc.h"
+
+static void __sql_Destructor( vlc_object_t* obj );
+
+/*
+ * @brief Create an instance of an SQL connection
+ * @param p_this Parent object
+ * @param psz_name Name which is passed to module_need (not needed)
+ * @return p_sql created and attached, module loaded
+ */
+sql_t *__sql_Create( vlc_object_t *p_this, char *psz_name, char* psz_host,
+       int i_port, char* psz_user, char* psz_pass )
+{
+    sql_t *p_sql;
+
+    p_sql = ( sql_t * ) vlc_custom_create( p_this, sizeof( sql_t ),
+                                           VLC_OBJECT_GENERIC, "sql" );
+    if( !p_sql )
+    {
+        msg_Err( p_this, "unable to create sql object" );
+        return NULL;
+    }
+    vlc_object_attach( p_sql, p_this );
+
+    config_PutPsz( p_sql, "database-path", psz_host );
+    config_PutPsz( p_sql, "database-user", psz_user );
+    config_PutPsz( p_sql, "database-pass", psz_pass );
+    config_PutInt( p_sql, "database-port", i_port );
+
+    p_sql->p_module = module_need( p_sql, "sql", psz_name, false );
+    if( !p_sql->p_module )
+    {
+        vlc_object_release( p_sql );
+        msg_Err( p_this, "SQL provider not found" );
+        return NULL;
+    }
+
+    vlc_object_set_destructor( p_sql, __sql_Destructor );
+
+    return p_sql;
+}
+
+/**
+ * @brief Destructor for p_sql object
+ * @param obj This p_sql object
+ * @return Nothing
+ */
+static void __sql_Destructor( vlc_object_t* obj )
+{
+    sql_t *p_sql = (sql_t *)obj;
+    assert( p_sql );
+
+    module_unneed( p_sql, p_sql->p_module );
+}
-- 
1.6.0.4

