dbd/mysql/connection.c

1
#include "dbd_mysql.h"
2
 
3
int dbd_mysql_statement_create(lua_State *L, connection_t *conn, const char *sql_query);
4
 
5
/*
6
 * connection,err = DBD.MySQl.New(dbname, user, password, host, port)
7
 */
8
static int connection_new(lua_State *L) {
9
    int n = lua_gettop(L);
10
 
11
    connection_t *conn = NULL;
12
 
13
    const char *host = NULL;
14
    const char *user = NULL;
15
    const char *password = NULL;
16
    const char *db = NULL;
17
    int port = 0;
18
 
19
    const char *unix_socket = NULL; /* TODO always NULL */
20
    int client_flag = 0; /* TODO always 0, set flags from options table */
21
 
22
    /* db, user, password, host, port */
23
    switch (n) {
24
    case 5:
25
	if (lua_isnil(L, 5) == 0) 
26
	    port = luaL_checkint(L, 5);
27
    case 4: 
28
	if (lua_isnil(L, 4) == 0) 
29
	    host = luaL_checkstring(L, 4);
30
    case 3:
31
	if (lua_isnil(L, 3) == 0) 
32
	    password = luaL_checkstring(L, 3);
33
    case 2:
34
	if (lua_isnil(L, 2) == 0) 
35
	    user = luaL_checkstring(L, 2);
36
    case 1:
37
	/*
38
	 * db is the only mandatory parameter
39
	 */
40
	db = luaL_checkstring(L, 1);
41
    }
42
 
43
    conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t));
44
 
45
    conn->mysql = mysql_init(NULL);
46
 
47
    if (!mysql_real_connect(conn->mysql, host, user, password, db, port, unix_socket, client_flag)) {
48
	lua_pushnil(L);
49
	lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, mysql_error(conn->mysql));
50
	return 2;
51
    }
52
 
53
    /*
54
     * by default turn off autocommit
55
     */
56
    mysql_autocommit(conn->mysql, 0);
57
 
58
    luaL_getmetatable(L, DBD_MYSQL_CONNECTION);
59
    lua_setmetatable(L, -2);
60
 
61
    return 1;
62
}
63
 
64
/*
65
 * success = connection:autocommit(on)
66
 */
67
static int connection_autocommit(lua_State *L) {
68
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
69
    int on = lua_toboolean(L, 2); 
70
    int err = 0;
71
 
72
    if (conn->mysql) {
73
	err = mysql_autocommit(conn->mysql, on);
74
    }
75
 
76
    lua_pushboolean(L, !err);
77
    return 1;
78
}
79
 
80
/*
81
 * success = connection:close()
82
 */
83
static int connection_close(lua_State *L) {
84
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
85
    int disconnect = 0;   
86
 
87
    if (conn->mysql) {
88
	mysql_close(conn->mysql);
89
	disconnect = 1;
90
	conn->mysql = NULL;
91
    }
92
 
93
    lua_pushboolean(L, disconnect);
94
    return 1;
95
}
96
 
97
/*
98
 * success = connection:commit()
99
 */
100
static int connection_commit(lua_State *L) {
101
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
102
    int err = 0;
103
 
104
    if (conn->mysql) {
105
	err = mysql_commit(conn->mysql);
106
    }
107
 
108
    lua_pushboolean(L, !err);
109
    return 1;
110
}
111
 
112
/* 
113
 * ok = connection:ping()
114
 */
115
static int connection_ping(lua_State *L) {
116
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
117
    int err = 1;   
118
 
119
    if (conn->mysql) {
120
	err = mysql_ping(conn->mysql);
121
    }
122
 
123
    lua_pushboolean(L, !err);
124
    return 1;
125
}
126
 
127
/*
128
 * statement,err = connection:prepare(sql_string)
129
 */
130
static int connection_prepare(lua_State *L) {
131
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
132
 
133
    if (conn->mysql) {
134
	return dbd_mysql_statement_create(L, conn, luaL_checkstring(L, 2)); 
135
    }
136
 
137
    lua_pushnil(L);    
138
    lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE);    
139
 
140
    return 2;
141
}
142
 
143
/*
144
 * quoted = connection:quote(str)
145
 */
146
static int connection_quote(lua_State *L) {
147
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
148
    size_t len;
149
    const char *from = luaL_checklstring(L, 2, &len);
150
    char *to = (char *)calloc(len*2+1, sizeof(char));
151
    int quoted_len;
152
 
153
    if (!conn->mysql) {
154
        luaL_error(L, DBI_ERR_DB_UNAVAILABLE);
155
    }
156
 
157
    quoted_len = mysql_real_escape_string(conn->mysql, to, from, len);
158
 
159
    lua_pushlstring(L, to, quoted_len);
160
    free(to);
161
 
162
    return 1;
163
}
164
 
165
/*
166
 * success = connection:rollback()
167
 */
168
static int connection_rollback(lua_State *L) {
169
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
170
    int err = 0;
171
 
172
    if (conn->mysql) {
173
	err = mysql_rollback(conn->mysql);
174
    }
175
 
176
    lua_pushboolean(L, !err);
177
    return 1;
178
}
179
 
180
/*
181
 * __gc
182
 */
183
static int connection_gc(lua_State *L) {
184
    /* always close the connection */
185
    connection_close(L);
186
 
187
    return 0;
188
}
189
 
190
/*
191
 * __tostring
192
 */
193
static int connection_tostring(lua_State *L) {
194
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
195
 
196
    lua_pushfstring(L, "%s: %p", DBD_MYSQL_CONNECTION, conn);
197
 
198
    return 1;
199
}
200
 
201
int dbd_mysql_connection(lua_State *L) {
202
    static const luaL_Reg connection_methods[] = {
203
	{"autocommit", connection_autocommit},
204
	{"close", connection_close},
205
	{"commit", connection_commit},
206
	{"ping", connection_ping},
207
	{"prepare", connection_prepare},
208
	{"quote", connection_quote},
209
	{"rollback", connection_rollback},
210
	{NULL, NULL}
211
    };
212
 
213
    static const luaL_Reg connection_class_methods[] = {
214
	{"New", connection_new},
215
	{NULL, NULL}
216
    };
217
 
218
    luaL_newmetatable(L, DBD_MYSQL_CONNECTION);
219
    luaL_register(L, 0, connection_methods);
220
    lua_pushvalue(L,-1);
221
    lua_setfield(L, -2, "__index");
222
 
223
    lua_pushcfunction(L, connection_gc);
224
    lua_setfield(L, -2, "__gc");
225
 
226
    lua_pushcfunction(L, connection_tostring);
227
    lua_setfield(L, -2, "__tostring");
228
 
229
    luaL_register(L, DBD_MYSQL_CONNECTION, connection_class_methods);
230
 
231
    return 1;    
232
}