activerecord-nuodb-adapter 1.0.0.rc.1 → 1.0.0.rc.2
Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc
CHANGED
@@ -4,6 +4,77 @@
|
|
4
4
|
|
5
5
|
This is the NuoDB ActiveRecord Adapter.
|
6
6
|
|
7
|
+
== RUNNING A SAMPLE APPLICATION
|
8
|
+
|
9
|
+
Let me walk you through the creation of a sample Ruby application to the point
|
10
|
+
of having it running against NuoDB...
|
11
|
+
|
12
|
+
Start up a minimal chorus as follows:
|
13
|
+
|
14
|
+
export NUODB_ROOT=/Users/Path/To/NuoDB
|
15
|
+
java -jar ${NUODB_ROOT}/jar/nuoagent.jar --broker &
|
16
|
+
${NUODB_ROOT}/bin/nuodb --chorus test --password bar --dba-user dba --dba-password baz --verbose debug --archive /var/tmp/nuodb --initialize --force &
|
17
|
+
${NUODB_ROOT}/bin/nuodb --chorus test --password bar --dba-user dba --dba-password baz &
|
18
|
+
|
19
|
+
Create a user in the database:
|
20
|
+
|
21
|
+
${NUODB_ROOT}/bin/nuosql test@localhost --user dba --password baz
|
22
|
+
> create user cloud password 'user';
|
23
|
+
> exit
|
24
|
+
|
25
|
+
Install our Gems; the following shows how to do this if you have copies
|
26
|
+
of the gems locally, but is easier if you install them from rubygems.org.
|
27
|
+
|
28
|
+
gem install nuodb-1.0.0.rc.2.gem
|
29
|
+
gem install activerecord-nuodb-adapter-1.0.0.rc.2.gem
|
30
|
+
|
31
|
+
Prepare a sample application:
|
32
|
+
|
33
|
+
rails new slambook
|
34
|
+
cd slambook/
|
35
|
+
|
36
|
+
Add the following Gems to your Gemfile:
|
37
|
+
|
38
|
+
gem 'nuodb', '=1.0.0.rc.2'
|
39
|
+
gem 'activerecord-nuodb-adapter', '=1.0.0.rc.2'
|
40
|
+
|
41
|
+
Update your config/database.yml file as follows:
|
42
|
+
|
43
|
+
development:
|
44
|
+
adapter: nuodb
|
45
|
+
database: test@localhost
|
46
|
+
username: cloud
|
47
|
+
password: user
|
48
|
+
schema: test
|
49
|
+
|
50
|
+
test:
|
51
|
+
adapter: nuodb
|
52
|
+
database: test@localhost
|
53
|
+
username: cloud
|
54
|
+
password: user
|
55
|
+
schema: test
|
56
|
+
|
57
|
+
production:
|
58
|
+
adapter: nuodb
|
59
|
+
database: test@localhost
|
60
|
+
username: cloud
|
61
|
+
password: user
|
62
|
+
schema: test
|
63
|
+
|
64
|
+
6. Build the application and prepare your databases:
|
65
|
+
|
66
|
+
bundle install
|
67
|
+
rake db:create
|
68
|
+
rake db:migrate
|
69
|
+
|
70
|
+
7. Start the Rails server:
|
71
|
+
|
72
|
+
bundle exec rails server
|
73
|
+
|
74
|
+
8. Open up your browser:
|
75
|
+
|
76
|
+
chrome http://localhost:3000
|
77
|
+
|
7
78
|
== BUILDING THE GEM
|
8
79
|
|
9
80
|
To compile and test run this command:
|
@@ -12,11 +83,11 @@ To compile and test run this command:
|
|
12
83
|
|
13
84
|
== INSTALLING THE GEM
|
14
85
|
|
15
|
-
gem install activerecord-nuodb-adapter-1.0.0.rc.
|
86
|
+
gem install activerecord-nuodb-adapter-1.0.0.rc.2.gem
|
16
87
|
|
17
88
|
Or from the source tree:
|
18
89
|
|
19
|
-
gem install pkg/activerecord-nuodb-adapter-1.0.0.rc.
|
90
|
+
gem install pkg/activerecord-nuodb-adapter-1.0.0.rc.2.gem
|
20
91
|
|
21
92
|
Or you can do this using Rake:
|
22
93
|
|
@@ -45,25 +116,57 @@ Run the tests:
|
|
45
116
|
|
46
117
|
Tag the product using tags per the SemVer specification; our tags have a v-prefix:
|
47
118
|
|
48
|
-
git tag -a v1.0.0-rc.
|
119
|
+
git tag -a v1.0.0-rc.2 -m "SemVer Version: v1.0.0-rc.2"
|
49
120
|
git push --tags
|
50
121
|
|
51
122
|
If you make a mistake, take it back quickly:
|
52
123
|
|
53
|
-
git tag -d v1.0.0-rc.
|
54
|
-
git push origin :refs/tags/v1.0.0-rc.
|
124
|
+
git tag -d v1.0.0-rc.2
|
125
|
+
git push origin :refs/tags/v1.0.0-rc.2
|
55
126
|
|
56
127
|
===PUBLISHING
|
57
128
|
|
58
129
|
Here are the commands used to publish:
|
59
130
|
|
60
|
-
gem push pkg/nuodb-1.0.0.rc.
|
131
|
+
gem push pkg/nuodb-1.0.0.rc.2.gem
|
61
132
|
|
62
133
|
== INSPECTING THE GEM
|
63
134
|
|
64
135
|
It is often useful to inspect the contents of a Gem before distribution.
|
65
136
|
To do this you dump the contents of a gem thus:
|
66
137
|
|
67
|
-
gem unpack pkg/activerecord-nuodb-adapter-1.0.0.rc.
|
138
|
+
gem unpack pkg/activerecord-nuodb-adapter-1.0.0.rc.2.gem
|
139
|
+
|
140
|
+
== RUNNING ACTIVE RECORD COMPLIANCE TEST SUITES
|
141
|
+
|
142
|
+
Install both the NuoDB Ruby Gem and the NuoDB ActiveRecord Adapter Gem:
|
143
|
+
|
144
|
+
gem install nuodb
|
145
|
+
gem install activerecord-nuodb-adapter
|
146
|
+
|
147
|
+
You may need to uninstall an earlier version to ensure you only have
|
148
|
+
the version you want to install:
|
149
|
+
|
150
|
+
gem uninstall activerecord-nuodb-adapter
|
151
|
+
|
152
|
+
Run equivalent commands to the following to set up your environment:
|
153
|
+
|
154
|
+
export NUODB_AR=1
|
155
|
+
export NUODB_ROOT=/Users/rbuck/tmp/nuodb
|
156
|
+
export PATH=${NUODB_ROOT}/bin:${PATH}
|
157
|
+
|
158
|
+
Start up NuoDB as follows:
|
159
|
+
|
160
|
+
java -jar ${NUODB_ROOT}/jar/nuoagent.jar --broker &
|
161
|
+
${NUODB_ROOT}/bin/nuodb --chorus arunit --password bar --dba-user dba --dba-password baz --force &
|
162
|
+
|
163
|
+
Configure your RVM environment:
|
164
|
+
|
165
|
+
cd rails
|
166
|
+
bundle install
|
167
|
+
|
168
|
+
Run the test suite as follows:
|
169
|
+
|
170
|
+
cd activerecord
|
171
|
+
ARCONN=nuodb ruby -Itest test/cases/base_test.rb
|
68
172
|
|
69
|
-
== REFERENCES
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.add_dependency('activerecord', '~> 3.2.8')
|
18
18
|
gem.add_development_dependency('rake', '~> 0.9')
|
19
19
|
gem.add_development_dependency('rdoc', '~> 3.10')
|
20
|
-
gem.add_dependency('nuodb', '~> 1.0.0.rc.
|
20
|
+
gem.add_dependency('nuodb', '~> 1.0.0.rc.2')
|
21
21
|
|
22
22
|
gem.files = `git ls-files`.split($\)
|
23
23
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
@@ -30,6 +30,7 @@ require 'arel/visitors/nuodb'
|
|
30
30
|
require 'active_record'
|
31
31
|
require 'active_record/base'
|
32
32
|
require 'active_record/connection_adapters/abstract_adapter'
|
33
|
+
require 'active_record/connection_adapters/abstract/database_statements'
|
33
34
|
require 'active_record/connection_adapters/statement_pool'
|
34
35
|
require 'active_record/connection_adapters/nuodb/version'
|
35
36
|
require 'arel/visitors/bind_visitor'
|
@@ -48,6 +49,7 @@ module ActiveRecord
|
|
48
49
|
end
|
49
50
|
# supply configuration defaults
|
50
51
|
config.reverse_merge! :host => 'localhost'
|
52
|
+
config.reverse_merge! :timezone => 'UTC'
|
51
53
|
ConnectionAdapters::NuoDBAdapter.new nil, logger, nil, config
|
52
54
|
end
|
53
55
|
|
@@ -142,22 +144,8 @@ module ActiveRecord
|
|
142
144
|
|
143
145
|
def simplified_type(field_type)
|
144
146
|
case field_type
|
145
|
-
when /real/i then
|
146
|
-
:float
|
147
|
-
when /money/i then
|
148
|
-
:decimal
|
149
|
-
when /image/i then
|
150
|
-
:binary
|
151
147
|
when /bit/i then
|
152
148
|
:boolean
|
153
|
-
when /uniqueidentifier/i then
|
154
|
-
:string
|
155
|
-
when /datetime/i then
|
156
|
-
:datetime
|
157
|
-
when /varchar\(max\)/ then
|
158
|
-
:text
|
159
|
-
when /timestamp/ then
|
160
|
-
:binary
|
161
149
|
else
|
162
150
|
super
|
163
151
|
end
|
@@ -218,7 +206,8 @@ module ActiveRecord
|
|
218
206
|
end
|
219
207
|
|
220
208
|
def dealloc(stmt)
|
221
|
-
|
209
|
+
# todo
|
210
|
+
#stmt.finish if connection.ping
|
222
211
|
end
|
223
212
|
end
|
224
213
|
|
@@ -300,10 +289,7 @@ module ActiveRecord
|
|
300
289
|
end
|
301
290
|
|
302
291
|
def connect!
|
303
|
-
|
304
|
-
@connection = ::NuoDB::Connection.createSqlConnection(
|
305
|
-
"#{config[:database]}@#{config[:host]}", config[:schema],
|
306
|
-
config[:username], config[:password])
|
292
|
+
@connection = ::NuoDB::Connection.new(config)
|
307
293
|
@statements = StatementPool.new(@connection, @config.fetch(:statement_limit) { 1000 })
|
308
294
|
@quoted_column_names, @quoted_table_names = {}, {}
|
309
295
|
end
|
@@ -320,7 +306,6 @@ module ActiveRecord
|
|
320
306
|
|
321
307
|
def clear_cache!
|
322
308
|
@statements.clear
|
323
|
-
@statements = nil
|
324
309
|
end
|
325
310
|
|
326
311
|
# SAVEPOINT SUPPORT ======================================
|
@@ -364,6 +349,8 @@ module ActiveRecord
|
|
364
349
|
LostConnection.new(message, exception)
|
365
350
|
when *connection_not_established_messages
|
366
351
|
ConnectionNotEstablished.new(message)
|
352
|
+
#when /violates foreign key constraint/
|
353
|
+
# InvalidForeignKey.new(message, exception)
|
367
354
|
else
|
368
355
|
super
|
369
356
|
end
|
@@ -384,7 +371,7 @@ module ActiveRecord
|
|
384
371
|
indexfields.schema = ? AND
|
385
372
|
indexfields.tablename = ?
|
386
373
|
eosql
|
387
|
-
row && row.first
|
374
|
+
row && row.first.downcase
|
388
375
|
end
|
389
376
|
|
390
377
|
def version
|
@@ -395,6 +382,24 @@ module ActiveRecord
|
|
395
382
|
|
396
383
|
public
|
397
384
|
|
385
|
+
# Bug: (4) methods, see: http://tools/jira/browse/DB-2389
|
386
|
+
|
387
|
+
def change_column(table_name, column_name, type, options = {})
|
388
|
+
raise NotImplementedError, "change_column is not implemented"
|
389
|
+
end
|
390
|
+
|
391
|
+
def change_column_default(table_name, column_name, default)
|
392
|
+
raise NotImplementedError, "change_column_default is not implemented"
|
393
|
+
end
|
394
|
+
|
395
|
+
def rename_column(table_name, column_name, new_column_name)
|
396
|
+
raise NotImplementedError, "rename_column is not implemented"
|
397
|
+
end
|
398
|
+
|
399
|
+
def rename_table(table_name, new_name)
|
400
|
+
raise NotImplementedError, "rename_table is not implemented"
|
401
|
+
end
|
402
|
+
|
398
403
|
def table_exists?(table_name)
|
399
404
|
return false unless table_name
|
400
405
|
|
@@ -473,38 +478,63 @@ module ActiveRecord
|
|
473
478
|
end
|
474
479
|
|
475
480
|
def columns(table_name, name = nil)
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
481
|
+
|
482
|
+
# the following query returns something like this:
|
483
|
+
#
|
484
|
+
# INDEXNAME TABLENAME NON_UNIQUE FIELD LENGTH
|
485
|
+
# ---------------------- --------- ---------- --------- ------
|
486
|
+
# COMPANIES..PRIMARY_KEY COMPANIES 0 ID 4
|
487
|
+
# COMPANY_INDEX COMPANIES 1 FIRM_ID 4
|
488
|
+
# COMPANY_INDEX COMPANIES 1 TYPE 255
|
489
|
+
# COMPANY_INDEX COMPANIES 1 RATING 4
|
490
|
+
# COMPANY_INDEX COMPANIES 1 RUBY_TYPE 255
|
491
|
+
|
492
|
+
result = exec_query(<<-eosql, 'SCHEMA', [config[:schema], table_name.to_s])
|
493
|
+
SELECT
|
494
|
+
fields.field as name,
|
495
|
+
fields.defaultvalue as default_value,
|
496
|
+
datatypes.name as data_type,
|
497
|
+
fields.flags as flags
|
498
|
+
FROM
|
499
|
+
system.fields AS fields, system.datatypes AS datatypes
|
500
|
+
WHERE
|
501
|
+
schema = ? AND tablename = ? AND
|
502
|
+
datatypes.id = fields.datatype
|
503
|
+
ORDER BY fields.fieldposition
|
504
|
+
eosql
|
505
|
+
|
506
|
+
columns = []
|
507
|
+
result.map do |row|
|
508
|
+
row.symbolize_keys!
|
509
|
+
columns << NuoDBColumn.new(row[:name].downcase, row[:default_value], row[:data_type], row[:flags].to_i & 1 == 0)
|
495
510
|
end
|
496
|
-
|
511
|
+
columns
|
497
512
|
end
|
498
513
|
|
499
|
-
# todo implement the remaining schema statements methods: rename columns, tables, etc...
|
500
|
-
# todo, and these methods have to clear the cache!!!
|
501
|
-
|
502
514
|
public
|
503
515
|
|
504
516
|
def native_database_types
|
505
|
-
|
517
|
+
{
|
518
|
+
# generic rails types...
|
519
|
+
:binary => {:name => 'binary'},
|
520
|
+
:boolean => {:name => 'boolean'},
|
521
|
+
:date => {:name => 'date'},
|
522
|
+
:datetime => {:name => 'datetime'},
|
523
|
+
:decimal => {:name => 'decimal'},
|
524
|
+
:float => {:name => 'float', :limit => 8},
|
525
|
+
:integer => {:name => 'integer'},
|
526
|
+
:primary_key => 'int not null generated by default as identity primary key',
|
527
|
+
:string => {:name => 'varchar', :limit => 255},
|
528
|
+
:text => {:name => 'varchar', :limit => 255},
|
529
|
+
:time => {:name => 'time'},
|
530
|
+
:timestamp => {:name => 'timestamp'},
|
531
|
+
# nuodb specific types...
|
532
|
+
:char => {:name => 'char'},
|
533
|
+
:numeric => {:name => 'numeric(20)'},
|
534
|
+
}
|
506
535
|
end
|
507
536
|
|
537
|
+
# maps logical rails types to nuodb-specific data types.
|
508
538
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
509
539
|
case type.to_s
|
510
540
|
when 'integer'
|
@@ -526,33 +556,11 @@ module ActiveRecord
|
|
526
556
|
|
527
557
|
private
|
528
558
|
|
529
|
-
NATIVE_DATABASE_TYPES = {
|
530
|
-
:primary_key => 'int not null generated by default as identity primary key',
|
531
|
-
:string => {:name => 'varchar', :limit => 255},
|
532
|
-
:text => {:name => 'varchar', :limit => 255},
|
533
|
-
:integer => {:name => 'integer'},
|
534
|
-
:float => {:name => 'float', :limit => 8},
|
535
|
-
:decimal => {:name => 'decimal'},
|
536
|
-
:datetime => {:name => 'datetime'},
|
537
|
-
:timestamp => {:name => 'datetime'},
|
538
|
-
:time => {:name => 'time'},
|
539
|
-
:date => {:name => 'date'},
|
540
|
-
:binary => {:name => 'binary'},
|
541
|
-
:boolean => {:name => 'boolean'},
|
542
|
-
:char => {:name => 'char'},
|
543
|
-
:varchar_max => {:name => 'varchar(max)'},
|
544
|
-
:nchar => {:name => 'nchar'},
|
545
|
-
:nvarchar => {:name => 'nvarchar', :limit => 255},
|
546
|
-
:nvarchar_max => {:name => 'nvarchar(max)'},
|
547
|
-
:ntext => {:name => 'ntext', :limit => 255},
|
548
|
-
:ss_timestamp => {:name => 'timestamp'}
|
549
|
-
}
|
550
|
-
|
551
559
|
def split_table_name(table)
|
552
560
|
name_parts = table.split '.'
|
553
561
|
case name_parts.length
|
554
562
|
when 1
|
555
|
-
schema_name =
|
563
|
+
schema_name = config[:schema]
|
556
564
|
table_name = name_parts[0]
|
557
565
|
when 2
|
558
566
|
schema_name = name_parts[0]
|
@@ -575,6 +583,11 @@ module ActiveRecord
|
|
575
583
|
@quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`')
|
576
584
|
end
|
577
585
|
|
586
|
+
def type_cast(value, column)
|
587
|
+
return super unless value == true || value == false
|
588
|
+
value ? true : false
|
589
|
+
end
|
590
|
+
|
578
591
|
def quoted_true
|
579
592
|
"'true'"
|
580
593
|
end
|
@@ -583,12 +596,22 @@ module ActiveRecord
|
|
583
596
|
"'false'"
|
584
597
|
end
|
585
598
|
|
599
|
+
def quoted_date(value)
|
600
|
+
if value.acts_like?(:time)
|
601
|
+
zone_conversion_method = :getutc
|
602
|
+
if value.respond_to?(zone_conversion_method)
|
603
|
+
value = value.send(zone_conversion_method)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
value.to_s(:db)
|
607
|
+
end
|
608
|
+
|
586
609
|
# DATABASE STATEMENTS ####################################
|
587
610
|
|
588
611
|
public
|
589
612
|
|
590
613
|
def outside_transaction?
|
591
|
-
|
614
|
+
nil
|
592
615
|
end
|
593
616
|
|
594
617
|
def supports_statement_cache?
|
@@ -619,86 +642,89 @@ module ActiveRecord
|
|
619
642
|
}
|
620
643
|
end
|
621
644
|
|
645
|
+
def default_sequence_name(table, column)
|
646
|
+
result = exec_query(<<-eosql, 'SCHEMA')
|
647
|
+
SELECT generator_sequence FROM system.fields WHERE tablename='#{table}' AND field='#{column}'
|
648
|
+
eosql
|
649
|
+
result.rows.first.first
|
650
|
+
rescue ActiveRecord::StatementInvalid
|
651
|
+
"#{table}$#{column}"
|
652
|
+
end
|
653
|
+
|
622
654
|
def execute(sql, name = 'SQL')
|
623
655
|
log(sql, name) do
|
624
656
|
cache = statements[process_id] ||= {
|
625
|
-
:stmt => raw_connection.
|
657
|
+
:stmt => raw_connection.statement
|
626
658
|
}
|
627
659
|
stmt = cache[:stmt]
|
628
660
|
stmt.execute(sql)
|
629
661
|
end
|
630
662
|
end
|
631
663
|
|
632
|
-
def
|
664
|
+
def exec_insert(sql, name, binds)
|
665
|
+
exec_query sql, name, binds.map { |col, val| type_cast(val, col) }, true
|
666
|
+
end
|
667
|
+
|
668
|
+
def exec_update(sql, name, binds)
|
669
|
+
exec_query(sql, name, binds, true)
|
670
|
+
end
|
671
|
+
|
672
|
+
def exec_delete(sql, name, binds)
|
673
|
+
exec_query(sql, name, binds.map { |col, val| type_cast(val, col) })
|
674
|
+
end
|
675
|
+
|
676
|
+
def exec_query(sql, name = 'SQL', binds = [], get_generated_keys = false)
|
633
677
|
log(sql, name, binds) do
|
634
678
|
if binds.empty?
|
635
679
|
|
636
680
|
cache = statements[process_id] ||= {
|
637
|
-
:stmt => raw_connection.
|
681
|
+
:stmt => raw_connection.statement
|
638
682
|
}
|
639
683
|
stmt = cache[:stmt]
|
640
684
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
685
|
+
results = nil
|
686
|
+
if stmt.execute(sql)
|
687
|
+
results = convert_results stmt.results
|
688
|
+
end
|
689
|
+
if get_generated_keys
|
690
|
+
generated_keys_result = stmt.generated_keys
|
691
|
+
if generated_keys_result.nil? || generated_keys_result.rows.empty?
|
692
|
+
@last_inserted_id = nil
|
693
|
+
else
|
694
|
+
@last_inserted_id = generated_keys_result.rows.last[0]
|
695
|
+
end
|
652
696
|
end
|
653
697
|
|
698
|
+
results
|
654
699
|
else
|
655
|
-
|
656
700
|
cache = statements[sql] ||= {
|
657
701
|
:stmt => raw_connection.prepare(sql)
|
658
702
|
}
|
659
703
|
stmt = cache[:stmt]
|
660
|
-
binds.to_enum.with_index(1).each { |bind, column|
|
661
|
-
value = bind[1]
|
662
|
-
case value
|
663
|
-
when String
|
664
|
-
stmt.setString column, value
|
665
|
-
when Integer
|
666
|
-
stmt.setInteger column, value
|
667
|
-
when Fixnum
|
668
|
-
stmt.setInteger column, value
|
669
|
-
when Float
|
670
|
-
stmt.setDouble column, value
|
671
|
-
when TrueClass
|
672
|
-
stmt.setBoolean column, true
|
673
|
-
when FalseClass
|
674
|
-
stmt.setBoolean column, false
|
675
|
-
when Time
|
676
|
-
stmt.setTime column, value
|
677
|
-
else
|
678
|
-
raise "don't know how to bind #{value.class} to parameter #{column}"
|
679
|
-
end
|
680
|
-
}
|
681
704
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
else
|
695
|
-
nil
|
705
|
+
results = nil
|
706
|
+
stmt.bind_params binds
|
707
|
+
if stmt.execute
|
708
|
+
results = convert_results stmt.results
|
709
|
+
end
|
710
|
+
if get_generated_keys
|
711
|
+
generated_keys_result = stmt.generated_keys
|
712
|
+
if generated_keys_result.nil? || generated_keys_result.rows.empty?
|
713
|
+
@last_inserted_id = nil
|
714
|
+
else
|
715
|
+
@last_inserted_id = generated_keys_result.rows.last[0]
|
716
|
+
end
|
696
717
|
end
|
697
718
|
|
719
|
+
results
|
698
720
|
end
|
699
721
|
end
|
700
722
|
end
|
701
723
|
|
724
|
+
def convert_results(results)
|
725
|
+
ActiveRecord::Result.new(column_names(results), results.rows)
|
726
|
+
end
|
727
|
+
|
702
728
|
def last_inserted_id(result)
|
703
729
|
@last_inserted_id
|
704
730
|
end
|
@@ -706,68 +732,21 @@ module ActiveRecord
|
|
706
732
|
protected
|
707
733
|
|
708
734
|
def select(sql, name = nil, binds = [])
|
709
|
-
exec_query(sql, name, binds).to_a
|
735
|
+
exec_query(sql, name, binds.map { |col, val| type_cast(val, col) }).to_a
|
710
736
|
end
|
711
737
|
|
712
738
|
protected
|
713
739
|
|
714
740
|
def select_rows(sql, name = nil)
|
715
|
-
|
741
|
+
exec_query(sql, name).rows
|
716
742
|
end
|
717
743
|
|
718
744
|
private
|
719
745
|
|
720
746
|
def column_names (result)
|
721
747
|
return [] if result.nil?
|
722
|
-
|
723
|
-
|
724
|
-
count = meta.getColumnCount
|
725
|
-
(1..count).each { |i|
|
726
|
-
names << meta.getColumnName(i).downcase
|
727
|
-
}
|
728
|
-
names
|
729
|
-
end
|
730
|
-
|
731
|
-
def all_rows(result)
|
732
|
-
rows = []
|
733
|
-
while (row = next_row(result)) != nil
|
734
|
-
rows << row
|
735
|
-
end
|
736
|
-
rows
|
737
|
-
end
|
738
|
-
|
739
|
-
def next_row(result)
|
740
|
-
return nil if result.nil?
|
741
|
-
if result.next
|
742
|
-
meta = result.getMetaData
|
743
|
-
count = meta.getColumnCount
|
744
|
-
row = []
|
745
|
-
(1..count).each { |i|
|
746
|
-
type = meta.getType(i)
|
747
|
-
case type
|
748
|
-
when :SQL_INTEGER
|
749
|
-
row << result.getInteger(i)
|
750
|
-
when :SQL_DOUBLE
|
751
|
-
row << result.getDouble(i)
|
752
|
-
when :SQL_STRING
|
753
|
-
row << result.getString(i)
|
754
|
-
when :SQL_DATE
|
755
|
-
row << result.getDate(i)
|
756
|
-
when :SQL_TIME
|
757
|
-
row << result.getTime(i)
|
758
|
-
when :SQL_TIMESTAMP
|
759
|
-
row << result.getTimestamp(i)
|
760
|
-
when :SQL_CHAR
|
761
|
-
row << result.getChar(i)
|
762
|
-
when :SQL_BOOLEAN
|
763
|
-
row << result.getBoolean(i)
|
764
|
-
else
|
765
|
-
raise "unknown type #{type} for column #{i}"
|
766
|
-
end
|
767
|
-
}
|
768
|
-
row
|
769
|
-
else
|
770
|
-
nil
|
748
|
+
result.columns.inject([]) do |array, column|
|
749
|
+
array << column.name.downcase
|
771
750
|
end
|
772
751
|
end
|
773
752
|
|
data/test/test_simple.rb
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
|
29
29
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), '../lib'))
|
30
30
|
|
31
|
-
require
|
31
|
+
require 'test/unit'
|
32
32
|
require 'rubygems'
|
33
33
|
require 'active_record'
|
34
34
|
|
@@ -37,7 +37,7 @@ class User < ActiveRecord::Base
|
|
37
37
|
|
38
38
|
def to_s
|
39
39
|
return "User(#{@id}), Username: #{@user_name}, Name: #{@first_name} #{@last_name}, #{@admin ? "admin" : "member"}\n" +
|
40
|
-
|
40
|
+
" Address: #{@addr}\n"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -45,7 +45,7 @@ class Addr < ActiveRecord::Base
|
|
45
45
|
belongs_to :User
|
46
46
|
|
47
47
|
def to_s
|
48
|
-
|
48
|
+
"Addr(#{@id}:#{@user_id}) Street: #{@street} City: #{@city} Zip: #{@zip}"
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -54,12 +54,12 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
54
54
|
def setup()
|
55
55
|
|
56
56
|
ActiveRecord::Base.establish_connection(
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
:adapter => 'nuodb',
|
58
|
+
:database => 'test',
|
59
|
+
:schema => 'test',
|
60
|
+
:username => 'cloud',
|
61
|
+
:password => 'user'
|
62
|
+
)
|
63
63
|
|
64
64
|
ActiveRecord::Schema.drop_table(User.table_name) rescue nil
|
65
65
|
|
@@ -72,6 +72,7 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
72
72
|
t.string :email, :limit => 20
|
73
73
|
t.string :user_name, :limit => 20
|
74
74
|
t.boolean :admin
|
75
|
+
t.time :created
|
75
76
|
end
|
76
77
|
create_table Addr.table_name do |t|
|
77
78
|
t.integer :user_id
|
@@ -83,7 +84,6 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
83
84
|
|
84
85
|
end
|
85
86
|
|
86
|
-
|
87
87
|
def test_create_user_records
|
88
88
|
|
89
89
|
fred = User.create do |u|
|
@@ -92,10 +92,12 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
92
92
|
u.email = "fredf@example.com"
|
93
93
|
u.user_name = "fred"
|
94
94
|
u.admin = true
|
95
|
+
u.created = Time.utc(2000, 1, 1, 10, 35, 50)
|
95
96
|
end
|
96
97
|
|
97
98
|
assert_not_nil fred
|
98
99
|
assert_not_nil fred.id
|
100
|
+
assert_equal Time.utc(2000, 1, 1, 10, 35, 50), fred.created
|
99
101
|
|
100
102
|
fred.create_addr do |a|
|
101
103
|
a.street = "301 Cobblestone Way"
|
@@ -130,21 +132,21 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
130
132
|
|
131
133
|
mask = 0
|
132
134
|
User.find do |entry|
|
133
|
-
case entry.id
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
135
|
+
case entry.id
|
136
|
+
when fred.id
|
137
|
+
assert_equal 'Fred', entry.first_name
|
138
|
+
assert_equal 'Flintstone', entry.last_name
|
139
|
+
assert_equal '301 Cobblestone Way', entry.addr.street
|
140
|
+
mask += 1
|
141
|
+
nil
|
142
|
+
when barney.id
|
143
|
+
assert_equal 'Barney', entry.first_name
|
144
|
+
assert_equal 'Rubble', entry.last_name
|
145
|
+
assert_equal '303 Cobblestone Way', entry.addr.street
|
146
|
+
mask += 10
|
147
|
+
nil
|
148
|
+
else
|
149
|
+
raise "unknown entry.id: #{entry.id}"
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
@@ -155,27 +157,38 @@ class NuoSimpleTest < Test::Unit::TestCase
|
|
155
157
|
entry.last_name = entry.last_name.upcase
|
156
158
|
# TODO entry.admin = !entry.admin
|
157
159
|
entry.addr.street = entry.addr.street.upcase
|
158
|
-
entry.addr.save
|
160
|
+
entry.addr.save
|
159
161
|
entry.save
|
160
162
|
end
|
161
163
|
|
162
164
|
assert_equal 2, User.count
|
163
165
|
|
164
166
|
User.find do |entry|
|
165
|
-
case entry.id
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
167
|
+
case entry.id
|
168
|
+
when fred.id
|
169
|
+
assert_equal 'FRED', entry.first_name
|
170
|
+
assert_equal '301 COBBLESTONE WAY', entry.addr.street
|
171
|
+
nil
|
172
|
+
when barney.id
|
173
|
+
assert_equal 'BARNEY', entry.first_name
|
174
|
+
assert_equal '303 COBBLESTONE WAY', entry.addr.street
|
175
|
+
nil
|
176
|
+
else
|
177
|
+
raise 'unknown entry.id'
|
176
178
|
end
|
177
179
|
end
|
178
180
|
|
181
|
+
User.default_timezone = :utc
|
182
|
+
attributes = {"created(1i)" => "2000",
|
183
|
+
"created(2i)" => "1",
|
184
|
+
"created(3i)" => "1",
|
185
|
+
"created(4i)" => "10",
|
186
|
+
"created(5i)" => "35",
|
187
|
+
"created(6i)" => "50"}
|
188
|
+
user = User.new(attributes)
|
189
|
+
assert_equal Time.utc(2000, 1, 1, 10, 35, 50), user.created
|
190
|
+
User.default_timezone = :local
|
191
|
+
|
179
192
|
end
|
180
193
|
|
181
194
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-nuodb-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.rc.
|
4
|
+
version: 1.0.0.rc.2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 1.0.0.rc.
|
69
|
+
version: 1.0.0.rc.2
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.0.0.rc.
|
77
|
+
version: 1.0.0.rc.2
|
78
78
|
description: An adapter for ActiveRecord and AREL to support the NuoDB distributed
|
79
79
|
database backend.
|
80
80
|
email:
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version: 1.3.1
|
123
123
|
requirements: []
|
124
124
|
rubyforge_project:
|
125
|
-
rubygems_version: 1.8.
|
125
|
+
rubygems_version: 1.8.23
|
126
126
|
signing_key:
|
127
127
|
specification_version: 3
|
128
128
|
summary: ActiveRecord adapter with AREL support for NuoDB.
|