mysql_framework 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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