51
51
return new xmldb_table($tablename);
54
function test_diagnose() {
54
public function test_diagnose() {
56
56
$result = $DB->diagnose();
57
57
$this->assertNull($result, 'Database self diagnostics failed %s');
60
function test_get_server_info() {
60
public function test_get_server_info() {
62
62
$result = $DB->get_server_info();
63
$this->assertTrue(is_array($result));
64
$this->assertTrue(array_key_exists('description', $result));
65
$this->assertTrue(array_key_exists('version', $result));
63
$this->assertInternalType('array', $result);
64
$this->assertArrayHasKey('description', $result);
65
$this->assertArrayHasKey('version', $result);
68
68
public function test_get_in_or_equal() {
71
// SQL_PARAMS_QM - IN or =
71
// SQL_PARAMS_QM - IN or =.
73
// Correct usage of multiple values
73
// Correct usage of multiple values.
74
74
$in_values = array('value1', 'value2', '3', 4, null, false, true);
75
75
list($usql, $params) = $DB->get_in_or_equal($in_values);
76
$this->assertEquals('IN ('.implode(',',array_fill(0, count($in_values), '?')).')', $usql);
76
$this->assertSame('IN ('.implode(',', array_fill(0, count($in_values), '?')).')', $usql);
77
77
$this->assertEquals(count($in_values), count($params));
78
78
foreach ($params as $key => $value) {
79
79
$this->assertSame($in_values[$key], $value);
82
// Correct usage of single value (in an array)
82
// Correct usage of single value (in an array).
83
83
$in_values = array('value1');
84
84
list($usql, $params) = $DB->get_in_or_equal($in_values);
85
85
$this->assertEquals("= ?", $usql);
86
$this->assertEquals(1, count($params));
86
$this->assertCount(1, $params);
87
87
$this->assertEquals($in_values[0], $params[0]);
89
// Correct usage of single value
89
// Correct usage of single value.
90
90
$in_value = 'value1';
91
91
list($usql, $params) = $DB->get_in_or_equal($in_values);
92
92
$this->assertEquals("= ?", $usql);
93
$this->assertEquals(1, count($params));
93
$this->assertCount(1, $params);
94
94
$this->assertEquals($in_value, $params[0]);
96
// SQL_PARAMS_QM - NOT IN or <>
96
// SQL_PARAMS_QM - NOT IN or <>.
98
// Correct usage of multiple values
98
// Correct usage of multiple values.
99
99
$in_values = array('value1', 'value2', 'value3', 'value4');
100
100
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
101
101
$this->assertEquals("NOT IN (?,?,?,?)", $usql);
102
$this->assertEquals(4, count($params));
102
$this->assertCount(4, $params);
103
103
foreach ($params as $key => $value) {
104
104
$this->assertEquals($in_values[$key], $value);
107
// Correct usage of single value (in array()
107
// Correct usage of single value (in array().
108
108
$in_values = array('value1');
109
109
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
110
110
$this->assertEquals("<> ?", $usql);
111
$this->assertEquals(1, count($params));
111
$this->assertCount(1, $params);
112
112
$this->assertEquals($in_values[0], $params[0]);
114
// Correct usage of single value
114
// Correct usage of single value.
115
115
$in_value = 'value1';
116
116
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
117
117
$this->assertEquals("<> ?", $usql);
118
$this->assertEquals(1, count($params));
118
$this->assertCount(1, $params);
119
119
$this->assertEquals($in_value, $params[0]);
121
// SQL_PARAMS_NAMED - IN or =
121
// SQL_PARAMS_NAMED - IN or =.
123
// Correct usage of multiple values
123
// Correct usage of multiple values.
124
124
$in_values = array('value1', 'value2', 'value3', 'value4');
125
125
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true);
126
$this->assertEquals(4, count($params));
126
$this->assertCount(4, $params);
127
127
reset($in_values);
129
129
foreach ($params as $key => $value) {
167
167
$this->assertEquals("NOT IN (".implode(',', $ps).")", $usql);
169
// Correct usage of single values (in array)
169
// Correct usage of single values (in array).
170
170
$in_values = array('value1');
171
171
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
172
$this->assertEquals(1, count($params));
172
$this->assertCount(1, $params);
173
173
$value = reset($params);
174
174
$key = key($params);
175
175
$this->assertEquals("<> :$key", $usql);
176
176
$this->assertEquals($in_value, $value);
178
// Correct usage of single value
178
// Correct usage of single value.
179
179
$in_value = 'value1';
180
180
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
181
$this->assertEquals(1, count($params));
181
$this->assertCount(1, $params);
182
182
$value = reset($params);
183
183
$key = key($params);
184
184
$this->assertEquals("<> :$key", $usql);
185
185
$this->assertEquals($in_value, $value);
187
// make sure the param names are unique
188
list($usql1, $params1) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param');
189
list($usql2, $params2) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param');
187
// Make sure the param names are unique.
188
list($usql1, $params1) = $DB->get_in_or_equal(array(1, 2, 3), SQL_PARAMS_NAMED, 'param');
189
list($usql2, $params2) = $DB->get_in_or_equal(array(1, 2, 3), SQL_PARAMS_NAMED, 'param');
190
190
$params1 = array_keys($params1);
191
191
$params2 = array_keys($params2);
192
192
$common = array_intersect($params1, $params2);
193
$this->assertEquals(count($common), 0);
195
// Some incorrect tests
197
// Incorrect usage passing not-allowed params type
193
$this->assertCount(0, $common);
195
// Some incorrect tests.
197
// Incorrect usage passing not-allowed params type.
198
198
$in_values = array(1, 2, 3);
200
200
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_DOLLAR, 'param', false);
201
201
$this->fail('An Exception is missing, expected due to not supported SQL_PARAMS_DOLLAR');
202
} catch (exception $e) {
203
$this->assertTrue($e instanceof dml_exception);
204
$this->assertEquals($e->errorcode, 'typenotimplement');
202
} catch (moodle_exception $e) {
203
$this->assertInstanceOf('dml_exception', $e);
204
$this->assertSame('typenotimplement', $e->errorcode);
207
// Incorrect usage passing empty array
207
// Incorrect usage passing empty array.
208
208
$in_values = array();
210
210
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
211
211
$this->fail('An Exception is missing, expected due to empty array of items');
212
} catch (exception $e) {
213
$this->assertTrue($e instanceof coding_exception);
212
} catch (moodle_exception $e) {
213
$this->assertInstanceOf('coding_exception', $e);
216
// Test using $onemptyitems
218
// Correct usage passing empty array and $onemptyitems = NULL (equal = true, QM)
219
$in_values = array();
220
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, NULL);
221
$this->assertEquals(' IS NULL', $usql);
222
$this->assertSame(array(), $params);
224
// Correct usage passing empty array and $onemptyitems = NULL (equal = false, NAMED)
225
$in_values = array();
226
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, NULL);
227
$this->assertEquals(' IS NOT NULL', $usql);
228
$this->assertSame(array(), $params);
230
// Correct usage passing empty array and $onemptyitems = true (equal = true, QM)
216
// Test using $onemptyitems.
218
// Correct usage passing empty array and $onemptyitems = null (equal = true, QM).
219
$in_values = array();
220
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, null);
221
$this->assertSame(' IS NULL', $usql);
222
$this->assertSame(array(), $params);
224
// Correct usage passing empty array and $onemptyitems = null (equal = false, NAMED).
225
$in_values = array();
226
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, null);
227
$this->assertSame(' IS NOT NULL', $usql);
228
$this->assertSame(array(), $params);
230
// Correct usage passing empty array and $onemptyitems = true (equal = true, QM).
231
231
$in_values = array();
232
232
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, true);
233
$this->assertEquals('= ?', $usql);
233
$this->assertSame('= ?', $usql);
234
234
$this->assertSame(array(true), $params);
236
// Correct usage passing empty array and $onemptyitems = true (equal = false, NAMED)
236
// Correct usage passing empty array and $onemptyitems = true (equal = false, NAMED).
237
237
$in_values = array();
238
238
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, true);
239
$this->assertEquals(1, count($params));
239
$this->assertCount(1, $params);
240
240
$value = reset($params);
241
241
$key = key($params);
242
$this->assertEquals('<> :'.$key, $usql);
242
$this->assertSame('<> :'.$key, $usql);
243
243
$this->assertSame($value, true);
245
// Correct usage passing empty array and $onemptyitems = -1 (equal = true, QM)
245
// Correct usage passing empty array and $onemptyitems = -1 (equal = true, QM).
246
246
$in_values = array();
247
247
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, -1);
248
$this->assertEquals('= ?', $usql);
248
$this->assertSame('= ?', $usql);
249
249
$this->assertSame(array(-1), $params);
251
// Correct usage passing empty array and $onemptyitems = -1 (equal = false, NAMED)
251
// Correct usage passing empty array and $onemptyitems = -1 (equal = false, NAMED).
252
252
$in_values = array();
253
253
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, -1);
254
$this->assertEquals(1, count($params));
254
$this->assertCount(1, $params);
255
255
$value = reset($params);
256
256
$key = key($params);
257
$this->assertEquals('<> :'.$key, $usql);
257
$this->assertSame('<> :'.$key, $usql);
258
258
$this->assertSame($value, -1);
260
// Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = true, QM)
260
// Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = true, QM).
261
261
$in_values = array();
262
262
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, 'onevalue');
263
$this->assertEquals('= ?', $usql);
263
$this->assertSame('= ?', $usql);
264
264
$this->assertSame(array('onevalue'), $params);
266
// Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = false, NAMED)
266
// Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = false, NAMED).
267
267
$in_values = array();
268
268
list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, 'onevalue');
269
$this->assertEquals(1, count($params));
269
$this->assertCount(1, $params);
270
270
$value = reset($params);
271
271
$key = key($params);
272
$this->assertEquals('<> :'.$key, $usql);
272
$this->assertSame('<> :'.$key, $usql);
273
273
$this->assertSame($value, 'onevalue');
330
330
$this->assertSame($rsql, $sql[$rtype]);
331
331
$this->assertSame($rparams, $params[$rtype]);
334
// Malformed table placeholder
333
// Malformed table placeholder.
335
334
$sql = "SELECT * FROM [testtable]";
336
335
$sqlarray = $DB->fix_sql_params($sql);
337
336
$this->assertSame($sql, $sqlarray[0]);
340
// Mixed param types (colon and dollar)
338
// Mixed param types (colon and dollar).
341
339
$sql = "SELECT * FROM {{$tablename}} WHERE name = :param1, course = \$1";
342
340
$params = array('param1' => 'record1', 'param2' => 3);
344
342
$DB->fix_sql_params($sql, $params);
345
343
$this->fail("Expecting an exception, none occurred");
346
} catch (Exception $e) {
347
$this->assertTrue($e instanceof dml_exception);
344
} catch (moodle_exception $e) {
345
$this->assertInstanceOf('dml_exception', $e);
350
// Mixed param types (question and dollar)
348
// Mixed param types (question and dollar).
351
349
$sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = \$1";
352
350
$params = array('param1' => 'record2', 'param2' => 5);
354
352
$DB->fix_sql_params($sql, $params);
355
353
$this->fail("Expecting an exception, none occurred");
356
} catch (Exception $e) {
357
$this->assertTrue($e instanceof dml_exception);
354
} catch (moodle_exception $e) {
355
$this->assertInstanceOf('dml_exception', $e);
360
// Too few params in sql
358
// Too few params in sql.
361
359
$sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = ?, id = ?";
362
360
$params = array('record2', 3);
364
362
$DB->fix_sql_params($sql, $params);
365
363
$this->fail("Expecting an exception, none occurred");
366
} catch (Exception $e) {
367
$this->assertTrue($e instanceof dml_exception);
364
} catch (moodle_exception $e) {
365
$this->assertInstanceOf('dml_exception', $e);
370
// Too many params in array: no error, just use what is necessary
368
// Too many params in array: no error, just use what is necessary.
372
370
$params[] = time();
374
$sqlarray = $DB->fix_sql_params($sql, $params);
375
$this->assertTrue(is_array($sqlarray));
376
$this->assertEquals(count($sqlarray[1]), 3);
377
} catch (Exception $e) {
378
$this->fail("Unexpected ".get_class($e)." exception");
371
$sqlarray = $DB->fix_sql_params($sql, $params);
372
$this->assertInternalType('array', $sqlarray);
373
$this->assertCount(3, $sqlarray[1]);
381
// Named params missing from array
375
// Named params missing from array.
382
376
$sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course";
383
377
$params = array('wrongname' => 'record1', 'course' => 1);
385
379
$DB->fix_sql_params($sql, $params);
386
380
$this->fail("Expecting an exception, none occurred");
387
} catch (Exception $e) {
388
$this->assertTrue($e instanceof dml_exception);
381
} catch (moodle_exception $e) {
382
$this->assertInstanceOf('dml_exception', $e);
391
385
// Duplicate named param in query - this is a very important feature!!
392
// it helps with debugging of sloppy code
386
// it helps with debugging of sloppy code.
393
387
$sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :name";
394
388
$params = array('name' => 'record2', 'course' => 3);
396
390
$DB->fix_sql_params($sql, $params);
397
391
$this->fail("Expecting an exception, none occurred");
398
} catch (Exception $e) {
399
$this->assertTrue($e instanceof dml_exception);
392
} catch (moodle_exception $e) {
393
$this->assertInstanceOf('dml_exception', $e);
402
// Extra named param is ignored
396
// Extra named param is ignored.
403
397
$sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course";
404
398
$params = array('name' => 'record1', 'course' => 1, 'extrastuff'=>'haha');
406
$sqlarray = $DB->fix_sql_params($sql, $params);
407
$this->assertTrue(is_array($sqlarray));
408
$this->assertEquals(count($sqlarray[1]), 2);
409
} catch (Exception $e) {
410
$this->fail("Unexpected ".get_class($e)." exception");
399
$sqlarray = $DB->fix_sql_params($sql, $params);
400
$this->assertInternalType('array', $sqlarray);
401
$this->assertCount(2, $sqlarray[1]);
413
// Params exceeding 30 chars length
403
// Params exceeding 30 chars length.
414
404
$sql = "SELECT * FROM {{$tablename}} WHERE name = :long_placeholder_with_more_than_30";
415
405
$params = array('long_placeholder_with_more_than_30' => 'record1');
417
407
$DB->fix_sql_params($sql, $params);
418
408
$this->fail("Expecting an exception, none occurred");
419
} catch (Exception $e) {
420
$this->assertTrue($e instanceof coding_exception);
409
} catch (moodle_exception $e) {
410
$this->assertInstanceOf('coding_exception', $e);
423
// Booleans in NAMED params are casting to 1/0 int
413
// Booleans in NAMED params are casting to 1/0 int.
424
414
$sql = "SELECT * FROM {{$tablename}} WHERE course = ? OR course = ?";
425
415
$params = array(true, false);
426
416
list($sql, $params) = $DB->fix_sql_params($sql, $params);
427
417
$this->assertTrue(reset($params) === 1);
428
418
$this->assertTrue(next($params) === 0);
430
// Booleans in QM params are casting to 1/0 int
420
// Booleans in QM params are casting to 1/0 int.
431
421
$sql = "SELECT * FROM {{$tablename}} WHERE course = :course1 OR course = :course2";
432
422
$params = array('course1' => true, 'course2' => false);
433
423
list($sql, $params) = $DB->fix_sql_params($sql, $params);
434
424
$this->assertTrue(reset($params) === 1);
435
425
$this->assertTrue(next($params) === 0);
437
// Booleans in DOLLAR params are casting to 1/0 int
427
// Booleans in DOLLAR params are casting to 1/0 int.
438
428
$sql = "SELECT * FROM {{$tablename}} WHERE course = \$1 OR course = \$2";
439
429
$params = array(true, false);
440
430
list($sql, $params) = $DB->fix_sql_params($sql, $params);
441
431
$this->assertTrue(reset($params) === 1);
442
432
$this->assertTrue(next($params) === 0);
444
// No data types are touched except bool
434
// No data types are touched except bool.
445
435
$sql = "SELECT * FROM {{$tablename}} WHERE name IN (?,?,?,?,?,?)";
446
$inparams = array('abc', 'ABC', NULL, '1', 1, 1.4);
436
$inparams = array('abc', 'ABC', null, '1', 1, 1.4);
447
437
list($sql, $params) = $DB->fix_sql_params($sql, $inparams);
448
438
$this->assertSame(array_values($params), array_values($inparams));
451
441
public function test_strtok() {
452
// strtok was previously used by bound emulation, make sure it is not used any more
442
// Strtok was previously used by bound emulation, make sure it is not used any more.
453
443
$DB = $this->tdb;
454
444
$dbman = $this->tdb->get_manager();
456
446
$table = $this->get_test_table();
457
447
$tablename = $table->getName();
459
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
460
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
449
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
450
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
461
451
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala');
462
452
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
463
453
$dbman->create_table($table);
1087
1077
$data = array(array('course' => 3, 'name' => 'record1'),
1088
1078
array('course' => 3, 'name' => 'record2'),
1089
1079
array('course' => 5, 'name' => 'record3'));
1090
foreach ($data as $key=>$record) {
1080
foreach ($data as $key => $record) {
1091
1081
$data[$key]['id'] = $DB->insert_record($tablename, $record);
1094
// Test repeated numeric keys are returned ok
1095
$rs = $DB->get_recordset($tablename, NULL, NULL, 'course, name, id');
1084
// Test repeated numeric keys are returned ok.
1085
$rs = $DB->get_recordset($tablename, null, null, 'course, name, id');
1099
foreach($rs as $key => $record) {
1089
foreach ($rs as $key => $record) {
1100
1090
$data_record = current($data);
1101
1091
$this->assertEquals($data_record['course'], $key);
1106
$this->assertEquals($count, 3);
1096
$this->assertEquals(3, $count);
1108
// Test string keys are returned ok
1109
$rs = $DB->get_recordset($tablename, NULL, NULL, 'name, course, id');
1098
// Test string keys are returned ok.
1099
$rs = $DB->get_recordset($tablename, null, null, 'name, course, id');
1113
foreach($rs as $key => $record) {
1103
foreach ($rs as $key => $record) {
1114
1104
$data_record = current($data);
1115
1105
$this->assertEquals($data_record['name'], $key);
1120
$this->assertEquals($count, 3);
1110
$this->assertEquals(3, $count);
1122
// Test numeric not starting in 1 keys are returned ok
1123
$rs = $DB->get_recordset($tablename, NULL, 'id DESC', 'id, course, name');
1112
// Test numeric not starting in 1 keys are returned ok.
1113
$rs = $DB->get_recordset($tablename, null, 'id DESC', 'id, course, name');
1125
1115
$data = array_reverse($data);
1128
foreach($rs as $key => $record) {
1118
foreach ($rs as $key => $record) {
1129
1119
$data_record = current($data);
1130
1120
$this->assertEquals($data_record['id'], $key);
1135
$this->assertEquals($count, 3);
1125
$this->assertEquals(3, $count);
1138
1128
public function test_get_recordset_list() {
1380
1370
$current_record = next($records);
1381
1371
$this->assertEquals(3, $current_record->id);
1383
// All records, but get only one field
1373
// All records, but get only one field.
1384
1374
$records = $DB->get_records($tablename, null, '', 'id');
1385
1375
$this->assertFalse(isset($records[1]->course));
1386
1376
$this->assertTrue(isset($records[1]->id));
1387
$this->assertEquals(4, count($records));
1377
$this->assertCount(4, $records);
1389
// Booleans into params
1379
// Booleans into params.
1390
1380
$records = $DB->get_records($tablename, array('course' => true));
1391
$this->assertEquals(0, count($records));
1381
$this->assertCount(0, $records);
1392
1382
$records = $DB->get_records($tablename, array('course' => false));
1393
$this->assertEquals(0, count($records));
1383
$this->assertCount(0, $records);
1395
// test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
1385
// Test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int).
1396
1386
$conditions = array('onetext' => '1');
1398
1388
$records = $DB->get_records($tablename, $conditions);
1399
1389
if (debugging()) {
1400
// only in debug mode - hopefully all devs test code in debug mode...
1390
// Only in debug mode - hopefully all devs test code in debug mode...
1401
1391
$this->fail('An Exception is missing, expected due to equating of text fields');
1403
} catch (exception $e) {
1404
$this->assertTrue($e instanceof dml_exception);
1405
$this->assertEquals($e->errorcode, 'textconditionsnotallowed');
1393
} catch (moodle_exception $e) {
1394
$this->assertInstanceOf('dml_exception', $e);
1395
$this->assertSame('textconditionsnotallowed', $e->errorcode);
1408
// test get_records passing non-existing table
1398
// Test get_records passing non-existing table.
1411
1401
$records = $DB->get_records('xxxx', array('id' => 0));
1412
1402
$this->fail('An Exception is missing, expected due to query against non-existing table');
1413
} catch (exception $e) {
1414
$this->assertTrue($e instanceof dml_exception);
1403
} catch (moodle_exception $e) {
1404
$this->assertInstanceOf('dml_exception', $e);
1415
1405
if (debugging()) {
1416
// information for developers only, normal users get general error message
1417
$this->assertEquals($e->errorcode, 'ddltablenotexist');
1406
// Information for developers only, normal users get general error message.
1407
$this->assertSame('ddltablenotexist', $e->errorcode);
1420
// and without params
1410
// And without params.
1422
1412
$records = $DB->get_records('xxxx', array());
1423
1413
$this->fail('An Exception is missing, expected due to query against non-existing table');
1424
} catch (exception $e) {
1425
$this->assertTrue($e instanceof dml_exception);
1414
} catch (moodle_exception $e) {
1415
$this->assertInstanceOf('dml_exception', $e);
1426
1416
if (debugging()) {
1427
// information for developers only, normal users get general error message
1428
$this->assertEquals($e->errorcode, 'ddltablenotexist');
1417
// Information for developers only, normal users get general error message.
1418
$this->assertSame('ddltablenotexist', $e->errorcode);
1432
// test get_records passing non-existing column
1422
// Test get_records passing non-existing column.
1434
1424
$records = $DB->get_records($tablename, array('xxxx' => 0));
1435
1425
$this->fail('An Exception is missing, expected due to query against non-existing column');
1436
} catch (exception $e) {
1437
$this->assertTrue($e instanceof dml_exception);
1426
} catch (moodle_exception $e) {
1427
$this->assertInstanceOf('dml_exception', $e);
1438
1428
if (debugging()) {
1439
// information for developers only, normal users get general error message
1440
$this->assertEquals($e->errorcode, 'ddlfieldnotexist');
1429
// Information for developers only, normal users get general error message.
1430
$this->assertSame('ddlfieldnotexist', $e->errorcode);
1444
// note: delegate limits testing to test_get_records_sql()
1434
// Note: delegate limits testing to test_get_records_sql().
1447
1437
public function test_get_records_list() {
1510
1498
$DB->insert_record($tablename2, array('course'=>6, 'nametext'=>'badabong'));
1512
1500
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3));
1513
$this->assertEquals(2, count($records));
1501
$this->assertCount(2, $records);
1514
1502
$this->assertEquals($inskey1, reset($records)->id);
1515
1503
$this->assertEquals($inskey4, next($records)->id);
1517
// Awful test, requires debug enabled and sent to browser. Let's do that and restore after test
1505
// Awful test, requires debug enabled and sent to browser. Let's do that and restore after test.
1518
1506
$records = $DB->get_records_sql("SELECT course AS id, course AS course FROM {{$tablename}}", null);
1519
1507
$this->assertDebuggingCalled();
1520
$this->assertEquals(6, count($records));
1521
$CFG->debug = DEBUG_MINIMAL;
1508
$this->assertCount(6, $records);
1509
set_debugging(DEBUG_MINIMAL);
1522
1510
$records = $DB->get_records_sql("SELECT course AS id, course AS course FROM {{$tablename}}", null);
1523
1511
$this->assertDebuggingNotCalled();
1524
$this->assertEquals(6, count($records));
1525
$CFG->debug = DEBUG_DEVELOPER;
1512
$this->assertCount(6, $records);
1513
set_debugging(DEBUG_DEVELOPER);
1527
// negative limits = no limits
1515
// Negative limits = no limits.
1528
1516
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, -1, -1);
1529
$this->assertEquals(7, count($records));
1517
$this->assertCount(7, $records);
1531
// zero limits = no limits
1519
// Zero limits = no limits.
1532
1520
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 0);
1533
$this->assertEquals(7, count($records));
1521
$this->assertCount(7, $records);
1535
// only limitfrom = skips that number of records
1523
// Only limitfrom = skips that number of records.
1536
1524
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0);
1537
$this->assertEquals(5, count($records));
1525
$this->assertCount(5, $records);
1538
1526
$this->assertEquals($inskey3, reset($records)->id);
1539
1527
$this->assertEquals($inskey7, end($records)->id);
1541
// only limitnum = fetches that number of records
1529
// Only limitnum = fetches that number of records.
1542
1530
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 3);
1543
$this->assertEquals(3, count($records));
1531
$this->assertCount(3, $records);
1544
1532
$this->assertEquals($inskey1, reset($records)->id);
1545
1533
$this->assertEquals($inskey3, end($records)->id);
1547
// both limitfrom and limitnum = skips limitfrom records and fetches limitnum ones
1535
// Both limitfrom and limitnum = skips limitfrom records and fetches limitnum ones.
1548
1536
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 3, 2);
1549
$this->assertEquals(2, count($records));
1537
$this->assertCount(2, $records);
1550
1538
$this->assertEquals($inskey4, reset($records)->id);
1551
1539
$this->assertEquals($inskey5, end($records)->id);
1553
// both limitfrom and limitnum in query having subqueris
1554
// note the subquery skips records with course = 0 and 3
1541
// Both limitfrom and limitnum in query having subqueris.
1542
// Note the subquery skips records with course = 0 and 3.
1555
1543
$sql = "SELECT * FROM {{$tablename}}
1556
1544
WHERE course NOT IN (
1557
1545
SELECT course FROM {{$tablename}}
1558
1546
WHERE course IN (0, 3))
1559
1547
ORDER BY course";
1560
$records = $DB->get_records_sql($sql, null, 0, 2); // Skip 0, get 2
1561
$this->assertEquals(2, count($records));
1548
$records = $DB->get_records_sql($sql, null, 0, 2); // Skip 0, get 2.
1549
$this->assertCount(2, $records);
1562
1550
$this->assertEquals($inskey6, reset($records)->id);
1563
1551
$this->assertEquals($inskey5, end($records)->id);
1564
$records = $DB->get_records_sql($sql, null, 2, 2); // Skip 2, get 2
1565
$this->assertEquals(2, count($records));
1552
$records = $DB->get_records_sql($sql, null, 2, 2); // Skip 2, get 2.
1553
$this->assertCount(2, $records);
1566
1554
$this->assertEquals($inskey3, reset($records)->id);
1567
1555
$this->assertEquals($inskey2, end($records)->id);
1569
// test 2 tables with aliases and limits with order bys
1557
// Test 2 tables with aliases and limits with order bys.
1570
1558
$sql = "SELECT t1.id, t1.course AS cid, t2.nametext
1571
1559
FROM {{$tablename}} t1, {{$tablename2}} t2
1572
1560
WHERE t2.course=t1.course
1573
1561
ORDER BY t1.course, ". $DB->sql_compare_text('t2.nametext');
1574
$records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5
1575
$this->assertEquals(2, count($records));
1576
$this->assertEquals('5', end($records)->cid);
1577
$this->assertEquals('4', reset($records)->cid);
1579
// test 2 tables with aliases and limits with the highest INT limit works
1580
$records = $DB->get_records_sql($sql, null, 2, PHP_INT_MAX); // Skip course {3,6}, get {4,5}
1581
$this->assertEquals(2, count($records));
1582
$this->assertEquals('5', end($records)->cid);
1583
$this->assertEquals('4', reset($records)->cid);
1585
// test 2 tables with aliases and limits with order bys (limit which is highest INT number)
1586
$records = $DB->get_records_sql($sql, null, PHP_INT_MAX, 2); // Skip all courses
1587
$this->assertEquals(0, count($records));
1589
// test 2 tables with aliases and limits with order bys (limit which s highest INT number)
1590
$records = $DB->get_records_sql($sql, null, PHP_INT_MAX, PHP_INT_MAX); // Skip all courses
1591
$this->assertEquals(0, count($records));
1593
// TODO: Test limits in queries having DISTINCT clauses
1595
// note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here
1562
$records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5.
1563
$this->assertCount(2, $records);
1564
$this->assertSame('5', end($records)->cid);
1565
$this->assertSame('4', reset($records)->cid);
1567
// Test 2 tables with aliases and limits with the highest INT limit works.
1568
$records = $DB->get_records_sql($sql, null, 2, PHP_INT_MAX); // Skip course {3,6}, get {4,5}.
1569
$this->assertCount(2, $records);
1570
$this->assertSame('5', end($records)->cid);
1571
$this->assertSame('4', reset($records)->cid);
1573
// Test 2 tables with aliases and limits with order bys (limit which is highest INT number).
1574
$records = $DB->get_records_sql($sql, null, PHP_INT_MAX, 2); // Skip all courses.
1575
$this->assertCount(0, $records);
1577
// Test 2 tables with aliases and limits with order bys (limit which s highest INT number).
1578
$records = $DB->get_records_sql($sql, null, PHP_INT_MAX, PHP_INT_MAX); // Skip all courses.
1579
$this->assertCount(0, $records);
1581
// TODO: Test limits in queries having DISTINCT clauses.
1583
// Note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here.
1598
1586
public function test_get_records_menu() {
1726
1714
$DB->insert_record($tablename, array('course' => 2));
1728
1716
$record = $DB->get_record_select($tablename, "id = ?", array(2));
1729
$this->assertTrue($record instanceof stdClass);
1717
$this->assertInstanceOf('stdClass', $record);
1731
1719
$this->assertEquals(2, $record->course);
1733
// note: delegates limit testing to test_get_records_sql()
1721
// Note: delegates limit testing to test_get_records_sql().
1736
1724
public function test_get_record_sql() {
1739
1725
$DB = $this->tdb;
1740
1726
$dbman = $DB->get_manager();
1742
1728
$table = $this->get_test_table();
1743
1729
$tablename = $table->getName();
1745
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1746
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1731
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1732
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1747
1733
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1748
1734
$dbman->create_table($table);
1750
1736
$DB->insert_record($tablename, array('course' => 3));
1751
1737
$DB->insert_record($tablename, array('course' => 2));
1754
1740
$record = $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(2));
1755
$this->assertTrue($record instanceof stdClass);
1741
$this->assertInstanceOf('stdClass', $record);
1756
1742
$this->assertEquals(2, $record->course);
1757
1743
$this->assertEquals(2, $record->id);
1759
// backwards compatibility with $ignoremultiple
1745
// Backwards compatibility with $ignoremultiple.
1760
1746
$this->assertFalse((bool)IGNORE_MISSING);
1761
1747
$this->assertTrue((bool)IGNORE_MULTIPLE);
1763
// record not found - ignore
1749
// Record not found - ignore.
1764
1750
$this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MISSING));
1765
1751
$this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MULTIPLE));
1767
// record not found error
1753
// Record not found error.
1769
1755
$DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), MUST_EXIST);
1770
1756
$this->fail("Exception expected");
3258
3241
$table = $this->get_test_table();
3259
3242
$tablename = $table->getName();
3260
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3261
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3243
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3244
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3262
3245
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3263
3246
$dbman->create_table($table);
3265
$o = new stdClass(); // objects without __toString - never worked
3248
$o = new stdClass(); // Objects without __toString - never worked.
3267
3250
$DB->fix_sql_params("SELECT {{$tablename}} WHERE course = ? ", array($o));
3268
3251
$this->fail('coding_exception expected');
3269
} catch (Exception $e) {
3270
$this->assertTrue($e instanceof coding_exception);
3252
} catch (moodle_exception $e) {
3253
$this->assertInstanceOf('coding_exception', $e);
3273
// objects with __toString() forbidden everywhere since 2.3
3256
// Objects with __toString() forbidden everywhere since 2.3.
3274
3257
$o = new dml_test_object_one();
3276
3259
$DB->fix_sql_params("SELECT {{$tablename}} WHERE course = ? ", array($o));
3277
3260
$this->fail('coding_exception expected');
3278
} catch (Exception $e) {
3279
$this->assertTrue($e instanceof coding_exception);
3261
} catch (moodle_exception $e) {
3262
$this->assertInstanceOf('coding_exception', $e);
3283
3266
$DB->execute("SELECT {{$tablename}} WHERE course = ? ", array($o));
3284
3267
$this->fail('coding_exception expected');
3285
} catch (Exception $e) {
3286
$this->assertTrue($e instanceof coding_exception);
3268
} catch (moodle_exception $e) {
3269
$this->assertInstanceOf('coding_exception', $e);
3290
3273
$DB->get_recordset_sql("SELECT {{$tablename}} WHERE course = ? ", array($o));
3291
3274
$this->fail('coding_exception expected');
3292
} catch (Exception $e) {
3293
$this->assertTrue($e instanceof coding_exception);
3275
} catch (moodle_exception $e) {
3276
$this->assertInstanceOf('coding_exception', $e);
3297
3280
$DB->get_records_sql("SELECT {{$tablename}} WHERE course = ? ", array($o));
3298
3281
$this->fail('coding_exception expected');
3299
} catch (Exception $e) {
3300
$this->assertTrue($e instanceof coding_exception);
3282
} catch (moodle_exception $e) {
3283
$this->assertInstanceOf('coding_exception', $e);
3343
3326
$record->course = $o;
3344
3327
$DB->update_record($tablename, $record);
3345
3328
$this->fail('coding_exception expected');
3346
} catch (Exception $e) {
3347
$this->assertTrue($e instanceof coding_exception);
3329
} catch (moodle_exception $e) {
3330
$this->assertInstanceOf('coding_exception', $e);
3351
3334
$DB->set_field_select($tablename, 'course', 1, "course = ? ", array($o));
3352
3335
$this->fail('coding_exception expected');
3353
} catch (Exception $e) {
3354
$this->assertTrue($e instanceof coding_exception);
3336
} catch (moodle_exception $e) {
3337
$this->assertInstanceOf('coding_exception', $e);
3358
3341
$DB->delete_records_select($tablename, "course = ? ", array($o));
3359
3342
$this->fail('coding_exception expected');
3360
} catch (Exception $e) {
3361
$this->assertTrue($e instanceof coding_exception);
3343
} catch (moodle_exception $e) {
3344
$this->assertInstanceOf('coding_exception', $e);
3365
function test_sql_null_from_clause() {
3348
public function test_sql_null_from_clause() {
3366
3349
$DB = $this->tdb;
3367
3350
$sql = "SELECT 1 AS id ".$DB->sql_null_from_clause();
3368
$this->assertEquals($DB->get_field_sql($sql), 1);
3351
$this->assertEquals(1, $DB->get_field_sql($sql));
3371
function test_sql_bitand() {
3354
public function test_sql_bitand() {
3372
3355
$DB = $this->tdb;
3373
3356
$dbman = $DB->get_manager();
3375
3358
$table = $this->get_test_table();
3376
3359
$tablename = $table->getName();
3378
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3379
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3380
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3361
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3362
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3363
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3381
3364
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3382
3365
$dbman->create_table($table);
3384
3367
$DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3386
3369
$sql = "SELECT ".$DB->sql_bitand(10, 3)." AS res ".$DB->sql_null_from_clause();
3387
$this->assertEquals($DB->get_field_sql($sql), 2);
3370
$this->assertEquals(2, $DB->get_field_sql($sql));
3389
3372
$sql = "SELECT id, ".$DB->sql_bitand('col1', 'col2')." AS res FROM {{$tablename}}";
3390
3373
$result = $DB->get_records_sql($sql);
3391
$this->assertEquals(count($result), 1);
3392
$this->assertEquals(reset($result)->res, 2);
3374
$this->assertCount(1, $result);
3375
$this->assertEquals(2, reset($result)->res);
3394
3377
$sql = "SELECT id, ".$DB->sql_bitand('col1', '?')." AS res FROM {{$tablename}}";
3395
3378
$result = $DB->get_records_sql($sql, array(10));
3396
$this->assertEquals(count($result), 1);
3397
$this->assertEquals(reset($result)->res, 2);
3379
$this->assertCount(1, $result);
3380
$this->assertEquals(2, reset($result)->res);
3400
function test_sql_bitnot() {
3383
public function test_sql_bitnot() {
3401
3384
$DB = $this->tdb;
3403
3386
$not = $DB->sql_bitnot(2);
3404
$notlimited = $DB->sql_bitand($not, 7); // might be positive or negative number which can not fit into PHP INT!
3387
$notlimited = $DB->sql_bitand($not, 7); // Might be positive or negative number which can not fit into PHP INT!
3406
3389
$sql = "SELECT $notlimited AS res ".$DB->sql_null_from_clause();
3407
$this->assertEquals($DB->get_field_sql($sql), 5);
3390
$this->assertEquals(5, $DB->get_field_sql($sql));
3410
function test_sql_bitor() {
3393
public function test_sql_bitor() {
3411
3394
$DB = $this->tdb;
3412
3395
$dbman = $DB->get_manager();
3414
3397
$table = $this->get_test_table();
3415
3398
$tablename = $table->getName();
3417
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3418
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3419
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3400
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3401
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3402
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3420
3403
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3421
3404
$dbman->create_table($table);
3423
3406
$DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3425
3408
$sql = "SELECT ".$DB->sql_bitor(10, 3)." AS res ".$DB->sql_null_from_clause();
3426
$this->assertEquals($DB->get_field_sql($sql), 11);
3409
$this->assertEquals(11, $DB->get_field_sql($sql));
3428
3411
$sql = "SELECT id, ".$DB->sql_bitor('col1', 'col2')." AS res FROM {{$tablename}}";
3429
3412
$result = $DB->get_records_sql($sql);
3430
$this->assertEquals(count($result), 1);
3431
$this->assertEquals(reset($result)->res, 11);
3413
$this->assertCount(1, $result);
3414
$this->assertEquals(11, reset($result)->res);
3433
3416
$sql = "SELECT id, ".$DB->sql_bitor('col1', '?')." AS res FROM {{$tablename}}";
3434
3417
$result = $DB->get_records_sql($sql, array(10));
3435
$this->assertEquals(count($result), 1);
3436
$this->assertEquals(reset($result)->res, 11);
3418
$this->assertCount(1, $result);
3419
$this->assertEquals(11, reset($result)->res);
3439
function test_sql_bitxor() {
3422
public function test_sql_bitxor() {
3440
3423
$DB = $this->tdb;
3441
3424
$dbman = $DB->get_manager();
3443
3426
$table = $this->get_test_table();
3444
3427
$tablename = $table->getName();
3446
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3447
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3448
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3429
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3430
$table->add_field('col1', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3431
$table->add_field('col2', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3449
3432
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3450
3433
$dbman->create_table($table);
3452
3435
$DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3454
3437
$sql = "SELECT ".$DB->sql_bitxor(10, 3)." AS res ".$DB->sql_null_from_clause();
3455
$this->assertEquals($DB->get_field_sql($sql), 9);
3438
$this->assertEquals(9, $DB->get_field_sql($sql));
3457
3440
$sql = "SELECT id, ".$DB->sql_bitxor('col1', 'col2')." AS res FROM {{$tablename}}";
3458
3441
$result = $DB->get_records_sql($sql);
3459
$this->assertEquals(count($result), 1);
3460
$this->assertEquals(reset($result)->res, 9);
3442
$this->assertCount(1, $result);
3443
$this->assertEquals(9, reset($result)->res);
3462
3445
$sql = "SELECT id, ".$DB->sql_bitxor('col1', '?')." AS res FROM {{$tablename}}";
3463
3446
$result = $DB->get_records_sql($sql, array(10));
3464
$this->assertEquals(count($result), 1);
3465
$this->assertEquals(reset($result)->res, 9);
3447
$this->assertCount(1, $result);
3448
$this->assertEquals(9, reset($result)->res);
3468
function test_sql_modulo() {
3451
public function test_sql_modulo() {
3469
3452
$DB = $this->tdb;
3470
3453
$sql = "SELECT ".$DB->sql_modulo(10, 7)." AS res ".$DB->sql_null_from_clause();
3471
$this->assertEquals($DB->get_field_sql($sql), 3);
3454
$this->assertEquals(3, $DB->get_field_sql($sql));
3474
function test_sql_ceil() {
3457
public function test_sql_ceil() {
3475
3458
$DB = $this->tdb;
3476
3459
$sql = "SELECT ".$DB->sql_ceil(665.666)." AS res ".$DB->sql_null_from_clause();
3477
$this->assertEquals($DB->get_field_sql($sql), 666);
3460
$this->assertEquals(666, $DB->get_field_sql($sql));
3480
function test_cast_char2int() {
3463
public function test_cast_char2int() {
3481
3464
$DB = $this->tdb;
3482
3465
$dbman = $DB->get_manager();
3484
3467
$table1 = $this->get_test_table("1");
3485
3468
$tablename1 = $table1->getName();
3487
$table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3470
$table1->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3488
3471
$table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3489
3472
$table1->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3490
3473
$table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3496
3479
$table2 = $this->get_test_table("2");
3497
3480
$tablename2 = $table2->getName();
3498
$table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3499
$table2->add_field('res', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3500
$table2->add_field('restext', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3481
$table2->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3482
$table2->add_field('res', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3483
$table2->add_field('restext', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
3501
3484
$table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3502
3485
$dbman->create_table($table2);
3504
3487
$DB->insert_record($tablename2, array('res'=>100, 'restext'=>200));
3506
// casting varchar field
3489
// Casting varchar field.
3507
3490
$sql = "SELECT *
3508
3491
FROM {".$tablename1."} t1
3509
3492
JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.name")." = t2.res ";
3510
3493
$records = $DB->get_records_sql($sql);
3511
$this->assertEquals(count($records), 1);
3512
// also test them in order clauses
3494
$this->assertCount(1, $records);
3495
// Also test them in order clauses.
3513
3496
$sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('name');
3514
3497
$records = $DB->get_records_sql($sql);
3515
$this->assertEquals(count($records), 2);
3516
$this->assertEquals(reset($records)->name, '10');
3517
$this->assertEquals(next($records)->name, '0100');
3498
$this->assertCount(2, $records);
3499
$this->assertSame('10', reset($records)->name);
3500
$this->assertSame('0100', next($records)->name);
3519
// casting text field
3502
// Casting text field.
3520
3503
$sql = "SELECT *
3521
3504
FROM {".$tablename1."} t1
3522
3505
JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.nametext", true)." = t2.restext ";
3523
3506
$records = $DB->get_records_sql($sql);
3524
$this->assertEquals(count($records), 1);
3525
// also test them in order clauses
3507
$this->assertCount(1, $records);
3508
// Also test them in order clauses.
3526
3509
$sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('nametext', true);
3527
3510
$records = $DB->get_records_sql($sql);
3528
$this->assertEquals(count($records), 2);
3529
$this->assertEquals(reset($records)->nametext, '20');
3530
$this->assertEquals(next($records)->nametext, '0200');
3511
$this->assertCount(2, $records);
3512
$this->assertSame('20', reset($records)->nametext);
3513
$this->assertSame('0200', next($records)->nametext);
3533
function test_cast_char2real() {
3516
public function test_cast_char2real() {
3534
3517
$DB = $this->tdb;
3535
3518
$dbman = $DB->get_manager();
3537
3520
$table = $this->get_test_table();
3538
3521
$tablename = $table->getName();
3540
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3523
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3541
3524
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3542
3525
$table->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3543
3526
$table->add_field('res', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null);
3547
3530
$DB->insert_record($tablename, array('name'=>'10.10', 'nametext'=>'10.10', 'res'=>5.1));
3548
3531
$DB->insert_record($tablename, array('name'=>'91.10', 'nametext'=>'91.10', 'res'=>666));
3549
$DB->insert_record($tablename, array('name'=>'011.10','nametext'=>'011.10','res'=>10.1));
3532
$DB->insert_record($tablename, array('name'=>'011.10', 'nametext'=>'011.10', 'res'=>10.1));
3551
// casting varchar field
3534
// Casting varchar field.
3552
3535
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('name')." > res";
3553
3536
$records = $DB->get_records_sql($sql);
3554
$this->assertEquals(count($records), 2);
3555
// also test them in order clauses
3537
$this->assertCount(2, $records);
3538
// Also test them in order clauses.
3556
3539
$sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('name');
3557
3540
$records = $DB->get_records_sql($sql);
3558
$this->assertEquals(count($records), 3);
3559
$this->assertEquals(reset($records)->name, '10.10');
3560
$this->assertEquals(next($records)->name, '011.10');
3561
$this->assertEquals(next($records)->name, '91.10');
3541
$this->assertCount(3, $records);
3542
$this->assertSame('10.10', reset($records)->name);
3543
$this->assertSame('011.10', next($records)->name);
3544
$this->assertSame('91.10', next($records)->name);
3563
// casting text field
3546
// Casting text field.
3564
3547
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('nametext', true)." > res";
3565
3548
$records = $DB->get_records_sql($sql);
3566
$this->assertEquals(count($records), 2);
3567
// also test them in order clauses
3549
$this->assertCount(2, $records);
3550
// Also test them in order clauses.
3568
3551
$sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('nametext', true);
3569
3552
$records = $DB->get_records_sql($sql);
3570
$this->assertEquals(count($records), 3);
3571
$this->assertEquals(reset($records)->nametext, '10.10');
3572
$this->assertEquals(next($records)->nametext, '011.10');
3573
$this->assertEquals(next($records)->nametext, '91.10');
3553
$this->assertCount(3, $records);
3554
$this->assertSame('10.10', reset($records)->nametext);
3555
$this->assertSame('011.10', next($records)->nametext);
3556
$this->assertSame('91.10', next($records)->nametext);
3576
3559
public function test_sql_compare_text() {
3716
3699
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false);
3717
3700
$records = $DB->get_records_sql($sql, array("%dup_r%"));
3718
$this->assertEquals(count($records), 2);
3701
$this->assertCount(2, $records);
3720
3703
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true);
3721
3704
$records = $DB->get_records_sql($sql, array("%dup%"));
3722
$this->assertEquals(count($records), 1);
3705
$this->assertCount(1, $records);
3724
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?'); // defaults
3707
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?'); // Defaults.
3725
3708
$records = $DB->get_records_sql($sql, array("%dup%"));
3726
$this->assertEquals(count($records), 1);
3709
$this->assertCount(1, $records);
3728
3711
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true);
3729
3712
$records = $DB->get_records_sql($sql, array("ouc\\_"));
3730
$this->assertEquals(count($records), 1);
3713
$this->assertCount(1, $records);
3732
3715
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, false, '|');
3733
3716
$records = $DB->get_records_sql($sql, array($DB->sql_like_escape("ouc%", '|')));
3734
$this->assertEquals(count($records), 1);
3717
$this->assertCount(1, $records);
3736
3719
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true);
3737
3720
$records = $DB->get_records_sql($sql, array('aui'));
3738
$this->assertEquals(count($records), 1);
3721
$this->assertCount(1, $records);
3740
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, true); // NOT LIKE
3723
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, true); // NOT LIKE.
3741
3724
$records = $DB->get_records_sql($sql, array("%o%"));
3742
$this->assertEquals(count($records), 3);
3725
$this->assertCount(3, $records);
3744
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, true, true); // NOT ILIKE
3727
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, true, true); // NOT ILIKE.
3745
3728
$records = $DB->get_records_sql($sql, array("%D%"));
3746
$this->assertEquals(count($records), 6);
3729
$this->assertCount(6, $records);
3748
// verify usual escaping characters work fine
3731
// Verify usual escaping characters work fine.
3749
3732
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, false, '\\');
3750
3733
$records = $DB->get_records_sql($sql, array("ouc\\_"));
3751
$this->assertEquals(count($records), 1);
3734
$this->assertCount(1, $records);
3752
3735
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, false, '|');
3753
3736
$records = $DB->get_records_sql($sql, array("ouc|%"));
3754
$this->assertEquals(count($records), 1);
3737
$this->assertCount(1, $records);
3756
// TODO: we do not require accent insensitivness yet, just make sure it does not throw errors
3739
// TODO: we do not require accent insensitivness yet, just make sure it does not throw errors.
3757
3740
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, false);
3758
3741
$records = $DB->get_records_sql($sql, array('aui'));
3759
//$this->assertEquals(count($records), 2, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3742
// $this->assertEquals(2, count($records), 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3760
3743
$sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, false);
3761
3744
$records = $DB->get_records_sql($sql, array('aui'));
3762
//$this->assertEquals(count($records), 3, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3745
// $this->assertEquals(3, count($records), 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3765
function test_coalesce() {
3748
public function test_coalesce() {
3766
3749
$DB = $this->tdb;
3768
// Testing not-null occurrences, return 1st
3751
// Testing not-null occurrences, return 1st.
3769
3752
$sql = "SELECT COALESCE('returnthis', 'orthis', 'orwhynotthis') AS test" . $DB->sql_null_from_clause();
3770
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array()));
3753
$this->assertSame('returnthis', $DB->get_field_sql($sql, array()));
3771
3754
$sql = "SELECT COALESCE(:paramvalue, 'orthis', 'orwhynotthis') AS test" . $DB->sql_null_from_clause();
3772
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3755
$this->assertSame('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3774
// Testing null occurrences, return 2nd
3757
// Testing null occurrences, return 2nd.
3775
3758
$sql = "SELECT COALESCE(null, 'returnthis', 'orthis') AS test" . $DB->sql_null_from_clause();
3776
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array()));
3759
$this->assertSame('returnthis', $DB->get_field_sql($sql, array()));
3777
3760
$sql = "SELECT COALESCE(:paramvalue, 'returnthis', 'orthis') AS test" . $DB->sql_null_from_clause();
3778
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null)));
3761
$this->assertSame('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null)));
3779
3762
$sql = "SELECT COALESCE(null, :paramvalue, 'orthis') AS test" . $DB->sql_null_from_clause();
3780
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3763
$this->assertSame('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3782
// Testing null occurrences, return 3rd
3765
// Testing null occurrences, return 3rd.
3783
3766
$sql = "SELECT COALESCE(null, null, 'returnthis') AS test" . $DB->sql_null_from_clause();
3784
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array()));
3767
$this->assertSame('returnthis', $DB->get_field_sql($sql, array()));
3785
3768
$sql = "SELECT COALESCE(null, :paramvalue, 'returnthis') AS test" . $DB->sql_null_from_clause();
3786
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null)));
3769
$this->assertSame('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null)));
3787
3770
$sql = "SELECT COALESCE(null, null, :paramvalue) AS test" . $DB->sql_null_from_clause();
3788
$this->assertEquals('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3771
$this->assertSame('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis')));
3790
// Testing all null occurrences, return null
3773
// Testing all null occurrences, return null.
3791
3774
// Note: under mssql, if all elements are nulls, at least one must be a "typed" null, hence
3792
3775
// we cannot test this in a cross-db way easily, so next 2 tests are using
3793
// different queries depending of the DB family
3776
// different queries depending of the DB family.
3794
3777
$customnull = $DB->get_dbfamily() == 'mssql' ? 'CAST(null AS varchar)' : 'null';
3795
3778
$sql = "SELECT COALESCE(null, null, " . $customnull . ") AS test" . $DB->sql_null_from_clause();
3796
3779
$this->assertNull($DB->get_field_sql($sql, array()));
3797
3780
$sql = "SELECT COALESCE(null, :paramvalue, " . $customnull . ") AS test" . $DB->sql_null_from_clause();
3798
3781
$this->assertNull($DB->get_field_sql($sql, array('paramvalue' => null)));
3800
// Check there are not problems with whitespace strings
3801
$sql = "SELECT COALESCE(null, '', null) AS test" . $DB->sql_null_from_clause();
3802
$this->assertEquals('', $DB->get_field_sql($sql, array()));
3783
// Check there are not problems with whitespace strings.
3803
3784
$sql = "SELECT COALESCE(null, :paramvalue, null) AS test" . $DB->sql_null_from_clause();
3804
$this->assertEquals('', $DB->get_field_sql($sql, array('paramvalue' => '')));
3785
$this->assertSame('', $DB->get_field_sql($sql, array('paramvalue' => '')));
3807
function test_sql_concat() {
3788
public function test_sql_concat() {
3808
3789
$DB = $this->tdb;
3809
3790
$dbman = $DB->get_manager();
3811
// Testing all sort of values
3792
// Testing all sort of values.
3812
3793
$sql = "SELECT ".$DB->sql_concat("?", "?", "?")." AS fullname ". $DB->sql_null_from_clause();
3813
// string, some unicode chars
3794
// String, some unicode chars.
3814
3795
$params = array('name', 'áéíóú', 'name3');
3815
$this->assertEquals('nameáéíóúname3', $DB->get_field_sql($sql, $params));
3816
// string, spaces and numbers
3796
$this->assertSame('nameáéíóúname3', $DB->get_field_sql($sql, $params));
3797
// String, spaces and numbers.
3817
3798
$params = array('name', ' ', 12345);
3818
$this->assertEquals('name 12345', $DB->get_field_sql($sql, $params));
3819
// float, empty and strings
3799
$this->assertSame('name 12345', $DB->get_field_sql($sql, $params));
3800
// Float, empty and strings.
3820
3801
$params = array(123.45, '', 'test');
3821
$this->assertEquals('123.45test', $DB->get_field_sql($sql, $params));
3802
$this->assertSame('123.45test', $DB->get_field_sql($sql, $params));
3823
3804
$params = array(12, 34, 56);
3824
$this->assertEquals('123456', $DB->get_field_sql($sql, $params));
3825
// float, null and strings
3805
$this->assertSame('123456', $DB->get_field_sql($sql, $params));
3806
// Float, null and strings.
3826
3807
$params = array(123.45, null, 'test');
3827
$this->assertNull($DB->get_field_sql($sql, $params)); // Concatenate NULL with anything result = NULL
3808
$this->assertNull($DB->get_field_sql($sql, $params)); // Concatenate null with anything result = null.
3829
// Testing fieldnames + values and also integer fieldnames
3810
// Testing fieldnames + values and also integer fieldnames.
3830
3811
$table = $this->get_test_table();
3831
3812
$tablename = $table->getName();
3833
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3814
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3834
3815
$table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3835
3816
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3836
3817
$dbman->create_table($table);
3970
3951
$DB->insert_record($tablename, array('name'=>0));
3972
3953
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array(''));
3973
$this->assertEquals(count($records), 1);
3954
$this->assertCount(1, $records);
3974
3955
$record = reset($records);
3975
$this->assertEquals($record->name, '');
3956
$this->assertSame('', $record->name);
3977
3958
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnull = ?", array(''));
3978
$this->assertEquals(count($records), 1);
3959
$this->assertCount(1, $records);
3979
3960
$record = reset($records);
3980
$this->assertEquals($record->namenotnull, '');
3961
$this->assertSame('', $record->namenotnull);
3982
3963
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnullnodeflt = ?", array(''));
3983
$this->assertEquals(count($records), 4);
3964
$this->assertCount(4, $records);
3984
3965
$record = reset($records);
3985
$this->assertEquals($record->namenotnullnodeflt, '');
3966
$this->assertSame('', $record->namenotnullnodeflt);
3988
function test_sql_isempty() {
3969
public function test_sql_isempty() {
3989
3970
$DB = $this->tdb;
3990
3971
$dbman = $DB->get_manager();
3992
3973
$table = $this->get_test_table();
3993
3974
$tablename = $table->getName();
3995
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3976
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3996
3977
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3997
3978
$table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3998
3979
$table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null);
4006
3987
$DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0));
4008
3989
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'name', false, false));
4009
$this->assertEquals(count($records), 1);
3990
$this->assertCount(1, $records);
4010
3991
$record = reset($records);
4011
$this->assertEquals($record->name, '');
3992
$this->assertSame('', $record->name);
4013
3994
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'namenull', true, false));
4014
$this->assertEquals(count($records), 1);
3995
$this->assertCount(1, $records);
4015
3996
$record = reset($records);
4016
$this->assertEquals($record->namenull, '');
3997
$this->assertSame('', $record->namenull);
4018
3999
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'description', false, true));
4019
$this->assertEquals(count($records), 1);
4000
$this->assertCount(1, $records);
4020
4001
$record = reset($records);
4021
$this->assertEquals($record->description, '');
4002
$this->assertSame('', $record->description);
4023
4004
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'descriptionnull', true, true));
4024
$this->assertEquals(count($records), 1);
4005
$this->assertCount(1, $records);
4025
4006
$record = reset($records);
4026
$this->assertEquals($record->descriptionnull, '');
4007
$this->assertSame('', $record->descriptionnull);
4029
function test_sql_isnotempty() {
4010
public function test_sql_isnotempty() {
4030
4011
$DB = $this->tdb;
4031
4012
$dbman = $DB->get_manager();
4033
4014
$table = $this->get_test_table();
4034
4015
$tablename = $table->getName();
4036
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4017
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4037
4018
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
4038
4019
$table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null);
4039
4020
$table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null);
4047
4028
$DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0));
4049
4030
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'name', false, false));
4050
$this->assertEquals(count($records), 3);
4031
$this->assertCount(3, $records);
4051
4032
$record = reset($records);
4052
$this->assertEquals($record->name, '??');
4033
$this->assertSame('??', $record->name);
4054
4035
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'namenull', true, false));
4055
$this->assertEquals(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour
4036
$this->assertCount(2, $records); // Nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour.
4056
4037
$record = reset($records);
4057
$this->assertEquals($record->namenull, 'la'); // so 'la' is the first non-empty 'namenull' record
4038
$this->assertSame('la', $record->namenull); // So 'la' is the first non-empty 'namenull' record.
4059
4040
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'description', false, true));
4060
$this->assertEquals(count($records), 3);
4041
$this->assertCount(3, $records);
4061
4042
$record = reset($records);
4062
$this->assertEquals($record->description, '??');
4043
$this->assertSame('??', $record->description);
4064
4045
$records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'descriptionnull', true, true));
4065
$this->assertEquals(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour
4046
$this->assertCount(2, $records); // Nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour.
4066
4047
$record = reset($records);
4067
$this->assertEquals($record->descriptionnull, 'lalala'); // so 'lalala' is the first non-empty 'descriptionnull' record
4048
$this->assertSame('lalala', $record->descriptionnull); // So 'lalala' is the first non-empty 'descriptionnull' record.
4070
function test_sql_regex() {
4051
public function test_sql_regex() {
4071
4052
$DB = $this->tdb;
4072
4053
$dbman = $DB->get_manager();
4074
4055
$table = $this->get_test_table();
4075
4056
$tablename = $table->getName();
4077
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4058
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4078
4059
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
4079
4060
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
4080
4061
$dbman->create_table($table);
4181
4162
// Verify also array keys, order is important in this test.
4182
4163
$this->assertEquals(array_keys($result), array_keys($records));
4184
// test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268
4165
// Test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268.
4185
4166
$sql = "SELECT DISTINCT course
4186
4167
FROM {{$tablename}}
4187
4168
ORDER BY course";
4189
4170
$records = $DB->get_records_sql($sql, null, 1);
4190
$this->assertEquals(2, count($records));
4171
$this->assertCount(2, $records);
4191
4172
$this->assertEquals(3, reset($records)->course);
4192
4173
$this->assertEquals(5, next($records)->course);
4194
4175
$records = $DB->get_records_sql($sql, null, 0, 2);
4195
$this->assertEquals(2, count($records));
4176
$this->assertCount(2, $records);
4196
4177
$this->assertEquals(2, reset($records)->course);
4197
4178
$this->assertEquals(3, next($records)->course);
4198
// both limitfrom and limitnum
4179
// Both limitfrom and limitnum.
4199
4180
$records = $DB->get_records_sql($sql, null, 2, 2);
4200
$this->assertEquals(1, count($records));
4181
$this->assertCount(1, $records);
4201
4182
$this->assertEquals(5, reset($records)->course);
4203
// we have sql like this in moodle, this syntax breaks on older versions of sqlite for example..
4184
// We have sql like this in moodle, this syntax breaks on older versions of sqlite for example..
4204
4185
$sql = "SELECT a.id AS id, a.course AS course
4205
4186
FROM {{$tablename}} a
4206
4187
JOIN (SELECT * FROM {{$tablename}}) b ON a.id = b.id
4207
4188
WHERE a.course = ?";
4209
4190
$records = $DB->get_records_sql($sql, array(3));
4210
$this->assertEquals(2, count($records));
4191
$this->assertCount(2, $records);
4211
4192
$this->assertEquals(1, reset($records)->id);
4212
4193
$this->assertEquals(2, next($records)->id);
4214
// do NOT try embedding sql_xxxx() helper functions in conditions array of count_records(), they don't break params/binding!
4195
// Do NOT try embedding sql_xxxx() helper functions in conditions array of count_records(), they don't break params/binding!
4215
4196
$count = $DB->count_records_select($tablename, "course = :course AND ".$DB->sql_compare_text('content')." = :content", array('course' => 3, 'content' => 'hello'));
4216
4197
$this->assertEquals(1, $count);
4218
// test int x string comparison
4199
// Test int x string comparison.
4219
4200
$sql = "SELECT *
4220
4201
FROM {{$tablename}} c
4221
4202
WHERE name = ?";
4222
$this->assertEquals(count($DB->get_records_sql($sql, array(10))), 0);
4223
$this->assertEquals(count($DB->get_records_sql($sql, array("10"))), 0);
4203
$this->assertCount(0, $DB->get_records_sql($sql, array(10)));
4204
$this->assertCount(0, $DB->get_records_sql($sql, array("10")));
4224
4205
$DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1'));
4225
4206
$DB->insert_record($tablename, array('course' => 7, 'content' => 'yy', 'name'=>'2'));
4226
$this->assertEquals(count($DB->get_records_sql($sql, array(1))), 1);
4227
$this->assertEquals(count($DB->get_records_sql($sql, array("1"))), 1);
4228
$this->assertEquals(count($DB->get_records_sql($sql, array(10))), 0);
4229
$this->assertEquals(count($DB->get_records_sql($sql, array("10"))), 0);
4207
$this->assertCount(1, $DB->get_records_sql($sql, array(1)));
4208
$this->assertCount(1, $DB->get_records_sql($sql, array("1")));
4209
$this->assertCount(0, $DB->get_records_sql($sql, array(10)));
4210
$this->assertCount(0, $DB->get_records_sql($sql, array("10")));
4230
4211
$DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1abc'));
4231
$this->assertEquals(count($DB->get_records_sql($sql, array(1))), 1);
4232
$this->assertEquals(count($DB->get_records_sql($sql, array("1"))), 1);
4212
$this->assertCount(1, $DB->get_records_sql($sql, array(1)));
4213
$this->assertCount(1, $DB->get_records_sql($sql, array("1")));
4234
4215
// Test get_in_or_equal() with a big number of elements. Note that ideally
4235
4216
// we should be detecting and warning about any use over, say, 200 elements
4236
// and recommend to change code to use subqueries and/or chunks instead.
4217
// And recommend to change code to use subqueries and/or chunks instead.
4237
4218
$currentcount = $DB->count_records($tablename);
4238
4219
$numelements = 10000; // Verify that we can handle 10000 elements (crazy!)
4239
4220
$values = range(1, $numelements);
4243
4224
FROM {{$tablename}}
4244
4225
WHERE id $insql";
4245
4226
$results = $DB->get_records_sql($sql, $inparams);
4246
$this->assertEquals($currentcount, count($results));
4227
$this->assertCount($currentcount, $results);
4248
4229
list($insql, $inparams) = $DB->get_in_or_equal($values, SQL_PARAMS_NAMED); // With NAMED params.
4249
4230
$sql = "SELECT *
4250
4231
FROM {{$tablename}}
4251
4232
WHERE id $insql";
4252
4233
$results = $DB->get_records_sql($sql, $inparams);
4253
$this->assertEquals($currentcount, count($results));
4256
function test_onelevel_commit() {
4258
$dbman = $DB->get_manager();
4260
$table = $this->get_test_table();
4261
$tablename = $table->getName();
4263
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4264
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
4234
$this->assertCount($currentcount, $results);
4237
public function test_replace_all_text() {
4239
$dbman = $DB->get_manager();
4241
if (!$DB->replace_all_text_supported()) {
4242
$this->markTestSkipped($DB->get_name().' does not support replacing of texts');
4245
$table = $this->get_test_table();
4246
$tablename = $table->getName();
4248
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4249
$table->add_field('name', XMLDB_TYPE_CHAR, '20', null, null);
4250
$table->add_field('intro', XMLDB_TYPE_TEXT, 'big', null, null);
4251
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
4252
$dbman->create_table($table);
4254
$id1 = (string)$DB->insert_record($tablename, array('name' => null, 'intro' => null));
4255
$id2 = (string)$DB->insert_record($tablename, array('name' => '', 'intro' => ''));
4256
$id3 = (string)$DB->insert_record($tablename, array('name' => 'xxyy', 'intro' => 'vvzz'));
4257
$id4 = (string)$DB->insert_record($tablename, array('name' => 'aa bb aa bb', 'intro' => 'cc dd cc aa'));
4258
$id5 = (string)$DB->insert_record($tablename, array('name' => 'kkllll', 'intro' => 'kkllll'));
4260
$expected = $DB->get_records($tablename, array(), 'id ASC');
4262
$columns = $DB->get_columns($tablename);
4264
$DB->replace_all_text($tablename, $columns['name'], 'aa', 'o');
4265
$result = $DB->get_records($tablename, array(), 'id ASC');
4266
$expected[$id4]->name = 'o bb o bb';
4267
$this->assertEquals($expected, $result);
4269
$DB->replace_all_text($tablename, $columns['intro'], 'aa', 'o');
4270
$result = $DB->get_records($tablename, array(), 'id ASC');
4271
$expected[$id4]->intro = 'cc dd cc o';
4272
$this->assertEquals($expected, $result);
4274
$DB->replace_all_text($tablename, $columns['name'], '_', '*');
4275
$DB->replace_all_text($tablename, $columns['name'], '?', '*');
4276
$DB->replace_all_text($tablename, $columns['name'], '%', '*');
4277
$DB->replace_all_text($tablename, $columns['intro'], '_', '*');
4278
$DB->replace_all_text($tablename, $columns['intro'], '?', '*');
4279
$DB->replace_all_text($tablename, $columns['intro'], '%', '*');
4280
$result = $DB->get_records($tablename, array(), 'id ASC');
4281
$this->assertEquals($expected, $result);
4283
$long = '1234567890123456789';
4284
$DB->replace_all_text($tablename, $columns['name'], 'kk', $long);
4285
$result = $DB->get_records($tablename, array(), 'id ASC');
4286
$expected[$id5]->name = core_text::substr($long.'llll', 0, 20);
4287
$this->assertEquals($expected, $result);
4289
$DB->replace_all_text($tablename, $columns['intro'], 'kk', $long);
4290
$result = $DB->get_records($tablename, array(), 'id ASC');
4291
$expected[$id5]->intro = $long.'llll';
4292
$this->assertEquals($expected, $result);
4295
public function test_onelevel_commit() {
4297
$dbman = $DB->get_manager();
4299
$table = $this->get_test_table();
4300
$tablename = $table->getName();
4302
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
4303
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
4265
4304
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
4266
4305
$dbman->create_table($table);
4881
4914
$sqlqm = "SELECT *
4882
4915
FROM {{$tablename}}";
4883
4916
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 0, 4));
4884
$this->assertEquals(4, count($records));
4885
$this->assertEquals('a', reset($records)->name);
4886
$this->assertEquals('d', end($records)->name);
4917
$this->assertCount(4, $records);
4918
$this->assertSame('a', reset($records)->name);
4919
$this->assertSame('d', end($records)->name);
4888
4921
$sqlqm = "SELECT *
4889
4922
FROM {{$tablename}}";
4890
4923
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 0, 8));
4891
$this->assertEquals(6, count($records));
4892
$this->assertEquals('a', reset($records)->name);
4893
$this->assertEquals('f', end($records)->name);
4924
$this->assertCount(6, $records);
4925
$this->assertSame('a', reset($records)->name);
4926
$this->assertSame('f', end($records)->name);
4895
4928
$sqlqm = "SELECT *
4896
4929
FROM {{$tablename}}";
4897
4930
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 1, 4));
4898
$this->assertEquals(4, count($records));
4899
$this->assertEquals('b', reset($records)->name);
4900
$this->assertEquals('e', end($records)->name);
4931
$this->assertCount(4, $records);
4932
$this->assertSame('b', reset($records)->name);
4933
$this->assertSame('e', end($records)->name);
4902
4935
$sqlqm = "SELECT *
4903
4936
FROM {{$tablename}}";
4904
4937
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 4, 4));
4905
$this->assertEquals(2, count($records));
4906
$this->assertEquals('e', reset($records)->name);
4907
$this->assertEquals('f', end($records)->name);
4938
$this->assertCount(2, $records);
4939
$this->assertSame('e', reset($records)->name);
4940
$this->assertSame('f', end($records)->name);
4909
4942
$sqlqm = "SELECT t.*, t.name AS test
4910
4943
FROM {{$tablename}} t
4911
4944
ORDER BY t.id ASC";
4912
4945
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 4, 4));
4913
$this->assertEquals(2, count($records));
4914
$this->assertEquals('e', reset($records)->name);
4915
$this->assertEquals('f', end($records)->name);
4946
$this->assertCount(2, $records);
4947
$this->assertSame('e', reset($records)->name);
4948
$this->assertSame('f', end($records)->name);
4917
4950
$sqlqm = "SELECT DISTINCT t.name, t.name AS test
4918
4951
FROM {{$tablename}} t
4919
4952
ORDER BY t.name DESC";
4920
4953
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 4, 4));
4921
$this->assertEquals(2, count($records));
4922
$this->assertEquals('b', reset($records)->name);
4923
$this->assertEquals('a', end($records)->name);
4954
$this->assertCount(2, $records);
4955
$this->assertSame('b', reset($records)->name);
4956
$this->assertSame('a', end($records)->name);
4925
4958
$sqlqm = "SELECT 1
4926
4959
FROM {{$tablename}} t
4927
4960
WHERE t.name = 'a'";
4928
4961
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 0, 1));
4929
$this->assertEquals(1, count($records));
4962
$this->assertCount(1, $records);
4931
4964
$sqlqm = "SELECT 'constant'
4932
4965
FROM {{$tablename}} t
4933
4966
WHERE t.name = 'a'";
4934
4967
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 0, 8));
4935
$this->assertEquals(1, count($records));
4968
$this->assertCount(1, $records);
4937
4970
$this->assertNotEmpty($DB->insert_record($tablename, array('name' => 'a', 'content'=>'one')));
4938
4971
$this->assertNotEmpty($DB->insert_record($tablename, array('name' => 'b', 'content'=>'two')));
4947
4980
GROUP BY t.name
4948
4981
ORDER BY t.name ASC";
4949
4982
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm));
4950
$this->assertEquals(6, count($records)); // a,b,c,d,e,f
4951
$this->assertEquals(2, reset($records)->count); // a has 2 records now
4952
$this->assertEquals(1, end($records)->count); // f has 1 record still
4983
$this->assertCount(6, $records); // a,b,c,d,e,f.
4984
$this->assertEquals(2, reset($records)->count); // a has 2 records now.
4985
$this->assertEquals(1, end($records)->count); // f has 1 record still.
4954
4987
$this->assertNotEmpty($records = $DB->get_records_sql($sqlqm, null, 0, 2));
4955
$this->assertEquals(2, count($records));
4988
$this->assertCount(2, $records);
4956
4989
$this->assertEquals(2, reset($records)->count);
4957
4990
$this->assertEquals(2, end($records)->count);
4993
public function test_queries_counter() {
4996
$dbman = $this->tdb->get_manager();
4999
$table = $this->get_test_table();
5000
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
5001
$table->add_field('fieldvalue', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
5002
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
5004
$dbman->create_table($table);
5005
$tablename = $table->getName();
5007
// Initial counters values.
5008
$initreads = $DB->perf_get_reads();
5009
$initwrites = $DB->perf_get_writes();
5010
$previousqueriestime = $DB->perf_get_queries_time();
5012
// Selects counts as reads.
5014
// The get_records_sql() method generates only 1 db query.
5015
$whatever = $DB->get_records_sql("SELECT * FROM {{$tablename}}");
5016
$this->assertEquals($initreads + 1, $DB->perf_get_reads());
5018
// The get_records() method generates 2 queries the first time is called
5019
// as it is fetching the table structure.
5020
$whatever = $DB->get_records($tablename);
5021
$this->assertEquals($initreads + 3, $DB->perf_get_reads());
5022
$this->assertEquals($initwrites, $DB->perf_get_writes());
5024
// The elapsed time is counted.
5025
$lastqueriestime = $DB->perf_get_queries_time();
5026
$this->assertGreaterThanOrEqual($previousqueriestime, $lastqueriestime);
5027
$previousqueriestime = $lastqueriestime;
5029
// Only 1 now, it already fetched the table columns.
5030
$whatever = $DB->get_records($tablename);
5031
$this->assertEquals($initreads + 4, $DB->perf_get_reads());
5033
// And only 1 more from now.
5034
$whatever = $DB->get_records($tablename);
5035
$this->assertEquals($initreads + 5, $DB->perf_get_reads());
5037
// Inserts counts as writes.
5039
$rec1 = new stdClass();
5040
$rec1->fieldvalue = 11;
5041
$rec1->id = $DB->insert_record($tablename, $rec1);
5042
$this->assertEquals($initwrites + 1, $DB->perf_get_writes());
5043
$this->assertEquals($initreads + 5, $DB->perf_get_reads());
5045
// The elapsed time is counted.
5046
$lastqueriestime = $DB->perf_get_queries_time();
5047
$this->assertGreaterThanOrEqual($previousqueriestime, $lastqueriestime);
5048
$previousqueriestime = $lastqueriestime;
5050
$rec2 = new stdClass();
5051
$rec2->fieldvalue = 22;
5052
$rec2->id = $DB->insert_record($tablename, $rec2);
5053
$this->assertEquals($initwrites + 2, $DB->perf_get_writes());
5055
// Updates counts as writes.
5057
$rec1->fieldvalue = 111;
5058
$DB->update_record($tablename, $rec1);
5059
$this->assertEquals($initwrites + 3, $DB->perf_get_writes());
5060
$this->assertEquals($initreads + 5, $DB->perf_get_reads());
5062
// The elapsed time is counted.
5063
$lastqueriestime = $DB->perf_get_queries_time();
5064
$this->assertGreaterThanOrEqual($previousqueriestime, $lastqueriestime);
5065
$previousqueriestime = $lastqueriestime;
5068
$totaldbqueries = $DB->perf_get_reads() + $DB->perf_get_writes();
5069
$this->assertEquals($totaldbqueries, $DB->perf_get_queries());
4970
5082
return $this->fix_table_names($sql);
4973
public function driver_installed(){}
4974
public function get_dbfamily(){}
4975
protected function get_dbtype(){}
4976
protected function get_dblibrary(){}
4977
public function get_name(){}
4978
public function get_configuration_help(){}
4979
public function get_configuration_hints(){}
4980
public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null){}
4981
public function get_server_info(){}
4982
protected function allowed_param_types(){}
4983
public function get_last_error(){}
4984
public function get_tables($usecache=true){}
4985
public function get_indexes($table){}
4986
public function get_columns($table, $usecache=true){}
4987
protected function normalise_value($column, $value){}
4988
public function set_debug($state){}
4989
public function get_debug(){}
4990
public function set_logging($state){}
4991
public function change_database_structure($sql){}
4992
public function execute($sql, array $params=null){}
4993
public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0){}
4994
public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0){}
4995
public function get_fieldset_sql($sql, array $params=null){}
4996
public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false){}
4997
public function insert_record($table, $dataobject, $returnid=true, $bulk=false){}
4998
public function import_record($table, $dataobject){}
4999
public function update_record_raw($table, $params, $bulk=false){}
5000
public function update_record($table, $dataobject, $bulk=false){}
5001
public function set_field_select($table, $newfield, $newvalue, $select, array $params=null){}
5002
public function delete_records_select($table, $select, array $params=null){}
5003
public function sql_concat(){}
5004
public function sql_concat_join($separator="' '", $elements=array()){}
5005
public function sql_substr($expr, $start, $length=false){}
5085
public function driver_installed() {}
5086
public function get_dbfamily() {}
5087
protected function get_dbtype() {}
5088
protected function get_dblibrary() {}
5089
public function get_name() {}
5090
public function get_configuration_help() {}
5091
public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) {}
5092
public function get_server_info() {}
5093
protected function allowed_param_types() {}
5094
public function get_last_error() {}
5095
public function get_tables($usecache=true) {}
5096
public function get_indexes($table) {}
5097
public function get_columns($table, $usecache=true) {}
5098
protected function normalise_value($column, $value) {}
5099
public function set_debug($state) {}
5100
public function get_debug() {}
5101
public function set_logging($state) {}
5102
public function change_database_structure($sql) {}
5103
public function execute($sql, array $params=null) {}
5104
public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {}
5105
public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {}
5106
public function get_fieldset_sql($sql, array $params=null) {}
5107
public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) {}
5108
public function insert_record($table, $dataobject, $returnid=true, $bulk=false) {}
5109
public function import_record($table, $dataobject) {}
5110
public function update_record_raw($table, $params, $bulk=false) {}
5111
public function update_record($table, $dataobject, $bulk=false) {}
5112
public function set_field_select($table, $newfield, $newvalue, $select, array $params=null) {}
5113
public function delete_records_select($table, $select, array $params=null) {}
5114
public function sql_concat() {}
5115
public function sql_concat_join($separator="' '", $elements=array()) {}
5116
public function sql_substr($expr, $start, $length=false) {}
5006
5117
public function begin_transaction() {}
5007
5118
public function commit_transaction() {}
5008
5119
public function rollback_transaction() {}