mainej-adapter_extensions 0.4.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,23 @@
1
+ 0.1.0 - March 5, 2007
2
+ * Initial release
3
+
4
+ 0.1.1 - March 5, 2007
5
+ * Bug fixes
6
+
7
+ 0.1.2 - March 5, 2007
8
+ * Bug fixes
9
+
10
+ 0.2.0 - March 6, 2007
11
+ * SQL Server adapter included (Seth Ladd)
12
+
13
+ 0.3.0 - March 8, 2007
14
+ * PostgreSQL adapter included
15
+ * Added tests for bulk loading
16
+ * bulk_load method now handles table missing and file missing as error cases
17
+
18
+ 0.3.1 - May 4, 2007
19
+ * Added support for modifying SELECT statements to add an INSERT INTO.
20
+
21
+ 0.4 - September 17, 2007
22
+ * Added copy_table method that can copy the structure and data from one table to another. Currently implemented in MySQL (tested), PostgreSQL (tested) and SQL Server adapters (untested).
23
+ * Added support for SELECT..INTO for PostgreSQL.
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright (c) 2007 Anthony Eden
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
5
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
7
+ following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial
10
+ portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
13
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
14
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,5 @@
1
+ This library provides extensions to Rails' ActiveRecord adapters.
2
+
3
+ To use the MySQL adapter extensions with Rails 2.x, you must patch the mysql_adapter with the mysql_adapter_opt_local_infile.patch.
4
+
5
+ To execute the unit tests you must first construct a adapter_extensions_unittest database.
@@ -0,0 +1,150 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/packagetask'
5
+ require 'rake/gempackagetask'
6
+ require 'rake/contrib/rubyforgepublisher'
7
+ require 'date'
8
+
9
+ require File.join(File.dirname(__FILE__), 'lib/adapter_extensions', 'version')
10
+
11
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
12
+ PKG_NAME = 'adapter_extensions'
13
+ PKG_VERSION = AdapterExtensions::VERSION::STRING + PKG_BUILD
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+ PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
16
+
17
+ RELEASE_NAME = "REL #{PKG_VERSION}"
18
+
19
+ RUBY_FORGE_PROJECT = "activewarehouse"
20
+ RUBY_FORGE_USER = "aeden"
21
+
22
+ desc 'Default: run unit tests.'
23
+ task :default => :test
24
+
25
+ desc 'Test the ETL application.'
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = true
30
+ # TODO: reset the database
31
+ end
32
+
33
+ namespace :rcov do
34
+ desc 'Measures test coverage'
35
+ task :test do
36
+ rm_f 'coverage.data'
37
+ mkdir 'coverage' unless File.exist?('coverage')
38
+ rcov = "rcov --aggregate coverage.data --text-summary -Ilib"
39
+ system("#{rcov} test/*_test.rb test/**/*_test.rb")
40
+ system("open coverage/index.html") if PLATFORM['darwin']
41
+ end
42
+ end
43
+
44
+ desc 'Generate documentation for the AdapterExtensions library.'
45
+ Rake::RDocTask.new(:rdoc) do |rdoc|
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = 'Extensions for Rails adapters'
48
+ rdoc.options << '--line-numbers' << '--inline-source'
49
+ rdoc.rdoc_files.include('README')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
52
+
53
+ PKG_FILES = FileList[
54
+ 'CHANGELOG',
55
+ 'README',
56
+ 'LICENSE',
57
+ 'Rakefile',
58
+ 'doc/**/*',
59
+ 'lib/**/*',
60
+ ] - [ 'test' ]
61
+
62
+ spec = Gem::Specification.new do |s|
63
+ s.name = 'adapter_extensions'
64
+ s.version = PKG_VERSION
65
+ s.summary = "Extensions to Rails ActiveRecord adapters."
66
+ s.description = <<-EOF
67
+ Provides various extensions to the Rails ActiveRecord adapters.
68
+ EOF
69
+
70
+ s.add_dependency('rake', '>= 0.7.1')
71
+ s.add_dependency('activesupport', '>= 1.3.1')
72
+ s.add_dependency('activerecord', '>= 1.14.4')
73
+ s.add_dependency('fastercsv', '>= 1.0.0')
74
+
75
+ s.rdoc_options << '--exclude' << '.'
76
+ s.has_rdoc = false
77
+
78
+ s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')}
79
+ s.require_path = 'lib'
80
+
81
+ s.author = "Anthony Eden"
82
+ s.email = "anthonyeden@gmail.com"
83
+ s.homepage = "http://activewarehouse.rubyforge.org/adapter_extensions"
84
+ s.rubyforge_project = "activewarehouse"
85
+ end
86
+
87
+ Rake::GemPackageTask.new(spec) do |pkg|
88
+ pkg.gem_spec = spec
89
+ pkg.need_tar = true
90
+ pkg.need_zip = true
91
+ end
92
+
93
+ namespace :github do
94
+ desc "Update Github Gemspec"
95
+ task :update_gemspec do
96
+ File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w"){|f| f << spec.to_ruby}
97
+ end
98
+ end
99
+
100
+
101
+
102
+ desc "Generate code statistics"
103
+ task :lines do
104
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
105
+
106
+ for file_name in FileList["lib/**/*.rb"]
107
+ next if file_name =~ /vendor/
108
+ f = File.open(file_name)
109
+
110
+ while line = f.gets
111
+ lines += 1
112
+ next if line =~ /^\s*$/
113
+ next if line =~ /^\s*#/
114
+ codelines += 1
115
+ end
116
+ puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
117
+
118
+ total_lines += lines
119
+ total_codelines += codelines
120
+
121
+ lines, codelines = 0, 0
122
+ end
123
+
124
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
125
+ end
126
+
127
+ desc "Publish the release files to RubyForge."
128
+ task :release => [ :package ] do
129
+ `rubyforge login`
130
+
131
+ for ext in %w( gem tgz zip )
132
+ release_command = "rubyforge add_release activewarehouse #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
133
+ puts release_command
134
+ system(release_command)
135
+ end
136
+ end
137
+
138
+ desc "Publish the API documentation"
139
+ task :pdoc => [:rdoc] do
140
+ Rake::SshDirPublisher.new("aeden@rubyforge.org", "/var/www/gforge-projects/activewarehouse/adapter_extensions/rdoc", "rdoc").upload
141
+ end
142
+
143
+ desc "Reinstall the gem from a local package copy"
144
+ task :reinstall => [:package] do
145
+ windows = RUBY_PLATFORM =~ /mswin/
146
+ sudo = windows ? '' : 'sudo'
147
+ gem = windows ? 'gem.bat' : 'gem'
148
+ `#{sudo} #{gem} uninstall -x -i #{PKG_NAME}`
149
+ `#{sudo} #{gem} install pkg/#{PKG_NAME}-#{PKG_VERSION}`
150
+ end
@@ -0,0 +1,23 @@
1
+ # Extensions to the Rails ActiveRecord adapters.
2
+ #
3
+ # Requiring this file will require all of the necessary files to function.
4
+
5
+ puts "Using AdapterExtensions"
6
+
7
+ require 'rubygems'
8
+ unless Kernel.respond_to?(:gem)
9
+ Kernel.send :alias_method, :gem, :require_gem
10
+ end
11
+
12
+ unless defined?(ActiveSupport)
13
+ gem 'activesupport'
14
+ require 'active_support'
15
+ end
16
+
17
+ unless defined?(ActiveRecord)
18
+ gem 'activerecord'
19
+ require 'active_record'
20
+ end
21
+
22
+ $:.unshift(File.dirname(__FILE__))
23
+ Dir[File.dirname(__FILE__) + "/adapter_extensions/**/*.rb"].each { |file| require(file) }
@@ -0,0 +1,44 @@
1
+ # This source file contains extensions to the abstract adapter.
2
+ module ActiveRecord #:nodoc:
3
+ module ConnectionAdapters #:nodoc:
4
+ # Extensions to the AbstractAdapter. In some cases a default implementation
5
+ # is provided, in others it is adapter-dependent and the method will
6
+ # raise a NotImplementedError if the adapter does not implement that method
7
+ class AbstractAdapter
8
+ # Truncate the specified table
9
+ def truncate(table_name)
10
+ execute("TRUNCATE TABLE #{table_name}")
11
+ end
12
+
13
+ # Bulk loading interface. Load the data from the specified file into the
14
+ # given table. Note that options will be adapter-dependent.
15
+ def bulk_load(file, table_name, options={})
16
+ raise ArgumentError, "#{file} does not exist" unless File.exist?(file)
17
+ raise ArgumentError, "#{table_name} does not exist" unless tables.include?(table_name)
18
+ do_bulk_load(file, table_name, options)
19
+ end
20
+
21
+ # SQL select into statement constructs a new table from the results
22
+ # of a select. It is used to select data from a table and create a new
23
+ # table with its result set at the same time. Note that this method
24
+ # name does not necessarily match the implementation. E.g. MySQL's
25
+ # version of this is 'CREATE TABLE ... AS SELECT ...'
26
+ def support_select_into_table?
27
+ false
28
+ end
29
+
30
+ # Add a chunk of SQL to the given query that will create a new table and
31
+ # execute the select into that table.
32
+ def add_select_into_table(new_table_name, sql_query)
33
+ raise NotImplementedError, "add_select_into_table is an abstract method"
34
+ end
35
+
36
+ protected
37
+
38
+ # for subclasses to implement
39
+ def do_bulk_load(file, table_name, options={})
40
+ raise NotImplementedError, "do_bulk_load is an abstract method"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ # Source code for the MysqlAdapter extensions.
2
+ module ActiveRecord #:nodoc:
3
+ module ConnectionAdapters #:nodoc:
4
+ # Adds new functionality to ActiveRecord MysqlAdapter.
5
+ class MysqlAdapter < AbstractAdapter
6
+
7
+ def support_select_into_table?
8
+ true
9
+ end
10
+
11
+ # Inserts an INTO table_name clause to the sql_query.
12
+ def add_select_into_table(new_table_name, sql_query)
13
+ "CREATE TABLE #{new_table_name} " + sql_query
14
+ end
15
+
16
+ # Copy the specified table.
17
+ def copy_table(old_table_name, new_table_name)
18
+ transaction do
19
+ execute "CREATE TABLE #{new_table_name} LIKE #{old_table_name}"
20
+ execute "INSERT INTO #{new_table_name} SELECT * FROM #{old_table_name}"
21
+ end
22
+ end
23
+
24
+ protected
25
+ # Call +bulk_load+, as that method wraps this method.
26
+ #
27
+ # Bulk load the data in the specified file. This implementation always uses the LOCAL keyword
28
+ # so the file must be found locally, not on the remote server, to be loaded.
29
+ #
30
+ # Options:
31
+ # * <tt>:ignore</tt> -- Ignore the specified number of lines from the source file
32
+ # * <tt>:columns</tt> -- Array of column names defining the source file column order
33
+ # * <tt>:fields</tt> -- Hash of options for fields:
34
+ # * <tt>:delimited_by</tt> -- The field delimiter
35
+ # * <tt>:enclosed_by</tt> -- The field enclosure
36
+ def do_bulk_load(file, table_name, options={})
37
+ return if File.size(file) == 0
38
+ q = "LOAD DATA LOCAL INFILE '#{file}' INTO TABLE #{table_name}"
39
+ if options[:fields]
40
+ q << " FIELDS"
41
+ q << " TERMINATED BY '#{options[:fields][:delimited_by]}'" if options[:fields][:delimited_by]
42
+ q << " ENCLOSED BY '#{options[:fields][:enclosed_by]}'" if options[:fields][:enclosed_by]
43
+ end
44
+ q << " IGNORE #{options[:ignore]} LINES" if options[:ignore]
45
+ q << " (#{options[:columns].join(',')})" if options[:columns]
46
+ execute(q)
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,52 @@
1
+ # Source code for the PostgreSQLAdapter extensions.
2
+ module ActiveRecord #:nodoc:
3
+ module ConnectionAdapters #:nodoc:
4
+ # Adds new functionality to ActiveRecord PostgreSQLAdapter.
5
+ class PostgreSQLAdapter < AbstractAdapter
6
+ def support_select_into_table?
7
+ true
8
+ end
9
+
10
+ # Inserts an INTO table_name clause to the sql_query.
11
+ def add_select_into_table(new_table_name, sql_query)
12
+ sql_query.sub(/FROM/i, "INTO #{new_table_name} FROM")
13
+ end
14
+
15
+ # Copy the specified table.
16
+ def copy_table(old_table_name, new_table_name)
17
+ execute add_select_into_table(new_table_name, "SELECT * FROM #{old_table_name}")
18
+ end
19
+
20
+ protected
21
+ # Call +bulk_load+, as that method wraps this method.
22
+ #
23
+ # Bulk load the data in the specified file.
24
+ #
25
+ # Options:
26
+ # * <tt>:ignore</tt> -- Ignore the specified number of lines from the source file. In the case of PostgreSQL
27
+ # only the first line will be ignored from the source file regardless of the number of lines specified.
28
+ # * <tt>:columns</tt> -- Array of column names defining the source file column order
29
+ # * <tt>:fields</tt> -- Hash of options for fields:
30
+ # * <tt>:delimited_by</tt> -- The field delimiter
31
+ # * <tt>:null_string</tt> -- The string that should be interpreted as NULL (in addition to \N)
32
+ # * <tt>:enclosed_by</tt> -- The field enclosure
33
+ def do_bulk_load(file, table_name, options={})
34
+ q = "COPY #{table_name} "
35
+ q << "(#{options[:columns].join(',')}) " if options[:columns]
36
+ q << "FROM '#{File.expand_path(file)}' "
37
+ if options[:fields]
38
+ q << "WITH "
39
+ q << "DELIMITER '#{options[:fields][:delimited_by]}' " if options[:fields][:delimited_by]
40
+ q << "NULL '#{options[:fields][:null_string]}'" if options[:fields][:null_string]
41
+ if options[:fields][:enclosed_by] || options[:ignore] && options[:ignore] > 0
42
+ q << "CSV "
43
+ q << "HEADER " if options[:ignore] && options[:ignore] > 0
44
+ q << "QUOTE '#{options[:fields][:enclosed_by]}' " if options[:fields][:enclosed_by]
45
+ end
46
+ end
47
+
48
+ execute(q)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ # Source code for the SQLServerAdapter extensions.
2
+ module ActiveRecord #:nodoc:
3
+ module ConnectionAdapters #:nodoc:
4
+ # Adds new functionality to ActiveRecord SQLServerAdapter.
5
+ class SQLServerAdapter < AbstractAdapter
6
+ def support_select_into_table?
7
+ true
8
+ end
9
+
10
+ # Inserts an INTO table_name clause to the sql_query.
11
+ def add_select_into_table(new_table_name, sql_query)
12
+ sql_query.sub(/FROM/i, "INTO #{new_table_name} FROM")
13
+ end
14
+
15
+ # Copy the specified table.
16
+ def copy_table(old_table_name, new_table_name)
17
+ execute add_select_into_table(new_table_name, "SELECT * FROM #{old_table_name}")
18
+ end
19
+
20
+ protected
21
+ # Call +bulk_load+, as that method wraps this method.
22
+ #
23
+ # Bulk load the data in the specified file. This implementation relies
24
+ # on bcp being in your PATH.
25
+ #
26
+ # Options:
27
+ # * <tt>:ignore</tt> -- Ignore the specified number of lines from the source file
28
+ # * <tt>:columns</tt> -- Array of column names defining the source file column order
29
+ # * <tt>:fields</tt> -- Hash of options for fields:
30
+ # * <tt>:delimited_by</tt> -- The field delimiter
31
+ # * <tt>:enclosed_by</tt> -- The field enclosure
32
+ def do_bulk_load(file, table_name, options={})
33
+ env_name = options[:env] || RAILS_ENV
34
+ config = ActiveRecord::Base.configurations[env_name]
35
+ puts "Loading table \"#{table_name}\" from file \"#{filename}\""
36
+ cmd = "bcp \"#{config['database']}.dbo.#{table_name}\" in " +
37
+ "\"#{filename}\" -S \"#{config['host']}\" -c " +
38
+ "-t \"#{options[:delimited_by]}\" -b10000 -a8192 -q -E -U \"#{config['username']}\" " +
39
+ "-P \"#{config['password']}\" -e \"#{filename}.in.errors\""
40
+ `#{cmd}`
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ # Source file identifying the version of AdapterExtensions in this package
2
+ module AdapterExtensions#:nodoc:
3
+ module VERSION #:nodoc:
4
+ MAJOR = 0
5
+ MINOR = 4
6
+ TINY = 0
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mainej-adapter_extensions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anthony Eden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-22 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.7.1
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: activesupport
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.3.1
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: activerecord
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.14.4
41
+ version:
42
+ - !ruby/object:Gem::Dependency
43
+ name: fastercsv
44
+ version_requirement:
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.0.0
50
+ version:
51
+ description: Provides various extensions to the Rails ActiveRecord adapters.
52
+ email: anthonyeden@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - CHANGELOG
61
+ - README
62
+ - LICENSE
63
+ - Rakefile
64
+ - lib/adapter_extensions
65
+ - lib/adapter_extensions.rb
66
+ - lib/adapter_extensions/connection_adapters
67
+ - lib/adapter_extensions/version.rb
68
+ - lib/adapter_extensions/connection_adapters/abstract_adapter.rb
69
+ - lib/adapter_extensions/connection_adapters/mysql_adapter.rb
70
+ - lib/adapter_extensions/connection_adapters/postgresql_adapter.rb
71
+ - lib/adapter_extensions/connection_adapters/sqlserver_adapter.rb
72
+ has_rdoc: false
73
+ homepage: http://activewarehouse.rubyforge.org/adapter_extensions
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --exclude
77
+ - .
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ version:
92
+ requirements: []
93
+
94
+ rubyforge_project: activewarehouse
95
+ rubygems_version: 1.0.1
96
+ signing_key:
97
+ specification_version: 2
98
+ summary: Extensions to Rails ActiveRecord adapters.
99
+ test_files: []
100
+