]> git.sesse.net Git - vlc/blob - modules/misc/sqlite.c
Sqlite: Typo in testing for threadsafeness
[vlc] / modules / misc / sqlite.c
1 /*****************************************************************************
2  * sqlite.c: An SQLite3 wrapper for VLC
3  *****************************************************************************
4  * Copyright (C) 2008-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Lejeune <phytos@videolan.org>
8  *          Jean-Philippe André <jpeg@videolan.org>
9  *          Rémi Duraffort <ivoire@videolan.org>
10  *          Adrien Maglo <magsoft@videolan.org>
11  *          Srikanth Raju <srikiraju@gmail.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc/vlc.h>
35 #include <vlc_sql.h>
36 #include <vlc_plugin.h>
37
38 #include <sqlite3.h>
39 #include <assert.h>
40
41
42 /*****************************************************************************
43  * Private structures
44  *****************************************************************************/
45 struct sql_sys_t
46 {
47     sqlite3 *db;              /**< Database connection. */
48     vlc_mutex_t lock;         /**< SQLite mutex. Threads are evil here. */
49     vlc_mutex_t trans_lock;   /**< Mutex for running transactions */
50 };
51
52 struct sql_stmt_t
53 {
54     sqlite3_stmt* p_sqlitestmt;
55 };
56
57
58 /*****************************************************************************
59  * Headers
60  *****************************************************************************/
61 static int load ( vlc_object_t * );
62 static void unload ( vlc_object_t * );
63
64 static int OpenDatabase( sql_t * );
65 static int CloseDatabase (sql_t * );
66 static int QueryCallback( sql_t * p_sql,
67                           const char * query,
68                           sql_query_callback_t callback,
69                           void *arg ); // 1st argument to callback
70 static int Query( sql_t * p_sql,
71                   const char * query,
72                   char *** result,
73                   int * nrow,
74                   int * ncol );
75 static int GetTables( sql_t * p_sql,
76                       char *** result );
77 static void FreeResult( sql_t * p_sql,
78                         char **pp_result );
79 static char* VMSprintf( const char* psz_fmt,
80                         va_list args );
81 static int BeginTransaction( sql_t* p_sql );
82 static int CommitTransaction( sql_t* p_sql );
83 static void RollbackTransaction( sql_t* p_sql );
84 static sql_stmt_t* PrepareStatement( sql_t* p_sql,
85                                      const char* psz_fmt,
86                                      int i_length );
87 static int BindValues( sql_t* p_sql,
88                        sql_stmt_t* p_stmt,
89                        int i_pos,
90                        unsigned int i_type,
91                        const sql_value_t* p_value );
92 static int StatementStep( sql_t* p_sql,
93                           sql_stmt_t* p_stmt );
94 static int StatementReset( sql_t* p_sql,
95                            sql_stmt_t* p_stmt );
96 static int StatementFinalize( sql_t* p_sql,
97                               sql_stmt_t* p_stmt );
98 static int GetColumnFromStatement( sql_t* p_sql,
99                                    sql_stmt_t* p_stmt,
100                                    int i_col,
101                                    int type,
102                                    sql_value_t *p_res );
103 static int GetColumnTypeFromStatement( sql_t* p_sql,
104                                        sql_stmt_t* p_stmt,
105                                        int i_col,
106                                        int* pi_type );
107 static int GetColumnSize( sql_t* p_sql,
108                           sql_stmt_t* p_stmt,
109                           int i_col );
110
111 /*****************************************************************************
112  * Module description
113  *****************************************************************************/
114 vlc_module_begin()
115     set_shortname( "SQLite" )
116     set_description( _("SQLite database module") )
117     set_capability( "sql", 1 )
118     set_callbacks( load, unload )
119     set_category( CAT_ADVANCED )
120 vlc_module_end()
121
122
123 /**
124  * @brief Load module
125  * @param obj Parent object
126  * @return VLC_SUCCESS or VLC_ENOMEM
127  */
128 static int load( vlc_object_t *p_this )
129 {
130     sql_t *p_sql = (sql_t *) p_this;
131
132     /* Initialize sys_t */
133     p_sql->p_sys = calloc( 1, sizeof( *p_sql->p_sys ) );
134     if( !p_sql->p_sys )
135         return VLC_ENOMEM;
136
137     vlc_mutex_init( &p_sql->p_sys->lock );
138     vlc_mutex_init( &p_sql->p_sys->trans_lock );
139
140     /* Open Database */
141     if( OpenDatabase( p_sql ) == VLC_SUCCESS )
142         msg_Dbg( p_sql, "sqlite module loaded" );
143     else
144     {
145         free( p_sql->p_sys );
146         vlc_mutex_destroy( &p_sql->p_sys->lock );
147         vlc_mutex_destroy( &p_sql->p_sys->trans_lock );
148         return VLC_EGENERIC;
149     }
150
151     p_sql->pf_query_callback = QueryCallback;
152     p_sql->pf_get_tables = GetTables;
153     p_sql->pf_query = Query;
154     p_sql->pf_free = FreeResult;
155     p_sql->pf_vmprintf = VMSprintf;
156     p_sql->pf_begin = BeginTransaction;
157     p_sql->pf_commit = CommitTransaction;
158     p_sql->pf_rollback = RollbackTransaction;
159     p_sql->pf_prepare = PrepareStatement;
160     p_sql->pf_bind = BindValues;
161     p_sql->pf_run = StatementStep;
162     p_sql->pf_reset = StatementReset;
163     p_sql->pf_finalize = StatementFinalize;
164     p_sql->pf_gettype = GetColumnTypeFromStatement;
165     p_sql->pf_getcolumn = GetColumnFromStatement;
166     p_sql->pf_getcolumnsize = GetColumnSize;
167
168     return VLC_SUCCESS;
169 }
170
171 /**
172  * @brief Unload module
173  * @param obj This sql_t object
174  * @return Nothing
175  */
176 static void unload( vlc_object_t *p_this )
177 {
178     sql_t *p_sql = (sql_t *)p_this;
179
180     CloseDatabase( p_sql );
181     vlc_mutex_destroy( &p_sql->p_sys->lock );
182     vlc_mutex_destroy( &p_sql->p_sys->trans_lock );
183     free( p_sql->p_sys );
184 }
185
186 /**
187  * @brief Sqlite Busy handler
188  * @param p_data sql_t object
189  * @param i_times Number of times busy handler has been invoked
190  */
191 static int vlc_sqlite_busy_handler( void* p_data, int i_times )
192 {
193     if( i_times >= 10 )
194     {
195         msg_Warn( (sql_t*) p_data, "Wait limit exceeded in SQLITE_BUSY handler" );
196         return 0;
197     }
198     msleep( 2000000 );
199     return 1;
200 }
201
202 /**
203  * @brief Open current database
204  * @param p_sql This sql_t object
205  * @return VLC_SUCCESS or VLC_EGENERIC
206  * @note p_sql->psz_host is required
207  */
208 static int OpenDatabase( sql_t *p_sql )
209 {
210     assert( p_sql->psz_host && *p_sql->psz_host );
211
212     if( sqlite3_threadsafe() == 0 )
213     {
214         msg_Err( p_sql, "Sqlite library on your system is not threadsafe" );
215         return VLC_EGENERIC;
216     }
217     if( sqlite3_open( p_sql->psz_host, &p_sql->p_sys->db ) != SQLITE_OK )
218     {
219         msg_Err( p_sql, "Can't open database : %s", p_sql->psz_host );
220         msg_Err( p_sql, "sqlite3 error: %d: %s",
221                       sqlite3_errcode( p_sql->p_sys->db ),
222                       sqlite3_errmsg( p_sql->p_sys->db ) );
223         return VLC_EGENERIC;
224     }
225     if( sqlite3_busy_timeout( p_sql->p_sys->db, 30000 ) != SQLITE_OK )
226     {
227         msg_Err( p_sql, "sqlite3 error: %d: %s",
228                       sqlite3_errcode( p_sql->p_sys->db ),
229                       sqlite3_errmsg( p_sql->p_sys->db ) );
230         return VLC_EGENERIC;
231     }
232     if( sqlite3_busy_handler( p_sql->p_sys->db, vlc_sqlite_busy_handler, p_sql )
233             != SQLITE_OK )
234     {
235         msg_Err( p_sql, "sqlite3 error: %d: %s",
236                       sqlite3_errcode( p_sql->p_sys->db ),
237                       sqlite3_errmsg( p_sql->p_sys->db ) );
238         return VLC_EGENERIC;
239     }
240
241     return VLC_SUCCESS;
242 }
243
244 /**
245  * @brief Close current database
246  * @param p_sql This sql_t object
247  * @return VLC_SUCCESS
248  * You have to set and open current database first
249  */
250 static int CloseDatabase( sql_t *p_sql )
251 {
252     assert( p_sql->p_sys->db );
253
254     /* Close all prepared statements */
255     sqlite3_stmt* p_stmt;
256     while( ( p_stmt = sqlite3_next_stmt( p_sql->p_sys->db, NULL ) ) != NULL )
257     {
258         if( sqlite3_finalize( p_stmt ) != SQLITE_OK )
259         {
260             msg_Warn( p_sql, "sqlite3 error: %d: %s",
261                       sqlite3_errcode( p_sql->p_sys->db ),
262                       sqlite3_errmsg( p_sql->p_sys->db ) );
263         }
264     }
265
266     /* Close database */
267     /* TODO: We've closed all open prepared statements
268      * Perhaps sqlite3_close can still fail? */
269     sqlite3_close( p_sql->p_sys->db );
270     p_sql->p_sys->db = NULL;
271
272     return VLC_SUCCESS;
273 }
274
275 /**
276  * @brief SQL Query with callback
277  * @param p_sql This sql_t object
278  * @param query SQL query
279  * @param callback Callback function to receive results row by row
280  * @param arg Argument to pass to callback
281  * @return VLC_SUCCESS or an error code
282  * You have to set and open current database first
283  */
284 static int QueryCallback( sql_t * p_sql,
285                           const char * query,
286                           sql_query_callback_t callback,
287                           void *arg )
288 {
289     int i_ret = VLC_SUCCESS;
290     vlc_mutex_lock( &p_sql->p_sys->lock );
291     assert( p_sql->p_sys->db );
292 #ifndef NDEBUG
293     msg_Dbg( p_sql, "QueryCallback: %s", query );
294 #endif
295     sqlite3_exec( p_sql->p_sys->db, query, callback, arg, NULL );
296     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
297     {
298         msg_Warn( p_sql, "sqlite3 error: %d: %s",
299                   sqlite3_errcode( p_sql->p_sys->db ),
300                   sqlite3_errmsg( p_sql->p_sys->db ) );
301         i_ret = VLC_EGENERIC;
302     }
303
304     vlc_mutex_unlock( &p_sql->p_sys->lock );
305     return i_ret;
306 }
307
308 /**
309  * @brief Direct SQL Query
310  * @param p_sql This sql_t object
311  * @param query SQL query
312  * @param result Return value : Array of results
313  * @param nrow Return value : Row number
314  * @param ncol Return value : Column number
315  * @return VLC_SUCCESS or an error code
316  * You have to set and open current database first
317  * @todo Handle transaction closing due to errors in sql query
318  */
319 static int Query( sql_t * p_sql,
320                   const char * query,
321                   char *** result,
322                   int * nrow,
323                   int * ncol )
324 {
325     assert( p_sql->p_sys->db );
326     int i_ret = VLC_SUCCESS;
327     vlc_mutex_lock( &p_sql->p_sys->lock );
328
329 #ifndef NDEBUG
330     msg_Dbg( p_sql, "Query: %s", query );
331 #endif
332     sqlite3_get_table( p_sql->p_sys->db, query, result, nrow, ncol, NULL );
333     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
334     {
335         msg_Warn( p_sql, "sqlite3 error: %d: %s",
336                   sqlite3_errcode( p_sql->p_sys->db ),
337                   sqlite3_errmsg( p_sql->p_sys->db ) );
338         i_ret = VLC_EGENERIC;
339     }
340
341     vlc_mutex_unlock( &p_sql->p_sys->lock );
342     return i_ret;
343 }
344
345 /**
346  * @brief Get tables in database
347  * @param p_sql This sql_t object
348  * @param result SQL query result
349  * @return Number of elements
350  * You have to set and open current database first
351  */
352 static int GetTables( sql_t * p_sql,
353                       char *** result )
354 {
355     int nrow, i_num = -1;
356
357     vlc_mutex_lock( &p_sql->p_sys->lock );
358
359     assert( p_sql->p_sys->db );
360
361     sqlite3_get_table( p_sql->p_sys->db, "SELECT * FROM sqlite_master;",
362                        result, &nrow, &i_num, NULL );
363     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
364     {
365         msg_Warn( p_sql, "sqlite3 error: %d: %s",
366                   sqlite3_errcode( p_sql->p_sys->db ),
367                   sqlite3_errmsg( p_sql->p_sys->db ) );
368     }
369     vlc_mutex_unlock( &p_sql->p_sys->lock );
370     return i_num;
371 }
372
373 /**
374  * @brief Free SQL request's result
375  * @param p_sql This SQL object.
376  * @param ppsz_result SQL result to free
377  */
378 static void FreeResult( sql_t * p_sql, char **ppsz_result )
379 {
380     VLC_UNUSED( p_sql );
381     if( ppsz_result != NULL )
382         sqlite3_free_table( ppsz_result );
383 }
384
385 /**
386  * @brief vmprintf replacement for SQLite.
387  * @param psz_fmt Format string
388  * @param args va_list of arguments
389  * This function implements the formats %q, %Q and %z.
390  */
391 static char* VMSprintf( const char* psz_fmt, va_list args )
392 {
393     char *psz = sqlite3_vmprintf( psz_fmt, args );
394     char *ret = strdup( psz );
395     sqlite3_free( psz );
396     return ret;
397 }
398
399 /**
400  * @brief Starts a Transaction and waits if necessary
401  * @param p_sql The SQL object
402  * @note This function locks the transactions on the database.
403  * Within the period of the transaction, only the calling thread may
404  * execute sql statements provided all threads use these transaction fns.
405  */
406 static int BeginTransaction( sql_t* p_sql )
407 {
408     int i_ret = VLC_SUCCESS;
409     vlc_mutex_lock( &p_sql->p_sys->trans_lock );
410     vlc_mutex_lock( &p_sql->p_sys->lock );
411     assert( p_sql->p_sys->db );
412
413     sqlite3_exec( p_sql->p_sys->db, "BEGIN;", NULL, NULL, NULL );
414 #ifndef NDEBUG
415     msg_Dbg( p_sql, "Transaction Query: BEGIN;" );
416 #endif
417     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
418     {
419         vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
420         vlc_mutex_unlock( &p_sql->p_sys->lock );
421         msg_Warn( p_sql, "sqlite3 error: %d: %s",
422                   sqlite3_errcode( p_sql->p_sys->db ),
423                   sqlite3_errmsg( p_sql->p_sys->db ) );
424         i_ret = VLC_EGENERIC;
425     }
426     vlc_mutex_unlock( &p_sql->p_sys->lock );
427     return i_ret;
428 }
429
430 /**
431  * @brief Commit a transaction
432  * @param p_sql The SQL object
433  * @note This function unlocks the transactions on the database
434  * Only the calling thread of "BeginTransaction" is allowed to call this method
435  * If the commit fails, the transaction lock is still held by the thread
436  * and this function may be retried or RollbackTransaction can be called
437  * @return VLC_SUCCESS or VLC_EGENERIC
438  */
439 static int CommitTransaction( sql_t* p_sql )
440 {
441     int i_ret = VLC_SUCCESS;
442     assert( p_sql->p_sys->db );
443     vlc_mutex_lock( &p_sql->p_sys->lock );
444
445     /** This turns the auto commit on. */
446     sqlite3_exec( p_sql->p_sys->db, "COMMIT;", NULL, NULL, NULL );
447 #ifndef NDEBUG
448     msg_Dbg( p_sql, "Transaction Query: COMMIT;" );
449 #endif
450     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
451     {
452         msg_Warn( p_sql, "sqlite3 error: %d: %s",
453                   sqlite3_errcode( p_sql->p_sys->db ),
454                   sqlite3_errmsg( p_sql->p_sys->db ) );
455         vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
456         i_ret = VLC_EGENERIC;
457     }
458     vlc_mutex_unlock( &p_sql->p_sys->lock );
459     return i_ret;
460 }
461
462 /**
463  * @brief Rollback a transaction, in case of failure
464  * @param p_sql The SQL object
465  * @return VLC_SUCCESS or VLC_EGENERIC
466  * @note This function unlocks the transactions on the database
467  * Only the calling thread of "BeginTransaction" is allowed to call this method
468  * If failed, if a statement in the transaction failed, it means that
469  * the transaction was automatically rolled back
470  * If failed otherwise, the engine is busy executing some queries and you must
471  * try again
472  */
473 static void RollbackTransaction( sql_t* p_sql )
474 {
475     assert( p_sql->p_sys->db );
476     vlc_mutex_lock( &p_sql->p_sys->lock );
477
478     sqlite3_exec( p_sql->p_sys->db, "ROLLBACK;", NULL, NULL, NULL );
479 #ifndef NDEBUG
480     msg_Dbg( p_sql, "Transaction Query: ROLLBACK;" );
481 #endif
482     if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
483     {
484         msg_Err( p_sql, "sqlite3 error: %d: %s",
485                   sqlite3_errcode( p_sql->p_sys->db ),
486                   sqlite3_errmsg( p_sql->p_sys->db ) );
487     }
488     vlc_mutex_unlock( &p_sql->p_sys->trans_lock );
489     vlc_mutex_unlock( &p_sql->p_sys->lock );
490 }
491
492 /**
493  * Prepare an sqlite statement
494  * @return statement object or NULL in case of failure
495  */
496 static sql_stmt_t* PrepareStatement( sql_t* p_sql, const char* psz_fmt, int i_length )
497 {
498     assert( p_sql->p_sys->db );
499     sql_stmt_t* p_stmt;
500     p_stmt = calloc( 1, sizeof( *p_stmt ) );
501     if( p_stmt == NULL )
502         return NULL;
503     vlc_mutex_lock( &p_sql->p_sys->lock );
504     if( sqlite3_prepare_v2( p_sql->p_sys->db, psz_fmt, i_length,
505                             &p_stmt->p_sqlitestmt, NULL ) != SQLITE_OK )
506     {
507         msg_Warn( p_sql, "sqlite3 error: %d: %s",
508                   sqlite3_errcode( p_sql->p_sys->db ),
509                   sqlite3_errmsg( p_sql->p_sys->db ) );
510         vlc_mutex_unlock( &p_sql->p_sys->lock );
511         free( p_stmt );
512         return NULL;
513     }
514
515     vlc_mutex_unlock( &p_sql->p_sys->lock );
516     return p_stmt;
517 }
518
519 /**
520  * @brief Bind arguments to a sql_stmt_t object
521  * @param p_sql The SQL object
522  * @param p_stmt Statement Object
523  * @param i_pos Position at which the parameter should be bound
524  * @param i_type Data type of the value
525  * @param p_value Value to be bound
526  * @return VLC_SUCCESS or VLC_EGENERIC
527  */
528 static int BindValues( sql_t* p_sql, sql_stmt_t* p_stmt,
529         int i_pos, unsigned int i_type, const sql_value_t* p_value )
530 {
531     assert( p_sql->p_sys->db );
532     assert( p_stmt->p_sqlitestmt );
533     vlc_mutex_lock( &p_sql->p_sys->lock );
534     int i_ret, i_vlc_ret = VLC_SUCCESS;
535     switch( i_type )
536     {
537         case SQL_INT:
538             i_ret = sqlite3_bind_int( p_stmt->p_sqlitestmt, i_pos, p_value->value.i );
539             break;
540         case SQL_DOUBLE:
541             i_ret = sqlite3_bind_double( p_stmt->p_sqlitestmt, i_pos, p_value->value.dbl );
542             break;
543         case SQL_TEXT:
544             i_ret = sqlite3_bind_text( p_stmt->p_sqlitestmt, i_pos, p_value->value.psz, p_value->length, NULL );
545             break;
546         case SQL_BLOB:
547             i_ret = sqlite3_bind_blob( p_stmt->p_sqlitestmt, i_pos, p_value->value.ptr, p_value->length, NULL );
548             break;
549         case SQL_NULL:
550             i_ret = sqlite3_bind_null( p_stmt->p_sqlitestmt, i_pos );
551             break;
552         default:
553             msg_Warn( p_sql, "Trying to bind invalid type of value %d", i_type );
554             vlc_mutex_unlock( &p_sql->p_sys->lock );
555             return VLC_EGENERIC;
556     }
557     if( i_ret != SQLITE_OK )
558     {
559         msg_Warn( p_sql, "sqlite3 error: %d: %s",
560                   sqlite3_errcode( p_sql->p_sys->db ),
561                   sqlite3_errmsg( p_sql->p_sys->db ) );
562         i_vlc_ret = VLC_EGENERIC;
563     }
564     vlc_mutex_unlock( &p_sql->p_sys->lock );
565     return i_vlc_ret;
566 }
567
568 /**
569  * @brief Run the SQL statement. If the statement fetches data, then only
570  * one row of the data is fetched at a time. Run this function again to
571  * fetch the next row.
572  * @param p_sql The SQL object
573  * @param p_stmt The statement
574  * @return VLC_SQL_DONE if done fetching all rows or there are no rows to fetch
575  * VLC_SQL_ROW if a row was fetched for this statement.
576  * VLC_EGENERIC if this function failed
577  */
578 static int StatementStep( sql_t* p_sql, sql_stmt_t* p_stmt )
579 {
580     assert( p_sql->p_sys->db );
581     assert( p_stmt->p_sqlitestmt );
582     vlc_mutex_lock( &p_sql->p_sys->lock );
583     int i_sqlret = sqlite3_step( p_stmt->p_sqlitestmt );
584     int i_ret = VLC_EGENERIC;
585     if( i_sqlret == SQLITE_ROW )
586         i_ret = VLC_SQL_ROW;
587     else if( i_ret == SQLITE_DONE )
588         i_ret = VLC_SQL_DONE;
589     else
590     {
591        msg_Warn( p_sql, "sqlite3 error: %d: %s",
592                   sqlite3_errcode( p_sql->p_sys->db ),
593                   sqlite3_errmsg( p_sql->p_sys->db ) );
594        i_ret = VLC_EGENERIC;
595     }
596     vlc_mutex_unlock( &p_sql->p_sys->lock );
597     return i_ret;
598 }
599
600 /**
601  * @brief Reset the SQL statement. Resetting the statement will unbind all
602  * the values that were bound on this statement
603  * @param p_sql The SQL object
604  * @param p_stmt The sql statement object
605  * @return VLC_SUCCESS or VLC_EGENERIC
606  */
607 static int StatementReset( sql_t* p_sql, sql_stmt_t* p_stmt )
608 {
609     assert( p_sql->p_sys->db );
610     assert( p_stmt->p_sqlitestmt );
611     int i_ret = VLC_SUCCESS;
612     vlc_mutex_lock( &p_sql->p_sys->lock );
613     if( sqlite3_reset( p_stmt->p_sqlitestmt ) != SQLITE_OK )
614     {
615         msg_Warn( p_sql, "sqlite3 error: %d: %s",
616                   sqlite3_errcode( p_sql->p_sys->db ),
617                   sqlite3_errmsg( p_sql->p_sys->db ) );
618         i_ret = VLC_EGENERIC;
619     }
620     vlc_mutex_unlock( &p_sql->p_sys->lock );
621     return i_ret;
622 }
623
624 /**
625  * @brief Destroy the sql statement object. This will free memory.
626  * @param p_sql The SQL object
627  * @param p_stmt The statement object
628  * @return VLC_SUCCESS or VLC_EGENERIC
629  */
630 static int StatementFinalize( sql_t* p_sql, sql_stmt_t* p_stmt )
631 {
632     assert( p_sql->p_sys->db );
633     assert( p_stmt->p_sqlitestmt );
634     int i_ret = VLC_SUCCESS;
635     vlc_mutex_lock( &p_sql->p_sys->lock );
636     if( sqlite3_finalize( p_stmt->p_sqlitestmt ) != SQLITE_OK )
637     {
638         msg_Warn( p_sql, "sqlite3 error: %d: %s",
639                   sqlite3_errcode( p_sql->p_sys->db ),
640                   sqlite3_errmsg( p_sql->p_sys->db ) );
641         i_ret = VLC_EGENERIC;
642     }
643     free( p_stmt );
644     vlc_mutex_unlock( &p_sql->p_sys->lock );
645     return i_ret;
646 }
647
648 /**
649  * @brief Get the column data
650  * @param p_sql The SQL object
651  * @param p_stmt The statement object
652  * @param i_col The column number
653  * @param type Datatype of result
654  * @param p_res The structure which contains the value of the result
655  * @return VLC_SUCCESS or VLC_EGENERIC
656  */
657 static int GetColumnFromStatement( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col,
658                           int type, sql_value_t *p_res )
659 {
660     assert( p_sql->p_sys->db );
661     assert( p_stmt->p_sqlitestmt );
662     int i_ret = VLC_SUCCESS;
663     vlc_mutex_lock( &p_sql->p_sys->lock );
664     const unsigned char* psz;
665     const void* ptr;
666     int size;
667     switch( type )
668     {
669         case SQL_INT:
670             p_res->value.i = sqlite3_column_int( p_stmt->p_sqlitestmt, i_col );
671             break;
672         case SQL_DOUBLE:
673             p_res->value.dbl = sqlite3_column_double( p_stmt->p_sqlitestmt, i_col );
674             break;
675         case SQL_TEXT:
676             psz = sqlite3_column_text( p_stmt->p_sqlitestmt, i_col );
677             if( psz )
678                 p_res->value.psz = strdup( (const char* ) psz );
679             break;
680         case SQL_BLOB:
681             ptr = sqlite3_column_blob( p_stmt->p_sqlitestmt, i_col );
682             size = sqlite3_column_bytes( p_stmt->p_sqlitestmt, i_col );
683             if( ptr )
684             {
685                 p_res->value.ptr = malloc( size );
686                 p_res->length = size;
687                 if( p_res->value.ptr )
688                     memcpy( p_res->value.ptr, ptr, size );
689                 else
690                     i_ret = VLC_ENOMEM;
691             }
692             break;
693         case SQL_NULL:
694         default:
695             msg_Warn( p_sql, "Trying to bind invalid type of value %d", type );
696             i_ret = VLC_EGENERIC;
697     }
698     vlc_mutex_unlock( &p_sql->p_sys->lock );
699     return i_ret;
700 }
701
702 /**
703  * @brief Get the datatype of the result of the column
704  * @param p_sql The SQL object
705  * @param p_stmt The sql statement object
706  * @param i_col The column
707  * @param pi_type pointer to datatype of the given column
708  * @return VLC_SUCCESS or VLC_EGENERIC
709  */
710 static int GetColumnTypeFromStatement( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col,
711                         int* pi_type )
712 {
713     assert( p_sql->p_sys->db );
714     assert( p_stmt->p_sqlitestmt );
715     assert( pi_type );
716     vlc_mutex_lock( &p_sql->p_sys->lock );
717     int i_ret = VLC_SUCCESS;
718     int i_sqlret = sqlite3_column_type( p_stmt->p_sqlitestmt, i_col );
719     switch( i_sqlret )
720     {
721         case SQLITE_INTEGER:
722             *pi_type = SQL_INT;
723             break;
724         case SQLITE_FLOAT:
725             *pi_type= SQL_DOUBLE;
726             break;
727         case SQLITE_TEXT:
728             *pi_type = SQL_TEXT;
729             break;
730         case SQLITE_BLOB:
731             *pi_type = SQL_BLOB;
732             break;
733         case SQLITE_NULL:
734             *pi_type = SQL_NULL;
735             break;
736         default:
737             i_ret = VLC_EGENERIC;
738     }
739     vlc_mutex_unlock( &p_sql->p_sys->lock );
740     return i_ret;
741 }
742
743 /**
744  * @brief Get the size of the column in bytes
745  * @param p_sql The SQL object
746  * @param p_stmt The sql statement object
747  * @param i_col The column
748  * @return Size of the column in bytes, undefined for invalid columns
749  */
750 static int GetColumnSize( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col )
751 {
752     assert( p_sql->p_sys->db );
753     assert( p_stmt->p_sqlitestmt );
754     return sqlite3_column_bytes( p_stmt->p_sqlitestmt, i_col );
755 }