postgresql-check 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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +90 -0
- data/Rakefile +2 -0
- data/lib/postgresql/check/command_recorder.rb +19 -0
- data/lib/postgresql/check/constraint.rb +6 -0
- data/lib/postgresql/check/schema_definitions.rb +15 -0
- data/lib/postgresql/check/schema_dumper.rb +34 -0
- data/lib/postgresql/check/schema_statements.rb +87 -0
- data/lib/postgresql/check/table.rb +13 -0
- data/lib/postgresql/check/table_definition.rb +20 -0
- data/lib/postgresql/check/version.rb +5 -0
- data/lib/postgresql/check.rb +42 -0
- data/postgresql-check.gemspec +23 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6eb60da5a7a04b6f3ba274a4e32de726bc1a675
|
4
|
+
data.tar.gz: 6fb2dcf1dff2148952e0bbbbefb8d1d26887675d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02e9e39c308790b9452afd8d362f00a5e31249587e408919cdcdce8f77dbf2798c507d866a9e482bc2aa082796f683bc24d11a142f2abc8c286168ce93621cf0
|
7
|
+
data.tar.gz: 8dd9938fe756ee6d7e4f76485014c4aa664af60da3f55c9127a72198a3b471be5ac52367d463beb37d3847620294907f83c511717708961d88b10cff69793507
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alexei Mikhailov
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Postgresql::Check
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/take-five/postgresql-check)
|
4
|
+
|
5
|
+
This gem introduces a few methods to your migrations for adding and removing
|
6
|
+
[Check Constraints](http://www.postgresql.org/docs/9.3/static/ddl-constraints.html).
|
7
|
+
It also dumps these constraints to `schema.rb`.
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
* PostgreSQL
|
12
|
+
* active_record >= 3.2.0
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'postgresql-check'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install postgresql-check
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Two new methods are introduced to migrations:
|
33
|
+
|
34
|
+
* `add_check(table_name, condition, :name => constraint_name)`
|
35
|
+
* `remove_check(table_name, :name => constraint_name)`
|
36
|
+
|
37
|
+
Given the following model:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class Product < ActiveRecord::Base
|
41
|
+
validates :price, :numericality => {:greater_than => 0}
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
You can add a check constraint in your migration:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
add_check :products, 'price > 0', :name => 'products_price_check'
|
49
|
+
```
|
50
|
+
|
51
|
+
**NOTE**: `:name` option is mandatory now.
|
52
|
+
|
53
|
+
To remove constraint use `remove_check` method:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
remove_check :products, :name => 'products_price_check'
|
57
|
+
```
|
58
|
+
|
59
|
+
## Change Table methods
|
60
|
+
|
61
|
+
This gem adds extra methods to `create_table` and `change_table`:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
create_table :products do |t|
|
65
|
+
t.decimal :price, :null => false
|
66
|
+
t.check 'price > 0', :name => 'products_price_check'
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Remove a check constraint:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
change_table :products do |t|
|
74
|
+
t.remove_check :name => 'products_price_check'
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
## Future plans
|
79
|
+
|
80
|
+
* Write tests
|
81
|
+
* Auto-generate constraint name
|
82
|
+
* Make `remove_check` reversible
|
83
|
+
|
84
|
+
## Contributing
|
85
|
+
|
86
|
+
1. Fork it ( https://github.com/[my-github-username]/postgresql-check/fork )
|
87
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
88
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
89
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
90
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Postgresql
|
2
|
+
module Check
|
3
|
+
module CommandRecorder
|
4
|
+
def add_check(*args)
|
5
|
+
record(:add_check, args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove_check(*args)
|
9
|
+
record(:remove_check, args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def invert_add_check(args)
|
13
|
+
table_name, condition, options = args
|
14
|
+
|
15
|
+
[:remove_check, [table_name, options]]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Postgresql
|
2
|
+
module Check
|
3
|
+
module SchemaDefinitions
|
4
|
+
def self.included(base)
|
5
|
+
base::Table.class_eval do
|
6
|
+
include Postgresql::Check::Table
|
7
|
+
end
|
8
|
+
|
9
|
+
base::TableDefinition.class_eval do
|
10
|
+
include Postgresql::Check::TableDefinition
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Postgresql
|
2
|
+
module Check
|
3
|
+
module SchemaDumper
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
alias_method_chain :table, :checks
|
8
|
+
end
|
9
|
+
|
10
|
+
def table_with_checks(table, stream)
|
11
|
+
table_without_checks(table, stream)
|
12
|
+
check_constraints(table, stream)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def check_constraints(table, stream)
|
17
|
+
if (checks = @connection.checks(table)).any?
|
18
|
+
definitions = checks.map do |check|
|
19
|
+
dump_check_constraint(check)
|
20
|
+
end
|
21
|
+
|
22
|
+
stream.puts
|
23
|
+
stream.puts definitions.join("\n")
|
24
|
+
stream.puts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def dump_check_constraint(check)
|
29
|
+
' add_check ' + remove_prefix_and_suffix(check.table_name).inspect + ', '+
|
30
|
+
check.condition.inspect + ', name: ' + check.name.inspect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Postgresql
|
2
|
+
module Check
|
3
|
+
module SchemaStatements
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
alias_method_chain :create_table, :checks
|
8
|
+
end
|
9
|
+
|
10
|
+
# Add a new Check constraint to table with given +table_name+
|
11
|
+
# using given +conditions+. Constraint name should be specified
|
12
|
+
# by +:name+ options in +options+ argument.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# add_check :products, 'price > 0', :name => 'products_price_chk'
|
16
|
+
#
|
17
|
+
# # Generates:
|
18
|
+
# # ALTER TABLE products ADD CONSTRAINT products_price_chk CHECK (price > 0)
|
19
|
+
#
|
20
|
+
# @note +:name+ option is mandatory.
|
21
|
+
#
|
22
|
+
# @param [String|Symbol] table_name Table name which constraint created on
|
23
|
+
# @param [String] condition Raw SQL string specifying constraint condition
|
24
|
+
# @param [Hash] options Hash with single mandatory key +:name+
|
25
|
+
# @option options [String|Symbol] :name Constraint name
|
26
|
+
def add_check(table_name, condition, options)
|
27
|
+
name = options.fetch(:name) { raise 'add_check, :name option required' }
|
28
|
+
|
29
|
+
sql = "ALTER TABLE #{quote_table_name(table_name)} " +
|
30
|
+
"ADD CONSTRAINT #{quote_column_name("#{table_name}_#{name}")} " +
|
31
|
+
"CHECK (#{condition})"
|
32
|
+
|
33
|
+
execute(sql)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Remove constraint with given name from table. Constraint name
|
37
|
+
# is specified with +options+ hash.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# remove_check :products, :name => 'products_price_chk'
|
41
|
+
#
|
42
|
+
# # Generates:
|
43
|
+
# # ALTER TABLE products DROP CONSTRAINT products_price_chk
|
44
|
+
#
|
45
|
+
# @param [String|Symbol] table_name Table name which constraint defined on
|
46
|
+
# @param [Hash] options Hash with single mandatory key +:name+
|
47
|
+
# @option options [String|Symbol] :name Constraint name
|
48
|
+
def remove_check(table_name, options)
|
49
|
+
name = options.fetch(:name) { raise 'remove_check, :name option required' }
|
50
|
+
|
51
|
+
sql = "ALTER TABLE #{quote_table_name(table_name)} " +
|
52
|
+
"DROP CONSTRAINT #{quote_column_name("#{table_name}_#{name}")}"
|
53
|
+
|
54
|
+
execute(sql)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def create_table_with_checks(table_name, *args, &block)
|
59
|
+
definition = nil
|
60
|
+
|
61
|
+
create_table_without_checks(table_name, *args) do |td|
|
62
|
+
definition = td # trick to get the definition
|
63
|
+
block.call(td) unless block.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
definition.checks.each do |condition, options|
|
67
|
+
add_check(table_name, condition, options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def checks(table_name)
|
73
|
+
checks_info = select_all %{
|
74
|
+
SELECT c.conname, c.consrc
|
75
|
+
FROM pg_constraint c
|
76
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
77
|
+
WHERE c.contype = 'c'
|
78
|
+
AND t.relname = '#{table_name}'
|
79
|
+
}
|
80
|
+
|
81
|
+
checks_info.map do |row|
|
82
|
+
Constraint.new(table_name, row['conname'], row['consrc'])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Postgresql
|
2
|
+
module Check
|
3
|
+
module TableDefinition
|
4
|
+
# Add new check constraint to table
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# create_table :goods do |t|
|
8
|
+
# t.float :price
|
9
|
+
# t.check 'price > 0', :name => 'price_gt_0'
|
10
|
+
# end
|
11
|
+
def check(condition, options)
|
12
|
+
checks << [condition, options]
|
13
|
+
end
|
14
|
+
|
15
|
+
def checks
|
16
|
+
@checks ||= []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'postgresql/check/version'
|
2
|
+
require 'active_support/dependencies/autoload'
|
3
|
+
require 'active_support/lazy_load_hooks'
|
4
|
+
|
5
|
+
module Postgresql
|
6
|
+
module Check
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
autoload :Constraint
|
10
|
+
autoload :CommandRecorder
|
11
|
+
autoload :SchemaStatements
|
12
|
+
autoload :SchemaDefinitions
|
13
|
+
autoload :SchemaDumper
|
14
|
+
autoload :Table
|
15
|
+
autoload :TableDefinition
|
16
|
+
|
17
|
+
def self.setup
|
18
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.module_eval do
|
19
|
+
include Postgresql::Check::SchemaStatements
|
20
|
+
include Postgresql::Check::SchemaDefinitions
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveRecord::SchemaDumper.class_eval do
|
24
|
+
include Postgresql::Check::SchemaDumper
|
25
|
+
end
|
26
|
+
|
27
|
+
ActiveRecord::Migration::CommandRecorder.class_eval do
|
28
|
+
include Postgresql::Check::CommandRecorder
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if defined?(Rails)
|
33
|
+
class Railtie < Rails::Railtie
|
34
|
+
initializer 'postgresql_check.setup' do
|
35
|
+
ActiveSupport.on_load :active_record do
|
36
|
+
Postgresql::Check.setup
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'postgresql/check/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'postgresql-check'
|
8
|
+
spec.version = Postgresql::Check::VERSION
|
9
|
+
spec.authors = ['Alexei Mikhailov']
|
10
|
+
spec.email = ['amikhailov83@gmail.com']
|
11
|
+
spec.summary = %q{Adds helpers to migrations and dumps check constraints to schema.rb}
|
12
|
+
spec.homepage = 'https://github.com/take-five/postgresql-check'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_dependency 'activerecord', '>= 3.2.0'
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: postgresql-check
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexei Mikhailov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- amikhailov83@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- lib/postgresql/check.rb
|
68
|
+
- lib/postgresql/check/command_recorder.rb
|
69
|
+
- lib/postgresql/check/constraint.rb
|
70
|
+
- lib/postgresql/check/schema_definitions.rb
|
71
|
+
- lib/postgresql/check/schema_dumper.rb
|
72
|
+
- lib/postgresql/check/schema_statements.rb
|
73
|
+
- lib/postgresql/check/table.rb
|
74
|
+
- lib/postgresql/check/table_definition.rb
|
75
|
+
- lib/postgresql/check/version.rb
|
76
|
+
- postgresql-check.gemspec
|
77
|
+
homepage: https://github.com/take-five/postgresql-check
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.2.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Adds helpers to migrations and dumps check constraints to schema.rb
|
101
|
+
test_files: []
|
102
|
+
has_rdoc:
|