pgtk 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # Pgtk main module.
24
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
+ # Copyright:: Copyright (c) 2019 Yegor Bugayenko
26
+ # License:: MIT
27
+ module Pgtk
28
+ # Nothing here.
29
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'English'
24
+ require 'rake'
25
+ require 'rake/tasklib'
26
+ require 'shellwords'
27
+ require 'yaml'
28
+ require_relative '../pgtk'
29
+
30
+ # Liquibase rake task.
31
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
32
+ # Copyright:: Copyright (c) 2019 Yegor Bugayenko
33
+ # License:: MIT
34
+ class Pgtk::LiquibaseTask < Rake::TaskLib
35
+ attr_accessor :name
36
+ attr_accessor :master
37
+ attr_accessor :yaml
38
+ attr_accessor :quiet
39
+
40
+ def initialize(*args, &task_block)
41
+ @name = args.shift || :liquibase
42
+ @quite = false
43
+ unless ::Rake.application.last_description
44
+ desc 'Deploy Liquibase changes to the running PostgreSQL server'
45
+ end
46
+ task(name, *args) do |_, task_args|
47
+ RakeFileUtils.send(:verbose, true) do
48
+ yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
49
+ run
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def run
57
+ raise "Option 'master' is mandatory" unless @master
58
+ raise "Option 'yaml' is mandatory" unless @yaml
59
+ yml = YAML.load_file(@yaml)
60
+ raise "YAML at #{yaml} is missing 'pgsql' section" unless yml['pgsql']
61
+ pom = File.expand_path(File.join(__dir__, '../resources/pom.xml'))
62
+ Dir.chdir(File.dirname(@master)) do
63
+ system(
64
+ [
65
+ 'mvn verify',
66
+ '--errors',
67
+ @quiet ? '--quiet' : '',
68
+ '--file',
69
+ Shellwords.escape(pom),
70
+ '--define',
71
+ "liquibase.changeLogFile=#{@master}",
72
+ '--define',
73
+ "liquibase.url=#{Shellwords.escape(yml['pgsql']['url'])}",
74
+ '--define',
75
+ "liquibase.logging=#{@quiet ? 'severe' : 'info'}",
76
+ '2>&1'
77
+ ].join(' ')
78
+ )
79
+ end
80
+ raise unless $CHILD_STATUS.exitstatus.zero?
81
+ end
82
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'cgi'
24
+ require 'English'
25
+ require 'rake'
26
+ require 'rake/tasklib'
27
+ require 'random-port'
28
+ require 'shellwords'
29
+ require 'tempfile'
30
+ require 'yaml'
31
+ require_relative '../pgtk'
32
+
33
+ # Pgsql rake task.
34
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
35
+ # Copyright:: Copyright (c) 2019 Yegor Bugayenko
36
+ # License:: MIT
37
+ class Pgtk::PgsqlTask < Rake::TaskLib
38
+ attr_accessor :name
39
+ attr_accessor :dir
40
+ attr_accessor :fresh_start
41
+ attr_accessor :user
42
+ attr_accessor :password
43
+ attr_accessor :dbname
44
+ attr_accessor :yaml
45
+ attr_accessor :quiet
46
+
47
+ def initialize(*args, &task_block)
48
+ @name = args.shift || :pgsql
49
+ @fresh_start = false
50
+ @quite = false
51
+ @user = 'test'
52
+ @password = 'test'
53
+ @dbname = 'test'
54
+ unless ::Rake.application.last_description
55
+ desc 'Start a local PostgreSQL server'
56
+ end
57
+ task(name, *args) do |_, task_args|
58
+ RakeFileUtils.send(:verbose, true) do
59
+ yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
60
+ run
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def run
68
+ raise "Option 'dir' is mandatory" unless @dir
69
+ raise "Option 'yaml' is mandatory" unless @yaml
70
+ home = File.expand_path(@dir)
71
+ FileUtils.rm_rf(home) if @fresh_start
72
+ if File.exist?(home)
73
+ raise "Directory/file #{home} is present, use fresh_start=true"
74
+ end
75
+ out = "2>&1 #{@quiet ? '>/dev/null' : ''}"
76
+ Tempfile.open do |pwfile|
77
+ IO.write(pwfile.path, @password)
78
+ system(
79
+ [
80
+ 'initdb --auth=trust',
81
+ "-D #{Shellwords.escape(home)}",
82
+ '--username',
83
+ Shellwords.escape(@user),
84
+ '--pwfile',
85
+ Shellwords.escape(pwfile.path),
86
+ out
87
+ ].join(' ')
88
+ )
89
+ end
90
+ raise unless $CHILD_STATUS.exitstatus.zero?
91
+ port = RandomPort::Pool.new.acquire
92
+ pid = Process.spawn('postgres', '-k', home, '-D', home, "--port=#{port}")
93
+ at_exit do
94
+ `kill -TERM #{pid}`
95
+ puts "PostgreSQL killed in PID #{pid}"
96
+ end
97
+ sleep 1
98
+ attempt = 0
99
+ begin
100
+ system(
101
+ [
102
+ "createdb -h localhost -p #{port}",
103
+ '--username',
104
+ Shellwords.escape(@user),
105
+ Shellwords.escape(@dbname),
106
+ out
107
+ ].join(' ')
108
+ )
109
+ raise unless $CHILD_STATUS.exitstatus.zero?
110
+ rescue StandardError => e
111
+ puts e.message
112
+ sleep(5)
113
+ attempt += 1
114
+ raise if attempt > 10
115
+ retry
116
+ end
117
+ IO.write(
118
+ @yaml,
119
+ {
120
+ 'pgsql' => {
121
+ 'host' => 'localhost',
122
+ 'port' => port,
123
+ 'dbname' => @dbname,
124
+ 'user' => @user,
125
+ 'password' => @password,
126
+ 'url' => [
127
+ "jdbc:postgresql://localhost:#{port}/",
128
+ "#{CGI.escape(@dbname)}?user=#{CGI.escape(@user)}",
129
+ "&password=#{CGI.escape(@password)}"
130
+ ].join
131
+ }
132
+ }.to_yaml
133
+ )
134
+ puts "PostgreSQL is running in PID #{pid}"
135
+ end
136
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'pg'
24
+ require_relative '../pgtk'
25
+
26
+ # Pool.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2019 Yegor Bugayenko
29
+ # License:: MIT
30
+ class Pgtk::Pool
31
+ # Constructor.
32
+ def initialize(host: 'localhost', port:, dbname:, user:, password:)
33
+ @host = host
34
+ @port = port
35
+ @port = port
36
+ @dbname = dbname
37
+ @user = user
38
+ @password = password
39
+ @pool = Queue.new
40
+ end
41
+
42
+ # Start it with a fixed number of connections.
43
+ def start(max = 1)
44
+ max.times do
45
+ @pool << PG.connect(
46
+ dbname: @dbname, host: @host, port: @port,
47
+ user: @user, password: @password
48
+ )
49
+ end
50
+ self
51
+ end
52
+
53
+ # Make a query and return the result as an array of hashes.
54
+ def exec(query, args = [], result = 0)
55
+ connect do |c|
56
+ c.exec_params(query, args, result) do |res|
57
+ if block_given?
58
+ yield res
59
+ else
60
+ rows = []
61
+ res.each { |r| rows << r }
62
+ rows
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ # Get a connection from the pool and let us work with it. The block
69
+ # has to be provided, for example:
70
+ #
71
+ # pgsql.connect do |c|
72
+ # c.transaction do |conn|
73
+ # conn.exec_params('DELETE FROM user WHERE id = $1', [id])
74
+ # conn.exec_params('INSERT INTO user (name) VALUES ($1)', [name])
75
+ # end
76
+ # end
77
+ def connect
78
+ conn = @pool.pop
79
+ begin
80
+ yield conn
81
+ ensure
82
+ @pool << conn
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative '../pgtk'
24
+
25
+ # Pgtk version.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2019 Yegor Bugayenko
28
+ # License:: MIT
29
+ module Pgtk
30
+ # Current version of the library.
31
+ VERSION = '0.1.0'
32
+ end
@@ -0,0 +1,63 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ (The MIT License)
4
+
5
+ Copyright (c) 2019 Yegor Bugayenko
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the 'Software'), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ -->
25
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
26
+ <modelVersion>4.0.0</modelVersion>
27
+ <groupId>pgtk</groupId>
28
+ <artifactId>pgtk</artifactId>
29
+ <version>1.0-SNAPSHOT</version>
30
+ <packaging>pom</packaging>
31
+ <dependencies>
32
+ <dependency>
33
+ <groupId>org.postgresql</groupId>
34
+ <artifactId>postgresql</artifactId>
35
+ <version>9.4.1212</version>
36
+ <scope>runtime</scope>
37
+ </dependency>
38
+ </dependencies>
39
+ <build>
40
+ <plugins>
41
+ <plugin>
42
+ <groupId>org.liquibase</groupId>
43
+ <artifactId>liquibase-maven-plugin</artifactId>
44
+ <version>3.2.2</version>
45
+ <configuration>
46
+ <driver>org.postgresql.Driver</driver>
47
+ <logging>info</logging>
48
+ <verbose>false</verbose>
49
+ <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
50
+ </configuration>
51
+ <executions>
52
+ <execution>
53
+ <id>update</id>
54
+ <goals>
55
+ <goal>update</goal>
56
+ </goals>
57
+ <phase>verify</phase>
58
+ </execution>
59
+ </executions>
60
+ </plugin>
61
+ </plugins>
62
+ </build>
63
+ </project>
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'English'
24
+
25
+ lib = File.expand_path('lib', __dir__)
26
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
27
+ require_relative 'lib/pgtk/version'
28
+ Gem::Specification.new do |s|
29
+ s.specification_version = 2 if s.respond_to? :specification_version=
30
+ if s.respond_to? :required_rubygems_version=
31
+ s.required_rubygems_version = Gem::Requirement.new('>= 0')
32
+ end
33
+ s.rubygems_version = '2.2'
34
+ s.required_ruby_version = '>= 2.3'
35
+ s.name = 'pgtk'
36
+ s.version = Pgtk::VERSION
37
+ s.license = 'MIT'
38
+ s.summary = 'PostgreSQL ToolKit for Ruby apps'
39
+ s.description = '...'
40
+ s.authors = ['Yegor Bugayenko']
41
+ s.email = 'yegor256@gmail.com'
42
+ s.homepage = 'http://github.com/yegor256/pgtk'
43
+ s.files = `git ls-files`.split($RS)
44
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
45
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
46
+ s.rdoc_options = ['--charset=UTF-8']
47
+ s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
48
+ s.add_runtime_dependency 'backtrace', '~> 0.3'
49
+ s.add_runtime_dependency 'pg', '1.1.3'
50
+ s.add_runtime_dependency 'random-port', '~> 0.3'
51
+ s.add_development_dependency 'codecov', '0.1.10'
52
+ s.add_development_dependency 'minitest', '5.5.0'
53
+ s.add_development_dependency 'rake', '12.0.0'
54
+ s.add_development_dependency 'rspec-rails', '3.1.0'
55
+ s.add_development_dependency 'rubocop', '0.61.0'
56
+ s.add_development_dependency 'rubocop-rspec', '1.31.0'
57
+ s.add_development_dependency 'xcop', '0.6'
58
+ end