sequel_pg 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ === 1.0.2
2
+
3
+ * Build the Windows gem against PostgreSQL 9.0.1 to support the new default bytea serialization format (jeremyevans)
4
+
5
+ * Allow use of Sequel::Postgres::PG_TYPES to add custom conversion support for types not handled by default (funny-falcon)
6
+
7
+ * Fix handling of timestamps with fractional seconds and offsets (funny-falcon)
8
+
9
+ === 1.0.1
10
+
11
+ * Correctly handle timestamps with negative offsets and fractional hours (jeremyevans)
12
+
1
13
  === 1.0.0
2
14
 
3
15
  * Initial Public Release
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Jeremy Evans
1
+ Copyright (c) 2010-2011 Jeremy Evans
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/README.rdoc CHANGED
@@ -126,8 +126,7 @@ above, please test and send me a report including:
126
126
  setting (via Sequel::Postgres.use_iso_date_format = false), you
127
127
  should be OK.
128
128
  * Adding your own type conversion procs to Sequel::Postgres::PG_TYPES
129
- does not have an effect with this plugin, since the type conversion
130
- is done in C.
129
+ only has an effect if those types are not handled by default.
131
130
  * The named_timezones plugin does not integrate with sequel_pg, since
132
131
  sequel_pg does it's own timestamp conversions. The :local and :utc
133
132
  settings for database_timestamp and application_timestamp do work,
@@ -5,8 +5,11 @@ dir_config('pg', ENV["POSTGRES_INCLUDE"] || (IO.popen("pg_config --includedir").
5
5
 
6
6
  if enable_config("static-build")
7
7
  # Link against all required libraries for static build, if they are available
8
- have_library('gdi32', 'CreateDC') && append_library($libs, 'gdi32')
9
- have_library('secur32') && append_library($libs, 'secur32')
8
+ have_library('gdi32', 'CreateDC')
9
+ have_library('secur32')
10
+ have_library('ws2_32')
11
+ have_library('eay32')
12
+ have_library('ssleay32', 'SSL_pending')
10
13
  end
11
14
 
12
15
  if (have_library('pq') || have_library('libpq') || have_library('ms/libpq')) && have_header('libpq-fe.h')
@@ -23,6 +23,7 @@
23
23
  #define SPG_APP_UTC 8
24
24
 
25
25
  static VALUE spg_Sequel;
26
+ static VALUE spg_PG_TYPES;
26
27
  static VALUE spg_Blob;
27
28
  static VALUE spg_BigDecimal;
28
29
  static VALUE spg_Date;
@@ -45,6 +46,9 @@ static ID spg_id_utc_offset;
45
46
  static ID spg_id_localtime;
46
47
  static ID spg_id_new_offset;
47
48
 
49
+ static ID spg_id_call;
50
+ static ID spg_id_get;
51
+
48
52
  static ID spg_id_columns;
49
53
  static ID spg_id_encoding;
50
54
 
@@ -90,45 +94,40 @@ static VALUE spg_date(const char *s) {
90
94
  static VALUE spg_timestamp(const char *s) {
91
95
  VALUE dtc, dt, rtz;
92
96
  int tz = SPG_NO_TZ;
93
- int year, month, day, hour, min, sec, usec, tokens, pos, utc_offset;
94
- int check_offset = 0;
97
+ int year, month, day, hour, min, sec, usec, tokens, utc_offset;
98
+ int usec_start, usec_stop;
99
+ char offset_sign = 0;
95
100
  int offset_hour = 0;
96
101
  int offset_minute = 0;
97
102
  int offset_seconds = 0;
98
103
  double offset_fraction = 0.0;
99
- char subsec[7];
100
104
 
101
105
  if (0 != strchr(s, '.')) {
102
- tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d.%s%n", &year, &month, &day, &hour, &min, &sec, subsec, &pos);
103
- if (tokens == 8) {
104
- check_offset = 1;
105
- }
106
- if(tokens != 7) {
106
+ tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d.%n%d%n%c%02d:%02d",
107
+ &year, &month, &day, &hour, &min, &sec,
108
+ &usec_start, &usec, &usec_stop,
109
+ &offset_sign, &offset_hour, &offset_minute);
110
+ if(tokens < 7) {
107
111
  rb_raise(rb_eArgError, "unexpected datetime format");
108
112
  }
109
- usec = atoi(subsec);
110
- usec *= (int) pow(10, (6 - strlen(subsec)));
113
+ usec *= (int) pow(10, (6 - (usec_stop - usec_start)));
111
114
  } else {
112
- tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d%n", &year, &month, &day, &hour, &min, &sec, &pos);
115
+ tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d%c%02d:%02d",
116
+ &year, &month, &day, &hour, &min, &sec,
117
+ &offset_sign, &offset_hour, &offset_minute);
113
118
  if (tokens == 3) {
114
119
  hour = 0;
115
120
  min = 0;
116
121
  sec = 0;
117
- } else if (tokens == 7) {
118
- check_offset = 1;
119
- } else if (tokens != 6) {
122
+ } else if (tokens < 6) {
120
123
  rb_raise(rb_eArgError, "unexpected datetime format");
121
124
  }
122
125
  usec = 0;
123
126
  }
124
127
 
125
- if (check_offset) {
126
- if(sscanf(s + pos, "%3d:%2d", &offset_hour, &offset_minute) == 0) {
127
- /* No offset found */
128
- check_offset = 0;
129
- } else if (s[pos] == '-') {
130
- offset_minute *= -1;
131
- }
128
+ if (offset_sign == '-') {
129
+ offset_hour *= -1;
130
+ offset_minute *= -1;
132
131
  }
133
132
 
134
133
  /* Get values of datetime_class, database_timezone, and application_timezone */
@@ -147,7 +146,7 @@ static VALUE spg_timestamp(const char *s) {
147
146
  }
148
147
 
149
148
  if (dtc == rb_cTime) {
150
- if (check_offset) {
149
+ if (offset_sign) {
151
150
  /* Offset given, convert to local time if not already in local time.
152
151
  * While PostgreSQL generally returns timestamps in local time, it's unwise to rely on this.
153
152
  */
@@ -184,7 +183,7 @@ static VALUE spg_timestamp(const char *s) {
184
183
  }
185
184
  } else {
186
185
  /* datetime.class == DateTime */
187
- if (check_offset) {
186
+ if (offset_sign) {
188
187
  /* Offset given, handle correct local time.
189
188
  * While PostgreSQL generally returns timestamps in local time, it's unwise to rely on this.
190
189
  */
@@ -235,6 +234,7 @@ static VALUE spg_fetch_rows_set_cols(VALUE self, VALUE ignore) {
235
234
  static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
236
235
  PGresult *res;
237
236
  VALUE colsyms[SPG_MAX_FIELDS];
237
+ VALUE colconvert[SPG_MAX_FIELDS];
238
238
  long ntuples;
239
239
  long nfields;
240
240
  long i;
@@ -257,6 +257,33 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
257
257
 
258
258
  for(j=0; j<nfields; j++) {
259
259
  colsyms[j] = rb_funcall(self, spg_id_output_identifier, 1, rb_str_new2(PQfname(res, j)));
260
+ i = PQftype(res, j);
261
+ switch (i) {
262
+ case 16:
263
+ case 17:
264
+ case 20:
265
+ case 21:
266
+ case 22:
267
+ case 23:
268
+ case 26:
269
+ case 700:
270
+ case 701:
271
+ case 790:
272
+ case 1700:
273
+ case 1082:
274
+ case 1083:
275
+ case 1266:
276
+ case 1114:
277
+ case 1184:
278
+ case 18:
279
+ case 25:
280
+ case 1043:
281
+ colconvert[j] = Qnil;
282
+ break;
283
+ default:
284
+ colconvert[j] = rb_funcall(spg_PG_TYPES, spg_id_get, 1, INT2NUM(i));
285
+ break;
286
+ }
260
287
  }
261
288
  rb_ivar_set(self, spg_id_columns, rb_ary_new4(nfields, colsyms));
262
289
 
@@ -303,11 +330,22 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
303
330
  case 1184:
304
331
  rv = spg_timestamp(v);
305
332
  break;
333
+ case 18: /* char */
334
+ case 25: /* text */
335
+ case 1043: /* varchar*/
336
+ rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
337
+ #ifdef SPG_ENCODING
338
+ rb_enc_associate_index(rv, enc_index);
339
+ #endif
340
+ break;
306
341
  default:
307
342
  rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
308
343
  #ifdef SPG_ENCODING
309
344
  rb_enc_associate_index(rv, enc_index);
310
345
  #endif
346
+ if (colconvert[j] != Qnil) {
347
+ rv = rb_funcall(colconvert[j], spg_id_call, 1, rv);
348
+ }
311
349
  }
312
350
  }
313
351
  rb_hash_aset(h, colsyms[j], rv);
@@ -319,7 +357,7 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
319
357
  }
320
358
 
321
359
  void Init_sequel_pg(void) {
322
- VALUE c;
360
+ VALUE c, spg_Postgres;
323
361
  ID cg;
324
362
  cg = rb_intern("const_get");
325
363
  spg_id_new = rb_intern("new");
@@ -337,6 +375,9 @@ void Init_sequel_pg(void) {
337
375
  spg_id_localtime = rb_intern("localtime");
338
376
  spg_id_new_offset = rb_intern("new_offset");
339
377
 
378
+ spg_id_call = rb_intern("call");
379
+ spg_id_get = rb_intern("[]");
380
+
340
381
  spg_id_columns = rb_intern("@columns");
341
382
  spg_id_encoding = rb_intern("@encoding");
342
383
 
@@ -347,13 +388,15 @@ void Init_sequel_pg(void) {
347
388
  spg_Blob = rb_funcall(rb_funcall(spg_Sequel, cg, 1, rb_str_new2("SQL")), cg, 1, rb_str_new2("Blob"));
348
389
  spg_BigDecimal = rb_funcall(rb_cObject, cg, 1, rb_str_new2("BigDecimal"));
349
390
  spg_Date = rb_funcall(rb_cObject, cg, 1, rb_str_new2("Date"));
391
+ spg_Postgres = rb_funcall(spg_Sequel, cg, 1, rb_str_new2("Postgres"));
392
+ spg_PG_TYPES = rb_funcall(spg_Postgres, cg, 1, rb_str_new2("PG_TYPES"));
350
393
 
351
394
  rb_global_variable(&spg_Sequel);
352
395
  rb_global_variable(&spg_Blob);
353
396
  rb_global_variable(&spg_BigDecimal);
354
397
  rb_global_variable(&spg_Date);
355
398
 
356
- c = rb_funcall(rb_funcall(spg_Sequel, cg, 1, rb_str_new2("Postgres")), cg, 1, rb_str_new2("Dataset"));
399
+ c = rb_funcall(spg_Postgres, cg, 1, rb_str_new2("Dataset"));
357
400
  rb_define_private_method(c, "yield_hash_rows", spg_yield_hash_rows, 2);
358
401
  rb_define_private_method(c, "fetch_rows_set_cols", spg_fetch_rows_set_cols, 1);
359
402
  }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_pg
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 1
10
- version: 1.0.1
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Evans
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-12 00:00:00 -07:00
18
+ date: 2011-03-16 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -64,9 +64,9 @@ extensions:
64
64
  extra_rdoc_files:
65
65
  - README.rdoc
66
66
  - CHANGELOG
67
- - LICENSE
67
+ - MIT-LICENSE
68
68
  files:
69
- - LICENSE
69
+ - MIT-LICENSE
70
70
  - CHANGELOG
71
71
  - README.rdoc
72
72
  - Rakefile