mysql_framework 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.
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MysqlFramework::Scripts::Manager do
6
+ let(:connector) { MysqlFramework::Connector.new }
7
+
8
+ before :each do
9
+ subject.instance_variable_set(:@mysql_connector, connector)
10
+ end
11
+
12
+ describe '#execute' do
13
+ before :each do
14
+ subject.initialize_script_history
15
+ end
16
+
17
+ it 'executes all pending scripts' do
18
+ expect(subject.table_exists?('demo')).to eq(false)
19
+ expect(subject.table_exists?('test')).to eq(false)
20
+
21
+ subject.execute
22
+
23
+ expect(subject.table_exists?('demo')).to eq(true)
24
+ expect(subject.table_exists?('test')).to eq(true)
25
+ end
26
+
27
+ after :each do
28
+ subject.drop_all_tables
29
+ end
30
+ end
31
+
32
+ describe '#apply_by_tag' do
33
+ before :each do
34
+ subject.initialize_script_history
35
+ end
36
+
37
+ it 'executes all pending scripts that match the tag' do
38
+ expect(subject.table_exists?('demo')).to eq(false)
39
+ expect(subject.table_exists?('test')).to eq(false)
40
+
41
+ subject.apply_by_tag([MysqlFramework::Support::Tables::TestTable::NAME])
42
+
43
+ expect(subject.table_exists?('demo')).to eq(false)
44
+ expect(subject.table_exists?('test')).to eq(true)
45
+ end
46
+
47
+ after :each do
48
+ subject.drop_all_tables
49
+ end
50
+ end
51
+
52
+ describe '#drop_all_tables' do
53
+ it 'drops the script history table and any registered tables' do
54
+ expect(subject).to receive(:drop_script_history)
55
+ expect(subject).to receive(:drop_table).with('test')
56
+ expect(subject).to receive(:drop_table).with('demo')
57
+
58
+ subject.drop_all_tables
59
+ end
60
+ end
61
+
62
+ describe '#retrieve_last_executed_script' do
63
+ before :each do
64
+ subject.initialize_script_history
65
+ end
66
+
67
+ context 'when no scripts have been executed' do
68
+ it 'returns 0' do
69
+ expect(subject.retrieve_last_executed_script).to eq(0)
70
+ end
71
+ end
72
+
73
+ context 'when scripts have been executed previously' do
74
+ before :each do
75
+ subject.apply_by_tag([MysqlFramework::Support::Tables::TestTable::NAME])
76
+ end
77
+
78
+ it 'returns the last executed script' do
79
+ expect(subject.retrieve_last_executed_script).to eq(201807031200)
80
+ end
81
+ end
82
+
83
+ after :each do
84
+ subject.drop_script_history
85
+ end
86
+ end
87
+
88
+ describe '#initialize_script_history' do
89
+ it 'creates a migration history table' do
90
+ expect(subject.table_exists?('migration_script_history')).to eq(false)
91
+ subject.initialize_script_history
92
+ expect(subject.table_exists?('migration_script_history')).to eq(true)
93
+ end
94
+ end
95
+
96
+ describe '#calculate_pending_scripts' do
97
+ it 'returns any scripts that are newer than the given date in ascending order' do
98
+ timestamp = 201701010000 # 00:00 01/01/2017
99
+ results = subject.calculate_pending_scripts(timestamp)
100
+
101
+ expect(results.length).to eq(3)
102
+ expect(results[0]).to be_a(MysqlFramework::Support::Scripts::CreateTestTable)
103
+ expect(results[1]).to be_a(MysqlFramework::Support::Scripts::CreateDemoTable)
104
+ end
105
+
106
+ context 'when there are scripts older than the given date' do
107
+ it 'returns only scripts that are newer than the given date in ascending order' do
108
+ timestamp = 201802021010 # 10:10 02/02/2018
109
+ results = subject.calculate_pending_scripts(timestamp)
110
+
111
+ expect(results.length).to eq(2)
112
+ expect(results[0]).to be_a(MysqlFramework::Support::Scripts::CreateDemoTable)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe '#table_exists?' do
118
+ context 'when the table exists' do
119
+ it 'returns true' do
120
+ expect(subject.table_exists?('gems')).to eq(true)
121
+ end
122
+ end
123
+
124
+ context 'when the table does not exist' do
125
+ it 'returns false' do
126
+ expect(subject.table_exists?('foo')).to eq(false)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#drop_script_history' do
132
+ it 'drops the migration script history table' do
133
+ query = <<~SQL
134
+ DROP TABLE IF EXISTS `#{ENV.fetch('MYSQL_DATABASE')}`.`migration_script_history`
135
+ SQL
136
+ expect(connector).to receive(:query).with(query)
137
+ subject.drop_script_history
138
+ end
139
+ end
140
+
141
+ describe '#drop_table' do
142
+ it 'drops the given table' do
143
+ expect(connector).to receive(:query).with(<<~SQL)
144
+ DROP TABLE IF EXISTS `some_database`.`some_table`
145
+ SQL
146
+ subject.drop_table('`some_database`.`some_table`')
147
+ end
148
+ end
149
+
150
+ describe '#all_tables' do
151
+ it 'returns all registered tables' do
152
+ expect(subject.all_tables).to eq(['test', 'demo'])
153
+ end
154
+ end
155
+
156
+ describe '.all_tables' do
157
+ it 'stores a class level array of tables' do
158
+ expect(described_class.all_tables).to eq(['test', 'demo'])
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MysqlFramework::SqlColumn do
6
+ subject { described_class.new(table: 'gems', column: 'version') }
7
+
8
+ describe '#to_s' do
9
+ it 'returns the prepared sql name with backticks' do
10
+ expect(subject.to_s).to eq('`gems`.`version`')
11
+ end
12
+ end
13
+
14
+ describe '#to_sym' do
15
+ it 'returns the column name as a symbol' do
16
+ expect(subject.to_sym).to eq(:version)
17
+ end
18
+ end
19
+
20
+ describe '#eq' do
21
+ it 'returns a SqlCondition for the comparison' do
22
+ condition = subject.eq('2.0.0')
23
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
24
+ expect(condition.to_s).to eq('`gems`.`version` = ?')
25
+ end
26
+ end
27
+
28
+ describe '#not_eq' do
29
+ it 'returns a SqlCondition for the comparison' do
30
+ condition = subject.not_eq('2.0.0')
31
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
32
+ expect(condition.to_s).to eq('`gems`.`version` <> ?')
33
+ end
34
+ end
35
+
36
+ describe '#gt' do
37
+ it 'returns a SqlCondition for the comparison' do
38
+ condition = subject.gt('2.0.0')
39
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
40
+ expect(condition.to_s).to eq('`gems`.`version` > ?')
41
+ end
42
+ end
43
+
44
+ describe '#gte' do
45
+ it 'returns a SqlCondition for the comparison' do
46
+ condition = subject.gte('2.0.0')
47
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
48
+ expect(condition.to_s).to eq('`gems`.`version` >= ?')
49
+ end
50
+ end
51
+
52
+ describe '#lt' do
53
+ it 'returns a SqlCondition for the comparison' do
54
+ condition = subject.lt('2.0.0')
55
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
56
+ expect(condition.to_s).to eq('`gems`.`version` < ?')
57
+ end
58
+ end
59
+
60
+ describe '#lte' do
61
+ it 'returns a SqlCondition for the comparison' do
62
+ condition = subject.lte('2.0.0')
63
+ expect(condition).to be_a(MysqlFramework::SqlCondition)
64
+ expect(condition.to_s).to eq('`gems`.`version` <= ?')
65
+ end
66
+ end
67
+
68
+ describe '#as' do
69
+ it 'returns the column specified as another name' do
70
+ expect(subject.as('v')).to eq('`gems`.`version` as `v`')
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MysqlFramework::SqlCondition do
6
+ subject { described_class.new(column: 'version', comparison: '=', value: '1.0.0') }
7
+
8
+ describe '#to_s' do
9
+ it 'returns the condition as a string for a prepared statement' do
10
+ expect(subject.to_s).to eq('version = ?')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,223 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MysqlFramework::SqlQuery do
6
+ let(:gems) { MysqlFramework::SqlTable.new('gems') }
7
+ let(:versions) { MysqlFramework::SqlTable.new('versions') }
8
+
9
+ describe 'building a query' do
10
+ it 'builds the insert query as expected' do
11
+ subject.insert(gems, 15)
12
+ .into(
13
+ gems[:name],
14
+ gems[:author],
15
+ gems[:created_at],
16
+ gems[:updated_at]
17
+ )
18
+ .values(
19
+ 'mysql_framework',
20
+ 'sage',
21
+ '2018-06-28 10:00:00',
22
+ '2018-06-28 10:00:00'
23
+ )
24
+
25
+ expect(subject.sql).to eq('insert into `gems` partition(p15) (`gems`.`name`,`gems`.`author`,`gems`.`created_at`,`gems`.`updated_at`) values (?,?,?,?)')
26
+ expect(subject.params).to eq(['mysql_framework', 'sage', '2018-06-28 10:00:00', '2018-06-28 10:00:00'])
27
+ end
28
+
29
+ it 'builds the update query as expected' do
30
+ subject.update(gems, 20)
31
+ .set(
32
+ name: 'mysql_framework',
33
+ updated_at: '2018-06-28 13:00:00'
34
+ )
35
+ .where(
36
+ gems[:id].eq('12345')
37
+ )
38
+
39
+ expect(subject.sql).to eq('update `gems` partition(p20) set `name` = ?, `updated_at` = ? where (`gems`.`id` = ?)')
40
+ expect(subject.params).to eq(['mysql_framework', '2018-06-28 13:00:00', '12345'])
41
+ end
42
+
43
+ it 'builds the delete query as expected' do
44
+ subject.delete.from(gems, 30)
45
+ .where(
46
+ gems[:id].eq('45678')
47
+ )
48
+
49
+ expect(subject.sql).to eq('delete from `gems` partition(p30) where (`gems`.`id` = ?)')
50
+ expect(subject.params).to eq(['45678'])
51
+ end
52
+
53
+ it 'builds a basic select query as expected' do
54
+ subject.select('*')
55
+ .from(gems, 40)
56
+ .where(
57
+ gems[:id].eq('9876')
58
+ )
59
+
60
+ expect(subject.sql).to eq('select * from `gems` partition(p40) where (`gems`.`id` = ?)')
61
+ expect(subject.params).to eq(['9876'])
62
+ end
63
+
64
+ it 'builds a joined select query as expected' do
65
+ subject.select('*')
66
+ .from(gems, 40)
67
+ .join(versions).on(versions[:gem_id], gems[:id])
68
+ .where(
69
+ gems[:id].eq('9876')
70
+ )
71
+
72
+ expect(subject.sql).to eq('select * from `gems` partition(p40) join `versions` on `versions`.`gem_id` = `gems`.`id` where (`gems`.`id` = ?)')
73
+ expect(subject.params).to eq(['9876'])
74
+ end
75
+ end
76
+
77
+ describe '#select' do
78
+ it 'sets the sql for a select statement' do
79
+ subject.select(gems[:id], gems[:name])
80
+ expect(subject.sql).to eq('select `gems`.`id`,`gems`.`name`')
81
+ end
82
+ end
83
+
84
+ describe '#delete' do
85
+ it 'sets the sql for a delete statement' do
86
+ subject.delete
87
+ expect(subject.sql).to eq('delete')
88
+ end
89
+ end
90
+
91
+ describe '#update' do
92
+ it 'sets the sql for an update statement' do
93
+ subject.update(gems)
94
+ expect(subject.sql).to eq('update `gems`')
95
+ end
96
+
97
+ context 'when a partition is specified' do
98
+ it 'sets the sql for an update statement' do
99
+ subject.update(gems, 25)
100
+ expect(subject.sql).to eq('update `gems` partition(p25)')
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#insert' do
106
+ it 'sets the sql for an insert statement' do
107
+ subject.insert(gems)
108
+ expect(subject.sql).to eq('insert into `gems`')
109
+ end
110
+
111
+ context 'when a partition is specified' do
112
+ it 'sets the sql for an insert statement' do
113
+ subject.insert(gems, 35)
114
+ expect(subject.sql).to eq('insert into `gems` partition(p35)')
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#into' do
120
+ it 'sets the sql for an into statement' do
121
+ subject.into(gems[:name], gems[:author], gems[:created_at])
122
+ expect(subject.sql).to eq('(`gems`.`name`,`gems`.`author`,`gems`.`created_at`)')
123
+ end
124
+ end
125
+
126
+ describe '#values' do
127
+ it 'sets the sql for the values statement' do
128
+ subject.values('mysql_framework', 'sage', '2016-06-28 10:00:00')
129
+ expect(subject.sql).to eq('values (?,?,?)')
130
+ end
131
+ end
132
+
133
+ describe '#set' do
134
+ it 'sets the sql for the set statement' do
135
+ subject.set(name: 'mysql_framework', author: 'sage', created_at: '2016-06-28 10:00:00')
136
+ expect(subject.sql).to eq('set `name` = ?, `author` = ?, `created_at` = ?')
137
+ end
138
+ end
139
+
140
+ describe '#from' do
141
+ it 'sets the sql for a from statement' do
142
+ subject.from(gems)
143
+ expect(subject.sql).to eq('from `gems`')
144
+ end
145
+
146
+ context 'when a partition is specified' do
147
+ it 'sets the sql for a from statement' do
148
+ subject.from(gems, 45)
149
+ expect(subject.sql).to eq('from `gems` partition(p45)')
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#where' do
155
+ before :each do
156
+ subject.where(gems['author'].eq('sage'), gems['created_at'].gt('2018-01-01 00:00:00'))
157
+ end
158
+
159
+ it 'appends where to the sql' do
160
+ expect(subject.sql).to include('where')
161
+ end
162
+
163
+ it 'sets the sql for the where statement' do
164
+ expect(subject.sql).to eq('where (`gems`.`author` = ? and `gems`.`created_at` > ?)')
165
+ end
166
+
167
+ context 'when the sql already contains a where' do
168
+ it 'does not append an extra where' do
169
+ subject.and.where(gems['name'].eq('mysql_framework'))
170
+ expect(subject.sql).to eq('where (`gems`.`author` = ? and `gems`.`created_at` > ?) and (`gems`.`name` = ?)')
171
+ end
172
+ end
173
+ end
174
+
175
+ describe '#and' do
176
+ it 'appends the sql for an and statement' do
177
+ subject.and
178
+ expect(subject.sql).to eq('and')
179
+ end
180
+ end
181
+
182
+ describe '#or' do
183
+ it 'appends the sql for an or statement' do
184
+ subject.or
185
+ expect(subject.sql).to eq('or')
186
+ end
187
+ end
188
+
189
+ describe '#order' do
190
+ it 'appends the sql for an order statement' do
191
+ subject.order(gems[:created_at], gems[:updated_at])
192
+ expect(subject.sql).to eq('order by `gems`.`created_at`,`gems`.`updated_at`')
193
+ end
194
+ end
195
+
196
+ describe '#order_desc' do
197
+ it 'appends the sql for an order descending statement' do
198
+ subject.order_desc(gems[:created_at], gems[:updated_at])
199
+ expect(subject.sql).to eq('order by `gems`.`created_at`,`gems`.`updated_at` desc')
200
+ end
201
+ end
202
+
203
+ describe '#limit' do
204
+ it 'appends the sql for a limit statement' do
205
+ subject.limit(10)
206
+ expect(subject.sql).to eq('limit 10')
207
+ end
208
+ end
209
+
210
+ describe '#join' do
211
+ it 'appends the sql for a join statement' do
212
+ subject.join(versions)
213
+ expect(subject.sql).to eq('join `versions`')
214
+ end
215
+ end
216
+
217
+ describe '#on' do
218
+ it 'appends the sql for the on statement' do
219
+ subject.on(gems[:id], versions[:gem_id])
220
+ expect(subject.sql).to eq('on `gems`.`id` = `versions`.`gem_id`')
221
+ end
222
+ end
223
+ end