2 * libdbi database backend
4 * Part of Gammu project
6 * Copyright (c) 2009 - 2011 Michal Cihar <michal@cihar.com>
8 * Licensed under GNU GPL version 2 or later
22 #pragma comment(lib, "libdbi.lib")
29 long long SMSDDBI_GetNumber(GSM_SMSDConfig
* Config
, SQL_result
*res
, unsigned int field
)
34 type
= dbi_result_get_field_type_idx(res
->dbi
, field
);
37 case DBI_TYPE_INTEGER
:
38 type
= dbi_result_get_field_attribs_idx(res
->dbi
, field
);
39 if ((type
& DBI_INTEGER_SIZEMASK
) == DBI_INTEGER_SIZE1
) {
40 return dbi_result_get_int_idx(res
->dbi
, field
);
41 } else if ((type
& DBI_INTEGER_SIZEMASK
) == DBI_INTEGER_SIZE2
) {
42 return dbi_result_get_int_idx(res
->dbi
, field
);
43 } else if ((type
& DBI_INTEGER_SIZEMASK
) == DBI_INTEGER_SIZE3
) {
44 return dbi_result_get_int_idx(res
->dbi
, field
);
45 } else if ((type
& DBI_INTEGER_SIZEMASK
) == DBI_INTEGER_SIZE4
) {
46 return dbi_result_get_int_idx(res
->dbi
, field
);
47 } else if ((type
& DBI_INTEGER_SIZEMASK
) == DBI_INTEGER_SIZE8
) {
48 return dbi_result_get_longlong_idx(res
->dbi
, field
);
50 SMSD_Log(DEBUG_ERROR
, Config
, "Wrong integer field subtype from DBI: %d", type
);
52 case DBI_TYPE_DECIMAL
:
53 type
= dbi_result_get_field_attribs_idx(res
->dbi
, field
);
54 if ((type
& DBI_DECIMAL_SIZEMASK
) == DBI_DECIMAL_SIZE4
) {
55 return dbi_result_get_int_idx(res
->dbi
, field
);
56 } else if ((type
& DBI_DECIMAL_SIZEMASK
) == DBI_DECIMAL_SIZE8
) {
57 return dbi_result_get_longlong_idx(res
->dbi
, field
);
59 SMSD_Log(DEBUG_ERROR
, Config
, "Wrong decimal field subtype from DBI: %d", type
);
62 SMSD_Log(DEBUG_ERROR
, Config
, "Wrong field type for number (not INTEGER nor DECIMAL) from DBI: %d", type
);
67 time_t SMSDDBI_GetDate(GSM_SMSDConfig
* Config
, SQL_result
*res
, unsigned int field
)
73 type
= dbi_result_get_field_type_idx(res
->dbi
, field
);
76 case DBI_TYPE_INTEGER
:
77 case DBI_TYPE_DECIMAL
:
78 return SMSDDBI_GetNumber(Config
, res
, field
);
80 date
= dbi_result_get_string_idx(res
->dbi
, field
);
81 return SMSDSQL_ParseDate(Config
, date
);
82 case DBI_TYPE_DATETIME
:
83 return dbi_result_get_datetime_idx(res
->dbi
, field
);
86 SMSD_Log(DEBUG_ERROR
, Config
, "Wrong field type for date from DBI: %d", type
);
91 gboolean
SMSDDBI_GetBool(GSM_SMSDConfig
* Config
, SQL_result
*res
, unsigned int field
)
98 type
= dbi_result_get_field_type_idx(res
->dbi
, field
);
101 case DBI_TYPE_INTEGER
:
102 case DBI_TYPE_DECIMAL
:
103 num
= SMSDDBI_GetNumber(Config
, res
, field
);
106 } else if (num
== 0) {
111 case DBI_TYPE_STRING
:
112 value
= dbi_result_get_string_idx(res
->dbi
, field
);
113 return GSM_StringToBool(value
);
116 SMSD_Log(DEBUG_ERROR
, Config
, "Wrong field type for boolean from DBI: %d", type
);
121 const char *SMSDDBI_GetString(GSM_SMSDConfig
* Config
, SQL_result
*res
, unsigned int col
)
123 return dbi_result_get_string_idx(res
->dbi
, col
+1);
126 static void SMSDDBI_LogError(GSM_SMSDConfig
* Config
)
130 rc
= dbi_conn_error(Config
->conn
.dbi
, &msg
);
132 SMSD_Log(DEBUG_ERROR
, Config
, "Unknown DBI error!");
134 SMSD_Log(DEBUG_ERROR
, Config
, "DBI error %d: %s", rc
, msg
);
138 void SMSDDBI_Callback(dbi_conn Conn
, void *Config
)
140 SMSDDBI_LogError((GSM_SMSDConfig
*) Config
);
143 /* Disconnects from a database */
144 void SMSDDBI_Free(GSM_SMSDConfig
* Config
)
146 if (Config
->conn
.dbi
!= NULL
) {
147 dbi_conn_close(Config
->conn
.dbi
);
149 Config
->conn
.dbi
= NULL
;
153 /* Connects to database */
154 static SQL_Error
SMSDDBI_Connect(GSM_SMSDConfig
* Config
)
157 struct GSM_SMSDdbobj
*db
= Config
->db
;
159 rc
= dbi_initialize(Config
->driverspath
);
162 SMSD_Log(DEBUG_ERROR
, Config
, "DBI did not find any drivers, try using DriversPath option");
166 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to initialize!");
170 Config
->conn
.dbi
= dbi_conn_new(Config
->driver
);
171 if (Config
->conn
.dbi
== NULL
) {
172 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to init %s driver!", Config
->driver
);
176 SMSD_Log(DEBUG_SQL
, Config
, "Using DBI driver '%s'", dbi_driver_get_name(dbi_conn_get_driver(Config
->conn
.dbi
)));
179 dbi_conn_error_handler(Config
->conn
.dbi
, SMSDDBI_Callback
, Config
);
181 if (dbi_conn_set_option(Config
->conn
.dbi
, "sqlite_dbdir", Config
->dbdir
) != 0) {
182 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set sqlite_dbdir!");
183 SMSDDBI_Free(Config
);
186 if (dbi_conn_set_option(Config
->conn
.dbi
, "sqlite3_dbdir", Config
->dbdir
) != 0) {
187 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set sqlite3_dbdir!");
188 SMSDDBI_Free(Config
);
191 if (dbi_conn_set_option(Config
->conn
.dbi
, "host", Config
->host
) != 0) {
192 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set host!");
193 SMSDDBI_Free(Config
);
196 if (dbi_conn_set_option(Config
->conn
.dbi
, "username", Config
->user
) != 0) {
197 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set username!");
198 SMSDDBI_Free(Config
);
201 if (dbi_conn_set_option(Config
->conn
.dbi
, "password", Config
->password
) != 0) {
202 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set password!");
203 SMSDDBI_Free(Config
);
206 if (dbi_conn_set_option(Config
->conn
.dbi
, "dbname", Config
->database
) != 0) {
207 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set dbname!");
208 SMSDDBI_Free(Config
);
211 if (dbi_conn_set_option(Config
->conn
.dbi
, "encoding", "UTF-8") != 0) {
212 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to set encoding!");
213 SMSDDBI_Free(Config
);
217 if (dbi_conn_connect(Config
->conn
.dbi
) != 0) {
218 SMSD_Log(DEBUG_ERROR
, Config
, "DBI failed to connect!");
219 SMSDDBI_Free(Config
);
226 static SQL_Error
SMSDDBI_Query(GSM_SMSDConfig
* Config
, const char *query
, SQL_result
* res
)
233 SMSD_Log(DEBUG_SQL
, Config
, "Execute SQL: %s", query
);
234 res
->dbi
= dbi_conn_query(Config
->conn
.dbi
, query
);
235 if (res
->dbi
!= NULL
)
238 SMSD_Log(DEBUG_INFO
, Config
, "SQL failed: %s", query
);
239 /* Black magic to decide whether we should bail out or attempt to retry */
240 rc
= dbi_conn_error(Config
->conn
.dbi
, &msg
);
242 SMSD_Log(DEBUG_INFO
, Config
, "SQL failure: %s", msg
);
243 if (strstr(msg
, "syntax") != NULL
) {
246 if (strstr(msg
, "violation") != NULL
) {
249 if (strstr(msg
, "violates") != NULL
) {
252 if (strstr(msg
, "SQL error") != NULL
) {
255 if (strstr(msg
, "duplicate") != NULL
) {
258 if (strstr(msg
, "unique") != NULL
) {
261 if (strstr(msg
, "need to rewrite") != NULL
) {
264 if (strstr(msg
, "locked") != NULL
) {
271 /* free sql results */
272 void SMSDDBI_FreeResult(GSM_SMSDConfig
* Config
, SQL_result
*res
)
274 dbi_result_free(res
->dbi
);
277 /* set pointer to next row */
278 int SMSDDBI_NextRow(GSM_SMSDConfig
* Config
, SQL_result
*res
)
280 return dbi_result_next_row(res
->dbi
);
283 char * SMSDDBI_QuoteString(GSM_SMSDConfig
* Config
, const char *string
)
285 char *encoded_text
= NULL
;
286 dbi_conn_quote_string_copy(Config
->conn
.dbi
, string
, &encoded_text
);
290 unsigned long long SMSDDBI_SeqID(GSM_SMSDConfig
* Config
, const char *id
)
292 unsigned long long new_id
;
295 new_id
= dbi_conn_sequence_last(Config
->conn
.dbi
, NULL
);
297 new_id
= dbi_conn_sequence_last(Config
->conn
.dbi
, id
);
298 /* Need to escape for PostgreSQL */
300 sprintf(buffer
, "\"%s\"", id
);
301 new_id
= dbi_conn_sequence_last(Config
->conn
.dbi
, buffer
);
307 unsigned long SMSDDBI_AffectedRows(GSM_SMSDConfig
* Config
, SQL_result
*res
)
309 return dbi_result_get_numrows_affected(res
->dbi
);
312 struct GSM_SMSDdbobj SMSDDBI
= {
319 SMSDDBI_AffectedRows
,
327 /* How should editor hadle tabs in this file? Add editor commands here.
328 * vim: noexpandtab sw=8 ts=8 sts=8: