ermetadb_local.c

Go to the documentation of this file.
00001 /*
00002  * File Name  : ermetadb_local.c
00003  * 
00004  * Description: Functions to access local metadb's
00005  */
00006 
00007 /*
00008  * This file is part of libermetadb.
00009  *
00010  * libermetadb is free software: you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation, either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * libermetadb is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00022  */
00023 
00024 /**
00025  * Copyright (C) 2008 iRex Technologies B.V.
00026  * All rights reserved.
00027  */
00028 
00029 //----------------------------------------------------------------------------
00030 // Include Files
00031 //----------------------------------------------------------------------------
00032 
00033 // system include files, between < >
00034 #include <glib.h>
00035 #include <string.h>
00036 
00037 // ereader include files, between < >
00038 #include <liberutils/er_error.h>
00039 
00040 // local include files, between " "
00041 #include "ermetadb_log.h"
00042 #include "ermetadb.h"
00043 #include "ermetadb_error.h"
00044 #include "ermetadb_private.h"
00045 #include "sqlite3_wrapper.h"
00046 
00047 #define LOCAL_MAX_COLUMNS  12
00048 static const struct
00049              {
00050                  const char     *table_name;
00051                  const char     *column_names[LOCAL_MAX_COLUMNS+1];
00052              } local_database_tables[]
00053              =
00054              {
00055                 {
00056                     "application_data",
00057                     {
00058                         "file_id",
00059                         "key",
00060                         "value",
00061                          NULL
00062                     }
00063                 },
00064                 { 
00065                     "annotations",
00066                     {
00067                         "annotation_id",
00068                         "file_id",
00069                         "annotation_type",
00070                         "layer",
00071                         "file_position",
00072                         "title",
00073                         "start_anchor",
00074                         "end_anchor",
00075                         "data",
00076                         NULL
00077                     }
00078                 },
00079                 { 
00080                     "file_metadata",
00081                     {
00082                         "file_id",
00083                         "filename",
00084                         NULL
00085                     }
00086                 },
00087                 {
00088                     NULL,
00089                     {}
00090                 }
00091              };
00092 
00093 #define CHECK_LOCAL \
00094     g_assert(thiz); \
00095     g_assert(thiz->database); \
00096     g_assert(!thiz->is_global);
00097 
00098 
00099 //============================================================================
00100 // Functions Implementation
00101 //============================================================================
00102 
00103 static const char* const * get_local_column_names(const char* table)
00104 {
00105     TRACE("entry: table [%s]", table);
00106     g_assert(table);
00107 
00108     int i;
00109     for (i = 0 ; local_database_tables[i].table_name; i++)
00110     {
00111         if ( strcmp(local_database_tables[i].table_name, table) == 0 )
00112         {
00113             return local_database_tables[i].column_names;
00114         }
00115     }
00116     return NULL;
00117 }
00118 
00119 
00120 static gint64 get_local_id(erMetadb thiz, const char* filename)
00121 {
00122     // build query
00123     char *query = sqlite3_mprintf("SELECT file_id FROM file_metadata WHERE filename = %Q LIMIT 1;",
00124                 filename);
00125 
00126     metadata_table *result = NULL;
00127     int rc = sql3_execute_query(thiz->database, query, NULL, &result);
00128     gint64 file_id = -1;
00129     if (rc == ER_OK && result) {
00130         const metadata_cell *cell = metadata_table_get_cell(result, 0);
00131         g_assert(cell->type == METADATA_INT64);
00132         file_id = cell->value.v_int64;
00133     }
00134 
00135     sqlite3_free(query);
00136     metadata_table_free(result);
00137     return file_id;
00138 }
00139 
00140 
00141 int ermetadb_local_remove_annotation (erMetadb thiz, const gint64 annotation_id)
00142 {
00143     LOGPRINTF("annotation_id [%lld]", annotation_id);
00144 
00145     CHECK_LOCAL
00146 
00147     char query[255];
00148     sprintf(query, "DELETE FROM annotations WHERE annotation_id = %lld", annotation_id );
00149     int rc = sql3_execute_query(thiz->database, query, NULL, NULL);
00150     if (rc != ER_OK)
00151     {
00152         ERRORPRINTF("cannot delete annotation, sql [%s]", query);
00153         rc = ERMETADB_FAIL;
00154     }
00155     return rc;
00156 }
00157 
00158 
00159 // set annotation details, without begin/commit transaction
00160 static int set_annotation_impl (erMetadb        thiz,
00161                                 const gint64    annotation_id,
00162                                 const gchar     *annotation_type,
00163                                 const gchar     *layer,
00164                                 const gint64    file_position,
00165                                 const gchar     *title,
00166                                 const gchar     *start_anchor,
00167                                 const gchar     *end_anchor,
00168                                 const gchar     *data_blob,
00169                                 const guint     data_len )
00170 {
00171     TRACE("annotation_id [%lld]", annotation_id);
00172 
00173     g_return_val_if_fail( annotation_type, ER_INVALID_PARAMETER );
00174     g_return_val_if_fail( layer, ER_INVALID_PARAMETER );
00175     g_return_val_if_fail( file_position >= 0, ER_INVALID_PARAMETER );
00176     g_return_val_if_fail( (start_anchor == NULL || start_anchor[0] != 0), ER_INVALID_PARAMETER );
00177     g_return_val_if_fail( (end_anchor == NULL || end_anchor[0] != 0), ER_INVALID_PARAMETER );
00178     g_return_val_if_fail( (data_blob == NULL || data_len > 0), ER_INVALID_PARAMETER );
00179 
00180     // build sql query
00181     GString *sql = g_string_new("");
00182     char *sql3_annotype = sqlite3_mprintf("%Q", annotation_type);
00183     char *sql3_layer    = sqlite3_mprintf("%Q", layer);
00184     g_string_printf(        sql, "UPDATE annotations"
00185                                  " SET annotation_type = %s,"
00186                                      " layer = %s,"
00187                                      " file_position = %lld",
00188                             sql3_annotype,
00189                             sql3_layer,
00190                             file_position );
00191     sqlite3_free(sql3_layer   );
00192     sqlite3_free(sql3_annotype);
00193 
00194     g_string_append(        sql, ", title = " );
00195     if (title)
00196     {
00197         char *sql3_string = sqlite3_mprintf("%Q", title);
00198         g_string_append( sql, sql3_string );
00199         sqlite3_free(sql3_string);
00200     }
00201     else
00202     {
00203         // clear old title
00204         g_string_append(    sql, "NULL" );
00205     }
00206 
00207     g_string_append(        sql, ", start_anchor = " );
00208     if (start_anchor)
00209     {
00210         char *sql3_string = sqlite3_mprintf("%Q", start_anchor);
00211         g_string_append( sql, sql3_string );
00212         sqlite3_free(sql3_string);
00213     }
00214     else
00215     {
00216         // clear old anchor
00217         g_string_append(    sql, "NULL" );
00218     }
00219 
00220     g_string_append(        sql, ", end_anchor = " );
00221     if (end_anchor)
00222     {
00223         char *sql3_string = sqlite3_mprintf("%Q", end_anchor);
00224         g_string_append( sql, sql3_string);
00225         sqlite3_free(sql3_string);
00226     }
00227     else
00228     {
00229         // clear old anchor
00230         g_string_append(    sql, "NULL" );
00231     }
00232 
00233     g_string_append(        sql, ", data = " );
00234     metadata_table *parameters = NULL;
00235     if (data_blob)
00236     {
00237         parameters = metadata_table_new();
00238         metadata_table_add_column( parameters, "data" );
00239         metadata_table_set_blob_static( parameters, 0, data_blob, data_len );
00240         g_string_append(        sql, "?1" );
00241     }
00242     else
00243     {
00244         // clear old data
00245         g_string_append(        sql, "NULL" );
00246     }
00247 
00248     g_string_append_printf( sql, " WHERE annotation_id = %lld;",
00249                             annotation_id );
00250 
00251     // execute query
00252     int rc = sql3_execute_query(thiz->database, sql->str, parameters, NULL);
00253     if (rc != ER_OK)
00254     {
00255         ERRORPRINTF("cannot set annotation details, sql [%s]", sql->str);
00256         rc = ERMETADB_FAIL;
00257     }
00258 
00259     metadata_table_free(parameters);
00260     return rc;
00261 }
00262 
00263 
00264 static gint64 find_or_create_filename(erMetadb thiz, const char* filename)
00265 {
00266     gint64 file_id = get_local_id(thiz, filename);
00267     if (file_id < 0) {
00268         char *sql = sqlite3_mprintf("INSERT INTO file_metadata (filename) VALUES (%Q);", filename);
00269         int rc = sql3_execute_query(thiz->database, sql, NULL, NULL);
00270         sqlite3_free(sql);
00271         if (rc != ER_OK)
00272         {
00273             ERRORPRINTF("cannot add filename [%s]", filename);
00274             return -1;
00275         }
00276         file_id = sqlite3_last_insert_rowid(thiz->database);
00277     }
00278     return file_id;
00279 }
00280 
00281 
00282 int ermetadb_local_create_annotation (erMetadb     thiz,
00283                                       const gchar  *filename,
00284                                       gint64       *annotation_id,
00285                                       const gchar  *annotation_type,
00286                                       const gchar  *layer,
00287                                       const gint64 file_position,
00288                                       const gchar  *title,
00289                                       const gchar  *start_anchor,
00290                                       const gchar  *end_anchor,
00291                                       const gchar  *data_blob,
00292                                       const guint  data_len )
00293 {
00294     LOGPRINTF("file [%s]", filename);
00295 
00296     CHECK_LOCAL
00297     g_assert(filename && filename[0]);
00298     g_assert(annotation_id);
00299 
00300     gint64 anno_id = -1;
00301 
00302     int ret = sql3_begin_transaction(thiz);
00303     if (ret != ER_OK) return ret;
00304 
00305     gint64 file_id = find_or_create_filename(thiz, filename);
00306     if (file_id < 0) {
00307         ret = ER_FAIL;
00308         goto out;
00309     }
00310 
00311     // create an empty annotation
00312     // build query
00313     GString *sql = g_string_new("");  // SQL statements
00314     g_string_printf( sql, "INSERT INTO annotations"
00315                           " (file_id, annotation_type, layer, file_position)"
00316                           " VALUES (%lld, 'dummy', 'dummy', 0 )",
00317                      file_id );
00318 
00319     // execute query
00320     int rc = sql3_execute_query(thiz->database, sql->str, NULL, NULL);
00321     if (rc != ER_OK)
00322     {
00323         ERRORPRINTF("cannot create annotation, sql [%s]", sql->str);
00324         ret = ERMETADB_FAIL;
00325     }
00326     else
00327     {
00328         // retrieve the new annotation_id
00329         anno_id = sqlite3_last_insert_rowid(thiz->database);
00330     }
00331     g_string_free(sql, TRUE);
00332 
00333     // set annotation fields
00334     if (ret == ER_OK)
00335     {
00336         ret = set_annotation_impl( thiz,
00337                                    anno_id,
00338                                    annotation_type,
00339                                    layer,
00340                                    file_position,
00341                                    title,
00342                                    start_anchor,
00343                                    end_anchor,
00344                                    data_blob,
00345                                    data_len        );
00346     }
00347 out:
00348     ret = sql3_commit_or_rollback(thiz, ret);
00349 
00350     *annotation_id = anno_id;
00351     return ret;
00352 }
00353 
00354 
00355 int ermetadb_local_set_annotation (erMetadb      thiz,
00356                                    const gint64  annotation_id,
00357                                    const gchar   *annotation_type,
00358                                    const gchar   *layer,
00359                                    const gint64  file_position,
00360                                    const gchar   *title,
00361                                    const gchar   *start_anchor,
00362                                    const gchar   *end_anchor,
00363                                    const gchar   *data_blob,
00364                                    const guint   data_len )
00365 {
00366     LOGPRINTF("annotation_id [%lld]", annotation_id);
00367 
00368     CHECK_LOCAL
00369     g_assert(annotation_id);
00370 
00371     int ret = sql3_begin_transaction(thiz);
00372     if (ret != ER_OK) return ret;
00373 
00374     ret = set_annotation_impl( thiz,
00375                                annotation_id,
00376                                annotation_type,
00377                                layer,
00378                                file_position,
00379                                title,
00380                                start_anchor,
00381                                end_anchor,
00382                                data_blob,
00383                                data_len        );
00384 
00385     ret = sql3_commit_or_rollback(thiz, ret);
00386     return ret;
00387 }
00388 
00389 
00390 // get annotation details for a list of annotations
00391 int ermetadb_local_get_annotations (erMetadb       thiz,
00392                                     const gint64   *annotation_id_list,
00393                                     long           annotation_id_num,
00394                                     metadata_table **values_tbl        )
00395 {
00396     LOGPRINTF("entry");
00397 
00398     CHECK_LOCAL
00399     g_return_val_if_fail(  annotation_id_list                , ER_INVALID_PARAMETER );
00400     g_return_val_if_fail(  annotation_id_num >= 0            , ER_INVALID_PARAMETER );
00401     g_return_val_if_fail( (values_tbl && *values_tbl == NULL), ER_INVALID_PARAMETER );
00402 
00403     // get known column names
00404     GString *columns = g_string_new("");
00405     const char* const *name;
00406     for ( name = get_local_column_names( "annotations" ) ; *name ; name++ )
00407     {
00408         if ( strcmp(*name, "file_id" ) != 0 )
00409         {
00410             if (columns->len != 0) g_string_append( columns, ", "  );
00411             g_string_append( columns, *name );
00412         }
00413     }
00414 
00415     metadata_table *result = NULL;
00416 
00417     int ret = sql3_begin_transaction_readonly(thiz);
00418     if (ret != ER_OK) goto out;
00419 
00420     // build sql
00421     const gint64 *p_anno = annotation_id_list;
00422     GString *sql = g_string_new("");  // SQL query
00423     g_string_printf( sql, "SELECT %s"
00424                           " FROM annotations"
00425                           " WHERE annotation_id IN (%lld",
00426                      columns->str,
00427                      *p_anno      );
00428     p_anno++;
00429     int i;
00430     for ( i = 1 ; i < annotation_id_num ; i++ )
00431     {
00432         g_string_append_printf( sql, ", %lld", *p_anno );
00433         p_anno++;
00434     }
00435     g_string_append( sql, ");" );
00436 
00437     // execute query
00438     int rc = sql3_execute_query(thiz->database, sql->str, NULL, &result);
00439     if (rc != ER_OK)
00440     {
00441         ERRORPRINTF("cannot get metadata, sql [%s]", sql->str);
00442         ret = ER_NOT_FOUND;
00443     }
00444     g_string_free(sql, TRUE);
00445 
00446     // NOTE can turn ok into fail!
00447     ret = sql3_commit_or_rollback(thiz, ret);
00448 out:
00449     g_string_free(columns, TRUE);
00450 
00451     *values_tbl = result;
00452     return ret;
00453 }
00454 
00455 
00456 // get a range of annotations's for a file/folder
00457 int ermetadb_local_select_annotations (erMetadb        thiz,
00458                                        const gchar     *filename,
00459                                        const gchar     *annotation_type,
00460                                        const gchar     *layer,
00461                                        const gint64    file_position_min,
00462                                        const gint64    file_position_max,
00463                                        metadata_table  **values_tbl )
00464 {
00465     LOGPRINTF("file [%s]", filename);
00466 
00467     CHECK_LOCAL
00468     g_assert(filename && filename[0]);
00469     g_return_val_if_fail( (annotation_type == NULL || annotation_type[0] != 0), ER_INVALID_PARAMETER );
00470     g_return_val_if_fail( values_tbl && *values_tbl == NULL, ER_INVALID_PARAMETER );
00471 
00472     // start transaction
00473     int ret = sql3_begin_transaction_readonly(thiz);
00474     if (ret != ER_OK) return ret;
00475 
00476     metadata_table *result = NULL;
00477     
00478     gint64 file_id = get_local_id(thiz, filename);
00479     if (file_id < 0) goto out;
00480 
00481     // build sql
00482     GString *sql = g_string_new("");
00483     g_string_printf( sql, "SELECT annotation_id"
00484                                ", annotation_type"
00485                                ", layer"
00486                                ", file_position"
00487                                ", start_anchor"
00488                                ", end_anchor"
00489                           " FROM annotations"
00490                           " WHERE file_id = %lld",
00491                      file_id );
00492     if (annotation_type)
00493     {
00494         char *str = sqlite3_mprintf("%Q", annotation_type);
00495         g_string_append_printf(sql, " AND annotation_type = %s", str);
00496         sqlite3_free(str);
00497     }
00498     if (layer)
00499     {
00500         char *str = sqlite3_mprintf("%Q", layer);
00501         g_string_append_printf(sql, " AND layer = %s", str);
00502         sqlite3_free(str);
00503     }
00504     if (file_position_min >= 0)
00505     {
00506         g_string_append_printf(sql, " AND file_position >= %lld", file_position_min);
00507     }
00508     if (file_position_max >= 0)
00509     {
00510         g_string_append_printf(sql, " AND file_position <= %lld", file_position_max);
00511     }
00512     g_string_append(sql, "ORDER BY file_position, annotation_type, layer;");
00513 
00514     // execute query
00515     int rc = sql3_execute_query(thiz->database, sql->str, NULL, &result);
00516     if (rc != ER_OK)
00517     {
00518         ERRORPRINTF("cannot get annotations, sql [%s]", sql->str);
00519         ret = ER_NOT_FOUND;
00520     }
00521     g_string_free(sql, TRUE);
00522 
00523 out:
00524     ret = sql3_commit_or_rollback(thiz, ret);
00525 
00526     *values_tbl = result;
00527     return ret;
00528 }
00529 
00530 
00531 static int local_delete_all_annotations (erMetadb thiz, gint64 file_id)
00532 {
00533     char query[255];
00534     sprintf(query, "DELETE FROM annotations WHERE file_id=%lld;", file_id );
00535     int rc = sql3_execute_query(thiz->database, query, NULL, NULL);
00536     if (rc != ER_OK)
00537     {
00538         ERRORPRINTF("cannot delete annotations, sql [%s]", query);
00539         rc = ERMETADB_FAIL;
00540     }
00541     return rc;
00542 }
00543 
00544 
00545 static GString *get_keys(const metadata_table *names_tbl)
00546 {
00547     GString *sql_keys = g_string_new("");
00548     int n_cols = metadata_table_n_columns(names_tbl);
00549     int col;
00550     for (col = 0 ; col < n_cols ; col++)
00551     {
00552         const metadata_cell *cell = metadata_table_get_cell(names_tbl, col);
00553         if (cell && cell->name && cell->name->str)
00554         {
00555             char *sql3_cellname = sqlite3_mprintf("%Q", cell->name->str);
00556             if (sql_keys->len > 0)
00557             {
00558                 g_string_append(sql_keys, ", ");
00559             }
00560             g_string_append(sql_keys, sql3_cellname);
00561 
00562             sqlite3_free( sql3_cellname );
00563         }
00564     }
00565     return sql_keys;
00566 }
00567 
00568 
00569 int ermetadb_local_remove_application_data (erMetadb             thiz,
00570                                             const gchar          *filename,
00571                                             const metadata_table *names_tbl )
00572 {
00573     LOGPRINTF("file [%s]", filename);
00574 
00575     CHECK_LOCAL
00576     g_assert(filename && filename[0]);
00577     g_return_val_if_fail( names_tbl, ER_INVALID_PARAMETER );
00578     g_return_val_if_fail( (metadata_table_n_rows(names_tbl) == 0), ER_INVALID_PARAMETER );
00579 
00580     gint64 file_id = get_local_id(thiz, filename);
00581     if (file_id < 0) return ER_NOT_FOUND;
00582 
00583     // start transaction
00584     int ret = sql3_begin_transaction(thiz);
00585     if (ret != ER_OK) return ret;
00586 
00587     // build sql query
00588     GString *keys = get_keys(names_tbl);
00589     GString *sql = g_string_new("");
00590     g_string_printf( sql, "DELETE FROM application_data"
00591                           " WHERE file_id=%lld"
00592                           "   AND key IN (%s);",
00593                      file_id, keys->str );
00594     g_string_free(keys, TRUE);
00595 
00596     int rc = sql3_execute_query(thiz->database, sql->str, NULL, NULL);
00597     if (rc != ER_OK)
00598     {
00599         ERRORPRINTF("cannot delete application_data, sql [%s]", sql->str);
00600         ret = ERMETADB_FAIL;
00601     }
00602     g_string_free(sql, TRUE);
00603 
00604     ret = sql3_commit_or_rollback(thiz, ret);
00605     return ret;
00606 }
00607 
00608 
00609 int ermetadb_local_set_application_data (erMetadb             thiz,
00610                                          const gchar          *filename,
00611                                          const metadata_table *values_tbl )
00612 {
00613     LOGPRINTF("file [%s]", filename);
00614 
00615     CHECK_LOCAL
00616     g_assert(filename && filename[0]);
00617     g_return_val_if_fail( values_tbl, ER_INVALID_PARAMETER );
00618     g_return_val_if_fail( (metadata_table_n_rows(values_tbl) == 1), ER_INVALID_PARAMETER );
00619 
00620     gint64 file_id = find_or_create_filename(thiz, filename);
00621     if (file_id < 0) return ER_NOT_FOUND;
00622 
00623     int ret = sql3_begin_transaction(thiz);
00624     if (ret != ER_OK) return ret;
00625 
00626     // build delete and insert statements for sql query
00627     GString *sql_del = NULL;     // SQL delete statement
00628     GString *sql_ins   = NULL;     // SQL insert statements
00629     int n_cols = metadata_table_n_columns(values_tbl);
00630     int col;
00631     for (col = 0 ; col < n_cols ; col++)
00632     {
00633         const metadata_cell*cell = metadata_table_get_cell(values_tbl, col);
00634         if (cell && cell->name && cell->name->str)
00635         {
00636             char* sql3_cellname = sqlite3_mprintf("%Q", cell->name->str);
00637 
00638             if (cell->type == METADATA_NULL)
00639             {
00640                 // add this key to sql delete statement
00641                 if (sql_del == NULL)
00642                 {
00643                     sql_del = g_string_new("");
00644                     g_string_printf( sql_del, "DELETE FROM application_data"
00645                                               " WHERE file_id=%lld"
00646                                               "   AND key IN ( %s",
00647                                      file_id,
00648                                      sql3_cellname );
00649                 }
00650                 else
00651                 {
00652                     g_string_append_printf( sql_del, ", %s", sql3_cellname );
00653                 }
00654             }
00655             else
00656             {
00657                 // add this key to sql_insert statement
00658                 if (sql_ins == NULL)
00659                 {
00660                     sql_ins = g_string_new("");
00661                 }
00662                 g_string_append_printf( sql_ins, "INSERT OR REPLACE INTO application_data"
00663                                                  " (file_id, key, value)"
00664                                                  " VALUES (%lld, %s, ?%d);",
00665                                         file_id,
00666                                         sql3_cellname,
00667                                         col + 1   );
00668             }
00669             sqlite3_free( sql3_cellname );
00670         }
00671     }
00672     if (sql_del) g_string_append( sql_del, " );" );
00673 
00674     // execute delete query
00675     if (sql_del)
00676     {
00677         int rc = sql3_execute_query(thiz->database, sql_del->str, NULL, NULL);
00678         if (rc != ER_OK)
00679         {
00680             ERRORPRINTF("cannot delete application_data, sql [%s]", sql_del->str);
00681             ret = ERMETADB_FAIL;
00682         }
00683     }
00684 
00685     // execute insert query
00686     if (ret == ER_OK && sql_ins)
00687     {
00688         int rc = sql3_execute_query(thiz->database, sql_ins->str, values_tbl, NULL);
00689         if (rc != ER_OK)
00690         {
00691             ERRORPRINTF("cannot insert application_data, sql [%s]", sql_ins->str);
00692             ret = ERMETADB_FAIL;
00693         }
00694     }
00695 
00696     ret = sql3_commit_or_rollback(thiz, ret);
00697 
00698     if (sql_ins) { g_string_free(sql_ins, TRUE); }
00699     if (sql_del) { g_string_free(sql_del, TRUE); }
00700     return ret;
00701 }
00702 
00703 
00704 // rotate table with key-value pairs:
00705 //   in:  table = multiple rows, each row represents a key-value pair
00706 //   out: rotated = single row, each column represents a key-value pair
00707 static metadata_table* rotate_keyval_table(const metadata_table *table)
00708 {
00709     // find 'key' and 'value' columns
00710     int n_keys  = metadata_table_n_rows(table);
00711     int col_key = metadata_table_find_column(table, "key"  );
00712     int col_val = metadata_table_find_column(table, "value");
00713     g_assert(col_key >= 0);
00714     g_assert(col_val >= 0);
00715 
00716     // create new table
00717     metadata_table *rotated = metadata_table_new();
00718 
00719     // convert table.rows into rotated.columns
00720     int key_index;
00721     gboolean ok = TRUE;
00722     for (key_index = 0 ; key_index < n_keys ; key_index++)
00723     {
00724         // set column name = key
00725         GString *key = metadata_table_get_string( table, 
00726                                          metadata_table_cell_index(table, key_index, col_key) );
00727         if (key == NULL || key->len == 0)
00728         {
00729             ERRORPRINTF("cannot read key from row [%d]", key_index);
00730             ok = FALSE;
00731         }
00732         else
00733         {
00734             int rc = metadata_table_add_column(rotated, key->str);
00735             if (rc != ER_OK)
00736             {
00737                 ERRORPRINTF("cannot add column [%s] in rotated, error [%d]", key->str, rc);
00738                 ok = FALSE;
00739             }
00740         }
00741         if (key)
00742         {
00743             g_string_free(key, TRUE);
00744         }
00745 
00746         // set column value = value
00747         if (ok)
00748         {
00749             const metadata_cell *cell = metadata_table_get_cell( table,
00750                                             metadata_table_cell_index(table, key_index, col_val) );
00751             int rc = metadata_table_set_cell( rotated, key_index, cell );
00752             if (rc != ER_OK)
00753             {
00754                 ERRORPRINTF("cannot set value type [%d] in cell, error [%d]", cell->type, rc);
00755                 ok = FALSE;
00756             }
00757         }
00758     }
00759 
00760     if (!ok)
00761     {
00762         metadata_table_free(rotated);
00763     }
00764     return rotated;
00765 }
00766 
00767 
00768 int ermetadb_local_get_application_data (erMetadb             thiz,
00769                                          const gchar          *filename,
00770                                          const metadata_table *names_tbl,
00771                                          metadata_table       **values_tbl )
00772 {
00773     LOGPRINTF("file [%s]", filename);
00774 
00775     CHECK_LOCAL
00776     g_assert(filename && filename[0]);
00777     g_return_val_if_fail( names_tbl, ER_INVALID_PARAMETER );
00778     g_return_val_if_fail( (values_tbl && *values_tbl == NULL ), ER_INVALID_PARAMETER );
00779 
00780     gint64 file_id = get_local_id(thiz, filename);
00781     if (file_id < 0) return ER_NOT_FOUND;
00782 
00783     int ret = sql3_begin_transaction_readonly(thiz);
00784     if (ret != ER_OK) return ret;
00785 
00786     // build sql query
00787     GString *keys = get_keys(names_tbl);
00788     GString *sql = g_string_new("");
00789     g_string_printf( sql, "SELECT key, value"
00790                           " FROM application_data"
00791                           " WHERE file_id=%lld"
00792                           "   AND key IN (%s);",
00793                      file_id,
00794                      keys->str );
00795     g_string_free(keys, TRUE);
00796 
00797     // execute query
00798     metadata_table *result = NULL;
00799     int rc = sql3_execute_query(thiz->database, sql->str, NULL, &result);
00800     if (rc != ER_OK)
00801     {
00802         ERRORPRINTF("cannot get application_data, sql [%s]", sql->str);
00803         ret = ERMETADB_FAIL;
00804     }
00805     g_string_free(sql, TRUE);
00806 
00807     // NOTE: ret can become OK here after rollback!
00808     ret = sql3_commit_or_rollback(thiz, ret);
00809 
00810     // rotate result: one row per key-val --> one column per key-val
00811     metadata_table *rotated = NULL;
00812     if (rc == ER_OK && result)
00813     {
00814         rotated = rotate_keyval_table(result);
00815     }
00816     *values_tbl = rotated;
00817 
00818     metadata_table_free(result);
00819     return ret;
00820 }
00821 
00822 
00823 static int local_delete_all_application_data (erMetadb thiz, gint64 file_id)
00824 {
00825     char query[255];
00826     sprintf(query, "DELETE FROM application_data WHERE file_id=%lld;", file_id );
00827 
00828     int rc = sql3_execute_query(thiz->database, query, NULL, NULL);
00829     if (rc != ER_OK)
00830     {
00831         ERRORPRINTF("cannot delete application_data, sql [%s]", query);
00832         rc = ERMETADB_FAIL;
00833     }
00834     return rc;
00835 }
00836 
00837 
00838 static int local_delete_entry(erMetadb thiz, gint64 file_id)
00839 {
00840     char query[255];
00841     snprintf(query, sizeof(query), "DELETE FROM file_metadata WHERE file_id = %lld;", file_id);
00842     return sql3_execute_query(thiz->database, query, NULL, NULL);
00843 }
00844 
00845 
00846 int local_delete_all_data_for_file(erMetadb thiz, const char* filename)
00847 {
00848     g_assert(!thiz->is_global);
00849 
00850     gint64 file_id = get_local_id(thiz, filename);
00851     if (file_id < 0) return ER_NOT_FOUND;
00852 
00853     return local_delete_all_data_for_id(thiz, file_id);
00854 }
00855 
00856 
00857 int local_delete_all_data_for_id(erMetadb thiz, gint64 file_id)
00858 {
00859     g_assert(!thiz->is_global);
00860 
00861     int ret = sql3_begin_transaction(thiz);
00862     if (ret != ER_OK) return ret;
00863 
00864     // delete annotations, application data and file_metadata entry
00865     local_delete_all_annotations(thiz, file_id);
00866     local_delete_all_application_data(thiz, file_id);
00867     local_delete_entry(thiz, file_id);
00868 
00869     ret = sql3_commit_or_rollback(thiz, ER_OK);
00870     return ret;
00871 
00872 }
00873 
Generated by  doxygen 1.6.2-20100208