swift 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,7 +71,7 @@ primitive Ruby type conversion.
71
71
  attribute :id, Swift::Type::Integer, serial: true, key: true
72
72
  attribute :name, Swift::Type::String
73
73
  attribute :email, Swift::Type::String
74
- attribute :updated_at, Swift::Type::Time
74
+ attribute :updated_at, Swift::Type::DateTime
75
75
  end # User
76
76
 
77
77
  Swift.db do |db|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.6.0
@@ -9,12 +9,12 @@ require 'swift/validations'
9
9
 
10
10
  class User < Swift::Scheme
11
11
  store :users
12
- attribute :id, Swift::Type::Integer, serial: true, key: true
12
+ attribute :id, Swift::Type::Integer, serial: true, key: true
13
13
  attribute :name, Swift::Type::String
14
14
  attribute :email, Swift::Type::String
15
15
  attribute :active, Swift::Type::Boolean
16
- attribute :created, Swift::Type::Time, default: proc { Time.now }
17
- attribute :optional, Swift::Type::String, default: 'woot'
16
+ attribute :created, Swift::Type::DateTime, default: proc { Time.now }
17
+ attribute :optional, Swift::Type::String, default: 'woot'
18
18
 
19
19
  validations do |errors|
20
20
  errors << [:name, 'is blank'] if name.to_s.empty?
@@ -86,10 +86,9 @@ static VALUE adapter_execute(int argc, VALUE *argv, VALUE self) {
86
86
  if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values);
87
87
  if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(query.sql, query.bind));
88
88
 
89
- // TODO: http://redmine.ruby-lang.org/issues/show/3762
90
- // rb_thread_blocking_region and C++ exceptions don't mix in 1.9.2.
91
- // rows = rb_thread_blocking_region(((VALUE (*)(void*))query_execute), &query, RUBY_UBF_IO, 0);
92
- rows = query_execute(&query);
89
+ if ((rows = rb_thread_blocking_region(((VALUE (*)(void*))query_execute), &query, RUBY_UBF_IO, 0)) == Qfalse)
90
+ rb_raise(eSwiftRuntimeError, "%s", query.error);
91
+
93
92
  if (rb_block_given_p()) {
94
93
  dbi::AbstractResultSet *result = handle->results();
95
94
  return result_each(Data_Wrap_Struct(cSwiftResult, 0, result_free, result));
@@ -55,6 +55,6 @@ exit 1 unless library_installed? 'pcrecpp', apt_install_hint('libpcre3-dev')
55
55
  exit 1 unless library_installed? 'uuid', apt_install_hint('uuid-dev')
56
56
  exit 1 unless library_installed? 'dbic++', apt_install_hint('dbic++-dev')
57
57
 
58
- assert_dbicpp_version '0.3.0'
58
+ assert_dbicpp_version '0.3.1'
59
59
 
60
60
  create_makefile 'swift'
@@ -1,19 +1,31 @@
1
1
  #include "query.h"
2
2
 
3
3
  VALUE query_execute(Query *query) {
4
- return UINT2NUM(
5
- query->bind.size() == 0
6
- ? query->handle->conn()->execute(query->sql)
7
- : query->handle->conn()->execute(query->sql, query->bind)
8
- );
4
+ try {
5
+ return UINT2NUM(
6
+ query->bind.size() == 0
7
+ ? query->handle->conn()->execute(query->sql)
8
+ : query->handle->conn()->execute(query->sql, query->bind)
9
+ );
10
+ }
11
+ catch (dbi::Error &e) {
12
+ query->error = e.what();
13
+ return Qfalse;
14
+ }
9
15
  }
10
16
 
11
17
  VALUE query_execute_statement(Query *query) {
12
- return UINT2NUM(
13
- query->bind.size() == 0
14
- ? query->statement->execute()
15
- : query->statement->execute(query->bind)
16
- );
18
+ try {
19
+ return UINT2NUM(
20
+ query->bind.size() == 0
21
+ ? query->statement->execute()
22
+ : query->statement->execute(query->bind)
23
+ );
24
+ }
25
+ catch (dbi::Error &e) {
26
+ query->error = e.what();
27
+ return Qfalse;
28
+ }
17
29
  }
18
30
 
19
31
  void query_bind_values(Query *query, VALUE bind_values) {
@@ -23,6 +35,12 @@ void query_bind_values(Query *query, VALUE bind_values) {
23
35
  if (bind_value == Qnil) {
24
36
  query->bind.push_back(dbi::PARAM(dbi::null()));
25
37
  }
38
+ else if (bind_value == Qtrue) {
39
+ query->bind.push_back(dbi::PARAM("1"));
40
+ }
41
+ else if (bind_value == Qfalse) {
42
+ query->bind.push_back(dbi::PARAM("0"));
43
+ }
26
44
  else if (rb_obj_is_kind_of(bind_value, rb_cIO) == Qtrue || rb_obj_is_kind_of(bind_value, cStringIO) == Qtrue) {
27
45
  bind_value = rb_funcall(bind_value, rb_intern("read"), 0);
28
46
  query->bind.push_back(dbi::PARAM_BINARY((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
@@ -8,6 +8,7 @@ struct Query {
8
8
  dbi::Handle *handle;
9
9
  dbi::AbstractStatement *statement;
10
10
  dbi::ResultRow bind;
11
+ const char *error;
11
12
  };
12
13
 
13
14
  VALUE query_execute(Query*);
@@ -1,9 +1,10 @@
1
1
  #include "result.h"
2
2
 
3
- VALUE cSwiftResult;
3
+ VALUE cBigDecimal;
4
+ VALUE cDate;
4
5
  VALUE cDateTime;
5
6
  VALUE cStringIO;
6
- VALUE cBigDecimal;
7
+ VALUE cSwiftResult;
7
8
 
8
9
  VALUE fNew, fNewBang;
9
10
 
@@ -91,6 +92,7 @@ static VALUE result_finish(VALUE self) {
91
92
  int64_t client_tzoffset(int64_t local, int isdst) {
92
93
  struct tm tm;
93
94
  gmtime_r((const time_t*)&local, &tm);
95
+ // TODO: This won't work in Lord Howe Island, Australia which uses half hour shift.
94
96
  return (int64_t)(local + (isdst ? 3600 : 0) - mktime(&tm));
95
97
  }
96
98
 
@@ -106,7 +108,7 @@ static void reduce(uint64_t *numerator, uint64_t *denominator) {
106
108
  *denominator = *denominator / b;
107
109
  }
108
110
 
109
- VALUE typecast_datetime(const char *data, uint64_t len) {
111
+ VALUE typecast_timestamp(VALUE klass, const char *data, uint64_t len) {
110
112
  struct tm tm;
111
113
  int64_t epoch, adjust, offset;
112
114
 
@@ -141,24 +143,27 @@ VALUE typecast_datetime(const char *data, uint64_t len) {
141
143
  }
142
144
 
143
145
  // 32bit platforms are for weenies
144
- uint64_t ajd_n = (epoch + adjust - offset), ajd_d = 86400L;
146
+ uint64_t ajd_n = (epoch + adjust - offset)*1000000 + usec*1000000, ajd_d = DAYMICROSECS;
145
147
  reduce(&ajd_n, &ajd_d);
146
148
  ajd_n = epoch_ajd_n*ajd_d + ajd_n*epoch_ajd_d;
147
149
  ajd_d = epoch_ajd_d*ajd_d;
148
150
  reduce(&ajd_n, &ajd_d);
149
151
 
150
152
  VALUE ajd = rb_rational_new(SIZET2NUM(ajd_n), SIZET2NUM(ajd_d));
151
- return rb_funcall(cDateTime, fNewBang, 3, ajd, rb_rational_new(INT2FIX(adjust), daysecs), sg);
153
+ return rb_funcall(klass, fNewBang, 3, ajd, rb_rational_new(INT2FIX(adjust), daysecs), sg);
152
154
  }
153
155
 
154
156
  // TODO: throw a warning ?
155
157
  return rb_str_new(data, len);
156
158
  }
157
159
 
160
+ #define typecast_datetime(data,len) typecast_timestamp(cDateTime, data, len)
161
+ #define typecast_date(data,len) typecast_timestamp(cDate, data, len)
162
+
158
163
  VALUE typecast_field(int type, const char *data, uint64_t length) {
159
164
  switch(type) {
160
165
  case DBI_TYPE_BOOLEAN:
161
- return strcmp(data, "t") == 0 || strcmp(data, "1") == 0 ? Qtrue : Qfalse;
166
+ return (data && (data[0] =='t' || data[0] == '1')) ? Qtrue : Qfalse;
162
167
  case DBI_TYPE_INT:
163
168
  return rb_cstr2inum(data, 10);
164
169
  case DBI_TYPE_BLOB:
@@ -167,6 +172,8 @@ VALUE typecast_field(int type, const char *data, uint64_t length) {
167
172
  return rb_enc_str_new(data, length, rb_utf8_encoding());
168
173
  case DBI_TYPE_TIME:
169
174
  return typecast_datetime(data, length);
175
+ case DBI_TYPE_DATE:
176
+ return typecast_date(data, length);
170
177
  case DBI_TYPE_NUMERIC:
171
178
  return rb_funcall(cBigDecimal, fNew, 1, rb_str_new2(data));
172
179
  case DBI_TYPE_FLOAT:
@@ -219,6 +226,7 @@ void init_swift_result() {
219
226
  VALUE mSwift = rb_define_module("Swift");
220
227
  cSwiftResult = rb_define_class_under(mSwift, "Result", rb_cObject);
221
228
  cDateTime = CONST_GET(rb_mKernel, "DateTime");
229
+ cDate = CONST_GET(rb_mKernel, "Date");
222
230
  cStringIO = CONST_GET(rb_mKernel, "StringIO");
223
231
  cBigDecimal = CONST_GET(rb_mKernel, "BigDecimal");
224
232
 
@@ -37,10 +37,8 @@ static VALUE statement_execute(int argc, VALUE *argv, VALUE self) {
37
37
  if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values);
38
38
  if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(statement->command(), query.bind));
39
39
 
40
- // TODO: http://redmine.ruby-lang.org/issues/show/3762
41
- // rb_thread_blocking_region and C++ exceptions don't mix in 1.9.2.
42
- // rb_thread_blocking_region(((VALUE (*)(void*))query_execute_statement), &query, RUBY_UBF_IO, 0);
43
- query_execute_statement(&query);
40
+ if (rb_thread_blocking_region(((VALUE (*)(void*))query_execute_statement), &query, RUBY_UBF_IO, 0) == Qfalse)
41
+ rb_raise(eSwiftRuntimeError, "%s", query.error);
44
42
  }
45
43
  CATCH_DBI_EXCEPTIONS();
46
44
 
@@ -17,10 +17,10 @@ extern VALUE eSwiftConnectionError;
17
17
 
18
18
  #define CATCH_DBI_EXCEPTIONS() \
19
19
  catch (dbi::ConnectionError &error) { \
20
- rb_raise(eSwiftConnectionError, "%s", CSTRING(rb_str_new2(error.what()))); \
20
+ rb_raise(eSwiftConnectionError, "%s", error.what()); \
21
21
  } \
22
22
  catch (dbi::Error &error) { \
23
- rb_raise(eSwiftRuntimeError, "%s", CSTRING(rb_str_new2(error.what()))); \
23
+ rb_raise(eSwiftRuntimeError, "%s", error.what()); \
24
24
  }
25
25
 
26
26
  #include "adapter.h"
@@ -31,5 +31,13 @@ extern VALUE eSwiftConnectionError;
31
31
  #include "request.h"
32
32
  #include "pool.h"
33
33
 
34
+ #undef SIZET2NUM
35
+ #ifdef HAVE_LONG_LONG
36
+ #define SIZET2NUM(x) ULL2NUM(x)
37
+ #define DAYMICROSECS 86400000000LL
38
+ #else
39
+ #define SIZET2NUM(x) ULONG2NUM(x)
40
+ #define DAYMICROSECS 86400000000L
34
41
  #endif
35
42
 
43
+ #endif
@@ -107,7 +107,7 @@ module Swift
107
107
  when Type::Integer then attribute.serial ? 'serial' : 'integer'
108
108
  when Type::Float then 'float'
109
109
  when Type::BigDecimal then 'numeric'
110
- when Type::Time then 'timestamp'
110
+ when Type::DateTime then 'timestamp'
111
111
  when Type::Boolean then 'boolean'
112
112
  when Type::IO then 'blob'
113
113
  else 'text'
@@ -2,11 +2,12 @@ module Swift
2
2
  module Type
3
3
  class BigDecimal < Attribute; end
4
4
  class Boolean < Attribute; end
5
+ class Date < Attribute; end
6
+ class DateTime < Attribute; end
5
7
  class Float < Attribute; end
6
8
  class Integer < Attribute; end
7
9
  class IO < Attribute; end
8
10
  class String < Attribute; end
9
- class Time < Attribute; end
10
11
  end # Type
11
12
  end # Swift
12
13
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{swift}
8
- s.version = "0.5.1"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Shane Hanna", "Bharanee 'Barney' Rathna"]
12
- s.date = %q{2010-08-30}
12
+ s.date = %q{2010-09-02}
13
13
  s.description = %q{A rational rudimentary database abstraction.}
14
14
  s.email = ["shane.hanna@gmail.com", "deepfryed@gmail.com"]
15
15
  s.extensions = ["ext/extconf.rb"]
@@ -63,12 +63,13 @@ Gem::Specification.new do |s|
63
63
  "test/test_scheme.rb",
64
64
  "test/test_timestamps.rb",
65
65
  "test/test_transactions.rb",
66
+ "test/test_types.rb",
66
67
  "test/test_validations.rb"
67
68
  ]
68
69
  s.homepage = %q{http://github.com/shanna/swift}
69
70
  s.rdoc_options = ["--charset=UTF-8"]
70
71
  s.require_paths = ["lib"]
71
- s.rubygems_version = %q{1.3.7}
72
+ s.rubygems_version = %q{1.3.6}
72
73
  s.summary = %q{A rational rudimentary database abstraction.}
73
74
  s.test_files = [
74
75
  "test/test_pool.rb",
@@ -82,6 +83,7 @@ Gem::Specification.new do |s|
82
83
  "test/test_encoding.rb",
83
84
  "test/test_timestamps.rb",
84
85
  "test/test_scheme.rb",
86
+ "test/test_types.rb",
85
87
  "examples/scheme.rb",
86
88
  "examples/async.rb",
87
89
  "examples/db.rb"
@@ -91,7 +93,7 @@ Gem::Specification.new do |s|
91
93
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
92
94
  s.specification_version = 3
93
95
 
94
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
96
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
95
97
  s.add_development_dependency(%q<minitest>, [">= 1.7.0"])
96
98
  s.add_development_dependency(%q<eventmachine>, [">= 0"])
97
99
  else
@@ -4,12 +4,12 @@ describe 'scheme' do
4
4
  before do
5
5
  @user = Class.new(Swift::Scheme) do
6
6
  store :users
7
- attribute :id, Swift::Type::Integer, serial: true, key: true
8
- attribute :name, Swift::Type::String, default: "dave"
9
- attribute :age, Swift::Type::Integer, default: 18
7
+ attribute :id, Swift::Type::Integer, serial: true, key: true
8
+ attribute :name, Swift::Type::String, default: "dave"
9
+ attribute :age, Swift::Type::Integer, default: 18
10
10
  attribute :email, Swift::Type::String
11
- attribute :verified, Swift::Type::Boolean, default: false
12
- attribute :created_at, Swift::Type::Time, default: proc { Time.now }
11
+ attribute :verified, Swift::Type::Boolean, default: false
12
+ attribute :created_at, Swift::Type::DateTime, default: proc { Time.now }
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,29 @@
1
+ require_relative 'helper'
2
+
3
+ describe 'Adapter' do
4
+ supported_by Swift::DB::Postgres, Swift::DB::Mysql do
5
+ describe 'typecasting' do
6
+ before do
7
+ @db = Swift.db
8
+ @db.execute %q{drop table if exists users}
9
+ @db.execute %q{
10
+ create table users(id serial, name text, age integer, height float, hacker bool, slacker bool, created date)
11
+ }
12
+ end
13
+
14
+ it 'query result is typecast correctly' do
15
+ bind = [ 'jim', 32, 178.71, true, false ]
16
+ @db.execute %q{insert into users(name,age,height,hacker,slacker, created) values(?, ?, ?, ?, ?, now())}, *bind
17
+
18
+ result = @db.prepare(%q{select * from users limit 1}).execute.first
19
+ assert_kind_of Integer, result[:id]
20
+ assert_kind_of String, result[:name]
21
+ assert_kind_of Integer, result[:age]
22
+ assert_kind_of Float, result[:height]
23
+ assert_kind_of TrueClass, result[:hacker]
24
+ assert_kind_of FalseClass, result[:slacker]
25
+ assert_kind_of Date, result[:created]
26
+ end
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 5
8
- - 1
9
- version: 0.5.1
7
+ - 6
8
+ - 0
9
+ version: 0.6.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Shane Hanna
@@ -15,14 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-30 00:00:00 +10:00
18
+ date: 2010-09-02 00:00:00 +10:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: minitest
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
@@ -37,7 +36,6 @@ dependencies:
37
36
  name: eventmachine
38
37
  prerelease: false
39
38
  requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
39
  requirements:
42
40
  - - ">="
43
41
  - !ruby/object:Gem::Version
@@ -103,10 +101,8 @@ files:
103
101
  - test/test_scheme.rb
104
102
  - test/test_timestamps.rb
105
103
  - test/test_transactions.rb
104
+ - test/test_types.rb
106
105
  - test/test_validations.rb
107
- - examples/scheme.rb
108
- - examples/async.rb
109
- - examples/db.rb
110
106
  has_rdoc: true
111
107
  homepage: http://github.com/shanna/swift
112
108
  licenses: []
@@ -117,7 +113,6 @@ rdoc_options:
117
113
  require_paths:
118
114
  - lib
119
115
  required_ruby_version: !ruby/object:Gem::Requirement
120
- none: false
121
116
  requirements:
122
117
  - - ">="
123
118
  - !ruby/object:Gem::Version
@@ -125,7 +120,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
120
  - 0
126
121
  version: "0"
127
122
  required_rubygems_version: !ruby/object:Gem::Requirement
128
- none: false
129
123
  requirements:
130
124
  - - ">="
131
125
  - !ruby/object:Gem::Version
@@ -135,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
129
  requirements: []
136
130
 
137
131
  rubyforge_project:
138
- rubygems_version: 1.3.7
132
+ rubygems_version: 1.3.6
139
133
  signing_key:
140
134
  specification_version: 3
141
135
  summary: A rational rudimentary database abstraction.
@@ -151,6 +145,7 @@ test_files:
151
145
  - test/test_encoding.rb
152
146
  - test/test_timestamps.rb
153
147
  - test/test_scheme.rb
148
+ - test/test_types.rb
154
149
  - examples/scheme.rb
155
150
  - examples/async.rb
156
151
  - examples/db.rb