dbd/sqlite3/connection.c

1
#include "dbd_sqlite3.h"
2
 
3
int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query);
4
 
5
static int run(connection_t *conn, const char *command) {
6
    int res = sqlite3_exec(conn->sqlite, command, NULL, NULL, NULL);
7
 
8
    return res != SQLITE_OK;
9
}
10
 
11
static int commit(connection_t *conn) {
12
    return run(conn, "COMMIT TRANSACTION");
13
}
14
 
15
 
16
static int begin(connection_t *conn) {
17
    int err = 0;
18
 
19
    if (sqlite3_get_autocommit(conn->sqlite)) {
20
        err = run(conn, "BEGIN TRANSACTION");
21
    } else {
22
        err = 0;
23
    }
24
 
25
    return err;
26
}
27
 
28
static int rollback(connection_t *conn) {
29
    return run(conn, "ROLLBACK TRANSACTION");
30
}
31
 
32
int try_begin_transaction(connection_t *conn) {
33
    if (conn->autocommit) {
34
        return 1;
35
    }
36
 
37
    return begin(conn) == 0;
38
}
39
 
40
/* 
41
 * connection,err = DBD.SQLite3.New(dbfile)
42
 */
43
static int connection_new(lua_State *L) {
44
    int n = lua_gettop(L);
45
 
46
    const char *db = NULL;
47
    connection_t *conn = NULL;
48
 
49
    /* db */
50
    switch(n) {
51
    default:
52
	/*
53
	 * db is the only mandatory parameter
54
	 */
55
	db = luaL_checkstring(L, 1);
56
    }
57
 
58
    conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t));
59
 
60
    if (sqlite3_open(db, &conn->sqlite) != SQLITE_OK) {
61
	lua_pushnil(L);
62
	lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, sqlite3_errmsg(conn->sqlite));
63
	return 2;
64
    }
65
 
66
    conn->autocommit = 0;
67
 
68
    luaL_getmetatable(L, DBD_SQLITE_CONNECTION);
69
    lua_setmetatable(L, -2);
70
 
71
    return 1;
72
}
73
 
74
/*
75
 * success = connection:autocommit(on)
76
 */
77
static int connection_autocommit(lua_State *L) {
78
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
79
    int on = lua_toboolean(L, 2); 
80
    int err = 1;
81
 
82
    if (conn->sqlite) {
83
	if (on) {
84
	    err = rollback(conn);
85
        }
86
 
87
	conn->autocommit = on;	
88
    }
89
 
90
    lua_pushboolean(L, !err);
91
    return 1;
92
}
93
 
94
 
95
/*
96
 * success = connection:close()
97
 */
98
static int connection_close(lua_State *L) {
99
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
100
    int disconnect = 0;   
101
 
102
    if (conn->sqlite) {
103
        rollback(conn);
104
	sqlite3_close(conn->sqlite);
105
	disconnect = 1;
106
	conn->sqlite = NULL;
107
    }
108
 
109
    lua_pushboolean(L, disconnect);
110
    return 1;
111
}
112
 
113
/*
114
 * success = connection:commit()
115
 */
116
static int connection_commit(lua_State *L) {
117
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
118
    int err = 1;
119
 
120
    if (conn->sqlite) {
121
	err = commit(conn);
122
    }
123
 
124
    lua_pushboolean(L, !err);
125
    return 1;
126
}
127
 
128
/*
129
 * ok = connection:ping()
130
 */
131
static int connection_ping(lua_State *L) {
132
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
133
    int ok = 0;   
134
 
135
    if (conn->sqlite) {
136
	ok = 1;
137
    }
138
 
139
    lua_pushboolean(L, ok);
140
    return 1;
141
}
142
 
143
/*
144
 * statement,err = connection:prepare(sql_str)
145
 */
146
static int connection_prepare(lua_State *L) {
147
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
148
 
149
    if (conn->sqlite) {
150
	return dbd_sqlite3_statement_create(L, conn, luaL_checkstring(L, 2));
151
    }
152
 
153
    lua_pushnil(L);    
154
    lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE);
155
    return 2;
156
}
157
 
158
/*
159
 * quoted = connection:quote(str)
160
 */
161
static int connection_quote(lua_State *L) {
162
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
163
    size_t len;
164
    const char *from = luaL_checklstring(L, 2, &len);
165
    char *to;
166
 
167
    if (!conn->sqlite) {
168
        luaL_error(L, DBI_ERR_DB_UNAVAILABLE);
169
    }
170
 
171
    to = sqlite3_mprintf("%q", from);
172
 
173
    lua_pushstring(L, to);
174
    sqlite3_free(to);
175
 
176
    return 1;
177
}
178
 
179
/*
180
 * success = connection:rollback()
181
 */
182
static int connection_rollback(lua_State *L) {
183
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
184
    int err = 1;
185
 
186
    if (conn->sqlite) {
187
	err =rollback(conn);
188
    }
189
 
190
    lua_pushboolean(L, !err);
191
    return 1;
192
}
193
 
194
/*
195
 * __gc 
196
 */
197
static int connection_gc(lua_State *L) {
198
    /* always close the connection */
199
    connection_close(L);
200
 
201
    return 0;
202
}
203
 
204
/*
205
 * __tostring
206
 */
207
static int connection_tostring(lua_State *L) {
208
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
209
 
210
    lua_pushfstring(L, "%s: %p", DBD_SQLITE_CONNECTION, conn);
211
 
212
    return 1;
213
}
214
 
215
int dbd_sqlite3_connection(lua_State *L) {
216
    /*
217
     * instance methods
218
     */
219
    static const luaL_Reg connection_methods[] = {
220
	{"autocommit", connection_autocommit},
221
	{"close", connection_close},
222
	{"commit", connection_commit},
223
	{"ping", connection_ping},
224
	{"prepare", connection_prepare},
225
	{"quote", connection_quote},
226
	{"rollback", connection_rollback},
227
	{NULL, NULL}
228
    };
229
 
230
    /*
231
     * class methods
232
     */
233
    static const luaL_Reg connection_class_methods[] = {
234
	{"New", connection_new},
235
	{NULL, NULL}
236
    };
237
 
238
    luaL_newmetatable(L, DBD_SQLITE_CONNECTION);
239
    luaL_register(L, 0, connection_methods);
240
    lua_pushvalue(L,-1);
241
    lua_setfield(L, -2, "__index");
242
 
243
    lua_pushcfunction(L, connection_gc);
244
    lua_setfield(L, -2, "__gc");
245
 
246
    lua_pushcfunction(L, connection_tostring);
247
    lua_setfield(L, -2, "__tostring");
248
 
249
    luaL_register(L, DBD_SQLITE_CONNECTION, connection_class_methods);
250
 
251
    return 1;    
252
}