activerecord-jdbccassandra-adapter 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 James Thompson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ # activerecord-jdbccassandra-adapter
2
+
3
+ * https://github.com/plainprogrammer/activerecord-jdbccassandra-adapter/
4
+
5
+ ## DESCRIPTION:
6
+
7
+ This is an ActiveRecord driver for Cassandra using JDBC running under JRuby.
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_helper'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ module Bundler
5
+ class GemHelper
6
+ def guard_already_tagged
7
+ # parent project performs the tag
8
+ end
9
+ def tag_version
10
+ Bundler.ui.confirm "Parent project tagged #{version_tag}"
11
+ yield if block_given?
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,6 @@
1
+ # NOTE: required by AR resolver with 'jdbccassandra' adapter configuration :
2
+ # require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
3
+ # we should make sure a jdbccassandr_connection is setup on ActiveRecord::Base
4
+ require 'arjdbc/cassandra'
5
+ # all setup should be performed in arjdbc/cassandra to avoid circular requires
6
+ # this should not be required from any loads performed by arjdbc/cassandra code
@@ -0,0 +1,3 @@
1
+ # NOTE: here for Bundler to auto-load the gem unless :require => false
2
+ require 'arjdbc'
3
+ require 'arjdbc/cassandra'
@@ -0,0 +1,275 @@
1
+ require 'arjdbc/jdbc'
2
+ require 'arjdbc/cassandra/version'
3
+ require 'arjdbc/cassandra/jdbc_connection'
4
+ require 'arjdbc/cassandra/column'
5
+ require 'arjdbc/cassandra/error'
6
+ require 'arjdbc/cassandra/adapter'
7
+ require 'arjdbc/cassandra/connection_methods'
8
+
9
+ module ArJdbc
10
+ module Cassandra
11
+ def self.extended(adapter)
12
+ adapter.configure_connection
13
+ end
14
+
15
+ def self.column_selector
16
+ [ /cassandra/i, lambda { |_,column| column.extend(::ArJdbc::Cassandra::Column) } ]
17
+ end
18
+
19
+ def self.jdbc_connection_class
20
+ ::ActiveRecord::ConnectionAdapters::CassandraJdbcConnection
21
+ end
22
+
23
+ NATIVE_DATABASE_TYPES = {
24
+ :primary_key => 'uuid PRIMARY KEY',
25
+ :string => { :name => 'varchar' },
26
+ :text => { :name => 'text' },
27
+ :integer => { :name => 'int' },
28
+ :float => { :name => 'float' },
29
+ :decimal => { :name => 'decimal' },
30
+ :datetime => { :name => 'timestamp' },
31
+ :timestamp => { :name => 'timestamp' },
32
+ :time => { :name => 'timestamp' },
33
+ :date => { :name => 'timestamp' },
34
+ :binary => { :name => 'blob' },
35
+ :boolean => { :name => 'boolean' },
36
+ # Extended support for Cassandra types
37
+ :ascii => { :name => 'ascii' },
38
+ :bigint => { :name => 'bigint' },
39
+ :blob => { :name => 'blob' },
40
+ :counter => { :name => 'counter' },
41
+ :double => { :name => 'double' },
42
+ :inet => { :name => 'inet' },
43
+ :timeuuid => { :name => 'timeuuid' },
44
+ :uuid => { :name => 'uuid' },
45
+ :varchar => { :name => 'varchar' },
46
+ :varint => { :name => 'varint' }
47
+ }
48
+
49
+ def native_database_types
50
+ NATIVE_DATABASE_TYPES
51
+ end
52
+
53
+ ADAPTER_NAME = 'Cassandra'.freeze
54
+
55
+ def adapter_name #:nodoc:
56
+ ADAPTER_NAME
57
+ end
58
+
59
+ def self.arel2_visitors(config)
60
+ {
61
+ 'cassandra' => ::Arel::Visitors::ToSql,
62
+ 'jdbccassandra' => ::Arel::Visitors::ToSql
63
+ }
64
+ end
65
+
66
+ def case_sensitive_modifier(node)
67
+ Arel::Nodes::Bin.new(node)
68
+ end
69
+
70
+ def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
71
+ where_sql
72
+ end
73
+
74
+ def supports_migrations?
75
+ false
76
+ end
77
+
78
+ def supports_primary_key? # :nodoc:
79
+ true
80
+ end
81
+
82
+ def supports_bulk_alter? # :nodoc:
83
+ false
84
+ end
85
+
86
+ def supports_index_sort_order? # :nodoc:
87
+ false
88
+ end
89
+
90
+ def supports_transaction_isolation? # :nodoc:
91
+ false
92
+ end
93
+
94
+ def supports_views? # :nodoc:
95
+ false
96
+ end
97
+
98
+ def supports_savepoints? # :nodoc:
99
+ false
100
+ end
101
+
102
+ # DATABASE STATEMENTS ======================================
103
+
104
+ def exec_insert(sql, name, binds)
105
+ execute sql, name, binds
106
+ end
107
+ alias :exec_update :exec_insert
108
+ alias :exec_delete :exec_insert
109
+
110
+ def select(sql, name = nil, binds = [])
111
+ query = sql.gsub(/[0-9a-z_-]+\.\*/i, '*')
112
+ execute query
113
+ end
114
+
115
+ # SCHEMA STATEMENTS ========================================
116
+
117
+ def structure_dump #:nodoc:
118
+ execute('DESCRIBE SCHEMA')
119
+ end
120
+
121
+ def recreate_database(name, options = {}) #:nodoc:
122
+ drop_database(name)
123
+ create_database(name, options)
124
+ end
125
+
126
+ def create_database(name, options = {}) #:nodoc:
127
+ query = "CREATE KEYSPACE #{name} WITH strategy_class = #{options[:strategy_class] || 'SimpleStrategy'}"
128
+
129
+ if options[:strategy_options]
130
+ if options[:strategy_options].is_a?(Array)
131
+ options[:strategy_options].each do |strategy_option|
132
+ query += " AND strategy_options:#{strategy_option}"
133
+ end
134
+ else
135
+ query += " AND strategy_options:#{options[:strategy_options]}"
136
+ end
137
+ end
138
+
139
+ execute query
140
+ end
141
+
142
+ def drop_database(name) #:nodoc:
143
+ execute "DROP KEYSPACE #{name}"
144
+ end
145
+
146
+ def create_table(name, options = {}) #:nodoc:
147
+ td = table_definition
148
+ td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
149
+
150
+ yield td if block_given?
151
+
152
+ create_sql = "CREATE TABLE #{name} ("
153
+ create_sql << td.to_sql
154
+ create_sql << ") #{options[:options]}"
155
+ execute create_sql
156
+ end
157
+
158
+ def drop_table(name) #:nodoc:
159
+ execute "DROP TABLE #{name}"
160
+ end
161
+
162
+ #def rename_table(name, new_name)
163
+ # execute "RENAME TABLE #{quote_table_name(name)} TO #{quote_table_name(new_name)}"
164
+ #end
165
+
166
+ #def remove_index!(table_name, index_name) #:nodoc:
167
+ # # missing table_name quoting in AR-2.3
168
+ # execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
169
+ #end
170
+
171
+ #def add_column(table_name, column_name, type, options = {})
172
+ # add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
173
+ # add_column_options!(add_column_sql, options)
174
+ # add_column_position!(add_column_sql, options)
175
+ # execute(add_column_sql)
176
+ #end
177
+
178
+ #def change_column_default(table_name, column_name, default) #:nodoc:
179
+ # column = column_for(table_name, column_name)
180
+ # change_column table_name, column_name, column.sql_type, :default => default
181
+ #end
182
+
183
+ #def change_column_null(table_name, column_name, null, default = nil)
184
+ # column = column_for(table_name, column_name)
185
+ #
186
+ # unless null || default.nil?
187
+ # execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
188
+ # end
189
+ #
190
+ # change_column table_name, column_name, column.sql_type, :null => null
191
+ #end
192
+
193
+ #def change_column(table_name, column_name, type, options = {}) #:nodoc:
194
+ # column = column_for(table_name, column_name)
195
+ #
196
+ # unless options_include_default?(options)
197
+ # options[:default] = column.default
198
+ # end
199
+ #
200
+ # unless options.has_key?(:null)
201
+ # options[:null] = column.null
202
+ # end
203
+ #
204
+ # change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
205
+ # add_column_options!(change_column_sql, options)
206
+ # add_column_position!(change_column_sql, options)
207
+ # execute(change_column_sql)
208
+ #end
209
+
210
+ #def rename_column(table_name, column_name, new_column_name) #:nodoc:
211
+ # options = {}
212
+ # if column = columns(table_name).find { |c| c.name == column_name.to_s }
213
+ # options[:default] = column.default
214
+ # options[:null] = column.null
215
+ # else
216
+ # raise ActiveRecord::ActiveRecordError, "No such column: #{table_name}.#{column_name}"
217
+ # end
218
+ # current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
219
+ # rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
220
+ # add_column_options!(rename_column_sql, options)
221
+ # execute(rename_column_sql)
222
+ #end
223
+
224
+ #def add_limit_offset!(sql, options) #:nodoc:
225
+ # limit, offset = options[:limit], options[:offset]
226
+ # if limit && offset
227
+ # sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
228
+ # elsif limit
229
+ # sql << " LIMIT #{sanitize_limit(limit)}"
230
+ # elsif offset
231
+ # sql << " OFFSET #{offset.to_i}"
232
+ # end
233
+ # sql
234
+ #end
235
+
236
+ #def type_to_sql(type, limit = nil, precision = nil, scale = nil)
237
+ # case type.to_s
238
+ # when 'binary'
239
+ # case limit
240
+ # when 0..0xfff; "varbinary(#{limit})"
241
+ # when nil; "blob"
242
+ # when 0x1000..0xffffffff; "blob(#{limit})"
243
+ # else raise(ActiveRecordError, "No binary type has character length #{limit}")
244
+ # end
245
+ # when 'integer'
246
+ # case limit
247
+ # when 1; 'tinyint'
248
+ # when 2; 'smallint'
249
+ # when 3; 'mediumint'
250
+ # when nil, 4, 11; 'int(11)' # compatibility with MySQL default
251
+ # when 5..8; 'bigint'
252
+ # else raise(ActiveRecordError, "No integer type has byte size #{limit}")
253
+ # end
254
+ # when 'text'
255
+ # case limit
256
+ # when 0..0xff; 'tinytext'
257
+ # when nil, 0x100..0xffff; 'text'
258
+ # when 0x10000..0xffffff; 'mediumtext'
259
+ # when 0x1000000..0xffffffff; 'longtext'
260
+ # else raise(ActiveRecordError, "No text type has character length #{limit}")
261
+ # end
262
+ # else
263
+ # super
264
+ # end
265
+ #end
266
+
267
+ #def add_column_position!(sql, options)
268
+ # if options[:first]
269
+ # sql << " FIRST"
270
+ # elsif options[:after]
271
+ # sql << " AFTER #{quote_column_name(options[:after])}"
272
+ # end
273
+ #end
274
+ end
275
+ end
@@ -0,0 +1,42 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ # Make sure we don't interfere with a pure Ruby version
4
+ remove_const(:CassandraAdapter) if const_defined?(:CassandraAdapter)
5
+
6
+ class CassandraAdapter < JdbcAdapter
7
+ include ::ArJdbc::Cassandra
8
+
9
+ def jdbc_connection_class(spec)
10
+ ::ArJdbc::Cassandra.jdbc_connection_class
11
+ end
12
+
13
+ def jdbc_column_class
14
+ CassandraColumn
15
+ end
16
+ #alias_chained_method :columns, :query_cache, :jdbc_columns
17
+
18
+ # some QUOTING caching :
19
+
20
+ @@quoted_table_names = {}
21
+
22
+ def quote_table_name(name)
23
+ unless quoted = @@quoted_table_names[name]
24
+ quoted = super
25
+ @@quoted_table_names[name] = quoted.freeze
26
+ end
27
+ quoted
28
+ end
29
+
30
+ @@quoted_column_names = {}
31
+
32
+ def quote_column_name(name)
33
+ unless quoted = @@quoted_column_names[name]
34
+ quoted = super
35
+ @@quoted_column_names[name] = quoted.freeze
36
+ end
37
+ quoted
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+ def cassandra_connection(config)
4
+ begin
5
+ require 'jdbc/cassandra'
6
+ ::Jdbc::Cassandra.load_driver(:require) if defined?(::Jdbc::Cassandra.load_driver)
7
+ rescue LoadError # assuming driver.jar is on the class-path
8
+ end
9
+
10
+ config[:host] ||= '127.0.0.1'
11
+ config[:port] ||= 9160
12
+ config[:url] ||= "jdbc:cassandra://#{config[:host]}:#{config[:port]}/#{config[:database]}"
13
+ config[:driver] ||= defined?(::Jdbc::Cassandra.driver_name) ? ::Jdbc::Cassandra.driver_name : 'org.apache.cassandra.cql.jdbc.CassandraDriver'
14
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::CassandraAdapter
15
+ config[:adapter_spec] = ::ArJdbc::Cassandra
16
+
17
+ options = (config[:options] ||= {})
18
+ #options['zeroDateTimeBehavior'] ||= 'convertToNull'
19
+ #options['jdbcCompliantTruncation'] ||= 'false'
20
+ #options['useUnicode'] ||= 'true'
21
+ #options['characterEncoding'] = config[:encoding] || 'utf8'
22
+
23
+ jdbc_connection(config)
24
+ end
25
+ alias_method :jdbccassandra_connection, :cassandra_connection
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module ArJdbc
2
+ module Cassandra
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-jdbccassandra-adapter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - James Thompson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord-jdbc-adapter
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 1.2.0
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.0
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ name: jdbc-cassandra
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: 1.2.5
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.5
43
+ none: false
44
+ prerelease: false
45
+ type: :runtime
46
+ description: Install this gem to use Cassandra with JRuby on Rails.
47
+ email:
48
+ - james@plainprograms.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - Rakefile
54
+ - README.md
55
+ - LICENSE.txt
56
+ - lib/activerecord-jdbccassandra-adapter.rb
57
+ - lib/active_record/connection_adapters/jdbccassandra_adapter.rb
58
+ - lib/arjdbc/cassandra.rb
59
+ - lib/arjdbc/cassandra/version.rb
60
+ - lib/arjdbc/cassandra/adapter.rb
61
+ - lib/arjdbc/cassandra/connection_methods.rb
62
+ homepage: https://github.com/plainprogrammer/activerecord-jdbccassandra-adapter
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ none: false
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ none: false
80
+ requirements: []
81
+ rubyforge_project: ''
82
+ rubygems_version: 1.8.24
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Cassandra JDBC adapter for JRuby on Rails.
86
+ test_files: []