Completed
Pull Request — 3 (#7945)
by Loz
09:17
created

testSortFieldBecomeIndexes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 49
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 35
nc 1
nop 0
dl 0
loc 49
rs 9.2258
c 0
b 0
f 0
1
<?php
2
3
class DataObjectSchemaGenerationTest extends SapphireTest {
4
	protected $extraDataObjects = array(
5
		'DataObjectSchemaGenerationTest_DO',
6
		'DataObjectSchemaGenerationTest_IndexDO'
7
	);
8
9
	public function setUpOnce() {
10
11
		// enable fulltext option on this table
12
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'create_table_options',
13
			array(MySQLSchemaManager::ID => 'ENGINE=MyISAM'));
14
15
		parent::setUpOnce();
16
	}
17
18
	/**
19
	 * Check that once a schema has been generated, then it doesn't need any more updating
20
	 */
21
	public function testFieldsDontRerequestChanges() {
22
		$schema = DB::get_schema();
23
		$test = $this;
24
		DB::quiet();
25
26
		// Table will have been initially created by the $extraDataObjects setting
27
28
		// Verify that it doesn't need to be recreated
29
		$schema->schemaUpdate(function() use ($test, $schema) {
30
			$obj = new DataObjectSchemaGenerationTest_DO();
31
			$obj->requireTable();
32
			$needsUpdating = $schema->doesSchemaNeedUpdating();
33
			$schema->cancelSchemaUpdate();
34
			$test->assertFalse($needsUpdating);
35
		});
36
	}
37
38
	/**
39
	 * Check that updates to a class fields are reflected in the database
40
	 */
41
	public function testFieldsRequestChanges() {
42
		$schema = DB::get_schema();
43
		$test = $this;
44
		DB::quiet();
45
46
		// Table will have been initially created by the $extraDataObjects setting
47
48
		// Let's insert a new field here
49
		Config::inst()->update('DataObjectSchemaGenerationTest_DO', 'db', array(
50
			'SecretField' => 'Varchar(100)'
51
		));
52
53
		// Verify that the above extra field triggered a schema update
54
		$schema->schemaUpdate(function() use ($test, $schema) {
55
			$obj = new DataObjectSchemaGenerationTest_DO();
56
			$obj->requireTable();
57
			$needsUpdating = $schema->doesSchemaNeedUpdating();
58
			$schema->cancelSchemaUpdate();
59
			$test->assertTrue($needsUpdating);
60
		});
61
	}
62
63
	/**
64
	 * Check that indexes on a newly generated class do not subsequently request modification
65
	 */
66
	public function testIndexesDontRerequestChanges() {
67
		$schema = DB::get_schema();
68
		$test = $this;
69
		DB::quiet();
70
71
		// Table will have been initially created by the $extraDataObjects setting
72
73
		// Verify that it doesn't need to be recreated
74
		$schema->schemaUpdate(function() use ($test, $schema) {
75
			$obj = new DataObjectSchemaGenerationTest_IndexDO();
76
			$obj->requireTable();
77
			$needsUpdating = $schema->doesSchemaNeedUpdating();
78
			$schema->cancelSchemaUpdate();
79
			$test->assertFalse($needsUpdating);
80
		});
81
82
		// Test with alternate index format, although these indexes are the same
83
		Config::inst()->remove('DataObjectSchemaGenerationTest_IndexDO', 'indexes');
84
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes',
85
			Config::inst()->get('DataObjectSchemaGenerationTest_IndexDO', 'indexes_alt')
86
		);
87
88
		// Verify that it still doesn't need to be recreated
89
		$schema->schemaUpdate(function() use ($test, $schema) {
90
			$obj2 = new DataObjectSchemaGenerationTest_IndexDO();
91
			$obj2->requireTable();
92
			$needsUpdating = $schema->doesSchemaNeedUpdating();
93
			$schema->cancelSchemaUpdate();
94
			$test->assertFalse($needsUpdating);
95
		});
96
	}
97
98
	/**
99
	 * Check that updates to a dataobject's indexes are reflected in DDL
100
	 */
101
	public function testIndexesRerequestChanges() {
102
		$schema = DB::get_schema();
103
		$test = $this;
104
		DB::quiet();
105
106
		// Table will have been initially created by the $extraDataObjects setting
107
108
		// Update the SearchFields index here
109
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes', array(
110
			'SearchFields' => array(
111
				'value' => 'Title'
112
			)
113
		));
114
115
		// Verify that the above index change triggered a schema update
116
		$schema->schemaUpdate(function() use ($test, $schema) {
117
			$obj = new DataObjectSchemaGenerationTest_IndexDO();
118
			$obj->requireTable();
119
			$needsUpdating = $schema->doesSchemaNeedUpdating();
120
			$schema->cancelSchemaUpdate();
121
			$test->assertTrue($needsUpdating);
122
		});
123
	}
124
125
	/**
126
	 * Tests the generation of the ClassName spec and ensure it's not unnecessarily influenced
127
	 * by the order of classnames of existing records
128
	 */
129
	public function testClassNameSpecGeneration() {
130
131
		// Test with blank entries
132
		DataObject::clear_classname_spec_cache();
133
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
134
		$this->assertEquals(
135
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
136
			$fields['ClassName']
137
		);
138
139
		// Test with instance of subclass
140
		$item1 = new DataObjectSchemaGenerationTest_IndexDO();
141
		$item1->write();
142
		DataObject::clear_classname_spec_cache();
143
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
144
		$this->assertEquals(
145
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
146
			$fields['ClassName']
147
		);
148
		$item1->delete();
149
150
		// Test with instance of main class
151
		$item2 = new DataObjectSchemaGenerationTest_DO();
152
		$item2->write();
153
		DataObject::clear_classname_spec_cache();
154
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
155
		$this->assertEquals(
156
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
157
			$fields['ClassName']
158
		);
159
		$item2->delete();
160
161
		// Test with instances of both classes
162
		$item1 = new DataObjectSchemaGenerationTest_IndexDO();
163
		$item1->write();
164
		$item2 = new DataObjectSchemaGenerationTest_DO();
165
		$item2->write();
166
		DataObject::clear_classname_spec_cache();
167
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
168
		$this->assertEquals(
169
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
170
			$fields['ClassName']
171
		);
172
		$item1->delete();
173
		$item2->delete();
174
	}
175
176
    public function testSortFieldBecomeIndexes()
177
    {
178
        $object = new DataObjectSchemaGenerationTest_Sorted();
179
        $indexes = $object->databaseIndexes();
180
        $this->assertArrayHasKey('Sort', $indexes);
181
        $this->assertTrue($indexes['Sort']);
182
183
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', 'Sort ASC');
184
        $indexes = $object->databaseIndexes();
185
        $this->assertArrayHasKey('Sort', $indexes);
186
        $this->assertTrue($indexes['Sort']);
187
188
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', 'Sort DESC');
189
        $indexes = $object->databaseIndexes();
190
        $this->assertArrayHasKey('Sort', $indexes);
191
        $this->assertTrue($indexes['Sort']);
192
193
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"Sort" DESC');
194
        $indexes = $object->databaseIndexes();
195
        $this->assertArrayHasKey('Sort', $indexes);
196
        $this->assertTrue($indexes['Sort']);
197
198
199
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"DataObjectSchemaGenerationTest_Sorted"."Sort" ASC');
200
        $indexes = $object->databaseIndexes();
201
        $this->assertArrayHasKey('Sort', $indexes);
202
        $this->assertTrue($indexes['Sort']);
203
204
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"Sort" DESC, "Title" ASC');
205
        $indexes = $object->databaseIndexes();
206
        $this->assertArrayHasKey('Sort', $indexes);
207
        $this->assertTrue($indexes['Sort']);
208
        $this->assertArrayHasKey('Title', $indexes);
209
        $this->assertTrue($indexes['Title']);
210
211
        // make sure that specific indexes aren't overwritten
212
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'indexes', array(
213
            'Sort' => 'unique',
214
        ));
215
216
        $indexes = $object->databaseIndexes();
217
        $this->assertArrayHasKey('Sort', $indexes);
218
        $this->assertEquals('unique', $indexes['Sort']);
219
220
        // make sure Text fields don't get indexes automatically - these can be db-driver dependent
221
		$object = new DataObjectSchemaGenerationTest_SortedByText();
222
		$indexes = $object->databaseIndexes();
223
		$this->assertArrayNotHasKey('Description', $indexes);
224
	}
225
}
226
227
class DataObjectSchemaGenerationTest_DO extends DataObject implements TestOnly {
228
	private static $db = array(
229
		'Enum1' => 'Enum("A, B, C, D","")',
230
		'Enum2' => 'Enum("A, B, C, D","A")',
231
		'NumberField' => 'Decimal',
232
		'FloatingField' => 'Decimal(10,3,1.1)',
233
		'TextValue' => 'Varchar',
234
		'Date' => 'SS_Datetime',
235
		'MyNumber' => 'Int'
236
	);
237
}
238
239
240
class DataObjectSchemaGenerationTest_IndexDO extends DataObjectSchemaGenerationTest_DO implements TestOnly {
241
	private static $db = array(
242
		'Title' => 'Varchar(255)',
243
		'Content' => 'Text'
244
	);
245
246
	private static $indexes = array(
247
		'NameIndex' => 'unique ("Title")',
248
		'SearchFields' => array(
249
			'type' => 'fulltext',
250
			'name' => 'SearchFields',
251
			'value' => '"Title","Content"'
252
		)
253
	);
254
255
	/** @config */
256
	private static $indexes_alt = array(
257
		'NameIndex' => array(
258
			'type' => 'unique',
259
			'name' => 'NameIndex',
260
			'value' => '"Title"'
261
		),
262
		'SearchFields' => 'fulltext ("Title","Content")'
263
	);
264
}
265
266
class DataObjectSchemaGenerationTest_Sorted extends DataObject implements TestOnly {
267
    private static $db = array(
268
        'Title' => 'Varchar',
269
        'Sort' => 'Int',
270
    );
271
272
    private static $default_sort = "Sort";
273
}
274
275
class DataObjectSchemaGenerationTest_SortedByText extends DataObject implements TestOnly {
276
	private static $db = array(
277
		'Title' => 'Varchar',
278
		'Description' => 'Text',
279
		'Sort' => 'Int',
280
	);
281
282
	private static $default_sort = "Description";
283
}
284