tiny_tds 0.4.5.rc1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/CHANGELOG +99 -0
- data/Gemfile +18 -0
- data/MIT-LICENSE +22 -0
- data/NOTES +11 -0
- data/README.rdoc +277 -0
- data/Rakefile +52 -0
- data/ext/tiny_tds/client.c +347 -0
- data/ext/tiny_tds/client.h +35 -0
- data/ext/tiny_tds/extconf.rb +84 -0
- data/ext/tiny_tds/result.c +493 -0
- data/ext/tiny_tds/result.h +36 -0
- data/ext/tiny_tds/tiny_tds_ext.c +12 -0
- data/ext/tiny_tds/tiny_tds_ext.h +18 -0
- data/lib/tiny_tds/1.8/tiny_tds.so +0 -0
- data/lib/tiny_tds/1.9/tiny_tds.so +0 -0
- data/lib/tiny_tds/client.rb +79 -0
- data/lib/tiny_tds/error.rb +29 -0
- data/lib/tiny_tds/result.rb +8 -0
- data/lib/tiny_tds/version.rb +3 -0
- data/lib/tiny_tds.rb +19 -0
- data/tasks/ports.rake +58 -0
- data/test/benchmark/query.rb +77 -0
- data/test/benchmark/query_odbc.rb +106 -0
- data/test/benchmark/query_tinytds.rb +111 -0
- data/test/client_test.rb +163 -0
- data/test/result_test.rb +437 -0
- data/test/schema/1px.gif +0 -0
- data/test/schema/sqlserver_2000.sql +138 -0
- data/test/schema/sqlserver_2005.sql +138 -0
- data/test/schema/sqlserver_2008.sql +138 -0
- data/test/schema/sqlserver_azure.sql +138 -0
- data/test/schema_test.rb +284 -0
- data/test/test_helper.rb +190 -0
- metadata +117 -0
@@ -0,0 +1,347 @@
|
|
1
|
+
|
2
|
+
#include <tiny_tds_ext.h>
|
3
|
+
#include <errno.h>
|
4
|
+
|
5
|
+
VALUE cTinyTdsClient;
|
6
|
+
extern VALUE mTinyTds, cTinyTdsError;
|
7
|
+
static ID sym_username, sym_password, sym_dataserver, sym_database, sym_appname, sym_tds_version, sym_login_timeout, sym_timeout, sym_encoding, sym_azure;
|
8
|
+
static ID intern_source_eql, intern_severity_eql, intern_db_error_number_eql, intern_os_error_number_eql;
|
9
|
+
static ID intern_new, intern_dup, intern_transpose_iconv_encoding, intern_local_offset, intern_gsub;
|
10
|
+
VALUE opt_escape_regex, opt_escape_dblquote;
|
11
|
+
|
12
|
+
|
13
|
+
// Lib Macros
|
14
|
+
|
15
|
+
#define GET_CLIENT_WRAPPER(self) \
|
16
|
+
tinytds_client_wrapper *cwrap; \
|
17
|
+
Data_Get_Struct(self, tinytds_client_wrapper, cwrap)
|
18
|
+
|
19
|
+
#define REQUIRE_OPEN_CLIENT(cwrap) \
|
20
|
+
if (cwrap->closed || cwrap->userdata->closed) { \
|
21
|
+
rb_raise(cTinyTdsError, "closed connection"); \
|
22
|
+
return Qnil; \
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
// Lib Backend (Helpers)
|
27
|
+
|
28
|
+
static VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *source, int severity, int dberr, int oserr) {
|
29
|
+
GET_CLIENT_USERDATA(dbproc);
|
30
|
+
if (cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
|
31
|
+
userdata->dbsqlok_sent = 1;
|
32
|
+
dbsqlok(dbproc);
|
33
|
+
userdata->dbcancel_sent = 1;
|
34
|
+
dbcancel(dbproc);
|
35
|
+
}
|
36
|
+
VALUE e = rb_exc_new2(cTinyTdsError, error);
|
37
|
+
rb_funcall(e, intern_source_eql, 1, rb_str_new2(source));
|
38
|
+
if (severity)
|
39
|
+
rb_funcall(e, intern_severity_eql, 1, INT2FIX(severity));
|
40
|
+
if (dberr)
|
41
|
+
rb_funcall(e, intern_db_error_number_eql, 1, INT2FIX(dberr));
|
42
|
+
if (oserr)
|
43
|
+
rb_funcall(e, intern_os_error_number_eql, 1, INT2FIX(oserr));
|
44
|
+
rb_exc_raise(e);
|
45
|
+
return Qnil;
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
// Lib Backend (Memory Management & Handlers)
|
50
|
+
|
51
|
+
int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) {
|
52
|
+
static char *source = "error";
|
53
|
+
GET_CLIENT_USERDATA(dbproc);
|
54
|
+
int return_value = INT_CONTINUE;
|
55
|
+
int cancel = 0;
|
56
|
+
switch(dberr) {
|
57
|
+
case SYBESMSG:
|
58
|
+
return return_value;
|
59
|
+
case SYBEICONVI:
|
60
|
+
return INT_CANCEL;
|
61
|
+
case SYBEFCON:
|
62
|
+
case SYBESOCK:
|
63
|
+
case SYBECONN:
|
64
|
+
return_value = INT_EXIT;
|
65
|
+
break;
|
66
|
+
case SYBESEOF: {
|
67
|
+
if (userdata && userdata->timing_out)
|
68
|
+
return_value = INT_TIMEOUT;
|
69
|
+
return INT_CANCEL;
|
70
|
+
break;
|
71
|
+
}
|
72
|
+
case SYBETIME: {
|
73
|
+
if (userdata) {
|
74
|
+
if (userdata->timing_out) {
|
75
|
+
return INT_CONTINUE;
|
76
|
+
} else {
|
77
|
+
userdata->timing_out = 1;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
cancel = 1;
|
81
|
+
break;
|
82
|
+
}
|
83
|
+
case SYBEWRIT: {
|
84
|
+
if (userdata && (userdata->dbsqlok_sent || userdata->dbcancel_sent))
|
85
|
+
return INT_CANCEL;
|
86
|
+
cancel = 1;
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
case SYBEREAD:
|
90
|
+
cancel = 1;
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
rb_tinytds_raise_error(dbproc, cancel, dberrstr, source, severity, dberr, oserr);
|
94
|
+
return return_value;
|
95
|
+
}
|
96
|
+
|
97
|
+
int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) {
|
98
|
+
static char *source = "message";
|
99
|
+
if (severity)
|
100
|
+
rb_tinytds_raise_error(dbproc, 1, msgtext, source, severity, msgno, msgstate);
|
101
|
+
return 0;
|
102
|
+
}
|
103
|
+
|
104
|
+
static void rb_tinytds_client_reset_userdata(tinytds_client_userdata *userdata) {
|
105
|
+
userdata->timing_out = 0;
|
106
|
+
userdata->dbsql_sent = 0;
|
107
|
+
userdata->dbsqlok_sent = 0;
|
108
|
+
userdata->dbcancel_sent = 0;
|
109
|
+
}
|
110
|
+
|
111
|
+
static void rb_tinytds_client_mark(void *ptr) {
|
112
|
+
tinytds_client_wrapper *cwrap = (tinytds_client_wrapper *)ptr;
|
113
|
+
if (cwrap) {
|
114
|
+
rb_gc_mark(cwrap->charset);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
static void rb_tinytds_client_free(void *ptr) {
|
119
|
+
tinytds_client_wrapper *cwrap = (tinytds_client_wrapper *)ptr;
|
120
|
+
if (cwrap->login)
|
121
|
+
dbloginfree(cwrap->login);
|
122
|
+
if (cwrap->client && !cwrap->closed) {
|
123
|
+
dbclose(cwrap->client);
|
124
|
+
cwrap->closed = 1;
|
125
|
+
cwrap->userdata->closed = 1;
|
126
|
+
}
|
127
|
+
xfree(cwrap->userdata);
|
128
|
+
xfree(ptr);
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE allocate(VALUE klass) {
|
132
|
+
VALUE obj;
|
133
|
+
tinytds_client_wrapper *cwrap;
|
134
|
+
obj = Data_Make_Struct(klass, tinytds_client_wrapper, rb_tinytds_client_mark, rb_tinytds_client_free, cwrap);
|
135
|
+
cwrap->closed = 1;
|
136
|
+
cwrap->charset = Qnil;
|
137
|
+
cwrap->userdata = malloc(sizeof(tinytds_client_userdata));
|
138
|
+
cwrap->userdata->closed = 1;
|
139
|
+
rb_tinytds_client_reset_userdata(cwrap->userdata);
|
140
|
+
return obj;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
// TinyTds::Client (public)
|
145
|
+
|
146
|
+
static VALUE rb_tinytds_tds_version(VALUE self) {
|
147
|
+
GET_CLIENT_WRAPPER(self);
|
148
|
+
return INT2FIX(dbtds(cwrap->client));
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE rb_tinytds_close(VALUE self) {
|
152
|
+
GET_CLIENT_WRAPPER(self);
|
153
|
+
if (cwrap->client && !cwrap->closed) {
|
154
|
+
dbclose(cwrap->client);
|
155
|
+
cwrap->closed = 1;
|
156
|
+
cwrap->userdata->closed = 1;
|
157
|
+
}
|
158
|
+
return Qtrue;
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE rb_tinytds_dead(VALUE self) {
|
162
|
+
GET_CLIENT_WRAPPER(self);
|
163
|
+
return dbdead(cwrap->client) ? Qtrue : Qfalse;
|
164
|
+
}
|
165
|
+
|
166
|
+
static VALUE rb_tinytds_closed(VALUE self) {
|
167
|
+
GET_CLIENT_WRAPPER(self);
|
168
|
+
return (cwrap->closed || cwrap->userdata->closed) ? Qtrue : Qfalse;
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE rb_tinytds_canceled(VALUE self) {
|
172
|
+
GET_CLIENT_WRAPPER(self);
|
173
|
+
return cwrap->userdata->dbcancel_sent ? Qtrue : Qfalse;
|
174
|
+
}
|
175
|
+
|
176
|
+
static VALUE rb_tinytds_sqlsent(VALUE self) {
|
177
|
+
GET_CLIENT_WRAPPER(self);
|
178
|
+
return cwrap->userdata->dbsql_sent ? Qtrue : Qfalse;
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
|
182
|
+
GET_CLIENT_WRAPPER(self);
|
183
|
+
rb_tinytds_client_reset_userdata(cwrap->userdata);
|
184
|
+
REQUIRE_OPEN_CLIENT(cwrap);
|
185
|
+
dbcmd(cwrap->client, StringValuePtr(sql));
|
186
|
+
if (dbsqlsend(cwrap->client) == FAIL) {
|
187
|
+
rb_warn("TinyTds: dbsqlsend() returned FAIL.\n");
|
188
|
+
return Qfalse;
|
189
|
+
}
|
190
|
+
cwrap->userdata->dbsql_sent = 1;
|
191
|
+
VALUE result = rb_tinytds_new_result_obj(cwrap->client);
|
192
|
+
rb_iv_set(result, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), intern_dup, 0));
|
193
|
+
GET_RESULT_WRAPPER(result);
|
194
|
+
rwrap->local_offset = rb_funcall(cTinyTdsClient, intern_local_offset, 0);
|
195
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
196
|
+
rwrap->encoding = cwrap->encoding;
|
197
|
+
#endif
|
198
|
+
return result;
|
199
|
+
}
|
200
|
+
|
201
|
+
static VALUE rb_tinytds_charset(VALUE self) {
|
202
|
+
GET_CLIENT_WRAPPER(self);
|
203
|
+
return cwrap->charset;
|
204
|
+
}
|
205
|
+
|
206
|
+
static VALUE rb_tinytds_encoding(VALUE self) {
|
207
|
+
GET_CLIENT_WRAPPER(self);
|
208
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
209
|
+
return rb_enc_from_encoding(cwrap->encoding);
|
210
|
+
#else
|
211
|
+
return Qnil;
|
212
|
+
#endif
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE rb_tinytds_escape(VALUE self, VALUE string) {
|
216
|
+
Check_Type(string, T_STRING);
|
217
|
+
GET_CLIENT_WRAPPER(self);
|
218
|
+
VALUE new_string = rb_funcall(string, intern_gsub, 2, opt_escape_regex, opt_escape_dblquote);
|
219
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
220
|
+
rb_enc_associate(new_string, cwrap->encoding);
|
221
|
+
#endif
|
222
|
+
return new_string;
|
223
|
+
}
|
224
|
+
|
225
|
+
/* Duplicated in result.c */
|
226
|
+
static VALUE rb_tinytds_return_code(VALUE self) {
|
227
|
+
GET_CLIENT_WRAPPER(self);
|
228
|
+
if (cwrap->client && dbhasretstat(cwrap->client)) {
|
229
|
+
return LONG2NUM((long)dbretstatus(cwrap->client));
|
230
|
+
} else {
|
231
|
+
return Qnil;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
|
236
|
+
// TinyTds::Client (protected)
|
237
|
+
|
238
|
+
static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
239
|
+
/* Parsing options hash to local vars. */
|
240
|
+
VALUE user, pass, dataserver, database, app, version, ltimeout, timeout, charset, azure;
|
241
|
+
user = rb_hash_aref(opts, sym_username);
|
242
|
+
pass = rb_hash_aref(opts, sym_password);
|
243
|
+
dataserver = rb_hash_aref(opts, sym_dataserver);
|
244
|
+
database = rb_hash_aref(opts, sym_database);
|
245
|
+
app = rb_hash_aref(opts, sym_appname);
|
246
|
+
version = rb_hash_aref(opts, sym_tds_version);
|
247
|
+
ltimeout = rb_hash_aref(opts, sym_login_timeout);
|
248
|
+
timeout = rb_hash_aref(opts, sym_timeout);
|
249
|
+
charset = rb_hash_aref(opts, sym_encoding);
|
250
|
+
azure = rb_hash_aref(opts, sym_azure);
|
251
|
+
/* Dealing with options. */
|
252
|
+
if (dbinit() == FAIL) {
|
253
|
+
rb_raise(cTinyTdsError, "failed dbinit() function");
|
254
|
+
return self;
|
255
|
+
}
|
256
|
+
dberrhandle(tinytds_err_handler);
|
257
|
+
dbmsghandle(tinytds_msg_handler);
|
258
|
+
GET_CLIENT_WRAPPER(self);
|
259
|
+
cwrap->login = dblogin();
|
260
|
+
if (!NIL_P(user))
|
261
|
+
dbsetluser(cwrap->login, StringValuePtr(user));
|
262
|
+
if (!NIL_P(pass))
|
263
|
+
dbsetlpwd(cwrap->login, StringValuePtr(pass));
|
264
|
+
if (!NIL_P(app))
|
265
|
+
dbsetlapp(cwrap->login, StringValuePtr(app));
|
266
|
+
if (!NIL_P(version))
|
267
|
+
dbsetlversion(cwrap->login, NUM2INT(version));
|
268
|
+
if (!NIL_P(ltimeout))
|
269
|
+
dbsetlogintime(NUM2INT(ltimeout));
|
270
|
+
if (!NIL_P(timeout))
|
271
|
+
dbsettime(NUM2INT(timeout));
|
272
|
+
if (!NIL_P(charset))
|
273
|
+
DBSETLCHARSET(cwrap->login, StringValuePtr(charset));
|
274
|
+
if (!NIL_P(database) && (azure == Qtrue)) {
|
275
|
+
#ifdef DBSETLDBNAME
|
276
|
+
DBSETLDBNAME(cwrap->login, StringValuePtr(database));
|
277
|
+
#else
|
278
|
+
rb_warn("TinyTds: Azure connections not supported in this version of FreeTDS.\n");
|
279
|
+
#endif
|
280
|
+
}
|
281
|
+
cwrap->client = dbopen(cwrap->login, StringValuePtr(dataserver));
|
282
|
+
if (cwrap->client) {
|
283
|
+
cwrap->closed = 0;
|
284
|
+
cwrap->charset = charset;
|
285
|
+
dbsetuserdata(cwrap->client, (BYTE*)cwrap->userdata);
|
286
|
+
cwrap->userdata->closed = 0;
|
287
|
+
if (!NIL_P(database) && (azure != Qtrue)) {
|
288
|
+
dbuse(cwrap->client, StringValuePtr(database));
|
289
|
+
}
|
290
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
291
|
+
VALUE transposed_encoding = rb_funcall(cTinyTdsClient, intern_transpose_iconv_encoding, 1, charset);
|
292
|
+
cwrap->encoding = rb_enc_find(StringValuePtr(transposed_encoding));
|
293
|
+
#endif
|
294
|
+
}
|
295
|
+
return self;
|
296
|
+
}
|
297
|
+
|
298
|
+
|
299
|
+
// Lib Init
|
300
|
+
|
301
|
+
void init_tinytds_client() {
|
302
|
+
cTinyTdsClient = rb_define_class_under(mTinyTds, "Client", rb_cObject);
|
303
|
+
rb_define_alloc_func(cTinyTdsClient, allocate);
|
304
|
+
/* Define TinyTds::Client Public Methods */
|
305
|
+
rb_define_method(cTinyTdsClient, "tds_version", rb_tinytds_tds_version, 0);
|
306
|
+
rb_define_method(cTinyTdsClient, "close", rb_tinytds_close, 0);
|
307
|
+
rb_define_method(cTinyTdsClient, "closed?", rb_tinytds_closed, 0);
|
308
|
+
rb_define_method(cTinyTdsClient, "canceled?", rb_tinytds_canceled, 0);
|
309
|
+
rb_define_method(cTinyTdsClient, "dead?", rb_tinytds_dead, 0);
|
310
|
+
rb_define_method(cTinyTdsClient, "sqlsent?", rb_tinytds_sqlsent, 0);
|
311
|
+
rb_define_method(cTinyTdsClient, "execute", rb_tinytds_execute, 1);
|
312
|
+
rb_define_method(cTinyTdsClient, "charset", rb_tinytds_charset, 0);
|
313
|
+
rb_define_method(cTinyTdsClient, "encoding", rb_tinytds_encoding, 0);
|
314
|
+
rb_define_method(cTinyTdsClient, "escape", rb_tinytds_escape, 1);
|
315
|
+
rb_define_method(cTinyTdsClient, "return_code", rb_tinytds_return_code, 0);
|
316
|
+
/* Define TinyTds::Client Protected Methods */
|
317
|
+
rb_define_protected_method(cTinyTdsClient, "connect", rb_tinytds_connect, 1);
|
318
|
+
/* Symbols For Connect */
|
319
|
+
sym_username = ID2SYM(rb_intern("username"));
|
320
|
+
sym_password = ID2SYM(rb_intern("password"));
|
321
|
+
sym_dataserver = ID2SYM(rb_intern("dataserver"));
|
322
|
+
sym_database = ID2SYM(rb_intern("database"));
|
323
|
+
sym_appname = ID2SYM(rb_intern("appname"));
|
324
|
+
sym_tds_version = ID2SYM(rb_intern("tds_version"));
|
325
|
+
sym_login_timeout = ID2SYM(rb_intern("login_timeout"));
|
326
|
+
sym_timeout = ID2SYM(rb_intern("timeout"));
|
327
|
+
sym_encoding = ID2SYM(rb_intern("encoding"));
|
328
|
+
sym_azure = ID2SYM(rb_intern("azure"));
|
329
|
+
/* Intern TinyTds::Error Accessors */
|
330
|
+
intern_source_eql = rb_intern("source=");
|
331
|
+
intern_severity_eql = rb_intern("severity=");
|
332
|
+
intern_db_error_number_eql = rb_intern("db_error_number=");
|
333
|
+
intern_os_error_number_eql = rb_intern("os_error_number=");
|
334
|
+
/* Intern Misc */
|
335
|
+
intern_new = rb_intern("new");
|
336
|
+
intern_dup = rb_intern("dup");
|
337
|
+
intern_transpose_iconv_encoding = rb_intern("transpose_iconv_encoding");
|
338
|
+
intern_local_offset = rb_intern("local_offset");
|
339
|
+
intern_gsub = rb_intern("gsub");
|
340
|
+
/* Escape Regexp Global */
|
341
|
+
opt_escape_regex = rb_funcall(rb_cRegexp, intern_new, 1, rb_str_new2("\\\'"));
|
342
|
+
opt_escape_dblquote = rb_str_new2("''");
|
343
|
+
rb_global_variable(&opt_escape_regex);
|
344
|
+
rb_global_variable(&opt_escape_dblquote);
|
345
|
+
}
|
346
|
+
|
347
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
#ifndef TINYTDS_CLIENT_H
|
3
|
+
#define TINYTDS_CLIENT_H
|
4
|
+
|
5
|
+
void init_tinytds_client();
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
short int closed;
|
9
|
+
short int timing_out;
|
10
|
+
short int dbsql_sent;
|
11
|
+
short int dbsqlok_sent;
|
12
|
+
RETCODE dbsqlok_retcode;
|
13
|
+
short int dbcancel_sent;
|
14
|
+
} tinytds_client_userdata;
|
15
|
+
|
16
|
+
typedef struct {
|
17
|
+
LOGINREC *login;
|
18
|
+
RETCODE return_code;
|
19
|
+
DBPROCESS *client;
|
20
|
+
short int closed;
|
21
|
+
VALUE charset;
|
22
|
+
tinytds_client_userdata *userdata;
|
23
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
24
|
+
rb_encoding *encoding;
|
25
|
+
#endif
|
26
|
+
} tinytds_client_wrapper;
|
27
|
+
|
28
|
+
|
29
|
+
// Lib Macros
|
30
|
+
|
31
|
+
#define GET_CLIENT_USERDATA(dbproc) \
|
32
|
+
tinytds_client_userdata *userdata = (tinytds_client_userdata *)dbgetuserdata(dbproc);
|
33
|
+
|
34
|
+
|
35
|
+
#endif
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
FREETDS_LIBRARIES = ['sybdb']
|
4
|
+
FREETDS_LIBRARIES.unshift 'iconv' if enable_config('iconv')
|
5
|
+
FREETDS_HEADERS = ['sybfront.h', 'sybdb.h']
|
6
|
+
|
7
|
+
dir_config('iconv') if enable_config('iconv')
|
8
|
+
dir_config('freetds')
|
9
|
+
|
10
|
+
def root_paths
|
11
|
+
eop_regexp = /#{File::SEPARATOR}bin$/
|
12
|
+
paths = ENV['PATH']
|
13
|
+
paths = paths.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
14
|
+
paths = paths.split(File::PATH_SEPARATOR)
|
15
|
+
bin_paths = paths.select{ |p| p =~ eop_regexp }
|
16
|
+
bin_paths.map{ |p| p.sub(eop_regexp,'') }.compact.reject{ |p| p.empty? }.uniq
|
17
|
+
end
|
18
|
+
|
19
|
+
def have_freetds_libraries?(*libraries)
|
20
|
+
libraries.all? { |l| have_library(l) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_freetds_libraries_path
|
24
|
+
root_paths.detect do |path|
|
25
|
+
[['lib'],['lib','freetds']].detect do |lpaths|
|
26
|
+
dir = File.join path, *lpaths
|
27
|
+
message = "looking for library directory #{dir} ..."
|
28
|
+
if File.directory?(dir)
|
29
|
+
puts "#{message} yes"
|
30
|
+
if with_ldflags("#{$LDFLAGS} -L#{dir}".strip) { have_freetds_libraries?(*FREETDS_LIBRARIES) }
|
31
|
+
$LDFLAGS = "-L#{dir} #{$LDFLAGS}".strip
|
32
|
+
true
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
36
|
+
else
|
37
|
+
puts "#{message} no"
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def have_freetds_headers?(*headers)
|
45
|
+
headers.all? { |h| have_header(h) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_freetds_include_path
|
49
|
+
root_paths.detect do |path|
|
50
|
+
[['include'],['include','freetds']].detect do |ipaths|
|
51
|
+
dir = File.join path, *ipaths
|
52
|
+
message = "looking for include directory #{dir} ..."
|
53
|
+
if File.directory?(dir)
|
54
|
+
puts "#{message} yes"
|
55
|
+
if with_cppflags("#{$CPPFLAGS} -I#{dir}".strip) { have_freetds_headers?(*FREETDS_HEADERS) }
|
56
|
+
$CPPFLAGS = "-I#{dir} #{$CPPFLAGS}".strip
|
57
|
+
true
|
58
|
+
else
|
59
|
+
false
|
60
|
+
end
|
61
|
+
else
|
62
|
+
puts "#{message} no"
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def have_freetds?
|
70
|
+
find_freetds_libraries_path && find_freetds_include_path
|
71
|
+
end
|
72
|
+
|
73
|
+
if enable_config("lookup", true)
|
74
|
+
unless have_freetds?
|
75
|
+
abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
|
76
|
+
end
|
77
|
+
else
|
78
|
+
$LDFLAGS = ENV.fetch("LDFLAGS")
|
79
|
+
unless have_freetds_libraries?(*FREETDS_LIBRARIES) && have_freetds_headers?(*FREETDS_HEADERS)
|
80
|
+
abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
create_makefile('tiny_tds/tiny_tds')
|