dumbo 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +1 -1
  4. data/bin/dumbo +65 -24
  5. data/config/boot.rb +2 -3
  6. data/dumbo.gemspec +1 -2
  7. data/lib/dumbo.rb +17 -16
  8. data/lib/dumbo/aggregate.rb +3 -5
  9. data/lib/dumbo/base_type.rb +17 -17
  10. data/lib/dumbo/binding_loader.rb +50 -0
  11. data/lib/dumbo/cast.rb +5 -5
  12. data/lib/dumbo/composite_type.rb +4 -4
  13. data/lib/dumbo/db_task.rb +6 -5
  14. data/lib/dumbo/dependency_resolver.rb +17 -18
  15. data/lib/dumbo/enum_type.rb +3 -4
  16. data/lib/dumbo/extension.rb +64 -20
  17. data/lib/dumbo/extension_migrator.rb +11 -11
  18. data/lib/dumbo/extension_version.rb +29 -11
  19. data/lib/dumbo/function.rb +21 -21
  20. data/lib/dumbo/operator.rb +4 -6
  21. data/lib/dumbo/pg_object.rb +17 -21
  22. data/lib/dumbo/rake_task.rb +63 -53
  23. data/lib/dumbo/range_type.rb +6 -9
  24. data/lib/dumbo/test.rb +8 -0
  25. data/lib/dumbo/test/fixture.rb +51 -0
  26. data/lib/dumbo/test/helper.rb +64 -0
  27. data/lib/dumbo/test/matchers.rb +76 -0
  28. data/lib/dumbo/test/regression_helper.rb +20 -0
  29. data/lib/dumbo/test/silence_unknown_oid.rb +12 -0
  30. data/lib/dumbo/type.rb +3 -4
  31. data/lib/dumbo/version.rb +1 -1
  32. data/spec/aggregate_spec.rb +9 -10
  33. data/spec/cast_spec.rb +5 -5
  34. data/spec/{Makefile → dumbo_sample/Makefile} +4 -0
  35. data/spec/{dumbo_sample--0.0.1.sql → dumbo_sample/dumbo_sample--0.0.1.sql} +0 -0
  36. data/spec/{dumbo_sample--0.0.2.sql → dumbo_sample/dumbo_sample--0.0.2.sql} +0 -0
  37. data/spec/dumbo_sample/dumbo_sample--0.0.3.sql +7 -0
  38. data/spec/dumbo_sample/dumbo_sample--0.0.4.sql +13 -0
  39. data/spec/{dumbo_sample.control → dumbo_sample/dumbo_sample.control} +0 -0
  40. data/spec/dumbo_sample/src/dumbo_sample.c +13 -0
  41. data/spec/dumbo_sample/src/dumbo_sample.h +17 -0
  42. data/spec/extension_migrator_spec.rb +12 -11
  43. data/spec/extension_spec.rb +41 -12
  44. data/spec/extension_version_spec.rb +27 -0
  45. data/spec/operator_spec.rb +6 -7
  46. data/spec/spec_helper.rb +15 -9
  47. data/spec/support/extension_helper.rb +31 -0
  48. data/spec/support/silence_unknown_oid.rb +12 -0
  49. data/spec/type_spec.rb +59 -55
  50. data/template/Rakefile +6 -6
  51. data/template/spec/sample_spec.rb.erb +1 -1
  52. metadata +33 -31
  53. data/config/database.yml +0 -31
  54. data/lib/tasks/db.rake +0 -52
  55. data/lib/tasks/dumbo.rake +0 -23
  56. data/spec/support/sql_helper.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c38d6d2545804ea840a234c51c3d912fc2988a3
4
- data.tar.gz: a1ace87c6b8469126e95a1eb94f9a503bcd93483
3
+ metadata.gz: 82e2e9299fa177d4e41fdc7b8c3417476190fff8
4
+ data.tar.gz: 5cf24b1b10829fcacf94016bd2fd29e21ab005d1
5
5
  SHA512:
6
- metadata.gz: 6043bb12bfee32add950dd79093d41c3ea70732028749ccf8db79413d2e2219e8b3d5b197695255c4cba3d24ce4e38b3e3a2bdfc83522095ba9b85466fbf4623
7
- data.tar.gz: ac5757b0c2dee69ecd5c0d962d3e0f4557b1937b5c08f63c0d3d3210134ef11975803a675e01f2770df35e250865e1331404577a42b246d8043406492394c778
6
+ metadata.gz: d08e465e241b15fb5796af82ecbe8480e37e22be2728bf96255e7cd00fee75e9d17073889dcead4af350eb9a22755e628267e59b23ebdfdd2977e552e6d6a2ee
7
+ data.tar.gz: 23e9fa7f1b2433e0d4c0641fe432c08674bbb3171bf66083c5dc032d7655acec3b0c93a3bf4523cdab21961499526bdf66f009a431c87df0dbc573e6f6b6b319
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ config/database.yml
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in dumbo.gemspec
4
- gemspec
4
+ gemspec
data/bin/dumbo CHANGED
@@ -3,25 +3,24 @@ require 'thor'
3
3
  require 'thor/group'
4
4
  require 'erubis'
5
5
  require 'fileutils'
6
+ require 'pathname'
6
7
 
7
8
  module Cli
8
9
  class Dumbo < Thor
10
+ desc 'new name', 'creates a new extension skeleton'
9
11
 
10
- desc "new name", "creates a new extension skeleton"
11
-
12
- def new(name, initial_version='0.0.1')
13
- FileUtils.mkdir_p("#{name}/sql")
14
- FileUtils.mkdir_p("#{name}/src")
15
- FileUtils.mkdir_p("#{name}/spec/support")
16
- FileUtils.mkdir_p("#{name}/config")
17
- FileUtils.mkdir_p("#{name}/lib/tasks")
12
+ def new(name, initial_version = '0.0.1')
13
+ mkdir("#{name}/sql")
14
+ mkdir("#{name}/src")
15
+ mkdir("#{name}/spec")
16
+ mkdir("#{name}/config")
17
+ mkdir("#{name}/lib/tasks")
18
18
 
19
19
  spec_helper = Dir.glob(File.expand_path('../../spec/spec_helper.rb', __FILE__))
20
20
  spec_helper += Dir.glob(File.expand_path('../../spec/support', __FILE__))
21
21
 
22
- FileUtils.cp_r spec_helper, "#{name}/spec/"
23
-
24
- FileUtils.cp File.expand_path('../../config/boot.rb', __FILE__), "#{name}/config/"
22
+ cp spec_helper, "#{name}/spec"
23
+ cp File.expand_path('../../config/boot.rb', __FILE__), "#{name}/config"
25
24
 
26
25
  template_path = File.expand_path('../../template', __FILE__)
27
26
 
@@ -30,29 +29,71 @@ module Cli
30
29
  dest_name = pathname.relative_path_from Pathname.new(template_path)
31
30
 
32
31
  if pathname.directory?
33
- FileUtils.mkdir_p("#{name}/#{dest_name}")
32
+ mkdir("#{name}/#{dest_name}", true)
34
33
  next
35
34
  end
36
35
 
37
- if dest_name.extname =='.erb'
36
+ if dest_name.extname == '.erb'
38
37
  eruby = Erubis::Eruby.new(File.read(template))
39
- File.open("#{name}/#{dest_name.sub_ext('')}",'w') do |f|
40
- f.puts eruby.result({ext_name: name})
41
- end
38
+ content = eruby.result(ext_name: name)
39
+ create "#{name}/#{dest_name.sub_ext('')}", content
40
+ else
41
+ cp template, "#{name}/#{dest_name}"
42
+ end
43
+ end
44
+
45
+ create "#{name}/#{name}.control", <<-STR
46
+ # #{name} extension
47
+ comment = 'my awesome extension'
48
+ default_version = '#{initial_version}'
49
+ relocatable = true
50
+ requires = ''
51
+ STR
52
+ end
53
+
54
+ no_commands do
55
+ def mkdir(path, silent_skip = false)
56
+ if File.directory?(path)
57
+ say_status('skip', "#{path}", :yellow) unless silent_skip
58
+ else
59
+ FileUtils.mkdir_p(path)
60
+ say_status('create', "#{path}")
61
+ end
62
+ end
63
+
64
+ def create(path, content, silent_skip = false)
65
+ if File.exist? path
66
+ say_status('skip', path, :yellow) unless silent_skip
42
67
  else
43
- FileUtils.cp template, "#{name}/#{dest_name}"
68
+ File.open(path, 'w') do |f|
69
+ f.puts content
70
+ end
71
+ say_status('create', path)
44
72
  end
45
73
  end
46
74
 
47
- File.open("#{name}/#{name}.control",'w') do |f|
48
- f.puts "# #{name} extension"
49
- f.puts "comment = 'my awesome extension'"
50
- f.puts "default_version = '#{initial_version}'"
51
- f.puts "relocatable = true"
52
- f.puts "requires = ''"
75
+ def cp(src, dest, silent_skip = false)
76
+ Array(src).each do |p|
77
+ path = Pathname.new(p)
78
+ if File.directory?(dest)
79
+ if File.exist?("#{dest}/#{path.basename}")
80
+ say_status('skip', "#{dest}/#{path.basename}", :yellow) unless silent_skip
81
+ else
82
+ FileUtils.cp_r p, dest
83
+ say_status('create', "#{dest}/#{path.basename}")
84
+ end
85
+ else
86
+ if File.exist?(dest)
87
+ say_status('skip', dest, :yellow) unless silent_skip
88
+ else
89
+ FileUtils.cp_r p, dest
90
+ say_status('create', dest)
91
+ end
92
+ end
93
+ end
53
94
  end
54
95
  end
55
96
  end
56
97
  end
57
98
 
58
- Cli::Dumbo.start(ARGV)
99
+ Cli::Dumbo.start(ARGV)
@@ -1,15 +1,14 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $LOAD_PATH.unshift File.expand_path('../..', __FILE__)
2
2
 
3
3
  # Set up gems listed in the Gemfile.
4
4
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
5
  ENV['DUMBO_ENV'] ||= 'development'
6
6
 
7
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
8
8
  Bundler.require(:default, ENV['DUMBO_ENV'].to_sym)
9
9
 
10
10
  def db_config
11
11
  @config ||= YAML.load_file('config/database.yml')
12
12
  end
13
13
 
14
-
15
14
  ActiveRecord::Base.establish_connection db_config[ENV['DUMBO_ENV']]
@@ -19,8 +19,7 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_dependency "rake"
21
21
  spec.add_dependency 'erubis'
22
- spec.add_dependency 'rspec', '~> 2.14.0'
23
- spec.add_dependency'factory_girl', '~> 4.0'
22
+ spec.add_dependency 'rspec', '~> 3.0.0'
24
23
  spec.add_dependency 'activerecord'
25
24
  spec.add_dependency 'pg', '> 0.17'
26
25
 
@@ -1,20 +1,21 @@
1
1
  require 'active_record'
2
- require "dumbo/version"
3
- require "dumbo/pg_object"
4
- require "dumbo/type"
5
- require "dumbo/function"
6
- require "dumbo/cast"
7
- require "dumbo/base_type"
8
- require "dumbo/aggregate"
9
- require "dumbo/composite_type"
10
- require "dumbo/dependency_resolver"
11
- require "dumbo/enum_type"
12
- require "dumbo/extension"
13
- require "dumbo/extension_migrator"
14
- require "dumbo/extension_version"
15
- require "dumbo/operator"
16
- require "dumbo/range_type"
17
- require "dumbo/version"
2
+ require 'dumbo/version'
3
+ require 'dumbo/pg_object'
4
+ require 'dumbo/type'
5
+ require 'dumbo/function'
6
+ require 'dumbo/cast'
7
+ require 'dumbo/base_type'
8
+ require 'dumbo/aggregate'
9
+ require 'dumbo/composite_type'
10
+ require 'dumbo/dependency_resolver'
11
+ require 'dumbo/enum_type'
12
+ require 'dumbo/extension'
13
+ require 'dumbo/extension_migrator'
14
+ require 'dumbo/extension_version'
15
+ require 'dumbo/operator'
16
+ require 'dumbo/range_type'
17
+ require 'dumbo/version'
18
+ require 'dumbo/binding_loader'
18
19
 
19
20
  module Dumbo
20
21
  # Your code goes here...
@@ -30,14 +30,13 @@ module Dumbo
30
30
  WHERE aggfnoid = #{oid}
31
31
  SQL
32
32
 
33
- result.first.each do |k,v|
34
- send("#{k}=",v) rescue nil
33
+ result.first.each do |k, v|
34
+ send("#{k}=", v) rescue nil
35
35
  end
36
36
 
37
37
  result.first
38
38
  end
39
39
 
40
-
41
40
  def to_sql
42
41
  attributes = []
43
42
  attributes << "SFUNC = #{sfunc}"
@@ -52,6 +51,5 @@ module Dumbo
52
51
  );
53
52
  SQL
54
53
  end
55
-
56
54
  end
57
- end
55
+ end
@@ -1,18 +1,18 @@
1
1
  module Dumbo
2
2
  class BaseType < Type
3
- attr_accessor :input_function,
4
- :output_function,
5
- :receive_function,
6
- :send_function,
7
- :analyze_function,
8
- :category,
9
- :default,
10
- :alignment,
11
- :storage,
12
- :type,
13
- :internallength,
14
- :attribute_name,
15
- :typrelid
3
+ attr_accessor :input_function,
4
+ :output_function,
5
+ :receive_function,
6
+ :send_function,
7
+ :analyze_function,
8
+ :category,
9
+ :default,
10
+ :alignment,
11
+ :storage,
12
+ :type,
13
+ :internallength,
14
+ :attribute_name,
15
+ :typrelid
16
16
 
17
17
  def load_attributes
18
18
  sql = <<-SQL
@@ -44,15 +44,15 @@ module Dumbo
44
44
  SQL
45
45
 
46
46
  result = execute sql
47
- result.first.each do |k,v|
48
- send("#{k}=",v) rescue nil
47
+ result.first.each do |k, v|
48
+ send("#{k}=", v) rescue nil
49
49
  end
50
50
 
51
51
  result.first
52
52
  end
53
53
 
54
54
  def to_sql
55
- <<-SQL.gsub(/^ {8}/, '')
55
+ <<-SQL.gsub(/^ {8}/, '')
56
56
  CREATE TYPE #{name}(
57
57
  INPUT=#{input_function},
58
58
  OUTPUT=#{output_function},
@@ -68,4 +68,4 @@ module Dumbo
68
68
  SQL
69
69
  end
70
70
  end
71
- end
71
+ end
@@ -0,0 +1,50 @@
1
+ require 'yaml'
2
+ module Dumbo
3
+ class BindingLoader
4
+
5
+ def self.load_pattern
6
+ /\s*--\s*load +([^\s'";]+)/
7
+ end
8
+
9
+ def initialize(file)
10
+ @file = file
11
+ end
12
+
13
+ def load
14
+ load_list.reduce({}) do |result, file|
15
+ yaml = Pathname.new(file).sub_ext('.yml')
16
+ bind = YAML.load_file(yaml)
17
+
18
+ result.merge(bind)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def load_list
25
+ files = []
26
+ IO.foreach(@file) do |line|
27
+ catch(:done) do
28
+ load_file = parse(line)
29
+ files << load_file if load_file
30
+ end
31
+ end
32
+ files
33
+ end
34
+
35
+ def parse(line)
36
+ return Regexp.last_match[1] if encoded_line(line) =~ BindingLoader.load_pattern
37
+
38
+ # end of first commenting block we're done.
39
+ throw :done unless line =~ /--/
40
+ end
41
+
42
+ def encoded_line(line)
43
+ if String.method_defined?(:encode)
44
+ line.encode!('UTF-8', 'UTF-8', invalid: :replace)
45
+ else
46
+ line
47
+ end
48
+ end
49
+ end
50
+ end
@@ -23,21 +23,21 @@ module Dumbo
23
23
  WHERE ca.oid = #{oid}
24
24
  SQL
25
25
 
26
- result.first.each do |k,v|
27
- send("#{k}=",v) rescue nil
26
+ result.first.each do |k, v|
27
+ send("#{k}=", v) rescue nil
28
28
  end
29
29
 
30
30
  result.first
31
31
  end
32
32
 
33
33
  def drop
34
- "DROP CAST (#{source_type} AS #{target_type})"
34
+ "DROP CAST (#{source_type} AS #{target_type});"
35
35
  end
36
36
 
37
37
  def to_sql
38
38
  attributes = []
39
39
  attributes << "WITH FUNCTION #{function_name}(#{source_type})" if function_name
40
- attributes << "WITHOUT FUNCTION" unless function_name
40
+ attributes << 'WITHOUT FUNCTION' unless function_name
41
41
  attributes << context if context
42
42
 
43
43
  <<-SQL.gsub(/^ {6}/, '')
@@ -46,4 +46,4 @@ module Dumbo
46
46
  SQL
47
47
  end
48
48
  end
49
- end
49
+ end
@@ -1,6 +1,6 @@
1
1
  module Dumbo
2
2
  class CompositeType < Type
3
- attr_accessor :attributes
3
+ attr_accessor :attributes
4
4
 
5
5
  def load_attributes
6
6
  super
@@ -16,11 +16,11 @@ module Dumbo
16
16
  SQL
17
17
 
18
18
  attribute = Struct.new(:name, :type)
19
- @attributes = res.map{|r| attribute.new(r['attname'],r['typname'])}
19
+ @attributes = res.map { |r| attribute.new(r['attname'], r['typname']) }
20
20
  end
21
21
 
22
22
  def to_sql
23
- attr_str = attributes.map{|a| "#{a.name} #{a.type}"}.join(",\n ")
23
+ attr_str = attributes.map { |a| "#{a.name} #{a.type}" }.join(",\n ")
24
24
  <<-SQL.gsub(/^ {6}/, '')
25
25
  CREATE TYPE #{name} AS (
26
26
  #{attr_str}
@@ -28,4 +28,4 @@ module Dumbo
28
28
  SQL
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -1,6 +1,7 @@
1
- require "rake"
1
+ require 'rake'
2
2
  require 'rake/tasklib'
3
3
  require 'active_record'
4
+ require 'yaml'
4
5
 
5
6
  module Dumbo
6
7
  class DbTask < ::Rake::TaskLib
@@ -9,7 +10,7 @@ module Dumbo
9
10
  @name = name
10
11
 
11
12
  namespace name do
12
- task environment: ['db:configure_connection' ]
13
+ task environment: ['db:configure_connection']
13
14
 
14
15
  task :configuration do
15
16
  @config = YAML.load_file('config/database.yml')[ENV['DUMBO_ENV']]
@@ -33,16 +34,16 @@ module Dumbo
33
34
 
34
35
  namespace :test do
35
36
  task :environment do
36
- ENV['DUMBO_ENV'] ||= 'test'
37
+ ENV['DUMBO_ENV'] = 'test'
37
38
  ActiveRecord::Schema.verbose = false
38
39
  end
39
40
 
40
41
  task load_structure: :environment do
41
- filename = ENV['DB_STRUCTURE'] || File.join("db", "structure.sql")
42
+ filename = ENV['DB_STRUCTURE'] || File.join('db', 'structure.sql')
42
43
  ActiveRecord::Tasks::DatabaseTasks.structure_load(@config, filename)
43
44
  end
44
45
 
45
- desc "Re-create and prepare test database"
46
+ desc 'Re-create and prepare test database'
46
47
  task prepare: [:environment, :drop, :create]
47
48
  end
48
49
  end
@@ -2,7 +2,6 @@ require 'pathname'
2
2
  require 'active_support/core_ext/module/attribute_accessors'
3
3
 
4
4
  module Dumbo
5
-
6
5
  class DependencyNotFound < StandardError
7
6
  attr_accessor :dep, :file
8
7
 
@@ -23,7 +22,7 @@ module Dumbo
23
22
  end
24
23
 
25
24
  def resolve
26
- list = dependency_list.sort{|a,b| a.last.size <=> b.last.size}
25
+ list = dependency_list.sort { |a, b| a.last.size <=> b.last.size }
27
26
  resolve_list(list)
28
27
  end
29
28
 
@@ -33,14 +32,13 @@ module Dumbo
33
32
  @resolve_list = []
34
33
  @temp_list = list
35
34
  loops = 0
36
- until @temp_list.empty? || loops > 10 do
37
- @temp_list.each do |(file, deps)|
38
- _resolve(file, deps)
39
- end
40
- loops +=1
35
+ # TODO find a better way here
36
+ until @temp_list.empty? || loops * 10 > @temp_list.size
37
+ file, deps = @temp_list.first
38
+ loops += 1 unless _resolve(file, deps)
41
39
  end
42
40
 
43
- raise "Can't resolve dependencies" if loops > 10
41
+ fail "Can't resolve dependencies" if loops > 10
44
42
 
45
43
  @resolve_list
46
44
  end
@@ -48,26 +46,26 @@ module Dumbo
48
46
  def _resolve(file, deps)
49
47
  if deps.empty?
50
48
  @resolve_list.push(@temp_list.shift.first)
51
- return
49
+ return true
52
50
  end
53
51
 
54
52
  left = deps - @resolve_list
55
53
  if left.empty?
56
54
  @resolve_list.push(@temp_list.shift.first)
57
- return
55
+ return true
58
56
  else
59
57
  @temp_list.push @temp_list.shift
58
+ return false
60
59
  end
61
60
  end
62
61
 
63
-
64
62
  def dependency_list
65
63
  @file_list.map do |file|
66
64
  deps = []
67
65
  IO.foreach(file) do |line|
68
66
  catch(:done) do
69
67
  dep = parse(line)
70
- deps << relative_path(dep,file) if dep
68
+ deps << relative_path(dep, file) if dep
71
69
  end
72
70
  end
73
71
  [file, deps]
@@ -76,30 +74,31 @@ module Dumbo
76
74
 
77
75
  def encoded_line(line)
78
76
  if String.method_defined?(:encode)
79
- line.encode!('UTF-8', 'UTF-8', :invalid => :replace)
77
+ line.encode!('UTF-8', 'UTF-8', invalid: :replace)
80
78
  else
81
79
  line
82
80
  end
83
81
  end
84
82
 
85
83
  def parse(line)
86
- return $1 if encoded_line(line) =~ DependencyResolver.depends_pattern
84
+ return Regexp.last_match[1] if encoded_line(line) =~ DependencyResolver.depends_pattern
87
85
 
88
86
  # end of first commenting block we're done.
89
87
  throw :done unless line =~ /--/
90
88
  end
91
89
 
92
- def relative_path(dep,file)
90
+ def relative_path(dep, file)
93
91
  p = Pathname.new(file).dirname.join(dep)
94
92
  if p.exist? && p.extname.present?
95
93
  return p.to_s
96
94
  elsif p.extname.empty?
97
- %w(.sql .erb).each do |ext|
95
+ %w(.sql .erb .sql.erb).each do |ext|
98
96
  new_p = p.sub_ext(ext)
99
97
  return new_p.to_s if new_p.exist?
100
98
  end
101
99
  end
102
- raise DependencyNotFound.new(dep, file)
100
+
101
+ fail DependencyNotFound.new(dep, file)
103
102
  end
104
103
  end
105
- end
104
+ end