gmyth/gmyth/gmyth_query.c
author ali@juiblex.co.uk
Sun Dec 13 22:42:34 2009 +0000 (2009-12-13)
branchtrunk
changeset 948 0399d9ea8b7b
parent 934 608cb47819c6
permissions -rw-r--r--
Don't require higher levels to bookkeep query state
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_query.c
     5  * 
     6  * @brief <p> GMythQuery class provides a wrapper for accessing
     7  * the libmysqlclient funtions.
     8  *
     9  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    10  * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
    11  *
    12  * 
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU Lesser 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 Lesser General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26  */
    27 
    28 #ifdef HAVE_CONFIG_H
    29 #include "config.h"
    30 #endif
    31 
    32 #include <stdlib.h>
    33 #include <stdio.h>
    34 
    35 #include "gmyth_query.h"
    36 #include "gmyth_debug.h"
    37 
    38 static void     gmyth_query_class_init(GMythQueryClass * klass);
    39 static void     gmyth_query_init(GMythQuery * object);
    40 
    41 static void     gmyth_query_dispose(GObject * object);
    42 static void     gmyth_query_finalize(GObject * object);
    43 
    44 static void     gmyth_query_print_error(MYSQL * conn, char *message);
    45 
    46 G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT)
    47     static void     gmyth_query_class_init(GMythQueryClass * klass)
    48 {
    49     GObjectClass   *gobject_class;
    50 
    51     gobject_class = (GObjectClass *) klass;
    52 
    53     gobject_class->dispose = gmyth_query_dispose;
    54     gobject_class->finalize = gmyth_query_finalize;
    55 }
    56 
    57 static void
    58 gmyth_query_init(GMythQuery * gmyth_query)
    59 {
    60     gmyth_query->backend_info = NULL;
    61 
    62     /*
    63      * initialize connection handler 
    64      */
    65     gmyth_query->conn = mysql_init(NULL);
    66 
    67     if (!(gmyth_query->conn))
    68         g_warning("[%s] MSQL structure not initialized", __FUNCTION__);
    69 }
    70 
    71 static void
    72 gmyth_query_dispose(GObject * object)
    73 {
    74     GMythQuery     *gmyth_query = GMYTH_QUERY(object);
    75 
    76     if (gmyth_query->backend_info) {
    77         g_object_unref(gmyth_query->backend_info);
    78         gmyth_query->backend_info = NULL;
    79     }
    80 
    81     G_OBJECT_CLASS(gmyth_query_parent_class)->dispose(object);
    82 }
    83 
    84 static void
    85 gmyth_query_finalize(GObject * object)
    86 {
    87     gmyth_query_disconnect(GMYTH_QUERY(object));
    88 
    89     G_OBJECT_CLASS(gmyth_query_parent_class)->finalize(object);
    90 }
    91 
    92 /** Creates a new instance of GMythQuery.
    93  *
    94  * @return a new instance of GMythQuery.
    95  */
    96 GMythQuery     *
    97 gmyth_query_new()
    98 {
    99     GMythQuery     *sql_query =
   100         GMYTH_QUERY(g_object_new(GMYTH_QUERY_TYPE, NULL));
   101 
   102     return sql_query;
   103 }
   104 
   105 gboolean
   106 gmyth_query_connect_with_timeout(GMythQuery * gmyth_query,
   107                                  GMythBackendInfo * backend_info,
   108                                  guint timeout)
   109 {
   110     g_return_val_if_fail(gmyth_query != NULL, FALSE);
   111 
   112     if (gmyth_query->conn == NULL)
   113         gmyth_query->conn = mysql_init(NULL);
   114 
   115     if (timeout != 0) {
   116       /*
   117        * sets connection timeout
   118        */
   119         mysql_options(gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT,
   120                       (gchar *) & timeout);
   121     }
   122 
   123     return gmyth_query_connect(gmyth_query, backend_info);
   124 }
   125 
   126 /** Connects to the Mysql database in the backend. The backend address
   127  * is loaded from the GMythBackendInfo instance.
   128  *
   129  * @param gmyth_query the GMythEPG instance to be connected.
   130  * @return true if connection was success, false if failed.
   131  */
   132 gboolean
   133 gmyth_query_connect(GMythQuery * gmyth_query,
   134                     GMythBackendInfo * backend_info)
   135 {
   136     g_return_val_if_fail(gmyth_query != NULL, FALSE);
   137     g_return_val_if_fail(backend_info != NULL, FALSE);
   138     g_return_val_if_fail(backend_info->hostname != NULL, FALSE);
   139     g_return_val_if_fail(backend_info->username != NULL, FALSE);
   140     g_return_val_if_fail(backend_info->password != NULL, FALSE);
   141     g_return_val_if_fail(backend_info->db_name != NULL, FALSE);
   142 
   143     if (gmyth_query->backend_info != NULL) {
   144         g_object_unref(gmyth_query->backend_info);
   145     }
   146     gmyth_query->backend_info = g_object_ref(backend_info);
   147 
   148     if (gmyth_query->conn == NULL) {
   149         gmyth_query->conn = mysql_init(NULL);
   150     }
   151 
   152     /*
   153      * connect to server
   154      */
   155     if (mysql_real_connect(gmyth_query->conn,
   156                            gmyth_query->backend_info->hostname,
   157                            gmyth_query->backend_info->username,
   158                            gmyth_query->backend_info->password,
   159                            gmyth_query->backend_info->db_name, 
   160                            gmyth_query->backend_info->db_port, 
   161                            NULL,
   162                            0) == NULL) {
   163         gmyth_query_print_error(gmyth_query->conn,
   164                                 "mysql_real_connect() failed");
   165         return FALSE;
   166     }
   167 
   168     gmyth_debug
   169         ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, "
   170          "password = %s, db name = %s)", __FUNCTION__,
   171          gmyth_query->backend_info->hostname,
   172          gmyth_query->backend_info->username,
   173          gmyth_query->backend_info->password,
   174          gmyth_query->backend_info->db_name);
   175 
   176     return TRUE;
   177 }
   178 
   179 gboolean
   180 gmyth_query_is_alive (GMythQuery *gmyth_query) 
   181 {
   182     g_return_val_if_fail (gmyth_query != NULL, FALSE);
   183 
   184     if (gmyth_query->conn == NULL)
   185         return FALSE;
   186 
   187     return (mysql_ping (gmyth_query->conn) == 0);
   188 }
   189 
   190 
   191 /** Disconnects from the Mysql database in the backend.
   192  * 
   193  * @param gmyth_query the GMythQuery instance to be disconnected
   194  * @return true if disconnection was success, false if failed.
   195  */
   196 gboolean
   197 gmyth_query_disconnect(GMythQuery * gmyth_query)
   198 {
   199     g_return_val_if_fail(gmyth_query != NULL, FALSE);
   200 
   201     if (gmyth_query->conn == NULL)
   202         return TRUE;
   203 
   204     /*
   205      * TODO: Check how to return error 
   206      */
   207     gmyth_debug("[%s] Closing gmyth_query->conn", __FUNCTION__);
   208 
   209     mysql_close(gmyth_query->conn);
   210     gmyth_query->conn = NULL;
   211 
   212     return TRUE;
   213 }
   214 
   215 static void
   216 gmyth_query_print_error(MYSQL * conn, char *message)
   217 {
   218     gmyth_debug("%s", message);
   219 
   220     if (conn != NULL) {
   221 #if MYSQL_VERSION_ID >= 40101
   222         gmyth_debug("Error %u (%s): %s\n",
   223                     mysql_errno(conn), mysql_sqlstate(conn),
   224                     mysql_error(conn));
   225 #else
   226         gmyth_debug("Error %u: %s\n", mysql_errno(conn),
   227                     mysql_error(conn));
   228 #endif
   229     }
   230 }
   231 
   232 /** Sends the given query to the backend returning the query result as
   233  * MYSQL_RES pointer.
   234  * 
   235  * FIXME: this function is returning NULL whether any error happens
   236  * or no rows are returned (e.g. UPDATE or REPLACE).
   237  * 
   238  * @param gmyth_query the GMythQuery instance.
   239  * @param stmt_str the query text.
   240  * @return the MYSQL_RES result pointer or NULL if any error happens.
   241  */
   242 MYSQL_RES*
   243 gmyth_query_process_statement(GMythQuery * gmyth_query, char *stmt_str)
   244 {
   245     g_return_val_if_fail(gmyth_query != NULL, NULL);
   246 
   247     gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
   248 
   249     //the statement failed
   250     if (gmyth_query->conn == NULL ||
   251       mysql_query(gmyth_query->conn, stmt_str) != 0) {
   252         gmyth_query_print_error(gmyth_query->conn,
   253                                 "Could not execute statement");
   254         return NULL;
   255     }
   256 
   257     //the statement succeeded; determine whether it returned data
   258     return mysql_store_result(gmyth_query->conn);
   259 }
   260 
   261 MYSQL_RES*
   262 gmyth_query_process_statement_with_increment(GMythQuery * gmyth_query,
   263                                              char *stmt_str, gulong * id)
   264 {
   265     g_return_val_if_fail(gmyth_query != NULL, NULL);
   266 
   267     gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
   268 
   269     /*
   270      * the statement failed
   271      */
   272     if (gmyth_query->conn == NULL ||
   273       mysql_query(gmyth_query->conn, stmt_str) != 0) {
   274         gmyth_query_print_error(gmyth_query->conn,
   275                                 "Could not execute statement");
   276         return NULL;
   277     }
   278 
   279     *id = (my_ulonglong) mysql_insert_id(gmyth_query->conn);
   280 
   281     /*
   282      * the statement succeeded; determine whether it returned data 
   283      */
   284     return mysql_store_result(gmyth_query->conn);
   285 }