ridgepole-mysql-partition 0.1.0

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cec4c5d98b1691c5dba8c6749772ff2133fb76d7
4
+ data.tar.gz: a4e15aa06fe339f3d53f8d7d589821cbeed2ff32
5
+ SHA512:
6
+ metadata.gz: 51c50da16248af8d5b7d7ee35766361ae177138b7f9148bdddbb98548579ea21c76dc2339b6d06f6acd57d433ec99c4313df2a5b0421453664b0e010d2f6d3f1
7
+ data.tar.gz: 7e13537d7ed39100242a394649ab53a19971d27e57694cf93ff8d9ee9ca1ee93fd125f2a24ade609cee7fca0ddfb2d26ea01be06119720570ba8d7460a6d8fff
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ # Editor
15
+ *.swp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ridgepole-mysql-partition.gemspec
6
+ gemspec
@@ -0,0 +1,35 @@
1
+ # Ridgepole::Mysql::Partition
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ridgepole/mysql/partition`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'ridgepole-mysql-partition'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install ridgepole-mysql-partition
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ridgepole-mysql-partition.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ridgepole/mysql/partition"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,16 @@
1
+ require "ridgepole/mysql/partition/version"
2
+
3
+ module Ridgepole
4
+ module MySQL
5
+ module Partition
6
+ autoload :RangePartitionChecker, "ridgepole/mysql/partition/range_partition_checker"
7
+ autoload :RangeParser, "ridgepole/mysql/partition/range_parser"
8
+ autoload :SQLBuilder, "ridgepole/mysql/partition/sql_builder"
9
+ autoload :DSLExtension, "ridgepole/mysql/partition/dsl_extension"
10
+ end
11
+ end
12
+ end
13
+
14
+ if defined?(Ridgepole::DSLParser::Context)
15
+ Ridgepole::DSLParser::Context.include(Ridgepole::MySQL::Partition::DSLExtension)
16
+ end
@@ -0,0 +1,18 @@
1
+ module Ridgepole
2
+ module MySQL
3
+ module Partition
4
+ module DSLExtension
5
+ def range_partition(table_name, columns:, between:, interval:)
6
+ range_parser = RangeParser.new(between: between, interval: interval)
7
+ range_partition_checker = RangePartitionChecker.new(table_name, range_parser)
8
+ sql_builder = SQLBuilder.new(table_name, columns, range_parser)
9
+
10
+ execute(sql_builder.to_sql) do |c|
11
+ # execute only if you need to update partition
12
+ range_partition_checker.can_apply?(c)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ module Ridgepole
2
+ module MySQL module Partition
3
+ class RangeParser
4
+ class TransparentValueParser
5
+ def parse_as_partition_name(value)
6
+ "p#{value}"
7
+ end
8
+
9
+ def parse_as_value(value)
10
+ value
11
+ end
12
+ end
13
+
14
+ class TimeValueParser
15
+ def parse_as_partition_name(time)
16
+ time.strftime("p%Y%m%d")
17
+ end
18
+
19
+ def parse_as_value(time)
20
+ time.strftime("%Y-%m-%d %H:%M:%S")
21
+ end
22
+ end
23
+
24
+ def initialize(between:, interval:)
25
+ @between = between
26
+ @interval = interval
27
+ end
28
+
29
+ def alter_keyword
30
+ "PARTITION BY RANGE"
31
+ end
32
+
33
+ def partition_string
34
+ range_to_array.map do |pname, pvalue|
35
+ "PARTITION #{pname} VALUES LESS THAN (\"#{pvalue}\") ENGINE=InnoDB"
36
+ end.join(",\n")
37
+ end
38
+
39
+ def partition_names
40
+ range_to_array.map(&:first)
41
+ end
42
+
43
+ private
44
+
45
+ def value_parser
46
+ @_value_parser ||=
47
+ begin
48
+ return TimeValueParser.new if @between.first.is_a?(Time)
49
+ TransparentValueParser.new
50
+ end
51
+ end
52
+
53
+ def range_to_array
54
+ # Do not use slice_each or else for Time
55
+ start_at = @between.first
56
+ end_at = @between.last
57
+
58
+ [].tap do |result|
59
+ iter = start_at
60
+ loop do
61
+ iter = [iter + @interval, end_at].min
62
+
63
+ result << [
64
+ value_parser.parse_as_partition_name(iter.dup),
65
+ value_parser.parse_as_value(iter.dup)
66
+ ]
67
+
68
+ break if iter >= end_at
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,34 @@
1
+ module Ridgepole
2
+ module MySQL
3
+ module Partition
4
+ class RangePartitionChecker
5
+ def initialize(table_name, range_parser)
6
+ @table_name = table_name
7
+ @applying_partition_names = range_parser.partition_names
8
+ end
9
+
10
+ # Require information_schema read access
11
+ def can_apply?(connection)
12
+ raw_connection = connection.raw_connection
13
+
14
+ db_name = raw_connection.query_options[:database]
15
+ query_string = query(db_name)
16
+
17
+ embbed_partition = raw_connection.query(query_string).each.flatten
18
+ embbed_partition != @applying_partition_names
19
+ end
20
+
21
+ private
22
+
23
+ def query(db_name)
24
+ query = <<-SQL
25
+ SELECT PARTITION_NAME FROM information_schema.PARTITIONS
26
+ WHERE TABLE_SCHEMA = '#{db_name}'
27
+ AND TABLE_NAME = '#{@table_name}'
28
+ AND PARTITION_NAME IS NOT NULL
29
+ SQL
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ module Ridgepole
2
+ module MySQL module Partition
3
+ class SQLBuilder
4
+ def initialize(table_name, columns, partition_parser)
5
+ @table_name = table_name
6
+ @columns = columns.is_a?(Array) ? columns : [columns]
7
+ @partition_parser = partition_parser
8
+ end
9
+
10
+ def to_sql
11
+ <<-SQL
12
+ ALTER TABLE #{@table_name} #{@partition_parser.alter_keyword} COLUMNS(#{@columns.join(",")}) (
13
+ #{@partition_parser.partition_string}
14
+ );
15
+ SQL
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module Ridgepole
2
+ module MySQL
3
+ module Partition
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ridgepole/mysql/partition/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ridgepole-mysql-partition"
8
+ spec.version = Ridgepole::MySQL::Partition::VERSION
9
+ spec.authors = ["Masashi AKISUE"]
10
+ spec.email = ["m.akisue.b@gmail.com"]
11
+
12
+ spec.summary = %q{The plugin to define MySQL range partition for ridgepole}
13
+ spec.description = %q{The plugin to define MySQL range partition for ridgepole}
14
+ spec.homepage = "https://github.com/the40san/ridgepole-mysql-partition"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.15"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ridgepole-mysql-partition
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Masashi AKISUE
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: The plugin to define MySQL range partition for ridgepole
56
+ email:
57
+ - m.akisue.b@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - lib/ridgepole/mysql/partition.rb
71
+ - lib/ridgepole/mysql/partition/dsl_extension.rb
72
+ - lib/ridgepole/mysql/partition/range_parser.rb
73
+ - lib/ridgepole/mysql/partition/range_partition_checker.rb
74
+ - lib/ridgepole/mysql/partition/sql_builder.rb
75
+ - lib/ridgepole/mysql/partition/version.rb
76
+ - ridgepole-mysql-partition.gemspec
77
+ homepage: https://github.com/the40san/ridgepole-mysql-partition
78
+ licenses: []
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.6.13
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: The plugin to define MySQL range partition for ridgepole
100
+ test_files: []