Completed
Push — master ( 819332...0b0cf9 )
by cam
01:42
created
ecrire/tests/Sql/SqlSchemaTableTest.php 1 patch
Indentation   +685 added lines, -685 removed lines patch added patch discarded remove patch
@@ -10,689 +10,689 @@
 block discarded – undo
10 10
 
11 11
 class SqlSchemaTableTest extends TestCase
12 12
 {
13
-	public static function setUpBeforeClass(): void
14
-	{
15
-		find_in_path('base/abstract_sql.php', '', true);
16
-	}
17
-
18
-	#[DataProvider('providerTablesData')]
19
-	public function testDropTablesSetup($table, $desc, $data): void
20
-	{
21
-		$this->assertTrue(sql_drop_table($table, true));
22
-	}
23
-
24
-	#[Depends('testDropTablesSetup')]
25
-	#[DataProvider('providerTablesData')]
26
-	public function testCreateTables($table, $desc, $data): void
27
-	{
28
-		$this->assertTrue(sql_create($table, $desc['field'], $desc['key']));
29
-	}
30
-
31
-	/**
32
-	 * Creation/suppression/analyse de tables dans la base de donnee
33
-	 *
34
-	 * Permet de verifier que
35
-	 * - tous les champs sont correctement ajoutes
36
-	 * - que les PRIMARY sont pris en compte
37
-	 * - que les KEY sont prises en compte
38
-	 */
39
-	#[Depends('testCreateTables')]
40
-	#[DataProvider('providerTablesData')]
41
-	public function testShowTable($table, $desc, $data) {
42
-		// lire la structure de la table
43
-		// la structure doit avoir le meme nombre de champs et de cle
44
-		// attention : la primary key DOIT etre dans les cle aussi
45
-		$_desc = sql_showtable($table);
46
-		$this->assertCount(count($desc['field']), $_desc['field']);
47
-		$this->assertCount($desc['nb_key_attendues'], $_desc['key']);
48
-	}
49
-
50
-	#[Depends('testCreateTables')]
51
-	#[DataProvider('providerTablesData')]
52
-	public function testInsertData($table, $desc, $data) {
53
-		$this->assertNotFalse(sql_insertq_multi($table, $data));
54
-		$this->assertEquals(count($data), sql_countsel($table));
55
-	}
56
-
57
-	/**
58
-	 * Teste que le champ "maj" s'actualise bien sur les update
59
-	 * ainsi que les autres champs !
60
-	 *
61
-	 * utilise sql_quote, sql_getfetsel, sql_update et sql_updateq.
62
-	 */
63
-	#[Depends('testInsertData')]
64
-	public function testMajTimestamp() {
65
-		$table = 'spip_test_tintin';
66
-		$where1 = 'id_tintin=' . sql_quote(1);
67
-		$where2 = 'id_tintin=' . sql_quote(2);
68
-
69
-		// lecture du timestamp actuel
70
-		$maj1 = sql_getfetsel('maj', $table, $where1);
71
-		$this->assertNotEmpty($maj1, "Le champ 'maj' n'a vraisemblablement pas recu de timestamp à l'insertion");
72
-
73
-		$maj2 = sql_getfetsel('maj', $table, $where2);
74
-		$this->assertNotEmpty($maj2, "Le champ 'maj' n'a vraisemblablement pas recu de timestamp à l'insertion");
75
-
76
-		// 1s de plus, sinon le timestamp ne change pas !
77
-		sleep(1);
78
-
79
-		// update
80
-		$texte = 'nouveau texte';
81
-		sql_update($table, [
82
-			'un_texte' => sql_quote($texte),
83
-		], $where1);
84
-
85
-		// comparaison timastamp
86
-		$maj_update = sql_getfetsel('maj', $table, $where1);
87
-		$this->assertNotEmpty($maj_update, "Le champ 'maj' est vide à l’update");
88
-		$this->assertNotFalse(strtotime($maj_update), "Le champ 'maj' est incorrect à l’update");
89
-		$this->assertNotEquals($maj1, $maj_update, "Le champ 'maj' n'a vraisemblablement pas été mis a jour lors de l'update");
90
-
91
-		// comparaison texte
92
-		$texte_update = sql_getfetsel('un_texte', $table, $where1);
93
-		$this->assertNotEmpty($texte_update, "Le champ 'un_texte' est vide à l’update");
94
-		$this->assertEquals($texte, $texte_update, "Le champ 'un_texte' n'est pas correctement rempli a l'update");
95
-
96
-		// idem avec updateq
97
-		$texte = 'encore un nouveau texte';
98
-		sql_updateq($table, [
99
-			'un_texte' => $texte,
100
-		], $where2);
101
-
102
-		// comparaison timastamp
103
-		$maj_updateq = sql_getfetsel('maj', $table, $where2);
104
-		$this->assertNotEmpty($maj_updateq, "Le champ 'maj' est vide à l’updateq");
105
-		$this->assertNotFalse(strtotime($maj_updateq), "Le champ 'maj' est incorrect à l’updateq");
106
-		$this->assertNotEquals($maj1, $maj_updateq, "Le champ 'maj' n'a vraisemblablement pas été mis a jour lors de l'updateq");
107
-
108
-		// comparaison texte
109
-		$texte_updateq = sql_getfetsel('un_texte', $table, $where2);
110
-		$this->assertNotEmpty($texte_updateq, "Le champ 'un_texte' est vide à l’updateq");
111
-		$this->assertEquals($texte, $texte_updateq, "Le champ 'un_texte' n'est pas correctement rempli a l'updateq");
112
-	}
113
-
114
-	/**
115
-	 * Selections diverses selon criteres
116
-	 */
117
-	#[Depends('testInsertData')]
118
-	public function testSelections() {
119
-		$data = $this->providerTablesData()['tintin'][2];
120
-
121
-		$res = sql_select('*', 'spip_test_tintin');
122
-		$this->assertNotFalse($res);
123
-		$this->assertEquals(count($data), sql_count($res), 'sql_count() ne renvoie pas la valeur attendue');
124
-
125
-		// selection float
126
-		$res = sql_select('*', 'spip_test_tintin', ['un_double>' . sql_quote(3)]);
127
-		$n = count(array_filter($data, fn ($entry) => $entry['un_double'] > 3));
128
-		$this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur un float');
129
-
130
-		// selection REGEXP
131
-		$res = sql_select('*', 'spip_test_tintin', ['un_varchar REGEXP ' . sql_quote('^De')]);
132
-		$n = count(array_filter($data, fn ($entry) => str_starts_with($entry['un_varchar'], 'De')));
133
-		$this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur une REGEXP');
134
-
135
-		// selection LIKE
136
-		$res = sql_select('*', 'spip_test_tintin', ['un_varchar LIKE ' . sql_quote('De%')]);
137
-		$this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur un LIKE');
138
-
139
-		// selection array(champs)
140
-		$res = sql_fetsel(['id_tintin', 'un_varchar'], 'spip_test_tintin');
141
-		$this->assertArrayHasKey('id_tintin', $res);
142
-		$this->assertArrayHasKey('un_varchar', $res);
143
-
144
-		// selection array(champs=>alias)
145
-		$res = sql_fetsel(['id_tintin AS id', 'un_varchar AS vchar'], 'spip_test_tintin');
146
-		$this->assertArrayHasKey('id', $res);
147
-		$this->assertArrayHasKey('vchar', $res);
148
-	}
149
-
150
-
151
-	#[Depends('testInsertData')]
152
-	public function testSelectionsMulti() {
153
-		$data = $this->providerTablesData()['milou'][2];
154
-
155
-		// selection avec sql_multi
156
-		$res = sql_select(['id_milou', sql_multi('grrrr', 'fr')], 'spip_test_milou', orderby: 'multi');
157
-		$this->assertNotFalse($res);
158
-		$this->assertEquals(count($data), sql_count($res), 'sql_multi mal interprété');
159
-		$this->assertEquals(3, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
160
-		$this->assertEquals(2, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
161
-		$this->assertEquals(1, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
162
-
163
-		// le bon texte avec multi
164
-		foreach (
165
-			[
166
-				'fr' => 'Crac',
167
-				'en' => 'Krack',
168
-			] as $lg => $res
169
-		) {
170
-			$multi = sql_getfetsel(sql_multi('grrrr', $lg), 'spip_test_milou', 'id_milou=' . sql_quote(2));
171
-			$this->assertEquals($res, $multi, 'sql_multi mal rendu');
172
-		}
173
-
174
-		// le bon texte avec multi et accents
175
-		foreach (
176
-			[
177
-				'fr' => 'Aérien',
178
-				'en' => 'Aérieny',
179
-			] as $lg => $res
180
-		) {
181
-			$multi = sql_getfetsel(sql_multi('alcool', $lg), 'spip_test_haddock', 'id_haddock=' . sql_quote(2));
182
-			$this->assertEquals($res, $multi, 'sql_multi avec accents, mal rendu');
183
-		}
184
-
185
-		// le bon texte avec multi et debut et fin de chaine
186
-		foreach (
187
-			[
188
-				'fr' => 'Un début de chaine : Vinasse, et [la fin]',
189
-				'en' => 'Un début de chaine : Vinassy, et [la fin]',
190
-				'de' => 'Un début de chaine : Vinasse, et [la fin]',
191
-			] as $lg => $res
192
-		) {
193
-			$multi = sql_getfetsel(sql_multi('alcool', $lg), 'spip_test_haddock', 'id_haddock=' . sql_quote(4));
194
-			$this->assertEquals($res, $multi, 'sql_multi avec crochets, mal rendu');
195
-		}
196
-	}
197
-
198
-
199
-
200
-	/**
201
-	 * Selections diverses entre plusieurs tables
202
-	 */
203
-	#[Depends('testInsertData')]
204
-	public function testSelectionsEntreTable() {
205
-		// selection 2 tables
206
-		// ! nombre en dur !
207
-		$res = sql_select(
208
-			['spip_test_tintin.id_tintin', 'spip_test_milou.id_milou'],
209
-			['spip_test_tintin', 'spip_test_milou'],
210
-			['spip_test_milou.id_tintin=spip_test_tintin.id_tintin']
211
-		);
212
-		$this->assertEquals(3, sql_count($res), 'Echec sélection');
213
-
214
-		// selection 2 tables avec alias =>
215
-		// ! nombre en dur !
216
-		$res = sql_select(
217
-			['a.id_tintin AS x', 'b.id_milou AS y'],
218
-			[
219
-				'a' => 'spip_test_tintin',
220
-				'b' => 'spip_test_milou',
221
-			],
222
-			['a.id_tintin=b.id_tintin']
223
-		);
224
-		$this->assertEquals(3, sql_count($res), 'Echec sélection avec alias de colonnes et tables');
225
-
226
-		// selection 2 tables avec alias AS
227
-		// ! nombre en dur !
228
-		$res = sql_select(
229
-			['a.id_tintin AS x', 'b.id_milou AS y'],
230
-			['spip_test_tintin AS a', 'spip_test_milou AS b'],
231
-			['a.id_tintin=b.id_tintin']
232
-		);
233
-		$this->assertEquals(3, sql_count($res));
234
-
235
-		// selection 2 tables avec INNER JOIN + ON
236
-		// ! nombre en dur !
237
-		$res = sql_select(
238
-			['a.id_tintin AS x', 'b.id_milou AS y'],
239
-			['spip_test_tintin AS a INNER JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)']
240
-		);
241
-		$this->assertEquals(3, sql_count($res), 'Echec sélection avec INNER JOIN + ON');
242
-
243
-		// selection 2 tables avec LEFT JOIN + ON
244
-		// ! nombre en dur !
245
-		$res = sql_select(
246
-			['a.id_tintin AS x', 'b.id_milou AS y'],
247
-			['spip_test_tintin AS a LEFT JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)']
248
-		);
249
-		$this->assertEquals(4, sql_count($res), 'Echec sélection avec LEFT JOIN + ON');
250
-
251
-
252
-		// selection 2 tables avec jointure INNER JOIN + USING
253
-		// ! nombre en dur !
254
-		// SQLite 2 se plante : il ne connait pas USING (enleve de la requete,
255
-		// et du coup ne fait pas correctement la jointure)
256
-		$res = sql_select(
257
-			['a.id_tintin AS x', 'b.id_milou AS y'],
258
-			['spip_test_tintin AS a INNER JOIN spip_test_milou AS b USING (id_tintin)']
259
-		);
260
-		$this->assertEquals(3, sql_count($res), 'Echec sélection avec INNER JOIN + USING');
261
-	}
262
-
263
-
264
-	/**
265
-	 * Selections mathematiques
266
-	 */
267
-	#[Depends('testInsertData')]
268
-	function testMathFunctions() {
269
-		foreach (
270
-			[
271
-				'COUNT' => 3,
272
-				'SUM' => 9000,
273
-				'AVG' => 3000,
274
-			] as $func => $expected
275
-		) {
276
-			$nb = sql_getfetsel("{$func}(un_int) AS nb", ['spip_test_tintin']);
277
-			$this->assertEquals($expected, $nb, "Selection {$func} en echec");
278
-		}
279
-
280
-		foreach (
281
-			[
282
-				'EXP(0)' => exp(0),
283
-				'ROUND(3.56)' => round(3.56),
284
-				'ROUND(3.5684,2)' => round(3.5684, 2),
285
-				'SQRT(9)' => 3,
286
-				//'1/2'=>(0), // Le standard SQL : entier divise par entier = division entiere (pas trouve la reference)
287
-				'1.0/2' => (1 / 2), // Le standart SQL : reel divise par entier = reel
288
-				//'4/3'=>1,
289
-				'ROUND(4.0/3,2)' => round(4 / 3, 2),
290
-				'1.5/2' => (1.5 / 2),
291
-				'2.0/2' => (2.0 / 2),
292
-				'2/2' => (2 / 2),
293
-				'md5(8)' => md5('8'),
294
-				'md5(' . sql_quote('a') . ')' => md5('a'),
295
-			] as $func => $expected
296
-		) {
297
-			$nb = sql_getfetsel("{$func} AS nb", ['spip_test_tintin'], ['id_tintin=' . sql_quote(1)]);
298
-			$this->assertEquals($expected, $nb, "Selection {$func} en echec");
299
-		}
300
-	}
301
-
302
-	/**
303
-	 * Selections mathematiques
304
-	 */
305
-	#[Depends('testInsertData')]
306
-
307
-	function testStringFunctions() {
308
-		foreach (
309
-			[
310
-				'CONCAT(' . sql_quote('cou') . ',' . sql_quote('cou') . ')' => 'coucou',
311
-				'CONCAT(' . sql_quote('cou,') . ',' . sql_quote('cou') . ')' => 'cou,cou',
312
-			] as $func => $expected
313
-		) {
314
-			$nb = sql_getfetsel("{$func} AS nb", ['spip_test_tintin'], ['id_tintin=' . sql_quote(1)]);
315
-			$this->assertEquals($expected, $nb, "Selection {$func} en echec");
316
-		}
317
-	}
318
-
319
-	/**
320
-	 * retours des fonctions d'erreurs lors d'une requete
321
-	 */
322
-	#[Depends('testCreateTables')]
323
-
324
-	function testErrorFunctions() {
325
-		// requete sans erreur
326
-		sql_select('*', 'spip_test_tintin');
327
-		$this->assertEquals('', sql_error(), 'sql_error() non vide lors d’une requete sans erreur');
328
-		$this->assertEquals(0, sql_errno(), 'sql_errno() ne retourne pas 0 lors d’une requete sans erreur');
329
-
330
-		// requete en erreur
331
-		sql_select('*', 'spip_test_toto');
332
-		$this->assertNotEquals('', sql_error(), 'sql_error() vide lors d’une requete en erreur');
333
-		$this->assertNotEquals(0, sql_errno(), 'sql_errno() retourne 0 lors d’une requete en erreur');
334
-	}
335
-
336
-	/**
337
-	 * Update de data
338
-	 */
339
-	#[Depends('testInsertData')]
340
-	public function testUpdateData() {
341
-		// ajouter un champ
342
-		$nb = sql_getfetsel('un_bigint', 'spip_test_tintin', 'id_tintin=' . sql_quote(1));
343
-		sql_update('spip_test_tintin', [
344
-			'un_bigint' => 'un_bigint+2',
345
-		]);
346
-		$nb2 = sql_getfetsel('un_bigint', 'spip_test_tintin', 'id_tintin=' . sql_quote(1));
347
-		$this->assertEquals($nb + 2, $nb2, 'sql_update n’a pas fait l’adition !');
348
-	}
349
-
350
-	/**
351
-	 * Delete de data
352
-	 */
353
-	#[Depends('testInsertData')]
354
-
355
-	public function test_delete_data() {
356
-		$nb = sql_countsel('spip_test_tintin');
357
-		// supprimer une ligne
358
-		sql_delete('spip_test_tintin', 'id_tintin=' . sql_quote(1));
359
-		$this->assertEquals($nb - 1, sql_countsel('spip_test_tintin'), "sql_delete n’a pas supprimé la ligne");
360
-
361
-		// supprimer tout
362
-		sql_delete('spip_test_tintin');
363
-		$this->assertEquals(0, sql_countsel('spip_test_tintin'), "sql_delete n’a pas vidé la table");
364
-	}
365
-
366
-	/**
367
-	 * Alter colonne
368
-	 */
369
-	#[Depends('testCreateTables')]
370
-	function testAlterColumns() {
371
-		$table = 'spip_test_tintin';
372
-
373
-		// supprimer une colonne
374
-		sql_alter("TABLE {$table} DROP COLUMN un_bigint");
375
-		$desc = sql_showtable($table);
376
-		$this->assertIsArray($desc, 'sql_alter rate DROP COLUMN (plus de table ou sql_showtable en erreur?)');
377
-		$this->assertArrayNotHasKey('un_bigint', $desc['field']);
378
-		$this->assertArrayHasKey('un_smallint', $desc['field']);
379
-
380
-		// supprimer une colonne (sans COLUMN)
381
-		sql_alter("TABLE {$table} DROP un_smallint");
382
-		$desc = sql_showtable($table);
383
-		$this->assertIsArray($desc, 'sql_alter rate DROP sans COLUMN (plus de table ou sql_showtable en erreur?)');
384
-		$this->assertArrayNotHasKey('un_smallint', $desc['field']);
385
-
386
-		// renommer une colonne
387
-		sql_alter("TABLE {$table} CHANGE un_varchar deux_varchars VARCHAR(30) NOT NULL DEFAULT ''");
388
-		$desc = sql_showtable($table);
389
-		$this->assertIsArray($desc, 'sql_alter rate CHANGE (plus de table ou sql_showtable en erreur?)');
390
-		$this->assertArrayHasKey('deux_varchars', $desc['field']);
391
-		$this->assertArrayNotHasKey('un_varchar', $desc['field']);
392
-
393
-		// changer le type d'une colonne
394
-		$table = 'spip_test_milou';
395
-		sql_alter("TABLE {$table} MODIFY schtroumf TEXT NOT NULL DEFAULT ''");
396
-		$desc = sql_showtable($table);
397
-		$this->assertIsArray($desc, 'sql_alter rate MODIFY (plus de table ou sql_showtable en erreur?)');
398
-		$this->assertArrayHasKey('schtroumf', $desc['field'], 'sql_alter rate MODIFY varchar en text');
399
-		$this->assertStringContainsStringIgnoringCase('TEXT', $desc['field']['schtroumf'], 'sql_alter rate MODIFY varchar en text');
400
-
401
-		// ajouter des colonnes
402
-		sql_alter("TABLE {$table} ADD COLUMN houba BIGINT(21) NOT NULL DEFAULT '0'");
403
-		$desc = sql_showtable($table);
404
-		$this->assertIsArray($desc, 'sql_alter rate ADD COLUMN (plus de table ou sql_showtable en erreur?)');
405
-		$this->assertArrayHasKey('houba', $desc['field'], 'sql_alter rate ADD COLUMN');
406
-		$this->assertStringContainsStringIgnoringCase('INT', $desc['field']['houba'], 'sql_alter rate ADD COLUMN');
407
-
408
-		// ajouter des colonnes avec "AFTER"
409
-		sql_alter("TABLE {$table} ADD COLUMN hop BIGINT(21) NOT NULL DEFAULT '0' AFTER id_tintin");
410
-		$desc = sql_showtable($table);
411
-		$this->assertIsArray($desc, 'sql_alter rate ADD COLUMN avec AFTER (plus de table ou sql_showtable en erreur?)');
412
-		$this->assertArrayHasKey('hop', $desc['field'], 'sql_alter rate ADD COLUMN avec AFTER');
413
-		$this->assertStringContainsStringIgnoringCase('INT', $desc['field']['hop'], 'sql_alter rate ADD COLUMN avec AFTER');
414
-	}
415
-
416
-
417
-	/**
418
-	 * Renomme table
419
-	 */
420
-	#[Depends('testCreateTables')]
421
-
422
-	public function testAlterRenameTable() {
423
-
424
-		$table_before = 'spip_test_tintin';
425
-		$table_after = 'spip_test_castafiore';
426
-		sql_drop_table($table_after, true);
427
-		$this->assertEmpty(sql_showtable($table_after));
428
-		$this->assertIsArray(sql_showtable($table_before));
429
-
430
-		// renommer une table
431
-		sql_alter("TABLE {$table_before} RENAME {$table_after}");
432
-		$this->assertEmpty(sql_showtable($table_before));
433
-		$this->assertIsArray(sql_showtable($table_after));
434
-
435
-		sql_alter("TABLE {$table_after} RENAME {$table_before}");
436
-		$this->assertEmpty(sql_showtable($table_after));
437
-		$this->assertIsArray(sql_showtable($table_before));
438
-	}
439
-
440
-
441
-	/**
442
-	 * pointer l'index
443
-	 */
444
-	#[Depends('testCreateTables')]
445
-
446
-	public function testAlterIndex() {
447
-		$table = 'spip_test_milou';
448
-
449
-		// supprimer un index
450
-		sql_alter("TABLE {$table} DROP INDEX sons");
451
-		$desc = sql_showtable($table);
452
-		$this->assertIsArray($desc, 'sql_alter rate DROP INDEX sons (plus de table ou sql_showtable en erreur?)');
453
-		$this->assertArrayNotHasKey('KEY sons', $desc['key'], 'sql_alter rate DROP INDEX sons');
454
-
455
-		// ajouter un index simple
456
-		sql_alter("TABLE {$table} ADD INDEX (wouaf)");
457
-		$desc = sql_showtable($table);
458
-		$this->assertIsArray($desc, 'sql_alter rate ADD INDEX (wouaf) (plus de table ou sql_showtable en erreur?)');
459
-		$this->assertArrayHasKey('KEY wouaf', $desc['key'], 'sql_alter rate ADD INDEX (wouaf)');
460
-
461
-		// ajouter un index nomme
462
-		sql_alter("TABLE {$table} ADD INDEX pluie (grrrr)");
463
-		$desc = sql_showtable($table);
464
-		$this->assertIsArray($desc, 'sql_alter rate ADD INDEX pluie (grrrr) (plus de table ou sql_showtable en erreur?)');
465
-		$this->assertArrayHasKey('KEY pluie', $desc['key'], 'sql_alter rate ADD INDEX pluie (grrrr)');
466
-
467
-		// supprimer un index
468
-		sql_alter("TABLE {$table} DROP INDEX pluie");
469
-		$desc = sql_showtable($table);
470
-		$this->assertIsArray($desc, 'sql_alter rate DROP INDEX pluie (plus de table ou sql_showtable en erreur?)');
471
-		$this->assertArrayNotHasKey('KEY pluie', $desc['key'], 'sql_alter rate DROP INDEX pluie');
472
-
473
-		// ajouter un index nomme double
474
-		sql_alter("TABLE {$table} ADD INDEX dring (grrrr, wouaf)");
475
-		$desc = sql_showtable($table);
476
-		$this->assertIsArray($desc, 'sql_alter rate ADD INDEX dring (grrrr, wouaf) (plus de table ou sql_showtable en erreur?)');
477
-		$this->assertArrayHasKey('KEY dring', $desc['key'], 'sql_alter rate ADD INDEX dring (grrrr, wouaf)');
478
-	}
479
-
480
-
481
-	/**
482
-	 * dezinguer la primary
483
-	 */
484
-	#[Depends('testCreateTables')]
485
-
486
-	public function testAlterPrimary() {
487
-		$table = 'spip_test_kirikou';
488
-		sql_drop_table($table, true);
489
-
490
-		// creer une table pour jouer
491
-		sql_create(
492
-			$table,
493
-			[
494
-				'un' => 'INTEGER NOT NULL',
495
-				'deux' => 'INTEGER NOT NULL',
496
-				'trois' => 'INTEGER NOT NULL',
497
-			],
498
-			[
499
-				'PRIMARY KEY' => 'un',
500
-			]
501
-		);
502
-
503
-		// supprimer une primary
504
-		$desc = sql_showtable($table);
505
-		sql_alter("TABLE {$table} DROP PRIMARY KEY");
506
-		$desc = sql_showtable($table);
507
-		$this->assertIsArray($desc, 'sql_alter rate DROP PRIMARY KEY (plus de table ou sql_showtable en erreur?)');
508
-		$this->assertArrayNotHasKey('PRIMARY KEY', $desc['key'], 'sql_alter rate DROP PRIMARY KEY');
509
-
510
-		// ajouter une primary
511
-		$desc = sql_showtable($table);
512
-		sql_alter("TABLE {$table} ADD PRIMARY KEY (deux, trois)");
513
-		$desc = sql_showtable($table);
514
-		$this->assertIsArray($desc, 'sql_alter rate ADD PRIMARY KEY (plus de table ou sql_showtable en erreur?)');
515
-		$this->assertArrayHasKey('PRIMARY KEY', $desc['key'], 'sql_alter rate ADD PRIMARY KEY');
516
-
517
-		sql_drop_table($table, true);
518
-	}
519
-
520
-	/**
521
-	 * Alter colonne
522
-	 */
523
-	#[Depends('testAlterColumns')]
524
-	#[Depends('testAlterIndex')]
525
-
526
-	function testAlterMultiple() {
527
-		$table = 'spip_test_milou';
528
-
529
-		// supprimer des colonnes
530
-		sql_alter("TABLE {$table} DROP INDEX dring, DROP COLUMN wouaf, DROP COLUMN grrrr");
531
-		$desc = sql_showtable($table);
532
-		$this->assertIsArray($desc, 'sql_alter rate DROP multiples (plus de table ou sql_showtable en erreur?)');
533
-		$this->assertArrayNotHasKey('waouf', $desc['field'], 'sql_alter rate DROP multiples');
534
-		$this->assertArrayNotHasKey('grrrr', $desc['field'], 'sql_alter rate DROP multiples');
535
-		$this->assertArrayNotHasKey('KEY dring', $desc['key'], 'sql_alter rate DROP multiples');
536
-
537
-		// ajouter des colonnes
538
-		sql_alter("TABLE {$table} ADD COLUMN a INT, ADD COLUMN b INT, ADD COLUMN c INT, ADD INDEX abc (a,b,c)");
539
-		$desc = sql_showtable($table);
540
-		$this->assertIsArray($desc, 'sql_alter rate ADD multiples (plus de table ou sql_showtable en erreur?)');
541
-		$this->assertArrayHasKey('a', $desc['field'], 'sql_alter rate ADD multiples');
542
-		$this->assertArrayHasKey('b', $desc['field'], 'sql_alter rate ADD multiples');
543
-		$this->assertArrayHasKey('c', $desc['field'], 'sql_alter rate ADD multiples');
544
-		$this->assertArrayHasKey('KEY abc', $desc['key'], 'sql_alter rate ADD multiples');
545
-	}
546
-
547
-	#[Depends('testCreateTables')]
548
-	#[DataProvider('providerTablesData')]
549
-	public function testDropTables($table, $desc, $data): void
550
-	{
551
-		$this->assertTrue(sql_drop_table($table, false));
552
-	}
553
-
554
-	/**
555
-	 * Description des tables & données de tests
556
-	 */
557
-	public static function providerTablesData(): array
558
-	{
559
-		return [
560
-			'tintin' => [
561
-				'spip_test_tintin',
562
-				[
563
-					'field' => [
564
-						"id_tintin" => "INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY",
565
-						"un_bigint" => "BIGINT(21) NOT NULL DEFAULT '0'",
566
-						"un_int" => "BIGINT(21) NOT NULL DEFAULT '0'",
567
-						"un_smallint" => "SMALLINT(3) NOT NULL DEFAULT '0'",
568
-						"un_double" => "DOUBLE NOT NULL DEFAULT '0'",
569
-						"un_tinyint" => "TINYINT(2) NOT NULL DEFAULT '0'",
570
-						"un_varchar" => "VARCHAR(30) NOT NULL DEFAULT ''",
571
-						"un_texte" => "TEXT NOT NULL DEFAULT ''",
572
-						"maj" => "TIMESTAMP"
573
-					],
574
-					'key' => [
575
-
576
-					],
577
-					'nb_key_attendues' => 1 // attention : la primary key DOIT etre dans les cle aussi
578
-				],
579
-				[
580
-					[
581
-						"id_tintin" => 1,
582
-						"un_bigint" => 30000,
583
-						"un_int" => 2000,
584
-						"un_smallint" => 40,
585
-						"un_double" => 2.58,
586
-						"un_tinyint" => 8,
587
-						"un_varchar" => "Premier varchar",
588
-						"un_texte" => "Premier texte",
589
-						//"maj" => "" // doit se remplir automatiquement
590
-					],
591
-					[
592
-						"id_tintin" => 2,
593
-						"un_bigint" => 40000,
594
-						"un_int" => 3000,
595
-						"un_smallint" => 50,
596
-						"un_double" => 3.58,
597
-						"un_tinyint" => 9,
598
-						"un_varchar" => "Deuxieme varchar",
599
-						"un_texte" => "Second texte",
600
-						//"maj" => "" // doit se remplir automatiquement
601
-					],
602
-					[
603
-						"id_tintin" => 3,
604
-						"un_bigint" => 60000,
605
-						"un_int" => 4000,
606
-						"un_smallint" => 70,
607
-						"un_double" => 8.58,
608
-						"un_tinyint" => 3,
609
-						"un_varchar" => "Troisieme varchar",
610
-						"un_texte" => "Troisieme texte",
611
-						//"maj" => "" // doit se remplir automatiquement
612
-					],
613
-				],
614
-
615
-			],
616
-			'milou' => [
617
-				'spip_test_milou',
618
-				[
619
-					'field' => [
620
-						"id_milou" => "INTEGER NOT NULL AUTO_INCREMENT",
621
-						"id_tintin" => "INTEGER NOT NULL",
622
-						"un_enum" => "ENUM('blanc','noir') NOT NULL DEFAULT 'blanc'",
623
-						"wouaf" => "VARCHAR(80) NOT NULL DEFAULT ''",
624
-						"grrrr" => "VARCHAR(80) NOT NULL DEFAULT ''",
625
-						"schtroumf" => "VARCHAR(80) NOT NULL DEFAULT ''",
626
-						"maj" => "TIMESTAMP"
627
-					],
628
-					'key' => [
629
-						"PRIMARY KEY" => "id_milou",
630
-						"KEY id_tintin" => "id_tintin",
631
-						"KEY sons" => "wouaf, grrrr",
632
-					],
633
-					'nb_key_attendues' => 3 // attention : la primary key DOIT etre dans les cle aussi
634
-				],
635
-				[
636
-					[
637
-						"id_milou" => 1,
638
-						"id_tintin" => 1,
639
-						"un_enum" => "blanc",
640
-						"wouaf" => "Warf !!",
641
-						"grrrr" => "Grogne !",
642
-						// "maj" => "" // doit se remplir automatiquement
643
-					],
644
-					[
645
-						"id_milou" => 2,
646
-						"id_tintin" => 1,
647
-						"un_enum" => "noir",
648
-						"wouaf" => "Wouf",
649
-						"grrrr" => "<multi>[fr]Crac[en]Krack</multi>",
650
-						// "maj" => "" // doit se remplir automatiquement
651
-					],
652
-					[
653
-						"id_milou" => 3,
654
-						"id_tintin" => 2,
655
-						"un_enum" => "blanc",
656
-						"wouaf" => "Wif",
657
-						"grrrr" => "Ahrg",
658
-						// "maj" => "" // doit se remplir automatiquement
659
-					],
660
-				],
661
-
662
-			],
663
-			'haddock' => [
664
-				'spip_test_haddock',
665
-				[
666
-					'field' => [
667
-						"id_haddock" => "INTEGER NOT NULL AUTO_INCREMENT",
668
-						"alcool" => "VARCHAR(80) NOT NULL DEFAULT ''",
669
-
670
-					],
671
-					'key' => [
672
-						"PRIMARY KEY" => "id_haddock",
673
-					],
674
-					'nb_key_attendues' => 1 // attention : la primary key DOIT etre dans les cle aussi
675
-				],
676
-				[
677
-					[
678
-						"id_haddock" => 1,
679
-						"alcool" => "<multi>[fr]Agile[en]Agily</multi>",
680
-					],
681
-					[
682
-						"id_haddock" => 2,
683
-						"alcool" => "<multi>[fr]Aérien[en]Aérieny</multi>",
684
-					],
685
-					[
686
-						"id_haddock" => 3,
687
-						"alcool" => "<multi>[fr]Vinasse[en]Vinassy</multi>",
688
-					],
689
-					[
690
-						"id_haddock" => 4,
691
-						"alcool" => "Un début de chaine : <multi>[fr]Vinasse[en]Vinassy</multi>, et [la fin]",
692
-					],
693
-				],
694
-
695
-			],
696
-		];
697
-	}
13
+    public static function setUpBeforeClass(): void
14
+    {
15
+        find_in_path('base/abstract_sql.php', '', true);
16
+    }
17
+
18
+    #[DataProvider('providerTablesData')]
19
+    public function testDropTablesSetup($table, $desc, $data): void
20
+    {
21
+        $this->assertTrue(sql_drop_table($table, true));
22
+    }
23
+
24
+    #[Depends('testDropTablesSetup')]
25
+    #[DataProvider('providerTablesData')]
26
+    public function testCreateTables($table, $desc, $data): void
27
+    {
28
+        $this->assertTrue(sql_create($table, $desc['field'], $desc['key']));
29
+    }
30
+
31
+    /**
32
+     * Creation/suppression/analyse de tables dans la base de donnee
33
+     *
34
+     * Permet de verifier que
35
+     * - tous les champs sont correctement ajoutes
36
+     * - que les PRIMARY sont pris en compte
37
+     * - que les KEY sont prises en compte
38
+     */
39
+    #[Depends('testCreateTables')]
40
+    #[DataProvider('providerTablesData')]
41
+    public function testShowTable($table, $desc, $data) {
42
+        // lire la structure de la table
43
+        // la structure doit avoir le meme nombre de champs et de cle
44
+        // attention : la primary key DOIT etre dans les cle aussi
45
+        $_desc = sql_showtable($table);
46
+        $this->assertCount(count($desc['field']), $_desc['field']);
47
+        $this->assertCount($desc['nb_key_attendues'], $_desc['key']);
48
+    }
49
+
50
+    #[Depends('testCreateTables')]
51
+    #[DataProvider('providerTablesData')]
52
+    public function testInsertData($table, $desc, $data) {
53
+        $this->assertNotFalse(sql_insertq_multi($table, $data));
54
+        $this->assertEquals(count($data), sql_countsel($table));
55
+    }
56
+
57
+    /**
58
+     * Teste que le champ "maj" s'actualise bien sur les update
59
+     * ainsi que les autres champs !
60
+     *
61
+     * utilise sql_quote, sql_getfetsel, sql_update et sql_updateq.
62
+     */
63
+    #[Depends('testInsertData')]
64
+    public function testMajTimestamp() {
65
+        $table = 'spip_test_tintin';
66
+        $where1 = 'id_tintin=' . sql_quote(1);
67
+        $where2 = 'id_tintin=' . sql_quote(2);
68
+
69
+        // lecture du timestamp actuel
70
+        $maj1 = sql_getfetsel('maj', $table, $where1);
71
+        $this->assertNotEmpty($maj1, "Le champ 'maj' n'a vraisemblablement pas recu de timestamp à l'insertion");
72
+
73
+        $maj2 = sql_getfetsel('maj', $table, $where2);
74
+        $this->assertNotEmpty($maj2, "Le champ 'maj' n'a vraisemblablement pas recu de timestamp à l'insertion");
75
+
76
+        // 1s de plus, sinon le timestamp ne change pas !
77
+        sleep(1);
78
+
79
+        // update
80
+        $texte = 'nouveau texte';
81
+        sql_update($table, [
82
+            'un_texte' => sql_quote($texte),
83
+        ], $where1);
84
+
85
+        // comparaison timastamp
86
+        $maj_update = sql_getfetsel('maj', $table, $where1);
87
+        $this->assertNotEmpty($maj_update, "Le champ 'maj' est vide à l’update");
88
+        $this->assertNotFalse(strtotime($maj_update), "Le champ 'maj' est incorrect à l’update");
89
+        $this->assertNotEquals($maj1, $maj_update, "Le champ 'maj' n'a vraisemblablement pas été mis a jour lors de l'update");
90
+
91
+        // comparaison texte
92
+        $texte_update = sql_getfetsel('un_texte', $table, $where1);
93
+        $this->assertNotEmpty($texte_update, "Le champ 'un_texte' est vide à l’update");
94
+        $this->assertEquals($texte, $texte_update, "Le champ 'un_texte' n'est pas correctement rempli a l'update");
95
+
96
+        // idem avec updateq
97
+        $texte = 'encore un nouveau texte';
98
+        sql_updateq($table, [
99
+            'un_texte' => $texte,
100
+        ], $where2);
101
+
102
+        // comparaison timastamp
103
+        $maj_updateq = sql_getfetsel('maj', $table, $where2);
104
+        $this->assertNotEmpty($maj_updateq, "Le champ 'maj' est vide à l’updateq");
105
+        $this->assertNotFalse(strtotime($maj_updateq), "Le champ 'maj' est incorrect à l’updateq");
106
+        $this->assertNotEquals($maj1, $maj_updateq, "Le champ 'maj' n'a vraisemblablement pas été mis a jour lors de l'updateq");
107
+
108
+        // comparaison texte
109
+        $texte_updateq = sql_getfetsel('un_texte', $table, $where2);
110
+        $this->assertNotEmpty($texte_updateq, "Le champ 'un_texte' est vide à l’updateq");
111
+        $this->assertEquals($texte, $texte_updateq, "Le champ 'un_texte' n'est pas correctement rempli a l'updateq");
112
+    }
113
+
114
+    /**
115
+     * Selections diverses selon criteres
116
+     */
117
+    #[Depends('testInsertData')]
118
+    public function testSelections() {
119
+        $data = $this->providerTablesData()['tintin'][2];
120
+
121
+        $res = sql_select('*', 'spip_test_tintin');
122
+        $this->assertNotFalse($res);
123
+        $this->assertEquals(count($data), sql_count($res), 'sql_count() ne renvoie pas la valeur attendue');
124
+
125
+        // selection float
126
+        $res = sql_select('*', 'spip_test_tintin', ['un_double>' . sql_quote(3)]);
127
+        $n = count(array_filter($data, fn ($entry) => $entry['un_double'] > 3));
128
+        $this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur un float');
129
+
130
+        // selection REGEXP
131
+        $res = sql_select('*', 'spip_test_tintin', ['un_varchar REGEXP ' . sql_quote('^De')]);
132
+        $n = count(array_filter($data, fn ($entry) => str_starts_with($entry['un_varchar'], 'De')));
133
+        $this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur une REGEXP');
134
+
135
+        // selection LIKE
136
+        $res = sql_select('*', 'spip_test_tintin', ['un_varchar LIKE ' . sql_quote('De%')]);
137
+        $this->assertEquals($n, sql_count($res), 'sql_count() ne renvoie pas la valeur attendue sur un LIKE');
138
+
139
+        // selection array(champs)
140
+        $res = sql_fetsel(['id_tintin', 'un_varchar'], 'spip_test_tintin');
141
+        $this->assertArrayHasKey('id_tintin', $res);
142
+        $this->assertArrayHasKey('un_varchar', $res);
143
+
144
+        // selection array(champs=>alias)
145
+        $res = sql_fetsel(['id_tintin AS id', 'un_varchar AS vchar'], 'spip_test_tintin');
146
+        $this->assertArrayHasKey('id', $res);
147
+        $this->assertArrayHasKey('vchar', $res);
148
+    }
149
+
150
+
151
+    #[Depends('testInsertData')]
152
+    public function testSelectionsMulti() {
153
+        $data = $this->providerTablesData()['milou'][2];
154
+
155
+        // selection avec sql_multi
156
+        $res = sql_select(['id_milou', sql_multi('grrrr', 'fr')], 'spip_test_milou', orderby: 'multi');
157
+        $this->assertNotFalse($res);
158
+        $this->assertEquals(count($data), sql_count($res), 'sql_multi mal interprété');
159
+        $this->assertEquals(3, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
160
+        $this->assertEquals(2, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
161
+        $this->assertEquals(1, sql_fetch($res)['id_milou'], 'sql_multi order by multi raté');
162
+
163
+        // le bon texte avec multi
164
+        foreach (
165
+            [
166
+                'fr' => 'Crac',
167
+                'en' => 'Krack',
168
+            ] as $lg => $res
169
+        ) {
170
+            $multi = sql_getfetsel(sql_multi('grrrr', $lg), 'spip_test_milou', 'id_milou=' . sql_quote(2));
171
+            $this->assertEquals($res, $multi, 'sql_multi mal rendu');
172
+        }
173
+
174
+        // le bon texte avec multi et accents
175
+        foreach (
176
+            [
177
+                'fr' => 'Aérien',
178
+                'en' => 'Aérieny',
179
+            ] as $lg => $res
180
+        ) {
181
+            $multi = sql_getfetsel(sql_multi('alcool', $lg), 'spip_test_haddock', 'id_haddock=' . sql_quote(2));
182
+            $this->assertEquals($res, $multi, 'sql_multi avec accents, mal rendu');
183
+        }
184
+
185
+        // le bon texte avec multi et debut et fin de chaine
186
+        foreach (
187
+            [
188
+                'fr' => 'Un début de chaine : Vinasse, et [la fin]',
189
+                'en' => 'Un début de chaine : Vinassy, et [la fin]',
190
+                'de' => 'Un début de chaine : Vinasse, et [la fin]',
191
+            ] as $lg => $res
192
+        ) {
193
+            $multi = sql_getfetsel(sql_multi('alcool', $lg), 'spip_test_haddock', 'id_haddock=' . sql_quote(4));
194
+            $this->assertEquals($res, $multi, 'sql_multi avec crochets, mal rendu');
195
+        }
196
+    }
197
+
198
+
199
+
200
+    /**
201
+     * Selections diverses entre plusieurs tables
202
+     */
203
+    #[Depends('testInsertData')]
204
+    public function testSelectionsEntreTable() {
205
+        // selection 2 tables
206
+        // ! nombre en dur !
207
+        $res = sql_select(
208
+            ['spip_test_tintin.id_tintin', 'spip_test_milou.id_milou'],
209
+            ['spip_test_tintin', 'spip_test_milou'],
210
+            ['spip_test_milou.id_tintin=spip_test_tintin.id_tintin']
211
+        );
212
+        $this->assertEquals(3, sql_count($res), 'Echec sélection');
213
+
214
+        // selection 2 tables avec alias =>
215
+        // ! nombre en dur !
216
+        $res = sql_select(
217
+            ['a.id_tintin AS x', 'b.id_milou AS y'],
218
+            [
219
+                'a' => 'spip_test_tintin',
220
+                'b' => 'spip_test_milou',
221
+            ],
222
+            ['a.id_tintin=b.id_tintin']
223
+        );
224
+        $this->assertEquals(3, sql_count($res), 'Echec sélection avec alias de colonnes et tables');
225
+
226
+        // selection 2 tables avec alias AS
227
+        // ! nombre en dur !
228
+        $res = sql_select(
229
+            ['a.id_tintin AS x', 'b.id_milou AS y'],
230
+            ['spip_test_tintin AS a', 'spip_test_milou AS b'],
231
+            ['a.id_tintin=b.id_tintin']
232
+        );
233
+        $this->assertEquals(3, sql_count($res));
234
+
235
+        // selection 2 tables avec INNER JOIN + ON
236
+        // ! nombre en dur !
237
+        $res = sql_select(
238
+            ['a.id_tintin AS x', 'b.id_milou AS y'],
239
+            ['spip_test_tintin AS a INNER JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)']
240
+        );
241
+        $this->assertEquals(3, sql_count($res), 'Echec sélection avec INNER JOIN + ON');
242
+
243
+        // selection 2 tables avec LEFT JOIN + ON
244
+        // ! nombre en dur !
245
+        $res = sql_select(
246
+            ['a.id_tintin AS x', 'b.id_milou AS y'],
247
+            ['spip_test_tintin AS a LEFT JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)']
248
+        );
249
+        $this->assertEquals(4, sql_count($res), 'Echec sélection avec LEFT JOIN + ON');
250
+
251
+
252
+        // selection 2 tables avec jointure INNER JOIN + USING
253
+        // ! nombre en dur !
254
+        // SQLite 2 se plante : il ne connait pas USING (enleve de la requete,
255
+        // et du coup ne fait pas correctement la jointure)
256
+        $res = sql_select(
257
+            ['a.id_tintin AS x', 'b.id_milou AS y'],
258
+            ['spip_test_tintin AS a INNER JOIN spip_test_milou AS b USING (id_tintin)']
259
+        );
260
+        $this->assertEquals(3, sql_count($res), 'Echec sélection avec INNER JOIN + USING');
261
+    }
262
+
263
+
264
+    /**
265
+     * Selections mathematiques
266
+     */
267
+    #[Depends('testInsertData')]
268
+    function testMathFunctions() {
269
+        foreach (
270
+            [
271
+                'COUNT' => 3,
272
+                'SUM' => 9000,
273
+                'AVG' => 3000,
274
+            ] as $func => $expected
275
+        ) {
276
+            $nb = sql_getfetsel("{$func}(un_int) AS nb", ['spip_test_tintin']);
277
+            $this->assertEquals($expected, $nb, "Selection {$func} en echec");
278
+        }
279
+
280
+        foreach (
281
+            [
282
+                'EXP(0)' => exp(0),
283
+                'ROUND(3.56)' => round(3.56),
284
+                'ROUND(3.5684,2)' => round(3.5684, 2),
285
+                'SQRT(9)' => 3,
286
+                //'1/2'=>(0), // Le standard SQL : entier divise par entier = division entiere (pas trouve la reference)
287
+                '1.0/2' => (1 / 2), // Le standart SQL : reel divise par entier = reel
288
+                //'4/3'=>1,
289
+                'ROUND(4.0/3,2)' => round(4 / 3, 2),
290
+                '1.5/2' => (1.5 / 2),
291
+                '2.0/2' => (2.0 / 2),
292
+                '2/2' => (2 / 2),
293
+                'md5(8)' => md5('8'),
294
+                'md5(' . sql_quote('a') . ')' => md5('a'),
295
+            ] as $func => $expected
296
+        ) {
297
+            $nb = sql_getfetsel("{$func} AS nb", ['spip_test_tintin'], ['id_tintin=' . sql_quote(1)]);
298
+            $this->assertEquals($expected, $nb, "Selection {$func} en echec");
299
+        }
300
+    }
301
+
302
+    /**
303
+     * Selections mathematiques
304
+     */
305
+    #[Depends('testInsertData')]
306
+
307
+    function testStringFunctions() {
308
+        foreach (
309
+            [
310
+                'CONCAT(' . sql_quote('cou') . ',' . sql_quote('cou') . ')' => 'coucou',
311
+                'CONCAT(' . sql_quote('cou,') . ',' . sql_quote('cou') . ')' => 'cou,cou',
312
+            ] as $func => $expected
313
+        ) {
314
+            $nb = sql_getfetsel("{$func} AS nb", ['spip_test_tintin'], ['id_tintin=' . sql_quote(1)]);
315
+            $this->assertEquals($expected, $nb, "Selection {$func} en echec");
316
+        }
317
+    }
318
+
319
+    /**
320
+     * retours des fonctions d'erreurs lors d'une requete
321
+     */
322
+    #[Depends('testCreateTables')]
323
+
324
+    function testErrorFunctions() {
325
+        // requete sans erreur
326
+        sql_select('*', 'spip_test_tintin');
327
+        $this->assertEquals('', sql_error(), 'sql_error() non vide lors d’une requete sans erreur');
328
+        $this->assertEquals(0, sql_errno(), 'sql_errno() ne retourne pas 0 lors d’une requete sans erreur');
329
+
330
+        // requete en erreur
331
+        sql_select('*', 'spip_test_toto');
332
+        $this->assertNotEquals('', sql_error(), 'sql_error() vide lors d’une requete en erreur');
333
+        $this->assertNotEquals(0, sql_errno(), 'sql_errno() retourne 0 lors d’une requete en erreur');
334
+    }
335
+
336
+    /**
337
+     * Update de data
338
+     */
339
+    #[Depends('testInsertData')]
340
+    public function testUpdateData() {
341
+        // ajouter un champ
342
+        $nb = sql_getfetsel('un_bigint', 'spip_test_tintin', 'id_tintin=' . sql_quote(1));
343
+        sql_update('spip_test_tintin', [
344
+            'un_bigint' => 'un_bigint+2',
345
+        ]);
346
+        $nb2 = sql_getfetsel('un_bigint', 'spip_test_tintin', 'id_tintin=' . sql_quote(1));
347
+        $this->assertEquals($nb + 2, $nb2, 'sql_update n’a pas fait l’adition !');
348
+    }
349
+
350
+    /**
351
+     * Delete de data
352
+     */
353
+    #[Depends('testInsertData')]
354
+
355
+    public function test_delete_data() {
356
+        $nb = sql_countsel('spip_test_tintin');
357
+        // supprimer une ligne
358
+        sql_delete('spip_test_tintin', 'id_tintin=' . sql_quote(1));
359
+        $this->assertEquals($nb - 1, sql_countsel('spip_test_tintin'), "sql_delete n’a pas supprimé la ligne");
360
+
361
+        // supprimer tout
362
+        sql_delete('spip_test_tintin');
363
+        $this->assertEquals(0, sql_countsel('spip_test_tintin'), "sql_delete n’a pas vidé la table");
364
+    }
365
+
366
+    /**
367
+     * Alter colonne
368
+     */
369
+    #[Depends('testCreateTables')]
370
+    function testAlterColumns() {
371
+        $table = 'spip_test_tintin';
372
+
373
+        // supprimer une colonne
374
+        sql_alter("TABLE {$table} DROP COLUMN un_bigint");
375
+        $desc = sql_showtable($table);
376
+        $this->assertIsArray($desc, 'sql_alter rate DROP COLUMN (plus de table ou sql_showtable en erreur?)');
377
+        $this->assertArrayNotHasKey('un_bigint', $desc['field']);
378
+        $this->assertArrayHasKey('un_smallint', $desc['field']);
379
+
380
+        // supprimer une colonne (sans COLUMN)
381
+        sql_alter("TABLE {$table} DROP un_smallint");
382
+        $desc = sql_showtable($table);
383
+        $this->assertIsArray($desc, 'sql_alter rate DROP sans COLUMN (plus de table ou sql_showtable en erreur?)');
384
+        $this->assertArrayNotHasKey('un_smallint', $desc['field']);
385
+
386
+        // renommer une colonne
387
+        sql_alter("TABLE {$table} CHANGE un_varchar deux_varchars VARCHAR(30) NOT NULL DEFAULT ''");
388
+        $desc = sql_showtable($table);
389
+        $this->assertIsArray($desc, 'sql_alter rate CHANGE (plus de table ou sql_showtable en erreur?)');
390
+        $this->assertArrayHasKey('deux_varchars', $desc['field']);
391
+        $this->assertArrayNotHasKey('un_varchar', $desc['field']);
392
+
393
+        // changer le type d'une colonne
394
+        $table = 'spip_test_milou';
395
+        sql_alter("TABLE {$table} MODIFY schtroumf TEXT NOT NULL DEFAULT ''");
396
+        $desc = sql_showtable($table);
397
+        $this->assertIsArray($desc, 'sql_alter rate MODIFY (plus de table ou sql_showtable en erreur?)');
398
+        $this->assertArrayHasKey('schtroumf', $desc['field'], 'sql_alter rate MODIFY varchar en text');
399
+        $this->assertStringContainsStringIgnoringCase('TEXT', $desc['field']['schtroumf'], 'sql_alter rate MODIFY varchar en text');
400
+
401
+        // ajouter des colonnes
402
+        sql_alter("TABLE {$table} ADD COLUMN houba BIGINT(21) NOT NULL DEFAULT '0'");
403
+        $desc = sql_showtable($table);
404
+        $this->assertIsArray($desc, 'sql_alter rate ADD COLUMN (plus de table ou sql_showtable en erreur?)');
405
+        $this->assertArrayHasKey('houba', $desc['field'], 'sql_alter rate ADD COLUMN');
406
+        $this->assertStringContainsStringIgnoringCase('INT', $desc['field']['houba'], 'sql_alter rate ADD COLUMN');
407
+
408
+        // ajouter des colonnes avec "AFTER"
409
+        sql_alter("TABLE {$table} ADD COLUMN hop BIGINT(21) NOT NULL DEFAULT '0' AFTER id_tintin");
410
+        $desc = sql_showtable($table);
411
+        $this->assertIsArray($desc, 'sql_alter rate ADD COLUMN avec AFTER (plus de table ou sql_showtable en erreur?)');
412
+        $this->assertArrayHasKey('hop', $desc['field'], 'sql_alter rate ADD COLUMN avec AFTER');
413
+        $this->assertStringContainsStringIgnoringCase('INT', $desc['field']['hop'], 'sql_alter rate ADD COLUMN avec AFTER');
414
+    }
415
+
416
+
417
+    /**
418
+     * Renomme table
419
+     */
420
+    #[Depends('testCreateTables')]
421
+
422
+    public function testAlterRenameTable() {
423
+
424
+        $table_before = 'spip_test_tintin';
425
+        $table_after = 'spip_test_castafiore';
426
+        sql_drop_table($table_after, true);
427
+        $this->assertEmpty(sql_showtable($table_after));
428
+        $this->assertIsArray(sql_showtable($table_before));
429
+
430
+        // renommer une table
431
+        sql_alter("TABLE {$table_before} RENAME {$table_after}");
432
+        $this->assertEmpty(sql_showtable($table_before));
433
+        $this->assertIsArray(sql_showtable($table_after));
434
+
435
+        sql_alter("TABLE {$table_after} RENAME {$table_before}");
436
+        $this->assertEmpty(sql_showtable($table_after));
437
+        $this->assertIsArray(sql_showtable($table_before));
438
+    }
439
+
440
+
441
+    /**
442
+     * pointer l'index
443
+     */
444
+    #[Depends('testCreateTables')]
445
+
446
+    public function testAlterIndex() {
447
+        $table = 'spip_test_milou';
448
+
449
+        // supprimer un index
450
+        sql_alter("TABLE {$table} DROP INDEX sons");
451
+        $desc = sql_showtable($table);
452
+        $this->assertIsArray($desc, 'sql_alter rate DROP INDEX sons (plus de table ou sql_showtable en erreur?)');
453
+        $this->assertArrayNotHasKey('KEY sons', $desc['key'], 'sql_alter rate DROP INDEX sons');
454
+
455
+        // ajouter un index simple
456
+        sql_alter("TABLE {$table} ADD INDEX (wouaf)");
457
+        $desc = sql_showtable($table);
458
+        $this->assertIsArray($desc, 'sql_alter rate ADD INDEX (wouaf) (plus de table ou sql_showtable en erreur?)');
459
+        $this->assertArrayHasKey('KEY wouaf', $desc['key'], 'sql_alter rate ADD INDEX (wouaf)');
460
+
461
+        // ajouter un index nomme
462
+        sql_alter("TABLE {$table} ADD INDEX pluie (grrrr)");
463
+        $desc = sql_showtable($table);
464
+        $this->assertIsArray($desc, 'sql_alter rate ADD INDEX pluie (grrrr) (plus de table ou sql_showtable en erreur?)');
465
+        $this->assertArrayHasKey('KEY pluie', $desc['key'], 'sql_alter rate ADD INDEX pluie (grrrr)');
466
+
467
+        // supprimer un index
468
+        sql_alter("TABLE {$table} DROP INDEX pluie");
469
+        $desc = sql_showtable($table);
470
+        $this->assertIsArray($desc, 'sql_alter rate DROP INDEX pluie (plus de table ou sql_showtable en erreur?)');
471
+        $this->assertArrayNotHasKey('KEY pluie', $desc['key'], 'sql_alter rate DROP INDEX pluie');
472
+
473
+        // ajouter un index nomme double
474
+        sql_alter("TABLE {$table} ADD INDEX dring (grrrr, wouaf)");
475
+        $desc = sql_showtable($table);
476
+        $this->assertIsArray($desc, 'sql_alter rate ADD INDEX dring (grrrr, wouaf) (plus de table ou sql_showtable en erreur?)');
477
+        $this->assertArrayHasKey('KEY dring', $desc['key'], 'sql_alter rate ADD INDEX dring (grrrr, wouaf)');
478
+    }
479
+
480
+
481
+    /**
482
+     * dezinguer la primary
483
+     */
484
+    #[Depends('testCreateTables')]
485
+
486
+    public function testAlterPrimary() {
487
+        $table = 'spip_test_kirikou';
488
+        sql_drop_table($table, true);
489
+
490
+        // creer une table pour jouer
491
+        sql_create(
492
+            $table,
493
+            [
494
+                'un' => 'INTEGER NOT NULL',
495
+                'deux' => 'INTEGER NOT NULL',
496
+                'trois' => 'INTEGER NOT NULL',
497
+            ],
498
+            [
499
+                'PRIMARY KEY' => 'un',
500
+            ]
501
+        );
502
+
503
+        // supprimer une primary
504
+        $desc = sql_showtable($table);
505
+        sql_alter("TABLE {$table} DROP PRIMARY KEY");
506
+        $desc = sql_showtable($table);
507
+        $this->assertIsArray($desc, 'sql_alter rate DROP PRIMARY KEY (plus de table ou sql_showtable en erreur?)');
508
+        $this->assertArrayNotHasKey('PRIMARY KEY', $desc['key'], 'sql_alter rate DROP PRIMARY KEY');
509
+
510
+        // ajouter une primary
511
+        $desc = sql_showtable($table);
512
+        sql_alter("TABLE {$table} ADD PRIMARY KEY (deux, trois)");
513
+        $desc = sql_showtable($table);
514
+        $this->assertIsArray($desc, 'sql_alter rate ADD PRIMARY KEY (plus de table ou sql_showtable en erreur?)');
515
+        $this->assertArrayHasKey('PRIMARY KEY', $desc['key'], 'sql_alter rate ADD PRIMARY KEY');
516
+
517
+        sql_drop_table($table, true);
518
+    }
519
+
520
+    /**
521
+     * Alter colonne
522
+     */
523
+    #[Depends('testAlterColumns')]
524
+    #[Depends('testAlterIndex')]
525
+
526
+    function testAlterMultiple() {
527
+        $table = 'spip_test_milou';
528
+
529
+        // supprimer des colonnes
530
+        sql_alter("TABLE {$table} DROP INDEX dring, DROP COLUMN wouaf, DROP COLUMN grrrr");
531
+        $desc = sql_showtable($table);
532
+        $this->assertIsArray($desc, 'sql_alter rate DROP multiples (plus de table ou sql_showtable en erreur?)');
533
+        $this->assertArrayNotHasKey('waouf', $desc['field'], 'sql_alter rate DROP multiples');
534
+        $this->assertArrayNotHasKey('grrrr', $desc['field'], 'sql_alter rate DROP multiples');
535
+        $this->assertArrayNotHasKey('KEY dring', $desc['key'], 'sql_alter rate DROP multiples');
536
+
537
+        // ajouter des colonnes
538
+        sql_alter("TABLE {$table} ADD COLUMN a INT, ADD COLUMN b INT, ADD COLUMN c INT, ADD INDEX abc (a,b,c)");
539
+        $desc = sql_showtable($table);
540
+        $this->assertIsArray($desc, 'sql_alter rate ADD multiples (plus de table ou sql_showtable en erreur?)');
541
+        $this->assertArrayHasKey('a', $desc['field'], 'sql_alter rate ADD multiples');
542
+        $this->assertArrayHasKey('b', $desc['field'], 'sql_alter rate ADD multiples');
543
+        $this->assertArrayHasKey('c', $desc['field'], 'sql_alter rate ADD multiples');
544
+        $this->assertArrayHasKey('KEY abc', $desc['key'], 'sql_alter rate ADD multiples');
545
+    }
546
+
547
+    #[Depends('testCreateTables')]
548
+    #[DataProvider('providerTablesData')]
549
+    public function testDropTables($table, $desc, $data): void
550
+    {
551
+        $this->assertTrue(sql_drop_table($table, false));
552
+    }
553
+
554
+    /**
555
+     * Description des tables & données de tests
556
+     */
557
+    public static function providerTablesData(): array
558
+    {
559
+        return [
560
+            'tintin' => [
561
+                'spip_test_tintin',
562
+                [
563
+                    'field' => [
564
+                        "id_tintin" => "INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY",
565
+                        "un_bigint" => "BIGINT(21) NOT NULL DEFAULT '0'",
566
+                        "un_int" => "BIGINT(21) NOT NULL DEFAULT '0'",
567
+                        "un_smallint" => "SMALLINT(3) NOT NULL DEFAULT '0'",
568
+                        "un_double" => "DOUBLE NOT NULL DEFAULT '0'",
569
+                        "un_tinyint" => "TINYINT(2) NOT NULL DEFAULT '0'",
570
+                        "un_varchar" => "VARCHAR(30) NOT NULL DEFAULT ''",
571
+                        "un_texte" => "TEXT NOT NULL DEFAULT ''",
572
+                        "maj" => "TIMESTAMP"
573
+                    ],
574
+                    'key' => [
575
+
576
+                    ],
577
+                    'nb_key_attendues' => 1 // attention : la primary key DOIT etre dans les cle aussi
578
+                ],
579
+                [
580
+                    [
581
+                        "id_tintin" => 1,
582
+                        "un_bigint" => 30000,
583
+                        "un_int" => 2000,
584
+                        "un_smallint" => 40,
585
+                        "un_double" => 2.58,
586
+                        "un_tinyint" => 8,
587
+                        "un_varchar" => "Premier varchar",
588
+                        "un_texte" => "Premier texte",
589
+                        //"maj" => "" // doit se remplir automatiquement
590
+                    ],
591
+                    [
592
+                        "id_tintin" => 2,
593
+                        "un_bigint" => 40000,
594
+                        "un_int" => 3000,
595
+                        "un_smallint" => 50,
596
+                        "un_double" => 3.58,
597
+                        "un_tinyint" => 9,
598
+                        "un_varchar" => "Deuxieme varchar",
599
+                        "un_texte" => "Second texte",
600
+                        //"maj" => "" // doit se remplir automatiquement
601
+                    ],
602
+                    [
603
+                        "id_tintin" => 3,
604
+                        "un_bigint" => 60000,
605
+                        "un_int" => 4000,
606
+                        "un_smallint" => 70,
607
+                        "un_double" => 8.58,
608
+                        "un_tinyint" => 3,
609
+                        "un_varchar" => "Troisieme varchar",
610
+                        "un_texte" => "Troisieme texte",
611
+                        //"maj" => "" // doit se remplir automatiquement
612
+                    ],
613
+                ],
614
+
615
+            ],
616
+            'milou' => [
617
+                'spip_test_milou',
618
+                [
619
+                    'field' => [
620
+                        "id_milou" => "INTEGER NOT NULL AUTO_INCREMENT",
621
+                        "id_tintin" => "INTEGER NOT NULL",
622
+                        "un_enum" => "ENUM('blanc','noir') NOT NULL DEFAULT 'blanc'",
623
+                        "wouaf" => "VARCHAR(80) NOT NULL DEFAULT ''",
624
+                        "grrrr" => "VARCHAR(80) NOT NULL DEFAULT ''",
625
+                        "schtroumf" => "VARCHAR(80) NOT NULL DEFAULT ''",
626
+                        "maj" => "TIMESTAMP"
627
+                    ],
628
+                    'key' => [
629
+                        "PRIMARY KEY" => "id_milou",
630
+                        "KEY id_tintin" => "id_tintin",
631
+                        "KEY sons" => "wouaf, grrrr",
632
+                    ],
633
+                    'nb_key_attendues' => 3 // attention : la primary key DOIT etre dans les cle aussi
634
+                ],
635
+                [
636
+                    [
637
+                        "id_milou" => 1,
638
+                        "id_tintin" => 1,
639
+                        "un_enum" => "blanc",
640
+                        "wouaf" => "Warf !!",
641
+                        "grrrr" => "Grogne !",
642
+                        // "maj" => "" // doit se remplir automatiquement
643
+                    ],
644
+                    [
645
+                        "id_milou" => 2,
646
+                        "id_tintin" => 1,
647
+                        "un_enum" => "noir",
648
+                        "wouaf" => "Wouf",
649
+                        "grrrr" => "<multi>[fr]Crac[en]Krack</multi>",
650
+                        // "maj" => "" // doit se remplir automatiquement
651
+                    ],
652
+                    [
653
+                        "id_milou" => 3,
654
+                        "id_tintin" => 2,
655
+                        "un_enum" => "blanc",
656
+                        "wouaf" => "Wif",
657
+                        "grrrr" => "Ahrg",
658
+                        // "maj" => "" // doit se remplir automatiquement
659
+                    ],
660
+                ],
661
+
662
+            ],
663
+            'haddock' => [
664
+                'spip_test_haddock',
665
+                [
666
+                    'field' => [
667
+                        "id_haddock" => "INTEGER NOT NULL AUTO_INCREMENT",
668
+                        "alcool" => "VARCHAR(80) NOT NULL DEFAULT ''",
669
+
670
+                    ],
671
+                    'key' => [
672
+                        "PRIMARY KEY" => "id_haddock",
673
+                    ],
674
+                    'nb_key_attendues' => 1 // attention : la primary key DOIT etre dans les cle aussi
675
+                ],
676
+                [
677
+                    [
678
+                        "id_haddock" => 1,
679
+                        "alcool" => "<multi>[fr]Agile[en]Agily</multi>",
680
+                    ],
681
+                    [
682
+                        "id_haddock" => 2,
683
+                        "alcool" => "<multi>[fr]Aérien[en]Aérieny</multi>",
684
+                    ],
685
+                    [
686
+                        "id_haddock" => 3,
687
+                        "alcool" => "<multi>[fr]Vinasse[en]Vinassy</multi>",
688
+                    ],
689
+                    [
690
+                        "id_haddock" => 4,
691
+                        "alcool" => "Un début de chaine : <multi>[fr]Vinasse[en]Vinassy</multi>, et [la fin]",
692
+                    ],
693
+                ],
694
+
695
+            ],
696
+        ];
697
+    }
698 698
 }
Please login to merge, or discard this patch.