active_sql 1.0.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,354 @@
1
+ /*
2
+ Sasie
3
+ sasieindrajit@gmail.com
4
+ */
5
+
6
+ #define IfNILorSTRING(obj) (NIL_P(obj)? NULL: StringValuePtr(obj))
7
+ #define IfNILorINT(obj) (NIL_P(obj)? 0: NUM2INT(obj))
8
+
9
+ struct config {
10
+ char *ser, *user, *pass, *db, *sock;
11
+ unsigned int pp, flg;
12
+ };
13
+
14
+ struct mysql {
15
+ MYSQL *conn;
16
+ unsigned int reconnect;
17
+ unsigned int adds;
18
+ };
19
+
20
+ struct config myConfig;
21
+ struct mysql mysObj;
22
+
23
+ static VALUE activeSQL;
24
+ static VALUE rb_cBase;
25
+ static VALUE rb_eSqlError;
26
+ static VALUE rb_cCols;
27
+
28
+ void Init_activesql();
29
+
30
+ // Definition section.
31
+ static void init_active_sqls();
32
+ static VALUE activeSQL_load_config(int argc, VALUE *argv, VALUE self);
33
+ static VALUE activeSQL_version(VALUE self);
34
+ static VALUE activeSQL_connect(VALUE self);
35
+ static VALUE activeSQL_reconnect(VALUE self);
36
+ static VALUE activeSQL_disconnect(VALUE self);
37
+ static VALUE activeSQL_connected(VALUE self);
38
+ static VALUE activeSQL_exec(VALUE self, VALUE arg, VALUE ret_vl);
39
+ static VALUE activeSQL_set_chars_set(int argc, VALUE *argv, VALUE self);
40
+ static VALUE activeSQL_exec_sql(VALUE self, VALUE arg);
41
+ static int castPreWrk(enum enum_field_types typ);
42
+ static VALUE castFrFetch(unsigned int typ, VALUE row, unsigned int itr);
43
+ static VALUE activeSQL_dyamic_meth(VALUE self);
44
+ static VALUE activeSQL_add_methods(int argc, VALUE *argv, VALUE self);
45
+ static VALUE activeSQL_added_methods(VALUE self);
46
+ static VALUE activeSQL_my_database(int argc, VALUE *argv, VALUE self);
47
+ static VALUE activeSQL_my_select(VALUE self);
48
+ static VALUE activeSQL_auto_commit(VALUE self, VALUE arg);
49
+
50
+ // Def.
51
+ static VALUE activeSQL_auto_commit(VALUE self, VALUE arg) {
52
+ //if (mysql_autocommit(mysObj.conn, 1) == 0)
53
+ // return Qtrue; Do it from query.
54
+ }
55
+
56
+ static VALUE activeSQL_my_select(VALUE self) {
57
+ return rb_reg_new("\\A\\s*(SELECT|SHOW|DESCRIBE|EXPLAIN|CHECK TABLE|DESC|CALL)", 57, 1);
58
+ }
59
+
60
+ static VALUE activeSQL_my_database(int argc, VALUE *argv, VALUE self) {
61
+ VALUE cdb;
62
+ if (!mysObj.reconnect) {
63
+ rb_scan_args(argc, argv, "01", &cdb);
64
+ if (TYPE(cdb) == T_STRING)
65
+ if (mysql_select_db(mysObj.conn, RSTRING_PTR(cdb)) == 0)
66
+ return Qtrue;
67
+ else
68
+ return Qfalse;
69
+ else
70
+ return Qfalse;
71
+ }
72
+ else
73
+ rb_raise(rb_eSqlError, "Connection not established.");
74
+ }
75
+
76
+ static VALUE activeSQL_added_methods(VALUE self) {
77
+ if (mysObj.adds == 0)
78
+ return Qtrue;
79
+ else
80
+ return Qfalse;
81
+ }
82
+
83
+ static VALUE activeSQL_add_methods(int argc, VALUE *argv, VALUE self) {
84
+ VALUE needed;
85
+ rb_scan_args(argc, argv, "01", &needed);
86
+ if (TYPE(needed) == T_TRUE) {
87
+ mysObj.adds = 0;
88
+ return Qtrue;
89
+ }
90
+ else if (TYPE(needed) == T_FALSE) {
91
+ mysObj.adds = 1;
92
+ return Qtrue;
93
+ }
94
+ else
95
+ return Qfalse;
96
+ }
97
+
98
+ static VALUE activeSQL_dyamic_meth(VALUE self) {
99
+ //unsigned int ind = findIndex();
100
+ //return RARRAY(self)->ptr[ind];
101
+ }
102
+
103
+ static VALUE activeSQL_exec_sql(VALUE self, VALUE arg) {
104
+ VALUE f;
105
+ if (mysObj.reconnect == 1)
106
+ f = rb_funcall(rb_cBase, rb_intern("connect!"), 0);
107
+ else
108
+ f = Qtrue;
109
+ if (TYPE(f) == T_TRUE) {
110
+ if (TYPE(arg) != T_STRING)
111
+ rb_raise(rb_eTypeError, "invalid type for input");
112
+ if (mysql_real_query(mysObj.conn, RSTRING_PTR(arg), (unsigned int) strlen(RSTRING_PTR(arg))))
113
+ rb_raise(rb_eSqlError, mysql_error(mysObj.conn));
114
+ else
115
+ return Qtrue;
116
+ }
117
+ else
118
+ rb_raise(rb_eSqlError, "Connection not established.");
119
+ }
120
+
121
+ static VALUE activeSQL_set_chars_set(int argc, VALUE *argv, VALUE self) {
122
+ VALUE cset;
123
+ if (!mysObj.reconnect) {
124
+ rb_scan_args(argc, argv, "01", &cset);
125
+ if (TYPE(cset) == T_STRING)
126
+ if (!mysql_set_character_set(mysObj.conn, RSTRING_PTR(cset)))
127
+ return rb_str_new2(mysql_character_set_name(mysObj.conn));
128
+ else
129
+ return Qfalse;
130
+ else
131
+ return rb_str_new2(mysql_character_set_name(mysObj.conn));
132
+ }
133
+ else
134
+ rb_raise(rb_eSqlError, "Connection not established.");
135
+ }
136
+
137
+ static VALUE activeSQL_exec(VALUE self, VALUE arg, VALUE ret_vl) {
138
+ unsigned int * castAs;
139
+ unsigned int i, n, fld_cnt, j;
140
+ unsigned long * lengths;
141
+ char **getters;
142
+ char *tbl_name;
143
+ char *dyn_method;
144
+ MYSQL_RES *res;
145
+ MYSQL_ROW row;
146
+ MYSQL_FIELD *fields;
147
+ VALUE ary, f, cmd;
148
+ VALUE res_set; //Colllect result to send it back.
149
+ if (mysObj.reconnect == 1)
150
+ f = rb_funcall(rb_cBase, rb_intern("connect!"), 0);
151
+ else
152
+ f = Qtrue;
153
+ if (TYPE(f) == T_TRUE) {
154
+ if (TYPE(arg) != T_STRING)
155
+ rb_raise(rb_eTypeError, "invalid type for input");
156
+ if (mysql_real_query(mysObj.conn, RSTRING_PTR(arg), (unsigned int) strlen(RSTRING_PTR(arg)))) {
157
+ rb_raise(rb_eSqlError, mysql_error(mysObj.conn));
158
+ }
159
+ if (TYPE(ret_vl) == T_TRUE) {
160
+ res = mysql_use_result(mysObj.conn);
161
+ res_set = rb_ary_new();
162
+ fld_cnt = mysql_num_fields(res);
163
+ fields = mysql_fetch_fields(res);
164
+ ary = rb_ary_new2(fld_cnt);
165
+
166
+ /* ALLOCATE ROOM : DYN METHODS FOR GETTERS */
167
+ getters = (char **) malloc(fld_cnt * sizeof (char *));
168
+ castAs = (unsigned int*) malloc(fld_cnt * sizeof (int));
169
+
170
+ for (i = 0; i < fld_cnt; i++) {
171
+ getters[i] = fields[i].name;
172
+ tbl_name = fields[i].org_name ? fields[i].org_name : fields[i].name;
173
+ strcat(tbl_name, "@");
174
+ strcat(tbl_name, fields[i].org_table ? fields[i].org_table : fields[i].table);
175
+ rb_ary_store(ary, i, rb_tainted_str_new2(tbl_name));
176
+ tbl_name = "";
177
+ castAs[i] = castPreWrk(fields[i].type);
178
+ }
179
+ rb_ary_push(res_set, ary);
180
+ while ((row = mysql_fetch_row(res)) != NULL) {
181
+ n = mysql_num_fields(res);
182
+ lengths = mysql_fetch_lengths(res);
183
+ ary = rb_ary_new2(n);
184
+ for (i = 0; i < n; i++) {
185
+ rb_ary_store(ary, i, row[i] ? castFrFetch(castAs[i], rb_tainted_str_new(row[i], lengths[i]), i) : Qnil);
186
+ //rb_define_singleton_method(ary, "{dynamic getters}", activeSQL_dyamic_meth, 0); WE CN ADD IF HV NEW WAY.
187
+ if (mysObj.adds == 0)
188
+ if (getters[i] != "") {
189
+ dyn_method = (char *) malloc(((unsigned int) strlen(getters[i]) + 21)); // **
190
+ sprintf(dyn_method, "def %s; self[%u]; end", getters[i], i);
191
+ cmd = rb_str_new2(dyn_method);
192
+ rb_obj_instance_eval(1, &cmd, ary);
193
+ free(dyn_method);
194
+ }
195
+ }
196
+ rb_ary_push(res_set, ary);
197
+ }
198
+
199
+ // FREE all.
200
+ free(getters);
201
+ free(castAs);
202
+ mysql_free_result(res);
203
+ return res_set;
204
+ }
205
+ else {
206
+ res = mysql_use_result(mysObj.conn); // To avoid out of sync error from api.
207
+ mysql_free_result(res);
208
+ return Qtrue; /* Add affacted rows instead of status if needed */
209
+ }
210
+ }
211
+ else
212
+ rb_raise(rb_eSqlError, "Connection not established.");
213
+ }
214
+
215
+ static VALUE activeSQL_connected(VALUE self) {
216
+ if (mysObj.reconnect == 0)
217
+ return Qtrue;
218
+ else
219
+ return Qfalse;
220
+ }
221
+
222
+ static VALUE activeSQL_disconnect(VALUE self) {
223
+ if (mysObj.reconnect == 0) {
224
+ mysObj.reconnect = 1;
225
+ mysql_close(mysObj.conn);
226
+ return Qtrue;
227
+ }
228
+ else
229
+ return Qfalse;
230
+ }
231
+
232
+ static VALUE activeSQL_reconnect(VALUE self) {
233
+ rb_funcall(rb_cBase, rb_intern("disconnect!"), 0);
234
+ return rb_funcall(rb_cBase, rb_intern("connect!"), 0);
235
+ }
236
+
237
+ static VALUE activeSQL_connect(VALUE self) {
238
+ if (mysObj.reconnect == 1) {
239
+ mysObj.conn = mysql_init(NULL);
240
+ if (!mysql_real_connect(mysObj.conn, myConfig.ser, myConfig.user, myConfig.pass, myConfig.db, myConfig.pp, myConfig.sock, myConfig.flg)) {
241
+ fprintf(stderr, "%s\n", mysql_error(mysObj.conn));
242
+ return Qfalse;
243
+ }
244
+ else {
245
+ mysObj.reconnect = 0;
246
+ return Qtrue;
247
+ }
248
+ }
249
+ else
250
+ return Qfalse;
251
+ }
252
+
253
+ static VALUE activeSQL_version(VALUE self) {
254
+ return rb_str_new("2.0.1", 5);
255
+ }
256
+
257
+ static VALUE activeSQL_load_config(int argc, VALUE *argv, VALUE self) {
258
+ VALUE host, user, passwd, db, port, sock, flag;
259
+ rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag);
260
+ myConfig.db = IfNILorSTRING(db);
261
+ myConfig.flg = IfNILorINT(flag);
262
+ myConfig.ser = IfNILorSTRING(host);
263
+ myConfig.user = IfNILorSTRING(user);
264
+ myConfig.pass = IfNILorSTRING(passwd);
265
+ myConfig.pp = IfNILorINT(port);
266
+ myConfig.sock = IfNILorSTRING(sock);
267
+ mysObj.reconnect = 1;
268
+ return Qnil;
269
+ }
270
+
271
+
272
+ // activeSQL
273
+ void Init_activesql() {
274
+ activeSQL = rb_define_module("ActiveSQL");
275
+ rb_cBase = rb_define_class_under(activeSQL, "Base", rb_cObject);
276
+ rb_eSqlError = rb_define_class("ActiveSQLError", rb_eStandardError);
277
+ rb_cCols = rb_define_class_under(activeSQL, "Cols", rb_cArray);
278
+ // methods visible.
279
+ rb_define_singleton_method(rb_cBase, "load_config", activeSQL_load_config, -1);
280
+ rb_define_singleton_method(rb_cBase, "version", activeSQL_version, 0);
281
+ rb_define_singleton_method(rb_cBase, "connect!", activeSQL_connect, 0);
282
+ rb_define_singleton_method(rb_cBase, "reconnect!", activeSQL_reconnect, 0);
283
+ rb_define_singleton_method(rb_cBase, "disconnect!", activeSQL_disconnect, 0);
284
+ rb_define_singleton_method(rb_cBase, "connected?", activeSQL_connected, 0);
285
+ rb_define_singleton_method(rb_cBase, "exec", activeSQL_exec, 2);
286
+ rb_define_singleton_method(rb_cBase, "my_char_set", activeSQL_set_chars_set, -1);
287
+ rb_define_singleton_method(rb_cBase, "exec_sql", activeSQL_exec_sql, 1);
288
+ rb_define_singleton_method(rb_cBase, "add_methods", activeSQL_add_methods, -1);
289
+ rb_define_singleton_method(rb_cBase, "add_methods?", activeSQL_added_methods, 0);
290
+ rb_define_singleton_method(rb_cBase, "my_database", activeSQL_my_database, -1);
291
+ rb_define_singleton_method(rb_cBase, "my_select?", activeSQL_my_select, 0);
292
+ //rb_define_singleton_method(rb_cBase, "auto_commit", activeSQL_auto_commit, 1);
293
+ init_active_sqls();
294
+ }
295
+
296
+ // Will work behind.
297
+ // static VALUE castFrFetch(unsigned int typ, char ** row, unsigned long len, unsigned int itr){
298
+
299
+ static VALUE castFrFetch(unsigned int typ, VALUE row, unsigned int itr) {
300
+ VALUE cst;
301
+ switch (typ){
302
+ case 1:
303
+ cst = rb_funcall2(row, rb_intern("to_i"), 0, NULL);
304
+ break;
305
+ case 2:
306
+ cst = rb_funcall2(row, rb_intern("to_f"), 0, NULL);
307
+ break;
308
+ case 3:
309
+ default:
310
+ return row;
311
+ }
312
+ return cst;
313
+ }
314
+
315
+ static int castPreWrk(enum enum_field_types typ) {
316
+ unsigned int ret;
317
+ switch (typ) {
318
+ case MYSQL_TYPE_SHORT:
319
+ case MYSQL_TYPE_INT24:
320
+ case MYSQL_TYPE_LONGLONG:
321
+ case MYSQL_TYPE_TINY:
322
+ case MYSQL_TYPE_LONG:
323
+ ret = 1;
324
+ break;
325
+ case MYSQL_TYPE_DECIMAL:
326
+ case MYSQL_TYPE_FLOAT:
327
+ case MYSQL_TYPE_DOUBLE:
328
+ ret = 2;
329
+ break;
330
+ case MYSQL_TYPE_TIMESTAMP:
331
+ case MYSQL_TYPE_DATE:
332
+ case MYSQL_TYPE_TIME:
333
+ case MYSQL_TYPE_DATETIME:
334
+ case MYSQL_TYPE_YEAR:
335
+ case MYSQL_TYPE_STRING:
336
+ case MYSQL_TYPE_VAR_STRING:
337
+ case MYSQL_TYPE_BLOB:
338
+ case MYSQL_TYPE_SET:
339
+ case MYSQL_TYPE_ENUM:
340
+ case MYSQL_TYPE_GEOMETRY:
341
+ case MYSQL_TYPE_NULL:
342
+ ret = 3;
343
+ break;
344
+ default:
345
+ ret = 3;
346
+ }
347
+ return ret;
348
+ }
349
+
350
+ static void init_active_sqls() {
351
+ mysObj.reconnect = 1;
352
+ // Append methods as getters.
353
+ mysObj.adds = 0;
354
+ }
Binary file
Binary file
@@ -7,3 +7,48 @@ rescue LoadError
7
7
  end
8
8
  end
9
9
 
10
+ module ActiveSQL
11
+ class Base
12
+ class << self
13
+
14
+ # Execute the sql queries.
15
+ def select_sql(qry)
16
+ if qry =~ my_select?
17
+ result = exec(qry, true)
18
+ cols = result.shift
19
+ result.instance_eval "def columns; #{cols.inspect}; end"
20
+ result
21
+ else
22
+ exec_sql(qry) # status.
23
+ end
24
+ end
25
+
26
+ # Result set not returned for execute_sql
27
+ def execute_sql(qry)
28
+ unless qry =~ my_select?
29
+ exec_sql(qry)
30
+ else
31
+ raise ActiveSQLError, "no return of result set"
32
+ end
33
+ end
34
+ alias :insert_sql :execute_sql
35
+
36
+ def establish_connection(config)
37
+ host = (config[:host] ||= 'localhost')
38
+ username = config[:username] ? config[:username].to_s : 'root'
39
+ password = config[:password] ? config[:password].to_s : ''
40
+ database = config[:database]
41
+ port = config[:port]
42
+ socket = config[:socket]
43
+ default_flags = 0
44
+ # No multi-results as of now.
45
+ options = [host, username, password, database, port, socket, default_flags]
46
+ load_config(*options)
47
+
48
+ # make connection across the parameters.
49
+ connect!
50
+ end
51
+
52
+ end
53
+ end
54
+ end
Binary file
data/readme.txt CHANGED
@@ -1,12 +1,55 @@
1
- Welcome :
2
- =========
3
-
4
- ActiveSQL is super fast.
1
+ ActiveSQL
2
+ ===========
3
+
4
+ Get the super fast mysql query results from Ruby and Rails applications.
5
+
6
+ Love to write queries.
5
7
 
6
- It works on mysql 5 or greater versions(tested under linux).
8
+ Build queries on your own.
9
+
10
+ Get super fast results.
11
+
12
+ Keep everything in mysql.
13
+
7
14
 
8
- Usage.
9
- ========
15
+ USAGE:
16
+ ======
17
+
18
+ require 'active_sql'
19
+
20
+ ActiveSQL::Base.establish_connection(:host=> 'localhost', :username=>'root', :password=> 'peep', :socket=> '') => true
21
+
22
+ ActiveSQL::Base.connected? => true
10
23
 
24
+ ActiveSQL::Base.insert_sql("insert into users values(1, user1@example.com, 12, 12.3)") => true
25
+
26
+ ActiveSQL::Base.execute_sql("delete from roles") => true
27
+
28
+ ActiveSQL::Base.select_sql("select * from users") => [[1, 'user1@example.com', 12, 12.3]]
29
+
30
+ ActiveSQL::Base.select_sql("select * from users").columns => ["id@users", "email@users", "rate@users", "points@users"]
11
31
 
32
+ user = ActiveSQL::Base.select_sql("select id, rate as rank from users limit 1").first
33
+ # Methods will be added by default.
34
+ # Disabling methods possible.
35
+ user.id => 1
36
+ user.rank => 12
37
+
38
+ ActiveSQL::Base.my_char_set => "latin1"
12
39
 
40
+ ActiveSQL::Base.my_char_set("utf8") => "utf8"
41
+
42
+ ActiveSQL::Base.my_database("another_database") => true
43
+
44
+ # Append get methods to every row.
45
+ ActiveSQL::Base.add_methods(true) => true
46
+
47
+ # Do not append methods:
48
+ ActiveSQL::Base.add_methods(false) => true
49
+
50
+ # Status of adding methods to the rows.
51
+ ActiveSQL::Base.add_methods? => true
52
+
53
+
54
+ Note:
55
+ Tentative build compiled by ruby 1.8 - linux.
metadata CHANGED
@@ -3,10 +3,10 @@ name: active_sql
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 1
6
+ - 2
7
7
  - 0
8
8
  - 1
9
- version: 1.0.1
9
+ version: 2.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - sasie
@@ -14,12 +14,12 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-03-14 00:00:00 +05:30
17
+ date: 2012-04-12 00:00:00 +05:30
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
21
21
  description: Easy to work with mysql from ruby and rails
22
- email: sasie@rocketmail.com
22
+ email: sasieindrajit@gmail.com
23
23
  executables: []
24
24
 
25
25
  extensions: []
@@ -29,9 +29,12 @@ extra_rdoc_files: []
29
29
  files:
30
30
  - lib/activesql.so
31
31
  - lib/active_sql.rb
32
+ - ext/activesql.c
33
+ - ext/activesql.o
34
+ - ext/activesql.so
32
35
  - readme.txt
33
36
  has_rdoc: true
34
- homepage: http://github.com/
37
+ homepage: https://github.com/sasie-sourcebits/active_sql
35
38
  licenses: []
36
39
 
37
40
  post_install_message: